diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 328894448ec..aaaa08de939 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -1939,6 +1939,7 @@ return array( 'OC\\Memcache\\Factory' => $baseDir . '/lib/private/Memcache/Factory.php', 'OC\\Memcache\\LoggerWrapperCache' => $baseDir . '/lib/private/Memcache/LoggerWrapperCache.php', 'OC\\Memcache\\Memcached' => $baseDir . '/lib/private/Memcache/Memcached.php', + 'OC\\Memcache\\MemcachedFactory' => $baseDir . '/lib/private/Memcache/MemcachedFactory.php', 'OC\\Memcache\\NullCache' => $baseDir . '/lib/private/Memcache/NullCache.php', 'OC\\Memcache\\ProfilerWrapperCache' => $baseDir . '/lib/private/Memcache/ProfilerWrapperCache.php', 'OC\\Memcache\\Redis' => $baseDir . '/lib/private/Memcache/Redis.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 90260142be6..9d62ce8d334 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -1980,6 +1980,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Memcache\\Factory' => __DIR__ . '/../../..' . '/lib/private/Memcache/Factory.php', 'OC\\Memcache\\LoggerWrapperCache' => __DIR__ . '/../../..' . '/lib/private/Memcache/LoggerWrapperCache.php', 'OC\\Memcache\\Memcached' => __DIR__ . '/../../..' . '/lib/private/Memcache/Memcached.php', + 'OC\\Memcache\\MemcachedFactory' => __DIR__ . '/../../..' . '/lib/private/Memcache/MemcachedFactory.php', 'OC\\Memcache\\NullCache' => __DIR__ . '/../../..' . '/lib/private/Memcache/NullCache.php', 'OC\\Memcache\\ProfilerWrapperCache' => __DIR__ . '/../../..' . '/lib/private/Memcache/ProfilerWrapperCache.php', 'OC\\Memcache\\Redis' => __DIR__ . '/../../..' . '/lib/private/Memcache/Redis.php', diff --git a/lib/private/Memcache/Memcached.php b/lib/private/Memcache/Memcached.php index a3d65d545ee..b67b0a90a4f 100644 --- a/lib/private/Memcache/Memcached.php +++ b/lib/private/Memcache/Memcached.php @@ -8,73 +8,18 @@ namespace OC\Memcache; -use OC\SystemConfig; -use OCP\HintException; -use OCP\IConfig; use OCP\IMemcache; -use OCP\Server; class Memcached extends Cache implements IMemcache { use CASTrait; - /** - * @var \Memcached $cache - */ - private static $cache = null; + private \Memcached $cache; use CADTrait; public function __construct($prefix = '') { parent::__construct($prefix); - if (is_null(self::$cache)) { - self::$cache = new \Memcached(); - - $defaultOptions = [ - \Memcached::OPT_CONNECT_TIMEOUT => 50, - \Memcached::OPT_RETRY_TIMEOUT => 50, - \Memcached::OPT_SEND_TIMEOUT => 50, - \Memcached::OPT_RECV_TIMEOUT => 50, - \Memcached::OPT_POLL_TIMEOUT => 50, - - // Enable compression - \Memcached::OPT_COMPRESSION => true, - - // Turn on consistent hashing - \Memcached::OPT_LIBKETAMA_COMPATIBLE => true, - - // Enable Binary Protocol - \Memcached::OPT_BINARY_PROTOCOL => true, - ]; - /** - * By default enable igbinary serializer if available - * - * Psalm checks depend on if igbinary is installed or not with memcached - * @psalm-suppress RedundantCondition - * @psalm-suppress TypeDoesNotContainType - */ - if (\Memcached::HAVE_IGBINARY) { - $defaultOptions[\Memcached::OPT_SERIALIZER] - = \Memcached::SERIALIZER_IGBINARY; - } - $options = Server::get(IConfig::class)->getSystemValue('memcached_options', []); - if (is_array($options)) { - $options = $options + $defaultOptions; - self::$cache->setOptions($options); - } else { - throw new HintException("Expected 'memcached_options' config to be an array, got $options"); - } - - $servers = Server::get(SystemConfig::class)->getValue('memcached_servers'); - if (!$servers) { - $server = Server::get(SystemConfig::class)->getValue('memcached_server'); - if ($server) { - $servers = [$server]; - } else { - $servers = [['localhost', 11211]]; - } - } - self::$cache->addServers($servers); - } + $this->cache = \OCP\Server::get(MemcachedFactory::class)->getInstance(); } /** @@ -86,8 +31,8 @@ class Memcached extends Cache implements IMemcache { #[\Override] public function get($key) { - $result = self::$cache->get($this->getNameSpace() . $key); - if ($result === false && self::$cache->getResultCode() === \Memcached::RES_NOTFOUND) { + $result = $this->cache->get($this->getNameSpace() . $key); + if ($result === false && $this->cache->getResultCode() === \Memcached::RES_NOTFOUND) { return null; } else { return $result; @@ -97,29 +42,29 @@ class Memcached extends Cache implements IMemcache { #[\Override] public function set($key, $value, $ttl = 0) { if ($ttl > 0) { - $result = self::$cache->set($this->getNameSpace() . $key, $value, $ttl); + $result = $this->cache->set($this->getNameSpace() . $key, $value, $ttl); } else { - $result = self::$cache->set($this->getNameSpace() . $key, $value); + $result = $this->cache->set($this->getNameSpace() . $key, $value); } return $result || $this->isSuccess(); } #[\Override] public function hasKey($key) { - self::$cache->get($this->getNameSpace() . $key); - return self::$cache->getResultCode() === \Memcached::RES_SUCCESS; + $this->cache->get($this->getNameSpace() . $key); + return $this->cache->getResultCode() === \Memcached::RES_SUCCESS; } #[\Override] public function remove($key) { - $result = self::$cache->delete($this->getNameSpace() . $key); - return $result || $this->isSuccess() || self::$cache->getResultCode() === \Memcached::RES_NOTFOUND; + $result = $this->cache->delete($this->getNameSpace() . $key); + return $result || $this->isSuccess() || $this->cache->getResultCode() === \Memcached::RES_NOTFOUND; } #[\Override] public function clear($prefix = '') { // Newer Memcached doesn't like getAllKeys(), flush everything - self::$cache->flush(); + $this->cache->flush(); return true; } @@ -133,7 +78,7 @@ class Memcached extends Cache implements IMemcache { */ #[\Override] public function add($key, $value, $ttl = 0) { - $result = self::$cache->add($this->getPrefix() . $key, $value, $ttl); + $result = $this->cache->add($this->getPrefix() . $key, $value, $ttl); return $result || $this->isSuccess(); } @@ -147,9 +92,9 @@ class Memcached extends Cache implements IMemcache { #[\Override] public function inc($key, $step = 1) { $this->add($key, 0); - $result = self::$cache->increment($this->getPrefix() . $key, $step); + $result = $this->cache->increment($this->getPrefix() . $key, $step); - if (self::$cache->getResultCode() !== \Memcached::RES_SUCCESS) { + if ($this->cache->getResultCode() !== \Memcached::RES_SUCCESS) { return false; } @@ -165,9 +110,9 @@ class Memcached extends Cache implements IMemcache { */ #[\Override] public function dec($key, $step = 1) { - $result = self::$cache->decrement($this->getPrefix() . $key, $step); + $result = $this->cache->decrement($this->getPrefix() . $key, $step); - if (self::$cache->getResultCode() !== \Memcached::RES_SUCCESS) { + if ($this->cache->getResultCode() !== \Memcached::RES_SUCCESS) { return false; } @@ -180,6 +125,6 @@ class Memcached extends Cache implements IMemcache { } private function isSuccess(): bool { - return self::$cache->getResultCode() === \Memcached::RES_SUCCESS; + return $this->cache->getResultCode() === \Memcached::RES_SUCCESS; } } diff --git a/lib/private/Memcache/MemcachedFactory.php b/lib/private/Memcache/MemcachedFactory.php new file mode 100644 index 00000000000..e829c72af65 --- /dev/null +++ b/lib/private/Memcache/MemcachedFactory.php @@ -0,0 +1,81 @@ +instance === null) { + $this->init(); + } + return $this->instance; + } + + /** @psalm-assert \Memcached $this->instance */ + public function init(): void { + $this->instance = new \Memcached(); + + $defaultOptions = [ + \Memcached::OPT_CONNECT_TIMEOUT => 50, + \Memcached::OPT_RETRY_TIMEOUT => 50, + \Memcached::OPT_SEND_TIMEOUT => 50, + \Memcached::OPT_RECV_TIMEOUT => 50, + \Memcached::OPT_POLL_TIMEOUT => 50, + + // Enable compression + \Memcached::OPT_COMPRESSION => true, + + // Turn on consistent hashing + \Memcached::OPT_LIBKETAMA_COMPATIBLE => true, + + // Enable Binary Protocol + \Memcached::OPT_BINARY_PROTOCOL => true, + ]; + /** + * By default enable igbinary serializer if available + * + * Psalm checks depend on if igbinary is installed or not with memcached + * @psalm-suppress RedundantCondition + * @psalm-suppress TypeDoesNotContainType + */ + if (\Memcached::HAVE_IGBINARY) { + $defaultOptions[\Memcached::OPT_SERIALIZER] + = \Memcached::SERIALIZER_IGBINARY; + } + $options = Server::get(IConfig::class)->getSystemValue('memcached_options', []); + if (is_array($options)) { + $options = $options + $defaultOptions; + $this->instance->setOptions($options); + } else { + throw new HintException("Expected 'memcached_options' config to be an array, got $options"); + } + + $servers = Server::get(SystemConfig::class)->getValue('memcached_servers'); + if (!$servers) { + $server = Server::get(SystemConfig::class)->getValue('memcached_server'); + if ($server) { + $servers = [$server]; + } else { + $servers = [['localhost', 11211]]; + } + } + $this->instance->addServers($servers); + } +}