Skip to content

Commit

Permalink
implementation of Redis caching
Browse files Browse the repository at this point in the history
  • Loading branch information
hans2103 committed May 19, 2014
1 parent 4b938e5 commit 3ae8372
Show file tree
Hide file tree
Showing 5 changed files with 309 additions and 0 deletions.
47 changes: 47 additions & 0 deletions administrator/components/com_config/model/form/application.xml
Expand Up @@ -81,6 +81,53 @@
size="5" />
</fieldset>

<fieldset
name="redis"
label="COM_CONFIG_REDIS_SETTINGS_LABEL">
<field
name="redis_persist"
type="radio"
class="btn-group btn-group-yesno"
default="1"
label="COM_CONFIG_FIELD_REDIS_PERSISTENT_LABEL"
description="COM_CONFIG_FIELD_REDIS_PERSISTENT_DESC"
filter="integer"
showon="cache_handler:redis">
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>

<field
name="redis_server_host"
type="text"
default="localhost"
label="COM_CONFIG_FIELD_REDIS_HOST_LABEL"
description="COM_CONFIG_FIELD_REDIS_HOST_DESC"
filter="string"
showon="cache_handler:redis"
size="25" />

<field
name="redis_server_port"
type="text"
default="6379"
label="COM_CONFIG_FIELD_REDIS_PORT_LABEL"
description="COM_CONFIG_FIELD_REDIS_PORT_DESC"
filter="integer"
showon="cache_handler:redis"
size="5" />

<field
name="redis_server_auth"
type="password"
label="COM_CONFIG_FIELD_REDIS_AUTH_LABEL"
description="COM_CONFIG_FIELD_REDIS_AUTH_DESC"
filter="raw"
showon="cache_handler:redis"
autocomplete="off"
size="30" />
</fieldset>

<fieldset
name="database"
label="CONFIG_DATABASE_SETTINGS_LABEL">
Expand Down
Expand Up @@ -20,4 +20,10 @@
{
$this->fieldsname .= ',memcache';
}
if (isset($this->data['cache_handler'])
|| $this->data['cache_handler'] == 'redis'
)
{
$this->fieldsname .= ',redis';
}
echo JLayoutHelper::render('joomla.content.options_default', $this);
8 changes: 8 additions & 0 deletions administrator/language/en-GB/en-GB.com_config.ini
Expand Up @@ -127,6 +127,14 @@ COM_CONFIG_FIELD_MEMCACHE_PERSISTENT_DESC="Persistent Memcache(d)"
COM_CONFIG_FIELD_MEMCACHE_PERSISTENT_LABEL="Persistent Memcache(d)"
COM_CONFIG_FIELD_MEMCACHE_PORT_DESC="Memcache(d) Server Port"
COM_CONFIG_FIELD_MEMCACHE_PORT_LABEL="Memcache(d) Server Port"
COM_CONFIG_FIELD_REDIS_AUTH_DESC="Redis Server Authentication"
COM_CONFIG_FIELD_REDIS_AUTH_LABEL="Redis Server Authentication"
COM_CONFIG_FIELD_REDIS_HOST_DESC="Redis Server Host"
COM_CONFIG_FIELD_REDIS_HOST_LABEL="Redis Server Host"
COM_CONFIG_FIELD_REDIS_PERSISTENT_DESC="Persistent Redis"
COM_CONFIG_FIELD_REDIS_PERSISTENT_LABEL="Persistent Redis"
COM_CONFIG_FIELD_REDIS_PORT_DESC="Redis Server Port"
COM_CONFIG_FIELD_REDIS_PORT_LABEL="Redis Server Port"
COM_CONFIG_FIELD_METAAUTHOR_DESC="Show the author meta tag when viewing articles"
COM_CONFIG_FIELD_METAAUTHOR_LABEL="Show Author Meta Tag"
COM_CONFIG_FIELD_METADESC_DESC="Enter a description of the overall Web site that is to be used by search engines. Generally, a maximum of 20 words is optimal."
Expand Down
1 change: 1 addition & 0 deletions administrator/language/en-GB/en-GB.lib_joomla.ini
Expand Up @@ -305,6 +305,7 @@ JLIB_FORM_VALUE_CACHE_EACCELERATOR="eAccelerator"
JLIB_FORM_VALUE_CACHE_FILE="File"
JLIB_FORM_VALUE_CACHE_MEMCACHE="Memcache"
JLIB_FORM_VALUE_CACHE_MEMCACHED="Memcached (Experimental)"
JLIB_FORM_VALUE_CACHE_REDIS="Redis"
JLIB_FORM_VALUE_CACHE_WINCACHE="Windows Cache"
JLIB_FORM_VALUE_CACHE_XCACHE="XCache"
JLIB_FORM_VALUE_SESSION_APC="Alternative PHP Cache"
Expand Down
247 changes: 247 additions & 0 deletions libraries/joomla/cache/storage/redis.php
@@ -0,0 +1,247 @@
<?php
/**
* @package Joomla.Platform
* @subpackage Cache
*
* @copyright Copyright (C) 2005 - 2014 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE
*/

