Location: PHPKode > projects > SolarPHP > solar-system-1.1.1/solar/source/solar/Solar/Cache/Adapter/Memcache.php
<?php
/**
 * 
 * Memcache cache controller.
 * 
 * This adapter lets you connect to a
 * [memcached](http://www.danga.com/memcached/) server, which uses system
 * memory to cache data. In general, you never need to instantiate it 
 * yourself; instead, use Solar_Cache as the frontend for it and specify
 * 'Solar_Cache_Memcache' in the config keys as the 'adapter' value.
 * 
 * This kind of cache is extremely fast, especially when on the same
 * server as the web process, although it may also be accessed via
 * network.  This particular adapter uses the PHP [[php::memcache | ]]
 * extension to manage the cache connection.  The extension is not
 * bundled with PHP; you will need to follow the
 * [installation instructions](http://php.net/memcache) before you can
 * use it.
 * 
 * @category Solar
 * 
 * @package Solar_Cache
 * 
 * @author Paul M. Jones <hide@address.com>
 * 
 * @license http://opensource.org/licenses/bsd-license.php BSD
 * 
 * @version $Id: Memcache.php 4442 2010-02-26 16:33:06Z pmjones $
 * 
 */
class Solar_Cache_Adapter_Memcache extends Solar_Cache_Adapter
{
    /**
     * 
     * Default configuration values.
     * 
     * @config string host The memcached host name, default 'localhost'.
     * 
     * @config int port The memcached port number, default 11211.
     * 
     * @config int timeout The timeout before the server connection is
     *   considered a miss, in seconds.  Default is 1 second, and should 
     *   not really be changed for reasons other than testing purposes.
     * 
     * @config array pool An array of memcache connections to connect to in a 
     *   multi-server pool. Each connection should be represented by an array
     *   with the following keys: `host`, `port`, `persistent`, `weight`, 
     *   `timeout`, `retry_interval`, `status` and `failure_callback`.
     *   The `pool` is empty by default, and will only be used instead of 
     *   a single-server connection if non-empty.
     * 
     * @var array
     * 
     */
    protected $_Solar_Cache_Adapter_Memcache = array(
        'host' => 'localhost',
        'port' => 11211,
        'timeout' => 1,
        'pool' => array(),
    );
    
    /**
     * 
     * Default configuration for a pool server node.
     * 
     * `host`
     * : (string) The memcached host name, default 'localhost'.
     * 
     * `port`
     * : (int) The memcached port number, default 11211.
     * 
     * `persistent`
     * : (bool) Controls the use of a persistent connection, default **TRUE**.
     * 
     * `weight`
     * : (int) Number of buckets to create for this server, which in turn 
     *   controls its probability of being selected. The probability is 
     *   relative to the total weight of all servers. Default 1.
     * 
     * `timeout`
     * : (int) Value in seconds which will be used for connecting to the 
     *   daemon. Default 1.
     * 
     * `retry_interval`
     * : (int) Controls how often a failed server will be retried. Default is
     *   15 seconds. A setting of -1 disables automatic retry.
     * 
     * `status`
     * : (bool) Controls if the server should be flagged as online. Setting 
     *   this parameter to **FALSE** and `retry_interval` to -1 allows a failed
     *   server to be kept in the pool so as not to affect the key distribution
     *   algorithm. Requests for this server will then failover or fail
     *   immediately depending on the *memcache.allow_failover* php.ini setting.
     *   Defaults to **TRUE**, meaning the server should be considered online.
     * 
     * `failure_callback`
     * : (callback) Allows specification of a callback function to run upon
     *   encountering a connection error. The callback is run before 
     *   failover is attempted, and takes two parameters: the hostname and port
     *   of the failed server. Default is null.
     * 
     * @var array
     * 
     */
    protected $_pool_node = array(
        'host'              => 'localhost',
        'port'              => 11211,
        'persistent'        => true,
        'weight'            => 1,
        'timeout'           => 1,
        'retry_interval'    => 1,
        'status'            => true,
        'failure_callback'  => null,        
    );
    
    
    /**
     * 
     * A memcache client object.
     * 
     * @var object
     * 
     */
    public $memcache;
    
    /**
     * 
     * Checks to make sure the memcache extension is available.
     * 
     * @return void
     * 
     */
    protected function _preConfig()
    {
        parent::_preConfig();
        if (! extension_loaded('memcache')) {
            throw $this->_exception('ERR_EXTENSION_NOT_LOADED', array(
                'extension' => 'memcache',
            ));
        }
    }
    
