MemcacheEngine.php 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. <?php
  2. /**
  3. * Memcache storage engine for cache
  4. *
  5. *
  6. * PHP 5
  7. *
  8. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  9. * Copyright 2005-2011, 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-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
  15. * @link http://cakephp.org CakePHP(tm) Project
  16. * @package Cake.Cache.Engine
  17. * @since CakePHP(tm) v 1.2.0.4933
  18. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  19. */
  20. /**
  21. * Memcache storage engine for cache. Memcache has some limitations in the amount of
  22. * control you have over expire times far in the future. See MemcacheEngine::write() for
  23. * more information.
  24. *
  25. * @package Cake.Cache.Engine
  26. */
  27. class MemcacheEngine extends CacheEngine {
  28. /**
  29. * Memcache wrapper.
  30. *
  31. * @var Memcache
  32. */
  33. protected $_Memcache = null;
  34. /**
  35. * Settings
  36. *
  37. * - servers = string or array of memcache servers, default => 127.0.0.1. If an
  38. * array MemcacheEngine will use them as a pool.
  39. * - compress = boolean, default => false
  40. *
  41. * @var array
  42. */
  43. public $settings = array();
  44. /**
  45. * Initialize the Cache Engine
  46. *
  47. * Called automatically by the cache frontend
  48. * To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array());
  49. *
  50. * @param array $settings array of setting for the engine
  51. * @return boolean True if the engine has been successfully initialized, false if not
  52. */
  53. public function init($settings = array()) {
  54. if (!class_exists('Memcache')) {
  55. return false;
  56. }
  57. parent::init(array_merge(array(
  58. 'engine' => 'Memcache',
  59. 'prefix' => Inflector::slug(APP_DIR) . '_',
  60. 'servers' => array('127.0.0.1'),
  61. 'compress' => false,
  62. 'persistent' => true
  63. ), $settings)
  64. );
  65. if ($this->settings['compress']) {
  66. $this->settings['compress'] = MEMCACHE_COMPRESSED;
  67. }
  68. if (!is_array($this->settings['servers'])) {
  69. $this->settings['servers'] = array($this->settings['servers']);
  70. }
  71. if (!isset($this->_Memcache)) {
  72. $return = false;
  73. $this->_Memcache = new Memcache();
  74. foreach ($this->settings['servers'] as $server) {
  75. list($host, $port) = $this->_parseServerString($server);
  76. if ($this->_Memcache->addServer($host, $port, $this->settings['persistent'])) {
  77. $return = true;
  78. }
  79. }
  80. return $return;
  81. }
  82. return true;
  83. }
  84. /**
  85. * Parses the server address into the host/port. Handles both IPv6 and IPv4
  86. * addresses and Unix sockets
  87. *
  88. * @param string $server The server address string.
  89. * @return array Array containing host, port
  90. */
  91. protected function _parseServerString($server) {
  92. if ($server[0] == 'u') {
  93. return array($server, 0);
  94. }
  95. if (substr($server, 0, 1) == '[') {
  96. $position = strpos($server, ']:');
  97. if ($position !== false) {
  98. $position++;
  99. }
  100. } else {
  101. $position = strpos($server, ':');
  102. }
  103. $port = 11211;
  104. $host = $server;
  105. if ($position !== false) {
  106. $host = substr($server, 0, $position);
  107. $port = substr($server, $position + 1);
  108. }
  109. return array($host, $port);
  110. }
  111. /**
  112. * Write data for key into cache. When using memcache as your cache engine
  113. * remember that the Memcache pecl extension does not support cache expiry times greater
  114. * than 30 days in the future. Any duration greater than 30 days will be treated as never expiring.
  115. *
  116. * @param string $key Identifier for the data
  117. * @param mixed $value Data to be cached
  118. * @param integer $duration How long to cache the data, in seconds
  119. * @return boolean True if the data was successfully cached, false on failure
  120. * @see http://php.net/manual/en/memcache.set.php
  121. */
  122. public function write($key, $value, $duration) {
  123. if ($duration > 30 * DAY) {
  124. $duration = 0;
  125. }
  126. return $this->_Memcache->set($key, $value, $this->settings['compress'], $duration);
  127. }
  128. /**
  129. * Read a key from the cache
  130. *
  131. * @param string $key Identifier for the data
  132. * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it
  133. */
  134. public function read($key) {
  135. return $this->_Memcache->get($key);
  136. }
  137. /**
  138. * Increments the value of an integer cached key
  139. *
  140. * @param string $key Identifier for the data
  141. * @param integer $offset How much to increment
  142. * @return New incremented value, false otherwise
  143. * @throws CacheException when you try to increment with compress = true
  144. */
  145. public function increment($key, $offset = 1) {
  146. if ($this->settings['compress']) {
  147. throw new CacheException(
  148. __d('cake_dev', 'Method increment() not implemented for compressed cache in %s', __CLASS__)
  149. );
  150. }
  151. return $this->_Memcache->increment($key, $offset);
  152. }
  153. /**
  154. * Decrements the value of an integer cached key
  155. *
  156. * @param string $key Identifier for the data
  157. * @param integer $offset How much to subtract
  158. * @return New decremented value, false otherwise
  159. * @throws CacheException when you try to decrement with compress = true
  160. */
  161. public function decrement($key, $offset = 1) {
  162. if ($this->settings['compress']) {
  163. throw new CacheException(
  164. __d('cake_dev', 'Method decrement() not implemented for compressed cache in %s', __CLASS__)
  165. );
  166. }
  167. return $this->_Memcache->decrement($key, $offset);
  168. }
  169. /**
  170. * Delete a key from the cache
  171. *
  172. * @param string $key Identifier for the data
  173. * @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed
  174. */
  175. public function delete($key) {
  176. return $this->_Memcache->delete($key);
  177. }
  178. /**
  179. * Delete all keys from the cache
  180. *
  181. * @param boolean $check
  182. * @return boolean True if the cache was successfully cleared, false otherwise
  183. */
  184. public function clear($check) {
  185. if ($check) {
  186. return true;
  187. }
  188. foreach ($this->_Memcache->getExtendedStats('slabs') as $slabs) {
  189. foreach (array_keys($slabs) as $slabId) {
  190. if (!is_numeric($slabId)) {
  191. continue;
  192. }
  193. foreach ($this->_Memcache->getExtendedStats('cachedump', $slabId) as $stats) {
  194. if (!is_array($stats)) {
  195. continue;
  196. }
  197. foreach (array_keys($stats) as $key) {
  198. if (strpos($key, $this->settings['prefix']) === 0) {
  199. $this->_Memcache->delete($key);
  200. }
  201. }
  202. }
  203. }
  204. }
  205. return true;
  206. }
  207. /**
  208. * Connects to a server in connection pool
  209. *
  210. * @param string $host host ip address or name
  211. * @param integer $port Server port
  212. * @return boolean True if memcache server was connected
  213. */
  214. public function connect($host, $port = 11211) {
  215. if ($this->_Memcache->getServerStatus($host, $port) === 0) {
  216. if ($this->_Memcache->connect($host, $port)) {
  217. return true;
  218. }
  219. return false;
  220. }
  221. return true;
  222. }
  223. }