blob: 836336d469d01584909ea37a9d3c4fa9bbfbf6e9 [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 *
Andrey Andreev125ef472016-01-11 12:33:00 +02009 * Copyright (c) 2014 - 2016, 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/)
Andrey Andreev125ef472016-01-11 12:33:00 +020032 * @copyright Copyright (c) 2014 - 2016, 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 {
113 // Third parameter is persistance and defaults to TRUE.
114 $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 {
201 return $this->_memcached->increment($id, $offset);
202 }
203
204 // ------------------------------------------------------------------------
205
206 /**
207 * Decrement a raw value
208 *
209 * @param string $id Cache ID
210 * @param int $offset Step/value to reduce by
211 * @return mixed New value on success or FALSE on failure
212 */
213 public function decrement($id, $offset = 1)
214 {
215 return $this->_memcached->decrement($id, $offset);
216 }
217
218 // ------------------------------------------------------------------------
219
220 /**
Greg Akerbde25d92010-12-21 09:31:21 -0600221 * Clean the Cache
222 *
Andrey Andreevb24b0332012-03-26 15:34:39 +0300223 * @return bool false on failure/true on success
Greg Akerbde25d92010-12-21 09:31:21 -0600224 */
225 public function clean()
226 {
227 return $this->_memcached->flush();
228 }
229
230 // ------------------------------------------------------------------------
231
232 /**
233 * Cache Info
234 *
Andrey Andreevb24b0332012-03-26 15:34:39 +0300235 * @return mixed array on success, false on failure
Greg Akerbde25d92010-12-21 09:31:21 -0600236 */
Andrey Andreevb24b0332012-03-26 15:34:39 +0300237 public function cache_info()
Greg Akerbde25d92010-12-21 09:31:21 -0600238 {
239 return $this->_memcached->getStats();
240 }
241
242 // ------------------------------------------------------------------------
Greg Aker151b7a92011-08-21 12:29:43 -0500243
Greg Akerbde25d92010-12-21 09:31:21 -0600244 /**
245 * Get Cache Metadata
246 *
Andrey Andreev364ba6f2016-03-12 12:18:36 +0200247 * @param mixed $id key to get cache metadata on
Andrey Andreevb24b0332012-03-26 15:34:39 +0300248 * @return mixed FALSE on failure, array on success.
Greg Akerbde25d92010-12-21 09:31:21 -0600249 */
250 public function get_metadata($id)
251 {
252 $stored = $this->_memcached->get($id);
253
254 if (count($stored) !== 3)
255 {
256 return FALSE;
257 }
258
Greg Aker999e7472011-01-29 16:16:58 -0600259 list($data, $time, $ttl) = $stored;
Greg Akerbde25d92010-12-21 09:31:21 -0600260
261 return array(
262 'expire' => $time + $ttl,
263 'mtime' => $time,
264 'data' => $data
265 );
266 }
267
268 // ------------------------------------------------------------------------
269
270 /**
Greg Akerbde25d92010-12-21 09:31:21 -0600271 * Is supported
272 *
273 * Returns FALSE if memcached is not supported on the system.
274 * If it is, we setup the memcached object & return TRUE
Andrey Andreevb24b0332012-03-26 15:34:39 +0300275 *
276 * @return bool
Greg Akerbde25d92010-12-21 09:31:21 -0600277 */
278 public function is_supported()
279 {
Andrey Andreev24a4a6a2015-08-31 15:11:47 +0300280 return (extension_loaded('memcached') OR extension_loaded('memcache'));
Greg Akerbde25d92010-12-21 09:31:21 -0600281 }
Andrey Andreev522c3f32016-03-12 12:13:43 +0200282
283 // ------------------------------------------------------------------------
284
285 /**
286 * Class destructor
287 *
288 * Closes the connection to Memcache(d) if present.
289 *
290 * @return void
291 */
292 public function __destruct()
293 {
294 if ($this->_memcached instanceof Memcache)
295 {
296 $this->_memcached->close();
297 }
Andrey Andreevf8312cf2016-04-01 21:11:23 +0300298 elseif ($this->_memcached instanceof Memcached && method_exists($this->_memcached, 'quit'))
Andrey Andreev522c3f32016-03-12 12:13:43 +0200299 {
300 $this->_memcached->quit();
301 }
302 }
Greg Akerbde25d92010-12-21 09:31:21 -0600303}