mirror of
https://github.com/NNTmux/newznab-tmux.git
synced 2026-08-31 10:18:55 +00:00
343 lines
7.9 KiB
PHP
343 lines
7.9 KiB
PHP
<?php
|
|
namespace newznab\libraries;
|
|
|
|
/**
|
|
* Class Cache
|
|
*
|
|
* Class for connecting to a memcached or redis server to cache data.
|
|
*
|
|
* @package newznab\libraries
|
|
*/
|
|
class Cache
|
|
{
|
|
const SERIALIZER_PHP = 0;
|
|
const SERIALIZER_IGBINARY = 1;
|
|
const SERIALIZER_NONE = 2;
|
|
|
|
const TYPE_DISABLED = 0;
|
|
const TYPE_MEMCACHED = 1;
|
|
const TYPE_REDIS = 2;
|
|
|
|
/**
|
|
* @var \Memcached|\Redis
|
|
*/
|
|
private $server = null;
|
|
|
|
/**
|
|
* Are we connected to the cache server?
|
|
* @var bool
|
|
*/
|
|
private $connected = false;
|
|
|
|
/**
|
|
* Optional socket file location.
|
|
* @var bool|string
|
|
*/
|
|
private $socketFile;
|
|
|
|
/**
|
|
* Serializer type.
|
|
* @var bool|int
|
|
*/
|
|
private $serializerType;
|
|
|
|
/**
|
|
* Are we using redis or memcached?
|
|
* @var bool
|
|
*/
|
|
private $isRedis = true;
|
|
|
|
/**
|
|
* Does the user have igBinary support and wants to use it?
|
|
* @var bool
|
|
*/
|
|
private $IgBinarySupport = false;
|
|
|
|
/**
|
|
* Store data on the cache server.
|
|
*
|
|
* @param string $key Key we can use to retrieve the data.
|
|
* @param string|array $data Data to store on the cache server.
|
|
* @param int $expiration Time before the data expires on the cache server.
|
|
*
|
|
* @return bool Success/Failure.
|
|
* @access public
|
|
*/
|
|
public function set($key, $data, $expiration)
|
|
{
|
|
if ($this->connected === true && $this->ping() === true) {
|
|
return $this->server->set(
|
|
$key,
|
|
($this->isRedis ? ($this->IgBinarySupport ? igbinary_serialize($data) : serialize($data)) : $data),
|
|
$expiration
|
|
);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Attempt to retrieve a value from the cache server, if not set it.
|
|
*
|
|
* @param string $key Key we can use to retrieve the data.
|
|
*
|
|
* @return bool|string False on failure or String, data belonging to the key.
|
|
* @access public
|
|
*/
|
|
public function get($key)
|
|
{
|
|
if ($this->connected === true && $this->ping() === true) {
|
|
$data = $this->server->get($key);
|
|
return ($this->isRedis ? ($this->IgBinarySupport ? igbinary_unserialize($data) : unserialize($data)) : $data);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Delete data tied to a key on the cache server.
|
|
*
|
|
* @param string $key Key we can use to retrieve the data.
|
|
*
|
|
* @return bool True if deleted, false if not.
|
|
* @access public
|
|
*/
|
|
public function delete($key)
|
|
{
|
|
if ($this->connected === true && $this->ping() === true) {
|
|
return (bool)$this->server->delete($key);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Flush all data from the cache server?
|
|
*/
|
|
public function flush()
|
|
{
|
|
if ($this->connected === true && $this->ping() === true) {
|
|
if ($this->isRedis === true) {
|
|
$this->server->flushAll();
|
|
} else {
|
|
$this->server->flush();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a SHA1 hash from a string which can be used to store/retrieve data.
|
|
*
|
|
* @param string $string
|
|
*
|
|
* @return string SHA1 hash of the input string.
|
|
* @access public
|
|
*/
|
|
public function createKey($string)
|
|
{
|
|
return sha1($string);
|
|
}
|
|
|
|
/**
|
|
* Get cache server statistics.
|
|
*
|
|
* @return array|string
|
|
* @access public
|
|
*/
|
|
public function serverStatistics()
|
|
{
|
|
if ($this->connected === true && $this->ping() === true) {
|
|
if ($this->isRedis === true) {
|
|
return $this->server->info();
|
|
} else {
|
|
return $this->server->getStats();
|
|
}
|
|
}
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* Verify the user's cache settings, try to connect to the cache server.
|
|
*/
|
|
public function __construct()
|
|
{
|
|
if (!defined('NN_CACHE_HOSTS')) {
|
|
throw new \CacheException(
|
|
'The NN_CACHE_HOSTS is not defined! Define it in settings.php'
|
|
);
|
|
}
|
|
|
|
if (!defined('NN_CACHE_TIMEOUT')) {
|
|
throw new \CacheException(
|
|
'The NN_CACHE_TIMEOUT is not defined! Define it in settings.php, it is the time in seconds to time out from your cache server.'
|
|
);
|
|
}
|
|
|
|
$this->socketFile = false;
|
|
if (defined('NN_CACHE_SOCKET_FILE') && NN_CACHE_SOCKET_FILE != '') {
|
|
$this->socketFile = true;
|
|
}
|
|
|
|
$this->serializerType = false;
|
|
if (defined('NN_CACHE_SERIALIZER')) {
|
|
$this->serializerType = true;
|
|
}
|
|
|
|
switch (NN_CACHE_TYPE) {
|
|
|
|
case self::TYPE_REDIS:
|
|
if (!extension_loaded('redis')) {
|
|
throw new CacheException('The redis extension is not loaded!');
|
|
}
|
|
$this->server = new \Redis();
|
|
$this->isRedis = true;
|
|
$this->connect();
|
|
if ($this->serializerType !== false) {
|
|
$this->serializerType = $this->verifySerializer();
|
|
$this->server->setOption(\Redis::OPT_SERIALIZER, $this->serializerType);
|
|
}
|
|
break;
|
|
|
|
case self::TYPE_MEMCACHED:
|
|
if (!extension_loaded('memcached')) {
|
|
throw new CacheException('The memcached extension is not loaded!');
|
|
}
|
|
$this->server = new \Memcached();
|
|
$this->isRedis = false;
|
|
if ($this->serializerType !== false) {
|
|
$this->serializerType = $this->verifySerializer();
|
|
$this->server->setOption(\Memcached::OPT_SERIALIZER, $this->serializerType);
|
|
}
|
|
$this->server->setOption(\Memcached::OPT_COMPRESSION, (defined('NN_CACHE_COMPRESSION') ? NN_CACHE_COMPRESSION : false));
|
|
$this->connect();
|
|
break;
|
|
|
|
case self::TYPE_DISABLED:
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Destroy the connections.
|
|
*/
|
|
public function __destruct()
|
|
{
|
|
switch (NN_CACHE_TYPE) {
|
|
case self::TYPE_REDIS:
|
|
$this->server->close();
|
|
break;
|
|
case self::TYPE_MEMCACHED:
|
|
$this->server->quit();
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Connect to the cache server(s).
|
|
*
|
|
* @throws CacheException
|
|
* @access private
|
|
*/
|
|
private function connect()
|
|
{
|
|
$this->connected = false;
|
|
if ($this->isRedis === true) {
|
|
if ($this->socketFile === false) {
|
|
$servers = unserialize(NN_CACHE_HOSTS);
|
|
foreach ($servers as $server) {
|
|
if ($this->server->connect($server['host'], $server['port'], (float)NN_CACHE_TIMEOUT) === false) {
|
|
throw new CacheException('Error connecting to the Redis server!');
|
|
} else {
|
|
$this->connected = true;
|
|
}
|
|
}
|
|
} else {
|
|
if ($this->server->connect(NN_CACHE_SOCKET_FILE) === false) {
|
|
throw new CacheException('Error connecting to the Redis server!');
|
|
} else {
|
|
$this->connected = true;
|
|
}
|
|
}
|
|
} else {
|
|
if ($this->socketFile === false) {
|
|
if ($this->server->addServers(unserialize(NN_CACHE_HOSTS)) === false) {
|
|
throw new CacheException('Error connecting to the Memcached server!');
|
|
} else {
|
|
$this->connected = true;
|
|
}
|
|
} else {
|
|
if ($this->server->addServers(array(array(NN_CACHE_SOCKET_FILE, 'port' => 0))) === false) {
|
|
throw new CacheException('Error connecting to the Memcached server!');
|
|
} else {
|
|
$this->connected = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Redis supports ping'ing the server, so use it.
|
|
*/
|
|
private function ping()
|
|
{
|
|
if ($this->isRedis === true) {
|
|
try {
|
|
return (bool)$this->server->ping();
|
|
} catch (\RedisException $error) {
|
|
$this->connect();
|
|
return $this->connected;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Verify the user selected serializer, return the memcached or redis appropriate serializer option.
|
|
*
|
|
* @return int
|
|
* @throws CacheException
|
|
* @access private
|
|
*/
|
|
private function verifySerializer()
|
|
{
|
|
switch (NN_CACHE_SERIALIZER) {
|
|
case self::SERIALIZER_IGBINARY:
|
|
if (extension_loaded('igbinary')) {
|
|
$this->IgBinarySupport = true;
|
|
if ($this->isRedis === true) {
|
|
return \Redis::SERIALIZER_IGBINARY;
|
|
} else {
|
|
if (\Memcached::HAVE_IGBINARY > 0) {
|
|
return \Memcached::SERIALIZER_IGBINARY;
|
|
} else {
|
|
throw new CacheException('Error: You have not compiled Memcached with igbinary support!');
|
|
}
|
|
}
|
|
} else {
|
|
throw new CacheException('Error: The igbinary extension is not loaded!');
|
|
}
|
|
case self::SERIALIZER_NONE:
|
|
if ($this->isRedis === true) {
|
|
return \Redis::SERIALIZER_NONE;
|
|
} else {
|
|
throw new CacheException('Error: Disabled serialization is not available on Memcached!');
|
|
}
|
|
case self::SERIALIZER_PHP:
|
|
default:
|
|
if ($this->isRedis === true) {
|
|
return \Redis::SERIALIZER_PHP;
|
|
} else {
|
|
return \Memcached::SERIALIZER_PHP;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Class CacheException
|
|
*
|
|
* @package newznab\libraries
|
|
*/
|
|
class CacheException extends \Exception
|
|
{
|
|
}
|