use Friendica\App;
use Friendica\Content\ForumManager;
use Friendica\Content\Text\BBCode;
-use Friendica\Core\Cache\Duration;
+use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Hook;
use Friendica\Database\DBA;
use Friendica\DI;
use FastRoute\Dispatcher;
use FastRoute\RouteCollector;
use FastRoute\RouteParser\Std;
-use Friendica\Core\Cache\Duration;
+use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Cache\ICache;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Asika\SimpleConsole\CommandArgsException;
use Friendica\App;
-use Friendica\Core\Cache\Duration;
+use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Cache\ICache;
use RuntimeException;
use DOMText;
use DOMXPath;
use Exception;
-use Friendica\Core\Cache\Duration;
+use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Hook;
use Friendica\Core\Renderer;
use Friendica\Database\Database;
namespace Friendica\Content;
use Friendica\Core\Addon;
-use Friendica\Core\Cache\Duration;
+use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Protocol;
use Friendica\Core\Renderer;
use Friendica\Database\DBA;
+++ /dev/null
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * 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
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Core;
-
-use Friendica\Core\Cache\ICache;
-
-/**
- * Abstract class for common used functions
- */
-abstract class BaseCache implements ICache
-{
- /**
- * @var string The hostname
- */
- private $hostName;
-
- public function __construct(string $hostName)
- {
- $this->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 $keys The keys, 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 $keys, string $prefix = null)
- {
- if (empty($prefix)) {
- return $keys;
- } else {
- $result = [];
-
- foreach ($keys as $key) {
- if (strpos($key, $prefix) === 0) {
- array_push($result, $key);
- }
- }
-
- return $result;
- }
- }
-}
+++ /dev/null
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * 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
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Core\Cache;
-
-use Exception;
-use Friendica\Core\BaseCache;
-
-/**
- * APCu Cache.
- */
-class APCuCache extends BaseCache implements IMemoryCache
-{
- use TraitCompareSet;
- use TraitCompareDelete;
-
- /**
- * @throws Exception
- */
- public function __construct(string $hostname)
- {
- if (!self::isAvailable()) {
- throw new Exception('APCu is not available.');
- }
-
- parent::__construct($hostname);
- }
-
- /**
- * (@inheritdoc)
- */
- public function getAllKeys($prefix = null)
- {
- $ns = $this->getCacheKey($prefix);
- $ns = preg_quote($ns, '/');
-
- if (class_exists('\APCIterator')) {
- $iterator = new \APCIterator('user', '/^' . $ns. '/', APC_ITER_KEY);
- } else {
- $iterator = new \APCUIterator('/^' . $ns . '/', APC_ITER_KEY);
- }
-
- $keys = [];
- foreach ($iterator as $item) {
- array_push($keys, $item['key']);
- }
-
- return $this->getOriginalKeys($keys);
- }
-
- /**
- * (@inheritdoc)
- */
- public function get($key)
- {
- $return = null;
- $cachekey = $this->getCacheKey($key);
-
- $cached = apcu_fetch($cachekey, $success);
- if (!$success) {
- 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 = Duration::FIVE_MINUTES)
- {
- $cachekey = $this->getCacheKey($key);
-
- $cached = serialize($value);
-
- if ($ttl > 0) {
- return apcu_store(
- $cachekey,
- $cached,
- $ttl
- );
- } else {
- return apcu_store(
- $cachekey,
- $cached
- );
- }
- }
-
- /**
- * (@inheritdoc)
- */
- public function delete($key)
- {
- $cachekey = $this->getCacheKey($key);
- return apcu_delete($cachekey);
- }
-
- /**
- * (@inheritdoc)
- */
- public function clear($outdated = true)
- {
- if ($outdated) {
- return true;
- } else {
- $prefix = $this->getPrefix();
- $prefix = preg_quote($prefix, '/');
-
- if (class_exists('\APCIterator')) {
- $iterator = new \APCIterator('user', '/^' . $prefix . '/', APC_ITER_KEY);
- } else {
- $iterator = new \APCUIterator('/^' . $prefix . '/', APC_ITER_KEY);
- }
-
- return apcu_delete($iterator);
- }
- }
-
- /**
- * (@inheritdoc)
- */
- public function add($key, $value, $ttl = Duration::FIVE_MINUTES)
- {
- $cachekey = $this->getCacheKey($key);
- $cached = serialize($value);
-
- return apcu_add($cachekey, $cached);
- }
-
- public static function isAvailable()
- {
- if (!extension_loaded('apcu')) {
- return false;
- } elseif (!ini_get('apc.enabled') && !ini_get('apc.enable_cli')) {
- return false;
- } elseif (
- version_compare(phpversion('apc') ?: '0.0.0', '4.0.6') === -1 &&
- version_compare(phpversion('apcu') ?: '0.0.0', '5.1.0') === -1
- ) {
- return false;
- }
-
- return true;
- }
-
- /**
- * {@inheritDoc}
- */
- public function getName()
- {
- return Type::APCU;
- }
-}
+++ /dev/null
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * 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
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Core\Cache;
-
-use Friendica\Core\BaseCache;
-
-/**
- * Implementation of the IMemoryCache mainly for testing purpose
- */
-class ArrayCache extends BaseCache implements IMemoryCache
-{
- use TraitCompareDelete;
-
- /** @var array Array with the cached data */
- protected $cachedData = array();
-
- /**
- * (@inheritdoc)
- */
- public function getAllKeys($prefix = null)
- {
- return $this->filterArrayKeysByPrefix(array_keys($this->cachedData), $prefix);
- }
-
- /**
- * (@inheritdoc)
- */
- public function get($key)
- {
- if (isset($this->cachedData[$key])) {
- return $this->cachedData[$key];
- }
- return null;
- }
-
- /**
- * (@inheritdoc)
- */
- public function set($key, $value, $ttl = Duration::FIVE_MINUTES)
- {
- $this->cachedData[$key] = $value;
- return true;
- }
-
- /**
- * (@inheritdoc)
- */
- public function delete($key)
- {
- unset($this->cachedData[$key]);
- return true;
- }
-
- /**
- * (@inheritdoc)
- */
- public function clear($outdated = true)
- {
- // Array doesn't support TTL so just don't delete something
- if ($outdated) {
- return true;
- }
-
- $this->cachedData = [];
- return true;
- }
-
- /**
- * (@inheritdoc)
- */
- public function add($key, $value, $ttl = Duration::FIVE_MINUTES)
- {
- if (isset($this->cachedData[$key])) {
- return false;
- } else {
- return $this->set($key, $value, $ttl);
- }
- }
-
- /**
- * (@inheritdoc)
- */
- public function compareSet($key, $oldValue, $newValue, $ttl = Duration::FIVE_MINUTES)
- {
- if ($this->get($key) === $oldValue) {
- return $this->set($key, $newValue);
- } else {
- return false;
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public function getName()
- {
- return Type::ARRAY;
- }
-}
+++ /dev/null
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * 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
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Core\Cache;
-
-use Friendica\Database\Database;
-use Friendica\Util\DateTimeFormat;
-use Friendica\Core\BaseCache;
-
-/**
- * Database Cache
- */
-class DatabaseCache extends BaseCache 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 = Duration::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 ']);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public function getName()
- {
- return Type::DATABASE;
- }
-}
+++ /dev/null
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * 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
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Core\Cache;
-
-/**
- * Enumeration for cache durations
- */
-abstract class Duration
-{
- const MONTH = 2592000;
- const HOUR = 3600;
- const HALF_HOUR = 1800;
- const QUARTER_HOUR = 900;
- const MINUTE = 60;
- const WEEK = 604800;
- const INFINITE = 0;
- const DAY = 86400;
- const FIVE_MINUTES = 300;
-}
--- /dev/null
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Cache\Enum;
+
+/**
+ * Enumeration for cache durations
+ */
+abstract class Duration
+{
+ const MONTH = 2592000;
+ const HOUR = 3600;
+ const HALF_HOUR = 1800;
+ const QUARTER_HOUR = 900;
+ const MINUTE = 60;
+ const WEEK = 604800;
+ const INFINITE = 0;
+ const DAY = 86400;
+ const FIVE_MINUTES = 300;
+}
--- /dev/null
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Cache\Enum;
+
+/**
+ * Enumeration for cache types
+ */
+abstract class Type
+{
+ const APCU = 'apcu';
+ const REDIS = 'redis';
+ const ARRAY = 'array';
+ const MEMCACHE = 'memcache';
+ const DATABASE = 'database';
+ const MEMCACHED = 'memcached';
+}
--- /dev/null
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Cache\Factory;
+
+use Friendica\App\BaseURL;
+use Friendica\Core\Cache;
+use Friendica\Core\Cache\ICache;
+use Friendica\Core\Config\IConfig;
+use Friendica\Database\Database;
+use Friendica\Util\Profiler;
+use Psr\Log\LoggerInterface;
+
+/**
+ * Class CacheFactory
+ *
+ * @package Friendica\Core\Cache
+ *
+ * A basic class to generate a CacheDriver
+ */
+class CacheFactory
+{
+ /**
+ * @var string The default cache if nothing set
+ */
+ const DEFAULT_TYPE = Cache\Enum\Type::DATABASE;
+
+ /**
+ * @var IConfig The IConfiguration to read parameters out of the config
+ */
+ private $config;
+
+ /**
+ * @var Database The database connection in case that the cache is used the dba connection
+ */
+ private $dba;
+
+ /**
+ * @var string The hostname, used as Prefix for Caching
+ */
+ private $hostname;
+
+ /**
+ * @var Profiler The optional profiler if the cached should be profiled
+ */
+ private $profiler;
+
+ /**
+ * @var LoggerInterface The Friendica Logger
+ */
+ private $logger;
+
+ public function __construct(BaseURL $baseURL, IConfig $config, Database $dba, Profiler $profiler, LoggerInterface $logger)
+ {
+ $this->hostname = $baseURL->getHostname();
+ $this->config = $config;
+ $this->dba = $dba;
+ $this->profiler = $profiler;
+ $this->logger = $logger;
+ }
+
+ /**
+ * This method creates a CacheDriver for the given cache driver name
+ *
+ * @param string $type The cache type to create (default is per config)
+ *
+ * @return ICache The instance of the CacheDriver
+ * @throws \Exception The exception if something went wrong during the CacheDriver creation
+ */
+ public function create(string $type = null)
+ {
+ if (empty($type)) {
+ $type = $this->config->get('system', 'cache_driver', self::DEFAULT_TYPE);
+ }
+
+ switch ($type) {
+ case Cache\Enum\Type::MEMCACHE:
+ $cache = new Cache\Type\MemcacheCache($this->hostname, $this->config);
+ break;
+ case Cache\Enum\Type::MEMCACHED:
+ $cache = new Cache\Type\MemcachedCache($this->hostname, $this->config, $this->logger);
+ break;
+ case Cache\Enum\Type::REDIS:
+ $cache = new Cache\Type\RedisCache($this->hostname, $this->config);
+ break;
+ case Cache\Enum\Type::APCU:
+ $cache = new Cache\Type\APCuCache($this->hostname);
+ break;
+ default:
+ $cache = new Cache\Type\DatabaseCache($this->hostname, $this->dba);
+ }
+
+ $profiling = $this->config->get('system', 'profiling', false);
+
+ // In case profiling is enabled, wrap the ProfilerCache around the current cache
+ if (isset($profiling) && $profiling !== false) {
+ return new Cache\Type\ProfilerCache($cache, $this->profiler);
+ } else {
+ return $cache;
+ }
+ }
+}
namespace Friendica\Core\Cache;
+use Friendica\Core\Cache\Enum\Duration;
+
/**
* Cache Interface
*/
namespace Friendica\Core\Cache;
+use Friendica\Core\Cache\Enum\Duration;
+
/**
* This interface defines methods for Memory-Caches only
*/
+++ /dev/null
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * 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
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Core\Cache;
-
-use Exception;
-use Friendica\Core\BaseCache;
-use Friendica\Core\Config\IConfig;
-use Memcache;
-
-/**
- * Memcache Cache
- */
-class MemcacheCache extends BaseCache implements IMemoryCache
-{
- use TraitCompareSet;
- use TraitCompareDelete;
- use TraitMemcacheCommand;
-
- /**
- * @var Memcache
- */
- private $memcache;
-
- /**
- * @throws Exception
- */
- public function __construct(string $hostname, IConfig $config)
- {
- if (!class_exists('Memcache', false)) {
- throw new Exception('Memcache class isn\'t available');
- }
-
- parent::__construct($hostname);
-
- $this->memcache = new Memcache();
-
- $this->server = $config->get('system', 'memcache_host');;
- $this->port = $config->get('system', 'memcache_port');
-
- if (!@$this->memcache->connect($this->server, $this->port)) {
- throw new Exception('Expected Memcache server at ' . $this->server . ':' . $this->port . ' isn\'t available');
- }
- }
-
- /**
- * (@inheritdoc)
- */
- public function getAllKeys($prefix = null)
- {
- $keys = $this->getOriginalKeys($this->getMemcacheKeys());
-
- 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 = Duration::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 = Duration::FIVE_MINUTES)
- {
- $cachekey = $this->getCacheKey($key);
- return $this->memcache->add($cachekey, serialize($value), MEMCACHE_COMPRESSED, $ttl);
- }
-
- /**
- * {@inheritDoc}
- */
- public function getName()
- {
- return Type::MEMCACHE;
- }
-}
+++ /dev/null
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * 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
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Core\Cache;
-
-use Exception;
-use Friendica\Core\BaseCache;
-use Friendica\Core\Config\IConfig;
-use Memcached;
-use Psr\Log\LoggerInterface;
-
-/**
- * Memcached Cache
- */
-class MemcachedCache extends BaseCache implements IMemoryCache
-{
- use TraitCompareSet;
- use TraitCompareDelete;
- use TraitMemcacheCommand;
-
- /**
- * @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, IConfig $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->server = $memcached_hosts[0][0] ?? 'localhost';
- $this->port = $memcached_hosts[0][1] ?? 11211;
-
- $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->getMemcacheKeys());
-
- 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
- $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 = Duration::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 = Duration::FIVE_MINUTES)
- {
- $cachekey = $this->getCacheKey($key);
- return $this->memcached->add($cachekey, $value, $ttl);
- }
-
- /**
- * {@inheritDoc}
- */
- public function getName()
- {
- return Type::MEMCACHED;
- }
-}
+++ /dev/null
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * 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
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Core\Cache;
-
-use Friendica\Core\System;
-use Friendica\Util\Profiler;
-
-/**
- * This class wraps cache driver so they can get profiled - in case the profiler is enabled
- *
- * It is using the decorator pattern (@see
- */
-class ProfilerCache implements ICache, IMemoryCache
-{
- /**
- * @var ICache The original cache driver
- */
- private $cache;
-
- /**
- * @var Profiler The profiler of Friendica
- */
- private $profiler;
-
- public function __construct(ICache $cache, Profiler $profiler)
- {
- $this->cache = $cache;
- $this->profiler = $profiler;
- }
-
- /**
- * {@inheritDoc}
- */
- public function getAllKeys($prefix = null)
- {
- $this->profiler->startRecording('cache');
-
- $return = $this->cache->getAllKeys($prefix);
-
- $this->profiler->stopRecording();
-
- return $return;
- }
-
- /**
- * {@inheritDoc}
- */
- public function get($key)
- {
- $this->profiler->startRecording('cache');
-
- $return = $this->cache->get($key);
-
- $this->profiler->stopRecording();
-
- return $return;
- }
-
- /**
- * {@inheritDoc}
- */
- public function set($key, $value, $ttl = Duration::FIVE_MINUTES)
- {
- $this->profiler->startRecording('cache');
-
- $return = $this->cache->set($key, $value, $ttl);
-
- $this->profiler->stopRecording();
-
- return $return;
- }
-
- /**
- * {@inheritDoc}
- */
- public function delete($key)
- {
- $this->profiler->startRecording('cache');
-
- $return = $this->cache->delete($key);
-
- $this->profiler->stopRecording();
-
- return $return;
- }
-
- /**
- * {@inheritDoc}
- */
- public function clear($outdated = true)
- {
- $this->profiler->startRecording('cache');
-
- $return = $this->cache->clear($outdated);
-
- $this->profiler->stopRecording();
-
- return $return;
- }
-
- /**
- * {@inheritDoc}
- */
- public function add($key, $value, $ttl = Duration::FIVE_MINUTES)
- {
- if ($this->cache instanceof IMemoryCache) {
- $this->profiler->startRecording('cache');
-
- $return = $this->cache->add($key, $value, $ttl);
-
- $this->profiler->stopRecording();
-
- return $return;
- } else {
- return false;
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public function compareSet($key, $oldValue, $newValue, $ttl = Duration::FIVE_MINUTES)
- {
- if ($this->cache instanceof IMemoryCache) {
- $this->profiler->startRecording('cache');
-
- $return = $this->cache->compareSet($key, $oldValue, $newValue, $ttl);
-
- $this->profiler->stopRecording();
-
- return $return;
- } else {
- return false;
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public function compareDelete($key, $value)
- {
- if ($this->cache instanceof IMemoryCache) {
- $this->profiler->startRecording('cache');
-
- $return = $this->cache->compareDelete($key, $value);
-
- $this->profiler->stopRecording();
-
- return $return;
- } else {
- return false;
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public function GetName()
- {
- return $this->cache->getName() . ' (with profiler)';
- }
-}
+++ /dev/null
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * 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
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Core\Cache;
-
-use Exception;
-use Friendica\Core\BaseCache;
-use Friendica\Core\Config\IConfig;
-use Redis;
-
-/**
- * Redis Cache. This driver is based on Memcache driver
- */
-class RedisCache extends BaseCache implements IMemoryCache
-{
- /**
- * @var Redis
- */
- private $redis;
-
- /**
- * @throws Exception
- */
- public function __construct(string $hostname, IConfig $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 (isset($redis_port) && !@$this->redis->connect($redis_host, $redis_port)) {
- throw new Exception('Expected Redis server at ' . $redis_host . ':' . $redis_port . ' isn\'t available');
- } elseif (!@$this->redis->connect($redis_host)) {
- throw new Exception('Expected Redis server at ' . $redis_host . ' 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 = Duration::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);
- $this->redis->del($cachekey);
- // Redis doesn't have an error state for del()
- return true;
- }
-
- /**
- * (@inheritdoc)
- */
- public function clear($outdated = true)
- {
- if ($outdated) {
- return true;
- } else {
- return $this->redis->flushAll();
- }
- }
-
- /**
- * (@inheritdoc)
- */
- public function add($key, $value, $ttl = Duration::FIVE_MINUTES)
- {
- $cachekey = $this->getCacheKey($key);
- $cached = serialize($value);
-
- return $this->redis->setnx($cachekey, $cached);
- }
-
- /**
- * (@inheritdoc)
- */
- public function compareSet($key, $oldValue, $newValue, $ttl = Duration::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;
- }
-
- /**
- * {@inheritDoc}
- */
- public function getName()
- {
- return Type::REDIS;
- }
-}
+++ /dev/null
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * 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
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Core\Cache;
-
-/**
- * Trait TraitCompareSetDelete
- *
- * This Trait is to compensate non native "exclusive" sets/deletes in caches
- */
-trait TraitCompareDelete
-{
- abstract public function get($key);
-
- abstract public function set($key, $value, $ttl = Duration::FIVE_MINUTES);
-
- abstract public function delete($key);
-
- abstract public function add($key, $value, $ttl = Duration::FIVE_MINUTES);
-
- /**
- * NonNative - Compares if the old value is set and removes it
- *
- * @param string $key The cache key
- * @param mixed $value The old value we know and want to delete
- * @return bool
- */
- public function compareDelete($key, $value) {
- if ($this->add($key . "_lock", true)) {
- if ($this->get($key) === $value) {
- $this->delete($key);
- $this->delete($key . "_lock");
- return true;
- } else {
- $this->delete($key . "_lock");
- return false;
- }
- } else {
- return false;
- }
- }
-}
+++ /dev/null
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * 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
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Core\Cache;
-
-/**
- * Trait TraitCompareSetDelete
- *
- * This Trait is to compensate non native "exclusive" sets/deletes in caches
- */
-trait TraitCompareSet
-{
- abstract public function get($key);
-
- abstract public function set($key, $value, $ttl = Duration::FIVE_MINUTES);
-
- abstract public function delete($key);
-
- abstract public function add($key, $value, $ttl = Duration::FIVE_MINUTES);
-
- /**
- * NonNative - Compares if the old value is set and sets the new value
- *
- * @param string $key The cache key
- * @param mixed $oldValue The old value we know from the cache
- * @param mixed $newValue The new value we want to set
- * @param int $ttl The cache lifespan, must be one of the Cache constants
- *
- * @return bool
- */
- public function compareSet($key, $oldValue, $newValue, $ttl = Duration::FIVE_MINUTES) {
- if ($this->add($key . "_lock", true)) {
- if ($this->get($key) === $oldValue) {
- $this->set($key, $newValue, $ttl);
- $this->delete($key . "_lock");
- return true;
- } else {
- $this->delete($key . "_lock");
- return false;
- }
- } else {
- return false;
- }
- }
-}
+++ /dev/null
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * 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
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Core\Cache;
-
-use Friendica\Network\HTTPException\InternalServerErrorException;
-
-/**
- * Trait for Memcache to add a custom version of the
- * method getAllKeys() since this isn't working anymore
- *
- * Adds the possibility to directly communicate with the memcache too
- */
-trait TraitMemcacheCommand
-{
- /**
- * @var string server address
- */
- protected $server;
-
- /**
- * @var int server port
- */
- protected $port;
-
- /**
- * Retrieves the stored keys of the memcache instance
- * Uses custom commands, which aren't bound to the used instance of the class
- *
- * @todo Due the fact that we use a custom command, there are race conditions possible:
- * - $this->memcache(d) adds a key
- * - $this->getMemcacheKeys is called directly "after"
- * - But $this->memcache(d) isn't finished adding the key, so getMemcacheKeys doesn't find it
- *
- * @return array All keys of the memcache instance
- *
- * @throws InternalServerErrorException
- */
- protected function getMemcacheKeys()
- {
- $string = $this->sendMemcacheCommand("stats items");
- $lines = explode("\r\n", $string);
- $slabs = [];
- $keys = [];
-
- foreach ($lines as $line) {
-
- if (preg_match("/STAT items:([\d]+):number ([\d]+)/", $line, $matches) &&
- isset($matches[1]) &&
- !in_array($matches[1], $keys)) {
-
- $slabs[] = $matches[1];
- $string = $this->sendMemcacheCommand("stats cachedump " . $matches[1] . " " . $matches[2]);
- preg_match_all("/ITEM (.*?) /", $string, $matches);
- $keys = array_merge($keys, $matches[1]);
- }
- }
-
- return $keys;
- }
-
- /**
- * Taken directly from memcache PECL source
- * Sends a command to the memcache instance and returns the result
- * as a string
- *
- * http://pecl.php.net/package/memcache
- *
- * @param string $command The command to send to the Memcache server
- *
- * @return string The returned buffer result
- *
- * @throws InternalServerErrorException In case the memcache server isn't available (anymore)
- */
- protected function sendMemcacheCommand(string $command)
- {
- $s = @fsockopen($this->server, $this->port);
- if (!$s) {
- throw new InternalServerErrorException("Cant connect to:" . $this->server . ':' . $this->port);
- }
-
- fwrite($s, $command . "\r\n");
- $buf = '';
-
- while (!feof($s)) {
-
- $buf .= fgets($s, 256);
-
- if (strpos($buf, "END\r\n") !== false) { // stat says end
- break;
- }
-
- if (strpos($buf, "DELETED\r\n") !== false || strpos($buf, "NOT_FOUND\r\n") !== false) { // delete says these
- break;
- }
-
- if (strpos($buf, "OK\r\n") !== false) { // flush_all says ok
- break;
- }
- }
-
- fclose($s);
- return ($buf);
- }
-}
+++ /dev/null
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * 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
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Core\Cache;
-
-/**
- * Enumeration for cache types
- */
-abstract class Type
-{
- const APCU = 'apcu';
- const REDIS = 'redis';
- const ARRAY = 'array';
- const MEMCACHE = 'memcache';
- const DATABASE = 'database';
- const MEMCACHED = 'memcached';
-}
--- /dev/null
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Cache\Type;
+
+use Exception;
+use Friendica\Core\Cache\Enum\Duration;
+use Friendica\Core\Cache\IMemoryCache;
+use Friendica\Core\Cache\Type\TraitCompareDelete;
+use Friendica\Core\Cache\Type\TraitCompareSet;
+use Friendica\Core\Cache\Enum\Type;
+
+/**
+ * APCu Cache.
+ */
+class APCuCache extends BaseCache implements IMemoryCache
+{
+ use TraitCompareSet;
+ use TraitCompareDelete;
+
+ /**
+ * @throws Exception
+ */
+ public function __construct(string $hostname)
+ {
+ if (!self::isAvailable()) {
+ throw new Exception('APCu is not available.');
+ }
+
+ parent::__construct($hostname);
+ }
+
+ /**
+ * (@inheritdoc)
+ */
+ public function getAllKeys($prefix = null)
+ {
+ $ns = $this->getCacheKey($prefix);
+ $ns = preg_quote($ns, '/');
+
+ if (class_exists('\APCIterator')) {
+ $iterator = new \APCIterator('user', '/^' . $ns. '/', APC_ITER_KEY);
+ } else {
+ $iterator = new \APCUIterator('/^' . $ns . '/', APC_ITER_KEY);
+ }
+
+ $keys = [];
+ foreach ($iterator as $item) {
+ array_push($keys, $item['key']);
+ }
+
+ return $this->getOriginalKeys($keys);
+ }
+
+ /**
+ * (@inheritdoc)
+ */
+ public function get($key)
+ {
+ $return = null;
+ $cachekey = $this->getCacheKey($key);
+
+ $cached = apcu_fetch($cachekey, $success);
+ if (!$success) {
+ 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 = Duration::FIVE_MINUTES)
+ {
+ $cachekey = $this->getCacheKey($key);
+
+ $cached = serialize($value);
+
+ if ($ttl > 0) {
+ return apcu_store(
+ $cachekey,
+ $cached,
+ $ttl
+ );
+ } else {
+ return apcu_store(
+ $cachekey,
+ $cached
+ );
+ }
+ }
+
+ /**
+ * (@inheritdoc)
+ */
+ public function delete($key)
+ {
+ $cachekey = $this->getCacheKey($key);
+ return apcu_delete($cachekey);
+ }
+
+ /**
+ * (@inheritdoc)
+ */
+ public function clear($outdated = true)
+ {
+ if ($outdated) {
+ return true;
+ } else {
+ $prefix = $this->getPrefix();
+ $prefix = preg_quote($prefix, '/');
+
+ if (class_exists('\APCIterator')) {
+ $iterator = new \APCIterator('user', '/^' . $prefix . '/', APC_ITER_KEY);
+ } else {
+ $iterator = new \APCUIterator('/^' . $prefix . '/', APC_ITER_KEY);
+ }
+
+ return apcu_delete($iterator);
+ }
+ }
+
+ /**
+ * (@inheritdoc)
+ */
+ public function add($key, $value, $ttl = Duration::FIVE_MINUTES)
+ {
+ $cachekey = $this->getCacheKey($key);
+ $cached = serialize($value);
+
+ return apcu_add($cachekey, $cached);
+ }
+
+ public static function isAvailable()
+ {
+ if (!extension_loaded('apcu')) {
+ return false;
+ } elseif (!ini_get('apc.enabled') && !ini_get('apc.enable_cli')) {
+ return false;
+ } elseif (
+ version_compare(phpversion('apc') ?: '0.0.0', '4.0.6') === -1 &&
+ version_compare(phpversion('apcu') ?: '0.0.0', '5.1.0') === -1
+ ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getName()
+ {
+ return Type::APCU;
+ }
+}
--- /dev/null
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Cache\Type;
+
+use Friendica\Core\Cache\Enum\Duration;
+use Friendica\Core\Cache\IMemoryCache;
+use Friendica\Core\Cache\Type\TraitCompareDelete;
+use Friendica\Core\Cache\Enum\Type;
+
+/**
+ * Implementation of the IMemoryCache mainly for testing purpose
+ */
+class ArrayCache extends BaseCache implements IMemoryCache
+{
+ use TraitCompareDelete;
+
+ /** @var array Array with the cached data */
+ protected $cachedData = array();
+
+ /**
+ * (@inheritdoc)
+ */
+ public function getAllKeys($prefix = null)
+ {
+ return $this->filterArrayKeysByPrefix(array_keys($this->cachedData), $prefix);
+ }
+
+ /**
+ * (@inheritdoc)
+ */
+ public function get($key)
+ {
+ if (isset($this->cachedData[$key])) {
+ return $this->cachedData[$key];
+ }
+ return null;
+ }
+
+ /**
+ * (@inheritdoc)
+ */
+ public function set($key, $value, $ttl = Duration::FIVE_MINUTES)
+ {
+ $this->cachedData[$key] = $value;
+ return true;
+ }
+
+ /**
+ * (@inheritdoc)
+ */
+ public function delete($key)
+ {
+ unset($this->cachedData[$key]);
+ return true;
+ }
+
+ /**
+ * (@inheritdoc)
+ */
+ public function clear($outdated = true)
+ {
+ // Array doesn't support TTL so just don't delete something
+ if ($outdated) {
+ return true;
+ }
+
+ $this->cachedData = [];
+ return true;
+ }
+
+ /**
+ * (@inheritdoc)
+ */
+ public function add($key, $value, $ttl = Duration::FIVE_MINUTES)
+ {
+ if (isset($this->cachedData[$key])) {
+ return false;
+ } else {
+ return $this->set($key, $value, $ttl);
+ }
+ }
+
+ /**
+ * (@inheritdoc)
+ */
+ public function compareSet($key, $oldValue, $newValue, $ttl = Duration::FIVE_MINUTES)
+ {
+ if ($this->get($key) === $oldValue) {
+ return $this->set($key, $newValue);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getName()
+ {
+ return Type::ARRAY;
+ }
+}
--- /dev/null
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Cache\Type;
+
+use Friendica\Core\Cache\ICache;
+
+/**
+ * Abstract class for common used functions
+ */
+abstract class BaseCache implements ICache
+{
+ /**
+ * @var string The hostname
+ */
+ private $hostName;
+
+ public function __construct(string $hostName)
+ {
+ $this->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 $keys The keys, 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 $keys, string $prefix = null)
+ {
+ if (empty($prefix)) {
+ return $keys;
+ } else {
+ $result = [];
+
+ foreach ($keys as $key) {
+ if (strpos($key, $prefix) === 0) {
+ array_push($result, $key);
+ }
+ }
+
+ return $result;
+ }
+ }
+}
--- /dev/null
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Cache\Type;
+
+use Friendica\Core\Cache\Enum\Duration;
+use Friendica\Core\Cache\ICache;
+use Friendica\Core\Cache\Enum\Type;
+use Friendica\Database\Database;
+use Friendica\Util\DateTimeFormat;
+
+/**
+ * Database Cache
+ */
+class DatabaseCache extends BaseCache 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 = Duration::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 ']);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getName()
+ {
+ return Type::DATABASE;
+ }
+}
--- /dev/null
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Cache\Type;
+
+use Exception;
+use Friendica\Core\Cache\Enum\Duration;
+use Friendica\Core\Cache\IMemoryCache;
+use Friendica\Core\Cache\Type\TraitCompareDelete;
+use Friendica\Core\Cache\Type\TraitCompareSet;
+use Friendica\Core\Cache\Type\TraitMemcacheCommand;
+use Friendica\Core\Cache\Enum\Type;
+use Friendica\Core\Config\IConfig;
+use Memcache;
+
+/**
+ * Memcache Cache
+ */
+class MemcacheCache extends BaseCache implements IMemoryCache
+{
+ use TraitCompareSet;
+ use TraitCompareDelete;
+ use TraitMemcacheCommand;
+
+ /**
+ * @var Memcache
+ */
+ private $memcache;
+
+ /**
+ * @throws Exception
+ */
+ public function __construct(string $hostname, IConfig $config)
+ {
+ if (!class_exists('Memcache', false)) {
+ throw new Exception('Memcache class isn\'t available');
+ }
+
+ parent::__construct($hostname);
+
+ $this->memcache = new Memcache();
+
+ $this->server = $config->get('system', 'memcache_host');;
+ $this->port = $config->get('system', 'memcache_port');
+
+ if (!@$this->memcache->connect($this->server, $this->port)) {
+ throw new Exception('Expected Memcache server at ' . $this->server . ':' . $this->port . ' isn\'t available');
+ }
+ }
+
+ /**
+ * (@inheritdoc)
+ */
+ public function getAllKeys($prefix = null)
+ {
+ $keys = $this->getOriginalKeys($this->getMemcacheKeys());
+
+ 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 = Duration::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 = Duration::FIVE_MINUTES)
+ {
+ $cachekey = $this->getCacheKey($key);
+ return $this->memcache->add($cachekey, serialize($value), MEMCACHE_COMPRESSED, $ttl);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getName()
+ {
+ return Type::MEMCACHE;
+ }
+}
--- /dev/null
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Cache\Type;
+
+use Exception;
+use Friendica\Core\Cache\Enum\Duration;
+use Friendica\Core\Cache\IMemoryCache;
+use Friendica\Core\Cache\Type\TraitCompareDelete;
+use Friendica\Core\Cache\Type\TraitCompareSet;
+use Friendica\Core\Cache\Type\TraitMemcacheCommand;
+use Friendica\Core\Cache\Enum\Type;
+use Friendica\Core\Config\IConfig;
+use Memcached;
+use Psr\Log\LoggerInterface;
+
+/**
+ * Memcached Cache
+ */
+class MemcachedCache extends BaseCache implements IMemoryCache
+{
+ use TraitCompareSet;
+ use TraitCompareDelete;
+ use TraitMemcacheCommand;
+
+ /**
+ * @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, IConfig $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->server = $memcached_hosts[0][0] ?? 'localhost';
+ $this->port = $memcached_hosts[0][1] ?? 11211;
+
+ $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->getMemcacheKeys());
+
+ 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
+ $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 = Duration::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 = Duration::FIVE_MINUTES)
+ {
+ $cachekey = $this->getCacheKey($key);
+ return $this->memcached->add($cachekey, $value, $ttl);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getName()
+ {
+ return Type::MEMCACHED;
+ }
+}
--- /dev/null
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Cache\Type;
+
+use Friendica\Core\Cache\Enum\Duration;
+use Friendica\Core\Cache\ICache;
+use Friendica\Core\Cache\IMemoryCache;
+use Friendica\Util\Profiler;
+
+/**
+ * This class wraps cache driver so they can get profiled - in case the profiler is enabled
+ *
+ * It is using the decorator pattern (@see
+ */
+class ProfilerCache implements ICache, IMemoryCache
+{
+ /**
+ * @var ICache The original cache driver
+ */
+ private $cache;
+
+ /**
+ * @var Profiler The profiler of Friendica
+ */
+ private $profiler;
+
+ public function __construct(ICache $cache, Profiler $profiler)
+ {
+ $this->cache = $cache;
+ $this->profiler = $profiler;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getAllKeys($prefix = null)
+ {
+ $this->profiler->startRecording('cache');
+
+ $return = $this->cache->getAllKeys($prefix);
+
+ $this->profiler->stopRecording();
+
+ return $return;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get($key)
+ {
+ $this->profiler->startRecording('cache');
+
+ $return = $this->cache->get($key);
+
+ $this->profiler->stopRecording();
+
+ return $return;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function set($key, $value, $ttl = Duration::FIVE_MINUTES)
+ {
+ $this->profiler->startRecording('cache');
+
+ $return = $this->cache->set($key, $value, $ttl);
+
+ $this->profiler->stopRecording();
+
+ return $return;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function delete($key)
+ {
+ $this->profiler->startRecording('cache');
+
+ $return = $this->cache->delete($key);
+
+ $this->profiler->stopRecording();
+
+ return $return;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function clear($outdated = true)
+ {
+ $this->profiler->startRecording('cache');
+
+ $return = $this->cache->clear($outdated);
+
+ $this->profiler->stopRecording();
+
+ return $return;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function add($key, $value, $ttl = Duration::FIVE_MINUTES)
+ {
+ if ($this->cache instanceof IMemoryCache) {
+ $this->profiler->startRecording('cache');
+
+ $return = $this->cache->add($key, $value, $ttl);
+
+ $this->profiler->stopRecording();
+
+ return $return;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function compareSet($key, $oldValue, $newValue, $ttl = Duration::FIVE_MINUTES)
+ {
+ if ($this->cache instanceof IMemoryCache) {
+ $this->profiler->startRecording('cache');
+
+ $return = $this->cache->compareSet($key, $oldValue, $newValue, $ttl);
+
+ $this->profiler->stopRecording();
+
+ return $return;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function compareDelete($key, $value)
+ {
+ if ($this->cache instanceof IMemoryCache) {
+ $this->profiler->startRecording('cache');
+
+ $return = $this->cache->compareDelete($key, $value);
+
+ $this->profiler->stopRecording();
+
+ return $return;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function GetName()
+ {
+ return $this->cache->getName() . ' (with profiler)';
+ }
+}
--- /dev/null
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Cache\Type;
+
+use Exception;
+use Friendica\Core\Cache\Enum\Duration;
+use Friendica\Core\Cache\IMemoryCache;
+use Friendica\Core\Cache\Enum\Type;
+use Friendica\Core\Config\IConfig;
+use Redis;
+
+/**
+ * Redis Cache. This driver is based on Memcache driver
+ */
+class RedisCache extends BaseCache implements IMemoryCache
+{
+ /**
+ * @var Redis
+ */
+ private $redis;
+
+ /**
+ * @throws Exception
+ */
+ public function __construct(string $hostname, IConfig $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 (isset($redis_port) && !@$this->redis->connect($redis_host, $redis_port)) {
+ throw new Exception('Expected Redis server at ' . $redis_host . ':' . $redis_port . ' isn\'t available');
+ } elseif (!@$this->redis->connect($redis_host)) {
+ throw new Exception('Expected Redis server at ' . $redis_host . ' 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 = Duration::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);
+ $this->redis->del($cachekey);
+ // Redis doesn't have an error state for del()
+ return true;
+ }
+
+ /**
+ * (@inheritdoc)
+ */
+ public function clear($outdated = true)
+ {
+ if ($outdated) {
+ return true;
+ } else {
+ return $this->redis->flushAll();
+ }
+ }
+
+ /**
+ * (@inheritdoc)
+ */
+ public function add($key, $value, $ttl = Duration::FIVE_MINUTES)
+ {
+ $cachekey = $this->getCacheKey($key);
+ $cached = serialize($value);
+
+ return $this->redis->setnx($cachekey, $cached);
+ }
+
+ /**
+ * (@inheritdoc)
+ */
+ public function compareSet($key, $oldValue, $newValue, $ttl = Duration::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;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getName()
+ {
+ return Type::REDIS;
+ }
+}
--- /dev/null
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Cache\Type;
+
+use Friendica\Core\Cache\Enum\Duration;
+
+/**
+ * Trait TraitCompareSetDelete
+ *
+ * This Trait is to compensate non native "exclusive" sets/deletes in caches
+ */
+trait TraitCompareDelete
+{
+ abstract public function get($key);
+
+ abstract public function set($key, $value, $ttl = Duration::FIVE_MINUTES);
+
+ abstract public function delete($key);
+
+ abstract public function add($key, $value, $ttl = Duration::FIVE_MINUTES);
+
+ /**
+ * NonNative - Compares if the old value is set and removes it
+ *
+ * @param string $key The cache key
+ * @param mixed $value The old value we know and want to delete
+ * @return bool
+ */
+ public function compareDelete($key, $value) {
+ if ($this->add($key . "_lock", true)) {
+ if ($this->get($key) === $value) {
+ $this->delete($key);
+ $this->delete($key . "_lock");
+ return true;
+ } else {
+ $this->delete($key . "_lock");
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+}
--- /dev/null
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Cache\Type;
+
+use Friendica\Core\Cache\Enum\Duration;
+
+/**
+ * Trait TraitCompareSetDelete
+ *
+ * This Trait is to compensate non native "exclusive" sets/deletes in caches
+ */
+trait TraitCompareSet
+{
+ abstract public function get($key);
+
+ abstract public function set($key, $value, $ttl = Duration::FIVE_MINUTES);
+
+ abstract public function delete($key);
+
+ abstract public function add($key, $value, $ttl = Duration::FIVE_MINUTES);
+
+ /**
+ * NonNative - Compares if the old value is set and sets the new value
+ *
+ * @param string $key The cache key
+ * @param mixed $oldValue The old value we know from the cache
+ * @param mixed $newValue The new value we want to set
+ * @param int $ttl The cache lifespan, must be one of the Cache constants
+ *
+ * @return bool
+ */
+ public function compareSet($key, $oldValue, $newValue, $ttl = Duration::FIVE_MINUTES) {
+ if ($this->add($key . "_lock", true)) {
+ if ($this->get($key) === $oldValue) {
+ $this->set($key, $newValue, $ttl);
+ $this->delete($key . "_lock");
+ return true;
+ } else {
+ $this->delete($key . "_lock");
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+}
--- /dev/null
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Cache\Type;
+
+use Friendica\Network\HTTPException\InternalServerErrorException;
+
+/**
+ * Trait for Memcache to add a custom version of the
+ * method getAllKeys() since this isn't working anymore
+ *
+ * Adds the possibility to directly communicate with the memcache too
+ */
+trait TraitMemcacheCommand
+{
+ /**
+ * @var string server address
+ */
+ protected $server;
+
+ /**
+ * @var int server port
+ */
+ protected $port;
+
+ /**
+ * Retrieves the stored keys of the memcache instance
+ * Uses custom commands, which aren't bound to the used instance of the class
+ *
+ * @todo Due the fact that we use a custom command, there are race conditions possible:
+ * - $this->memcache(d) adds a key
+ * - $this->getMemcacheKeys is called directly "after"
+ * - But $this->memcache(d) isn't finished adding the key, so getMemcacheKeys doesn't find it
+ *
+ * @return array All keys of the memcache instance
+ *
+ * @throws InternalServerErrorException
+ */
+ protected function getMemcacheKeys()
+ {
+ $string = $this->sendMemcacheCommand("stats items");
+ $lines = explode("\r\n", $string);
+ $slabs = [];
+ $keys = [];
+
+ foreach ($lines as $line) {
+
+ if (preg_match("/STAT items:([\d]+):number ([\d]+)/", $line, $matches) &&
+ isset($matches[1]) &&
+ !in_array($matches[1], $keys)) {
+
+ $slabs[] = $matches[1];
+ $string = $this->sendMemcacheCommand("stats cachedump " . $matches[1] . " " . $matches[2]);
+ preg_match_all("/ITEM (.*?) /", $string, $matches);
+ $keys = array_merge($keys, $matches[1]);
+ }
+ }
+
+ return $keys;
+ }
+
+ /**
+ * Taken directly from memcache PECL source
+ * Sends a command to the memcache instance and returns the result
+ * as a string
+ *
+ * http://pecl.php.net/package/memcache
+ *
+ * @param string $command The command to send to the Memcache server
+ *
+ * @return string The returned buffer result
+ *
+ * @throws InternalServerErrorException In case the memcache server isn't available (anymore)
+ */
+ protected function sendMemcacheCommand(string $command)
+ {
+ $s = @fsockopen($this->server, $this->port);
+ if (!$s) {
+ throw new InternalServerErrorException("Cant connect to:" . $this->server . ':' . $this->port);
+ }
+
+ fwrite($s, $command . "\r\n");
+ $buf = '';
+
+ while (!feof($s)) {
+
+ $buf .= fgets($s, 256);
+
+ if (strpos($buf, "END\r\n") !== false) { // stat says end
+ break;
+ }
+
+ if (strpos($buf, "DELETED\r\n") !== false || strpos($buf, "NOT_FOUND\r\n") !== false) { // delete says these
+ break;
+ }
+
+ if (strpos($buf, "OK\r\n") !== false) { // flush_all says ok
+ break;
+ }
+ }
+
+ fclose($s);
+ return ($buf);
+ }
+}
namespace Friendica\Core\Lock;
use Friendica\Core\BaseLock;
-use Friendica\Core\Cache\Duration;
+use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Cache\IMemoryCache;
class CacheLock extends BaseLock
namespace Friendica\Core\Lock;
use Friendica\Core\BaseLock;
-use Friendica\Core\Cache\Duration;
+use Friendica\Core\Cache\Enum\Duration;
use Friendica\Database\Database;
use Friendica\Util\DateTimeFormat;
namespace Friendica\Core\Lock;
-use Friendica\Core\Cache\Duration;
+use Friendica\Core\Cache\Enum\Duration;
/**
* Lock Interface
namespace Friendica\Core\Lock;
use Friendica\Core\BaseLock;
-use Friendica\Core\Cache\Duration;
+use Friendica\Core\Cache\Enum\Duration;
class SemaphoreLock extends BaseLock
{
namespace Friendica\Core\Lock;
-use Friendica\Core\Cache\Type as CacheType;
+use Friendica\Core\Cache\Enum\Type as CacheType;
/**
* Enumeration for lock types
// Compare the current structure with the defined structure
// If the Lock is acquired, never release it automatically to avoid double updates
- if (DI::lock()->acquire('dbupdate', 0, Cache\Duration::INFINITE)) {
+ if (DI::lock()->acquire('dbupdate', 0, Cache\Enum\Duration::INFINITE)) {
Logger::notice('Update starting.', ['from' => $stored, 'to' => $current]);
// If the update fails or times-out completely you may need to
// delete the config entry to try again.
- if (DI::lock()->acquire('dbupdate_function', 120, Cache\Duration::INFINITE)) {
+ if (DI::lock()->acquire('dbupdate_function', 120, Cache\Enum\Duration::INFINITE)) {
// call the specific update
Logger::notice('Pre update function start.', ['function' => $funcname]);
+++ /dev/null
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * 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
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Factory;
-
-use Friendica\App\BaseURL;
-use Friendica\Core\Cache;
-use Friendica\Core\Cache\ICache;
-use Friendica\Core\Config\IConfig;
-use Friendica\Database\Database;
-use Friendica\Util\Profiler;
-use Psr\Log\LoggerInterface;
-
-/**
- * Class CacheFactory
- *
- * @package Friendica\Core\Cache
- *
- * A basic class to generate a CacheDriver
- */
-class CacheFactory
-{
- /**
- * @var string The default cache if nothing set
- */
- const DEFAULT_TYPE = Cache\Type::DATABASE;
-
- /**
- * @var IConfig The IConfiguration to read parameters out of the config
- */
- private $config;
-
- /**
- * @var Database The database connection in case that the cache is used the dba connection
- */
- private $dba;
-
- /**
- * @var string The hostname, used as Prefix for Caching
- */
- private $hostname;
-
- /**
- * @var Profiler The optional profiler if the cached should be profiled
- */
- private $profiler;
-
- /**
- * @var LoggerInterface The Friendica Logger
- */
- private $logger;
-
- public function __construct(BaseURL $baseURL, IConfig $config, Database $dba, Profiler $profiler, LoggerInterface $logger)
- {
- $this->hostname = $baseURL->getHostname();
- $this->config = $config;
- $this->dba = $dba;
- $this->profiler = $profiler;
- $this->logger = $logger;
- }
-
- /**
- * This method creates a CacheDriver for the given cache driver name
- *
- * @param string $type The cache type to create (default is per config)
- *
- * @return ICache The instance of the CacheDriver
- * @throws \Exception The exception if something went wrong during the CacheDriver creation
- */
- public function create(string $type = null)
- {
- if (empty($type)) {
- $type = $this->config->get('system', 'cache_driver', self::DEFAULT_TYPE);
- }
-
- switch ($type) {
- case Cache\Type::MEMCACHE:
- $cache = new Cache\MemcacheCache($this->hostname, $this->config);
- break;
- case Cache\Type::MEMCACHED:
- $cache = new Cache\MemcachedCache($this->hostname, $this->config, $this->logger);
- break;
- case Cache\Type::REDIS:
- $cache = new Cache\RedisCache($this->hostname, $this->config);
- break;
- case Cache\Type::APCU:
- $cache = new Cache\APCuCache($this->hostname);
- break;
- default:
- $cache = new Cache\DatabaseCache($this->hostname, $this->dba);
- }
-
- $profiling = $this->config->get('system', 'profiling', false);
-
- // In case profiling is enabled, wrap the ProfilerCache around the current cache
- if (isset($profiling) && $profiling !== false) {
- return new Cache\ProfilerCache($cache, $this->profiler);
- } else {
- return $cache;
- }
- }
-}
namespace Friendica\Factory;
+use Friendica\Core\Cache\Factory\CacheFactory;
use Friendica\Core\Cache\IMemoryCache;
-use Friendica\Core\Cache\Type;
+use Friendica\Core\Cache\Enum\Type;
use Friendica\Core\Config\IConfig;
use Friendica\Core\Lock;
use Friendica\Database\Database;
use Friendica\App;
use Friendica\Core\Cache\ICache;
-use Friendica\Core\Cache\Type;
+use Friendica\Core\Cache\Enum\Type;
use Friendica\Core\Config\IConfig;
use Friendica\Core\Session;
use Friendica\Core\System;
namespace Friendica\Model;
use Friendica\Content\Text\HTML;
-use Friendica\Core\Cache\Duration;
+use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Logger;
use Friendica\Core\System;
use Friendica\Database\DBA;
namespace Friendica\Model;
-use Friendica\Core\Cache\Duration;
+use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Logger;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\App;
use Friendica\Content\Text\BBCode;
use Friendica\Content\Widget\ContactBlock;
-use Friendica\Core\Cache\Duration;
+use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Hook;
use Friendica\Core\Logger;
use Friendica\Core\Protocol;
namespace Friendica\Model;
use Friendica\Content\Text\BBCode;
-use Friendica\Core\Cache\Duration;
+use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Logger;
use Friendica\Core\Protocol;
use Friendica\Core\System;
use Friendica\Content\Pager;
use Friendica\Content\Text\HTML;
use Friendica\Content\Widget;
-use Friendica\Core\Cache\Duration;
+use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Logger;
use Friendica\Core\Renderer;
use Friendica\Core\Search;
use Friendica\Content\Feature;
use Friendica\Content\Text\BBCode;
-use Friendica\Core\Cache\Duration;
+use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Logger;
use Friendica\Core\Protocol;
use Friendica\Core\System;
use Friendica\Content\Feature;
use Friendica\Content\Text\BBCode;
use Friendica\Content\Text\Markdown;
-use Friendica\Core\Cache\Duration;
+use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Logger;
use Friendica\Core\Protocol;
use Friendica\Core\System;
use Friendica\Content\PageInfo;
use Friendica\Content\Text\BBCode;
use Friendica\Content\Text\HTML;
-use Friendica\Core\Cache\Duration;
+use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Logger;
use Friendica\Core\Protocol;
use Friendica\Database\DBA;
use DOMXPath;
use Friendica\Content\Text\BBCode;
use Friendica\Content\Text\HTML;
-use Friendica\Core\Cache\Duration;
+use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Logger;
use Friendica\Core\Protocol;
use Friendica\Database\DBA;
namespace Friendica\Util;
-use Friendica\Core\Cache\Duration;
+use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Logger;
use Exception;
use Friendica\DI;
namespace Friendica\Worker;
-use Friendica\Core\Cache\Duration;
+use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Logger;
use Friendica\Core\Search;
use Friendica\DI;
]
],
Cache\ICache::class => [
- 'instanceOf' => Factory\CacheFactory::class,
+ 'instanceOf' => Cache\Factory\CacheFactory::class,
'call' => [
['create', [], Dice::CHAIN_CALL],
],
],
Cache\IMemoryCache::class => [
- 'instanceOf' => Factory\CacheFactory::class,
+ 'instanceOf' => Cache\Factory\CacheFactory::class,
'call' => [
['create', [], Dice::CHAIN_CALL],
],
namespace Friendica\Test\src\Core\Cache;
-use Friendica\Core\Cache\APCuCache;
+use Friendica\Core\Cache\Type\APCuCache;
/**
* @group APCU
namespace Friendica\Test\src\Core\Cache;
-use Friendica\Core\Cache\ArrayCache;
+use Friendica\Core\Cache\Type\ArrayCache;
class ArrayCacheTest extends MemoryCacheTest
{
$dba = new StaticDatabase($configCache, $profiler, $logger);
- $this->cache = new Cache\DatabaseCache('database', $dba);
+ $this->cache = new Cache\Type\DatabaseCache('database', $dba);
return $this->cache;
}
namespace Friendica\Test\src\Core\Cache;
use Exception;
-use Friendica\Core\Cache\MemcacheCache;
+use Friendica\Core\Cache\Type\MemcacheCache;
use Friendica\Core\Config\IConfig;
use Mockery;
namespace Friendica\Test\src\Core\Cache;
use Exception;
-use Friendica\Core\Cache\MemcachedCache;
+use Friendica\Core\Cache\Type\MemcachedCache;
use Friendica\Core\Config\IConfig;
use Mockery;
use Psr\Log\NullLogger;
namespace Friendica\Test\src\Core\Cache;
use Exception;
-use Friendica\Core\Cache\RedisCache;
+use Friendica\Core\Cache\Type\RedisCache;
use Friendica\Core\Config\IConfig;
use Mockery;
->andReturn(null);
try {
- $this->cache = new RedisCache($host, $configMock);
+ $this->cache = new \Friendica\Core\Cache\Type\RedisCache($host, $configMock);
} catch (Exception $e) {
static::markTestSkipped('Redis is not available. Failure: ' . $e->getMessage());
}
namespace Friendica\Test\src\Core\Lock;
-use Friendica\Core\Cache\APCuCache;
+use Friendica\Core\Cache\Type\APCuCache;
use Friendica\Core\Lock\CacheLock;
/**
namespace Friendica\Test\src\Core\Lock;
-use Friendica\Core\Cache\ArrayCache;
+use Friendica\Core\Cache\Type\ArrayCache;
use Friendica\Core\Lock\CacheLock;
class ArrayCacheLockTest extends LockTest
namespace Friendica\Test\src\Core\Lock;
use Exception;
-use Friendica\Core\Cache\MemcacheCache;
+use Friendica\Core\Cache\Type\MemcacheCache;
use Friendica\Core\Config\IConfig;
use Friendica\Core\Lock\CacheLock;
use Mockery;
namespace Friendica\Test\src\Core\Lock;
use Exception;
-use Friendica\Core\Cache\MemcachedCache;
+use Friendica\Core\Cache\Type\MemcachedCache;
use Friendica\Core\Config\IConfig;
use Friendica\Core\Lock\CacheLock;
use Mockery;
namespace Friendica\Test\src\Core\Lock;
use Exception;
-use Friendica\Core\Cache\RedisCache;
+use Friendica\Core\Cache\Type\RedisCache;
use Friendica\Core\Config\IConfig;
use Friendica\Core\Lock\CacheLock;
use Mockery;