blob: ef020f23e1a61e303b755ad076a9172db1e1d842 [file] [log] [blame]
Andrey Andreevc5536aa2012-11-01 17:33:58 +02001<?php
Greg Akerbde25d92010-12-21 09:31:21 -06002/**
3 * CodeIgniter
4 *
Andrey Andreevfe9309d2015-01-09 17:48:58 +02005 * An open source application development framework for PHP
Derek Jonesf4a4bd82011-10-20 12:18:42 -05006 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +02007 * This content is released under the MIT License (MIT)
Andrey Andreev7d4ea072011-12-25 19:23:50 +02008 *
Master Yodada60e9b2016-12-31 08:46:18 -08009 * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
Andrey Andreev7d4ea072011-12-25 19:23:50 +020010 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020011 * 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:
Greg Akerbde25d92010-12-21 09:31:21 -060017 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020018 * 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
Andrey Andreev1924e872016-01-11 12:55:34 +020031 * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
Master Yodada60e9b2016-12-31 08:46:18 -080032 * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020033 * @license http://opensource.org/licenses/MIT MIT License
Andrey Andreevbd202c92016-01-11 12:50:18 +020034 * @link https://codeigniter.com
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020035 * @since Version 2.0
Greg Aker151b7a92011-08-21 12:29:43 -050036 * @filesource
Greg Akerbde25d92010-12-21 09:31:21 -060037 */
Andrey Andreevc5536aa2012-11-01 17:33:58 +020038defined('BASEPATH') OR exit('No direct script access allowed');
Greg Akerbde25d92010-12-21 09:31:21 -060039
Greg Akerbde25d92010-12-21 09:31:21 -060040/**
Greg Aker151b7a92011-08-21 12:29:43 -050041 * CodeIgniter Memcached Caching Class
Greg Akerbde25d92010-12-21 09:31:21 -060042 *
43 * @package CodeIgniter
44 * @subpackage Libraries
45 * @category Core
Derek Jonesf4a4bd82011-10-20 12:18:42 -050046 * @author EllisLab Dev Team
Greg Aker151b7a92011-08-21 12:29:43 -050047 * @link
Greg Akerbde25d92010-12-21 09:31:21 -060048 */
Phil Sturgeoneb2dcda2011-04-02 14:44:58 +010049class CI_Cache_memcached extends CI_Driver {
Greg Akerbde25d92010-12-21 09:31:21 -060050
Timothy Warren0688ac92012-04-20 10:25:04 -040051 /**
52 * Holds the memcached object
53 *
54 * @var object
55 */
56 protected $_memcached;
Greg Akerbde25d92010-12-21 09:31:21 -060057
Timothy Warren0688ac92012-04-20 10:25:04 -040058 /**
59 * Memcached configuration
60 *
61 * @var array
62 */
Andrey Andreev9c948aa2016-03-12 12:33:07 +020063 protected $_config = array(
Timothy Warren0688ac92012-04-20 10:25:04 -040064 'default' => array(
Andrey Andreev6a3d7e52013-07-18 19:14:05 +030065 'host' => '127.0.0.1',
66 'port' => 11211,
67 'weight' => 1
Timothy Warren0688ac92012-04-20 10:25:04 -040068 )
69 );
Greg Akerbde25d92010-12-21 09:31:21 -060070
Andrey Andreev9aade1c2015-06-22 13:19:45 +030071 // ------------------------------------------------------------------------
72
73 /**
74 * Class constructor
75 *
76 * Setup Memcache(d)
77 *
78 * @return void
79 */
80 public function __construct()
81 {
82 // Try to load memcached server info from the config file.
83 $CI =& get_instance();
Andrey Andreev9c948aa2016-03-12 12:33:07 +020084 $defaults = $this->_config['default'];
Andrey Andreev9aade1c2015-06-22 13:19:45 +030085
86 if ($CI->config->load('memcached', TRUE, TRUE))
87 {
Andrey Andreev9c948aa2016-03-12 12:33:07 +020088 $this->_config = $CI->config->config['memcached'];
Andrey Andreev9aade1c2015-06-22 13:19:45 +030089 }
90
91 if (class_exists('Memcached', FALSE))
92 {
93 $this->_memcached = new Memcached();
94 }
95 elseif (class_exists('Memcache', FALSE))
96 {
97 $this->_memcached = new Memcache();
98 }
99 else
100 {
Andrey Andreev24a4a6a2015-08-31 15:11:47 +0300101 log_message('error', 'Cache: Failed to create Memcache(d) object; extension not loaded?');
Andrey Andreev1be89872016-03-11 18:12:57 +0200102 return;
Andrey Andreev9aade1c2015-06-22 13:19:45 +0300103 }
104
Andrey Andreev9c948aa2016-03-12 12:33:07 +0200105 foreach ($this->_config as $cache_server)
Andrey Andreev9aade1c2015-06-22 13:19:45 +0300106 {
107 isset($cache_server['hostname']) OR $cache_server['hostname'] = $defaults['host'];
108 isset($cache_server['port']) OR $cache_server['port'] = $defaults['port'];
109 isset($cache_server['weight']) OR $cache_server['weight'] = $defaults['weight'];
110
Andrey Andreevc13b4a62016-03-12 12:30:21 +0200111 if ($this->_memcached instanceof Memcache)
Andrey Andreev9aade1c2015-06-22 13:19:45 +0300112 {
Andrey Andreev71d8f722017-01-17 12:01:00 +0200113 // Third parameter is persistence and defaults to TRUE.
Andrey Andreev9aade1c2015-06-22 13:19:45 +0300114 $this->_memcached->addServer(
115 $cache_server['hostname'],
116 $cache_server['port'],
117 TRUE,
118 $cache_server['weight']
119 );
120 }
Andrey Andreevc13b4a62016-03-12 12:30:21 +0200121 elseif ($this->_memcached instanceof Memcached)
Andrey Andreev9aade1c2015-06-22 13:19:45 +0300122 {
123 $this->_memcached->addServer(
124 $cache_server['hostname'],
125 $cache_server['port'],
126 $cache_server['weight']
127 );
128 }
129 }
130 }
131
132 // ------------------------------------------------------------------------
133
Greg Akerbde25d92010-12-21 09:31:21 -0600134 /**
135 * Fetch from cache
136 *
Andrey Andreev43d7fa72014-01-09 17:29:45 +0200137 * @param string $id Cache ID
138 * @return mixed Data on success, FALSE on failure
Greg Aker151b7a92011-08-21 12:29:43 -0500139 */
Greg Akerbde25d92010-12-21 09:31:21 -0600140 public function get($id)
Greg Aker151b7a92011-08-21 12:29:43 -0500141 {
Greg Akerbde25d92010-12-21 09:31:21 -0600142 $data = $this->_memcached->get($id);
Greg Aker151b7a92011-08-21 12:29:43 -0500143
Andrey Andreev43d7fa72014-01-09 17:29:45 +0200144 return is_array($data) ? $data[0] : $data;
Greg Akerbde25d92010-12-21 09:31:21 -0600145 }
146
147 // ------------------------------------------------------------------------
148
149 /**
150 * Save
151 *
Andrey Andreev43d7fa72014-01-09 17:29:45 +0200152 * @param string $id Cache ID
153 * @param mixed $data Data being cached
154 * @param int $ttl Time to live
155 * @param bool $raw Whether to store the raw value
156 * @return bool TRUE on success, FALSE on failure
Greg Akerbde25d92010-12-21 09:31:21 -0600157 */
Andrey Andreev43d7fa72014-01-09 17:29:45 +0200158 public function save($id, $data, $ttl = 60, $raw = FALSE)
Greg Akerbde25d92010-12-21 09:31:21 -0600159 {
Andrey Andreev43d7fa72014-01-09 17:29:45 +0200160 if ($raw !== TRUE)
161 {
Andrey Andreevb2a0e702014-01-18 16:54:51 +0200162 $data = array($data, time(), $ttl);
Andrey Andreev43d7fa72014-01-09 17:29:45 +0200163 }
164
Andrey Andreevc13b4a62016-03-12 12:30:21 +0200165 if ($this->_memcached instanceof Memcached)
Mark Huotba00e9f2011-09-23 08:20:29 -0400166 {
Andrey Andreev43d7fa72014-01-09 17:29:45 +0200167 return $this->_memcached->set($id, $data, $ttl);
Mark Huotba00e9f2011-09-23 08:20:29 -0400168 }
Andrey Andreevc13b4a62016-03-12 12:30:21 +0200169 elseif ($this->_memcached instanceof Memcache)
Mark Huotba00e9f2011-09-23 08:20:29 -0400170 {
Andrey Andreev43d7fa72014-01-09 17:29:45 +0200171 return $this->_memcached->set($id, $data, 0, $ttl);
Mark Huotba00e9f2011-09-23 08:20:29 -0400172 }
Andrey Andreev7d4ea072011-12-25 19:23:50 +0200173
Mark Huotba00e9f2011-09-23 08:20:29 -0400174 return FALSE;
Greg Akerbde25d92010-12-21 09:31:21 -0600175 }
176
177 // ------------------------------------------------------------------------
Greg Aker151b7a92011-08-21 12:29:43 -0500178
Greg Akerbde25d92010-12-21 09:31:21 -0600179 /**
180 * Delete from Cache
181 *
Andrey Andreev364ba6f2016-03-12 12:18:36 +0200182 * @param mixed $id key to be deleted.
Andrey Andreev56454792012-05-17 14:32:19 +0300183 * @return bool true on success, false on failure
Greg Akerbde25d92010-12-21 09:31:21 -0600184 */
185 public function delete($id)
186 {
187 return $this->_memcached->delete($id);
188 }
189
190 // ------------------------------------------------------------------------
Greg Aker151b7a92011-08-21 12:29:43 -0500191
Greg Akerbde25d92010-12-21 09:31:21 -0600192 /**
Andrey Andreev43d7fa72014-01-09 17:29:45 +0200193 * Increment a raw value
194 *
195 * @param string $id Cache ID
196 * @param int $offset Step/value to add
197 * @return mixed New value on success or FALSE on failure
198 */
199 public function increment($id, $offset = 1)
200 {
Andrey Andreev47df0882018-01-05 17:29:31 +0200201 if (($result = $this->_memcached->increment($id, $offset)) === FALSE)
202 {
203 return $this->_memcached->add($id, $offset) ? $offset : FALSE;
204 }
205
206 return $result;
Andrey Andreev43d7fa72014-01-09 17:29:45 +0200207 }
208
209 // ------------------------------------------------------------------------
210
211 /**
212 * Decrement a raw value
213 *
214 * @param string $id Cache ID
215 * @param int $offset Step/value to reduce by
216 * @return mixed New value on success or FALSE on failure
217 */
218 public function decrement($id, $offset = 1)
219 {
Andrey Andreev47df0882018-01-05 17:29:31 +0200220 if (($result = $this->_memcached->decrement($id, $offset)) === FALSE)
221 {
222 return $this->_memcached->add($id, 0) ? 0 : FALSE;
223 }
224
225 return $result;
Andrey Andreev43d7fa72014-01-09 17:29:45 +0200226 }
227
228 // ------------------------------------------------------------------------
229
230 /**
Greg Akerbde25d92010-12-21 09:31:21 -0600231 * Clean the Cache
232 *
Andrey Andreevb24b0332012-03-26 15:34:39 +0300233 * @return bool false on failure/true on success
Greg Akerbde25d92010-12-21 09:31:21 -0600234 */
235 public function clean()
236 {
237 return $this->_memcached->flush();
238 }
239
240 // ------------------------------------------------------------------------
241
242 /**
243 * Cache Info
244 *
Andrey Andreevb24b0332012-03-26 15:34:39 +0300245 * @return mixed array on success, false on failure
Greg Akerbde25d92010-12-21 09:31:21 -0600246 */
Andrey Andreevb24b0332012-03-26 15:34:39 +0300247 public function cache_info()
Greg Akerbde25d92010-12-21 09:31:21 -0600248 {
249 return $this->_memcached->getStats();
250 }
251
252 // ------------------------------------------------------------------------
Greg Aker151b7a92011-08-21 12:29:43 -0500253
Greg Akerbde25d92010-12-21 09:31:21 -0600254 /**
255 * Get Cache Metadata
256 *
Andrey Andreev364ba6f2016-03-12 12:18:36 +0200257 * @param mixed $id key to get cache metadata on
Andrey Andreevb24b0332012-03-26 15:34:39 +0300258 * @return mixed FALSE on failure, array on success.
Greg Akerbde25d92010-12-21 09:31:21 -0600259 */
260 public function get_metadata($id)
261 {
262 $stored = $this->_memcached->get($id);
263
264 if (count($stored) !== 3)
265 {
266 return FALSE;
267 }
268
Greg Aker999e7472011-01-29 16:16:58 -0600269 list($data, $time, $ttl) = $stored;
Greg Akerbde25d92010-12-21 09:31:21 -0600270
271 return array(
272 'expire' => $time + $ttl,
273 'mtime' => $time,
274 'data' => $data
275 );
276 }
277
278 // ------------------------------------------------------------------------
279
280 /**
Greg Akerbde25d92010-12-21 09:31:21 -0600281 * Is supported
282 *
283 * Returns FALSE if memcached is not supported on the system.
284 * If it is, we setup the memcached object & return TRUE
Andrey Andreevb24b0332012-03-26 15:34:39 +0300285 *
286 * @return bool
Greg Akerbde25d92010-12-21 09:31:21 -0600287 */
288 public function is_supported()
289 {
Andrey Andreev24a4a6a2015-08-31 15:11:47 +0300290 return (extension_loaded('memcached') OR extension_loaded('memcache'));
Greg Akerbde25d92010-12-21 09:31:21 -0600291 }
Andrey Andreev522c3f32016-03-12 12:13:43 +0200292
293 // ------------------------------------------------------------------------
294
295 /**
296 * Class destructor
297 *
298 * Closes the connection to Memcache(d) if present.
299 *
300 * @return void
301 */
302 public function __destruct()
303 {
304 if ($this->_memcached instanceof Memcache)
305 {
306 $this->_memcached->close();
307 }
Andrey Andreevf8312cf2016-04-01 21:11:23 +0300308 elseif ($this->_memcached instanceof Memcached && method_exists($this->_memcached, 'quit'))
Andrey Andreev522c3f32016-03-12 12:13:43 +0200309 {
310 $this->_memcached->quit();
311 }
312 }
Greg Akerbde25d92010-12-21 09:31:21 -0600313}