Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
16591 anikendra 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
}