Tuesday, October 1, 2013

Create a zip with files that was changes in the specific commit.

To create an archive that contains files changes in the specific commit you can use the following approach:

export COMMIT_HASH=1ae404a0cbe5
git archive -o ../$COMMIT_HASH.zip $COMMIT_HASH `git diff-tree --no-commit-id --name-only -r $COMMIT_HASH`

Wednesday, April 3, 2013

How to disable ASLR in linux permanently.

I was trying to install IBM DB2 v9.7 on the Ubuntu 12.10 and ./db2prereqcheck had been saying to me this:
WARNING:
DBT3534W  The db2prereqcheck utility determined that ASLR is set to ON and that this could cause issues with some tools.
Many articles in the Internat says that ASLR can be disabled by just executing this command in the bash:
sudo sh -c "echo 0 > /proc/sys/kernel/randomize_va_space"
But this is not a permanent solution, you have to execute this command after every reboot of the machine.
Also in order to disable ASLR permanently there are some articles recommending to add
kernel.randomize_va_space=0
to the kernel boot parameters, but this won't work.
Finally I found the solution: simply add
kernel.randomize_va_space=0
to the end of the /etc/sysctl.conf. To immediately apply changes execute as root:
sysctl -p
http://www-01.ibm.com/support/docview.wss?uid=swg21365583

Wednesday, February 20, 2013

Class group configuration and use in factory methods

How to define a group of classes.

Let's review the process of the configuration of class groups. Generally it should look like this in the config tree:

    
        
            
                
                    Rewrite_Class_Name
                
                Class_Name_Prefix
            
        
    

group_type represents the essence of all classes that belongs to this group type. There are helpers, blocks, models - all these are group types. You free to define a new group type, if you need.
group_name unites all classes of the particular type of the particular module. All blocks of the Mage_Tag module for instance. But you're allowed to define more than one class group of the same type withing one module. Group name should be unique across the system.

Inside the group name node we are defining a list of class rewrites and a class name prefix. To rewrite for instance catalog/product_option model with your custom class you should define new rewrite directive with class_name equals to "product_option" within the "models" group type within the "catalog" group name. Class prefix of the group is being defined under the <class> or <model>. Below I will show you that there is no difference between <class> and <model>, either can be used.

Basicly it means that we are defining a group of classes with it's class prefix and group of rewrite directives. For example let's define a group of blocks with lestar_test group type and rewrite lestar_test/form block with custom class:

    
        
            
                Lestar_Test_Blocks
                
                    
YouOrganization_Test_Block_Form

Why it works?

The process of determining of the class name by the classId (catalog/product) is implemented in the Mage_Core_Model_Config::getGroupedClassName($groupType, $classId, $groupRootNode = null). It's important to understand what it does. Method's source code:
/**
 * Retrieve class name by class group
 *
 * @param   string $groupType currently supported model, block, helper
 * @param   string $classId slash separated class identifier, ex. group/class
 * @param   string $groupRootNode optional config path for group config
 * @return  string
 */
public function getGroupedClassName($groupType, $classId, $groupRootNode = null)
{
    if (empty($groupRootNode)) {
        $groupRootNode = 'global/' . $groupType . 's';
    }

    $classArr = explode('/', trim($classId));
    $group = $classArr[0];
    $class = !empty($classArr[1]) ? $classArr[1] : null;

    if (isset($this->_classNameCache[$groupRootNode][$group][$class])) {
        return $this->_classNameCache[$groupRootNode][$group][$class];
    }

    $config = $this->_xml->global->{$groupType . 's'}->{$group};

    // First - check maybe the entity class was rewritten
    $className = null;
    if (isset($config->rewrite->$class)) {
        $className = (string)$config->rewrite->$class;
    } else {
        /**
         * Backwards compatibility for pre-MMDB extensions.
         * In MMDB release resource nodes <..._mysql4> were renamed to <..._resource>. So  is left
         * to keep name of previously used nodes, that still may be used by non-updated extensions.
         */
        if ($config->deprecatedNode) {
            $deprecatedNode = $config->deprecatedNode;
            $configOld = $this->_xml->global->{$groupType . 's'}->$deprecatedNode;
            if (isset($configOld->rewrite->$class)) {
                $className = (string)$configOld->rewrite->$class;
            }
        }
    }

    // Second - if entity is not rewritten then use class prefix to form class name
    if (empty($className)) {
        if (!empty($config)) {
            $className = $config->getClassName();
        }
        if (empty($className)) {
            $className = 'mage_' . $group . '_' . $groupType;
        }
        if (!empty($class)) {
            $className .= '_' . $class;
        }
        $className = uc_words($className);
    }

    $this->_classNameCache[$groupRootNode][$group][$class] = $className;
    return $className;
}
Let's go through this method and review what each peace does:

    if (empty($groupRootNode)) {
        $groupRootNode = 'global/' . $groupType . 's';
    }
