From f3d05486fdac57815709fafe1472620a8de3c18f Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma Date: Mon, 18 Apr 2016 08:21:50 +0200 Subject: Move \OC\Memcache to PSR-4 --- lib/private/Memcache/APC.php | 135 +++++++++++++++++++++++ lib/private/Memcache/APCu.php | 140 ++++++++++++++++++++++++ lib/private/Memcache/ArrayCache.php | 158 +++++++++++++++++++++++++++ lib/private/Memcache/CADTrait.php | 53 +++++++++ lib/private/Memcache/CASTrait.php | 56 ++++++++++ lib/private/Memcache/Cache.php | 96 +++++++++++++++++ lib/private/Memcache/Factory.php | 189 ++++++++++++++++++++++++++++++++ lib/private/Memcache/Memcached.php | 189 ++++++++++++++++++++++++++++++++ lib/private/Memcache/NullCache.php | 72 +++++++++++++ lib/private/Memcache/Redis.php | 208 ++++++++++++++++++++++++++++++++++++ lib/private/Memcache/XCache.php | 134 +++++++++++++++++++++++ lib/private/memcache/apc.php | 135 ----------------------- lib/private/memcache/apcu.php | 140 ------------------------ lib/private/memcache/arraycache.php | 158 --------------------------- lib/private/memcache/cache.php | 96 ----------------- lib/private/memcache/cadtrait.php | 53 --------- lib/private/memcache/castrait.php | 56 ---------- lib/private/memcache/factory.php | 189 -------------------------------- lib/private/memcache/memcached.php | 189 -------------------------------- lib/private/memcache/nullcache.php | 72 ------------- lib/private/memcache/redis.php | 208 ------------------------------------ lib/private/memcache/xcache.php | 134 ----------------------- 22 files changed, 1430 insertions(+), 1430 deletions(-) create mode 100644 lib/private/Memcache/APC.php create mode 100644 lib/private/Memcache/APCu.php create mode 100644 lib/private/Memcache/ArrayCache.php create mode 100644 lib/private/Memcache/CADTrait.php create mode 100644 lib/private/Memcache/CASTrait.php create mode 100644 lib/private/Memcache/Cache.php create mode 100644 lib/private/Memcache/Factory.php create mode 100644 lib/private/Memcache/Memcached.php create mode 100644 lib/private/Memcache/NullCache.php create mode 100644 lib/private/Memcache/Redis.php create mode 100644 lib/private/Memcache/XCache.php delete mode 100644 lib/private/memcache/apc.php delete mode 100644 lib/private/memcache/apcu.php delete mode 100644 lib/private/memcache/arraycache.php delete mode 100644 lib/private/memcache/cache.php delete mode 100644 lib/private/memcache/cadtrait.php delete mode 100644 lib/private/memcache/castrait.php delete mode 100644 lib/private/memcache/factory.php delete mode 100644 lib/private/memcache/memcached.php delete mode 100644 lib/private/memcache/nullcache.php delete mode 100644 lib/private/memcache/redis.php delete mode 100644 lib/private/memcache/xcache.php diff --git a/lib/private/Memcache/APC.php b/lib/private/Memcache/APC.php new file mode 100644 index 00000000000..2354ad07749 --- /dev/null +++ b/lib/private/Memcache/APC.php @@ -0,0 +1,135 @@ + + * @author Clark Tomlinson + * @author Morris Jobke + * @author Otto Sabart + * @author Robin Appelman + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Memcache; + +use OCP\IMemcache; + +class APC extends Cache implements IMemcache { + use CASTrait { + cas as casEmulated; + } + + use CADTrait; + + public function get($key) { + $result = apc_fetch($this->getPrefix() . $key, $success); + if (!$success) { + return null; + } + return $result; + } + + public function set($key, $value, $ttl = 0) { + return apc_store($this->getPrefix() . $key, $value, $ttl); + } + + public function hasKey($key) { + return apc_exists($this->getPrefix() . $key); + } + + public function remove($key) { + return apc_delete($this->getPrefix() . $key); + } + + public function clear($prefix = '') { + $ns = $this->getPrefix() . $prefix; + $ns = preg_quote($ns, '/'); + $iter = new \APCIterator('user', '/^' . $ns . '/', APC_ITER_KEY); + return apc_delete($iter); + } + + /** + * Set a value in the cache if it's not already stored + * + * @param string $key + * @param mixed $value + * @param int $ttl Time To Live in seconds. Defaults to 60*60*24 + * @return bool + */ + public function add($key, $value, $ttl = 0) { + return apc_add($this->getPrefix() . $key, $value, $ttl); + } + + /** + * Increase a stored number + * + * @param string $key + * @param int $step + * @return int | bool + */ + public function inc($key, $step = 1) { + $this->add($key, 0); + return apc_inc($this->getPrefix() . $key, $step); + } + + /** + * Decrease a stored number + * + * @param string $key + * @param int $step + * @return int | bool + */ + public function dec($key, $step = 1) { + return apc_dec($this->getPrefix() . $key, $step); + } + + /** + * Compare and set + * + * @param string $key + * @param mixed $old + * @param mixed $new + * @return bool + */ + public function cas($key, $old, $new) { + // apc only does cas for ints + if (is_int($old) and is_int($new)) { + return apc_cas($this->getPrefix() . $key, $old, $new); + } else { + return $this->casEmulated($key, $old, $new); + } + } + + static public function isAvailable() { + if (!extension_loaded('apc')) { + return false; + } elseif (!\OC::$server->getIniWrapper()->getBool('apc.enabled')) { + return false; + } elseif (!\OC::$server->getIniWrapper()->getBool('apc.enable_cli') && \OC::$CLI) { + return false; + } else { + return true; + } + } +} + +if (!function_exists('apc_exists')) { + function apc_exists($keys) { + $result = false; + apc_fetch($keys, $result); + return $result; + } +} diff --git a/lib/private/Memcache/APCu.php b/lib/private/Memcache/APCu.php new file mode 100644 index 00000000000..350ce913ed8 --- /dev/null +++ b/lib/private/Memcache/APCu.php @@ -0,0 +1,140 @@ + + * @author Bart Visscher + * @author Clark Tomlinson + * @author Lukas Reschke + * @author Morris Jobke + * @author Robin Appelman + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Memcache; + +use OCP\IMemcache; + +class APCu extends Cache implements IMemcache { + use CASTrait { + cas as casEmulated; + } + + use CADTrait; + + public function get($key) { + $result = apcu_fetch($this->getPrefix() . $key, $success); + if (!$success) { + return null; + } + return $result; + } + + public function set($key, $value, $ttl = 0) { + return apcu_store($this->getPrefix() . $key, $value, $ttl); + } + + public function hasKey($key) { + return apcu_exists($this->getPrefix() . $key); + } + + public function remove($key) { + return apcu_delete($this->getPrefix() . $key); + } + + public function clear($prefix = '') { + $ns = $this->getPrefix() . $prefix; + $ns = preg_quote($ns, '/'); + if(class_exists('\APCIterator')) { + $iter = new \APCIterator('user', '/^' . $ns . '/', APC_ITER_KEY); + } else { + $iter = new \APCUIterator('/^' . $ns . '/', APC_ITER_KEY); + } + return apcu_delete($iter); + } + + /** + * Set a value in the cache if it's not already stored + * + * @param string $key + * @param mixed $value + * @param int $ttl Time To Live in seconds. Defaults to 60*60*24 + * @return bool + */ + public function add($key, $value, $ttl = 0) { + return apcu_add($this->getPrefix() . $key, $value, $ttl); + } + + /** + * Increase a stored number + * + * @param string $key + * @param int $step + * @return int | bool + */ + public function inc($key, $step = 1) { + $this->add($key, 0); + return apcu_inc($this->getPrefix() . $key, $step); + } + + /** + * Decrease a stored number + * + * @param string $key + * @param int $step + * @return int | bool + */ + public function dec($key, $step = 1) { + return apcu_dec($this->getPrefix() . $key, $step); + } + + /** + * Compare and set + * + * @param string $key + * @param mixed $old + * @param mixed $new + * @return bool + */ + public function cas($key, $old, $new) { + // apc only does cas for ints + if (is_int($old) and is_int($new)) { + return apcu_cas($this->getPrefix() . $key, $old, $new); + } else { + return $this->casEmulated($key, $old, $new); + } + } + + /** + * @return bool + */ + static public function isAvailable() { + if (!extension_loaded('apcu')) { + return false; + } elseif (!\OC::$server->getIniWrapper()->getBool('apc.enabled')) { + return false; + } elseif (!\OC::$server->getIniWrapper()->getBool('apc.enable_cli') && \OC::$CLI) { + return false; + } elseif ( + version_compare(phpversion('apc'), '4.0.6') === -1 && + version_compare(phpversion('apcu'), '5.1.0') === -1 + ) { + return false; + } else { + return true; + } + } +} diff --git a/lib/private/Memcache/ArrayCache.php b/lib/private/Memcache/ArrayCache.php new file mode 100644 index 00000000000..837f888a307 --- /dev/null +++ b/lib/private/Memcache/ArrayCache.php @@ -0,0 +1,158 @@ + + * @author Morris Jobke + * @author Robin Appelman + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Memcache; + +use OCP\IMemcache; + +class ArrayCache extends Cache implements IMemcache { + /** @var array Array with the cached data */ + protected $cachedData = array(); + + use CADTrait; + + /** + * {@inheritDoc} + */ + public function get($key) { + if ($this->hasKey($key)) { + return $this->cachedData[$key]; + } + return null; + } + + /** + * {@inheritDoc} + */ + public function set($key, $value, $ttl = 0) { + $this->cachedData[$key] = $value; + return true; + } + + /** + * {@inheritDoc} + */ + public function hasKey($key) { + return isset($this->cachedData[$key]); + } + + /** + * {@inheritDoc} + */ + public function remove($key) { + unset($this->cachedData[$key]); + return true; + } + + /** + * {@inheritDoc} + */ + public function clear($prefix = '') { + if ($prefix === '') { + $this->cachedData = []; + return true; + } + + foreach ($this->cachedData as $key => $value) { + if (strpos($key, $prefix) === 0) { + $this->remove($key); + } + } + return true; + } + + /** + * Set a value in the cache if it's not already stored + * + * @param string $key + * @param mixed $value + * @param int $ttl Time To Live in seconds. Defaults to 60*60*24 + * @return bool + */ + public function add($key, $value, $ttl = 0) { + // since this cache is not shared race conditions aren't an issue + if ($this->hasKey($key)) { + return false; + } else { + return $this->set($key, $value, $ttl); + } + } + + /** + * Increase a stored number + * + * @param string $key + * @param int $step + * @return int | bool + */ + public function inc($key, $step = 1) { + $oldValue = $this->get($key); + if (is_int($oldValue)) { + $this->set($key, $oldValue + $step); + return $oldValue + $step; + } else { + $success = $this->add($key, $step); + return ($success) ? $step : false; + } + } + + /** + * Decrease a stored number + * + * @param string $key + * @param int $step + * @return int | bool + */ + public function dec($key, $step = 1) { + $oldValue = $this->get($key); + if (is_int($oldValue)) { + $this->set($key, $oldValue - $step); + return $oldValue - $step; + } else { + return false; + } + } + + /** + * Compare and set + * + * @param string $key + * @param mixed $old + * @param mixed $new + * @return bool + */ + public function cas($key, $old, $new) { + if ($this->get($key) === $old) { + return $this->set($key, $new); + } else { + return false; + } + } + + /** + * {@inheritDoc} + */ + static public function isAvailable() { + return true; + } +} diff --git a/lib/private/Memcache/CADTrait.php b/lib/private/Memcache/CADTrait.php new file mode 100644 index 00000000000..d44d98cba0b --- /dev/null +++ b/lib/private/Memcache/CADTrait.php @@ -0,0 +1,53 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Memcache; + +trait CADTrait { + abstract public function get($key); + + abstract public function remove($key); + + abstract public function add($key, $value, $ttl = 0); + + /** + * Compare and delete + * + * @param string $key + * @param mixed $old + * @return bool + */ + public function cad($key, $old) { + //no native cas, emulate with locking + if ($this->add($key . '_lock', true)) { + if ($this->get($key) === $old) { + $this->remove($key); + $this->remove($key . '_lock'); + return true; + } else { + $this->remove($key . '_lock'); + return false; + } + } else { + return false; + } + } +} diff --git a/lib/private/Memcache/CASTrait.php b/lib/private/Memcache/CASTrait.php new file mode 100644 index 00000000000..43253fc966b --- /dev/null +++ b/lib/private/Memcache/CASTrait.php @@ -0,0 +1,56 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Memcache; + +trait CASTrait { + abstract public function get($key); + + abstract public function set($key, $value, $ttl = 0); + + abstract public function remove($key); + + abstract public function add($key, $value, $ttl = 0); + + /** + * Compare and set + * + * @param string $key + * @param mixed $old + * @param mixed $new + * @return bool + */ + public function cas($key, $old, $new) { + //no native cas, emulate with locking + if ($this->add($key . '_lock', true)) { + if ($this->get($key) === $old) { + $this->set($key, $new); + $this->remove($key . '_lock'); + return true; + } else { + $this->remove($key . '_lock'); + return false; + } + } else { + return false; + } + } +} diff --git a/lib/private/Memcache/Cache.php b/lib/private/Memcache/Cache.php new file mode 100644 index 00000000000..63d20721aac --- /dev/null +++ b/lib/private/Memcache/Cache.php @@ -0,0 +1,96 @@ + + * @author Morris Jobke + * @author Robin Appelman + * @author Robin McCorkell + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Memcache; + +abstract class Cache implements \ArrayAccess, \OCP\ICache { + /** + * @var string $prefix + */ + protected $prefix; + + /** + * @param string $prefix + */ + public function __construct($prefix = '') { + $this->prefix = $prefix; + } + + /** + * @return string Prefix used for caching purposes + */ + public function getPrefix() { + return $this->prefix; + } + + /** + * @param string $key + * @return mixed + */ + abstract public function get($key); + + /** + * @param string $key + * @param mixed $value + * @param int $ttl + * @return mixed + */ + abstract public function set($key, $value, $ttl = 0); + + /** + * @param string $key + * @return mixed + */ + abstract public function hasKey($key); + + /** + * @param string $key + * @return mixed + */ + abstract public function remove($key); + + /** + * @param string $prefix + * @return mixed + */ + abstract public function clear($prefix = ''); + + //implement the ArrayAccess interface + + public function offsetExists($offset) { + return $this->hasKey($offset); + } + + public function offsetSet($offset, $value) { + $this->set($offset, $value); + } + + public function offsetGet($offset) { + return $this->get($offset); + } + + public function offsetUnset($offset) { + $this->remove($offset); + } +} diff --git a/lib/private/Memcache/Factory.php b/lib/private/Memcache/Factory.php new file mode 100644 index 00000000000..a005f319b3e --- /dev/null +++ b/lib/private/Memcache/Factory.php @@ -0,0 +1,189 @@ + + * @author Lukas Reschke + * @author Markus Goetz + * @author Morris Jobke + * @author Robin Appelman + * @author Robin McCorkell + * @author Thomas Müller + * @author Vincent Petry + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Memcache; + +use \OCP\ICacheFactory; +use \OCP\ILogger; + +class Factory implements ICacheFactory { + const NULL_CACHE = '\\OC\\Memcache\\NullCache'; + + /** + * @var string $globalPrefix + */ + private $globalPrefix; + + /** + * @var ILogger $logger + */ + private $logger; + + /** + * @var string $localCacheClass + */ + private $localCacheClass; + + /** + * @var string $distributedCacheClass + */ + private $distributedCacheClass; + + /** + * @var string $lockingCacheClass + */ + private $lockingCacheClass; + + /** + * @param string $globalPrefix + * @param ILogger $logger + * @param string|null $localCacheClass + * @param string|null $distributedCacheClass + * @param string|null $lockingCacheClass + */ + public function __construct($globalPrefix, ILogger $logger, + $localCacheClass = null, $distributedCacheClass = null, $lockingCacheClass = null) + { + $this->logger = $logger; + $this->globalPrefix = $globalPrefix; + + if (!$localCacheClass) { + $localCacheClass = self::NULL_CACHE; + } + if (!$distributedCacheClass) { + $distributedCacheClass = $localCacheClass; + } + + $missingCacheMessage = 'Memcache {class} not available for {use} cache'; + $missingCacheHint = 'Is the matching PHP module installed and enabled?'; + if (!$localCacheClass::isAvailable()) { + if (\OC::$CLI && !defined('PHPUNIT_RUN')) { + // CLI should not hard-fail on broken memcache + $this->logger->info($missingCacheMessage, [ + 'class' => $localCacheClass, + 'use' => 'local', + 'app' => 'cli' + ]); + $localCacheClass = self::NULL_CACHE; + } else { + throw new \OC\HintException(strtr($missingCacheMessage, [ + '{class}' => $localCacheClass, '{use}' => 'local' + ]), $missingCacheHint); + } + } + if (!$distributedCacheClass::isAvailable()) { + if (\OC::$CLI && !defined('PHPUNIT_RUN')) { + // CLI should not hard-fail on broken memcache + $this->logger->info($missingCacheMessage, [ + 'class' => $distributedCacheClass, + 'use' => 'distributed', + 'app' => 'cli' + ]); + $distributedCacheClass = self::NULL_CACHE; + } else { + throw new \OC\HintException(strtr($missingCacheMessage, [ + '{class}' => $distributedCacheClass, '{use}' => 'distributed' + ]), $missingCacheHint); + } + } + if (!($lockingCacheClass && $lockingCacheClass::isAvailable())) { + // don't fallback since the fallback might not be suitable for storing lock + $lockingCacheClass = self::NULL_CACHE; + } + + $this->localCacheClass = $localCacheClass; + $this->distributedCacheClass = $distributedCacheClass; + $this->lockingCacheClass = $lockingCacheClass; + } + + /** + * create a cache instance for storing locks + * + * @param string $prefix + * @return \OCP\IMemcache + */ + public function createLocking($prefix = '') { + return new $this->lockingCacheClass($this->globalPrefix . '/' . $prefix); + } + + /** + * create a distributed cache instance + * + * @param string $prefix + * @return \OC\Memcache\Cache + */ + public function createDistributed($prefix = '') { + return new $this->distributedCacheClass($this->globalPrefix . '/' . $prefix); + } + + /** + * create a local cache instance + * + * @param string $prefix + * @return \OC\Memcache\Cache + */ + public function createLocal($prefix = '') { + return new $this->localCacheClass($this->globalPrefix . '/' . $prefix); + } + + /** + * @see \OC\Memcache\Factory::createDistributed() + * @param string $prefix + * @return \OC\Memcache\Cache + */ + public function create($prefix = '') { + return $this->createDistributed($prefix); + } + + /** + * check memcache availability + * + * @return bool + */ + public function isAvailable() { + return ($this->distributedCacheClass !== self::NULL_CACHE); + } + + /** + * @see \OC\Memcache\Factory::createLocal() + * @param string $prefix + * @return Cache + */ + public function createLowLatency($prefix = '') { + return $this->createLocal($prefix); + } + + /** + * check local memcache availability + * + * @return bool + */ + public function isAvailableLowLatency() { + return ($this->localCacheClass !== self::NULL_CACHE); + } +} diff --git a/lib/private/Memcache/Memcached.php b/lib/private/Memcache/Memcached.php new file mode 100644 index 00000000000..a30f9da7ed7 --- /dev/null +++ b/lib/private/Memcache/Memcached.php @@ -0,0 +1,189 @@ + + * @author Bart Visscher + * @author Morris Jobke + * @author Robin Appelman + * @author Robin McCorkell + * @author Thomas Müller + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Memcache; + +use OCP\IMemcache; + +class Memcached extends Cache implements IMemcache { + use CASTrait; + + /** + * @var \Memcached $cache + */ + private static $cache = null; + + use CADTrait; + + public function __construct($prefix = '') { + parent::__construct($prefix); + if (is_null(self::$cache)) { + self::$cache = new \Memcached(); + $servers = \OC::$server->getSystemConfig()->getValue('memcached_servers'); + if (!$servers) { + $server = \OC::$server->getSystemConfig()->getValue('memcached_server'); + if ($server) { + $servers = array($server); + } else { + $servers = array(array('localhost', 11211)); + } + } + self::$cache->addServers($servers); + } + } + + /** + * entries in XCache gets namespaced to prevent collisions between owncloud instances and users + */ + protected function getNameSpace() { + return $this->prefix; + } + + public function get($key) { + $result = self::$cache->get($this->getNamespace() . $key); + if ($result === false and self::$cache->getResultCode() == \Memcached::RES_NOTFOUND) { + return null; + } else { + return $result; + } + } + + public function set($key, $value, $ttl = 0) { + if ($ttl > 0) { + $result = self::$cache->set($this->getNamespace() . $key, $value, $ttl); + } else { + $result = self::$cache->set($this->getNamespace() . $key, $value); + } + $this->verifyReturnCode(); + return $result; + } + + public function hasKey($key) { + self::$cache->get($this->getNamespace() . $key); + return self::$cache->getResultCode() === \Memcached::RES_SUCCESS; + } + + public function remove($key) { + $result= self::$cache->delete($this->getNamespace() . $key); + if (self::$cache->getResultCode() !== \Memcached::RES_NOTFOUND) { + $this->verifyReturnCode(); + } + return $result; + } + + public function clear($prefix = '') { + $prefix = $this->getNamespace() . $prefix; + $allKeys = self::$cache->getAllKeys(); + if ($allKeys === false) { + // newer Memcached doesn't like getAllKeys(), flush everything + self::$cache->flush(); + return true; + } + $keys = array(); + $prefixLength = strlen($prefix); + foreach ($allKeys as $key) { + if (substr($key, 0, $prefixLength) === $prefix) { + $keys[] = $key; + } + } + if (method_exists(self::$cache, 'deleteMulti')) { + self::$cache->deleteMulti($keys); + } else { + foreach ($keys as $key) { + self::$cache->delete($key); + } + } + return true; + } + + /** + * Set a value in the cache if it's not already stored + * + * @param string $key + * @param mixed $value + * @param int $ttl Time To Live in seconds. Defaults to 60*60*24 + * @return bool + * @throws \Exception + */ + public function add($key, $value, $ttl = 0) { + $result = self::$cache->add($this->getPrefix() . $key, $value, $ttl); + if (self::$cache->getResultCode() !== \Memcached::RES_NOTSTORED) { + $this->verifyReturnCode(); + } + return $result; + } + + /** + * Increase a stored number + * + * @param string $key + * @param int $step + * @return int | bool + */ + public function inc($key, $step = 1) { + $this->add($key, 0); + $result = self::$cache->increment($this->getPrefix() . $key, $step); + + if (self::$cache->getResultCode() !== \Memcached::RES_SUCCESS) { + return false; + } + + return $result; + } + + /** + * Decrease a stored number + * + * @param string $key + * @param int $step + * @return int | bool + */ + public function dec($key, $step = 1) { + $result = self::$cache->decrement($this->getPrefix() . $key, $step); + + if (self::$cache->getResultCode() !== \Memcached::RES_SUCCESS) { + return false; + } + + return $result; + } + + static public function isAvailable() { + return extension_loaded('memcached'); + } + + /** + * @throws \Exception + */ + private function verifyReturnCode() { + $code = self::$cache->getResultCode(); + if ($code === \Memcached::RES_SUCCESS) { + return; + } + $message = self::$cache->getResultMessage(); + throw new \Exception("Error $code interacting with memcached : $message"); + } +} diff --git a/lib/private/Memcache/NullCache.php b/lib/private/Memcache/NullCache.php new file mode 100644 index 00000000000..c490ca7e03c --- /dev/null +++ b/lib/private/Memcache/NullCache.php @@ -0,0 +1,72 @@ + + * @author Robin Appelman + * @author Robin McCorkell + * @author Thomas Müller + * @author Vincent Petry + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Memcache; + +class NullCache extends Cache implements \OCP\IMemcache { + public function get($key) { + return null; + } + + public function set($key, $value, $ttl = 0) { + return true; + } + + public function hasKey($key) { + return false; + } + + public function remove($key) { + return true; + } + + public function add($key, $value, $ttl = 0) { + return true; + } + + public function inc($key, $step = 1) { + return true; + } + + public function dec($key, $step = 1) { + return true; + } + + public function cas($key, $old, $new) { + return true; + } + + public function cad($key, $old) { + return true; + } + + public function clear($prefix = '') { + return true; + } + + static public function isAvailable() { + return true; + } +} diff --git a/lib/private/Memcache/Redis.php b/lib/private/Memcache/Redis.php new file mode 100644 index 00000000000..b3444a2b4e9 --- /dev/null +++ b/lib/private/Memcache/Redis.php @@ -0,0 +1,208 @@ + + * @author Jörn Friedrich Dreyer + * @author Lukas Reschke + * @author Michael Telatynski <7t3chguy@gmail.com> + * @author Morris Jobke + * @author Robin Appelman + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Memcache; + +use OCP\IMemcacheTTL; + +class Redis extends Cache implements IMemcacheTTL { + /** + * @var \Redis $cache + */ + private static $cache = null; + + public function __construct($prefix = '') { + parent::__construct($prefix); + if (is_null(self::$cache)) { + // TODO allow configuring a RedisArray, see https://github.com/nicolasff/phpredis/blob/master/arrays.markdown#redis-arrays + self::$cache = new \Redis(); + $config = \OC::$server->getSystemConfig()->getValue('redis', array()); + if (isset($config['host'])) { + $host = $config['host']; + } else { + $host = '127.0.0.1'; + } + if (isset($config['port'])) { + $port = $config['port']; + } else { + $port = 6379; + } + if (isset($config['timeout'])) { + $timeout = $config['timeout']; + } else { + $timeout = 0.0; // unlimited + } + + self::$cache->connect($host, $port, $timeout); + if(isset($config['password']) && $config['password'] !== '') { + self::$cache->auth($config['password']); + } + + if (isset($config['dbindex'])) { + self::$cache->select($config['dbindex']); + } + } + } + + /** + * entries in redis get namespaced to prevent collisions between ownCloud instances and users + */ + protected function getNameSpace() { + return $this->prefix; + } + + public function get($key) { + $result = self::$cache->get($this->getNamespace() . $key); + if ($result === false && !self::$cache->exists($this->getNamespace() . $key)) { + return null; + } else { + return json_decode($result, true); + } + } + + public function set($key, $value, $ttl = 0) { + if ($ttl > 0) { + return self::$cache->setex($this->getNamespace() . $key, $ttl, json_encode($value)); + } else { + return self::$cache->set($this->getNamespace() . $key, json_encode($value)); + } + } + + public function hasKey($key) { + return self::$cache->exists($this->getNamespace() . $key); + } + + public function remove($key) { + if (self::$cache->delete($this->getNamespace() . $key)) { + return true; + } else { + return false; + } + } + + public function clear($prefix = '') { + $prefix = $this->getNamespace() . $prefix . '*'; + $it = null; + self::$cache->setOption(\Redis::OPT_SCAN, \Redis::SCAN_RETRY); + while ($keys = self::$cache->scan($it, $prefix)) { + self::$cache->delete($keys); + } + return true; + } + + /** + * Set a value in the cache if it's not already stored + * + * @param string $key + * @param mixed $value + * @param int $ttl Time To Live in seconds. Defaults to 60*60*24 + * @return bool + */ + public function add($key, $value, $ttl = 0) { + // don't encode ints for inc/dec + if (!is_int($value)) { + $value = json_encode($value); + } + return self::$cache->setnx($this->getPrefix() . $key, $value); + } + + /** + * Increase a stored number + * + * @param string $key + * @param int $step + * @return int | bool + */ + public function inc($key, $step = 1) { + return self::$cache->incrBy($this->getNamespace() . $key, $step); + } + + /** + * Decrease a stored number + * + * @param string $key + * @param int $step + * @return int | bool + */ + public function dec($key, $step = 1) { + if (!$this->hasKey($key)) { + return false; + } + return self::$cache->decrBy($this->getNamespace() . $key, $step); + } + + /** + * Compare and set + * + * @param string $key + * @param mixed $old + * @param mixed $new + * @return bool + */ + public function cas($key, $old, $new) { + if (!is_int($new)) { + $new = json_encode($new); + } + self::$cache->watch($this->getNamespace() . $key); + if ($this->get($key) === $old) { + $result = self::$cache->multi() + ->set($this->getNamespace() . $key, $new) + ->exec(); + return ($result === false) ? false : true; + } + self::$cache->unwatch(); + return false; + } + + /** + * Compare and delete + * + * @param string $key + * @param mixed $old + * @return bool + */ + public function cad($key, $old) { + self::$cache->watch($this->getNamespace() . $key); + if ($this->get($key) === $old) { + $result = self::$cache->multi() + ->del($this->getNamespace() . $key) + ->exec(); + return ($result === false) ? false : true; + } + self::$cache->unwatch(); + return false; + } + + public function setTTL($key, $ttl) { + self::$cache->expire($this->getNamespace() . $key, $ttl); + } + + static public function isAvailable() { + return extension_loaded('redis') + && version_compare(phpversion('redis'), '2.2.5', '>='); + } +} + diff --git a/lib/private/Memcache/XCache.php b/lib/private/Memcache/XCache.php new file mode 100644 index 00000000000..e80901faadc --- /dev/null +++ b/lib/private/Memcache/XCache.php @@ -0,0 +1,134 @@ + + * @author Bart Visscher + * @author Clark Tomlinson + * @author Morris Jobke + * @author Robin Appelman + * @author Thomas Müller + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Memcache; + +use OCP\IMemcache; + +/** + * See http://xcache.lighttpd.net/wiki/XcacheApi for provided constants and + * functions etc. + */ +class XCache extends Cache implements IMemcache { + use CASTrait; + + use CADTrait; + + /** + * entries in XCache gets namespaced to prevent collisions between ownCloud instances and users + */ + protected function getNameSpace() { + return $this->prefix; + } + + public function get($key) { + return xcache_get($this->getNamespace() . $key); + } + + public function set($key, $value, $ttl = 0) { + if ($ttl > 0) { + return xcache_set($this->getNamespace() . $key, $value, $ttl); + } else { + return xcache_set($this->getNamespace() . $key, $value); + } + } + + public function hasKey($key) { + return xcache_isset($this->getNamespace() . $key); + } + + public function remove($key) { + return xcache_unset($this->getNamespace() . $key); + } + + public function clear($prefix = '') { + if (function_exists('xcache_unset_by_prefix')) { + return xcache_unset_by_prefix($this->getNamespace() . $prefix); + } else { + // Since we can not clear by prefix, we just clear the whole cache. + xcache_clear_cache(\XC_TYPE_VAR, 0); + } + return true; + } + + /** + * Set a value in the cache if it's not already stored + * + * @param string $key + * @param mixed $value + * @param int $ttl Time To Live in seconds. Defaults to 60*60*24 + * @return bool + */ + public function add($key, $value, $ttl = 0) { + if ($this->hasKey($key)) { + return false; + } else { + return $this->set($key, $value, $ttl); + } + } + + /** + * Increase a stored number + * + * @param string $key + * @param int $step + * @return int | bool + */ + public function inc($key, $step = 1) { + return xcache_inc($this->getPrefix() . $key, $step); + } + + /** + * Decrease a stored number + * + * @param string $key + * @param int $step + * @return int | bool + */ + public function dec($key, $step = 1) { + return xcache_dec($this->getPrefix() . $key, $step); + } + + static public function isAvailable() { + if (!extension_loaded('xcache')) { + return false; + } + if (\OC::$CLI && !getenv('XCACHE_TEST')) { + return false; + } + if (!function_exists('xcache_unset_by_prefix') && \OC::$server->getIniWrapper()->getBool('xcache.admin.enable_auth')) { + // We do not want to use XCache if we can not clear it without + // using the administration function xcache_clear_cache() + // AND administration functions are password-protected. + return false; + } + $var_size = \OC::$server->getIniWrapper()->getBytes('xcache.var_size'); + if (!$var_size) { + return false; + } + return true; + } +} diff --git a/lib/private/memcache/apc.php b/lib/private/memcache/apc.php deleted file mode 100644 index 2354ad07749..00000000000 --- a/lib/private/memcache/apc.php +++ /dev/null @@ -1,135 +0,0 @@ - - * @author Clark Tomlinson - * @author Morris Jobke - * @author Otto Sabart - * @author Robin Appelman - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Memcache; - -use OCP\IMemcache; - -class APC extends Cache implements IMemcache { - use CASTrait { - cas as casEmulated; - } - - use CADTrait; - - public function get($key) { - $result = apc_fetch($this->getPrefix() . $key, $success); - if (!$success) { - return null; - } - return $result; - } - - public function set($key, $value, $ttl = 0) { - return apc_store($this->getPrefix() . $key, $value, $ttl); - } - - public function hasKey($key) { - return apc_exists($this->getPrefix() . $key); - } - - public function remove($key) { - return apc_delete($this->getPrefix() . $key); - } - - public function clear($prefix = '') { - $ns = $this->getPrefix() . $prefix; - $ns = preg_quote($ns, '/'); - $iter = new \APCIterator('user', '/^' . $ns . '/', APC_ITER_KEY); - return apc_delete($iter); - } - - /** - * Set a value in the cache if it's not already stored - * - * @param string $key - * @param mixed $value - * @param int $ttl Time To Live in seconds. Defaults to 60*60*24 - * @return bool - */ - public function add($key, $value, $ttl = 0) { - return apc_add($this->getPrefix() . $key, $value, $ttl); - } - - /** - * Increase a stored number - * - * @param string $key - * @param int $step - * @return int | bool - */ - public function inc($key, $step = 1) { - $this->add($key, 0); - return apc_inc($this->getPrefix() . $key, $step); - } - - /** - * Decrease a stored number - * - * @param string $key - * @param int $step - * @return int | bool - */ - public function dec($key, $step = 1) { - return apc_dec($this->getPrefix() . $key, $step); - } - - /** - * Compare and set - * - * @param string $key - * @param mixed $old - * @param mixed $new - * @return bool - */ - public function cas($key, $old, $new) { - // apc only does cas for ints - if (is_int($old) and is_int($new)) { - return apc_cas($this->getPrefix() . $key, $old, $new); - } else { - return $this->casEmulated($key, $old, $new); - } - } - - static public function isAvailable() { - if (!extension_loaded('apc')) { - return false; - } elseif (!\OC::$server->getIniWrapper()->getBool('apc.enabled')) { - return false; - } elseif (!\OC::$server->getIniWrapper()->getBool('apc.enable_cli') && \OC::$CLI) { - return false; - } else { - return true; - } - } -} - -if (!function_exists('apc_exists')) { - function apc_exists($keys) { - $result = false; - apc_fetch($keys, $result); - return $result; - } -} diff --git a/lib/private/memcache/apcu.php b/lib/private/memcache/apcu.php deleted file mode 100644 index 350ce913ed8..00000000000 --- a/lib/private/memcache/apcu.php +++ /dev/null @@ -1,140 +0,0 @@ - - * @author Bart Visscher - * @author Clark Tomlinson - * @author Lukas Reschke - * @author Morris Jobke - * @author Robin Appelman - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Memcache; - -use OCP\IMemcache; - -class APCu extends Cache implements IMemcache { - use CASTrait { - cas as casEmulated; - } - - use CADTrait; - - public function get($key) { - $result = apcu_fetch($this->getPrefix() . $key, $success); - if (!$success) { - return null; - } - return $result; - } - - public function set($key, $value, $ttl = 0) { - return apcu_store($this->getPrefix() . $key, $value, $ttl); - } - - public function hasKey($key) { - return apcu_exists($this->getPrefix() . $key); - } - - public function remove($key) { - return apcu_delete($this->getPrefix() . $key); - } - - public function clear($prefix = '') { - $ns = $this->getPrefix() . $prefix; - $ns = preg_quote($ns, '/'); - if(class_exists('\APCIterator')) { - $iter = new \APCIterator('user', '/^' . $ns . '/', APC_ITER_KEY); - } else { - $iter = new \APCUIterator('/^' . $ns . '/', APC_ITER_KEY); - } - return apcu_delete($iter); - } - - /** - * Set a value in the cache if it's not already stored - * - * @param string $key - * @param mixed $value - * @param int $ttl Time To Live in seconds. Defaults to 60*60*24 - * @return bool - */ - public function add($key, $value, $ttl = 0) { - return apcu_add($this->getPrefix() . $key, $value, $ttl); - } - - /** - * Increase a stored number - * - * @param string $key - * @param int $step - * @return int | bool - */ - public function inc($key, $step = 1) { - $this->add($key, 0); - return apcu_inc($this->getPrefix() . $key, $step); - } - - /** - * Decrease a stored number - * - * @param string $key - * @param int $step - * @return int | bool - */ - public function dec($key, $step = 1) { - return apcu_dec($this->getPrefix() . $key, $step); - } - - /** - * Compare and set - * - * @param string $key - * @param mixed $old - * @param mixed $new - * @return bool - */ - public function cas($key, $old, $new) { - // apc only does cas for ints - if (is_int($old) and is_int($new)) { - return apcu_cas($this->getPrefix() . $key, $old, $new); - } else { - return $this->casEmulated($key, $old, $new); - } - } - - /** - * @return bool - */ - static public function isAvailable() { - if (!extension_loaded('apcu')) { - return false; - } elseif (!\OC::$server->getIniWrapper()->getBool('apc.enabled')) { - return false; - } elseif (!\OC::$server->getIniWrapper()->getBool('apc.enable_cli') && \OC::$CLI) { - return false; - } elseif ( - version_compare(phpversion('apc'), '4.0.6') === -1 && - version_compare(phpversion('apcu'), '5.1.0') === -1 - ) { - return false; - } else { - return true; - } - } -} diff --git a/lib/private/memcache/arraycache.php b/lib/private/memcache/arraycache.php deleted file mode 100644 index 837f888a307..00000000000 --- a/lib/private/memcache/arraycache.php +++ /dev/null @@ -1,158 +0,0 @@ - - * @author Morris Jobke - * @author Robin Appelman - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Memcache; - -use OCP\IMemcache; - -class ArrayCache extends Cache implements IMemcache { - /** @var array Array with the cached data */ - protected $cachedData = array(); - - use CADTrait; - - /** - * {@inheritDoc} - */ - public function get($key) { - if ($this->hasKey($key)) { - return $this->cachedData[$key]; - } - return null; - } - - /** - * {@inheritDoc} - */ - public function set($key, $value, $ttl = 0) { - $this->cachedData[$key] = $value; - return true; - } - - /** - * {@inheritDoc} - */ - public function hasKey($key) { - return isset($this->cachedData[$key]); - } - - /** - * {@inheritDoc} - */ - public function remove($key) { - unset($this->cachedData[$key]); - return true; - } - - /** - * {@inheritDoc} - */ - public function clear($prefix = '') { - if ($prefix === '') { - $this->cachedData = []; - return true; - } - - foreach ($this->cachedData as $key => $value) { - if (strpos($key, $prefix) === 0) { - $this->remove($key); - } - } - return true; - } - - /** - * Set a value in the cache if it's not already stored - * - * @param string $key - * @param mixed $value - * @param int $ttl Time To Live in seconds. Defaults to 60*60*24 - * @return bool - */ - public function add($key, $value, $ttl = 0) { - // since this cache is not shared race conditions aren't an issue - if ($this->hasKey($key)) { - return false; - } else { - return $this->set($key, $value, $ttl); - } - } - - /** - * Increase a stored number - * - * @param string $key - * @param int $step - * @return int | bool - */ - public function inc($key, $step = 1) { - $oldValue = $this->get($key); - if (is_int($oldValue)) { - $this->set($key, $oldValue + $step); - return $oldValue + $step; - } else { - $success = $this->add($key, $step); - return ($success) ? $step : false; - } - } - - /** - * Decrease a stored number - * - * @param string $key - * @param int $step - * @return int | bool - */ - public function dec($key, $step = 1) { - $oldValue = $this->get($key); - if (is_int($oldValue)) { - $this->set($key, $oldValue - $step); - return $oldValue - $step; - } else { - return false; - } - } - - /** - * Compare and set - * - * @param string $key - * @param mixed $old - * @param mixed $new - * @return bool - */ - public function cas($key, $old, $new) { - if ($this->get($key) === $old) { - return $this->set($key, $new); - } else { - return false; - } - } - - /** - * {@inheritDoc} - */ - static public function isAvailable() { - return true; - } -} diff --git a/lib/private/memcache/cache.php b/lib/private/memcache/cache.php deleted file mode 100644 index 63d20721aac..00000000000 --- a/lib/private/memcache/cache.php +++ /dev/null @@ -1,96 +0,0 @@ - - * @author Morris Jobke - * @author Robin Appelman - * @author Robin McCorkell - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Memcache; - -abstract class Cache implements \ArrayAccess, \OCP\ICache { - /** - * @var string $prefix - */ - protected $prefix; - - /** - * @param string $prefix - */ - public function __construct($prefix = '') { - $this->prefix = $prefix; - } - - /** - * @return string Prefix used for caching purposes - */ - public function getPrefix() { - return $this->prefix; - } - - /** - * @param string $key - * @return mixed - */ - abstract public function get($key); - - /** - * @param string $key - * @param mixed $value - * @param int $ttl - * @return mixed - */ - abstract public function set($key, $value, $ttl = 0); - - /** - * @param string $key - * @return mixed - */ - abstract public function hasKey($key); - - /** - * @param string $key - * @return mixed - */ - abstract public function remove($key); - - /** - * @param string $prefix - * @return mixed - */ - abstract public function clear($prefix = ''); - - //implement the ArrayAccess interface - - public function offsetExists($offset) { - return $this->hasKey($offset); - } - - public function offsetSet($offset, $value) { - $this->set($offset, $value); - } - - public function offsetGet($offset) { - return $this->get($offset); - } - - public function offsetUnset($offset) { - $this->remove($offset); - } -} diff --git a/lib/private/memcache/cadtrait.php b/lib/private/memcache/cadtrait.php deleted file mode 100644 index d44d98cba0b..00000000000 --- a/lib/private/memcache/cadtrait.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Memcache; - -trait CADTrait { - abstract public function get($key); - - abstract public function remove($key); - - abstract public function add($key, $value, $ttl = 0); - - /** - * Compare and delete - * - * @param string $key - * @param mixed $old - * @return bool - */ - public function cad($key, $old) { - //no native cas, emulate with locking - if ($this->add($key . '_lock', true)) { - if ($this->get($key) === $old) { - $this->remove($key); - $this->remove($key . '_lock'); - return true; - } else { - $this->remove($key . '_lock'); - return false; - } - } else { - return false; - } - } -} diff --git a/lib/private/memcache/castrait.php b/lib/private/memcache/castrait.php deleted file mode 100644 index 43253fc966b..00000000000 --- a/lib/private/memcache/castrait.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Memcache; - -trait CASTrait { - abstract public function get($key); - - abstract public function set($key, $value, $ttl = 0); - - abstract public function remove($key); - - abstract public function add($key, $value, $ttl = 0); - - /** - * Compare and set - * - * @param string $key - * @param mixed $old - * @param mixed $new - * @return bool - */ - public function cas($key, $old, $new) { - //no native cas, emulate with locking - if ($this->add($key . '_lock', true)) { - if ($this->get($key) === $old) { - $this->set($key, $new); - $this->remove($key . '_lock'); - return true; - } else { - $this->remove($key . '_lock'); - return false; - } - } else { - return false; - } - } -} diff --git a/lib/private/memcache/factory.php b/lib/private/memcache/factory.php deleted file mode 100644 index a005f319b3e..00000000000 --- a/lib/private/memcache/factory.php +++ /dev/null @@ -1,189 +0,0 @@ - - * @author Lukas Reschke - * @author Markus Goetz - * @author Morris Jobke - * @author Robin Appelman - * @author Robin McCorkell - * @author Thomas Müller - * @author Vincent Petry - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Memcache; - -use \OCP\ICacheFactory; -use \OCP\ILogger; - -class Factory implements ICacheFactory { - const NULL_CACHE = '\\OC\\Memcache\\NullCache'; - - /** - * @var string $globalPrefix - */ - private $globalPrefix; - - /** - * @var ILogger $logger - */ - private $logger; - - /** - * @var string $localCacheClass - */ - private $localCacheClass; - - /** - * @var string $distributedCacheClass - */ - private $distributedCacheClass; - - /** - * @var string $lockingCacheClass - */ - private $lockingCacheClass; - - /** - * @param string $globalPrefix - * @param ILogger $logger - * @param string|null $localCacheClass - * @param string|null $distributedCacheClass - * @param string|null $lockingCacheClass - */ - public function __construct($globalPrefix, ILogger $logger, - $localCacheClass = null, $distributedCacheClass = null, $lockingCacheClass = null) - { - $this->logger = $logger; - $this->globalPrefix = $globalPrefix; - - if (!$localCacheClass) { - $localCacheClass = self::NULL_CACHE; - } - if (!$distributedCacheClass) { - $distributedCacheClass = $localCacheClass; - } - - $missingCacheMessage = 'Memcache {class} not available for {use} cache'; - $missingCacheHint = 'Is the matching PHP module installed and enabled?'; - if (!$localCacheClass::isAvailable()) { - if (\OC::$CLI && !defined('PHPUNIT_RUN')) { - // CLI should not hard-fail on broken memcache - $this->logger->info($missingCacheMessage, [ - 'class' => $localCacheClass, - 'use' => 'local', - 'app' => 'cli' - ]); - $localCacheClass = self::NULL_CACHE; - } else { - throw new \OC\HintException(strtr($missingCacheMessage, [ - '{class}' => $localCacheClass, '{use}' => 'local' - ]), $missingCacheHint); - } - } - if (!$distributedCacheClass::isAvailable()) { - if (\OC::$CLI && !defined('PHPUNIT_RUN')) { - // CLI should not hard-fail on broken memcache - $this->logger->info($missingCacheMessage, [ - 'class' => $distributedCacheClass, - 'use' => 'distributed', - 'app' => 'cli' - ]); - $distributedCacheClass = self::NULL_CACHE; - } else { - throw new \OC\HintException(strtr($missingCacheMessage, [ - '{class}' => $distributedCacheClass, '{use}' => 'distributed' - ]), $missingCacheHint); - } - } - if (!($lockingCacheClass && $lockingCacheClass::isAvailable())) { - // don't fallback since the fallback might not be suitable for storing lock - $lockingCacheClass = self::NULL_CACHE; - } - - $this->localCacheClass = $localCacheClass; - $this->distributedCacheClass = $distributedCacheClass; - $this->lockingCacheClass = $lockingCacheClass; - } - - /** - * create a cache instance for storing locks - * - * @param string $prefix - * @return \OCP\IMemcache - */ - public function createLocking($prefix = '') { - return new $this->lockingCacheClass($this->globalPrefix . '/' . $prefix); - } - - /** - * create a distributed cache instance - * - * @param string $prefix - * @return \OC\Memcache\Cache - */ - public function createDistributed($prefix = '') { - return new $this->distributedCacheClass($this->globalPrefix . '/' . $prefix); - } - - /** - * create a local cache instance - * - * @param string $prefix - * @return \OC\Memcache\Cache - */ - public function createLocal($prefix = '') { - return new $this->localCacheClass($this->globalPrefix . '/' . $prefix); - } - - /** - * @see \OC\Memcache\Factory::createDistributed() - * @param string $prefix - * @return \OC\Memcache\Cache - */ - public function create($prefix = '') { - return $this->createDistributed($prefix); - } - - /** - * check memcache availability - * - * @return bool - */ - public function isAvailable() { - return ($this->distributedCacheClass !== self::NULL_CACHE); - } - - /** - * @see \OC\Memcache\Factory::createLocal() - * @param string $prefix - * @return Cache - */ - public function createLowLatency($prefix = '') { - return $this->createLocal($prefix); - } - - /** - * check local memcache availability - * - * @return bool - */ - public function isAvailableLowLatency() { - return ($this->localCacheClass !== self::NULL_CACHE); - } -} diff --git a/lib/private/memcache/memcached.php b/lib/private/memcache/memcached.php deleted file mode 100644 index a30f9da7ed7..00000000000 --- a/lib/private/memcache/memcached.php +++ /dev/null @@ -1,189 +0,0 @@ - - * @author Bart Visscher - * @author Morris Jobke - * @author Robin Appelman - * @author Robin McCorkell - * @author Thomas Müller - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Memcache; - -use OCP\IMemcache; - -class Memcached extends Cache implements IMemcache { - use CASTrait; - - /** - * @var \Memcached $cache - */ - private static $cache = null; - - use CADTrait; - - public function __construct($prefix = '') { - parent::__construct($prefix); - if (is_null(self::$cache)) { - self::$cache = new \Memcached(); - $servers = \OC::$server->getSystemConfig()->getValue('memcached_servers'); - if (!$servers) { - $server = \OC::$server->getSystemConfig()->getValue('memcached_server'); - if ($server) { - $servers = array($server); - } else { - $servers = array(array('localhost', 11211)); - } - } - self::$cache->addServers($servers); - } - } - - /** - * entries in XCache gets namespaced to prevent collisions between owncloud instances and users - */ - protected function getNameSpace() { - return $this->prefix; - } - - public function get($key) { - $result = self::$cache->get($this->getNamespace() . $key); - if ($result === false and self::$cache->getResultCode() == \Memcached::RES_NOTFOUND) { - return null; - } else { - return $result; - } - } - - public function set($key, $value, $ttl = 0) { - if ($ttl > 0) { - $result = self::$cache->set($this->getNamespace() . $key, $value, $ttl); - } else { - $result = self::$cache->set($this->getNamespace() . $key, $value); - } - $this->verifyReturnCode(); - return $result; - } - - public function hasKey($key) { - self::$cache->get($this->getNamespace() . $key); - return self::$cache->getResultCode() === \Memcached::RES_SUCCESS; - } - - public function remove($key) { - $result= self::$cache->delete($this->getNamespace() . $key); - if (self::$cache->getResultCode() !== \Memcached::RES_NOTFOUND) { - $this->verifyReturnCode(); - } - return $result; - } - - public function clear($prefix = '') { - $prefix = $this->getNamespace() . $prefix; - $allKeys = self::$cache->getAllKeys(); - if ($allKeys === false) { - // newer Memcached doesn't like getAllKeys(), flush everything - self::$cache->flush(); - return true; - } - $keys = array(); - $prefixLength = strlen($prefix); - foreach ($allKeys as $key) { - if (substr($key, 0, $prefixLength) === $prefix) { - $keys[] = $key; - } - } - if (method_exists(self::$cache, 'deleteMulti')) { - self::$cache->deleteMulti($keys); - } else { - foreach ($keys as $key) { - self::$cache->delete($key); - } - } - return true; - } - - /** - * Set a value in the cache if it's not already stored - * - * @param string $key - * @param mixed $value - * @param int $ttl Time To Live in seconds. Defaults to 60*60*24 - * @return bool - * @throws \Exception - */ - public function add($key, $value, $ttl = 0) { - $result = self::$cache->add($this->getPrefix() . $key, $value, $ttl); - if (self::$cache->getResultCode() !== \Memcached::RES_NOTSTORED) { - $this->verifyReturnCode(); - } - return $result; - } - - /** - * Increase a stored number - * - * @param string $key - * @param int $step - * @return int | bool - */ - public function inc($key, $step = 1) { - $this->add($key, 0); - $result = self::$cache->increment($this->getPrefix() . $key, $step); - - if (self::$cache->getResultCode() !== \Memcached::RES_SUCCESS) { - return false; - } - - return $result; - } - - /** - * Decrease a stored number - * - * @param string $key - * @param int $step - * @return int | bool - */ - public function dec($key, $step = 1) { - $result = self::$cache->decrement($this->getPrefix() . $key, $step); - - if (self::$cache->getResultCode() !== \Memcached::RES_SUCCESS) { - return false; - } - - return $result; - } - - static public function isAvailable() { - return extension_loaded('memcached'); - } - - /** - * @throws \Exception - */ - private function verifyReturnCode() { - $code = self::$cache->getResultCode(); - if ($code === \Memcached::RES_SUCCESS) { - return; - } - $message = self::$cache->getResultMessage(); - throw new \Exception("Error $code interacting with memcached : $message"); - } -} diff --git a/lib/private/memcache/nullcache.php b/lib/private/memcache/nullcache.php deleted file mode 100644 index c490ca7e03c..00000000000 --- a/lib/private/memcache/nullcache.php +++ /dev/null @@ -1,72 +0,0 @@ - - * @author Robin Appelman - * @author Robin McCorkell - * @author Thomas Müller - * @author Vincent Petry - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Memcache; - -class NullCache extends Cache implements \OCP\IMemcache { - public function get($key) { - return null; - } - - public function set($key, $value, $ttl = 0) { - return true; - } - - public function hasKey($key) { - return false; - } - - public function remove($key) { - return true; - } - - public function add($key, $value, $ttl = 0) { - return true; - } - - public function inc($key, $step = 1) { - return true; - } - - public function dec($key, $step = 1) { - return true; - } - - public function cas($key, $old, $new) { - return true; - } - - public function cad($key, $old) { - return true; - } - - public function clear($prefix = '') { - return true; - } - - static public function isAvailable() { - return true; - } -} diff --git a/lib/private/memcache/redis.php b/lib/private/memcache/redis.php deleted file mode 100644 index b3444a2b4e9..00000000000 --- a/lib/private/memcache/redis.php +++ /dev/null @@ -1,208 +0,0 @@ - - * @author Jörn Friedrich Dreyer - * @author Lukas Reschke - * @author Michael Telatynski <7t3chguy@gmail.com> - * @author Morris Jobke - * @author Robin Appelman - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Memcache; - -use OCP\IMemcacheTTL; - -class Redis extends Cache implements IMemcacheTTL { - /** - * @var \Redis $cache - */ - private static $cache = null; - - public function __construct($prefix = '') { - parent::__construct($prefix); - if (is_null(self::$cache)) { - // TODO allow configuring a RedisArray, see https://github.com/nicolasff/phpredis/blob/master/arrays.markdown#redis-arrays - self::$cache = new \Redis(); - $config = \OC::$server->getSystemConfig()->getValue('redis', array()); - if (isset($config['host'])) { - $host = $config['host']; - } else { - $host = '127.0.0.1'; - } - if (isset($config['port'])) { - $port = $config['port']; - } else { - $port = 6379; - } - if (isset($config['timeout'])) { - $timeout = $config['timeout']; - } else { - $timeout = 0.0; // unlimited - } - - self::$cache->connect($host, $port, $timeout); - if(isset($config['password']) && $config['password'] !== '') { - self::$cache->auth($config['password']); - } - - if (isset($config['dbindex'])) { - self::$cache->select($config['dbindex']); - } - } - } - - /** - * entries in redis get namespaced to prevent collisions between ownCloud instances and users - */ - protected function getNameSpace() { - return $this->prefix; - } - - public function get($key) { - $result = self::$cache->get($this->getNamespace() . $key); - if ($result === false && !self::$cache->exists($this->getNamespace() . $key)) { - return null; - } else { - return json_decode($result, true); - } - } - - public function set($key, $value, $ttl = 0) { - if ($ttl > 0) { - return self::$cache->setex($this->getNamespace() . $key, $ttl, json_encode($value)); - } else { - return self::$cache->set($this->getNamespace() . $key, json_encode($value)); - } - } - - public function hasKey($key) { - return self::$cache->exists($this->getNamespace() . $key); - } - - public function remove($key) { - if (self::$cache->delete($this->getNamespace() . $key)) { - return true; - } else { - return false; - } - } - - public function clear($prefix = '') { - $prefix = $this->getNamespace() . $prefix . '*'; - $it = null; - self::$cache->setOption(\Redis::OPT_SCAN, \Redis::SCAN_RETRY); - while ($keys = self::$cache->scan($it, $prefix)) { - self::$cache->delete($keys); - } - return true; - } - - /** - * Set a value in the cache if it's not already stored - * - * @param string $key - * @param mixed $value - * @param int $ttl Time To Live in seconds. Defaults to 60*60*24 - * @return bool - */ - public function add($key, $value, $ttl = 0) { - // don't encode ints for inc/dec - if (!is_int($value)) { - $value = json_encode($value); - } - return self::$cache->setnx($this->getPrefix() . $key, $value); - } - - /** - * Increase a stored number - * - * @param string $key - * @param int $step - * @return int | bool - */ - public function inc($key, $step = 1) { - return self::$cache->incrBy($this->getNamespace() . $key, $step); - } - - /** - * Decrease a stored number - * - * @param string $key - * @param int $step - * @return int | bool - */ - public function dec($key, $step = 1) { - if (!$this->hasKey($key)) { - return false; - } - return self::$cache->decrBy($this->getNamespace() . $key, $step); - } - - /** - * Compare and set - * - * @param string $key - * @param mixed $old - * @param mixed $new - * @return bool - */ - public function cas($key, $old, $new) { - if (!is_int($new)) { - $new = json_encode($new); - } - self::$cache->watch($this->getNamespace() . $key); - if ($this->get($key) === $old) { - $result = self::$cache->multi() - ->set($this->getNamespace() . $key, $new) - ->exec(); - return ($result === false) ? false : true; - } - self::$cache->unwatch(); - return false; - } - - /** - * Compare and delete - * - * @param string $key - * @param mixed $old - * @return bool - */ - public function cad($key, $old) { - self::$cache->watch($this->getNamespace() . $key); - if ($this->get($key) === $old) { - $result = self::$cache->multi() - ->del($this->getNamespace() . $key) - ->exec(); - return ($result === false) ? false : true; - } - self::$cache->unwatch(); - return false; - } - - public function setTTL($key, $ttl) { - self::$cache->expire($this->getNamespace() . $key, $ttl); - } - - static public function isAvailable() { - return extension_loaded('redis') - && version_compare(phpversion('redis'), '2.2.5', '>='); - } -} - diff --git a/lib/private/memcache/xcache.php b/lib/private/memcache/xcache.php deleted file mode 100644 index e80901faadc..00000000000 --- a/lib/private/memcache/xcache.php +++ /dev/null @@ -1,134 +0,0 @@ - - * @author Bart Visscher - * @author Clark Tomlinson - * @author Morris Jobke - * @author Robin Appelman - * @author Thomas Müller - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Memcache; - -use OCP\IMemcache; - -/** - * See http://xcache.lighttpd.net/wiki/XcacheApi for provided constants and - * functions etc. - */ -class XCache extends Cache implements IMemcache { - use CASTrait; - - use CADTrait; - - /** - * entries in XCache gets namespaced to prevent collisions between ownCloud instances and users - */ - protected function getNameSpace() { - return $this->prefix; - } - - public function get($key) { - return xcache_get($this->getNamespace() . $key); - } - - public function set($key, $value, $ttl = 0) { - if ($ttl > 0) { - return xcache_set($this->getNamespace() . $key, $value, $ttl); - } else { - return xcache_set($this->getNamespace() . $key, $value); - } - } - - public function hasKey($key) { - return xcache_isset($this->getNamespace() . $key); - } - - public function remove($key) { - return xcache_unset($this->getNamespace() . $key); - } - - public function clear($prefix = '') { - if (function_exists('xcache_unset_by_prefix')) { - return xcache_unset_by_prefix($this->getNamespace() . $prefix); - } else { - // Since we can not clear by prefix, we just clear the whole cache. - xcache_clear_cache(\XC_TYPE_VAR, 0); - } - return true; - } - - /** - * Set a value in the cache if it's not already stored - * - * @param string $key - * @param mixed $value - * @param int $ttl Time To Live in seconds. Defaults to 60*60*24 - * @return bool - */ - public function add($key, $value, $ttl = 0) { - if ($this->hasKey($key)) { - return false; - } else { - return $this->set($key, $value, $ttl); - } - } - - /** - * Increase a stored number - * - * @param string $key - * @param int $step - * @return int | bool - */ - public function inc($key, $step = 1) { - return xcache_inc($this->getPrefix() . $key, $step); - } - - /** - * Decrease a stored number - * - * @param string $key - * @param int $step - * @return int | bool - */ - public function dec($key, $step = 1) { - return xcache_dec($this->getPrefix() . $key, $step); - } - - static public function isAvailable() { - if (!extension_loaded('xcache')) { - return false; - } - if (\OC::$CLI && !getenv('XCACHE_TEST')) { - return false; - } - if (!function_exists('xcache_unset_by_prefix') && \OC::$server->getIniWrapper()->getBool('xcache.admin.enable_auth')) { - // We do not want to use XCache if we can not clear it without - // using the administration function xcache_clear_cache() - // AND administration functions are password-protected. - return false; - } - $var_size = \OC::$server->getIniWrapper()->getBytes('xcache.var_size'); - if (!$var_size) { - return false; - } - return true; - } -} -- cgit v1.2.3