Кеширование на файлах. Новая версия. Более тормозно но более гибко

Главные вкладки

Аватар пользователя Ильич Рамирес Санчес Ильич Рамирес Санчес 2 июля 2008 в 3:48

Берем 5ый друпал. Zend_Framework - кладем его в подкаталог library.
В $conf путь к ZF определяется так.
'filecache_zend_path' => 'library' . PATH_SEPARATOR . 'library' . DIRECTORY_SEPARATOR . 'Azarov',

От ZF на самом деле надо очень мало - следующие файлы и каталоги:
Cache, Cache.php, Exception.php, Loader, Loader.php, Version.php

В комментариях описаны примерные конфигурационные параметры.
По умолчанию пользуется стандартный зендовский класс Zend_Cache_Backend_File.
У меня есть своя его версия чуть получше - чистка мусора в ней проводится раз в 5000 раз или как задашь и актуальность записей оценивается по своему.

По результатам тестирования - на 30% медленнее предыдущей модели. НО. Тут больше гибкости - учитывая заморочки 6го друпала - я буду развивать именно этот вариант Smile

Вот такие пироги Smile

Гибкость в следующем -можно подставлять бекенды кеша какие нравятся. Для APC, для мемкеша и тд.

Потом может разовью решение в сторону того что будет похоже на cacherouter. Вот такие дела. Smile

/*
*
*   Filecache2 by Ilya V. "brainstorm" Azarov, brainstorm.name
*   This module uses Zend framework cache to organize file cachig for drupal
*
*   $conf configuration variables in settings.php
*   $conf['filecache_zend_path'] - library path of zend framework
*   by default 'library' . DIRECTORY_SEPARATOR  . 'library'  . DIRECTORY_SEPARATOR . 'Azarov'
*   $conf['filecache_maincacheclass'] = 'Zend_Cache_Backend_File' - main class for caching
*   we use our class - Zend_Cache_Backend_Fastfile for caching
*   Other advanced options would be later
*   See _filecache2_params for defaults
*/

/*
 *  Wrapper for cache $conf parameters
 */

