pictcode / lib / Cake / Cache / Engine / MemcacheEngine.php @ 6e557b3d
履歴 | 表示 | アノテート | ダウンロード (8.129 KB)
| 1 | 635eef61 | spyder1211 | <?php
 | 
      
|---|---|---|---|
| 2 | /**
 | 
      ||
| 3 |  * Memcache storage engine for cache
 | 
      ||
| 4 |  *
 | 
      ||
| 5 |  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
 | 
      ||
| 6 |  * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 | 
      ||
| 7 |  *
 | 
      ||
| 8 |  * Licensed under The MIT License
 | 
      ||
| 9 |  * For full copyright and license information, please see the LICENSE.txt
 | 
      ||
| 10 |  * Redistributions of files must retain the above copyright notice.
 | 
      ||
| 11 |  *
 | 
      ||
| 12 |  * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 | 
      ||
| 13 |  * @link          http://cakephp.org CakePHP(tm) Project
 | 
      ||
| 14 |  * @package       Cake.Cache.Engine
 | 
      ||
| 15 |  * @since         CakePHP(tm) v 1.2.0.4933
 | 
      ||
| 16 |  * @license       http://www.opensource.org/licenses/mit-license.php MIT License
 | 
      ||
| 17 |  */
 | 
      ||
| 18 | |||
| 19 | /**
 | 
      ||
| 20 |  * Memcache storage engine for cache. Memcache has some limitations in the amount of
 | 
      ||
| 21 |  * control you have over expire times far in the future. See MemcacheEngine::write() for
 | 
      ||
| 22 |  * more information.
 | 
      ||
| 23 |  *
 | 
      ||
| 24 |  * @package Cake.Cache.Engine
 | 
      ||
| 25 |  * @deprecated 3.0.0 You should use the Memcached adapter instead.
 | 
      ||
| 26 |  */
 | 
      ||
