XcacheEngine.php 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  11. * @link http://cakephp.org CakePHP(tm) Project
  12. * @since 1.2.0
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Cache\Engine;
  16. use Cake\Cache\CacheEngine;
  17. /**
  18. * Xcache storage engine for cache
  19. *
  20. * @link http://trac.lighttpd.net/xcache/ Xcache
  21. */
  22. class XcacheEngine extends CacheEngine {
  23. /**
  24. * The default config used unless overriden by runtime configuration
  25. *
  26. * - `duration` Specify how long items in this cache configuration last.
  27. * - `groups` List of groups or 'tags' associated to every key stored in this config.
  28. * handy for deleting a complete group from cache.
  29. * - `prefix` Prefix appended to all entries. Good for when you need to share a keyspace
  30. * with either another cache config or another application.
  31. * - `probability` Probability of hitting a cache gc cleanup. Setting to 0 will disable
  32. * cache::gc from ever being called automatically.
  33. * - `PHP_AUTH_USER` xcache.admin.user
  34. * - `PHP_AUTH_PW` xcache.admin.password
  35. *
  36. * @var array
  37. */
  38. protected $_defaultConfig = [
  39. 'duration' => 3600,
  40. 'groups' => [],
  41. 'prefix' => null,
  42. 'probability' => 100,
  43. 'PHP_AUTH_USER' => 'user',
  44. 'PHP_AUTH_PW' => 'password'
  45. ];
  46. /**
  47. * Initialize the Cache Engine
  48. *
  49. * Called automatically by the cache frontend
  50. *
  51. * @param array $config array of setting for the engine
  52. * @return bool True if the engine has been successfully initialized, false if not
  53. */
  54. public function init(array $config = []) {
  55. if (php_sapi_name() !== 'cli') {
  56. parent::init($config);
  57. return function_exists('xcache_info');
  58. }
  59. return false;
  60. }
  61. /**
  62. * Write data for key into cache
  63. *
  64. * @param string $key Identifier for the data
  65. * @param mixed $value Data to be cached
  66. * @return bool True if the data was successfully cached, false on failure
  67. */
  68. public function write($key, $value) {
  69. $key = $this->_key($key);
  70. $duration = $this->_config['duration'];
  71. $expires = time() + $duration;
  72. xcache_set($key . '_expires', $expires, $duration);
  73. return xcache_set($key, $value, $duration);
  74. }
  75. /**
  76. * Read a key from the cache
  77. *
  78. * @param string $key Identifier for the data
  79. * @return mixed The cached data, or false if the data doesn't exist,
  80. * has expired, or if there was an error fetching it
  81. */
  82. public function read($key) {
  83. $key = $this->_key($key);
  84. if (xcache_isset($key)) {
  85. $time = time();
  86. $cachetime = (int)xcache_get($key . '_expires');
  87. if ($cachetime < $time || ($time + $this->_config['duration']) < $cachetime) {
  88. return false;
  89. }
  90. return xcache_get($key);
  91. }
  92. return false;
  93. }
  94. /**
  95. * Increments the value of an integer cached key
  96. * If the cache key is not an integer it will be treated as 0
  97. *
  98. * @param string $key Identifier for the data
  99. * @param int $offset How much to increment
  100. * @return bool|int New incremented value, false otherwise
  101. */
  102. public function increment($key, $offset = 1) {
  103. $key = $this->_key($key);
  104. return xcache_inc($key, $offset);
  105. }
  106. /**
  107. * Decrements the value of an integer cached key.
  108. * If the cache key is not an integer it will be treated as 0
  109. *
  110. * @param string $key Identifier for the data
  111. * @param int $offset How much to subtract
  112. * @return bool|int New decremented value, false otherwise
  113. */
  114. public function decrement($key, $offset = 1) {
  115. $key = $this->_key($key);
  116. return xcache_dec($key, $offset);
  117. }
  118. /**
  119. * Delete a key from the cache
  120. *
  121. * @param string $key Identifier for the data
  122. * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
  123. */
  124. public function delete($key) {
  125. $key = $this->_key($key);
  126. return xcache_unset($key);
  127. }
  128. /**
  129. * Delete all keys from the cache
  130. *
  131. * @param bool $check If true no deletes will occur and instead CakePHP will rely
  132. * on key TTL values.
  133. * Unused for Xcache engine.
  134. * @return bool True if the cache was successfully cleared, false otherwise
  135. */
  136. public function clear($check) {
  137. $this->_auth();
  138. $max = xcache_count(XC_TYPE_VAR);
  139. for ($i = 0; $i < $max; $i++) {
  140. xcache_clear_cache(XC_TYPE_VAR, $i);
  141. }
  142. $this->_auth(true);
  143. return true;
  144. }
  145. /**
  146. * Returns the `group value` for each of the configured groups
  147. * If the group initial value was not found, then it initializes
  148. * the group accordingly.
  149. *
  150. * @return array
  151. */
  152. public function groups() {
  153. $result = [];
  154. foreach ($this->_config['groups'] as $group) {
  155. $value = xcache_get($this->_config['prefix'] . $group);
  156. if (!$value) {
  157. $value = 1;
  158. xcache_set($this->_config['prefix'] . $group, $value, 0);
  159. }
  160. $result[] = $group . $value;
  161. }
  162. return $result;
  163. }
  164. /**
  165. * Increments the group value to simulate deletion of all keys under a group
  166. * old values will remain in storage until they expire.
  167. *
  168. * @param string $group The group to clear.
  169. * @return bool success
  170. */
  171. public function clearGroup($group) {
  172. return (bool)xcache_inc($this->_config['prefix'] . $group, 1);
  173. }
  174. /**
  175. * Populates and reverses $_SERVER authentication values
  176. * Makes necessary changes (and reverting them back) in $_SERVER
  177. *
  178. * This has to be done because xcache_clear_cache() needs to pass Basic Http Auth
  179. * (see xcache.admin configuration config)
  180. *
  181. * @param bool $reverse Revert changes
  182. * @return void
  183. */
  184. protected function _auth($reverse = false) {
  185. static $backup = [];
  186. $keys = ['PHP_AUTH_USER' => 'user', 'PHP_AUTH_PW' => 'password'];
  187. foreach ($keys as $key => $value) {
  188. if ($reverse) {
  189. if (isset($backup[$key])) {
  190. $_SERVER[$key] = $backup[$key];
  191. unset($backup[$key]);
  192. } else {
  193. unset($_SERVER[$key]);
  194. }
  195. } else {
  196. $value = env($key);
  197. if (!empty($value)) {
  198. $backup[$key] = $value;
  199. }
  200. if (!empty($this->_config[$value])) {
  201. $_SERVER[$key] = $this->_config[$value];
  202. } elseif (!empty($this->_config[$key])) {
  203. $_SERVER[$key] = $this->_config[$key];
  204. } else {
  205. $_SERVER[$key] = $value;
  206. }
  207. }
  208. }
  209. }
  210. }