PageRenderTime 38ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/code/ryzom/tools/server/www/webtt/cake/libs/cache.php

https://bitbucket.org/mattraykowski/ryzomcore_demoshard
PHP | 702 lines | 300 code | 55 blank | 347 comment | 68 complexity | 94593bc56cc228e681e42c42ac80e991 MD5 | raw file
Possible License(s): AGPL-3.0, GPL-3.0, LGPL-2.1
  1. <?php
  2. /**
  3. * Caching for CakePHP.
  4. *
  5. *
  6. * PHP versions 4 and 5
  7. *
  8. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  9. * Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
  10. *
  11. * Licensed under The MIT License
  12. * Redistributions of files must retain the above copyright notice.
  13. *
  14. * @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
  15. * @link http://cakephp.org CakePHP(tm) Project
  16. * @package cake
  17. * @subpackage cake.cake.libs
  18. * @since CakePHP(tm) v 1.2.0.4933
  19. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  20. */
  21. /**
  22. * Caching for CakePHP.
  23. *
  24. * @package cake
  25. * @subpackage cake.cake.libs
  26. */
  27. class Cache {
  28. /**
  29. * Cache configuration stack
  30. * Keeps the permanent/default settings for each cache engine.
  31. * These settings are used to reset the engines after temporary modification.
  32. *
  33. * @var array
  34. * @access private
  35. */
  36. var $__config = array();
  37. /**
  38. * Holds name of the current configuration name being used.
  39. *
  40. * @var array
  41. * @access private
  42. */
  43. var $__name = 'default';
  44. /**
  45. * Whether to reset the settings with the next call to Cache::set();
  46. *
  47. * @var array
  48. * @access private
  49. */
  50. var $__reset = false;
  51. /**
  52. * Engine instances keyed by configuration name.
  53. *
  54. * @var array
  55. */
  56. var $_engines = array();
  57. /**
  58. * Returns a singleton instance
  59. *
  60. * @return object
  61. * @access public
  62. * @static
  63. */
  64. function &getInstance() {
  65. static $instance = array();
  66. if (!$instance) {
  67. $instance[0] =& new Cache();
  68. }
  69. return $instance[0];
  70. }
  71. /**
  72. * Set the cache configuration to use. config() can
  73. * both create new configurations, return the settings for already configured
  74. * configurations. It also sets the 'default' configuration to use for subsequent
  75. * operations.
  76. *
  77. * To create a new configuration:
  78. *
  79. * `Cache::config('my_config', array('engine' => 'File', 'path' => TMP));`
  80. *
  81. * To get the settings for a configuration, and set it as the currently selected configuration
  82. *
  83. * `Cache::config('default');`
  84. *
  85. * The following keys are used in core cache engines:
  86. *
  87. * - `duration` Specify how long items in this cache configuration last.
  88. * - `prefix` Prefix appended to all entries. Good for when you need to share a keyspace
  89. * with either another cache config or annother application.
  90. * - `probability` Probability of hitting a cache gc cleanup. Setting to 0 will disable
  91. * cache::gc from ever being called automatically.
  92. * - `servers' Used by memcache. Give the address of the memcached servers to use.
  93. * - `compress` Used by memcache. Enables memcache's compressed format.
  94. * - `serialize` Used by FileCache. Should cache objects be serialized first.
  95. * - `path` Used by FileCache. Path to where cachefiles should be saved.
  96. * - `lock` Used by FileCache. Should files be locked before writing to them?
  97. * - `user` Used by Xcache. Username for XCache
  98. * - `password` Used by Xcache. Password for XCache
  99. *
  100. * @see app/config/core.php for configuration settings
  101. * @param string $name Name of the configuration
  102. * @param array $settings Optional associative array of settings passed to the engine
  103. * @return array(engine, settings) on success, false on failure
  104. * @access public
  105. * @static
  106. */
  107. function config($name = null, $settings = array()) {
  108. $self =& Cache::getInstance();
  109. if (is_array($name)) {
  110. $settings = $name;
  111. }
  112. if ($name === null || !is_string($name)) {
  113. $name = $self->__name;
  114. }
  115. $current = array();
  116. if (isset($self->__config[$name])) {
  117. $current = $self->__config[$name];
  118. }
  119. if (!empty($settings)) {
  120. $self->__config[$name] = array_merge($current, $settings);
  121. }
  122. if (empty($self->__config[$name]['engine'])) {
  123. return false;
  124. }
  125. $engine = $self->__config[$name]['engine'];
  126. $self->__name = $name;
  127. if (!isset($self->_engines[$name])) {
  128. $self->_buildEngine($name);
  129. $settings = $self->__config[$name] = $self->settings($name);
  130. } elseif ($settings = $self->set($self->__config[$name])) {
  131. $self->__config[$name] = $settings;
  132. }
  133. return compact('engine', 'settings');
  134. }
  135. /**
  136. * Finds and builds the instance of the required engine class.
  137. *
  138. * @param string $name Name of the config array that needs an engine instance built
  139. * @return void
  140. * @access protected
  141. */
  142. function _buildEngine($name) {
  143. $config = $this->__config[$name];
  144. list($plugin, $class) = pluginSplit($config['engine']);
  145. $cacheClass = $class . 'Engine';
  146. if (!class_exists($cacheClass) && $this->__loadEngine($class, $plugin) === false) {
  147. return false;
  148. }
  149. $cacheClass = $class . 'Engine';
  150. $this->_engines[$name] =& new $cacheClass();
  151. if ($this->_engines[$name]->init($config)) {
  152. if ($this->_engines[$name]->settings['probability'] && time() % $this->_engines[$name]->settings['probability'] === 0) {
  153. $this->_engines[$name]->gc();
  154. }
  155. return true;
  156. }
  157. return false;
  158. }
  159. /**
  160. * Returns an array containing the currently configured Cache settings.
  161. *
  162. * @return array Array of configured Cache config names.
  163. */
  164. function configured() {
  165. $self =& Cache::getInstance();
  166. return array_keys($self->__config);
  167. }
  168. /**
  169. * Drops a cache engine. Deletes the cache configuration information
  170. * If the deleted configuration is the last configuration using an certain engine,
  171. * the Engine instance is also unset.
  172. *
  173. * @param string $name A currently configured cache config you wish to remove.
  174. * @return boolen success of the removal, returns false when the config does not exist.
  175. */
  176. function drop($name) {
  177. $self =& Cache::getInstance();
  178. if (!isset($self->__config[$name])) {
  179. return false;
  180. }
  181. unset($self->__config[$name]);
  182. unset($self->_engines[$name]);
  183. return true;
  184. }
  185. /**
  186. * Tries to find and include a file for a cache engine and returns object instance
  187. *
  188. * @param $name Name of the engine (without 'Engine')
  189. * @return mixed $engine object or null
  190. * @access private
  191. */
  192. function __loadEngine($name, $plugin = null) {
  193. if ($plugin) {
  194. return App::import('Lib', $plugin . '.cache' . DS . $name, false);
  195. } else {
  196. $core = App::core();
  197. $path = $core['libs'][0] . 'cache' . DS . strtolower($name) . '.php';
  198. if (file_exists($path)) {
  199. require $path;
  200. return true;
  201. }
  202. return App::import('Lib', 'cache' . DS . $name, false);
  203. }
  204. }
  205. /**
  206. * Temporarily change settings to current config options. if no params are passed, resets settings if needed
  207. * Cache::write() will reset the configuration changes made
  208. *
  209. * @param mixed $settings Optional string for simple name-value pair or array
  210. * @param string $value Optional for a simple name-value pair
  211. * @return array Array of settings.
  212. * @access public
  213. * @static
  214. */
  215. function set($settings = array(), $value = null) {
  216. $self =& Cache::getInstance();
  217. if (!isset($self->__config[$self->__name]) || !isset($self->_engines[$self->__name])) {
  218. return false;
  219. }
  220. $name = $self->__name;
  221. if (!empty($settings)) {
  222. $self->__reset = true;
  223. }
  224. if ($self->__reset === true) {
  225. if (empty($settings)) {
  226. $self->__reset = false;
  227. $settings = $self->__config[$name];
  228. } else {
  229. if (is_string($settings) && $value !== null) {
  230. $settings = array($settings => $value);
  231. }
  232. $settings = array_merge($self->__config[$name], $settings);
  233. if (isset($settings['duration']) && !is_numeric($settings['duration'])) {
  234. $settings['duration'] = strtotime($settings['duration']) - time();
  235. }
  236. }
  237. $self->_engines[$name]->settings = $settings;
  238. }
  239. return $self->settings($name);
  240. }
  241. /**
  242. * Garbage collection
  243. *
  244. * Permanently remove all expired and deleted data
  245. *
  246. * @return void
  247. * @access public
  248. * @static
  249. */
  250. function gc() {
  251. $self =& Cache::getInstance();
  252. $self->_engines[$self->__name]->gc();
  253. }
  254. /**
  255. * Write data for key into cache. Will automatically use the currently
  256. * active cache configuration. To set the currently active configuration use
  257. * Cache::config()
  258. *
  259. * ### Usage:
  260. *
  261. * Writing to the active cache config:
  262. *
  263. * `Cache::write('cached_data', $data);`
  264. *
  265. * Writing to a specific cache config:
  266. *
  267. * `Cache::write('cached_data', $data, 'long_term');`
  268. *
  269. * @param string $key Identifier for the data
  270. * @param mixed $value Data to be cached - anything except a resource
  271. * @param string $config Optional string configuration name to write to.
  272. * @return boolean True if the data was successfully cached, false on failure
  273. * @access public
  274. * @static
  275. */
  276. function write($key, $value, $config = null) {
  277. $self =& Cache::getInstance();
  278. if (!$config) {
  279. $config = $self->__name;
  280. }
  281. $settings = $self->settings($config);
  282. if (empty($settings)) {
  283. return null;
  284. }
  285. if (!$self->isInitialized($config)) {
  286. return false;
  287. }
  288. $key = $self->_engines[$config]->key($key);
  289. if (!$key || is_resource($value)) {
  290. return false;
  291. }
  292. $success = $self->_engines[$config]->write($settings['prefix'] . $key, $value, $settings['duration']);
  293. $self->set();
  294. return $success;
  295. }
  296. /**
  297. * Read a key from the cache. Will automatically use the currently
  298. * active cache configuration. To set the currently active configuration use
  299. * Cache::config()
  300. *
  301. * ### Usage:
  302. *
  303. * Reading from the active cache configuration.
  304. *
  305. * `Cache::read('my_data');`
  306. *
  307. * Reading from a specific cache configuration.
  308. *
  309. * `Cache::read('my_data', 'long_term');`
  310. *
  311. * @param string $key Identifier for the data
  312. * @param string $config optional name of the configuration to use.
  313. * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it
  314. * @access public
  315. * @static
  316. */
  317. function read($key, $config = null) {
  318. $self =& Cache::getInstance();
  319. if (!$config) {
  320. $config = $self->__name;
  321. }
  322. $settings = $self->settings($config);
  323. if (empty($settings)) {
  324. return null;
  325. }
  326. if (!$self->isInitialized($config)) {
  327. return false;
  328. }
  329. $key = $self->_engines[$config]->key($key);
  330. if (!$key) {
  331. return false;
  332. }
  333. $success = $self->_engines[$config]->read($settings['prefix'] . $key);
  334. if ($config !== null && $config !== $self->__name) {
  335. $self->set();
  336. }
  337. return $success;
  338. }
  339. /**
  340. * Increment a number under the key and return incremented value.
  341. *
  342. * @param string $key Identifier for the data
  343. * @param integer $offset How much to add
  344. * @param string $config Optional string configuration name. If not specified the current
  345. * default config will be used.
  346. * @return mixed new value, or false if the data doesn't exist, is not integer,
  347. * or if there was an error fetching it.
  348. * @access public
  349. */
  350. function increment($key, $offset = 1, $config = null) {
  351. $self =& Cache::getInstance();
  352. if (!$config) {
  353. $config = $self->__name;
  354. }
  355. $settings = $self->settings($config);
  356. if (empty($settings)) {
  357. return null;
  358. }
  359. if (!$self->isInitialized($config)) {
  360. return false;
  361. }
  362. $key = $self->_engines[$config]->key($key);
  363. if (!$key || !is_integer($offset) || $offset < 0) {
  364. return false;
  365. }
  366. $success = $self->_engines[$config]->increment($settings['prefix'] . $key, $offset);
  367. $self->set();
  368. return $success;
  369. }
  370. /**
  371. * Decrement a number under the key and return decremented value.
  372. *
  373. * @param string $key Identifier for the data
  374. * @param integer $offset How much to substract
  375. * @param string $config Optional string configuration name, if not specified the current
  376. * default config will be used.
  377. * @return mixed new value, or false if the data doesn't exist, is not integer,
  378. * or if there was an error fetching it
  379. * @access public
  380. */
  381. function decrement($key, $offset = 1, $config = null) {
  382. $self =& Cache::getInstance();
  383. if (!$config) {
  384. $config = $self->__name;
  385. }
  386. $settings = $self->settings($config);
  387. if (empty($settings)) {
  388. return null;
  389. }
  390. if (!$self->isInitialized($config)) {
  391. return false;
  392. }
  393. $key = $self->_engines[$config]->key($key);
  394. if (!$key || !is_integer($offset) || $offset < 0) {
  395. return false;
  396. }
  397. $success = $self->_engines[$config]->decrement($settings['prefix'] . $key, $offset);
  398. $self->set();
  399. return $success;
  400. }
  401. /**
  402. * Delete a key from the cache. Will automatically use the currently
  403. * active cache configuration. To set the currently active configuration use
  404. * Cache::config()
  405. *
  406. * ### Usage:
  407. *
  408. * Deleting from the active cache configuration.
  409. *
  410. * `Cache::delete('my_data');`
  411. *
  412. * Deleting from a specific cache configuration.
  413. *
  414. * `Cache::delete('my_data', 'long_term');`
  415. *
  416. * @param string $key Identifier for the data
  417. * @param string $config name of the configuration to use
  418. * @return boolean True if the value was succesfully deleted, false if it didn't exist or couldn't be removed
  419. * @access public
  420. * @static
  421. */
  422. function delete($key, $config = null) {
  423. $self =& Cache::getInstance();
  424. if (!$config) {
  425. $config = $self->__name;
  426. }
  427. $settings = $self->settings($config);
  428. if (empty($settings)) {
  429. return null;
  430. }
  431. if (!$self->isInitialized($config)) {
  432. return false;
  433. }
  434. $key = $self->_engines[$config]->key($key);
  435. if (!$key) {
  436. return false;
  437. }
  438. $success = $self->_engines[$config]->delete($settings['prefix'] . $key);
  439. $self->set();
  440. return $success;
  441. }
  442. /**
  443. * Delete all keys from the cache.
  444. *
  445. * @param boolean $check if true will check expiration, otherwise delete all
  446. * @param string $config name of the configuration to use
  447. * @return boolean True if the cache was succesfully cleared, false otherwise
  448. * @access public
  449. * @static
  450. */
  451. function clear($check = false, $config = null) {
  452. $self =& Cache::getInstance();
  453. if (!$config) {
  454. $config = $self->__name;
  455. }
  456. $settings = $self->settings($config);
  457. if (empty($settings)) {
  458. return null;
  459. }
  460. if (!$self->isInitialized($config)) {
  461. return false;
  462. }
  463. $success = $self->_engines[$config]->clear($check);
  464. $self->set();
  465. return $success;
  466. }
  467. /**
  468. * Check if Cache has initialized a working config for the given name.
  469. *
  470. * @param string $engine Name of the engine
  471. * @param string $config Name of the configuration setting
  472. * @return bool Whether or not the config name has been initialized.
  473. * @access public
  474. * @static
  475. */
  476. function isInitialized($name = null) {
  477. if (Configure::read('Cache.disable')) {
  478. return false;
  479. }
  480. $self =& Cache::getInstance();
  481. if (!$name && isset($self->__config[$self->__name])) {
  482. $name = $self->__name;
  483. }
  484. return isset($self->_engines[$name]);
  485. }
  486. /**
  487. * Return the settings for current cache engine. If no name is supplied the settings
  488. * for the 'active default' configuration will be returned. To set the 'active default'
  489. * configuration use `Cache::config()`
  490. *
  491. * @param string $engine Name of the configuration to get settings for.
  492. * @return array list of settings for this engine
  493. * @see Cache::config()
  494. * @access public
  495. * @static
  496. */
  497. function settings($name = null) {
  498. $self =& Cache::getInstance();
  499. if (!$name && isset($self->__config[$self->__name])) {
  500. $name = $self->__name;
  501. }
  502. if (!empty($self->_engines[$name])) {
  503. return $self->_engines[$name]->settings();
  504. }
  505. return array();
  506. }
  507. /**
  508. * Write the session when session data is persisted with cache.
  509. *
  510. * @return void
  511. * @access public
  512. */
  513. function __destruct() {
  514. if (Configure::read('Session.save') == 'cache' && function_exists('session_write_close')) {
  515. session_write_close();
  516. }
  517. }
  518. }
  519. /**
  520. * Storage engine for CakePHP caching
  521. *
  522. * @package cake
  523. * @subpackage cake.cake.libs
  524. */
  525. class CacheEngine {
  526. /**
  527. * Settings of current engine instance
  528. *
  529. * @var int
  530. * @access public
  531. */
  532. var $settings = array();
  533. /**
  534. * Initialize the cache engine
  535. *
  536. * Called automatically by the cache frontend
  537. *
  538. * @param array $params Associative array of parameters for the engine
  539. * @return boolean True if the engine has been succesfully initialized, false if not
  540. * @access public
  541. */
  542. function init($settings = array()) {
  543. $this->settings = array_merge(
  544. array('prefix' => 'cake_', 'duration'=> 3600, 'probability'=> 100),
  545. $this->settings,
  546. $settings
  547. );
  548. if (!is_numeric($this->settings['duration'])) {
  549. $this->settings['duration'] = strtotime($this->settings['duration']) - time();
  550. }
  551. return true;
  552. }
  553. /**
  554. * Garbage collection
  555. *
  556. * Permanently remove all expired and deleted data
  557. *
  558. * @access public
  559. */
  560. function gc() {
  561. }
  562. /**
  563. * Write value for a key into cache
  564. *
  565. * @param string $key Identifier for the data
  566. * @param mixed $value Data to be cached
  567. * @param mixed $duration How long to cache the data, in seconds
  568. * @return boolean True if the data was succesfully cached, false on failure
  569. * @access public
  570. */
  571. function write($key, &$value, $duration) {
  572. trigger_error(sprintf(__('Method write() not implemented in %s', true), get_class($this)), E_USER_ERROR);
  573. }
  574. /**
  575. * Read a key from the cache
  576. *
  577. * @param string $key Identifier for the data
  578. * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it
  579. * @access public
  580. */
  581. function read($key) {
  582. trigger_error(sprintf(__('Method read() not implemented in %s', true), get_class($this)), E_USER_ERROR);
  583. }
  584. /**
  585. * Increment a number under the key and return incremented value
  586. *
  587. * @param string $key Identifier for the data
  588. * @param integer $offset How much to add
  589. * @return New incremented value, false otherwise
  590. * @access public
  591. */
  592. function increment($key, $offset = 1) {
  593. trigger_error(sprintf(__('Method increment() not implemented in %s', true), get_class($this)), E_USER_ERROR);
  594. }
  595. /**
  596. * Decrement a number under the key and return decremented value
  597. *
  598. * @param string $key Identifier for the data
  599. * @param integer $value How much to substract
  600. * @return New incremented value, false otherwise
  601. * @access public
  602. */
  603. function decrement($key, $offset = 1) {
  604. trigger_error(sprintf(__('Method decrement() not implemented in %s', true), get_class($this)), E_USER_ERROR);
  605. }
  606. /**
  607. * Delete a key from the cache
  608. *
  609. * @param string $key Identifier for the data
  610. * @return boolean True if the value was succesfully deleted, false if it didn't exist or couldn't be removed
  611. * @access public
  612. */
  613. function delete($key) {
  614. }
  615. /**
  616. * Delete all keys from the cache
  617. *
  618. * @param boolean $check if true will check expiration, otherwise delete all
  619. * @return boolean True if the cache was succesfully cleared, false otherwise
  620. * @access public
  621. */
  622. function clear($check) {
  623. }
  624. /**
  625. * Cache Engine settings
  626. *
  627. * @return array settings
  628. * @access public
  629. */
  630. function settings() {
  631. return $this->settings;
  632. }
  633. /**
  634. * Generates a safe key for use with cache engine storage engines.
  635. *
  636. * @param string $key the key passed over
  637. * @return mixed string $key or false
  638. * @access public
  639. */
  640. function key($key) {
  641. if (empty($key)) {
  642. return false;
  643. }
  644. $key = Inflector::underscore(str_replace(array(DS, '/', '.'), '_', strval($key)));
  645. return $key;
  646. }
  647. }