From: Philipp Holzer Date: Sun, 4 Aug 2019 08:26:53 +0000 (+0200) Subject: Rename *CacheDriver to *Cache because they don't act as driver anymore X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=86bf2ee45a7c7409dbc470b5b1706b19e7e40507;p=friendica.git Rename *CacheDriver to *Cache because they don't act as driver anymore --- diff --git a/src/Console/Cache.php b/src/Console/Cache.php index 7596ae6d51..5f508da7a8 100644 --- a/src/Console/Cache.php +++ b/src/Console/Cache.php @@ -4,7 +4,7 @@ namespace Friendica\Console; use Asika\SimpleConsole\CommandArgsException; use Friendica\App; -use Friendica\Core\Cache\ICacheDriver; +use Friendica\Core\Cache\ICache; use Friendica\Core\Config\Configuration; use Friendica\Factory\CacheDriverFactory; use RuntimeException; @@ -33,7 +33,7 @@ class Cache extends \Asika\SimpleConsole\Console private $cacheDriverName; /** - * @var ICacheDriver + * @var ICache */ private $cache; @@ -71,7 +71,7 @@ HELP; return $help; } - public function __construct(App\Mode $appMode, Configuration $config, ICacheDriver $cache, array $argv = null) + public function __construct(App\Mode $appMode, Configuration $config, ICache $cache, array $argv = null) { parent::__construct($argv); @@ -161,7 +161,7 @@ HELP; if (count($this->args) >= 3) { $key = $this->getArgument(1); $value = $this->getArgument(2); - $duration = intval($this->getArgument(3, ICacheDriver::FIVE_MINUTES)); + $duration = intval($this->getArgument(3, ICache::FIVE_MINUTES)); if (is_array($this->cache->get($key))) { throw new RuntimeException("$key is an array and can't be set using this command."); diff --git a/src/Core/Cache.php b/src/Core/Cache.php index 0c5597aa5e..e469dcba10 100644 --- a/src/Core/Cache.php +++ b/src/Core/Cache.php @@ -5,31 +5,31 @@ namespace Friendica\Core; use Friendica\BaseObject; -use Friendica\Core\Cache\ICacheDriver; +use Friendica\Core\Cache\ICache; /** * @brief Class for storing data for a short time */ class Cache extends BaseObject { - /** @deprecated Use ICacheDriver::MONTH */ - const MONTH = ICacheDriver::MONTH; - /** @deprecated Use ICacheDriver::WEEK */ - const WEEK = 604800; - /** @deprecated Use ICacheDriver::DAY */ - const DAY = 86400; - /** @deprecated Use ICacheDriver::HOUR */ - const HOUR = 3600; - /** @deprecated Use ICacheDriver::HALF_HOUR */ - const HALF_HOUR = 1800; - /** @deprecated Use ICacheDriver::QUARTER_HOUR */ - const QUARTER_HOUR = 900; - /** @deprecated Use ICacheDriver::FIVE_MINUTES */ - const FIVE_MINUTES = 300; - /** @deprecated Use ICacheDriver::MINUTE */ - const MINUTE = 60; - /** @deprecated Use ICacheDriver::INFINITE */ - const INFINITE = 0; + /** @deprecated Use ICache::MONTH */ + const MONTH = ICache::MONTH; + /** @deprecated Use ICache::WEEK */ + const WEEK = ICache::WEEK; + /** @deprecated Use ICache::DAY */ + const DAY = ICache::DAY; + /** @deprecated Use ICache::HOUR */ + const HOUR = ICache::HOUR; + /** @deprecated Use ICache::HALF_HOUR */ + const HALF_HOUR = ICache::HALF_HOUR; + /** @deprecated Use ICache::QUARTER_HOUR */ + const QUARTER_HOUR = ICache::QUARTER_HOUR; + /** @deprecated Use ICache::FIVE_MINUTES */ + const FIVE_MINUTES = ICache::FIVE_MINUTES; + /** @deprecated Use ICache::MINUTE */ + const MINUTE = ICache::MINUTE; + /** @deprecated Use ICache::INFINITE */ + const INFINITE = ICache::INFINITE; /** * @brief Returns all the cache keys sorted alphabetically @@ -41,7 +41,7 @@ class Cache extends BaseObject */ public static function getAllKeys($prefix = null) { - return self::getClass(ICacheDriver::class)->getAllKeys($prefix); + return self::getClass(ICache::class)->getAllKeys($prefix); } /** @@ -54,7 +54,7 @@ class Cache extends BaseObject */ public static function get($key) { - return self::getClass(ICacheDriver::class)->get($key); + return self::getClass(ICache::class)->get($key); } /** @@ -69,9 +69,9 @@ class Cache extends BaseObject * @return bool * @throws \Exception */ - public static function set($key, $value, $duration = ICacheDriver::MONTH) + public static function set($key, $value, $duration = ICache::MONTH) { - return self::getClass(ICacheDriver::class)->set($key, $value, $duration); + return self::getClass(ICache::class)->set($key, $value, $duration); } /** @@ -84,7 +84,7 @@ class Cache extends BaseObject */ public static function delete($key) { - return self::getClass(ICacheDriver::class)->delete($key); + return self::getClass(ICache::class)->delete($key); } /** @@ -97,6 +97,6 @@ class Cache extends BaseObject */ public static function clear($outdated = true) { - return self::getClass(ICacheDriver::class)->clear($outdated); + return self::getClass(ICache::class)->clear($outdated); } } diff --git a/src/Core/Cache/APCuCache.php b/src/Core/Cache/APCuCache.php index b89d7fe4b3..350c8fa067 100644 --- a/src/Core/Cache/APCuCache.php +++ b/src/Core/Cache/APCuCache.php @@ -6,11 +6,11 @@ use Exception; use Friendica\Core\Cache; /** - * APCu Cache Driver. + * APCu Cache. * * @author Philipp Holzer */ -class APCuCache extends AbstractCacheDriver implements IMemoryCacheDriver +class APCuCache extends AbstractCache implements IMemoryCache { use TraitCompareSet; use TraitCompareDelete; diff --git a/src/Core/Cache/AbstractCache.php b/src/Core/Cache/AbstractCache.php new file mode 100644 index 0000000000..c60615f089 --- /dev/null +++ b/src/Core/Cache/AbstractCache.php @@ -0,0 +1,91 @@ +hostName = $hostName; + } + + /** + * Returns the prefix (to avoid namespace conflicts) + * + * @return string + * @throws \Exception + */ + protected function getPrefix() + { + // We fetch with the hostname as key to avoid problems with other applications + return $this->hostName; + } + + /** + * @param string $key The original key + * @return string The cache key used for the cache + * @throws \Exception + */ + protected function getCacheKey($key) + { + return $this->getPrefix() . ":" . $key; + } + + /** + * @param array $keys A list of cached keys + * @return array A list of original keys + */ + protected function getOriginalKeys($keys) + { + if (empty($keys)) { + return []; + } else { + // Keys are prefixed with the node hostname, let's remove it + array_walk($keys, function (&$value) { + $value = preg_replace('/^' . $this->hostName . ':/', '', $value); + }); + + sort($keys); + + return $keys; + } + } + + /** + * Filters the keys of an array with a given prefix + * Returns the filtered keys as an new array + * + * @param array $array The array, which should get filtered + * @param string|null $prefix The prefix (if null, all keys will get returned) + * + * @return array The filtered array with just the keys + */ + protected function filterArrayKeysByPrefix($array, $prefix = null) + { + if (empty($prefix)) { + return array_keys($array); + } else { + $result = []; + + foreach (array_keys($array) as $key) { + if (strpos($key, $prefix) === 0) { + array_push($result, $key); + } + } + + return $result; + } + } +} diff --git a/src/Core/Cache/AbstractCacheDriver.php b/src/Core/Cache/AbstractCacheDriver.php deleted file mode 100644 index e12f63bfa4..0000000000 --- a/src/Core/Cache/AbstractCacheDriver.php +++ /dev/null @@ -1,91 +0,0 @@ -hostName = $hostName; - } - - /** - * Returns the prefix (to avoid namespace conflicts) - * - * @return string - * @throws \Exception - */ - protected function getPrefix() - { - // We fetch with the hostname as key to avoid problems with other applications - return $this->hostName; - } - - /** - * @param string $key The original key - * @return string The cache key used for the cache - * @throws \Exception - */ - protected function getCacheKey($key) - { - return $this->getPrefix() . ":" . $key; - } - - /** - * @param array $keys A list of cached keys - * @return array A list of original keys - */ - protected function getOriginalKeys($keys) - { - if (empty($keys)) { - return []; - } else { - // Keys are prefixed with the node hostname, let's remove it - array_walk($keys, function (&$value) { - $value = preg_replace('/^' . $this->hostName . ':/', '', $value); - }); - - sort($keys); - - return $keys; - } - } - - /** - * Filters the keys of an array with a given prefix - * Returns the filtered keys as an new array - * - * @param array $array The array, which should get filtered - * @param string|null $prefix The prefix (if null, all keys will get returned) - * - * @return array The filtered array with just the keys - */ - protected function filterArrayKeysByPrefix($array, $prefix = null) - { - if (empty($prefix)) { - return array_keys($array); - } else { - $result = []; - - foreach (array_keys($array) as $key) { - if (strpos($key, $prefix) === 0) { - array_push($result, $key); - } - } - - return $result; - } - } -} diff --git a/src/Core/Cache/ArrayCache.php b/src/Core/Cache/ArrayCache.php index f2f37708de..76f867f700 100644 --- a/src/Core/Cache/ArrayCache.php +++ b/src/Core/Cache/ArrayCache.php @@ -5,13 +5,13 @@ namespace Friendica\Core\Cache; use Friendica\Core\Cache; /** - * Implementation of the IMemoryCacheDriver mainly for testing purpose + * Implementation of the IMemoryCache mainly for testing purpose * * Class ArrayCache * * @package Friendica\Core\Cache */ -class ArrayCache extends AbstractCacheDriver implements IMemoryCacheDriver +class ArrayCache extends AbstractCache implements IMemoryCache { use TraitCompareDelete; diff --git a/src/Core/Cache/DatabaseCache.php b/src/Core/Cache/DatabaseCache.php new file mode 100644 index 0000000000..0289ada867 --- /dev/null +++ b/src/Core/Cache/DatabaseCache.php @@ -0,0 +1,113 @@ + + */ +class DatabaseCache extends AbstractCache implements ICache +{ + /** + * @var Database + */ + private $dba; + + public function __construct(string $hostname, Database $dba) + { + parent::__construct($hostname); + + $this->dba = $dba; + } + + /** + * (@inheritdoc) + */ + public function getAllKeys($prefix = null) + { + if (empty($prefix)) { + $where = ['`expires` >= ?', DateTimeFormat::utcNow()]; + } else { + $where = ['`expires` >= ? AND `k` LIKE CONCAT(?, \'%\')', DateTimeFormat::utcNow(), $prefix]; + } + + $stmt = $this->dba->select('cache', ['k'], $where); + + $keys = []; + while ($key = $this->dba->fetch($stmt)) { + array_push($keys, $key['k']); + } + $this->dba->close($stmt); + + return $keys; + } + + /** + * (@inheritdoc) + */ + public function get($key) + { + $cache = $this->dba->selectFirst('cache', ['v'], ['`k` = ? AND (`expires` >= ? OR `expires` = -1)', $key, DateTimeFormat::utcNow()]); + + if ($this->dba->isResult($cache)) { + $cached = $cache['v']; + $value = @unserialize($cached); + + // Only return a value if the serialized value is valid. + // We also check if the db entry is a serialized + // boolean 'false' value (which we want to return). + if ($cached === serialize(false) || $value !== false) { + return $value; + } + } + + return null; + } + + /** + * (@inheritdoc) + */ + public function set($key, $value, $ttl = Cache::FIVE_MINUTES) + { + if ($ttl > 0) { + $fields = [ + 'v' => serialize($value), + 'expires' => DateTimeFormat::utc('now + ' . $ttl . 'seconds'), + 'updated' => DateTimeFormat::utcNow() + ]; + } else { + $fields = [ + 'v' => serialize($value), + 'expires' => -1, + 'updated' => DateTimeFormat::utcNow() + ]; + } + + return $this->dba->update('cache', $fields, ['k' => $key], true); + } + + /** + * (@inheritdoc) + */ + public function delete($key) + { + return $this->dba->delete('cache', ['k' => $key]); + } + + /** + * (@inheritdoc) + */ + public function clear($outdated = true) + { + if ($outdated) { + return $this->dba->delete('cache', ['`expires` < NOW()']); + } else { + return $this->dba->delete('cache', ['`k` IS NOT NULL ']); + } + } +} diff --git a/src/Core/Cache/DatabaseCacheDriver.php b/src/Core/Cache/DatabaseCacheDriver.php deleted file mode 100644 index f1d6150701..0000000000 --- a/src/Core/Cache/DatabaseCacheDriver.php +++ /dev/null @@ -1,113 +0,0 @@ - - */ -class DatabaseCacheDriver extends AbstractCacheDriver implements ICacheDriver -{ - /** - * @var Database - */ - private $dba; - - public function __construct(string $hostname, Database $dba) - { - parent::__construct($hostname); - - $this->dba = $dba; - } - - /** - * (@inheritdoc) - */ - public function getAllKeys($prefix = null) - { - if (empty($prefix)) { - $where = ['`expires` >= ?', DateTimeFormat::utcNow()]; - } else { - $where = ['`expires` >= ? AND `k` LIKE CONCAT(?, \'%\')', DateTimeFormat::utcNow(), $prefix]; - } - - $stmt = $this->dba->select('cache', ['k'], $where); - - $keys = []; - while ($key = $this->dba->fetch($stmt)) { - array_push($keys, $key['k']); - } - $this->dba->close($stmt); - - return $keys; - } - - /** - * (@inheritdoc) - */ - public function get($key) - { - $cache = $this->dba->selectFirst('cache', ['v'], ['`k` = ? AND (`expires` >= ? OR `expires` = -1)', $key, DateTimeFormat::utcNow()]); - - if ($this->dba->isResult($cache)) { - $cached = $cache['v']; - $value = @unserialize($cached); - - // Only return a value if the serialized value is valid. - // We also check if the db entry is a serialized - // boolean 'false' value (which we want to return). - if ($cached === serialize(false) || $value !== false) { - return $value; - } - } - - return null; - } - - /** - * (@inheritdoc) - */ - public function set($key, $value, $ttl = Cache::FIVE_MINUTES) - { - if ($ttl > 0) { - $fields = [ - 'v' => serialize($value), - 'expires' => DateTimeFormat::utc('now + ' . $ttl . 'seconds'), - 'updated' => DateTimeFormat::utcNow() - ]; - } else { - $fields = [ - 'v' => serialize($value), - 'expires' => -1, - 'updated' => DateTimeFormat::utcNow() - ]; - } - - return $this->dba->update('cache', $fields, ['k' => $key], true); - } - - /** - * (@inheritdoc) - */ - public function delete($key) - { - return $this->dba->delete('cache', ['k' => $key]); - } - - /** - * (@inheritdoc) - */ - public function clear($outdated = true) - { - if ($outdated) { - return $this->dba->delete('cache', ['`expires` < NOW()']); - } else { - return $this->dba->delete('cache', ['`k` IS NOT NULL ']); - } - } -} diff --git a/src/Core/Cache/ICache.php b/src/Core/Cache/ICache.php new file mode 100644 index 0000000000..f57e105cc0 --- /dev/null +++ b/src/Core/Cache/ICache.php @@ -0,0 +1,67 @@ + + */ +interface ICache +{ + const MONTH = 2592000; + const WEEK = 604800; + const DAY = 86400; + const HOUR = 3600; + const HALF_HOUR = 1800; + const QUARTER_HOUR = 900; + const FIVE_MINUTES = 300; + const MINUTE = 60; + const INFINITE = 0; + + /** + * Lists all cache keys + * + * @param string prefix optional a prefix to search + * + * @return array Empty if it isn't supported by the cache driver + */ + public function getAllKeys($prefix = null); + + /** + * Fetches cached data according to the key + * + * @param string $key The key to the cached data + * + * @return mixed Cached $value or "null" if not found + */ + public function get($key); + + /** + * Stores data in the cache identified by the key. The input $value can have multiple formats. + * + * @param string $key The cache key + * @param mixed $value The value to store + * @param integer $ttl The cache lifespan, must be one of the Cache constants + * + * @return bool + */ + public function set($key, $value, $ttl = self::FIVE_MINUTES); + + /** + * Delete a key from the cache + * + * @param string $key The cache key + * + * @return bool + */ + public function delete($key); + + /** + * Remove outdated data from the cache + * @param boolean $outdated just remove outdated values + * + * @return bool + */ + public function clear($outdated = true); +} diff --git a/src/Core/Cache/ICacheDriver.php b/src/Core/Cache/ICacheDriver.php deleted file mode 100644 index 34b741968a..0000000000 --- a/src/Core/Cache/ICacheDriver.php +++ /dev/null @@ -1,67 +0,0 @@ - - */ -interface ICacheDriver -{ - const MONTH = 2592000; - const WEEK = 604800; - const DAY = 86400; - const HOUR = 3600; - const HALF_HOUR = 1800; - const QUARTER_HOUR = 900; - const FIVE_MINUTES = 300; - const MINUTE = 60; - const INFINITE = 0; - - /** - * Lists all cache keys - * - * @param string prefix optional a prefix to search - * - * @return array Empty if it isn't supported by the cache driver - */ - public function getAllKeys($prefix = null); - - /** - * Fetches cached data according to the key - * - * @param string $key The key to the cached data - * - * @return mixed Cached $value or "null" if not found - */ - public function get($key); - - /** - * Stores data in the cache identified by the key. The input $value can have multiple formats. - * - * @param string $key The cache key - * @param mixed $value The value to store - * @param integer $ttl The cache lifespan, must be one of the Cache constants - * - * @return bool - */ - public function set($key, $value, $ttl = self::FIVE_MINUTES); - - /** - * Delete a key from the cache - * - * @param string $key The cache key - * - * @return bool - */ - public function delete($key); - - /** - * Remove outdated data from the cache - * @param boolean $outdated just remove outdated values - * - * @return bool - */ - public function clear($outdated = true); -} diff --git a/src/Core/Cache/IMemoryCache.php b/src/Core/Cache/IMemoryCache.php new file mode 100644 index 0000000000..939e545741 --- /dev/null +++ b/src/Core/Cache/IMemoryCache.php @@ -0,0 +1,44 @@ + + */ +class MemcacheCache extends AbstractCache implements IMemoryCache +{ + use TraitCompareSet; + use TraitCompareDelete; + + /** + * @var Memcache + */ + private $memcache; + + /** + * @throws Exception + */ + public function __construct(string $hostname, Configuration $config) + { + if (!class_exists('Memcache', false)) { + throw new Exception('Memcache class isn\'t available'); + } + + parent::__construct($hostname); + + $this->memcache = new Memcache(); + + $memcache_host = $config->get('system', 'memcache_host'); + $memcache_port = $config->get('system', 'memcache_port'); + + if (!$this->memcache->connect($memcache_host, $memcache_port)) { + throw new Exception('Expected Memcache server at ' . $memcache_host . ':' . $memcache_port . ' isn\'t available'); + } + } + + /** + * (@inheritdoc) + */ + public function getAllKeys($prefix = null) + { + $keys = []; + $allSlabs = $this->memcache->getExtendedStats('slabs'); + foreach ($allSlabs as $slabs) { + foreach (array_keys($slabs) as $slabId) { + $cachedump = $this->memcache->getExtendedStats('cachedump', (int)$slabId); + foreach ($cachedump as $key => $arrVal) { + if (!is_array($arrVal)) { + continue; + } + $keys = array_merge($keys, array_keys($arrVal)); + } + } + } + + $keys = $this->getOriginalKeys($keys); + + return $this->filterArrayKeysByPrefix($keys, $prefix); + } + + /** + * (@inheritdoc) + */ + public function get($key) + { + $return = null; + $cachekey = $this->getCacheKey($key); + + // We fetch with the hostname as key to avoid problems with other applications + $cached = $this->memcache->get($cachekey); + + // @see http://php.net/manual/en/memcache.get.php#84275 + if (is_bool($cached) || is_double($cached) || is_long($cached)) { + return $return; + } + + $value = @unserialize($cached); + + // Only return a value if the serialized value is valid. + // We also check if the db entry is a serialized + // boolean 'false' value (which we want to return). + if ($cached === serialize(false) || $value !== false) { + $return = $value; + } + + return $return; + } + + /** + * (@inheritdoc) + */ + public function set($key, $value, $ttl = Cache::FIVE_MINUTES) + { + $cachekey = $this->getCacheKey($key); + + // We store with the hostname as key to avoid problems with other applications + if ($ttl > 0) { + return $this->memcache->set( + $cachekey, + serialize($value), + MEMCACHE_COMPRESSED, + time() + $ttl + ); + } else { + return $this->memcache->set( + $cachekey, + serialize($value), + MEMCACHE_COMPRESSED + ); + } + } + + /** + * (@inheritdoc) + */ + public function delete($key) + { + $cachekey = $this->getCacheKey($key); + return $this->memcache->delete($cachekey); + } + + /** + * (@inheritdoc) + */ + public function clear($outdated = true) + { + if ($outdated) { + return true; + } else { + return $this->memcache->flush(); + } + } + + /** + * (@inheritdoc) + */ + public function add($key, $value, $ttl = Cache::FIVE_MINUTES) + { + $cachekey = $this->getCacheKey($key); + return $this->memcache->add($cachekey, serialize($value), MEMCACHE_COMPRESSED, $ttl); + } +} diff --git a/src/Core/Cache/MemcacheCacheDriver.php b/src/Core/Cache/MemcacheCacheDriver.php deleted file mode 100644 index bf8c34a416..0000000000 --- a/src/Core/Cache/MemcacheCacheDriver.php +++ /dev/null @@ -1,151 +0,0 @@ - - */ -class MemcacheCacheDriver extends AbstractCacheDriver implements IMemoryCacheDriver -{ - use TraitCompareSet; - use TraitCompareDelete; - - /** - * @var Memcache - */ - private $memcache; - - /** - * @throws Exception - */ - public function __construct(string $hostname, Configuration $config) - { - if (!class_exists('Memcache', false)) { - throw new Exception('Memcache class isn\'t available'); - } - - parent::__construct($hostname); - - $this->memcache = new Memcache(); - - $memcache_host = $config->get('system', 'memcache_host'); - $memcache_port = $config->get('system', 'memcache_port'); - - if (!$this->memcache->connect($memcache_host, $memcache_port)) { - throw new Exception('Expected Memcache server at ' . $memcache_host . ':' . $memcache_port . ' isn\'t available'); - } - } - - /** - * (@inheritdoc) - */ - public function getAllKeys($prefix = null) - { - $keys = []; - $allSlabs = $this->memcache->getExtendedStats('slabs'); - foreach ($allSlabs as $slabs) { - foreach (array_keys($slabs) as $slabId) { - $cachedump = $this->memcache->getExtendedStats('cachedump', (int)$slabId); - foreach ($cachedump as $key => $arrVal) { - if (!is_array($arrVal)) { - continue; - } - $keys = array_merge($keys, array_keys($arrVal)); - } - } - } - - $keys = $this->getOriginalKeys($keys); - - return $this->filterArrayKeysByPrefix($keys, $prefix); - } - - /** - * (@inheritdoc) - */ - public function get($key) - { - $return = null; - $cachekey = $this->getCacheKey($key); - - // We fetch with the hostname as key to avoid problems with other applications - $cached = $this->memcache->get($cachekey); - - // @see http://php.net/manual/en/memcache.get.php#84275 - if (is_bool($cached) || is_double($cached) || is_long($cached)) { - return $return; - } - - $value = @unserialize($cached); - - // Only return a value if the serialized value is valid. - // We also check if the db entry is a serialized - // boolean 'false' value (which we want to return). - if ($cached === serialize(false) || $value !== false) { - $return = $value; - } - - return $return; - } - - /** - * (@inheritdoc) - */ - public function set($key, $value, $ttl = Cache::FIVE_MINUTES) - { - $cachekey = $this->getCacheKey($key); - - // We store with the hostname as key to avoid problems with other applications - if ($ttl > 0) { - return $this->memcache->set( - $cachekey, - serialize($value), - MEMCACHE_COMPRESSED, - time() + $ttl - ); - } else { - return $this->memcache->set( - $cachekey, - serialize($value), - MEMCACHE_COMPRESSED - ); - } - } - - /** - * (@inheritdoc) - */ - public function delete($key) - { - $cachekey = $this->getCacheKey($key); - return $this->memcache->delete($cachekey); - } - - /** - * (@inheritdoc) - */ - public function clear($outdated = true) - { - if ($outdated) { - return true; - } else { - return $this->memcache->flush(); - } - } - - /** - * (@inheritdoc) - */ - public function add($key, $value, $ttl = Cache::FIVE_MINUTES) - { - $cachekey = $this->getCacheKey($key); - return $this->memcache->add($cachekey, serialize($value), MEMCACHE_COMPRESSED, $ttl); - } -} diff --git a/src/Core/Cache/MemcachedCache.php b/src/Core/Cache/MemcachedCache.php new file mode 100644 index 0000000000..f841cae2ce --- /dev/null +++ b/src/Core/Cache/MemcachedCache.php @@ -0,0 +1,154 @@ + + */ +class MemcachedCache extends AbstractCache implements IMemoryCache +{ + use TraitCompareSet; + use TraitCompareDelete; + + /** + * @var \Memcached + */ + private $memcached; + + /** + * @var LoggerInterface + */ + private $logger; + + /** + * Due to limitations of the INI format, the expected configuration for Memcached servers is the following: + * array { + * 0 => "hostname, port(, weight)", + * 1 => ... + * } + * + * @param array $memcached_hosts + * @throws \Exception + */ + public function __construct(string $hostname, Configuration $config, LoggerInterface $logger) + { + if (!class_exists('Memcached', false)) { + throw new Exception('Memcached class isn\'t available'); + } + + parent::__construct($hostname); + + $this->logger = $logger; + + $this->memcached = new Memcached(); + + $memcached_hosts = $config->get('system', 'memcached_hosts'); + + array_walk($memcached_hosts, function (&$value) { + if (is_string($value)) { + $value = array_map('trim', explode(',', $value)); + } + }); + + $this->memcached->addServers($memcached_hosts); + + if (count($this->memcached->getServerList()) == 0) { + throw new Exception('Expected Memcached servers aren\'t available, config:' . var_export($memcached_hosts, true)); + } + } + + /** + * (@inheritdoc) + */ + public function getAllKeys($prefix = null) + { + $keys = $this->getOriginalKeys($this->memcached->getAllKeys()); + + if ($this->memcached->getResultCode() == Memcached::RES_SUCCESS) { + return $this->filterArrayKeysByPrefix($keys, $prefix); + } else { + $this->logger->debug('Memcached \'getAllKeys\' failed', ['result' => $this->memcached->getResultMessage()]); + return []; + } + } + + /** + * (@inheritdoc) + */ + public function get($key) + { + $return = null; + $cachekey = $this->getCacheKey($key); + + // We fetch with the hostname as key to avoid problems with other applications + $value = $this->memcached->get($cachekey); + + if ($this->memcached->getResultCode() === Memcached::RES_SUCCESS) { + $return = $value; + } else { + $this->logger->debug('Memcached \'get\' failed', ['result' => $this->memcached->getResultMessage()]); + } + + return $return; + } + + /** + * (@inheritdoc) + */ + public function set($key, $value, $ttl = Cache::FIVE_MINUTES) + { + $cachekey = $this->getCacheKey($key); + + // We store with the hostname as key to avoid problems with other applications + if ($ttl > 0) { + return $this->memcached->set( + $cachekey, + $value, + $ttl + ); + } else { + return $this->memcached->set( + $cachekey, + $value + ); + } + } + + /** + * (@inheritdoc) + */ + public function delete($key) + { + $cachekey = $this->getCacheKey($key); + return $this->memcached->delete($cachekey); + } + + /** + * (@inheritdoc) + */ + public function clear($outdated = true) + { + if ($outdated) { + return true; + } else { + return $this->memcached->flush(); + } + } + + /** + * (@inheritdoc) + */ + public function add($key, $value, $ttl = Cache::FIVE_MINUTES) + { + $cachekey = $this->getCacheKey($key); + return $this->memcached->add($cachekey, $value, $ttl); + } +} diff --git a/src/Core/Cache/MemcachedCacheDriver.php b/src/Core/Cache/MemcachedCacheDriver.php deleted file mode 100644 index 7b3a2d5dfa..0000000000 --- a/src/Core/Cache/MemcachedCacheDriver.php +++ /dev/null @@ -1,154 +0,0 @@ - - */ -class MemcachedCacheDriver extends AbstractCacheDriver implements IMemoryCacheDriver -{ - use TraitCompareSet; - use TraitCompareDelete; - - /** - * @var \Memcached - */ - private $memcached; - - /** - * @var LoggerInterface - */ - private $logger; - - /** - * Due to limitations of the INI format, the expected configuration for Memcached servers is the following: - * array { - * 0 => "hostname, port(, weight)", - * 1 => ... - * } - * - * @param array $memcached_hosts - * @throws \Exception - */ - public function __construct(string $hostname, Configuration $config, LoggerInterface $logger) - { - if (!class_exists('Memcached', false)) { - throw new Exception('Memcached class isn\'t available'); - } - - parent::__construct($hostname); - - $this->logger = $logger; - - $this->memcached = new Memcached(); - - $memcached_hosts = $config->get('system', 'memcached_hosts'); - - array_walk($memcached_hosts, function (&$value) { - if (is_string($value)) { - $value = array_map('trim', explode(',', $value)); - } - }); - - $this->memcached->addServers($memcached_hosts); - - if (count($this->memcached->getServerList()) == 0) { - throw new Exception('Expected Memcached servers aren\'t available, config:' . var_export($memcached_hosts, true)); - } - } - - /** - * (@inheritdoc) - */ - public function getAllKeys($prefix = null) - { - $keys = $this->getOriginalKeys($this->memcached->getAllKeys()); - - if ($this->memcached->getResultCode() == Memcached::RES_SUCCESS) { - return $this->filterArrayKeysByPrefix($keys, $prefix); - } else { - $this->logger->debug('Memcached \'getAllKeys\' failed', ['result' => $this->memcached->getResultMessage()]); - return []; - } - } - - /** - * (@inheritdoc) - */ - public function get($key) - { - $return = null; - $cachekey = $this->getCacheKey($key); - - // We fetch with the hostname as key to avoid problems with other applications - $value = $this->memcached->get($cachekey); - - if ($this->memcached->getResultCode() === Memcached::RES_SUCCESS) { - $return = $value; - } else { - $this->logger->debug('Memcached \'get\' failed', ['result' => $this->memcached->getResultMessage()]); - } - - return $return; - } - - /** - * (@inheritdoc) - */ - public function set($key, $value, $ttl = Cache::FIVE_MINUTES) - { - $cachekey = $this->getCacheKey($key); - - // We store with the hostname as key to avoid problems with other applications - if ($ttl > 0) { - return $this->memcached->set( - $cachekey, - $value, - $ttl - ); - } else { - return $this->memcached->set( - $cachekey, - $value - ); - } - } - - /** - * (@inheritdoc) - */ - public function delete($key) - { - $cachekey = $this->getCacheKey($key); - return $this->memcached->delete($cachekey); - } - - /** - * (@inheritdoc) - */ - public function clear($outdated = true) - { - if ($outdated) { - return true; - } else { - return $this->memcached->flush(); - } - } - - /** - * (@inheritdoc) - */ - public function add($key, $value, $ttl = Cache::FIVE_MINUTES) - { - $cachekey = $this->getCacheKey($key); - return $this->memcached->add($cachekey, $value, $ttl); - } -} diff --git a/src/Core/Cache/ProfilerCache.php b/src/Core/Cache/ProfilerCache.php index 04271e7c69..72d72b2716 100644 --- a/src/Core/Cache/ProfilerCache.php +++ b/src/Core/Cache/ProfilerCache.php @@ -11,10 +11,10 @@ use Friendica\Util\Profiler; * * It is using the decorator pattern (@see */ -class ProfilerCache implements ICacheDriver, IMemoryCacheDriver +class ProfilerCache implements ICache, IMemoryCache { /** - * @var ICacheDriver The original cache driver + * @var ICache The original cache driver */ private $cache; @@ -23,7 +23,7 @@ class ProfilerCache implements ICacheDriver, IMemoryCacheDriver */ private $profiler; - public function __construct(ICacheDriver $cache, Profiler $profiler) + public function __construct(ICache $cache, Profiler $profiler) { $this->cache = $cache; $this->profiler = $profiler; @@ -104,7 +104,7 @@ class ProfilerCache implements ICacheDriver, IMemoryCacheDriver */ public function add($key, $value, $ttl = Cache::FIVE_MINUTES) { - if ($this->cache instanceof IMemoryCacheDriver) { + if ($this->cache instanceof IMemoryCache) { $time = microtime(true); $return = $this->cache->add($key, $value, $ttl); @@ -122,7 +122,7 @@ class ProfilerCache implements ICacheDriver, IMemoryCacheDriver */ public function compareSet($key, $oldValue, $newValue, $ttl = Cache::FIVE_MINUTES) { - if ($this->cache instanceof IMemoryCacheDriver) { + if ($this->cache instanceof IMemoryCache) { $time = microtime(true); $return = $this->cache->compareSet($key, $oldValue, $newValue, $ttl); @@ -140,7 +140,7 @@ class ProfilerCache implements ICacheDriver, IMemoryCacheDriver */ public function compareDelete($key, $value) { - if ($this->cache instanceof IMemoryCacheDriver) { + if ($this->cache instanceof IMemoryCache) { $time = microtime(true); $return = $this->cache->compareDelete($key, $value); diff --git a/src/Core/Cache/RedisCache.php b/src/Core/Cache/RedisCache.php new file mode 100644 index 0000000000..6f3a647c55 --- /dev/null +++ b/src/Core/Cache/RedisCache.php @@ -0,0 +1,195 @@ + + * @author Roland Haeder + */ +class RedisCache extends AbstractCache implements IMemoryCache +{ + /** + * @var Redis + */ + private $redis; + + /** + * @throws Exception + */ + public function __construct(string $hostname, Configuration $config) + { + if (!class_exists('Redis', false)) { + throw new Exception('Redis class isn\'t available'); + } + + parent::__construct($hostname); + + $this->redis = new Redis(); + + $redis_host = $config->get('system', 'redis_host'); + $redis_port = $config->get('system', 'redis_port'); + $redis_pw = $config->get('system', 'redis_password'); + $redis_db = $config->get('system', 'redis_db', 0); + + if (!$this->redis->connect($redis_host, $redis_port)) { + throw new Exception('Expected Redis server at ' . $redis_host . ':' . $redis_port . ' isn\'t available'); + } + + if (isset($redis_pw) && !$this->redis->auth($redis_pw)) { + throw new Exception('Cannot authenticate redis server at ' . $redis_host . ':' . $redis_port); + } + + if ($redis_db !== 0 && !$this->redis->select($redis_db)) { + throw new Exception('Cannot switch to redis db ' . $redis_db . ' at ' . $redis_host . ':' . $redis_port); + } + } + + /** + * (@inheritdoc) + */ + public function getAllKeys($prefix = null) + { + if (empty($prefix)) { + $search = '*'; + } else { + $search = $prefix . '*'; + } + + $list = $this->redis->keys($this->getCacheKey($search)); + + return $this->getOriginalKeys($list); + } + + /** + * (@inheritdoc) + */ + public function get($key) + { + $return = null; + $cachekey = $this->getCacheKey($key); + + $cached = $this->redis->get($cachekey); + if ($cached === false && !$this->redis->exists($cachekey)) { + return null; + } + + $value = unserialize($cached); + + // Only return a value if the serialized value is valid. + // We also check if the db entry is a serialized + // boolean 'false' value (which we want to return). + if ($cached === serialize(false) || $value !== false) { + $return = $value; + } + + return $return; + } + + /** + * (@inheritdoc) + */ + public function set($key, $value, $ttl = Cache::FIVE_MINUTES) + { + $cachekey = $this->getCacheKey($key); + + $cached = serialize($value); + + if ($ttl > 0) { + return $this->redis->setex( + $cachekey, + $ttl, + $cached + ); + } else { + return $this->redis->set( + $cachekey, + $cached + ); + } + } + + /** + * (@inheritdoc) + */ + public function delete($key) + { + $cachekey = $this->getCacheKey($key); + return ($this->redis->delete($cachekey) > 0); + } + + /** + * (@inheritdoc) + */ + public function clear($outdated = true) + { + if ($outdated) { + return true; + } else { + return $this->redis->flushAll(); + } + } + + /** + * (@inheritdoc) + */ + public function add($key, $value, $ttl = Cache::FIVE_MINUTES) + { + $cachekey = $this->getCacheKey($key); + $cached = serialize($value); + + return $this->redis->setnx($cachekey, $cached); + } + + /** + * (@inheritdoc) + */ + public function compareSet($key, $oldValue, $newValue, $ttl = Cache::FIVE_MINUTES) + { + $cachekey = $this->getCacheKey($key); + + $newCached = serialize($newValue); + + $this->redis->watch($cachekey); + // If the old value isn't what we expected, somebody else changed the key meanwhile + if ($this->get($key) === $oldValue) { + if ($ttl > 0) { + $result = $this->redis->multi() + ->setex($cachekey, $ttl, $newCached) + ->exec(); + } else { + $result = $this->redis->multi() + ->set($cachekey, $newCached) + ->exec(); + } + return $result !== false; + } + $this->redis->unwatch(); + return false; + } + + /** + * (@inheritdoc) + */ + public function compareDelete($key, $value) + { + $cachekey = $this->getCacheKey($key); + + $this->redis->watch($cachekey); + // If the old value isn't what we expected, somebody else changed the key meanwhile + if ($this->get($key) === $value) { + $result = $this->redis->multi() + ->del($cachekey) + ->exec(); + return $result !== false; + } + $this->redis->unwatch(); + return false; + } +} diff --git a/src/Core/Cache/RedisCacheDriver.php b/src/Core/Cache/RedisCacheDriver.php deleted file mode 100644 index 951f51dc13..0000000000 --- a/src/Core/Cache/RedisCacheDriver.php +++ /dev/null @@ -1,195 +0,0 @@ - - * @author Roland Haeder - */ -class RedisCacheDriver extends AbstractCacheDriver implements IMemoryCacheDriver -{ - /** - * @var Redis - */ - private $redis; - - /** - * @throws Exception - */ - public function __construct(string $hostname, Configuration $config) - { - if (!class_exists('Redis', false)) { - throw new Exception('Redis class isn\'t available'); - } - - parent::__construct($hostname); - - $this->redis = new Redis(); - - $redis_host = $config->get('system', 'redis_host'); - $redis_port = $config->get('system', 'redis_port'); - $redis_pw = $config->get('system', 'redis_password'); - $redis_db = $config->get('system', 'redis_db', 0); - - if (!$this->redis->connect($redis_host, $redis_port)) { - throw new Exception('Expected Redis server at ' . $redis_host . ':' . $redis_port . ' isn\'t available'); - } - - if (isset($redis_pw) && !$this->redis->auth($redis_pw)) { - throw new Exception('Cannot authenticate redis server at ' . $redis_host . ':' . $redis_port); - } - - if ($redis_db !== 0 && !$this->redis->select($redis_db)) { - throw new Exception('Cannot switch to redis db ' . $redis_db . ' at ' . $redis_host . ':' . $redis_port); - } - } - - /** - * (@inheritdoc) - */ - public function getAllKeys($prefix = null) - { - if (empty($prefix)) { - $search = '*'; - } else { - $search = $prefix . '*'; - } - - $list = $this->redis->keys($this->getCacheKey($search)); - - return $this->getOriginalKeys($list); - } - - /** - * (@inheritdoc) - */ - public function get($key) - { - $return = null; - $cachekey = $this->getCacheKey($key); - - $cached = $this->redis->get($cachekey); - if ($cached === false && !$this->redis->exists($cachekey)) { - return null; - } - - $value = unserialize($cached); - - // Only return a value if the serialized value is valid. - // We also check if the db entry is a serialized - // boolean 'false' value (which we want to return). - if ($cached === serialize(false) || $value !== false) { - $return = $value; - } - - return $return; - } - - /** - * (@inheritdoc) - */ - public function set($key, $value, $ttl = Cache::FIVE_MINUTES) - { - $cachekey = $this->getCacheKey($key); - - $cached = serialize($value); - - if ($ttl > 0) { - return $this->redis->setex( - $cachekey, - $ttl, - $cached - ); - } else { - return $this->redis->set( - $cachekey, - $cached - ); - } - } - - /** - * (@inheritdoc) - */ - public function delete($key) - { - $cachekey = $this->getCacheKey($key); - return ($this->redis->delete($cachekey) > 0); - } - - /** - * (@inheritdoc) - */ - public function clear($outdated = true) - { - if ($outdated) { - return true; - } else { - return $this->redis->flushAll(); - } - } - - /** - * (@inheritdoc) - */ - public function add($key, $value, $ttl = Cache::FIVE_MINUTES) - { - $cachekey = $this->getCacheKey($key); - $cached = serialize($value); - - return $this->redis->setnx($cachekey, $cached); - } - - /** - * (@inheritdoc) - */ - public function compareSet($key, $oldValue, $newValue, $ttl = Cache::FIVE_MINUTES) - { - $cachekey = $this->getCacheKey($key); - - $newCached = serialize($newValue); - - $this->redis->watch($cachekey); - // If the old value isn't what we expected, somebody else changed the key meanwhile - if ($this->get($key) === $oldValue) { - if ($ttl > 0) { - $result = $this->redis->multi() - ->setex($cachekey, $ttl, $newCached) - ->exec(); - } else { - $result = $this->redis->multi() - ->set($cachekey, $newCached) - ->exec(); - } - return $result !== false; - } - $this->redis->unwatch(); - return false; - } - - /** - * (@inheritdoc) - */ - public function compareDelete($key, $value) - { - $cachekey = $this->getCacheKey($key); - - $this->redis->watch($cachekey); - // If the old value isn't what we expected, somebody else changed the key meanwhile - if ($this->get($key) === $value) { - $result = $this->redis->multi() - ->del($cachekey) - ->exec(); - return $result !== false; - } - $this->redis->unwatch(); - return false; - } -} diff --git a/src/Core/Lock.php b/src/Core/Lock.php index 04dfaa1c5e..06313fdd2d 100644 --- a/src/Core/Lock.php +++ b/src/Core/Lock.php @@ -8,8 +8,8 @@ namespace Friendica\Core; use Friendica\BaseObject; -use Friendica\Core\Cache\ICacheDriver; -use Friendica\Core\Lock\ILockDriver; +use Friendica\Core\Cache\ICache; +use Friendica\Core\Lock\ILock; /** * This class contain Functions for preventing parallel execution of functions @@ -26,9 +26,9 @@ class Lock extends BaseObject * @return boolean Was the lock successful? * @throws \Exception */ - public static function acquire($key, $timeout = 120, $ttl = ICacheDriver::FIVE_MINUTES) + public static function acquire($key, $timeout = 120, $ttl = ICache::FIVE_MINUTES) { - return self::getClass(ILockDriver::class)->acquireLock($key, $timeout, $ttl); + return self::getClass(ILock::class)->acquireLock($key, $timeout, $ttl); } /** @@ -42,7 +42,7 @@ class Lock extends BaseObject */ public static function release($key, $override = false) { - return self::getClass(ILockDriver::class)->releaseLock($key, $override); + return self::getClass(ILock::class)->releaseLock($key, $override); } /** @@ -52,6 +52,6 @@ class Lock extends BaseObject */ public static function releaseAll() { - self::getClass(ILockDriver::class)->releaseAll(); + self::getClass(ILock::class)->releaseAll(); } } diff --git a/src/Core/Lock/AbstractLock.php b/src/Core/Lock/AbstractLock.php new file mode 100644 index 0000000000..31744a9245 --- /dev/null +++ b/src/Core/Lock/AbstractLock.php @@ -0,0 +1,68 @@ +acquireLock[$key]) && $this->acquiredLocks[$key] === true; + } + + /** + * Mark a locally acquired lock + * + * @param string $key The Name of the lock + */ + protected function markAcquire($key) + { + $this->acquiredLocks[$key] = true; + } + + /** + * Mark a release of a locally acquired lock + * + * @param string $key The Name of the lock + */ + protected function markRelease($key) + { + unset($this->acquiredLocks[$key]); + } + + /** + * Releases all lock that were set by us + * + * @return boolean Was the unlock of all locks successful? + */ + public function releaseAll() + { + $return = true; + + foreach ($this->acquiredLocks as $acquiredLock => $hasLock) { + if (!$this->releaseLock($acquiredLock)) { + $return = false; + } + } + + return $return; + } +} diff --git a/src/Core/Lock/AbstractLockDriver.php b/src/Core/Lock/AbstractLockDriver.php deleted file mode 100644 index 71ad08d088..0000000000 --- a/src/Core/Lock/AbstractLockDriver.php +++ /dev/null @@ -1,68 +0,0 @@ -acquireLock[$key]) && $this->acquiredLocks[$key] === true; - } - - /** - * Mark a locally acquired lock - * - * @param string $key The Name of the lock - */ - protected function markAcquire($key) - { - $this->acquiredLocks[$key] = true; - } - - /** - * Mark a release of a locally acquired lock - * - * @param string $key The Name of the lock - */ - protected function markRelease($key) - { - unset($this->acquiredLocks[$key]); - } - - /** - * Releases all lock that were set by us - * - * @return boolean Was the unlock of all locks successful? - */ - public function releaseAll() - { - $return = true; - - foreach ($this->acquiredLocks as $acquiredLock => $hasLock) { - if (!$this->releaseLock($acquiredLock)) { - $return = false; - } - } - - return $return; - } -} diff --git a/src/Core/Lock/CacheLockDriver.php b/src/Core/Lock/CacheLockDriver.php index 6169933ddc..69db1c27f8 100644 --- a/src/Core/Lock/CacheLockDriver.php +++ b/src/Core/Lock/CacheLockDriver.php @@ -3,21 +3,21 @@ namespace Friendica\Core\Lock; use Friendica\Core\Cache; -use Friendica\Core\Cache\IMemoryCacheDriver; +use Friendica\Core\Cache\IMemoryCache; -class CacheLockDriver extends AbstractLockDriver +class CacheLockDriver extends AbstractLock { /** - * @var \Friendica\Core\Cache\ICacheDriver; + * @var \Friendica\Core\Cache\ICache; */ private $cache; /** * CacheLockDriver constructor. * - * @param IMemoryCacheDriver $cache The CacheDriver for this type of lock + * @param IMemoryCache $cache The CacheDriver for this type of lock */ - public function __construct(IMemoryCacheDriver $cache) + public function __construct(IMemoryCache $cache) { $this->cache = $cache; } diff --git a/src/Core/Lock/DatabaseLock.php b/src/Core/Lock/DatabaseLock.php new file mode 100644 index 0000000000..e451f5acb0 --- /dev/null +++ b/src/Core/Lock/DatabaseLock.php @@ -0,0 +1,117 @@ +dba = $dba; + $this->pid = isset($pid) ? $pid : getmypid(); + } + + /** + * (@inheritdoc) + */ + public function acquireLock($key, $timeout = 120, $ttl = Cache::FIVE_MINUTES) + { + $got_lock = false; + $start = time(); + + do { + $this->dba->lock('locks'); + $lock = $this->dba->selectFirst('locks', ['locked', 'pid'], ['`name` = ? AND `expires` >= ?', $key, DateTimeFormat::utcNow()]); + + if ($this->dba->isResult($lock)) { + if ($lock['locked']) { + // We want to lock something that was already locked by us? So we got the lock. + if ($lock['pid'] == $this->pid) { + $got_lock = true; + } + } + if (!$lock['locked']) { + $this->dba->update('locks', ['locked' => true, 'pid' => $this->pid, 'expires' => DateTimeFormat::utc('now + ' . $ttl . 'seconds')], ['name' => $key]); + $got_lock = true; + } + } else { + $this->dba->insert('locks', ['name' => $key, 'locked' => true, 'pid' => $this->pid, 'expires' => DateTimeFormat::utc('now + ' . $ttl . 'seconds')]); + $got_lock = true; + $this->markAcquire($key); + } + + $this->dba->unlock(); + + if (!$got_lock && ($timeout > 0)) { + usleep(rand(100000, 2000000)); + } + } while (!$got_lock && ((time() - $start) < $timeout)); + + return $got_lock; + } + + /** + * (@inheritdoc) + */ + public function releaseLock($key, $override = false) + { + if ($override) { + $where = ['name' => $key]; + } else { + $where = ['name' => $key, 'pid' => $this->pid]; + } + + $return = $this->dba->delete('locks', $where); + + $this->markRelease($key); + + return $return; + } + + /** + * (@inheritdoc) + */ + public function releaseAll() + { + $return = $this->dba->delete('locks', ['pid' => $this->pid]); + + $this->acquiredLocks = []; + + return $return; + } + + /** + * (@inheritdoc) + */ + public function isLocked($key) + { + $lock = $this->dba->selectFirst('locks', ['locked'], ['`name` = ? AND `expires` >= ?', $key, DateTimeFormat::utcNow()]); + + if ($this->dba->isResult($lock)) { + return $lock['locked'] !== false; + } else { + return false; + } + } +} diff --git a/src/Core/Lock/DatabaseLockDriver.php b/src/Core/Lock/DatabaseLockDriver.php deleted file mode 100644 index e9e0500bb4..0000000000 --- a/src/Core/Lock/DatabaseLockDriver.php +++ /dev/null @@ -1,117 +0,0 @@ -dba = $dba; - $this->pid = isset($pid) ? $pid : getmypid(); - } - - /** - * (@inheritdoc) - */ - public function acquireLock($key, $timeout = 120, $ttl = Cache::FIVE_MINUTES) - { - $got_lock = false; - $start = time(); - - do { - $this->dba->lock('locks'); - $lock = $this->dba->selectFirst('locks', ['locked', 'pid'], ['`name` = ? AND `expires` >= ?', $key, DateTimeFormat::utcNow()]); - - if ($this->dba->isResult($lock)) { - if ($lock['locked']) { - // We want to lock something that was already locked by us? So we got the lock. - if ($lock['pid'] == $this->pid) { - $got_lock = true; - } - } - if (!$lock['locked']) { - $this->dba->update('locks', ['locked' => true, 'pid' => $this->pid, 'expires' => DateTimeFormat::utc('now + ' . $ttl . 'seconds')], ['name' => $key]); - $got_lock = true; - } - } else { - $this->dba->insert('locks', ['name' => $key, 'locked' => true, 'pid' => $this->pid, 'expires' => DateTimeFormat::utc('now + ' . $ttl . 'seconds')]); - $got_lock = true; - $this->markAcquire($key); - } - - $this->dba->unlock(); - - if (!$got_lock && ($timeout > 0)) { - usleep(rand(100000, 2000000)); - } - } while (!$got_lock && ((time() - $start) < $timeout)); - - return $got_lock; - } - - /** - * (@inheritdoc) - */ - public function releaseLock($key, $override = false) - { - if ($override) { - $where = ['name' => $key]; - } else { - $where = ['name' => $key, 'pid' => $this->pid]; - } - - $return = $this->dba->delete('locks', $where); - - $this->markRelease($key); - - return $return; - } - - /** - * (@inheritdoc) - */ - public function releaseAll() - { - $return = $this->dba->delete('locks', ['pid' => $this->pid]); - - $this->acquiredLocks = []; - - return $return; - } - - /** - * (@inheritdoc) - */ - public function isLocked($key) - { - $lock = $this->dba->selectFirst('locks', ['locked'], ['`name` = ? AND `expires` >= ?', $key, DateTimeFormat::utcNow()]); - - if ($this->dba->isResult($lock)) { - return $lock['locked'] !== false; - } else { - return false; - } - } -} diff --git a/src/Core/Lock/ILock.php b/src/Core/Lock/ILock.php new file mode 100644 index 0000000000..3c56369eb9 --- /dev/null +++ b/src/Core/Lock/ILock.php @@ -0,0 +1,51 @@ + + */ +interface ILock +{ + /** + * Checks, if a key is currently locked to a or my process + * + * @param string $key The name of the lock + * + * @return bool + */ + public function isLocked($key); + + /** + * + * Acquires a lock for a given name + * + * @param string $key The Name of the lock + * @param integer $timeout Seconds until we give up + * @param integer $ttl Seconds The lock lifespan, must be one of the Cache constants + * + * @return boolean Was the lock successful? + */ + public function acquireLock($key, $timeout = 120, $ttl = Cache\ICache::FIVE_MINUTES); + + /** + * Releases a lock if it was set by us + * + * @param string $key The Name of the lock + * @param bool $override Overrides the lock to get released + * + * @return boolean Was the unlock successful? + */ + public function releaseLock($key, $override = false); + + /** + * Releases all lock that were set by us + * + * @return boolean Was the unlock of all locks successful? + */ + public function releaseAll(); +} diff --git a/src/Core/Lock/ILockDriver.php b/src/Core/Lock/ILockDriver.php deleted file mode 100644 index 43793d6287..0000000000 --- a/src/Core/Lock/ILockDriver.php +++ /dev/null @@ -1,51 +0,0 @@ - - */ -interface ILockDriver -{ - /** - * Checks, if a key is currently locked to a or my process - * - * @param string $key The name of the lock - * - * @return bool - */ - public function isLocked($key); - - /** - * - * Acquires a lock for a given name - * - * @param string $key The Name of the lock - * @param integer $timeout Seconds until we give up - * @param integer $ttl Seconds The lock lifespan, must be one of the Cache constants - * - * @return boolean Was the lock successful? - */ - public function acquireLock($key, $timeout = 120, $ttl = Cache\ICacheDriver::FIVE_MINUTES); - - /** - * Releases a lock if it was set by us - * - * @param string $key The Name of the lock - * @param bool $override Overrides the lock to get released - * - * @return boolean Was the unlock successful? - */ - public function releaseLock($key, $override = false); - - /** - * Releases all lock that were set by us - * - * @return boolean Was the unlock of all locks successful? - */ - public function releaseAll(); -} diff --git a/src/Core/Lock/SemaphoreLock.php b/src/Core/Lock/SemaphoreLock.php new file mode 100644 index 0000000000..b791d8c392 --- /dev/null +++ b/src/Core/Lock/SemaphoreLock.php @@ -0,0 +1,72 @@ +markAcquire($key); + return true; + } + } + + return false; + } + + /** + * (@inheritdoc) + */ + public function releaseLock($key, $override = false) + { + if (empty(self::$semaphore[$key])) { + return false; + } else { + $success = @sem_release(self::$semaphore[$key]); + unset(self::$semaphore[$key]); + $this->markRelease($key); + return $success; + } + } + + /** + * (@inheritdoc) + */ + public function isLocked($key) + { + return isset(self::$semaphore[$key]); + } +} diff --git a/src/Core/Lock/SemaphoreLockDriver.php b/src/Core/Lock/SemaphoreLockDriver.php deleted file mode 100644 index 781e110b17..0000000000 --- a/src/Core/Lock/SemaphoreLockDriver.php +++ /dev/null @@ -1,72 +0,0 @@ -markAcquire($key); - return true; - } - } - - return false; - } - - /** - * (@inheritdoc) - */ - public function releaseLock($key, $override = false) - { - if (empty(self::$semaphore[$key])) { - return false; - } else { - $success = @sem_release(self::$semaphore[$key]); - unset(self::$semaphore[$key]); - $this->markRelease($key); - return $success; - } - } - - /** - * (@inheritdoc) - */ - public function isLocked($key) - { - return isset(self::$semaphore[$key]); - } -} diff --git a/src/Factory/CacheDriverFactory.php b/src/Factory/CacheDriverFactory.php index 6b4c878f12..f604a0507d 100644 --- a/src/Factory/CacheDriverFactory.php +++ b/src/Factory/CacheDriverFactory.php @@ -3,7 +3,7 @@ namespace Friendica\Factory; use Friendica\Core\Cache; -use Friendica\Core\Cache\ICacheDriver; +use Friendica\Core\Cache\ICache; use Friendica\Core\Config\Configuration; use Friendica\Database\Database; use Friendica\Util\BaseURL; @@ -61,7 +61,7 @@ class CacheDriverFactory /** * This method creates a CacheDriver for the given cache driver name * - * @return ICacheDriver The instance of the CacheDriver + * @return ICache The instance of the CacheDriver * @throws \Exception The exception if something went wrong during the CacheDriver creation */ public function create() @@ -70,19 +70,19 @@ class CacheDriverFactory switch ($driver) { case 'memcache': - $cache = new Cache\MemcacheCacheDriver($this->hostname, $this->config); + $cache = new Cache\MemcacheCache($this->hostname, $this->config); break; case 'memcached': - $cache = new Cache\MemcachedCacheDriver($this->hostname, $this->config, $this->logger); + $cache = new Cache\MemcachedCache($this->hostname, $this->config, $this->logger); break; case 'redis': - $cache = new Cache\RedisCacheDriver($this->hostname, $this->config); + $cache = new Cache\RedisCache($this->hostname, $this->config); break; case 'apcu': $cache = new Cache\APCuCache($this->hostname); break; default: - $cache = new Cache\DatabaseCacheDriver($this->hostname, $this->dba); + $cache = new Cache\DatabaseCache($this->hostname, $this->dba); } $profiling = $this->config->get('system', 'profiling', false); diff --git a/src/Factory/LockDriverFactory.php b/src/Factory/LockDriverFactory.php index d31728be6c..b0c87cfcec 100644 --- a/src/Factory/LockDriverFactory.php +++ b/src/Factory/LockDriverFactory.php @@ -2,8 +2,8 @@ namespace Friendica\Factory; -use Friendica\Core\Cache\ICacheDriver; -use Friendica\Core\Cache\IMemoryCacheDriver; +use Friendica\Core\Cache\ICache; +use Friendica\Core\Cache\IMemoryCache; use Friendica\Core\Config\Configuration; use Friendica\Core\Lock; use Friendica\Database\Database; @@ -35,7 +35,7 @@ class LockDriverFactory private $dba; /** - * @var ICacheDriver The memory cache driver in case we use it + * @var ICache The memory cache driver in case we use it */ private $cacheDriver; @@ -49,7 +49,7 @@ class LockDriverFactory */ private $logger; - public function __construct(ICacheDriver $cacheDriver, Configuration $config, Database $dba, Profiler $profiler, LoggerInterface $logger) + public function __construct(ICache $cacheDriver, Configuration $config, Database $dba, Profiler $profiler, LoggerInterface $logger) { $this->cacheDriver = $cacheDriver; $this->config = $config; @@ -66,17 +66,17 @@ class LockDriverFactory case 'memcache': case 'memcached': case 'redis': - if ($this->cacheDriver instanceof IMemoryCacheDriver) { + if ($this->cacheDriver instanceof IMemoryCache) { return new Lock\CacheLockDriver($this->cacheDriver); } break; case 'database': - return new Lock\DatabaseLockDriver($this->dba); + return new Lock\DatabaseLock($this->dba); break; case 'semaphore': - return new Lock\SemaphoreLockDriver(); + return new Lock\SemaphoreLock(); break; default: @@ -96,7 +96,7 @@ class LockDriverFactory * 2. Cache Locking * 3. Database Locking * - * @return Lock\ILockDriver + * @return Lock\ILock */ private function useAutoDriver() { @@ -104,7 +104,7 @@ class LockDriverFactory // 1. Try to use Semaphores for - local - locking if (function_exists('sem_get')) { try { - return new Lock\SemaphoreLockDriver(); + return new Lock\SemaphoreLock(); } catch (\Exception $exception) { $this->logger->debug('Using Semaphore driver for locking failed.', ['exception' => $exception]); } @@ -114,7 +114,7 @@ class LockDriverFactory $cache_driver = $this->config->get('system', 'cache_driver', 'database'); if ($cache_driver != 'database') { try { - if ($this->cacheDriver instanceof IMemoryCacheDriver) { + if ($this->cacheDriver instanceof IMemoryCache) { return new Lock\CacheLockDriver($this->cacheDriver); } } catch (\Exception $exception) { @@ -123,6 +123,6 @@ class LockDriverFactory } // 3. Use Database Locking as a Fallback - return new Lock\DatabaseLockDriver($this->dba); + return new Lock\DatabaseLock($this->dba); } } diff --git a/static/dependencies.config.php b/static/dependencies.config.php index 55a2c6845b..1399fe7285 100644 --- a/static/dependencies.config.php +++ b/static/dependencies.config.php @@ -4,7 +4,7 @@ use Dice\Dice; use Friendica\App; use Friendica\Core\Cache; use Friendica\Core\Config; -use Friendica\Core\Lock\ILockDriver; +use Friendica\Core\Lock\ILock; use Friendica\Database\Database; use Friendica\Factory; use Friendica\Util; @@ -106,30 +106,30 @@ return [ * $app = $dice->create(App::class, [], ['$channel' => 'index']); * and is automatically passed as an argument with the same name */ - LoggerInterface::class => [ + LoggerInterface::class => [ 'instanceOf' => Factory\LoggerFactory::class, 'call' => [ ['create', [], Dice::CHAIN_CALL], ], ], - '$devLogger' => [ + '$devLogger' => [ 'instanceOf' => Factory\LoggerFactory::class, 'call' => [ ['createDev', [], Dice::CHAIN_CALL], ] ], - Cache\ICacheDriver::class => [ + Cache\ICache::class => [ 'instanceOf' => Factory\CacheDriverFactory::class, - 'call' => [ + 'call' => [ ['create', [], Dice::CHAIN_CALL], ], ], - Cache\IMemoryCacheDriver::class => [ - 'instanceOf' => Cache\ICacheDriver::class, + Cache\IMemoryCache::class => [ + 'instanceOf' => Cache\ICache::class, ], - ILockDriver::class => [ + ILock::class => [ 'instanceOf' => Factory\LockDriverFactory::class, - 'call' => [ + 'call' => [ ['create', [], Dice::CHAIN_CALL], ], ], diff --git a/tests/Util/DbaLockMockTrait.php b/tests/Util/DbaLockMockTrait.php index 3f76edb884..5b405dcfc2 100644 --- a/tests/Util/DbaLockMockTrait.php +++ b/tests/Util/DbaLockMockTrait.php @@ -3,7 +3,7 @@ namespace Friendica\Test\Util; use Friendica\Core\Cache; -use Friendica\Core\Lock\DatabaseLockDriver; +use Friendica\Core\Lock\DatabaseLock; trait DbaLockMockTrait { @@ -12,7 +12,6 @@ trait DbaLockMockTrait /** * Mocking acquireLock with DBA-backend - * @see DatabaseLockDriver::acquireLock() * * @param mixed $key The key to lock * @param int $ttl The TimeToLive @@ -22,6 +21,9 @@ trait DbaLockMockTrait * @param bool $rowExists True, if a row already exists in the lock table * @param null $time The current timestamp * @param null|int $times How often the method will get used + * + *@see DatabaseLock::acquireLock() + * */ public function mockAcquireLock($key, $ttl = Cache::FIVE_MINUTES, $locked = false, $pid = null, $rowExists = true, $time = null, $times = null) { @@ -55,12 +57,14 @@ trait DbaLockMockTrait /** * Mocking isLocked with DBA-backend - * @see DatabaseLockDriver::isLocked() * * @param mixed $key The key of the lock * @param null|bool $return True, if the key is already locked - * @param null $time The current timestamp + * @param null $time The current timestamp * @param null|int $times How often the method will get used + * + *@see DatabaseLock::isLocked() + * */ public function mockIsLocked($key, $return = true, $time = null, $times = null) { @@ -76,10 +80,12 @@ trait DbaLockMockTrait /** * Mocking releaseAll with DBA-backend - * @see DatabaseLockDriver::releaseAll() * - * @param null $pid The PID which was set - * @param null|int $times How often the method will get used + * @param null $pid The PID which was set + * @param null|int $times How often the method will get used + * + *@see DatabaseLock::releaseAll() + * */ public function mockReleaseAll($pid = null, $times = null) { @@ -92,11 +98,13 @@ trait DbaLockMockTrait /** * Mocking ReleaseLock with DBA-backend - * @see DatabaseLockDriver::releaseLock() * * @param mixed $key The key to release * @param null|int $pid The PID which was set * @param null|int $times How often the method will get used + * + *@see DatabaseLock::releaseLock() + * */ public function mockReleaseLock($key, $pid = null, $times = null) { diff --git a/tests/src/Core/Cache/APCuCacheDriverTest.php b/tests/src/Core/Cache/APCuCacheDriverTest.php deleted file mode 100644 index 9925b02352..0000000000 --- a/tests/src/Core/Cache/APCuCacheDriverTest.php +++ /dev/null @@ -1,29 +0,0 @@ -markTestSkipped('APCu is not available'); - } - - parent::setUp(); - } - - protected function getInstance() - { - $this->cache = new APCuCache('localhost'); - return $this->cache; - } - - public function tearDown() - { - $this->cache->clear(false); - parent::tearDown(); - } -} diff --git a/tests/src/Core/Cache/APCuCacheTest.php b/tests/src/Core/Cache/APCuCacheTest.php new file mode 100644 index 0000000000..1b90be574e --- /dev/null +++ b/tests/src/Core/Cache/APCuCacheTest.php @@ -0,0 +1,29 @@ +markTestSkipped('APCu is not available'); + } + + parent::setUp(); + } + + protected function getInstance() + { + $this->cache = new APCuCache('localhost'); + return $this->cache; + } + + public function tearDown() + { + $this->cache->clear(false); + parent::tearDown(); + } +} diff --git a/tests/src/Core/Cache/ArrayCacheDriverTest.php b/tests/src/Core/Cache/ArrayCacheDriverTest.php deleted file mode 100644 index 68b8d1dba1..0000000000 --- a/tests/src/Core/Cache/ArrayCacheDriverTest.php +++ /dev/null @@ -1,26 +0,0 @@ -cache = new ArrayCache('localhost'); - return $this->cache; - } - - public function tearDown() - { - $this->cache->clear(false); - parent::tearDown(); - } - - public function testTTL() - { - // Array Cache doesn't support TTL - return true; - } -} diff --git a/tests/src/Core/Cache/ArrayCacheTest.php b/tests/src/Core/Cache/ArrayCacheTest.php new file mode 100644 index 0000000000..60ca2761e5 --- /dev/null +++ b/tests/src/Core/Cache/ArrayCacheTest.php @@ -0,0 +1,26 @@ +cache = new ArrayCache('localhost'); + return $this->cache; + } + + public function tearDown() + { + $this->cache->clear(false); + parent::tearDown(); + } + + public function testTTL() + { + // Array Cache doesn't support TTL + return true; + } +} diff --git a/tests/src/Core/Cache/CacheTest.php b/tests/src/Core/Cache/CacheTest.php index 088715cd79..92fdaffa32 100644 --- a/tests/src/Core/Cache/CacheTest.php +++ b/tests/src/Core/Cache/CacheTest.php @@ -2,7 +2,7 @@ namespace Friendica\Test\src\Core\Cache; -use Friendica\Core\Cache\MemcachedCacheDriver; +use Friendica\Core\Cache\MemcachedCache; use Friendica\Test\MockedTest; use Friendica\Util\PidFile; @@ -14,12 +14,12 @@ abstract class CacheTest extends MockedTest protected $startTime = 1417011228; /** - * @var \Friendica\Core\Cache\ICacheDriver + * @var \Friendica\Core\Cache\ICache */ protected $instance; /** - * @var \Friendica\Core\Cache\IMemoryCacheDriver + * @var \Friendica\Core\Cache\IMemoryCache */ protected $cache; @@ -202,7 +202,7 @@ abstract class CacheTest extends MockedTest */ public function testGetAllKeys($value1, $value2, $value3) { - if ($this->cache instanceof MemcachedCacheDriver) { + if ($this->cache instanceof MemcachedCache) { $this->markTestSkipped('Memcached doesn\'t support getAllKeys anymore'); } diff --git a/tests/src/Core/Cache/DatabaseCacheDriverTest.php b/tests/src/Core/Cache/DatabaseCacheDriverTest.php deleted file mode 100644 index 1aa9bf02b8..0000000000 --- a/tests/src/Core/Cache/DatabaseCacheDriverTest.php +++ /dev/null @@ -1,48 +0,0 @@ -setUpVfsDir(); - - parent::setUp(); - } - - protected function getInstance() - { - $logger = new NullLogger(); - $profiler = \Mockery::mock(Profiler::class); - $profiler->shouldReceive('saveTimestamp')->withAnyArgs()->andReturn(true); - - // load real config to avoid mocking every config-entry which is related to the Database class - $configFactory = new ConfigFactory(); - $loader = new ConfigFileLoader($this->root->url()); - $configCache = $configFactory->createCache($loader); - - $dba = new StaticDatabase($configCache, $profiler, $logger); - - $this->cache = new Cache\DatabaseCacheDriver('database', $dba); - return $this->cache; - } - - public function tearDown() - { - $this->cache->clear(false); - parent::tearDown(); - } -} diff --git a/tests/src/Core/Cache/DatabaseCacheTest.php b/tests/src/Core/Cache/DatabaseCacheTest.php new file mode 100644 index 0000000000..dbc98bcf4f --- /dev/null +++ b/tests/src/Core/Cache/DatabaseCacheTest.php @@ -0,0 +1,48 @@ +setUpVfsDir(); + + parent::setUp(); + } + + protected function getInstance() + { + $logger = new NullLogger(); + $profiler = \Mockery::mock(Profiler::class); + $profiler->shouldReceive('saveTimestamp')->withAnyArgs()->andReturn(true); + + // load real config to avoid mocking every config-entry which is related to the Database class + $configFactory = new ConfigFactory(); + $loader = new ConfigFileLoader($this->root->url()); + $configCache = $configFactory->createCache($loader); + + $dba = new StaticDatabase($configCache, $profiler, $logger); + + $this->cache = new Cache\DatabaseCache('database', $dba); + return $this->cache; + } + + public function tearDown() + { + $this->cache->clear(false); + parent::tearDown(); + } +} diff --git a/tests/src/Core/Cache/MemcacheCacheDriverTest.php b/tests/src/Core/Cache/MemcacheCacheDriverTest.php deleted file mode 100644 index 31aa0b4852..0000000000 --- a/tests/src/Core/Cache/MemcacheCacheDriverTest.php +++ /dev/null @@ -1,35 +0,0 @@ -shouldReceive('get') - ->with('system', 'memcache_host') - ->andReturn('localhost'); - $configMock - ->shouldReceive('get') - ->with('system', 'memcache_port') - ->andReturn(11211); - - $this->cache = new MemcacheCacheDriver('localhost', $configMock); - return $this->cache; - } - - public function tearDown() - { - $this->cache->clear(false); - parent::tearDown(); - } -} diff --git a/tests/src/Core/Cache/MemcacheCacheTest.php b/tests/src/Core/Cache/MemcacheCacheTest.php new file mode 100644 index 0000000000..ccc3723153 --- /dev/null +++ b/tests/src/Core/Cache/MemcacheCacheTest.php @@ -0,0 +1,35 @@ +shouldReceive('get') + ->with('system', 'memcache_host') + ->andReturn('localhost'); + $configMock + ->shouldReceive('get') + ->with('system', 'memcache_port') + ->andReturn(11211); + + $this->cache = new MemcacheCache('localhost', $configMock); + return $this->cache; + } + + public function tearDown() + { + $this->cache->clear(false); + parent::tearDown(); + } +} diff --git a/tests/src/Core/Cache/MemcachedCacheDriverTest.php b/tests/src/Core/Cache/MemcachedCacheDriverTest.php deleted file mode 100644 index ade3886841..0000000000 --- a/tests/src/Core/Cache/MemcachedCacheDriverTest.php +++ /dev/null @@ -1,35 +0,0 @@ -shouldReceive('get') - ->with('system', 'memcached_hosts') - ->andReturn([0 => 'localhost, 11211']); - - $logger = new NullLogger(); - - $this->cache = new MemcachedCacheDriver('localhost', $configMock, $logger); - return $this->cache; - } - - public function tearDown() - { - $this->cache->clear(false); - parent::tearDown(); - } -} diff --git a/tests/src/Core/Cache/MemcachedCacheTest.php b/tests/src/Core/Cache/MemcachedCacheTest.php new file mode 100644 index 0000000000..d887250197 --- /dev/null +++ b/tests/src/Core/Cache/MemcachedCacheTest.php @@ -0,0 +1,35 @@ +shouldReceive('get') + ->with('system', 'memcached_hosts') + ->andReturn([0 => 'localhost, 11211']); + + $logger = new NullLogger(); + + $this->cache = new MemcachedCache('localhost', $configMock, $logger); + return $this->cache; + } + + public function tearDown() + { + $this->cache->clear(false); + parent::tearDown(); + } +} diff --git a/tests/src/Core/Cache/MemoryCacheTest.php b/tests/src/Core/Cache/MemoryCacheTest.php index 0bd7617dd0..19c102396b 100644 --- a/tests/src/Core/Cache/MemoryCacheTest.php +++ b/tests/src/Core/Cache/MemoryCacheTest.php @@ -2,12 +2,12 @@ namespace Friendica\Test\src\Core\Cache; -use Friendica\Core\Cache\IMemoryCacheDriver; +use Friendica\Core\Cache\IMemoryCache; abstract class MemoryCacheTest extends CacheTest { /** - * @var \Friendica\Core\Cache\IMemoryCacheDriver + * @var \Friendica\Core\Cache\IMemoryCache */ protected $instance; @@ -15,7 +15,7 @@ abstract class MemoryCacheTest extends CacheTest { parent::setUp(); - if (!($this->instance instanceof IMemoryCacheDriver)) { + if (!($this->instance instanceof IMemoryCache)) { throw new \Exception('MemoryCacheTest unsupported'); } } diff --git a/tests/src/Core/Cache/RedisCacheDriverTest.php b/tests/src/Core/Cache/RedisCacheDriverTest.php deleted file mode 100644 index 999261834f..0000000000 --- a/tests/src/Core/Cache/RedisCacheDriverTest.php +++ /dev/null @@ -1,45 +0,0 @@ -shouldReceive('get') - ->with('system', 'redis_host') - ->andReturn('localhost'); - $configMock - ->shouldReceive('get') - ->with('system', 'redis_port') - ->andReturn(null); - - $configMock - ->shouldReceive('get') - ->with('system', 'redis_db', 0) - ->andReturn(3); - $configMock - ->shouldReceive('get') - ->with('system', 'redis_password') - ->andReturn(null); - - $this->cache = new RedisCacheDriver('localhost', $configMock); - return $this->cache; - } - - public function tearDown() - { - $this->cache->clear(false); - parent::tearDown(); - } -} diff --git a/tests/src/Core/Cache/RedisCacheTest.php b/tests/src/Core/Cache/RedisCacheTest.php new file mode 100644 index 0000000000..df353252df --- /dev/null +++ b/tests/src/Core/Cache/RedisCacheTest.php @@ -0,0 +1,45 @@ +shouldReceive('get') + ->with('system', 'redis_host') + ->andReturn('localhost'); + $configMock + ->shouldReceive('get') + ->with('system', 'redis_port') + ->andReturn(null); + + $configMock + ->shouldReceive('get') + ->with('system', 'redis_db', 0) + ->andReturn(3); + $configMock + ->shouldReceive('get') + ->with('system', 'redis_password') + ->andReturn(null); + + $this->cache = new RedisCache('localhost', $configMock); + return $this->cache; + } + + public function tearDown() + { + $this->cache->clear(false); + parent::tearDown(); + } +} diff --git a/tests/src/Core/Lock/APCuCacheLockDriverTest.php b/tests/src/Core/Lock/APCuCacheLockDriverTest.php deleted file mode 100644 index 70796b2698..0000000000 --- a/tests/src/Core/Lock/APCuCacheLockDriverTest.php +++ /dev/null @@ -1,23 +0,0 @@ -markTestSkipped('APCu is not available'); - } - - parent::setUp(); - } - - protected function getInstance() - { - return new CacheLockDriver(new APCuCache('localhost')); - } -} diff --git a/tests/src/Core/Lock/APCuCacheLockTest.php b/tests/src/Core/Lock/APCuCacheLockTest.php new file mode 100644 index 0000000000..c961013254 --- /dev/null +++ b/tests/src/Core/Lock/APCuCacheLockTest.php @@ -0,0 +1,23 @@ +markTestSkipped('APCu is not available'); + } + + parent::setUp(); + } + + protected function getInstance() + { + return new CacheLockDriver(new APCuCache('localhost')); + } +} diff --git a/tests/src/Core/Lock/ArrayCacheLockDriverTest.php b/tests/src/Core/Lock/ArrayCacheLockDriverTest.php deleted file mode 100644 index 9b74cd5670..0000000000 --- a/tests/src/Core/Lock/ArrayCacheLockDriverTest.php +++ /dev/null @@ -1,20 +0,0 @@ -setUpVfsDir(); - - parent::setUp(); - } - - protected function getInstance() - { - $logger = new NullLogger(); - $profiler = \Mockery::mock(Profiler::class); - $profiler->shouldReceive('saveTimestamp')->withAnyArgs()->andReturn(true); - - // load real config to avoid mocking every config-entry which is related to the Database class - $configFactory = new ConfigFactory(); - $loader = new ConfigFileLoader($this->root->url()); - $configCache = $configFactory->createCache($loader); - - $dba = new StaticDatabase($configCache, $profiler, $logger); - - return new DatabaseLockDriver($dba, $this->pid); - } -} diff --git a/tests/src/Core/Lock/DatabaseLockTest.php b/tests/src/Core/Lock/DatabaseLockTest.php new file mode 100644 index 0000000000..2b20b2c101 --- /dev/null +++ b/tests/src/Core/Lock/DatabaseLockTest.php @@ -0,0 +1,43 @@ +setUpVfsDir(); + + parent::setUp(); + } + + protected function getInstance() + { + $logger = new NullLogger(); + $profiler = \Mockery::mock(Profiler::class); + $profiler->shouldReceive('saveTimestamp')->withAnyArgs()->andReturn(true); + + // load real config to avoid mocking every config-entry which is related to the Database class + $configFactory = new ConfigFactory(); + $loader = new ConfigFileLoader($this->root->url()); + $configCache = $configFactory->createCache($loader); + + $dba = new StaticDatabase($configCache, $profiler, $logger); + + return new DatabaseLock($dba, $this->pid); + } +} diff --git a/tests/src/Core/Lock/LockTest.php b/tests/src/Core/Lock/LockTest.php index 5eb409539b..0c231713ae 100644 --- a/tests/src/Core/Lock/LockTest.php +++ b/tests/src/Core/Lock/LockTest.php @@ -12,7 +12,7 @@ abstract class LockTest extends MockedTest protected $startTime = 1417011228; /** - * @var \Friendica\Core\Lock\ILockDriver + * @var \Friendica\Core\Lock\ILock */ protected $instance; diff --git a/tests/src/Core/Lock/MemcacheCacheLockDriverTest.php b/tests/src/Core/Lock/MemcacheCacheLockDriverTest.php deleted file mode 100644 index 8c723f34ed..0000000000 --- a/tests/src/Core/Lock/MemcacheCacheLockDriverTest.php +++ /dev/null @@ -1,30 +0,0 @@ -shouldReceive('get') - ->with('system', 'memcache_host') - ->andReturn('localhost'); - $configMock - ->shouldReceive('get') - ->with('system', 'memcache_port') - ->andReturn(11211); - - return new CacheLockDriver(new MemcacheCacheDriver('localhost', $configMock)); - } -} diff --git a/tests/src/Core/Lock/MemcacheCacheLockTest.php b/tests/src/Core/Lock/MemcacheCacheLockTest.php new file mode 100644 index 0000000000..b4272b0d25 --- /dev/null +++ b/tests/src/Core/Lock/MemcacheCacheLockTest.php @@ -0,0 +1,30 @@ +shouldReceive('get') + ->with('system', 'memcache_host') + ->andReturn('localhost'); + $configMock + ->shouldReceive('get') + ->with('system', 'memcache_port') + ->andReturn(11211); + + return new CacheLockDriver(new MemcacheCache('localhost', $configMock)); + } +} diff --git a/tests/src/Core/Lock/MemcachedCacheLockDriverTest.php b/tests/src/Core/Lock/MemcachedCacheLockDriverTest.php deleted file mode 100644 index 7685d816de..0000000000 --- a/tests/src/Core/Lock/MemcachedCacheLockDriverTest.php +++ /dev/null @@ -1,29 +0,0 @@ -shouldReceive('get') - ->with('system', 'memcached_hosts') - ->andReturn([0 => 'localhost, 11211']); - - $logger = new NullLogger(); - - return new CacheLockDriver(new MemcachedCacheDriver('localhost', $configMock, $logger)); - } -} diff --git a/tests/src/Core/Lock/MemcachedCacheLockTest.php b/tests/src/Core/Lock/MemcachedCacheLockTest.php new file mode 100644 index 0000000000..ab5d678d68 --- /dev/null +++ b/tests/src/Core/Lock/MemcachedCacheLockTest.php @@ -0,0 +1,29 @@ +shouldReceive('get') + ->with('system', 'memcached_hosts') + ->andReturn([0 => 'localhost, 11211']); + + $logger = new NullLogger(); + + return new CacheLockDriver(new MemcachedCache('localhost', $configMock, $logger)); + } +} diff --git a/tests/src/Core/Lock/RedisCacheLockDriverTest.php b/tests/src/Core/Lock/RedisCacheLockDriverTest.php deleted file mode 100644 index fdc961ccc8..0000000000 --- a/tests/src/Core/Lock/RedisCacheLockDriverTest.php +++ /dev/null @@ -1,39 +0,0 @@ -shouldReceive('get') - ->with('system', 'redis_host') - ->andReturn('localhost'); - $configMock - ->shouldReceive('get') - ->with('system', 'redis_port') - ->andReturn(null); - - $configMock - ->shouldReceive('get') - ->with('system', 'redis_db', 0) - ->andReturn(3); - $configMock - ->shouldReceive('get') - ->with('system', 'redis_password') - ->andReturn(null); - - return new CacheLockDriver(new RedisCacheDriver('localhost', $configMock)); - } -} diff --git a/tests/src/Core/Lock/RedisCacheLockTest.php b/tests/src/Core/Lock/RedisCacheLockTest.php new file mode 100644 index 0000000000..dab31f5e3c --- /dev/null +++ b/tests/src/Core/Lock/RedisCacheLockTest.php @@ -0,0 +1,39 @@ +shouldReceive('get') + ->with('system', 'redis_host') + ->andReturn('localhost'); + $configMock + ->shouldReceive('get') + ->with('system', 'redis_port') + ->andReturn(null); + + $configMock + ->shouldReceive('get') + ->with('system', 'redis_db', 0) + ->andReturn(3); + $configMock + ->shouldReceive('get') + ->with('system', 'redis_password') + ->andReturn(null); + + return new CacheLockDriver(new RedisCache('localhost', $configMock)); + } +} diff --git a/tests/src/Core/Lock/SemaphoreLockDriverTest.php b/tests/src/Core/Lock/SemaphoreLockDriverTest.php deleted file mode 100644 index d5aaa36ba9..0000000000 --- a/tests/src/Core/Lock/SemaphoreLockDriverTest.php +++ /dev/null @@ -1,44 +0,0 @@ -makePartial(); - - $app = \Mockery::mock(App::class); - $app->shouldReceive('getHostname')->andReturn('friendica.local'); - $dice->shouldReceive('create')->with(App::class)->andReturn($app); - - $configMock = \Mockery::mock(Configuration::class); - $configMock - ->shouldReceive('get') - ->with('system', 'temppath', NULL, false) - ->andReturn('/tmp/'); - $dice->shouldReceive('create')->with(Configuration::class)->andReturn($configMock); - - // @todo Because "get_temppath()" is using static methods, we have to initialize the BaseObject - BaseObject::setDependencyInjection($dice); - } - - protected function getInstance() - { - return new SemaphoreLockDriver(); - } - - function testLockTTL() - { - // Semaphore doesn't work with TTL - return true; - } -} diff --git a/tests/src/Core/Lock/SemaphoreLockTest.php b/tests/src/Core/Lock/SemaphoreLockTest.php new file mode 100644 index 0000000000..7b9b03d728 --- /dev/null +++ b/tests/src/Core/Lock/SemaphoreLockTest.php @@ -0,0 +1,44 @@ +makePartial(); + + $app = \Mockery::mock(App::class); + $app->shouldReceive('getHostname')->andReturn('friendica.local'); + $dice->shouldReceive('create')->with(App::class)->andReturn($app); + + $configMock = \Mockery::mock(Configuration::class); + $configMock + ->shouldReceive('get') + ->with('system', 'temppath', NULL, false) + ->andReturn('/tmp/'); + $dice->shouldReceive('create')->with(Configuration::class)->andReturn($configMock); + + // @todo Because "get_temppath()" is using static methods, we have to initialize the BaseObject + BaseObject::setDependencyInjection($dice); + } + + protected function getInstance() + { + return new SemaphoreLock(); + } + + function testLockTTL() + { + // Semaphore doesn't work with TTL + return true; + } +}