File indexing completed on 2025-01-19 05:20:56
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Cache 0017 * @subpackage Zend_Cache_Backend 0018 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0019 * @license http://framework.zend.com/license/new-bsd New BSD License 0020 * @version $Id$ 0021 */ 0022 0023 0024 /** 0025 * @see Zend_Cache_Backend_Interface 0026 */ 0027 // require_once 'Zend/Cache/Backend/ExtendedInterface.php'; 0028 0029 /** 0030 * @see Zend_Cache_Backend 0031 */ 0032 // require_once 'Zend/Cache/Backend.php'; 0033 0034 0035 /** 0036 * @package Zend_Cache 0037 * @subpackage Zend_Cache_Backend 0038 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0039 * @license http://framework.zend.com/license/new-bsd New BSD License 0040 */ 0041 class Zend_Cache_Backend_Apc extends Zend_Cache_Backend implements Zend_Cache_Backend_ExtendedInterface 0042 { 0043 /** 0044 * Log message 0045 */ 0046 const TAGS_UNSUPPORTED_BY_CLEAN_OF_APC_BACKEND = 'Zend_Cache_Backend_Apc::clean() : tags are unsupported by the Apc backend'; 0047 const TAGS_UNSUPPORTED_BY_SAVE_OF_APC_BACKEND = 'Zend_Cache_Backend_Apc::save() : tags are unsupported by the Apc backend'; 0048 0049 /** 0050 * Constructor 0051 * 0052 * @param array $options associative array of options 0053 * @throws Zend_Cache_Exception 0054 * @return void 0055 */ 0056 public function __construct(array $options = array()) 0057 { 0058 if (!extension_loaded('apc')) { 0059 Zend_Cache::throwException('The apc extension must be loaded for using this backend !'); 0060 } 0061 parent::__construct($options); 0062 } 0063 0064 /** 0065 * Test if a cache is available for the given id and (if yes) return it (false else) 0066 * 0067 * WARNING $doNotTestCacheValidity=true is unsupported by the Apc backend 0068 * 0069 * @param string $id cache id 0070 * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested 0071 * @return string cached datas (or false) 0072 */ 0073 public function load($id, $doNotTestCacheValidity = false) 0074 { 0075 $tmp = apc_fetch($id); 0076 if (is_array($tmp)) { 0077 return $tmp[0]; 0078 } 0079 return false; 0080 } 0081 0082 /** 0083 * Test if a cache is available or not (for the given id) 0084 * 0085 * @param string $id cache id 0086 * @return mixed false (a cache is not available) or "last modified" timestamp (int) of the available cache record 0087 */ 0088 public function test($id) 0089 { 0090 $tmp = apc_fetch($id); 0091 if (is_array($tmp)) { 0092 return $tmp[1]; 0093 } 0094 return false; 0095 } 0096 0097 /** 0098 * Save some string datas into a cache record 0099 * 0100 * Note : $data is always "string" (serialization is done by the 0101 * core not by the backend) 0102 * 0103 * @param string $data datas to cache 0104 * @param string $id cache id 0105 * @param array $tags array of strings, the cache record will be tagged by each string entry 0106 * @param int $specificLifetime if != false, set a specific lifetime for this cache record (null => infinite lifetime) 0107 * @return boolean true if no problem 0108 */ 0109 public function save($data, $id, $tags = array(), $specificLifetime = false) 0110 { 0111 $lifetime = $this->getLifetime($specificLifetime); 0112 $result = apc_store($id, array($data, time(), $lifetime), $lifetime); 0113 if (count($tags) > 0) { 0114 $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_APC_BACKEND); 0115 } 0116 return $result; 0117 } 0118 0119 /** 0120 * Remove a cache record 0121 * 0122 * @param string $id cache id 0123 * @return boolean true if no problem 0124 */ 0125 public function remove($id) 0126 { 0127 return apc_delete($id); 0128 } 0129 0130 /** 0131 * Clean some cache records 0132 * 0133 * Available modes are : 0134 * 'all' (default) => remove all cache entries ($tags is not used) 0135 * 'old' => unsupported 0136 * 'matchingTag' => unsupported 0137 * 'notMatchingTag' => unsupported 0138 * 'matchingAnyTag' => unsupported 0139 * 0140 * @param string $mode clean mode 0141 * @param array $tags array of tags 0142 * @throws Zend_Cache_Exception 0143 * @return boolean true if no problem 0144 */ 0145 public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array()) 0146 { 0147 switch ($mode) { 0148 case Zend_Cache::CLEANING_MODE_ALL: 0149 return apc_clear_cache('user'); 0150 break; 0151 case Zend_Cache::CLEANING_MODE_OLD: 0152 $this->_log("Zend_Cache_Backend_Apc::clean() : CLEANING_MODE_OLD is unsupported by the Apc backend"); 0153 break; 0154 case Zend_Cache::CLEANING_MODE_MATCHING_TAG: 0155 case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG: 0156 case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG: 0157 $this->_log(self::TAGS_UNSUPPORTED_BY_CLEAN_OF_APC_BACKEND); 0158 break; 0159 default: 0160 Zend_Cache::throwException('Invalid mode for clean() method'); 0161 break; 0162 } 0163 } 0164 0165 /** 0166 * Return true if the automatic cleaning is available for the backend 0167 * 0168 * DEPRECATED : use getCapabilities() instead 0169 * 0170 * @deprecated 0171 * @return boolean 0172 */ 0173 public function isAutomaticCleaningAvailable() 0174 { 0175 return false; 0176 } 0177 0178 /** 0179 * Return the filling percentage of the backend storage 0180 * 0181 * @throws Zend_Cache_Exception 0182 * @return int integer between 0 and 100 0183 */ 0184 public function getFillingPercentage() 0185 { 0186 $mem = apc_sma_info(true); 0187 $memSize = $mem['num_seg'] * $mem['seg_size']; 0188 $memAvailable= $mem['avail_mem']; 0189 $memUsed = $memSize - $memAvailable; 0190 if ($memSize == 0) { 0191 Zend_Cache::throwException('can\'t get apc memory size'); 0192 } 0193 if ($memUsed > $memSize) { 0194 return 100; 0195 } 0196 return ((int) (100. * ($memUsed / $memSize))); 0197 } 0198 0199 /** 0200 * Return an array of stored tags 0201 * 0202 * @return array array of stored tags (string) 0203 */ 0204 public function getTags() 0205 { 0206 $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_APC_BACKEND); 0207 return array(); 0208 } 0209 0210 /** 0211 * Return an array of stored cache ids which match given tags 0212 * 0213 * In case of multiple tags, a logical AND is made between tags 0214 * 0215 * @param array $tags array of tags 0216 * @return array array of matching cache ids (string) 0217 */ 0218 public function getIdsMatchingTags($tags = array()) 0219 { 0220 $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_APC_BACKEND); 0221 return array(); 0222 } 0223 0224 /** 0225 * Return an array of stored cache ids which don't match given tags 0226 * 0227 * In case of multiple tags, a logical OR is made between tags 0228 * 0229 * @param array $tags array of tags 0230 * @return array array of not matching cache ids (string) 0231 */ 0232 public function getIdsNotMatchingTags($tags = array()) 0233 { 0234 $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_APC_BACKEND); 0235 return array(); 0236 } 0237 0238 /** 0239 * Return an array of stored cache ids which match any given tags 0240 * 0241 * In case of multiple tags, a logical AND is made between tags 0242 * 0243 * @param array $tags array of tags 0244 * @return array array of any matching cache ids (string) 0245 */ 0246 public function getIdsMatchingAnyTags($tags = array()) 0247 { 0248 $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_APC_BACKEND); 0249 return array(); 0250 } 0251 0252 /** 0253 * Return an array of stored cache ids 0254 * 0255 * @return array array of stored cache ids (string) 0256 */ 0257 public function getIds() 0258 { 0259 $ids = array(); 0260 $iterator = new APCIterator('user', null, APC_ITER_KEY); 0261 foreach ($iterator as $item) { 0262 $ids[] = $item['key']; 0263 } 0264 0265 return $ids; 0266 } 0267 0268 /** 0269 * Return an array of metadatas for the given cache id 0270 * 0271 * The array must include these keys : 0272 * - expire : the expire timestamp 0273 * - tags : a string array of tags 0274 * - mtime : timestamp of last modification time 0275 * 0276 * @param string $id cache id 0277 * @return array array of metadatas (false if the cache id is not found) 0278 */ 0279 public function getMetadatas($id) 0280 { 0281 $tmp = apc_fetch($id); 0282 if (is_array($tmp)) { 0283 $data = $tmp[0]; 0284 $mtime = $tmp[1]; 0285 if (!isset($tmp[2])) { 0286 // because this record is only with 1.7 release 0287 // if old cache records are still there... 0288 return false; 0289 } 0290 $lifetime = $tmp[2]; 0291 return array( 0292 'expire' => $mtime + $lifetime, 0293 'tags' => array(), 0294 'mtime' => $mtime 0295 ); 0296 } 0297 return false; 0298 } 0299 0300 /** 0301 * Give (if possible) an extra lifetime to the given cache id 0302 * 0303 * @param string $id cache id 0304 * @param int $extraLifetime 0305 * @return boolean true if ok 0306 */ 0307 public function touch($id, $extraLifetime) 0308 { 0309 $tmp = apc_fetch($id); 0310 if (is_array($tmp)) { 0311 $data = $tmp[0]; 0312 $mtime = $tmp[1]; 0313 if (!isset($tmp[2])) { 0314 // because this record is only with 1.7 release 0315 // if old cache records are still there... 0316 return false; 0317 } 0318 $lifetime = $tmp[2]; 0319 $newLifetime = $lifetime - (time() - $mtime) + $extraLifetime; 0320 if ($newLifetime <=0) { 0321 return false; 0322 } 0323 apc_store($id, array($data, time(), $newLifetime), $newLifetime); 0324 return true; 0325 } 0326 return false; 0327 } 0328 0329 /** 0330 * Return an associative array of capabilities (booleans) of the backend 0331 * 0332 * The array must include these keys : 0333 * - automatic_cleaning (is automating cleaning necessary) 0334 * - tags (are tags supported) 0335 * - expired_read (is it possible to read expired cache records 0336 * (for doNotTestCacheValidity option for example)) 0337 * - priority does the backend deal with priority when saving 0338 * - infinite_lifetime (is infinite lifetime can work with this backend) 0339 * - get_list (is it possible to get the list of cache ids and the complete list of tags) 0340 * 0341 * @return array associative of with capabilities 0342 */ 0343 public function getCapabilities() 0344 { 0345 return array( 0346 'automatic_cleaning' => false, 0347 'tags' => false, 0348 'expired_read' => false, 0349 'priority' => false, 0350 'infinite_lifetime' => false, 0351 'get_list' => true 0352 ); 0353 } 0354 0355 }