Apc.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Cache
  17. * @subpackage Zend_Cache_Backend
  18. * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. */
  21. /**
  22. * @see Zend_Cache_Backend_Interface
  23. */
  24. require_once 'Zend/Cache/Backend/ExtendedInterface.php';
  25. /**
  26. * @see Zend_Cache_Backend
  27. */
  28. require_once 'Zend/Cache/Backend.php';
  29. /**
  30. * @package Zend_Cache
  31. * @subpackage Zend_Cache_Backend
  32. * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  33. * @license http://framework.zend.com/license/new-bsd New BSD License
  34. */
  35. class Zend_Cache_Backend_Apc extends Zend_Cache_Backend implements Zend_Cache_Backend_ExtendedInterface
  36. {
  37. /**
  38. * Log message
  39. */
  40. const TAGS_UNSUPPORTED_BY_CLEAN_OF_APC_BACKEND = 'Zend_Cache_Backend_Apc::clean() : tags are unsupported by the Apc backend';
  41. const TAGS_UNSUPPORTED_BY_SAVE_OF_APC_BACKEND = 'Zend_Cache_Backend_Apc::save() : tags are unsupported by the Apc backend';
  42. /**
  43. * Constructor
  44. *
  45. * @param array $options associative array of options
  46. * @throws Zend_Cache_Exception
  47. * @return void
  48. */
  49. public function __construct(array $options = array())
  50. {
  51. if (!extension_loaded('apc')) {
  52. Zend_Cache::throwException('The apc extension must be loaded for using this backend !');
  53. }
  54. parent::__construct($options);
  55. }
  56. /**
  57. * Test if a cache is available for the given id and (if yes) return it (false else)
  58. *
  59. * WARNING $doNotTestCacheValidity=true is unsupported by the Apc backend
  60. *
  61. * @param string $id cache id
  62. * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested
  63. * @return string cached datas (or false)
  64. */
  65. public function load($id, $doNotTestCacheValidity = false)
  66. {
  67. $tmp = apc_fetch($id);
  68. if (is_array($tmp)) {
  69. return $tmp[0];
  70. }
  71. return false;
  72. }
  73. /**
  74. * Test if a cache is available or not (for the given id)
  75. *
  76. * @param string $id cache id
  77. * @return mixed false (a cache is not available) or "last modified" timestamp (int) of the available cache record
  78. */
  79. public function test($id)
  80. {
  81. $tmp = apc_fetch($id);
  82. if (is_array($tmp)) {
  83. return $tmp[1];
  84. }
  85. return false;
  86. }
  87. /**
  88. * Save some string datas into a cache record
  89. *
  90. * Note : $data is always "string" (serialization is done by the
  91. * core not by the backend)
  92. *
  93. * @param string $data datas to cache
  94. * @param string $id cache id
  95. * @param array $tags array of strings, the cache record will be tagged by each string entry
  96. * @param int $specificLifetime if != false, set a specific lifetime for this cache record (null => infinite lifetime)
  97. * @return boolean true if no problem
  98. */
  99. public function save($data, $id, $tags = array(), $specificLifetime = false)
  100. {
  101. $lifetime = $this->getLifetime($specificLifetime);
  102. $result = apc_store($id, array($data, time(), $lifetime), $lifetime);
  103. if (count($tags) > 0) {
  104. $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_APC_BACKEND);
  105. }
  106. return $result;
  107. }
  108. /**
  109. * Remove a cache record
  110. *
  111. * @param string $id cache id
  112. * @return boolean true if no problem
  113. */
  114. public function remove($id)
  115. {
  116. return apc_delete($id);
  117. }
  118. /**
  119. * Clean some cache records
  120. *
  121. * Available modes are :
  122. * 'all' (default) => remove all cache entries ($tags is not used)
  123. * 'old' => unsupported
  124. * 'matchingTag' => unsupported
  125. * 'notMatchingTag' => unsupported
  126. * 'matchingAnyTag' => unsupported
  127. *
  128. * @param string $mode clean mode
  129. * @param array $tags array of tags
  130. * @throws Zend_Cache_Exception
  131. * @return boolean true if no problem
  132. */
  133. public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
  134. {
  135. switch ($mode) {
  136. case Zend_Cache::CLEANING_MODE_ALL:
  137. return apc_clear_cache('user');
  138. break;
  139. case Zend_Cache::CLEANING_MODE_OLD:
  140. $this->_log("Zend_Cache_Backend_Apc::clean() : CLEANING_MODE_OLD is unsupported by the Apc backend");
  141. break;
  142. case Zend_Cache::CLEANING_MODE_MATCHING_TAG:
  143. case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG:
  144. case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG:
  145. $this->_log(self::TAGS_UNSUPPORTED_BY_CLEAN_OF_APC_BACKEND);
  146. break;
  147. default:
  148. Zend_Cache::throwException('Invalid mode for clean() method');
  149. break;
  150. }
  151. }
  152. /**
  153. * Return true if the automatic cleaning is available for the backend
  154. *
  155. * DEPRECATED : use getCapabilities() instead
  156. *
  157. * @deprecated
  158. * @return boolean
  159. */
  160. public function isAutomaticCleaningAvailable()
  161. {
  162. return false;
  163. }
  164. /**
  165. * Return the filling percentage of the backend storage
  166. *
  167. * @throws Zend_Cache_Exception
  168. * @return int integer between 0 and 100
  169. */
  170. public function getFillingPercentage()
  171. {
  172. $mem = apc_sma_info(true);
  173. $memSize = $mem['num_seg'] * $mem['seg_size'];
  174. $memAvailable= $mem['avail_mem'];
  175. $memUsed = $memSize - $memAvailable;
  176. if ($memSize == 0) {
  177. Zend_Cache::throwException('can\'t get apc memory size');
  178. }
  179. if ($memUsed > $memSize) {
  180. return 100;
  181. }
  182. return ((int) (100. * ($memUsed / $memSize)));
  183. }
  184. /**
  185. * Return an array of stored tags
  186. *
  187. * @return array array of stored tags (string)
  188. */
  189. public function getTags()
  190. {
  191. $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_APC_BACKEND);
  192. return array();
  193. }
  194. /**
  195. * Return an array of stored cache ids which match given tags
  196. *
  197. * In case of multiple tags, a logical AND is made between tags
  198. *
  199. * @param array $tags array of tags
  200. * @return array array of matching cache ids (string)
  201. */
  202. public function getIdsMatchingTags($tags = array())
  203. {
  204. $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_APC_BACKEND);
  205. return array();
  206. }
  207. /**
  208. * Return an array of stored cache ids which don't match given tags
  209. *
  210. * In case of multiple tags, a logical OR is made between tags
  211. *
  212. * @param array $tags array of tags
  213. * @return array array of not matching cache ids (string)
  214. */
  215. public function getIdsNotMatchingTags($tags = array())
  216. {
  217. $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_APC_BACKEND);
  218. return array();
  219. }
  220. /**
  221. * Return an array of stored cache ids which match any given tags
  222. *
  223. * In case of multiple tags, a logical AND is made between tags
  224. *
  225. * @param array $tags array of tags
  226. * @return array array of any matching cache ids (string)
  227. */
  228. public function getIdsMatchingAnyTags($tags = array())
  229. {
  230. $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_APC_BACKEND);
  231. return array();
  232. }
  233. /**
  234. * Return an array of stored cache ids
  235. *
  236. * @return array array of stored cache ids (string)
  237. */
  238. public function getIds()
  239. {
  240. $res = array();
  241. $array = apc_cache_info('user', false);
  242. $records = $array['cache_list'];
  243. foreach ($records as $record) {
  244. $res[] = $record['info'];
  245. }
  246. return $res;
  247. }
  248. /**
  249. * Return an array of metadatas for the given cache id
  250. *
  251. * The array must include these keys :
  252. * - expire : the expire timestamp
  253. * - tags : a string array of tags
  254. * - mtime : timestamp of last modification time
  255. *
  256. * @param string $id cache id
  257. * @return array array of metadatas (false if the cache id is not found)
  258. */
  259. public function getMetadatas($id)
  260. {
  261. $tmp = apc_fetch($id);
  262. if (is_array($tmp)) {
  263. $data = $tmp[0];
  264. $mtime = $tmp[1];
  265. if (!isset($tmp[2])) {
  266. // because this record is only with 1.7 release
  267. // if old cache records are still there...
  268. return false;
  269. }
  270. $lifetime = $tmp[2];
  271. return array(
  272. 'expire' => $mtime + $lifetime,
  273. 'tags' => array(),
  274. 'mtime' => $mtime
  275. );
  276. }
  277. return false;
  278. }
  279. /**
  280. * Give (if possible) an extra lifetime to the given cache id
  281. *
  282. * @param string $id cache id
  283. * @param int $extraLifetime
  284. * @return boolean true if ok
  285. */
  286. public function touch($id, $extraLifetime)
  287. {
  288. $tmp = apc_fetch($id);
  289. if (is_array($tmp)) {
  290. $data = $tmp[0];
  291. $mtime = $tmp[1];
  292. if (!isset($tmp[2])) {
  293. // because this record is only with 1.7 release
  294. // if old cache records are still there...
  295. return false;
  296. }
  297. $lifetime = $tmp[2];
  298. $newLifetime = $lifetime - (time() - $mtime) + $extraLifetime;
  299. if ($newLifetime <=0) {
  300. return false;
  301. }
  302. apc_store($id, array($data, time(), $newLifetime), $newLifetime);
  303. return true;
  304. }
  305. return false;
  306. }
  307. /**
  308. * Return an associative array of capabilities (booleans) of the backend
  309. *
  310. * The array must include these keys :
  311. * - automatic_cleaning (is automating cleaning necessary)
  312. * - tags (are tags supported)
  313. * - expired_read (is it possible to read expired cache records
  314. * (for doNotTestCacheValidity option for example))
  315. * - priority does the backend deal with priority when saving
  316. * - infinite_lifetime (is infinite lifetime can work with this backend)
  317. * - get_list (is it possible to get the list of cache ids and the complete list of tags)
  318. *
  319. * @return array associative of with capabilities
  320. */
  321. public function getCapabilities()
  322. {
  323. return array(
  324. 'automatic_cleaning' => false,
  325. 'tags' => false,
  326. 'expired_read' => false,
  327. 'priority' => false,
  328. 'infinite_lifetime' => false,
  329. 'get_list' => true
  330. );
  331. }
  332. }