Subversion-Projekte lars-tiefland.ci

Revision

Revision 2049 | Zur aktuellen Revision | Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
68 lars 1
<?php
2
/**
3
 * CodeIgniter
4
 *
5
 * An open source application development framework for PHP
6
 *
7
 * This content is released under the MIT License (MIT)
8
 *
9
 * Copyright (c) 2014 - 2016, British Columbia Institute of Technology
10
 *
11
 * Permission is hereby granted, free of charge, to any person obtaining a copy
12
 * of this software and associated documentation files (the "Software"), to deal
13
 * in the Software without restriction, including without limitation the rights
14
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
 * copies of the Software, and to permit persons to whom the Software is
16
 * furnished to do so, subject to the following conditions:
17
 *
18
 * The above copyright notice and this permission notice shall be included in
19
 * all copies or substantial portions of the Software.
20
 *
21
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
 * THE SOFTWARE.
28
 *
29
 * @package	CodeIgniter
30
 * @author	EllisLab Dev Team
31
 * @copyright	Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
32
 * @copyright	Copyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)
33
 * @license	http://opensource.org/licenses/MIT	MIT License
34
 * @link	https://codeigniter.com
35
 * @since	Version 3.0.0
36
 * @filesource
37
 */
38
defined('BASEPATH') OR exit('No direct script access allowed');
39
 
40
/**
41
 * CodeIgniter Redis Caching Class
42
 *
43
 * @package	   CodeIgniter
44
 * @subpackage Libraries
45
 * @category   Core
46
 * @author	   Anton Lindqvist <anton@qvister.se>
47
 * @link
48
 */