    /**
     * 
     * Post-construction tasks to complete object construction.
     * 
     * @return void
     * 
     */
    protected function _postConstruct()
    {
        parent::_postConstruct();
        
        $this->memcache = new Memcache;
        
        // pool or single-server connection?
        if (empty($this->_config['pool'])) {
            
            // make sure we can connect
            $result = @$this->memcache->connect(
                $this->_config['host'],
                $this->_config['port'],
                $this->_config['timeout']
            );
        
            if (! $result) {
                throw $this->_exception('ERR_CONNECTION_FAILED', array(
                    'host'    => $this->_config['host'],
                    'port'    => $this->_config['port'],
                    'timeout' => $this->_config['timeout'],
                ));
            }
            
        } else {
            
            // set up a pool
            $this->_createPool();
        }
    }
    
    /**
     * 
     * Updates or inserts cache entry data.
     * 
     * @param string $key The entry ID.
     * 
     * @param mixed $data The data to write into the entry.
     * 
     * @param int $life A custom lifespan, in seconds, for the entry; if null,
     * uses the default lifespan for the adapter instance.
     * 
     * @return bool True on success, false on failure.
     * 
     */
    public function save($key, $data, $life = null)
    {
        if (! $this->_active) {
            return;
        }
        
        // modify the key to add the prefix
        $key = $this->entry($key);
        
        // life value
        if ($life === null) {
            $life = $this->_life;
        }
        
        // store in memcache
        return $this->memcache->set($key, $data, null, $life);
    }
    
    /**
     * 
     * Inserts cache entry data, but only if the entry does not already exist.
     * 
     * @param string $key The entry ID.
     * 
     * @param mixed $data The data to write into the entry.
     * 
     * @param int $life A custom lifespan, in seconds, for the entry; if null,
     * uses the default lifespan for the adapter instance.
     * 
     * @return bool True on success, false on failure.
     * 
     */
    public function add($key, $data, $life = null)
    {
        if (! $this->_active) {
            return;
        }
        
        // modify the key to add the prefix
        $key = $this->entry($key);
        
        // life value
        if ($life === null) {
            $life = $this->_life;
        }
        
        // add to memcache
        return $this->memcache->add($key, $data, null, $life);
    }
    
    /**
     * 
     * Gets cache entry data.
     * 
     * @param string $key The entry ID.
     * 
     * @return mixed Boolean false on failure, string on success.
     * 
     */
    public function fetch($key)
    {
        if (! $this->_active) {
            return;
        }
        
        // modify the key to add the prefix
        $key = $this->entry($key);
        
        // get from memcache
        return $this->memcache->get($key);
    }
    
    /**
     * 
     * Increments a cache entry value by the specified amount.  If the entry
     * does not exist, creates it at zero, then increments it.
     * 
     * @param string $key The entry ID.
     * 
     * @param string $amt The amount to increment by (default +1).  Using
     * negative values is effectively a decrement.
     * 
     * @return int The new value of the cache entry.
     * 
     */
    public function increment($key, $amt = 1)
    {
        if (! $this->_active) {
            return;
        }
        
        // modify the key to add the prefix
        $key = $this->entry($key);
        
        // make sure we have a key to increment
        $this->add($key, 0, null, $this->_life);
        
        // let memcache do the increment and retain its value
        $val = $this->memcache->increment($key, $amt);
        
        // done
        return $val;
    }
    
    /**
     * 
     * Deletes a cache entry.
     * 
     * @param string $key The entry ID.
     * 
     * @return void
     * 
     */
    public function delete($key)
    {
        if (! $this->_active) {
            return;
        }
        
        // modify the key to add the prefix
        $key = $this->entry($key);
        
        // remove from memcache
        $this->memcache->delete($key);
    }
    
    /**
     * 
     * Removes all cache entries.
     * 
     * @return void
     * 
     */
    public function deleteAll()
    {
        if (! $this->_active) {
            return;
        }
        
        $this->memcache->flush();
    }
    
    /**
     * 
     * Adds servers to a memcache connection pool from configuration.
     * 
     * @return void
     * 
     */
    protected function _createPool()
    {
        $connection_count = 0;
        
        foreach ($this->_config['pool'] as $server) {
            // set all defaults
            $server = array_merge($this->_pool_node, $server);
            
            // separate addServer calls in case failure_callback is 
            // empty
            if (empty($server['failure_callback'])) {
                $result = $this->memcache->addServer(
                    (string) $server['host'],
                    (int)    $server['port'],
                    (bool)   $server['persistent'],
                    (int)    $server['weight'],
                    (int)    $server['retry_interval'],
                    (bool)   $server['status']
                );
                                
            } else {
                $result = $this->memcache->addServer(
                    (string) $server['host'],
                    (int)    $server['port'],
                    (bool)   $server['persistent'],
                    (int)    $server['weight'],
                    (int)    $server['retry_interval'],
                    (bool)   $server['status'],
                             $server['failure_callback']
                );
            }
            
            // Did connection to the last node succeed?
            if ($result === true) {
                $connection_count++;
            }
        
        }
        
        // make sure we connected to at least one
        if ($connection_count < 1) {
            $info = $this->_config['pool'];
            throw $this->_exception('ERR_CONNECTION_FAILED', $info);
        }
    }
}
Return current item: SolarPHP