The groupRootNode variable is used only to stash already resolved class names. It won't change the default root node of the config lookup.

    $classArr = explode('/', trim($classId));
    $group = $classArr[0];
    $class = !empty($classArr[1]) ? $classArr[1] : null;

    if (isset($this->_classNameCache[$groupRootNode][$group][$class])) {
        return $this->_classNameCache[$groupRootNode][$group][$class];
    }
Explode class id and find out group name and class name (actually only it's part after class prefix). Then look up in the stashed resolves and return if hit.

    $config = $this->_xml->global->{$groupType . 's'}->{$group};
Retrieves the config node of the necessary group of the classes.

    // First - check maybe the entity class was rewritten
    $className = null;
    if (isset($config->rewrite->$class)) {
        $className = (string)$config->rewrite->$class;
This is the place where overriding of the class is happening. It will look for the existence of the node named as class name inside of the rewrite node. And if this node exists magento will treat it's content as complete class name.

    } else {
        /**
         * Backwards compatibility for pre-MMDB extensions.
         * In MMDB release resource nodes <..._mysql4> were renamed to <..._resource>. So  is left
         * to keep name of previously used nodes, that still may be used by non-updated extensions.
         */
        if ($config->deprecatedNode) {
            $deprecatedNode = $config->deprecatedNode;
            $configOld = $this->_xml->global->{$groupType . 's'}->$deprecatedNode;
            if (isset($configOld->rewrite->$class)) {
                $className = (string)$configOld->rewrite->$class;
            }
        }
    }
If rewrite is not exists, but exists deprecatedNode node in the group config it will try to find rewrite inside of this config node. The value of the deprecatedNode contains the name of another group config of the same type. Next example will define override using deprecated node:


    
        
            group2
        
        
            
                This_Is_Rewriten_ClassName
            
        
    

This thing is had become needed after magento renamed resource groups from *_mysql4 to *_resource. All rewrites of classes made inside _mysql4 groups will still work.

// Second - if entity is not rewritten then use class prefix to form class name
    if (empty($className)) {
        if (!empty($config)) {
            $className = $config->getClassName();
        }
        if (empty($className)) {
            $className = 'mage_' . $group . '_' . $groupType;
        }
        if (!empty($class)) {
            $className .= '_' . $class;
        }
        $className = uc_words($className);
    }
This peace of code determines class name in standard way (if override didn't happen before). If group config node exists then it will call Mage_Core_Model_Config_Element::getClassName():

        if (!empty($config)) {
            $className = $config->getClassName();
        }
This is the source code of the getClassName method:

public function getClassName()
{
    if ($this->class) {
        $model = (string)$this->class;
    } elseif ($this->model) {
        $model = (string)$this->model;
    } else {
        return false;
    }
    return Mage::getConfig()->getModelClassName($model);
}
It looks for the class node, then it will look for the model node cast founded to the string and return, otherwise it will return false. So in the configuration not only <class> node can be specified but <model> node too, it's the same in either way. The last line is never called, probably it's legacy code.

        if (empty($className)) {
            $className = 'mage_' . $group . '_' . $groupType;
        }
This piece of code forms the class name prefix if it wasn't defined in the config. This is why sometimes you get an error that some class (which name starts with Mage_) is not found if you messed up with the configuration.

        if (!empty($class)) {
            $className .= '_' . $class;
        }
The last peace of code concatenates class group prefix with actual class name in the group.

        $className = uc_words($className);
Next class name is passed through the uc_words function which capitalizes ever word separated with the underscore. Finally class name is being stashed for the future use and returned:

    $this->_classNameCache[$groupRootNode][$group][$class] = $className;
    return $className;

Where the class grouping is using?

There are a couple of factory methods using class group configuration:

Mage::helper($name);
Mage::getModel($modelClass = '', $arguments = array());
Mage::getSingleton($modelClass='', array $arguments=array());
Mage::getBlockSingleton($type);
Mage::getResourceSingleton($type);
Mage::getResourceHelper($moduleName);
Mage::gerResourceModel($modelClass, $arguments = array());
Helpers
You call Mage::helper($name) method to retrieve any helper object.
/**
 * Retrieve helper object
 *
 * @param string $name the helper name
 * @return Mage_Core_Helper_Abstract
 */
public static function helper($name)
{
    $registryKey = '_helper/' . $name;
    if (!self::registry($registryKey)) {
        $helperClass = self::getConfig()->getHelperClassName($name);
        self::register($registryKey, new $helperClass);
    }
    return self::registry($registryKey);
}
To return requested helper object to you Magento will look into the static registry of the Mage class using registry key that is equal to the concatenation of the '_helper/' string and requested helper name. If it fails Magento will ask config object for the helper class name, then will create an instance, store this object in the static registry and finally will return the helper object to you.

Let's go deeper to see how Mage_Core_Model_Config::getHelperClassName() works.
/**
 * Retrieve helper class name
 *
 * @param   string $name
 * @return  string
 */
public function getHelperClassName($helperName)
{
    if (strpos($helperName, '/') === false) {
        $helperName .= '/data';
    }
    return $this->getGroupedClassName('helper', $helperName);
}
From the code above you can see why Magento returns Data helper when you don't specify only helpers group name. I mean if you pass 'core' to the helper factory method you will get the Mage_Core_Helper_Data class object. Magento examines specified helper name and if it doesn't contain slash Magento will add '/data' to the end of the helper name.
Finally it will call Mage_Core_Model_Config::getGroupedClassName() using 'helper' as class group type and helper name as classId.

This is how you get a helper. Please note that any helper object is being instantiated only once. If you second time request the helper you will get previous instance of it from the registry. But you can preassing or change already instantiated helper using static methods of the Mage class to manipulate the registry. Also note that you can't pass any parameters to the helper class constructor.
Models
To create a new model you call Mage::getModelInstance($modelClass='', $constructArguments=array())
/**
 * Retrieve model object
 *
 * @link    Mage_Core_Model_Config::getModelInstance
 * @param   string $modelClass
 * @param   array|object $arguments
 * @return  Mage_Core_Model_Abstract|false
 */
public static function getModel($modelClass = '', $arguments = array())
{
    return self::getConfig()->getModelInstance($modelClass, $arguments);
}
This method works very simply: it calls Mage_Core_Model_Config::getModelClassName($modelClass) to get a class name. If class name was found then it will create a new instance of this class passing $constructArguments to the constructor. Otherwise it will return false.

Mage_Core_Model_Config::getModelClassName($modelClass) also works simply: just looks for the "/" in the $modelClass, if "/" isn't present in the $modelClass, then method returns $modelClass as result. Otherwise it will call $this->getGroupedClassName('model', $modelClass); and return it's result.
/**
 * Get model class instance.
 *
 * Example:
 * $config->getModelInstance('catalog/product')
 *
 * Will instantiate Mage_Catalog_Model_Mysql4_Product
 *
 * @param string $modelClass
 * @param array|object $constructArguments
 * @return Mage_Core_Model_Abstract|false
 */
public function getModelInstance($modelClass='', $constructArguments=array())
{
    $className = $this->getModelClassName($modelClass);
    if (class_exists($className)) {
        Varien_Profiler::start('CORE::create_object_of::'.$className);
        $obj = new $className($constructArguments);
        Varien_Profiler::stop('CORE::create_object_of::'.$className);
        return $obj;
    } else {
        return false;
    }
}
Singletons
To get a singleton object you call Mage::getSingleton($modelClass='', array $arguments=array()).
/**
 * Retrieve model object singleton
 *
 * @param   string $modelClass
 * @param   array $arguments
 * @return  Mage_Core_Model_Abstract
 */
public static function getSingleton($modelClass='', array $arguments=array())
{
    $registryKey = '_singleton/'.$modelClass;
    if (!self::registry($registryKey)) {
        self::register($registryKey, self::getModel($modelClass, $arguments));
    }
    return self::registry($registryKey);
}
From the code above you can see that Magento works with singletons just like with helpers: it stores singleton objects in the Mage class static registry on singleton creation, or returns singleton from the registry if it was already created before. To create a new singleton Magento uses getModel method which means that singleton is a model created only once.
Resource models