From 8c4ee529cd9935caab435d8e931979c53ff16683 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Mon, 17 Aug 2015 10:30:55 +0900 Subject: [PATCH] Add support for Redis cache handler --- classes/cache/CacheHandler.class.php | 10 ++ classes/cache/CacheRedis.class.php | 237 +++++++++++++++++++++++++++ 2 files changed, 247 insertions(+) create mode 100644 classes/cache/CacheRedis.class.php diff --git a/classes/cache/CacheHandler.class.php b/classes/cache/CacheHandler.class.php index a3740b8ec..620868920 100644 --- a/classes/cache/CacheHandler.class.php +++ b/classes/cache/CacheHandler.class.php @@ -69,6 +69,11 @@ class CacheHandler extends Handler $type = 'memcache'; $url = $info->use_object_cache; } + else if(substr($info->use_object_cache, 0, 5) == 'redis') + { + $type = 'redis'; + $url = $info->use_object_cache; + } else if($info->use_object_cache == 'wincache') { $type = 'wincache'; @@ -93,6 +98,11 @@ class CacheHandler extends Handler $type = 'memcache'; $url = $info->use_template_cache; } + else if(substr($info->use_template_cache, 0, 5) == 'redis') + { + $type = 'redis'; + $url = $info->use_template_cache; + } else if($info->use_template_cache == 'wincache') { $type = 'wincache'; diff --git a/classes/cache/CacheRedis.class.php b/classes/cache/CacheRedis.class.php new file mode 100644 index 000000000..6297b50be --- /dev/null +++ b/classes/cache/CacheRedis.class.php @@ -0,0 +1,237 @@ + */ + +/** + * Cache class for Redis + * + * @author NAVER (developer@xpressengine.com) + */ +class CacheRedis extends CacheBase +{ + /** + * instance of Redis + * @var redis + */ + var $redis; + var $status; + + /** + * Get instance of CacheRedis + * + * @param string $url url of Redis + * @return CacheRedis instance of CacheRedis + */ + function getInstance($url) + { + if(!$GLOBALS['__CacheRedis__']) + { + $GLOBALS['__CacheRedis__'] = new CacheRedis($url); + } + return $GLOBALS['__CacheRedis__']; + } + + /** + * Construct + * + * Do not use this directly. You can use getInstance() instead. + * @param string $url url of Redis + * @return void + */ + function CacheRedis($url) + { + //$config['url'] = 'redis://localhost:6379/1'; + $config['url'] = is_array($url) ? reset($url) : $url; + + if(!class_exists('Redis')) + { + return $this->status = false; + } + + try + { + $this->redis = new Redis; + $info = parse_url($url); + $this->redis->connect($info['host'], $info['port'], 0.15); + if(isset($info['path']) && $dbnum = intval(substr($info['path'], 1))) + { + $this->redis->select($dbnum); + } + return $this->status = true; + } + catch(RedisException $e) + { + return $this->status = false; + } + } + + /** + * Return whether support or not support cache + * + * @return bool Return true on support or false on not support + */ + function isSupport() + { + if($this->status !== null) + { + return $this->status; + } + + try + { + return $this->redis->setex('xe', 1, 'xe'); + } + catch(RedisException $e) + { + return $this->status = false; + } + } + + /** + * Get unique key of given key by path of XE + * + * @param string $key Cache key + * @return string Return unique key + */ + function getKey($key) + { + return sha1(_XE_PATH_ . $key); + } + + /** + * Store data at the server + * + * CacheRedis::put() stores an item $buff with $key on the Redis server. + * Parameter $valid_time is expiration time in seconds. If it's 0, the item never expires + * (but Redis server doesn't guarantee this item to be stored all the time, it could be delete from the cache to make place for other items). + * + * Remember that resource variables (i.e. file and connection descriptors) cannot be stored in the cache, + * because they can not be adequately represented in serialized state. + * + * @param string $key The key that will be associated with the item. + * @param mixed $buff The variable to store. Strings and integers are stored as is, other types are stored serialized. + * @param int $valid_time Expiration time of the item. + * You can also use Unix timestamp or a number of seconds starting from current time, but in the latter case the number of seconds may not exceed 2592000 (30 days). + * If it's equal to zero, use the default valid time CacheRedis::valid_time. + * @return bool Returns true on success or false on failure. + */ + function put($key, $buff, $valid_time = 0) + { + if($valid_time > 60 * 60 * 24 * 30) + { + $valid_time = $valid_time - time(); + } + if($valid_time <= 0) + { + $valid_time = $this->valid_time; + } + + try + { + return $this->redis->setex($this->getKey($key), $valid_time, array($_SERVER['REQUEST_TIME'], $buff)); + } + catch(RedisException $e) + { + return $this->status = false; + } + } + + /** + * Return whether cache is valid or invalid + * + * @param string $key Cache key + * @param int $modified_time Unix time of data modified. + * If stored time is older then modified time, the data is invalid. + * @return bool Return true on valid or false on invalid. + */ + function isValid($key, $modified_time = 0) + { + $_key = $this->getKey($key); + $obj = $this->redis->get($_key); + if(!$obj || !is_array($obj)) + { + return false; + } + unset($obj[1]); + + if($modified_time > 0 && $modified_time > $obj[0]) + { + $this->redis->del($_key); + return false; + } + + return true; + } + + /** + * Retrieve item from the server + * + * CacheRedis::get() returns previously stored data if an item with such $key exists on the server at this moment. + * + * @param string $key The key to fetch + * @param int $modified_time Unix time of data modified. + * If stored time is older then modified time, return false. + * @return false|mixed Return false on failure or older then modified time. Return the string associated with the $key on success. + */ + function get($key, $modified_time = 0) + { + $_key = $this->getKey($key); + $obj = $this->redis->get($_key); + if(!$obj || !is_array($obj)) + { + return false; + } + + if($modified_time > 0 && $modified_time > $obj[0]) + { + $this->redis->del($_key); + return false; + } + + return $obj[1]; + } + + /** + * Delete item from the server + * + * CacheRedis::delete() deletes an item with tey $key. + * + * @param string $key The key associated with the item to delete. + * @return void + */ + function delete($key) + { + $_key = $this->getKey($key); + + try + { + $this->redis->del($_key); + } + catch(RedisException $e) + { + return $this->status = false; + } + } + + /** + * Flush all existing items at the server + * + * CacheRedis::truncate() immediately invalidates all existing items. + * If using multiple databases, items in other databases are not affected. + * + * @return bool Returns true on success or false on failure. + */ + function truncate() + { + try + { + return $this->redis->flushDB(); + } + catch(RedisException $e) + { + return $this->status = false; + } + } + +} +/* End of file CacheRedis.class.php */ +/* Location: ./classes/cache/CacheRedis.class.php */