From d8c400bf582e3b11f6c78179b1e38fefec3ad8e1 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 24 Aug 2017 09:48:32 +0200 Subject: [PATCH] [Cache] Fix lazy Memcached connections --- .../Component/Cache/Traits/MemcachedTrait.php | 45 ++++++++++++++----- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Component/Cache/Traits/MemcachedTrait.php b/src/Symfony/Component/Cache/Traits/MemcachedTrait.php index 9dc44355c042a..8a836bac18c45 100644 --- a/src/Symfony/Component/Cache/Traits/MemcachedTrait.php +++ b/src/Symfony/Component/Cache/Traits/MemcachedTrait.php @@ -30,6 +30,7 @@ trait MemcachedTrait ); private $client; + private $lazyClient; public static function isSupported() { @@ -41,14 +42,18 @@ private function init(\Memcached $client, $namespace, $defaultLifetime) if (!static::isSupported()) { throw new CacheException('Memcached >= 2.2.0 is required'); } - $opt = $client->getOption(\Memcached::OPT_SERIALIZER); - if (\Memcached::SERIALIZER_PHP !== $opt && \Memcached::SERIALIZER_IGBINARY !== $opt) { - throw new CacheException('MemcachedAdapter: "serializer" option must be "php" or "igbinary".'); + if (get_class($client) === 'Memcached') { + $opt = $client->getOption(\Memcached::OPT_SERIALIZER); + if (\Memcached::SERIALIZER_PHP !== $opt && \Memcached::SERIALIZER_IGBINARY !== $opt) { + throw new CacheException('MemcachedAdapter: "serializer" option must be "php" or "igbinary".'); + } + $this->maxIdLength -= strlen($client->getOption(\Memcached::OPT_PREFIX_KEY)); + $this->client = $client; + } else { + $this->lazyClient = $client; } - $this->maxIdLength -= strlen($client->getOption(\Memcached::OPT_PREFIX_KEY)); parent::__construct($namespace, $defaultLifetime); - $this->client = $client; } /** @@ -191,7 +196,7 @@ protected function doSave(array $values, $lifetime) $lifetime += time(); } - return $this->checkResultCode($this->client->setMulti($values, $lifetime)); + return $this->checkResultCode($this->getClient()->setMulti($values, $lifetime)); } /** @@ -201,7 +206,7 @@ protected function doFetch(array $ids) { $unserializeCallbackHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback'); try { - return $this->checkResultCode($this->client->getMulti($ids)); + return $this->checkResultCode($this->getClient()->getMulti($ids)); } catch (\Error $e) { throw new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine()); } finally { @@ -214,7 +219,7 @@ protected function doFetch(array $ids) */ protected function doHave($id) { - return false !== $this->client->get($id) || $this->checkResultCode(\Memcached::RES_SUCCESS === $this->client->getResultCode()); + return false !== $this->getClient()->get($id) || $this->checkResultCode(\Memcached::RES_SUCCESS === $this->client->getResultCode()); } /** @@ -223,7 +228,7 @@ protected function doHave($id) protected function doDelete(array $ids) { $ok = true; - foreach ($this->checkResultCode($this->client->deleteMulti($ids)) as $result) { + foreach ($this->checkResultCode($this->getClient()->deleteMulti($ids)) as $result) { if (\Memcached::RES_SUCCESS !== $result && \Memcached::RES_NOTFOUND !== $result) { $ok = false; } @@ -237,7 +242,7 @@ protected function doDelete(array $ids) */ protected function doClear($namespace) { - return $this->checkResultCode($this->client->flush()); + return $this->checkResultCode($this->getClient()->flush()); } private function checkResultCode($result) @@ -250,4 +255,24 @@ private function checkResultCode($result) throw new CacheException(sprintf('MemcachedAdapter client error: %s.', strtolower($this->client->getResultMessage()))); } + + /** + * @return \Memcached + */ + private function getClient() + { + if ($this->client) { + return $this->client; + } + + $opt = $this->lazyClient->getOption(\Memcached::OPT_SERIALIZER); + if (\Memcached::SERIALIZER_PHP !== $opt && \Memcached::SERIALIZER_IGBINARY !== $opt) { + throw new CacheException('MemcachedAdapter: "serializer" option must be "php" or "igbinary".'); + } + if ('' !== $prefix = (string) $this->lazyClient->getOption(\Memcached::OPT_PREFIX_KEY)) { + throw new CacheException(sprintf('MemcachedAdapter: "prefix_key" option must be empty when using proxified connections, "%s" given.', $prefix)); + } + + return $this->client = $this->lazyClient; + } }