core/core.services.yml | 2 + core/lib/Drupal/Core/Cache/ApcuBackend.php | 56 +++++++++++++++-------- core/lib/Drupal/Core/Cache/ApcuBackendFactory.php | 25 ++++++++++ 3 files changed, 64 insertions(+), 19 deletions(-) diff --git a/core/core.services.yml b/core/core.services.yml index bb8e4bc..b4f9bdd 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -25,6 +25,8 @@ services: cache.backend.database: class: Drupal\Core\Cache\DatabaseBackendFactory arguments: ['@database'] + cache.backend.apcu: + class: Drupal\Core\Cache\ApcuBackendFactory cache.bootstrap: class: Drupal\Core\Cache\CacheBackendInterface tags: diff --git a/core/lib/Drupal/Core/Cache/ApcuBackend.php b/core/lib/Drupal/Core/Cache/ApcuBackend.php index bb274d7..9670e01 100644 --- a/core/lib/Drupal/Core/Cache/ApcuBackend.php +++ b/core/lib/Drupal/Core/Cache/ApcuBackend.php @@ -8,7 +8,7 @@ namespace Drupal\Core\Cache; /** - * Stores cache items in the Alternative PHP Cache (APC). + * Stores cache items in the Alternative PHP Cache User Cache (APCu). */ class ApcuBackend implements CacheBackendInterface { @@ -73,9 +73,9 @@ public function __construct($bin, $site_prefix) { * The cache item ID to prefix. * * @return string - * The APC key for the cache item ID. + * The APCu key for the cache item ID. */ - protected function getApcKey($cid) { + protected function getApcuKey($cid) { return $this->binPrefix . $cid; } @@ -83,7 +83,7 @@ protected function getApcKey($cid) { * {@inheritdoc} */ public function get($cid, $allow_invalid = FALSE) { - $cache = apc_fetch($this->getApcKey($cid)); + $cache = apc_fetch($this->getApcuKey($cid)); return $this->prepareItem($cache, $allow_invalid); } @@ -91,10 +91,10 @@ public function get($cid, $allow_invalid = FALSE) { * {@inheritdoc} */ public function getMultiple(&$cids, $allow_invalid = FALSE) { - // Translate the requested cache item IDs to APC keys. + // Translate the requested cache item IDs to APCu keys. $map = array(); foreach ($cids as $cid) { - $map[$this->getApcKey($cid)] = $cid; + $map[$this->getApcuKey($cid)] = $cid; } $result = apc_fetch(array_keys($map)); @@ -114,12 +114,12 @@ public function getMultiple(&$cids, $allow_invalid = FALSE) { /** * Returns all cached items, optionally limited by a cache ID prefix. * - * APC is a memory cache, shared across all server processes. To prevent cache - * item clashes with other applications/installations, every cache item is - * prefixed with a unique string for this application. Therefore, functions - * like apc_clear_cache() cannot be used, and instead, a list of all cache - * items belonging to this application need to be retrieved through this - * method instead. + * APCu is a memory cache, shared across all server processes. To prevent + * cache item clashes with other applications/installations, every cache item + * is prefixed with a unique string for this site. Therefore, functions like + * apc_clear_cache() cannot be used, and instead, a list of all cache items + * belonging to this application need to be retrieved through this method + * instead. * * @param string $prefix * (optional) A cache ID prefix to limit the result to. @@ -128,7 +128,7 @@ public function getMultiple(&$cids, $allow_invalid = FALSE) { * An APCIterator containing matched items. */ public function getAll($prefix = '') { - return new \APCIterator('user', '/^' . preg_quote($this->getApcKey($prefix), '/') . '/'); + return new \APCIterator('user', '/^' . preg_quote($this->getApcuKey($prefix), '/') . '/'); } /** @@ -136,8 +136,11 @@ public function getAll($prefix = '') { * * Checks that the item is either permanent or did not expire. * - * @param stdClass $cache + * @param \stdClass $cache * An item loaded from cache_get() or cache_get_multiple(). + * @param bool $allow_invalid + * If TRUE, a cache item may be returned even if it is expired or has been + * invalidated. See ::get(). * * @return mixed * The cache item or FALSE if the item expired. @@ -186,22 +189,36 @@ public function set($cid, $data, $expire = CacheBackendInterface::CACHE_PERMANEN $cache->data = $data; // apc_store()'s $ttl argument can be omitted but also set to 0 (zero), - // which happens to be identical to CACHE_PERMANENT. - apc_store($this->getApcKey($cid), $cache, $expire); + // in which case the value will persist until it's removed from the cache or + // until the next cache clear, restart, etc. This is what we want to do + // when $expire equals CacheBackendInterface::CACHE_PERMANENT. + if ($expire === CacheBackendInterface::CACHE_PERMANENT) { + $expire = 0; + } + apc_store($this->getApcuKey($cid), $cache, $expire); + } + + /** + * {@inheritdoc + */ + public function setMultiple(array $items = array()) { + foreach ($items as $cid => $item) { + $this->set($cid, $item['data'], isset($item['expire']) ? $item['expire'] : CacheBackendInterface::CACHE_PERMANENT, isset($item['tags']) ? $item['tags'] : array()); + } } /** * {@inheritdoc} */ public function delete($cid) { - apc_delete($this->getApcKey($cid)); + apc_delete($this->getApcuKey($cid)); } /** * {@inheritdoc} */ public function deleteMultiple(array $cids) { - apc_delete(array_map(array($this, 'getApcKey'), $cids)); + apc_delete(array_map(array($this, 'getApcuKey'), $cids)); } /** @@ -223,7 +240,8 @@ public function garbageCollection() { * {@inheritdoc} */ public function removeBin() { - apc_clear_cache('user'); + $this->deleteAll(); + apc_delete(new \APCIterator('user', '/^' . preg_quote($this->tagsPrefix, '/') . '/')); } /** diff --git a/core/lib/Drupal/Core/Cache/ApcuBackendFactory.php b/core/lib/Drupal/Core/Cache/ApcuBackendFactory.php index e69de29..a18fc6f 100644 --- a/core/lib/Drupal/Core/Cache/ApcuBackendFactory.php +++ b/core/lib/Drupal/Core/Cache/ApcuBackendFactory.php @@ -0,0 +1,25 @@ +