| 27 | class MemcacheEngine extends CacheEngine {  | 
      ||
| 28 | |||
| 29 | /**
 | 
      ||
| 30 |  * Contains the compiled group names
 | 
      ||
| 31 |  * (prefixed with the global configuration prefix)
 | 
      ||
| 32 |  *
 | 
      ||
| 33 |  * @var array
 | 
      ||
| 34 |  */
 | 
      ||
| 35 | protected $_compiledGroupNames = array();  | 
      ||
| 36 | |||
| 37 | /**
 | 
      ||
| 38 |  * Memcache wrapper.
 | 
      ||
| 39 |  *
 | 
      ||
| 40 |  * @var Memcache
 | 
      ||
| 41 |  */
 | 
      ||
| 42 | protected $_Memcache = null;  | 
      ||
| 43 | |||
| 44 | /**
 | 
      ||
| 45 |  * Settings
 | 
      ||
| 46 |  *
 | 
      ||
| 47 |  *  - servers = string or array of memcache servers, default => 127.0.0.1. If an
 | 
      ||
| 48 |  *    array MemcacheEngine will use them as a pool.
 | 
      ||
| 49 |  *  - compress = boolean, default => false
 | 
      ||
| 50 |  *
 | 
      ||
| 51 |  * @var array
 | 
      ||
| 52 |  */
 | 
      ||
| 53 | public $settings = array();  | 
      ||
| 54 | |||
| 55 | /**
 | 
      ||
| 56 |  * Initialize the Cache Engine
 | 
      ||
| 57 |  *
 | 
      ||
| 58 |  * Called automatically by the cache frontend
 | 
      ||
| 59 |  * To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array());
 | 
      ||
| 60 |  *
 | 
      ||
| 61 |  * @param array $settings array of setting for the engine
 | 
      ||
| 62 |  * @return bool True if the engine has been successfully initialized, false if not
 | 
      ||
| 63 |  */
 | 
      ||
| 64 | public function init($settings = array()) {  | 
      ||
| 65 | if (!class_exists('Memcache')) {  | 
      ||
| 66 | return false;  | 
      ||
| 67 | }  | 
      ||
| 68 | if (!isset($settings['prefix'])) {  | 
      ||
| 69 | $settings['prefix'] = Inflector::slug(APP_DIR) . '_';  | 
      ||
| 70 | }  | 
      ||
| 71 | $settings += array(  | 
      ||
| 72 | 'engine' => 'Memcache',  | 
      ||
| 73 | 'servers' => array('127.0.0.1'),  | 
      ||
| 74 | 'compress' => false,  | 
      ||
| 75 | 'persistent' => true  | 
      ||
| 76 | );  | 
      ||
| 77 | parent::init($settings);  | 
      ||
| 78 | |||
| 79 | if ($this->settings['compress']) {  | 
      ||
| 80 | $this->settings['compress'] = MEMCACHE_COMPRESSED;  | 
      ||
| 81 | }  | 
      ||
| 82 | if (is_string($this->settings['servers'])) {  | 
      ||
| 83 | $this->settings['servers'] = array($this->settings['servers']);  | 
      ||
| 84 | }  | 
      ||
| 85 | if (!isset($this->_Memcache)) {  | 
      ||
| 86 | $return = false;  | 
      ||
| 87 | $this->_Memcache = new Memcache();  | 
      ||
| 88 | foreach ($this->settings['servers'] as $server) {  | 
      ||
| 89 | list($host, $port) = $this->_parseServerString($server);  | 
      ||
| 90 | if ($this->_Memcache->addServer($host, $port, $this->settings['persistent'])) {  | 
      ||
| 91 | $return = true;  | 
      ||
| 92 | }  | 
      ||
| 93 | }  | 
      ||
| 94 | return $return;  | 
      ||
| 95 | }  | 
      ||
| 96 | return true;  | 
      ||
| 97 | }  | 
      ||
| 98 | |||
| 99 | /**
 | 
      ||
| 100 |  * Parses the server address into the host/port. Handles both IPv6 and IPv4
 | 
      ||
| 101 |  * addresses and Unix sockets
 | 
      ||
| 102 |  *
 | 
      ||
| 103 |  * @param string $server The server address string.
 | 
      ||
| 104 |  * @return array Array containing host, port
 | 
      ||
| 105 |  */
 | 
      ||
| 106 | protected function _parseServerString($server) {  | 
      ||
| 107 | if (strpos($server, 'unix://') === 0) {  | 
      ||
| 108 | return array($server, 0);  | 
      ||
| 109 | }  | 
      ||
| 110 | if (substr($server, 0, 1) === '[') {  | 
      ||
| 111 | $position = strpos($server, ']:');  | 
      ||
| 112 | if ($position !== false) {  | 
      ||
| 113 |                                 $position++;
 | 
      ||
| 114 | }  | 
      ||
| 115 |                 } else {
 | 
      ||
| 116 | $position = strpos($server, ':');  | 
      ||
| 117 | }  | 
      ||
| 118 | $port = 11211;  | 
      ||
| 119 | $host = $server;  | 
      ||
| 120 | if ($position !== false) {  | 
      ||
| 121 | $host = substr($server, 0, $position);  | 
      ||
| 122 | $port = substr($server, $position + 1);  | 
      ||
| 123 | }  | 
      ||
| 124 | return array($host, $port);  | 
      ||
| 125 | }  | 
      ||
| 126 | |||
| 127 | /**
 | 
      ||
| 128 |  * Write data for key into cache. When using memcache as your cache engine
 | 
      ||
| 129 |  * remember that the Memcache pecl extension does not support cache expiry times greater
 | 
      ||
| 130 |  * than 30 days in the future. Any duration greater than 30 days will be treated as never expiring.
 | 
      ||
| 131 |  *
 | 
      ||
| 132 |  * @param string $key Identifier for the data
 | 
      ||
| 133 |  * @param mixed $value Data to be cached
 | 
      ||
| 134 |  * @param int $duration How long to cache the data, in seconds
 | 
      ||
| 135 |  * @return bool True if the data was successfully cached, false on failure
 | 
      ||
| 136 |  * @see http://php.net/manual/en/memcache.set.php
 | 
      ||
| 137 |  */
 | 
      ||
| 138 | public function write($key, $value, $duration) {  | 
      ||
| 139 | if ($duration > 30 * DAY) {  | 
      ||
| 140 | $duration = 0;  | 
      ||
| 141 | }  | 
      ||
| 142 | return $this->_Memcache->set($key, $value, $this->settings['compress'], $duration);  | 
      ||
| 143 | }  | 
      ||
| 144 | |||
| 145 | /**
 | 
      ||
| 146 |  * Read a key from the cache
 | 
      ||
| 147 |  *
 | 
      ||
| 148 |  * @param string $key Identifier for the data
 | 
      ||
| 149 |  * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it
 | 
      ||
| 150 |  */
 | 
      ||
| 151 | public function read($key) {  | 
      ||
| 152 | return $this->_Memcache->get($key);  | 
      ||
| 153 | }  | 
      ||
| 154 | |||
| 155 | /**
 | 
      ||
| 156 |  * Increments the value of an integer cached key
 | 
      ||
| 157 |  *
 | 
      ||
| 158 |  * @param string $key Identifier for the data
 | 
      ||
| 159 |  * @param int $offset How much to increment
 | 
      ||
| 160 |  * @return New incremented value, false otherwise
 | 
      ||
| 161 |  * @throws CacheException when you try to increment with compress = true
 | 
      ||
| 162 |  */
 | 
      ||
| 163 | public function increment($key, $offset = 1) {  | 
      ||
| 164 | if ($this->settings['compress']) {  | 
      ||
| 165 | throw new CacheException(  | 
      ||
| 166 | __d('cake_dev', 'Method %s not implemented for compressed cache in %s', 'increment()', __CLASS__)  | 
      ||
| 167 | );  | 
      ||
| 168 | }  | 
      ||
| 169 | return $this->_Memcache->increment($key, $offset);  | 
      ||
| 170 | }  | 
      ||
| 171 | |||
| 172 | /**
 | 
      ||
| 173 |  * Decrements the value of an integer cached key
 | 
      ||
| 174 |  *
 | 
      ||
| 175 |  * @param string $key Identifier for the data
 | 
      ||
| 176 |  * @param int $offset How much to subtract
 | 
      ||
| 177 |  * @return New decremented value, false otherwise
 | 
      ||
| 178 |  * @throws CacheException when you try to decrement with compress = true
 | 
      ||
| 179 |  */
 | 
      ||
| 180 | public function decrement($key, $offset = 1) {  | 
      ||
| 181 | if ($this->settings['compress']) {  | 
      ||
| 182 | throw new CacheException(  | 
      ||
| 183 | __d('cake_dev', 'Method %s not implemented for compressed cache in %s', 'decrement()', __CLASS__)  | 
      ||
| 184 | );  | 
      ||
| 185 | }  | 
      ||
| 186 | return $this->_Memcache->decrement($key, $offset);  | 
      ||
| 187 | }  | 
      ||
| 188 | |||
| 189 | /**
 | 
      ||
| 190 |  * Delete a key from the cache
 | 
      ||
| 191 |  *
 | 
      ||
| 192 |  * @param string $key Identifier for the data
 | 
      ||
| 193 |  * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
 | 
      ||
| 194 |  */
 | 
      ||
| 195 | public function delete($key) {  | 
      ||
| 196 | return $this->_Memcache->delete($key);  | 
      ||
| 197 | }  | 
      ||
| 198 | |||
| 199 | /**
 | 
      ||
| 200 |  * Delete all keys from the cache
 | 
      ||
| 201 |  *
 | 
      ||
| 202 |  * @param bool $check If true no deletes will occur and instead CakePHP will rely
 | 
      ||
| 203 |  *   on key TTL values.
 | 
      ||
| 204 |  * @return bool True if the cache was successfully cleared, false otherwise
 | 
      ||
| 205 |  */
 | 
      ||
| 206 | public function clear($check) {  | 
      ||
| 207 | if ($check) {  | 
      ||
| 208 | return true;  | 
      ||
| 209 | }  | 
      ||
| 210 | foreach ($this->_Memcache->getExtendedStats('slabs', 0) as $slabs) {  | 
      ||
| 211 | foreach (array_keys($slabs) as $slabId) {  | 
      ||
| 212 | if (!is_numeric($slabId)) {  | 
      ||
| 213 |                                         continue;
 | 
      ||
| 214 | }  | 
      ||
| 215 | |||
| 216 | foreach ($this->_Memcache->getExtendedStats('cachedump', $slabId, 0) as $stats) {  | 
      ||
| 217 | if (!is_array($stats)) {  | 
      ||
| 218 |                                                 continue;
 | 
      ||
| 219 | }  | 
      ||
| 220 | foreach (array_keys($stats) as $key) {  | 
      ||
| 221 | if (strpos($key, $this->settings['prefix']) === 0) {  | 
      ||
| 222 | $this->_Memcache->delete($key);  | 
      ||
| 223 | }  | 
      ||
| 224 | }  | 
      ||
| 225 | }  | 
      ||
| 226 | }  | 
      ||
| 227 | }  | 
      ||
| 228 | return true;  | 
      ||
| 229 | }  | 
      ||
| 230 | |||
| 231 | /**
 | 
      ||
| 232 |  * Connects to a server in connection pool
 | 
      ||
| 233 |  *
 | 
      ||
| 234 |  * @param string $host host ip address or name
 | 
      ||
| 235 |  * @param int $port Server port
 | 
      ||
| 236 |  * @return bool True if memcache server was connected
 | 
      ||
| 237 |  */
 | 
      ||
| 238 | public function connect($host, $port = 11211) {  | 
      ||
| 239 | if ($this->_Memcache->getServerStatus($host, $port) === 0) {  | 
      ||
| 240 | if ($this->_Memcache->connect($host, $port)) {  | 
      ||
| 241 | return true;  | 
      ||
| 242 | }  | 
      ||
| 243 | return false;  | 
      ||
| 244 | }  | 
      ||
| 245 | return true;  | 
      ||
| 246 | }  | 
      ||
| 247 | |||
| 248 | /**
 | 
      ||
| 249 |  * Returns the `group value` for each of the configured groups
 | 
      ||
| 250 |  * If the group initial value was not found, then it initializes
 | 
      ||
| 251 |  * the group accordingly.
 | 
      ||
| 252 |  *
 | 
      ||
| 253 |  * @return array
 | 
      ||
| 254 |  */
 | 
      ||
| 255 | public function groups() {  | 
      ||
| 256 | if (empty($this->_compiledGroupNames)) {  | 
      ||
| 257 | foreach ($this->settings['groups'] as $group) {  | 
      ||
| 258 | $this->_compiledGroupNames[] = $this->settings['prefix'] . $group;  | 
      ||
| 259 | }  | 
      ||
| 260 | }  | 
      ||
| 261 | |||
| 262 | $groups = $this->_Memcache->get($this->_compiledGroupNames);  | 
      ||
| 263 | if (count($groups) !== count($this->settings['groups'])) {  | 
      ||
| 264 | foreach ($this->_compiledGroupNames as $group) {  | 
      ||
| 265 | if (!isset($groups[$group])) {  | 
      ||
| 266 | $this->_Memcache->set($group, 1, false, 0);  | 
      ||
| 267 | $groups[$group] = 1;  | 
      ||
| 268 | }  | 
      ||
| 269 | }  | 
      ||
| 270 | ksort($groups);  | 
      ||
| 271 | }  | 
      ||
| 272 | |||
| 273 | $result = array();  | 
      ||
| 274 | $groups = array_values($groups);  | 
      ||
| 275 | foreach ($this->settings['groups'] as $i => $group) {  | 
      ||
| 276 | $result[] = $group . $groups[$i];  | 
      ||
| 277 | }  | 
      ||
| 278 | |||
| 279 | return $result;  | 
      ||
| 280 | }  | 
      ||
| 281 | |||
| 282 | /**
 | 
      ||
| 283 |  * Increments the group value to simulate deletion of all keys under a group
 | 
      ||
| 284 |  * old values will remain in storage until they expire.
 | 
      ||
| 285 |  *
 | 
      ||
| 286 |  * @param string $group The group to clear.
 | 
      ||
| 287 |  * @return bool success
 | 
      ||
| 288 |  */
 | 
      ||
| 289 | public function clearGroup($group) {  | 
      ||
| 290 | return (bool)$this->_Memcache->increment($this->settings['prefix'] . $group);  | 
      ||
| 291 | }  | 
      ||
| 292 | }  |