統計
| ブランチ: | リビジョン:

pictcode / lib / Cake / Cache / Engine / MemcacheEngine.php @ 635eef61

履歴 | 表示 | アノテート | ダウンロード (8.129 KB)

1
<?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
}