MetaL logo

Metastorage troubleshooting guide


Page version


Metastorage troubleshooting guide

    This guide is meant to help users understanding and solving problems that they may find when they try to use Metastorage.

  • Obtaining support

  • Installation
    • could not find class file metal_compiler.php
    • If the metastorage command exits with an error message like could not find class file metal_compiler.php in directory /some/path/metal, this means that the standard MetaL distribution is not installed in the parent directory of the Metastorage installation path.

      Please check the section of Metastorage tutorial about its installation to learn how to correctly install the MetaL distribution for use with Metastorage.


  • Compiling components
    • set_time_limit(): Cannot set time limit in safe mode
    • Metastorage needs to be executed by PHP in normal mode. Safe mode prevents PHP scripts to run for longer than the default time limit. It also disallows the creation a files, preventing Metastorage to generate the projects files.

      To disable PHP safe mode, just edit its php.ini configuration file and make sure the safe mode option line is set like this:

      
       safe_mode = Off
      
      

      If for some reason you are not able to locate your system php.ini file or you are not able to change it, when you run PHP from the command line you can use a new php.ini file with the safe mode and other settings. You can make PHP use the new php.ini file instead of the default using the -c switch like this:

      
       /path/to/php -c /my/php.ini -q -C /path/to/metastorage my.component
      
      

    • could not find class file metastorage.php
    • could not find the file my.component in the current directory
    • To run the metastorage command when it is executed from a directory different than Metastorage installation directory, you need to specify the -C switch to the PHP command to tell it to not change the current directory to metastorage command path.

      
       /path/to/php -q -C /path/to/metastorage my.component
      
      

    • Allowed memory size of 8388608 bytes exhausted
    • The default memory limit used on each invocation of a PHP script is of 8MB. Usually this is insufficient to run Metastorage compiler. 32MB is often enough to compile most components. However, if you use PHP optimizer extensions like Zend Optimizer, you may need to increase to 256MB or disable these extensions when you run Metastorage.

      To increase the PHP memory limit, just edit its php.ini configuration file and make sure the memory limit option is set to an higher value like this:

      
       memory_limit = 32M
      
      

    • Maximum function nesting level of '64' reached
    • Some PHP debugging extensions like Xdebug are capable of watching the running scripts and prevent that they enter in infinite function call recursion loops. This is done by stopping the current script when it exceeds a given limit of recursive function calls.

      The MetaL compiler engine often calls functions that end up calling themselves to process nested language structures. Although this is the normal behavior of the MetaL engine, it may exceed the function call nesting level limit and abort Metastorage execution.

      To avoid this problem, the allowed nesting level limit needs to be increased. If you are using the Xdebug PHP extension, you can increase the nesting level limit by setting the respective configuration option in the php.ini like this:

      
       xdebug.max_nesting_level = 1000
      
      

    • getreference of a variable of a class of a different component is not yet supported
    • Retrieving objects of an external component must be done using the factory class or the data classes of that component.

      Retrieving an object pointed by a reference variable of an external component class can be done using first a getreference function defined with the oid parameter to tell it to return the external object identifier.

      
       <class>
      
         <name>article</name>
      
         <variable>
           <name>author</name>
           <class>user</class>
           <component>accounts</component>
         </variable>
      
         <function>
           <name>getauthoroid</name>
           <type>getreference</type>
           <parameters>
             <variable>author</variable>
             <oid />
           </parameters>
         </function>
      
       </class>
      
      

      Then use the a getobject type function of the external component factory class to retrieve object using its OID.

      
       <component>
      
         <name>accounts</name>
      
         ...
      
         <factory>
      
           <function>
             <name>getuserbyoid</name>
             <type>getobject</type>
             <parameters>
               <class>user</class>
               <id>
                 <argument>user_oid</argument>
               </id>
             </parameters>
           </function>
      
         </factory>
      
       </component>
      
      

    • cloning objects of classes with variables of type largedata is not yet a supported
    • Metastorage does not yet support cloning objects with variables of type largedata.

      Large data variable values maybe copied or not, depending on the purpose of the applications that need to clone objects.

      For now, if you need to clone an object of a class with large data variables, it is recommended that you create a new object of that class and assign each of the new object variables individually.

      If you need to also copy the large data variables, you need to explicitly retrieve the large data values from the original object into a string variable or to a file, and then store the data in the new object.

    • object expressions may only be returned specifying the object identifier (oid)
    • Report queries can only return scalar values. Therefore report queries cannot return object instances.

      If you need to retrieve an object or an object reference variable, you must specify that you want to retrieve the object identifier using the oid tag in the report query column expression, like this:

      
       <column>
        <name>column_name</name>
        <value><variable>
         <object>object_name</object>
         <name>reference_variable_name</name>
         <oid />
        </variable></value>
       </column>
      
      

  • Using the generated code
    • it was attempted to set the rrrrrr reference variable to a cccccc class object that is not yet persisted
    • When a setreference type function is called, it stores the OID of the reference object passed as argument to the function if it is not a null object reference. However, the if the reference object was just created and was not yet saved, its OID is not yet determined and so the setreference type function fails with the error above.

      When this happens, it means that the calling application must be fixed to invoke the persist type function of the reference object before calling the setreference type function.

    • it was atempted to persist an object of the class cccccc with a required variable that is not initialized
    • By default, all class variables are required and so they have to be initialized. Otherwise, the class persist type function fails with the above error message.

      If the class variable was not really meant to always be required, it must be defined as optional. If the variable is always required it must be initialized before calling the class persist type function.

    • transactions are not in use
    • Certain database types, like MySQL, can only implement transactions with table types that support them.

      The MySQL Metabase driver used by the Metastorage generated code, assumes that the default table type is MYISAM. However, MYISAM tables do not support transactions.

      Transaction support can be enabled using another table type like INNODB. You also need to configure the MySQL Metabase to explicitly support transactions. That can be done using a connection string like these:

      
       mysql://host/database?Options/DefaultTableType=INNODB&Options/UseTransactions=1
      
       mysql://localhost/cms?Options/DefaultTableType=INNODB&Options/UseTransactions=1
      
      

      If you have not used a connection string that determines the use of transactional tables when the database schema was created, you can change the type of a MySQL table, for instance to INNODB, executing an SQL query like this:

      
       ALTER TABLE name_of_the_table TYPE=INNODB
      
      

For more information contact: info-at-meta-language.net