defined('JPATH_PLATFORM') or die;

/**
* Redis cache storage handler
*
* @package Joomla.Platform
* @subpackage Cache
* @since 11.1
*/
class JCacheStorageRedis extends JCacheStorage
{
/**
* Redis connection object
*
* @var Redis
* @since 11.1
*/
protected static $_redis = null;

/**
* Persistent session flag
*
* @var boolean
* @since 11.1
*/
protected $_persistent = false;

/**
* Constructor
*
* @param array $options Optional parameters.
*
* @since 11.1
*/
public function __construct($options = array())
{
parent::__construct($options);
if (self::$_redis === null)
{
$this->getConnection();
}
}

/**
* Return redis connection object
*
* @return object redis connection object
*
* @since 11.1
* @throws RuntimeException
*/
protected function getConnection()
{
if ((class_exists('Redis')) != true)
{
return false;
}

$config = JFactory::getConfig();
$this->_persistent = $config->get('redis_persist', true);

$server = array();
$server['host'] = $config->get('redis_server_host', 'localhost');
$server['port'] = $config->get('redis_server_port', 6379);
$server['auth'] = $config->get('redis_server_auth', NULL);

self::$_redis = new Redis();
if($this->_persistent){
$redistest = self::$_redis->pconnect($server['host'], $server['port']) && self::$_redis->auth($server['auth']);
}else{
$redistest = self::$_redis->connect($server['host'], $server['port']) && self::$_redis->auth($server['auth']);
}

if ($redistest == false){
throw new RuntimeException('Could not connect to redis server', 500);
}

return;
}

/**
* Get cached data from redis by id and group
*
* @param string $id The cache data id
* @param string $group The cache data group
* @param boolean $checkTime True to verify cache time expiration threshold
*
* @return mixed Boolean false on failure or a cached data string
*
* @since 11.1
*/
public function get($id, $group, $checkTime = true)
{
$cache_id = $this->_getCacheId($id, $group);
$back = self::$_redis->get($cache_id);
return $back;
}

/**
* Get all cached data
*
* @return array data
*
* @since 11.1
*/
public function getAll()
{
parent::getAll();

$allKeys = self::$_redis->keys('*');
$data = array();
$secret = $this->_hash;

if (!empty($allKeys)){
foreach ($allKeys as $key){
$namearr = explode('-', $key);

if ($namearr !== false && $namearr[0] == $secret && $namearr[1] == 'cache'){
$group = $namearr[2];

if (!isset($data[$group])){
$item = new JCacheStorageHelper($group);
}
else{
$item = $data[$group];
}
$item->updateSize(strlen($key)*8/1024);
$data[$group] = $item;
}
}
}

return $data;
}

/**
* Store the data to redis by id and group
*
* @param string $id The cache data id
* @param string $group The cache data group
* @param string $data The data to store in cache
*
* @return boolean True on success, false otherwise
*
* @since 11.1
*/
public function store($id, $group, $data)
{
$cache_id = $this->_getCacheId($id, $group);

$tmparr = new stdClass;
$tmparr->name = $cache_id;
$tmparr->size = strlen($data);

$config = JFactory::getConfig();
$lifetime = (int) $config->get('cachetime', 15);
if ($this->_lifetime == $lifetime){
$this->_lifetime = $lifetime * 60;
}

$index[] = $tmparr;

self::$_redis->setex($cache_id, 3600, $data);

return true;
}

/**
* Remove a cached data entry by id and group
*
* @param string $id The cache data id
* @param string $group The cache data group
*
* @return boolean True on success, false otherwise
*
* @since 11.1
*/
public function remove($id, $group)
{
$cache_id = $this->_getCacheId($id, $group);
return self::$_redis->delete($cache_id);
}

/**
* Clean cache for a group given a mode.
*
* @param string $group The cache data group
* @param string $mode The mode for cleaning cache [group|notgroup]
* group mode : cleans all cache in the group
* notgroup mode : cleans all cache not in the group
*
* @return boolean True on success, false otherwise
*
* @since 11.1
*/
public function clean($group, $mode = null)
{
$allKeys = self::$_redis->keys('*');
if ($allKeys === false)
{
$allKeys = array();
}
$secret = $this->_hash;

foreach ($allKeys as $key)
{
if (strpos($key, $secret . '-cache-' . $group . '-') === 0 && $mode == 'group')
{
self::$_redis->delete($key);
}
if (strpos($key, $secret . '-cache-' . $group . '-') !== 0 && $mode != 'group')
{
self::$_redis->delete($key);
}
}
return true;
}

/**
* Test to see if the cache storage is available.
*
* @return boolean True on success, false otherwise.
*
* @since 12.1
*/
public static function isSupported()
{
if (class_exists('Redis') != true)
{
return false;
}
else
{
return true;
}
}
}

0 comments on commit 3ae8372

Please sign in to comment.