49
class CI_Cache_redis extends CI_Driver
50
{
51
	/**
52
	 * Default config
53
	 *
54
	 * @static
55
	 * @var	array
56
	 */
57
	protected static $_default_config = array(
58
		'socket_type' => 'tcp',
59
		'host' => '127.0.0.1',
60
		'password' => NULL,
61
		'port' => 6379,
62
		'timeout' => 0
63
	);
64
 
65
	/**
66
	 * Redis connection
67
	 *
68
	 * @var	Redis
69
	 */
70
	protected $_redis;
71
 
72
	/**
73
	 * An internal cache for storing keys of serialized values.
74
	 *
75
	 * @var	array
76
	 */
77
	protected $_serialized = array();
78
 
79
	// ------------------------------------------------------------------------
80
 
81
	/**
82
	 * Class constructor
83
	 *
84
	 * Setup Redis
85
	 *
86
	 * Loads Redis config file if present. Will halt execution
87
	 * if a Redis connection can't be established.
88
	 *
89
	 * @return	void
90
	 * @see		Redis::connect()
91
	 */
92
	public function __construct()
93
	{
94
		if ( ! $this->is_supported())
95
		{
96
			log_message('error', 'Cache: Failed to create Redis object; extension not loaded?');
97
			return;
98
		}
99
 
100
		$CI =& get_instance();
101
 
102
		if ($CI->config->load('redis', TRUE, TRUE))
103
		{
104
			$config = array_merge(self::$_default_config, $CI->config->item('redis'));
105
		}
106
		else
107
		{
108
			$config = self::$_default_config;
109
		}
110
 
111
		$this->_redis = new Redis();
112
 
113
		try
114
		{
115
			if ($config['socket_type'] === 'unix')
116
			{
117
				$success = $this->_redis->connect($config['socket']);
118
			}
119
			else // tcp socket
120
			{
121
				$success = $this->_redis->connect($config['host'], $config['port'], $config['timeout']);
122
			}
123
 
124
			if ( ! $success)
125
			{
126
				log_message('error', 'Cache: Redis connection failed. Check your configuration.');
127
			}
128
 
129
			if (isset($config['password']) && ! $this->_redis->auth($config['password']))
130
			{
131
				log_message('error', 'Cache: Redis authentication failed.');
132
			}
133
		}
134
		catch (RedisException $e)
135
		{
136
			log_message('error', 'Cache: Redis connection refused ('.$e->getMessage().')');
137
		}
138
 
139
		// Initialize the index of serialized values.
140
		$serialized = $this->_redis->sMembers('_ci_redis_serialized');
141
		empty($serialized) OR $this->_serialized = array_flip($serialized);
142
	}
143
 
144
	// ------------------------------------------------------------------------
145
 
146
	/**
147
	 * Get cache
148
	 *
149
	 * @param	string	$key	Cache ID
150
	 * @return	mixed
151
	 */
152
	public function get($key)
153
	{
154
		$value = $this->_redis->get($key);
155
 
156
		if ($value !== FALSE && isset($this->_serialized[$key]))
157
		{
158
			return unserialize($value);
159
		}
160
 
161
		return $value;
162
	}
163
 
164
	// ------------------------------------------------------------------------
165
 
166
	/**
167
	 * Save cache
168
	 *
169
	 * @param	string	$id	Cache ID
170
	 * @param	mixed	$data	Data to save
171
	 * @param	int	$ttl	Time to live in seconds
172
	 * @param	bool	$raw	Whether to store the raw value (unused)
173
	 * @return	bool	TRUE on success, FALSE on failure
174
	 */
175
	public function save($id, $data, $ttl = 60, $raw = FALSE)
176
	{
177
		if (is_array($data) OR is_object($data))
178
		{
179
			if ( ! $this->_redis->sIsMember('_ci_redis_serialized', $id) && ! $this->_redis->sAdd('_ci_redis_serialized', $id))
180
			{
181
				return FALSE;
182
			}
183
 
184
			isset($this->_serialized[$id]) OR $this->_serialized[$id] = TRUE;
185
			$data = serialize($data);
186
		}
187
		elseif (isset($this->_serialized[$id]))
188
		{
189
			$this->_serialized[$id] = NULL;
190
			$this->_redis->sRemove('_ci_redis_serialized', $id);
191
		}
192
 
193
		return $this->_redis->set($id, $data, $ttl);
194
	}
195
 
196
	// ------------------------------------------------------------------------
197
 
198
	/**
199
	 * Delete from cache
200
	 *
201
	 * @param	string	$key	Cache key
202
	 * @return	bool
203
	 */
204
	public function delete($key)
205
	{
206
		if ($this->_redis->delete($key) !== 1)
207
		{
208
			return FALSE;
209
		}
210
 
211
		if (isset($this->_serialized[$key]))
212
		{
213
			$this->_serialized[$key] = NULL;
214
			$this->_redis->sRemove('_ci_redis_serialized', $key);
215
		}
216
 
217
		return TRUE;
218
	}
219
 
220
	// ------------------------------------------------------------------------
221
 
222
	/**
223
	 * Increment a raw value
224
	 *
225
	 * @param	string	$id	Cache ID
226
	 * @param	int	$offset	Step/value to add
227
	 * @return	mixed	New value on success or FALSE on failure
228
	 */
229
	public function increment($id, $offset = 1)
230
	{
231
		return $this->_redis->incr($id, $offset);
232
	}
233
 
234
	// ------------------------------------------------------------------------
235
 
236
	/**
237
	 * Decrement a raw value
238
	 *
239
	 * @param	string	$id	Cache ID
240
	 * @param	int	$offset	Step/value to reduce by
241
	 * @return	mixed	New value on success or FALSE on failure
242
	 */
243
	public function decrement($id, $offset = 1)
244
	{
245
		return $this->_redis->decr($id, $offset);
246
	}
247
 
248
	// ------------------------------------------------------------------------
249
 
250
	/**
251
	 * Clean cache
252
	 *
253
	 * @return	bool
254
	 * @see		Redis::flushDB()
255
	 */
256
	public function clean()
257
	{
258
		return $this->_redis->flushDB();
259
	}
260
 
261
	// ------------------------------------------------------------------------
262
 
263
	/**
264
	 * Get cache driver info
265
	 *
266
	 * @param	string	$type	Not supported in Redis.
267
	 *				Only included in order to offer a
268
	 *				consistent cache API.
269
	 * @return	array
270
	 * @see		Redis::info()
271
	 */
272
	public function cache_info($type = NULL)
273
	{
274
		return $this->_redis->info();
275
	}
276
 
277
	// ------------------------------------------------------------------------
278
 
279
	/**
280
	 * Get cache metadata
281
	 *
282
	 * @param	string	$key	Cache key
283
	 * @return	array
284
	 */
285
	public function get_metadata($key)
286
	{
287
		$value = $this->get($key);
288
 
289
		if ($value !== FALSE)
290
		{
291
			return array(
292
				'expire' => time() + $this->_redis->ttl($key),
293
				'data' => $value
294
			);
295
		}
296
 
297
		return FALSE;
298
	}
299
 
300
	// ------------------------------------------------------------------------
301
 
302
	/**
303
	 * Check if Redis driver is supported
304
	 *
305
	 * @return	bool
306
	 */
307
	public function is_supported()
308
	{
309
		return extension_loaded('redis');
310
	}
311
 
312
	// ------------------------------------------------------------------------
313
 
314
	/**
315
	 * Class destructor
316
	 *
317
	 * Closes the connection to Redis if present.
318
	 *
319
	 * @return	void
320
	 */
321
	public function __destruct()
322
	{
323
		if ($this->_redis)
324
		{
325
			$this->_redis->close();
326
		}
327
	}
328
}