From: Michael M Slusarz Date: Tue, 18 May 2010 19:43:38 +0000 (-0600) Subject: Add Stack driver to horde/Cache package X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=04837db013582f5fe55f92e62fd09e3c09790ce7;p=horde.git Add Stack driver to horde/Cache package --- diff --git a/framework/Cache/lib/Horde/Cache/Sql.php b/framework/Cache/lib/Horde/Cache/Sql.php index e540e0540..abb8b3127 100644 --- a/framework/Cache/lib/Horde/Cache/Sql.php +++ b/framework/Cache/lib/Horde/Cache/Sql.php @@ -38,13 +38,6 @@ class Horde_Cache_Sql extends Horde_Cache_Base protected $_db; /** - * The memory cache object to use, if configured. - * - * @var Horde_Cache - */ - protected $_mc = null; - - /** * Constructor. * * @param array $params Parameters: @@ -52,8 +45,6 @@ class Horde_Cache_Sql extends Horde_Cache_Base * 'db' - (Horde_Db_Adapter_Base) [REQUIRED] The DB instance. * 'table' - (string) The name of the cache table. * DEFAULT: 'horde_cache' - * 'use_memorycache' - (Horde_Cache) Use this memory caching object to - * cache the data (to avoid DB accesses). * * * @throws Horde_Cache_Exception @@ -64,12 +55,7 @@ class Horde_Cache_Sql extends Horde_Cache_Base throw new Horde_Cache_Exception('Missing db parameter.'); } $this->_db = $params['db']; - - if (isset($params['use_memorycache'])) { - $this->_mc = $params['use_memorycache']; - } - - unset($params['db'], $params['use_memorycache']); + unset($params['db']); $params = array_merge(array( 'table' => 'horde_cache', @@ -111,13 +97,6 @@ class Horde_Cache_Sql extends Horde_Cache_Base $okey = $key; $key = hash('md5', $key); - if ($this->_mc) { - $data = $this->_mc->get($key, $lifetime); - if ($data !== false) { - return $data; - } - } - $timestamp = time(); $maxage = $timestamp - $lifetime; @@ -146,10 +125,6 @@ class Horde_Cache_Sql extends Horde_Cache_Base return false; } - if ($this->_mc) { - $this->_mc->set($key, $result); - } - if ($this->_logger) { $this->_logger->log(sprintf('Cache hit: %s (Id %s newer than %d)', $okey, $key, $maxage), 'DEBUG'); } @@ -172,10 +147,6 @@ class Horde_Cache_Sql extends Horde_Cache_Base $okey = $key; $key = hash('md5', $key); - if ($this->_mc) { - $this->_mc->set($key, $data); - } - $timestamp = time(); // 0 lifetime indicates the object should not be GC'd. @@ -224,10 +195,6 @@ class Horde_Cache_Sql extends Horde_Cache_Base $okey = $key; $key = hash('md5', $key); - if ($this->_mc && $this->_mc->exists($key, $lifetime)) { - return true; - } - /* Build SQL query. */ $query = 'SELECT 1 FROM ' . $this->_params['table'] . ' WHERE cache_id = ?'; @@ -271,10 +238,6 @@ class Horde_Cache_Sql extends Horde_Cache_Base { $key = hash('md5', $key); - if ($this->_mc) { - $this->_mc->expire($key); - } - $query = 'DELETE FROM ' . $this->_params['table'] . ' WHERE cache_id = ?'; $values = array($key); diff --git a/framework/Cache/lib/Horde/Cache/Stack.php b/framework/Cache/lib/Horde/Cache/Stack.php new file mode 100644 index 000000000..8cdc74b3f --- /dev/null +++ b/framework/Cache/lib/Horde/Cache/Stack.php @@ -0,0 +1,154 @@ + + * @category Horde + * @package Cache + */ +class Horde_Cache_Stack extends Horde_Cache_Base +{ + /** + * Stack of cache drivers. + * + * @var string + */ + protected $_stack = array(); + + /** + * Constructor. + * + * @param array $params Parameters: + *
+     * 'stack' - (array) [REQUIRED] A list of cache drivers to loop
+     *           through, in order of priority. The last entry is considered
+     *           the 'master' driver, for purposes of writes.
+     *           Each value should contain an array with two keys: 'driver', a
+     *           string value with the Cache driver to use, and 'params',
+     *           containing any parameters needed by this driver.
+     * 
+ * + * @throws InvalidArgumentException + */ + public function __construct(array $params = array()) + { + if (!isset($params['stack'])) { + throw new InvalidArgumentException('Missing stack parameter.'); + } + + foreach ($params['stack'] as $val) { + $this->_stack[] = Horde_Cache::factory($val['driver'], $val['params']); + } + + unset($params['stack']); + + parent::__construct($params); + } + + /** + * Attempts to retrieve a cached object and return it to the + * caller. + * + * @param string $key Object ID to query. + * @param integer $lifetime Lifetime of the object in seconds. + * + * @return mixed Cached data, or false if none was found. + */ + public function get($key, $lifetime = 1) + { + foreach ($this->_stack as $val) { + $result = $val->get($key, $lifetime); + if ($result !== false) { + break; + } + } + + return $result; + } + + /** + * Attempts to store an object in the cache. + * + * @param string $key Object ID used as the caching key. + * @param mixed $data Data to store in the cache. + * @param integer $lifetime Object lifetime - i.e. the time before the + * data becomes available for garbage + * collection. If null use the default Horde GC + * time. If 0 will not be GC'd. + * + * @return boolean True on success, false on failure. + */ + public function set($key, $data, $lifetime = null) + { + /* Do writes in *reverse* order - it is OK if a write to one of the + * non-master backends fails. */ + $master = true; + + foreach (array_reverse($this->_stack) as $val) { + $result = $val->set($key, $data, $lifetime); + if ($result === false) { + if ($master) { + return false; + } + + /* Attempt to invalidate cache if write failed. */ + $val->expire($id); + } + $master = false; + } + + return true; + } + + /** + * Checks if a given key exists in the cache, valid for the given + * lifetime. + * + * @param string $key Cache key to check. + * @param integer $lifetime Lifetime of the key in seconds. + * + * @return boolean Existence. + */ + public function exists($key, $lifetime = 1) + { + foreach ($this->_stack as $val) { + $result = $val->exists($key, $lifetime); + if ($result === true) { + break; + } + } + + return $result; + } + + /** + * Expire any existing data for the given key. + * + * @param string $key Cache key to expire. + * + * @return boolean Success or failure. + */ + public function expire($key) + { + /* Only report success from master. */ + $master = $success = true; + + foreach (array_reverse($this->_stack) as $val) { + $result = $val->expire($id); + if ($master && ($result === false)) { + $success = false; + } + $master = false; + } + + return $success; + } + +} diff --git a/framework/Cache/package.xml b/framework/Cache/package.xml index e6aa6f7e4..78e63a0ad 100644 --- a/framework/Cache/package.xml +++ b/framework/Cache/package.xml @@ -53,6 +53,7 @@ Performance Suite's content cache), memcached, or an SQL table. + @@ -87,15 +88,16 @@ Performance Suite's content cache), memcached, or an SQL table. Log pear.horde.org + + Memcache + pear.horde.org + apc eaccelerator - - memcache - @@ -109,6 +111,7 @@ Performance Suite's content cache), memcached, or an SQL table. + diff --git a/framework/Core/lib/Horde/Core/Binder/Cache.php b/framework/Core/lib/Horde/Core/Binder/Cache.php index ce31ed15c..ed6d1a863 100644 --- a/framework/Core/lib/Horde/Core/Binder/Cache.php +++ b/framework/Core/lib/Horde/Core/Binder/Cache.php @@ -7,31 +7,49 @@ class Horde_Core_Binder_Cache implements Horde_Injector_Binder { public function create(Horde_Injector $injector) { - return $this->_getCacheInstance($GLOBALS['conf']['cache']['driver'], $injector); - } - - protected function _getCacheInstance($driver, $injector) - { - if (empty($driver) || (strcasecmp($driver, 'None') === 0)) { + $driver = empty($GLOBALS['conf']['cache']['driver']) + ? 'Null' + : $GLOBALS['conf']['cache']['driver']; + if (strcasecmp($driver, 'None') === 0) { $driver = 'Null'; } $params = Horde::getDriverConfig('cache', $driver); + if (isset($GLOBALS['conf']['cache']['default_lifetime'])) { + $params['lifetime'] = $GLOBALS['conf']['cache']['default_lifetime']; + } + + $logger = $injector->getInstance('Horde_Log_Logger'); if (strcasecmp($driver, 'Memcache') === 0) { $params['memcache'] = $injector->getInstance('Horde_Memcache'); - } elseif (strcasecmp($driver, 'Sql') === 0) { - $params['db'] = $injector->getInstance('Horde_Db_Adapter_Base'); + } else { + if (strcasecmp($driver, 'Sql') === 0) { + $params['db'] = $injector->getInstance('Horde_Db_Adapter_Base'); + } if (!empty($params['use_memorycache'])) { - $params['use_memorycache'] = $this->_getCacheInstance($params['use_memorycache'], $injector); + $params = array( + 'stack' => array( + array( + 'driver' => 'Memcache', + 'params' => array_merge($params, array( + 'logger' => $logger, + 'memcache' => $injector->getInstance('Horde_Memcache') + )) + ), + array( + 'driver' => $driver, + 'params' => array_merge($params, array( + 'logger' => $logger + )) + ) + ) + ); + $driver = 'Stack'; } } - if (isset($GLOBALS['conf']['cache']['default_lifetime'])) { - $params['lifetime'] = $GLOBALS['conf']['cache']['default_lifetime']; - } - $params['logger'] = $injector->getInstance('Horde_Log_Logger'); return Horde_Cache::factory($driver, $params);