本文共 14808 字,大约阅读时间需要 49 分钟。
//construct.initialize内存实例 base on $options
/**
* Class constructor. Initialize cache instance based on options
*
* @param array $options
*/
public function __construct(array $options = array())
{
$this->_defaultBackendOptions['cache_dir'] = Mage::getBaseDir('cache');
/**
* Initialize id prefix
*/
$this->_idPrefix = isset($options['id_prefix']) ? $options['id_prefix'] : '';
if (!$this->_idPrefix && isset($options['prefix'])) {
$this->_idPrefix = $options['prefix'];
}
if (empty($this->_idPrefix)) {
$this->_idPrefix = substr(md5(Mage::getConfig()->getOptions()->getEtcDir()), 0, 3).'_';
}
$backend = $this->_getBackendOptions($options);
$frontend = $this->_getFrontendOptions($options);
$this->_frontend = Zend_Cache::factory('Varien_Cache_Core', $backend['type'], $frontend, $backend['options'],
true, true, true
);
if (isset($options['request_processors'])) {
$this->_requestProcessors = $options['request_processors'];
}
}
1
$this->_defaultBackendOptions['cache_dir'] = Mage::getBaseDir('cache');
为cache对象属性:_defaultBackendOptions['cache_dir']赋值为var/cache/.
2
//为$this->idPrefix赋值:
取决于$options里面的变量,如:id_prefix,prefix,顺序为:$options['id_prefix']存在,则$this->idPrefix = $options['id_prefix'].如果$options['prefix']存在,则$this->idPrefix = $options[id_prefix],
如果都不存在,下面有介绍。。。。
$this->_idPrefix = isset($options['id_prefix']) ? $options['id_prefix'] : '';
if (!$this->_idPrefix && isset($options['prefix'])) {
$this->_idPrefix = $options['prefix'];
}
if (empty($this->_idPrefix)) {
$this->_idPrefix = substr(md5(Mage::getConfig()->getOptions()->getEtcDir()), 0, 3).'_';
}
3
$backend = $this->_getBackendOptions($options);
//该函数的参数:$cacheOptions,即为construct中的$options参数。
protected function _getBackendOptions(array $cacheOptions)
{
$enable2levels = false;
//1
$type = isset($cacheOptions['backend']) ? $cacheOptions['backend'] : $this->_defaultBackend;
//2
if (isset($cacheOptions['backend_options']) && is_array($cacheOptions['backend_options'])) {
$options = $cacheOptions['backend_options'];
} else {
$options = array();
}
//
$backendType = false;
//3
switch (strtolower($type)) {
case 'sqlite':
if (extension_loaded('sqlite') && isset($options['cache_db_complete_path'])) {
$backendType = 'Sqlite';
}
break;
//4
case 'memcached':
if (extension_loaded('memcache')) {
if (isset($cacheOptions['memcached'])) {
$options = $cacheOptions['memcached'];
}
$enable2levels = true;
$backendType = 'Memcached';
}
break;
case 'apc':
//5
if (extension_loaded('apc') && ini_get('apc.enabled')) {
$enable2levels = true;
$backendType = 'Apc';
}
break;
//6
case 'xcache':
if (extension_loaded('xcache')) {
$enable2levels = true;
$backendType = 'Xcache';
}
break;
case 'eaccelerator':
//7
case 'varien_cache_backend_eaccelerator':
if (extension_loaded('eaccelerator') && ini_get('eaccelerator.enable')) {
$enable2levels = true;
$backendType = 'Varien_Cache_Backend_Eaccelerator';
}
break;
//8
case 'database':
$backendType = 'Varien_Cache_Backend_Database';
$options = $this->getDbAdapterOptions();
break;
//9
default:
if ($type != $this->_defaultBackend) {
try {
if (class_exists($type, true)) {
$implements = class_implements($type, true);
if (in_array('Zend_Cache_Backend_Interface', $implements)) {
$backendType = $type;
}
}
} catch (Exception $e) {
}
}
}
//10
if (!$backendType) {
$backendType = $this->_defaultBackend;
foreach ($this->_defaultBackendOptions as $option => $value) {
if (!array_key_exists($option, $options)) {
$options[$option] = $value;
}
}
}
//11
$backendOptions = array('type' => $backendType, 'options' => $options);
if ($enable2levels) {
$backendOptions = $this->_getTwoLevelsBackendOptions($backendOptions, $cacheOptions);
}
return $backendOptions;
}
3.1
$type = isset($cacheOptions['backend']) ? $cacheOptions['backend'] : $this->_defaultBackend;
如果存在$cacheOptions['backend'],则$type等于$cacheOptions['backend'],如果不存在,则$type等于$this->_defaultBackend;
3.2
if (isset($cacheOptions['backend_options']) && is_array($cacheOptions['backend_options'])) {
$options = $cacheOptions['backend_options'];
} else {
$options = array();
}
如果$cacheOptions['backend_options']存在,而且是数组,则$options等于
$cacheOptions['backend_options']
3.3
switch (strtolower($type)) {
case 'sqlite':
if (extension_loaded('sqlite') && isset($options['cache_db_complete_path'])) {
$backendType = 'Sqlite';
}
break;
由3.1可以得出$type,如果
1>$type='sqlite',(sqlite是嵌入式关系数据库),
2>sqlite的需要加载的库文件已经加载
3>($options可以有3.2得出)$options['cache_db_complete_path']存在,则$backendType='sqlite'
总结:
是通过$type的值,库文件的存在性,$options['cache_db_complete_path']是否存在值,进而决定$backendType的值。
------------------>得出$backendTyoe的值
注:
$options['cache_db_complete_path'] = $cacheOptions['backend_options']['cache_db_complete_path']。
3.4
//4
case 'memcached':
if (extension_loaded('memcache')) {
if (isset($cacheOptions['memcached'])) {
$options = $cacheOptions['memcached'];
}
$enable2levels = true;
$backendType = 'Memcached';
}
break;
mencache:内存显示情况。
如果
存在memcached需要加载的库文件则$enable2levels = true;$backendType ='Memcached';
如果
1.存在memcached需要加载的库文件
2.isset($cacheOptions['memcached'])
则$options = $cacheOptions['memcached'].
如果条件成立->------------------>得出$enable2levels和$backendType的值,对$options重新赋值
3.5
case 'apc':
if (extension_loaded('apc') && ini_get('apc.enabled')) {
$enable2levels = true;
$backendType = 'Apc';
}
break;
如果apc的库文件加载,而且int_get('apc.enabled')
则$enable2levels =true, $backendType ='Apc'
3.6
case 'xcache':
if (extension_loaded('xcache')) {
$enable2levels = true;
$backendType = 'Xcache';
}
break;
如果加载了xcache的扩展库文件,则$enable2levels=true,$backendType='Xcache'.
3.7
case 'varien_cache_backend_eaccelerator':
if (extension_loaded('eaccelerator') && ini_get('eaccelerator.enable')) {
$enable2levels = true;
$backendType = 'Varien_Cache_Backend_Eaccelerator';
}
break;
如果eaccelerator的扩展库文件加载,ini_get('eaccelerator.enable')
则
$enable2levels = true;
$backendType = 'Varien_Cache_Backend_Eaccelerator';
3.8
case 'database':
$backendType = 'Varien_Cache_Backend_Database';
$options = $this->getDbAdapterOptions();
break;
如果为database
则
$backendType = 'Varien_Cache_Backend_Database';
$options = $this->getDbAdapterOptions();
3.8.1
/**
* Get options for database backend type
*
* @return array
*/
protected function getDbAdapterOptions()
{
$options['adapter_callback'] = array($this, 'getDbAdapter');
$options['data_table'] = Mage::getSingleton('core/resource')->getTableName('core/cache');
$options['tags_table'] = Mage::getSingleton('core/resource')->getTableName('core/cache_tag');
return $options;
}
得到$options['adapter_callback'] ,$options['data_table'],$options['tags_table']的值。
3.9
default:
if ($type != $this->_defaultBackend) {
try {
if (class_exists($type, true)) {
$implements = class_implements($type, true);
if (in_array('Zend_Cache_Backend_Interface', $implements)) {
$backendType = $type;
}
}
} catch (Exception $e) {
}
}
}
如果type不等于$this->_defaultBackend(此值为'file'),而且存在type这个类,这个类实现了zend_cache_backend_INterface这个接口。
则
$backendType = $type;
3.10
if (!$backendType) {
$backendType = $this->_defaultBackend;
foreach ($this->_defaultBackendOptions as $option => $value) {
if (!array_key_exists($option, $options)) {
$options[$option] = $value;
}
}
}
3.10.1
/**
* Default iotions for default backend
*
* @var array
*/
protected $_defaultBackendOptions = array(
'hashed_directory_level' => 1,
'hashed_directory_umask' => 0777,
'file_name_prefix' => 'mage',
);
如果backendType没有值,也就是上面的这些情况下都没有给backendType赋值,则等于默认值file($this->_defaultBackend),如果$this->_defaultBackendOptions的key值不存在于$options中,则将该key-value加入到$options。
3.11
//11
$backendOptions = array('type' => $backendType, 'options' => $options);
if ($enable2levels) {
$backendOptions = $this->_getTwoLevelsBackendOptions($backendOptions, $cacheOptions);
}
return $backendOptions;
}
3.11.1
$backendOptions = array('type' => $backendType, 'options' => $options);
return $backendOptions
3.11.2
if ($enable2levels) {
$backendOptions = $this->_getTwoLevelsBackendOptions($backendOptions, $cacheOptions);
}
return $backendOptions;
3.11.2.1
/**
* Initialize two levels backend model options
*
* @param array $fastOptions fast level backend type and options
* @param array $cacheOptions all cache options
* @return array
*/
protected function _getTwoLevelsBackendOptions($fastOptions, $cacheOptions)
{
$options = array();
$options['fast_backend'] = $fastOptions['type'];
$options['fast_backend_options'] = $fastOptions['options'];
$options['fast_backend_custom_naming'] = true;
$options['fast_backend_autoload'] = true;
$options['slow_backend_custom_naming'] = true;
$options['slow_backend_autoload'] = true;
if (isset($cacheOptions['slow_backend'])) {
$options['slow_backend'] = $cacheOptions['slow_backend'];
} else {
$options['slow_backend'] = $this->_defaultBackend;
}
if (isset($cacheOptions['slow_backend_options'])) {
$options['slow_backend_options'] = $cacheOptions['slow_backend_options'];
} else {
$options['slow_backend_options'] = $this->_defaultBackendOptions;
}
if ($options['slow_backend'] == 'database') {
$options['slow_backend'] = 'Varien_Cache_Backend_Database';
$options['slow_backend_options'] = $this->getDbAdapterOptions();
}
$backend = array(
'type' => 'TwoLevels',
'options' => $options
);
return $backend;
}
//由于不是很懂cache,对于这些复杂的赋值,只知道赋值的结果,而不知道这些赋值有什么作用,现就分析到这里吧。总归
$backendOptions = array('type' => $backendType, 'options' => $options);
return $backendOptions
返回一个type和options的数组。
type指明类型: file,database,eaccelerator,xcache,apc,memcached,sqlite等
options指明: 这个type需要用到的一个数值,options是一个数组,包含需要用到的值对。
4
$frontend = $this->_getFrontendOptions($options);
/**
* Get options of cache frontend (options of Zend_Cache_Core)
*
* @param array $cacheOptions
* @return array
*/
protected function _getFrontendOptions(array $cacheOptions)
{
$options = isset($cacheOptions['frontend_options']) ? $cacheOptions['frontend_options'] : array();
if (!array_key_exists('caching', $options)) {
$options['caching'] = true;
}
if (!array_key_exists('lifetime', $options)) {
$options['lifetime'] = isset($cacheOptions['lifetime']) ? $cacheOptions['lifetime'] : self::DEFAULT_LIFETIME;
}
if (!array_key_exists('automatic_cleaning_factor', $options)) {
$options['automatic_cleaning_factor'] = 0;
}
$options['cache_id_prefix'] = $this->_idPrefix;
return $options;
}
5
$this->_frontend = Zend_Cache::factory('Varien_Cache_Core', $backend['type'], $frontend, $backend['options'],
true, true, true
);
Mage_Core_Model_Cache->_frontend的赋值:
5.1
/**
* Factory
*
* @param mixed $frontend frontend name (string) or Zend_Cache_Frontend_ object
* @param mixed $backend backend name (string) or Zend_Cache_Backend_ object
* @param array $frontendOptions associative array of options for the corresponding frontend constructor
* @param array $backendOptions associative array of options for the corresponding backend constructor
* @param boolean $customFrontendNaming if true, the frontend argument is used as a complete class name ; if false, the frontend argument is used as the end of "Zend_Cache_Frontend_[...]" class name
* @param boolean $customBackendNaming if true, the backend argument is used as a complete class name ; if false, the backend argument is used as the end of "Zend_Cache_Backend_[...]" class name
* @param boolean $autoload if true, there will no #require_once for backend and frontend (usefull only for custom backends/frontends)
* @throws Zend_Cache_Exception
* @return Zend_Cache_Core|Zend_Cache_Frontend
*/
public static function factory($frontend, $backend, $frontendOptions = array(), $backendOptions = array(), $customFrontendNaming = false, $customBackendNaming = false, $autoload = false)
{
if (is_string($backend)) {
//1
$backendObject = self::_makeBackend($backend, $backendOptions, $customBackendNaming, $autoload);
} else {
if ((is_object($backend)) && (in_array('Zend_Cache_Backend_Interface', class_implements($backend)))) {
$backendObject = $backend;
} else {
self::throwException('backend must be a backend name (string) or an object which implements Zend_Cache_Backend_Interface');
}
}
if (is_string($frontend)) {
$frontendObject = self::_makeFrontend($frontend, $frontendOptions, $customFrontendNaming, $autoload);
} else {
if (is_object($frontend)) {
$frontendObject = $frontend;
} else {
self::throwException('frontend must be a frontend name (string) or an object');
}
}
$frontendObject->setBackend($backendObject);
return $frontendObject;
}
5.1.1
/**
* Frontend Constructor
*
* @param string $backend
* @param array $backendOptions
* @param boolean $customBackendNaming
* @param boolean $autoload
* @return Zend_Cache_Backend
*/
public static function _makeBackend($backend, $backendOptions, $customBackendNaming = false, $autoload = false)
{
if (!$customBackendNaming) {
//1
$backend = self::_normalizeName($backend);
}
if (in_array($backend, Zend_Cache::$standardBackends)) {
// we use a standard backend
$backendClass = 'Zend_Cache_Backend_' . $backend;
// security controls are explicit
#require_once str_replace('_', DIRECTORY_SEPARATOR, $backendClass) . '.php';
} else {
// we use a custom backend
if (!preg_match('~^[/w]+$~D', $backend)) {
Zend_Cache::throwException("Invalid backend name [$backend]");
}
if (!$customBackendNaming) {
// we use this boolean to avoid an API break
$backendClass = 'Zend_Cache_Backend_' . $backend;
} else {
$backendClass = $backend;
}
if (!$autoload) {
$file = str_replace('_', DIRECTORY_SEPARATOR, $backendClass) . '.php';
if (!(self::_isReadable($file))) {
self::throwException("file $file not found in include_path");
}
#require_once $file;
}
}
return new $backendClass($backendOptions);
}
5.1.1
/**
* Normalize frontend and backend names to allow multiple words TitleCased
*
* @param string $name Name to normalize
* @return string
*/
protected static function _normalizeName($name)
{
$name = ucfirst(strtolower($name));
$name = str_replace(array('-', '_', '.'), ' ', $name);
$name = ucwords($name);
$name = str_replace(' ', '', $name);
return $name;
}
标准化这个名字,例如由mage_core_model_config-->mageCoreModelConfig.
总结:
$this->_frontend = Zend_Cache::factory('Varien_Cache_Core', $backend['type'], $frontend, $backend['options'],
true, true, true
);
返回值为
Zend_Cache_Core|Zend_Cache_Frontend,
6
if (isset($options['request_processors'])) {
$this->_requestProcessors = $options['request_processors'];
}
总结:
根据传入值$options,
得到
1
$this->_defaultBackendOptions['cache_dir'] = Mage::getBaseDir('cache');
2
$this->_idPrefix
3
//backend和$frontend类型为数组。返回一个包含type和options的数组。
$backend = $this->_getBackendOptions($options);
$frontend = $this->_getFrontendOptions($options);
进而得出
$this->_frontend = Zend_Cache::factory('Varien_Cache_Core', $backend['type'], $frontend, $backend['options'],
true, true, true
);
$this->_frontend 为Zend_Cache_Core|Zend_Cache_Frontend类型
4
$this->_requestProcessors = $options['request_processors'];
对cache的机制了解不是很多,还处于模糊阶段,所以对magento的核心cache不能有很好的理解,就先这样吧,知道个大体结构。到此为止。。
magento 的cache机制是zendframework框架的,所以,研究这个框架再回来看magento的核心内存机制cache。
转载地址:http://hgdli.baihongyu.com/