From 23be1a7cdbf089379522fd21b1ca11e16068167d Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Mon, 28 May 2012 20:47:12 -0400 Subject: [PATCH] ... --- framework/caching/CacheDependency.php | 113 ----------------- framework/caching/DbCache.php | 227 +++++++++++++++------------------- framework/caching/Dependency.php | 8 +- framework/caching/MemCache.php | 128 ++++++------------- framework/caching/MemCacheServer.php | 51 ++++++++ 5 files changed, 190 insertions(+), 337 deletions(-) delete mode 100644 framework/caching/CacheDependency.php create mode 100644 framework/caching/MemCacheServer.php diff --git a/framework/caching/CacheDependency.php b/framework/caching/CacheDependency.php deleted file mode 100644 index 208400d..0000000 --- a/framework/caching/CacheDependency.php +++ /dev/null @@ -1,113 +0,0 @@ - - * @since 2.0 - */ -class CacheDependency extends \yii\base\Object -{ - /** - * @var boolean Whether this dependency is reusable or not. - * If set to true, dependent data for this cache dependency will only be generated once per request. - * You can then use the same cache dependency for multiple separate cache calls on the same page - * without the overhead of re-evaluating the dependency each time. - * Defaults to false; - * @since 1.1.11 - */ - public $reuseDependentData = false; - - /** - * @var array cached data for reusable dependencies. - * @since 1.1.11 - */ - private static $_reusableData = array(); - - private $_hash; - private $_data; - - /** - * Evaluates the dependency by generating and saving the data related with dependency. - * This method is invoked by cache before writing data into it. - */ - public function evaluateDependency() - { - if ($this->reuseDependentData) { - $hash = $this->getHash(); - if (!isset(self::$_reusableData[$hash]['dependentData'])) { - self::$_reusableData[$hash]['dependentData'] = $this->generateDependentData(); - } - $this->_data = self::$_reusableData[$hash]['dependentData']; - } else { - $this->_data = $this->generateDependentData(); - } - } - - /** - * @return boolean whether the dependency has changed. - */ - public function getHasChanged() - { - if ($this->reuseDependentData) { - $hash = $this->getHash(); - if (!isset(self::$_reusableData[$hash]['hasChanged'])) { - if (!isset(self::$_reusableData[$hash]['dependentData'])) { - self::$_reusableData[$hash]['dependentData'] = $this->generateDependentData(); - } - self::$_reusableData[$hash]['hasChanged'] = self::$_reusableData[$hash]['dependentData'] != $this->_data; - } - return self::$_reusableData[$hash]['hasChanged']; - } else { - return $this->generateDependentData() != $this->_data; - } - } - - /** - * @return mixed the data used to determine if dependency has been changed. - * This data is available after {@link evaluateDependency} is called. - */ - public function getDependentData() - { - return $this->_data; - } - - /** - * Generates the data needed to determine if dependency has been changed. - * Derived classes should override this method to generate actual dependent data. - * @return mixed the data needed to determine if dependency has been changed. - */ - protected function generateDependentData() - { - return null; - } - - /** - * Generates a unique hash that identifies this cache dependency. - * @return string the hash for this cache dependency - */ - private function getHash() - { - if ($this->_hash === null) { - $this->_hash = sha1(serialize($this)); - } - return $this->_hash; - } -} \ No newline at end of file diff --git a/framework/caching/DbCache.php b/framework/caching/DbCache.php index 59bcbc1..3bd1fcf 100644 --- a/framework/caching/DbCache.php +++ b/framework/caching/DbCache.php @@ -1,6 +1,6 @@ * @since 2.0 */ -class CDbCache extends CCache +class DbCache extends Cache { /** - * @var string the ID of the {@link CDbConnection} application component. If not set, + * @var string the ID of the {@link Connection} application component. If not set, * a SQLite3 database will be automatically created and used. The SQLite database file * is protected/runtime/cache-YiiVersion.db. */ @@ -50,19 +51,23 @@ class CDbCache extends CCache * binary data type (e.g. LONGBLOB in MySQL, BYTEA in PostgreSQL.) * @see autoCreateCacheTable */ - public $cacheTableName='YiiCache'; + public $cacheTableName = 'tbl_cache'; /** * @var boolean whether the cache DB table should be created automatically if it does not exist. Defaults to true. * If you already have the table created, it is recommended you set this property to be false to improve performance. * @see cacheTableName */ - public $autoCreateCacheTable=true; + public $autoCreateCacheTable = true; /** - * @var CDbConnection the DB connection instance + * @var integer the probability (parts per million) that garbage collection (GC) should be performed + * when storing a piece of data in the cache. Defaults to 100, meaning 0.01% chance. + * This number should be between 0 and 1000000. A value 0 meaning no GC will be performed at all. + **/ + public $gcProbability = 100; + /** + * @var Connection the DB connection instance */ private $_db; - private $_gcProbability=100; - private $_gced=false; /** * Initializes this application component. @@ -75,61 +80,36 @@ class CDbCache extends CCache { parent::init(); - $db=$this->getDbConnection(); + $db = $this->getDbConnection(); $db->setActive(true); - if($this->autoCreateCacheTable) - { - $sql="DELETE FROM {$this->cacheTableName} WHERE expire>0 AND expire<".time(); - try - { + if ($this->autoCreateCacheTable) { + $sql = "DELETE FROM {$this->cacheTableName} WHERE expire>0 AND expire<" . time(); + try { $db->createCommand($sql)->execute(); - } - catch(Exception $e) - { - $this->createCacheTable($db,$this->cacheTableName); + } catch (Exception $e) { + $this->createCacheTable($db, $this->cacheTableName); } } } /** - * @return integer the probability (parts per million) that garbage collection (GC) should be performed - * when storing a piece of data in the cache. Defaults to 100, meaning 0.01% chance. - */ - public function getGCProbability() - { - return $this->_gcProbability; - } - - /** - * @param integer $value the probability (parts per million) that garbage collection (GC) should be performed - * when storing a piece of data in the cache. Defaults to 100, meaning 0.01% chance. - * This number should be between 0 and 1000000. A value 0 meaning no GC will be performed at all. - */ - public function setGCProbability($value) - { - $value=(int)$value; - if($value<0) - $value=0; - if($value>1000000) - $value=1000000; - $this->_gcProbability=$value; - } - - /** * Creates the cache DB table. - * @param CDbConnection $db the database connection + * @param Connection $db the database connection * @param string $tableName the name of the table to be created */ - protected function createCacheTable($db,$tableName) + protected function createCacheTable($db, $tableName) { - $driver=$db->getDriverName(); - if($driver==='mysql') - $blob='LONGBLOB'; - else if($driver==='pgsql') - $blob='BYTEA'; - else - $blob='BLOB'; - $sql=<<getDriverName(); + if ($driver === 'mysql') { + $blob = 'LONGBLOB'; + } else { + if ($driver === 'pgsql') { + $blob = 'BYTEA'; + } else { + $blob = 'BLOB'; + } + } + $sql = <<_db!==null) - return $this->_db; - else if(($id=$this->connectionID)!==null) - { - if(($this->_db=\Yii::$application->getComponent($id)) instanceof CDbConnection) - return $this->_db; - else - throw new CException(Yii::t('yii','CDbCache.connectionID "{id}" is invalid. Please make sure it refers to the ID of a CDbConnection application component.', - array('{id}'=>$id))); - } - else - { - $dbFile=\Yii::$application->getRuntimePath().DIRECTORY_SEPARATOR.'cache-'.Yii::getVersion().'.db'; - return $this->_db=new CDbConnection('sqlite:'.$dbFile); + if ($this->_db === null) { + if ($this->connectionID !== null && ($db = \Yii::$application->getComponent($this->connectionID)) instanceof Connection) { + $this->_db = $db; + } else { + throw new Exception("DbCache.connectionID must refer to the ID of a DB connection application component."); + } } + return $this->_db; } /** * Sets the DB connection used by the cache component. - * @param CDbConnection $value the DB connection instance - * @since 1.1.5 + * @param Connection $value the DB connection instance */ public function setDbConnection($value) { - $this->_db=$value; + $this->_db = $value; } /** @@ -181,19 +154,21 @@ EOD; */ protected function getValue($key) { - $time=time(); - $sql="SELECT value FROM {$this->cacheTableName} WHERE id='$key' AND (expire=0 OR expire>$time)"; - $db=$this->getDbConnection(); - if($db->queryCachingDuration>0) - { - $duration=$db->queryCachingDuration; - $db->queryCachingDuration=0; - $result=$db->createCommand($sql)->queryScalar(); - $db->queryCachingDuration=$duration; + $query = new Query; + $query->select(array('value')) + ->from($this->cacheTableName) + ->where(array('id' => $key)) + ->andWhere('expire = 0 OR expire > ' . time()); + $db = $this->getDbConnection(); + if ($db->queryCachingDuration >= 0) { + $duration = $db->queryCachingDuration; + $db->queryCachingDuration = -1; + $result = $query->createCommand($db)->queryScalar(); + $db->queryCachingDuration = $duration; return $result; + } else { + return $query->createCommand($db)->queryScalar(); } - else - return $db->createCommand($sql)->queryScalar(); } /** @@ -203,29 +178,31 @@ EOD; */ protected function getValues($keys) { - if(empty($keys)) + if (empty($keys)) { return array(); + } - $ids=implode("','",$keys); - $time=time(); - $sql="SELECT id, value FROM {$this->cacheTableName} WHERE id IN ('$ids') AND (expire=0 OR expire>$time)"; + $ids = implode("','", $keys); + $time = time(); + $sql = "SELECT id, value FROM {$this->cacheTableName} WHERE id IN ('$ids') AND (expire=0 OR expire>$time)"; - $db=$this->getDbConnection(); - if($db->queryCachingDuration>0) - { - $duration=$db->queryCachingDuration; - $db->queryCachingDuration=0; - $rows=$db->createCommand($sql)->queryAll(); - $db->queryCachingDuration=$duration; + $db = $this->getDbConnection(); + if ($db->queryCachingDuration > 0) { + $duration = $db->queryCachingDuration; + $db->queryCachingDuration = 0; + $rows = $db->createCommand($sql)->queryAll(); + $db->queryCachingDuration = $duration; + } else { + $rows = $db->createCommand($sql)->queryAll(); } - else - $rows=$db->createCommand($sql)->queryAll(); - $results=array(); - foreach($keys as $key) - $results[$key]=false; - foreach($rows as $row) - $results[$row['id']]=$row['value']; + $results = array(); + foreach ($keys as $key) { + $results[$key] = false; + } + foreach ($rows as $row) { + $results[$row['id']] = $row['value']; + } return $results; } @@ -238,10 +215,10 @@ EOD; * @param integer $expire the number of seconds in which the cached value will expire. 0 means never expire. * @return boolean true if the value is successfully stored into cache, false otherwise */ - protected function setValue($key,$value,$expire) + protected function setValue($key, $value, $expire) { $this->deleteValue($key); - return $this->addValue($key,$value,$expire); + return $this->addValue($key, $value, $expire); } /** @@ -253,28 +230,24 @@ EOD; * @param integer $expire the number of seconds in which the cached value will expire. 0 means never expire. * @return boolean true if the value is successfully stored into cache, false otherwise */ - protected function addValue($key,$value,$expire) + protected function addValue($key, $value, $expire) { - if(!$this->_gced && mt_rand(0,1000000)<$this->_gcProbability) - { + if (mt_rand(0, 1000000) < $this->_gcProbability) { $this->gc(); - $this->_gced=true; } - if($expire>0) - $expire+=time(); - else - $expire=0; - $sql="INSERT INTO {$this->cacheTableName} (id,expire,value) VALUES ('$key',$expire,:value)"; - try - { - $command=$this->getDbConnection()->createCommand($sql); - $command->bindValue(':value',$value,PDO::PARAM_LOB); + if ($expire > 0) { + $expire += time(); + } else { + $expire = 0; + } + $sql = "INSERT INTO {$this->cacheTableName} (id,expire,value) VALUES ('$key',$expire,:value)"; + try { + $command = $this->getDbConnection()->createCommand($sql); + $command->bindValue(':value', $value, PDO::PARAM_LOB); $command->execute(); return true; - } - catch(Exception $e) - { + } catch (Exception $e) { return false; } } @@ -287,7 +260,7 @@ EOD; */ protected function deleteValue($key) { - $sql="DELETE FROM {$this->cacheTableName} WHERE id='$key'"; + $sql = "DELETE FROM {$this->cacheTableName} WHERE id='$key'"; $this->getDbConnection()->createCommand($sql)->execute(); return true; } @@ -297,7 +270,7 @@ EOD; */ protected function gc() { - $this->getDbConnection()->createCommand("DELETE FROM {$this->cacheTableName} WHERE expire>0 AND expire<".time())->execute(); + $this->getDbConnection()->createCommand("DELETE FROM {$this->cacheTableName} WHERE expire>0 AND expire<" . time())->execute(); } /** diff --git a/framework/caching/Dependency.php b/framework/caching/Dependency.php index 29b95d5..6f6bb4b 100644 --- a/framework/caching/Dependency.php +++ b/framework/caching/Dependency.php @@ -1,6 +1,6 @@ * @since 2.0 */ -class CCacheDependency extends CComponent implements ICacheDependency +class Dependency extends \yii\base\Object { /** * @var boolean Whether this dependency is reusable or not. diff --git a/framework/caching/MemCache.php b/framework/caching/MemCache.php index b026cac..706eb28 100644 --- a/framework/caching/MemCache.php +++ b/framework/caching/MemCache.php @@ -9,20 +9,27 @@ namespace yii\caching; +use yii\base\Exception; + /** - * MemCache implements a cache application component based on {@link http://memcached.org/ memcached}. + * MemCache implements a cache application component based on [memcache](http://pecl.php.net/package/memcache) + * and [memcached](http://pecl.php.net/package/memcached). + * + * MemCache supports both [memcache](http://pecl.php.net/package/memcache) and + * [memcached](http://pecl.php.net/package/memcached). By setting [[useMemcached]] to be true or false, + * one can let MemCache to use either memcached or memcache, respectively. * - * MemCache can be configured with a list of memcache servers by settings - * its {@link setServers servers} property. By default, MemCache assumes - * there is a memcache server running on localhost at port 11211. + * MemCache can be configured with a list of memcache servers by settings its [[servers]] property. + * By default, MemCache assumes there is a memcache server running on localhost at port 11211. * - * See {@link CCache} manual for common cache operations that are supported by MemCache. + * See [[Cache]] for common cache operations that ApcCache supports. * * Note, there is no security measure to protected data in memcache. * All data in memcache can be accessed by any process running in the system. * * To use MemCache as the cache application component, configure the application as follows, - *
+ *
+ * ~~~
  * array(
  *     'components'=>array(
  *         'cache'=>array(
@@ -42,18 +49,13 @@ namespace yii\caching;
  *         ),
  *     ),
  * )
- * 
- * In the above, two memcache servers are used: server1 and server2. - * You can configure more properties of every server, including: - * host, port, persistent, weight, timeout, retryInterval, status. - * See {@link http://www.php.net/manual/en/function.memcache-addserver.php} - * for more details. + * ~~~ * - * MemCache can also be used with {@link http://pecl.php.net/package/memcached memcached}. - * To do so, set {@link useMemcached} to be true. + * In the above, two memcache servers are used: server1 and server2. You can configure more properties of + * each server, such as `persistent`, `weight`, `timeout`. Please see [[MemCacheServer]] for available options. * - * @property mixed $memCache The memcache instance (or memcached if {@link useMemcached} is true) used by this component. - * @property array $servers List of memcache server configurations. Each element is a {@link MemCacheServerConfiguration}. + * @property mixed $memCache The memcache instance (or memcached if [[useMemcached]] is true) used by this component. + * @property MemCacheServer[] $servers List of memcache server configurations. * * @author Qiang Xue * @since 2.0 @@ -68,7 +70,7 @@ class MemCache extends Cache */ public $useMemcached = false; /** - * @var Memcache the Memcache instance + * @var \Memcache|\Memcached the Memcache instance */ private $_cache = null; /** @@ -78,9 +80,7 @@ class MemCache extends Cache /** * Initializes this application component. - * This method is required by the {@link IApplicationComponent} interface. * It creates the memcache instance and adds memcache servers. - * @throws CException if memcache extension is not loaded */ public function init() { @@ -89,36 +89,41 @@ class MemCache extends Cache $cache = $this->getMemCache(); if (count($servers)) { foreach ($servers as $server) { + if ($server->host === null) { + throw new Exception("The 'host' property must be specified for every memcache server."); + } if ($this->useMemcached) { $cache->addServer($server->host, $server->port, $server->weight); } else { - $cache->addServer($server->host, $server->port, $server->persistent, $server->weight, $server->timeout, $server->status); + $cache->addServer($server->host, $server->port, $server->persistent, + $server->weight, $server->timeout, $server->retryInterval, $server->status); } } } else { - $cache->addServer('localhost', 11211); + $cache->addServer('127.0.0.1', 11211); } } /** - * @throws CException if extension isn't loaded - * @return Memcache|Memcached the memcache instance (or memcached if {@link useMemcached} is true) used by this component. + * Returns the underlying memcache (or memcached) object. + * @return \Memcache|\Memcached the memcache (or memcached) object used by this cache component. + * @throws Exception if memcache or memcached extension is not loaded */ public function getMemCache() { - if ($this->_cache !== null) { - return $this->_cache; - } else { + if ($this->_cache === null) { $extension = $this->useMemcached ? 'memcached' : 'memcache'; if (!extension_loaded($extension)) { - throw new CException(Yii::t('yii', "MemCache requires PHP $extension extension to be loaded.")); + throw new Exception("MemCache requires PHP $extension extension to be loaded."); } - return $this->_cache = $this->useMemcached ? new Memcached : new Memcache; + $this->_cache = $this->useMemcached ? new \Memcached : new \Memcache; } + return $this->_cache; } /** - * @return array list of memcache server configurations. Each element is a {@link MemCacheServerConfiguration}. + * Returns the memcache server configurations. + * @return MemCacheServer[] list of memcache server configurations. */ public function getServers() { @@ -133,7 +138,7 @@ class MemCache extends Cache public function setServers($config) { foreach ($config as $c) { - $this->_servers[] = new MemCacheServerConfiguration($c); + $this->_servers[] = MemCacheServer::newInstance($c); } } @@ -213,72 +218,9 @@ class MemCache extends Cache * Deletes all values from cache. * This is the implementation of the method declared in the parent class. * @return boolean whether the flush operation was successful. - * @since 1.1.5 */ protected function flushValues() { return $this->_cache->flush(); } } - -/** - * MemCacheServerConfiguration represents the configuration data for a single memcache server. - * - * See {@link http://www.php.net/manual/en/function.Memcache-addServer.php} - * for detailed explanation of each configuration property. - * - * @author Qiang Xue - * @version $Id$ - * @package system.caching - * @since 1.0 - */ -class MemCacheServerConfiguration extends CComponent -{ - /** - * @var string memcache server hostname or IP address - */ - public $host; - /** - * @var integer memcache server port - */ - public $port = 11211; - /** - * @var boolean whether to use a persistent connection - */ - public $persistent = true; - /** - * @var integer probability of using this server among all servers. - */ - public $weight = 1; - /** - * @var integer value in seconds which will be used for connecting to the server - */ - public $timeout = 15; - /** - * @var integer how often a failed server will be retried (in seconds) - */ - public $retryInterval = 15; - /** - * @var boolean if the server should be flagged as online upon a failure - */ - public $status = true; - - /** - * Constructor. - * @param array $config list of memcache server configurations. - * @throws CException if the configuration is not an array - */ - public function __construct($config) - { - if (is_array($config)) { - foreach ($config as $key => $value) { - $this->$key = $value; - } - if ($this->host === null) { - throw new CException(Yii::t('yii', 'MemCache server configuration must have "host" value.')); - } - } else { - throw new CException(Yii::t('yii', 'MemCache server configuration must be an array.')); - } - } -} \ No newline at end of file diff --git a/framework/caching/MemCacheServer.php b/framework/caching/MemCacheServer.php new file mode 100644 index 0000000..3c7e055 --- /dev/null +++ b/framework/caching/MemCacheServer.php @@ -0,0 +1,51 @@ + + * @since 2.0 + */ +class MemCacheServer extends \yii\base\Object +{ + /** + * @var string memcache server hostname or IP address + */ + public $host; + /** + * @var integer memcache server port + */ + public $port = 11211; + /** + * @var integer probability of using this server among all servers. + */ + public $weight = 1; + /** + * @var boolean whether to use a persistent connection. This is used by memcache only. + */ + public $persistent = true; + /** + * @var integer value in seconds which will be used for connecting to the server. This is used by memcache only. + */ + public $timeout = 15; + /** + * @var integer how often a failed server will be retried (in seconds). This is used by memcache only. + */ + public $retryInterval = 15; + /** + * @var boolean if the server should be flagged as online upon a failure. This is used by memcache only. + */ + public $status = true; +} \ No newline at end of file