diff options
Diffstat (limited to 'framework/caching/CFileCache.php')
| -rw-r--r-- | framework/caching/CFileCache.php | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/framework/caching/CFileCache.php b/framework/caching/CFileCache.php new file mode 100644 index 0000000..a339699 --- /dev/null +++ b/framework/caching/CFileCache.php @@ -0,0 +1,222 @@ +<?php +/** + * CFileCache class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * CFileCache provides a file-based caching mechanism. + * + * For each data value being cached, CFileCache will use store it in a separate file + * under {@link cachePath} which defaults to 'protected/runtime/cache'. + * CFileCache will perform garbage collection automatically to remove expired cache files. + * + * See {@link CCache} manual for common cache operations that are supported by CFileCache. + * + * @property integer $gCProbability 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. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id: CFileCache.php 3515 2011-12-28 12:29:24Z mdomba $ + * @package system.caching + */ +class CFileCache extends CCache +{ + /** + * @var string the directory to store cache files. Defaults to null, meaning + * using 'protected/runtime/cache' as the directory. + */ + public $cachePath; + /** + * @var string cache file suffix. Defaults to '.bin'. + */ + public $cacheFileSuffix='.bin'; + /** + * @var integer the level of sub-directories to store cache files. Defaults to 0, + * meaning no sub-directories. If the system has huge number of cache files (e.g. 10K+), + * you may want to set this value to be 1 or 2 so that the file system is not over burdened. + * The value of this property should not exceed 16 (less than 3 is recommended). + */ + public $directoryLevel=0; + + private $_gcProbability=100; + private $_gced=false; + + /** + * Initializes this application component. + * This method is required by the {@link IApplicationComponent} interface. + * It checks the availability of memcache. + * @throws CException if APC cache extension is not loaded or is disabled. + */ + public function init() + { + parent::init(); + if($this->cachePath===null) + $this->cachePath=Yii::app()->getRuntimePath().DIRECTORY_SEPARATOR.'cache'; + if(!is_dir($this->cachePath)) + mkdir($this->cachePath,0777,true); + } + + /** + * @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; + } + + /** + * 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() + { + $this->gc(false); + return true; + } + + /** + * Retrieves a value from cache with a specified key. + * This is the implementation of the method declared in the parent class. + * @param string $key a unique key identifying the cached value + * @return string the value stored in cache, false if the value is not in the cache or expired. + */ + protected function getValue($key) + { + $cacheFile=$this->getCacheFile($key); + if(($time=@filemtime($cacheFile))>time()) + return @file_get_contents($cacheFile); + else if($time>0) + @unlink($cacheFile); + return false; + } + + /** + * Stores a value identified by a key in cache. + * This is the implementation of the method declared in the parent class. + * + * @param string $key the key identifying the value to be cached + * @param string $value the value to be cached + * @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) + { + if(!$this->_gced && mt_rand(0,1000000)<$this->_gcProbability) + { + $this->gc(); + $this->_gced=true; + } + + if($expire<=0) + $expire=31536000; // 1 year + $expire+=time(); + + $cacheFile=$this->getCacheFile($key); + if($this->directoryLevel>0) + @mkdir(dirname($cacheFile),0777,true); + if(@file_put_contents($cacheFile,$value,LOCK_EX)!==false) + { + @chmod($cacheFile,0777); + return @touch($cacheFile,$expire); + } + else + return false; + } + + /** + * Stores a value identified by a key into cache if the cache does not contain this key. + * This is the implementation of the method declared in the parent class. + * + * @param string $key the key identifying the value to be cached + * @param string $value the value to be cached + * @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) + { + $cacheFile=$this->getCacheFile($key); + if(@filemtime($cacheFile)>time()) + return false; + return $this->setValue($key,$value,$expire); + } + + /** + * Deletes a value with the specified key from cache + * This is the implementation of the method declared in the parent class. + * @param string $key the key of the value to be deleted + * @return boolean if no error happens during deletion + */ + protected function deleteValue($key) + { + $cacheFile=$this->getCacheFile($key); + return @unlink($cacheFile); + } + + /** + * Returns the cache file path given the cache key. + * @param string $key cache key + * @return string the cache file path + */ + protected function getCacheFile($key) + { + if($this->directoryLevel>0) + { + $base=$this->cachePath; + for($i=0;$i<$this->directoryLevel;++$i) + { + if(($prefix=substr($key,$i+$i,2))!==false) + $base.=DIRECTORY_SEPARATOR.$prefix; + } + return $base.DIRECTORY_SEPARATOR.$key.$this->cacheFileSuffix; + } + else + return $this->cachePath.DIRECTORY_SEPARATOR.$key.$this->cacheFileSuffix; + } + + /** + * Removes expired cache files. + * @param boolean $expiredOnly whether to removed expired cache files only. If true, all cache files under {@link cachePath} will be removed. + * @param string $path the path to clean with. If null, it will be {@link cachePath}. + */ + public function gc($expiredOnly=true,$path=null) + { + if($path===null) + $path=$this->cachePath; + if(($handle=opendir($path))===false) + return; + while(($file=readdir($handle))!==false) + { + if($file[0]==='.') + continue; + $fullPath=$path.DIRECTORY_SEPARATOR.$file; + if(is_dir($fullPath)) + $this->gc($expiredOnly,$fullPath); + else if($expiredOnly && @filemtime($fullPath)<time() || !$expiredOnly) + @unlink($fullPath); + } + closedir($handle); + } +} |
