Skip to content
This repository has been archived by the owner on Sep 25, 2018. It is now read-only.

php7, CiiRedisCache Segfault #1

Open
charlesportwoodii opened this issue Aug 19, 2015 · 0 comments
Open

php7, CiiRedisCache Segfault #1

charlesportwoodii opened this issue Aug 19, 2015 · 0 comments
Labels

Comments

@charlesportwoodii
Copy link
Collaborator

CiiRedisCache segfaults with phpredis on php7, and has problems running unserialize on the returned object. Proposing new class structure to match CRedisCache, and waiting for php7 signoff until phpredis works with php7.

<?php
/**
 * CiRedisCache class file
 *
 * @author Charles R. Portwood II <[email protected]>
 * @package cii.cache
 * @link https://www.ciims.io
 * @copyright 2015
 * @license MIT License
 */

/**
 * CiiRedisCache implements a cache application component based on {@link http://redis.io/ redis}.
 *
 * CiiRedisCache needs to be configured with {@link hostname}, {@link port} and {@link database} of the server
 * to connect to. By default CiiRedisCache assumes there is a redis server running on 127.0.0.1 at
 * port 6379 and uses the database number 0.
 *
 * See {@link CCache} manual for common cache operations that are supported by CiiRedisCache.
 *
 * To use CiiRedisCache as the cache application component, configure the application as follows,
 * array(
 *     'components'=>array(
 *         'cache'=>array(
 *             'class'=>'CiiRedisCache',
 *             'hostname'=>'localhost',
 *             'port'=>6379,
 *             'database'=>0,
 *         ),
 *     ),
 * )
 *
 * @author Charles R. Portwood II <[email protected]>
 * @package cii.cache
 */
class CiiRedisCache extends CiiCache
{
    /**
     * @var string hostname to use for connecting to the redis server. Defaults to '127.0.0.1'.
     */
    public $hostname = '127.0.0.1';

    /**
     * @var int the port to use for connecting to the redis server. Default port is 6379.
     */
    public $port = 6379;

    /**
     * @var string the password to use to authenticate with the redis server. If not set, no AUTH command will be sent.
     */
    public $password =  NULL;

    /**
     * @var int the redis database to use. This is an integer value starting from 0. Defaults to 0.
     */
    public $database = 0;

    /**
     * @var float timeout to use for connection to redis. If not set the timeout set in php.ini will be used: ini_get("default_socket_timeout")
     */
    public $timeout = NULL;

    /**
     * @var redis socket connection
     */
    public $socket;

    /**
     * @var Redis connection to redis
     */
    private $_redis = NULL;

    /**
     * Initialize the connection
     */
    public function init()
    {
        parent::init();
        $this->connect();
    }

    /**
     * Establishes a connection to the redis server.
     * It does nothing if the connection has already been established.
     * @throws CException if connecting fails
     */
    protected function connect()
    {
        if($this->_redis !== NULL)
            return $this->_redis;
        else
        {
            try {
                $this->_redis = new Redis;
                if (isset($this->socket))
                    $val = $this->_redis->connect($this->socket);
                else
                {
                    $this->_redis->pconnect(
                        $this->hostname,
                        $this->port,
                        isset($this->timeout) ? $this->timeout : 2.5
                    );
                }

                // If a password is set, connect to auth
                if ($this->password !== NULL)
                    $this->_redis->auth($this->password);

                $this->_redis->select($this->database);
            } catch (Exception $e) {
                throw new CException('Failed to connect to redis: ' . $e->getMessage());
            }
        }
    }

    /**
     * Retrieves a value from cache with a specified key.
     * This is the implementation of the method declared in the parent class.
     * @param string $key a unique key identifying the cached value
     * @return string|boolean the value stored in cache, false if the value is not in the cache or expired.
     */
    protected function getValue($key)
    {
        return $this->_redis->get($key);
    }

    /**
     * Retrieves multiple values from cache with the specified keys.
     * @param array $keys a list of keys identifying the cached values
     * @return array a list of cached values indexed by the keys
     */
    protected function getValues($keys)
    {
        return $this->_redis->mget($keys);
    }

    /**
     * Stores a value identified by a key in cache.
     * This is the implementation of the method declared in the parent class.
     *
     * @param string $key the key identifying the value to be cached
     * @param string $value the value to be cached
     * @param integer $expire the number of seconds in which the cached value will expire. 0 means never expire.
     * @return boolean true if the value is successfully stored into cache, false otherwise
     */
    protected function setValue($key, $value, $expire)
    {
        if ($expire == 0)
            return (bool)$this->_redis->set($key, $value);
        else
            return $this->_redis->set($key, $value);
    }

    /**
     * Stores a value identified by a key into cache if the cache does not contain this key.
     * This is the implementation of the method declared in the parent class.
     *
     * @param string $key the key identifying the value to be cached
     * @param string $value the value to be cached
     * @param integer $expire the number of seconds in which the cached value will expire. 0 means never expire.
     * @return boolean true if the value is successfully stored into cache, false otherwise
     */
    protected function addValue($key, $value, $expire)
    {
        if ($expire == 0)
            return (bool)$this->_redis->setnx($key, $value);

        if ($this->_redis->setnx($key, $expire, $value))
            return $this->_redis->expire($key,$expire);

        return false;
    }

    /**
     * Deletes a value with the specified key from cache
     * This is the implementation of the method declared in the parent class.
     * @param string $key the key of the value to be deleted
     * @return boolean if no error happens during deletion
     */
    protected function deleteValue($key)
    {
        return (bool)$this->_redis->del($key);
    }

    /**
     * Deletes all values from cache.
     * This is the implementation of the method declared in the parent class.
     * @return boolean whether the flush operation was successful.
     */
    protected function flushValues()
    {
        // As part of CiiMS 1.8, we only delete keys related to CiiMS rather than everything in the system
        $keys = $this->_redis->getKeys($this->generateUniqueIdentifier() . '*');
        foreach ($keys as $k)
            $this->deleteValue($k);

        return true;
    }
}
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

1 participant