function _filecache2_params($param){
    static $defaults;
    if(!isset($defaults) ) $defaults = array(
        'filecache_zend_path' => 'library' . PATH_SEPARATOR  . 'library'  . DIRECTORY_SEPARATOR . 'Azarov',
        'filecache_maincacheclass' => 'File', // Zend_Cache_Backend_File
        'filecache_path' => 'files/cache',
        'filecache_opts_Zend_Cache_Backend_File' => array(
            'cache_dir' => null,
            'file_locking' => true,
            'hashed_directory_level' => 3,
            'hashed_directory_umask' => 0755
        ),
        // Zend_Cache_Backend_Fastfile
        'filecache_opts_Fastfile' => array(
            'cache_dir' => false, // say system - we need this option but it's auto
            'file_locking' => true,
            'cleaning_factor' => '5000', // evertime on couter is equal - make full clean
            'hashed_directory_level' => 3,
            'hashed_directory_umask' => 0755,
            'file_name_prefix' => 'zc',
        ),
        // Zend_Cache_Backend_File
        'filecache_opts_File' => array(
            'cache_dir' => false, // say system - we need this option but it's auto
            'file_locking' => true,
            'hashed_directory_level' => 3,
            'hashed_directory_umask' => 0755,
            'file_name_prefix' => 'zc',
        )
    );
    global $conf;
    if(isset($conf[$param] ) ) return $conf[$param];    
    elseif(isset($defaults[$param] ) ) return $defaults[$param];
    return false;
}
function _filecache2_init_loaders(){
    static $loaded;
    if(!isset($loaded) ){
        set_include_path(get_include_path() . PATH_SEPARATOR . _filecache2_params('filecache_zend_path') );
        include_once('Zend/Loader.php');
        Zend_Loader::registerAutoload();
        $loaded = true;
    }
}
function _filecache2_name_encode($cid){
    return str_replace('=', '_', base64_encode($cid) );
}
function _filecache2_get_cache_object($table){
    static $objects;
    if(isset($objects[$table] ) ) return $objects[$table];
    _filecache2_init_loaders();
    // FOR FUTURE - make objects depending on per table configuration
    $dirname = _filecache2_params('filecache_path') . DIRECTORY_SEPARATOR . $table;
    if(!is_dir($dirname) ) mkdir($dirname, 0755, true);
    $bopts = _filecache2_params('filecache_opts_' . _filecache2_params('filecache_maincacheclass') );
    if(!$bopts) Zend_Cache::throwException('No options for ' . _filecache2_params('filecache_maincacheclass') );
    if(isset($bopts['cache_dir'] ) ) $bopts['cache_dir'] = $dirname;
    $cache = Zend_Cache::factory('Core', _filecache2_params('filecache_maincacheclass'),
        array('caching' => true, 'lifetime' => null, 'automatic_cleaning_factor' => 0, 'ignore_user_abort' => true),
        $bopts
    );
    $objects[$table] = $cache;
    return $objects[$table];
}
function cache_get($cid, $table = 'cache') {
    global $user;
    // Garbage collection necessary when enforcing a minimum cache lifetime
    $cache_flush = variable_get('cache_flush', 0);
    if ($cache_flush && ($cache_flush + variable_get('cache_lifetime', 0) <= time())) {
        _filecache2_get_cache_object($table)->clean(Zend_Cache::CLEANING_MODE_OLD);
        variable_set('cache_flush', 0);
    }
    $mcid = _filecache2_name_encode($cid);
    if($co = [user=unserialize]unserialize[/user](_filecache2_get_cache_object($table)->load($mcid) ) ){
        return $co;
    }
    return 0;
}
function cache_set($cid, $table = 'cache', $data, $expire = CACHE_PERMANENT, $headers = NULL) {
    // save($data, $id = null, $tags = array(), $specificLifetime = false)
    $mcid = _filecache2_name_encode($cid);
    $t = time();
    $specificLifetime = false;
    if($expire != CACHE_PERMANENT){
        $t = $expire - $t;
        if($t > 0) $specificLifetime = $t;
    }
    $o = new stdClass();
    $o->data = $data;
    $o->created = time();
    $o->expire =  $expire;
    $o->headers = $headers;
    $s = serialize($o);unset($o);
    _filecache2_get_cache_object($table)->save($s, $mcid, array(), $specificLifetime);
}
function cache_clear_all($cid = NULL, $table = NULL, $wildcard = FALSE){
    global $user;
    if (!isset($cid) && !isset($table)) {
        cache_clear_all(NULL, 'cache_page');
        return;
    }
    if (empty($cid)) {
        if (variable_get('cache_lifetime', 0)) {
            // We store the time in the current user's $user->cache variable which
            // will be saved into the sessions table by sess_write(). We then
            // simulate that the cache was flushed for this user by not returning
            // cached data that was cached before the timestamp.
            $user->cache = time();
            $cache_flush = variable_get('cache_flush', 0);
            if ($cache_flush == 0) {
                // This is the first request to clear the cache, start a timer.
                variable_set('cache_flush', time());
            }
            else if (time() > ($cache_flush + variable_get('cache_lifetime', 0))) {
                // Clear the cache for everyone, cache_flush_delay seconds have
                // passed since the first request to clear the cache.
                _filecache2_get_cache_object($table)->clean(Zend_Cache::CLEANING_MODE_OLD);
                variable_set('cache_flush', 0);
            }
        }else{
            // No minimum cache lifetime, flush all temporary cache entries now.
            _filecache2_get_cache_object($table)->clean(Zend_Cache::CLEANING_MODE_ALL);
        }
    }else{
        if ($wildcard) {
            _filecache2_get_cache_object($table)->clean(Zend_Cache::CLEANING_MODE_ALL);
        }else{
            $mcid = _filecache2_name_encode($cid);
            _filecache2_get_cache_object($table)->remove($mcid);
        }
    }
}

Комментарии

Аватар пользователя Ильич Рамирес Санчес Ильич Рамирес Санчес 6 июля 2008 в 16:30

CACHE_TEMPORARY - обычно складываются в отдельные таблицы и функция та же что и у CACHE_PERMANENT, так что в данной конфигурации модуль для 5ки достаточен Smile
Для 6ки в процессе - и там уже думать сильно надо на тему очисток кеша меню и форм... дело ближайших двух недель...