X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs-website;a=blobdiff_plain;f=web%2Fmodules%2Fcontrib%2Fmemcache%2Fsrc%2FMemcacheBackend.php;h=d85de8e7504505c223095bf174b14e44d3643084;hp=13b6da731136ec91fc050cc20a0da5ce7618629d;hb=059867c3f96750652c80f39e44c442a58c2549ee;hpb=f8fc16ae6b862bef59baaad5d051dd37b7ff11b2 diff --git a/web/modules/contrib/memcache/src/MemcacheBackend.php b/web/modules/contrib/memcache/src/MemcacheBackend.php index 13b6da731..d85de8e75 100644 --- a/web/modules/contrib/memcache/src/MemcacheBackend.php +++ b/web/modules/contrib/memcache/src/MemcacheBackend.php @@ -1,16 +1,11 @@ bin = $bin; $this->memcache = $memcache; - $this->lock = $lock; - $this->settings = $settings; $this->checksumProvider = $checksum_provider; + $this->timestampInvalidator = $timestamp_invalidator; + + $this->ensureBinDeletionTimeIsSet(); } /** * {@inheritdoc} */ public function get($cid, $allow_invalid = FALSE) { - $cids = array($cid); + $cids = [$cid]; $cache = $this->getMultiple($cids, $allow_invalid); return reset($cache); } @@ -94,14 +81,14 @@ class MemcacheBackend implements CacheBackendInterface { * {@inheritdoc} */ public function getMultiple(&$cids, $allow_invalid = FALSE) { - $keys = array_map(function($cid) { - return $this->key($cid); - }, $cids); - - $cache = $this->memcache->getMulti($keys); + $cache = $this->memcache->getMulti($cids); $fetched = []; - foreach ($cache as $key => $result) { + foreach ($cache as $result) { + if (!$this->timeIsGreaterThanBinDeletionTime($result->created)) { + continue; + } + if ($this->valid($result->cid, $result) || $allow_invalid) { // Add it to the fetched items to diff later. $fetched[$result->cid] = $result; @@ -126,51 +113,14 @@ class MemcacheBackend implements CacheBackendInterface { * The cache item. * * @return bool + * TRUE if valid, FALSE otherwise. */ protected function valid($cid, \stdClass $cache) { - $lock_key = "memcache_$cid:$this->bin"; - $cache->valid = FALSE; - - if ($cache) { - // Items that have expired are invalid. - if (isset($cache->expire) && ($cache->expire != CacheBackendInterface::CACHE_PERMANENT) && ($cache->expire <= REQUEST_TIME)) { - // If the memcache_stampede_protection variable is set, allow one - // process to rebuild the cache entry while serving expired content to - // the rest. - if ($this->settings->get('stampede_protection', FALSE)) { - // The process that acquires the lock will get a cache miss, all - // others will get a cache hit. - if (!$this->lock->acquire($lock_key, $this->settings->get('stampede_semaphore', 15))) { - $cache->valid = TRUE; - } - } - } - else { - $cache->valid = TRUE; - } - } - // On cache misses, attempt to avoid stampedes when the - // memcache_stampede_protection variable is enabled. - else { - if ($this->settings->get('stampede_protection', FALSE) && !$this->lock->acquire($lock_key, $this->settings->get('stampede_semaphore', 15))) { - // Prevent any single request from waiting more than three times due to - // stampede protection. By default this is a maximum total wait of 15 - // seconds. This accounts for two possibilities - a cache and lock miss - // more than once for the same item. Or a cache and lock miss for - // different items during the same request. - // @todo: it would be better to base this on time waited rather than - // number of waits, but the lock API does not currently provide this - // information. Currently the limit will kick in for three waits of 25ms - // or three waits of 5000ms. - $this->lockCount++; - if ($this->lockCount <= $this->settings->get('stampede_wait_limit', 3)) { - // The memcache_stampede_semaphore variable was used in previous - // releases of memcache, but the max_wait variable was not, so by - // default divide the semaphore value by 3 (5 seconds). - $this->lock->wait($lock_key, $this->settings->get('stampede_wait_time', 5)); - $cache = $this->get($cid); - } - } + $cache->valid = TRUE; + + // Items that have expired are invalid. + if ($cache->expire != CacheBackendInterface::CACHE_PERMANENT && $cache->expire <= REQUEST_TIME) { + $cache->valid = FALSE; } // Check if invalidateTags() has been called with any of the items's tags. @@ -178,14 +128,16 @@ class MemcacheBackend implements CacheBackendInterface { $cache->valid = FALSE; } - return (bool) $cache->valid; + return $cache->valid; } /** * {@inheritdoc} */ - public function set($cid, $data, $expire = CacheBackendInterface::CACHE_PERMANENT, array $tags = array()) { - assert('\Drupal\Component\Assertion\Inspector::assertAllStrings($tags)'); + public function set($cid, $data, $expire = CacheBackendInterface::CACHE_PERMANENT, array $tags = []) { + assert(Inspector::assertAllStrings($tags)); + + $tags[] = "memcache:$this->bin"; $tags = array_unique($tags); // Sort the cache tags so that they are stored consistently. sort($tags); @@ -193,14 +145,14 @@ class MemcacheBackend implements CacheBackendInterface { // Create new cache object. $cache = new \stdClass(); $cache->cid = $cid; - $cache->data = is_object($data) ? clone $data : $data; + $cache->data = $data; $cache->created = round(microtime(TRUE), 3); $cache->expire = $expire; $cache->tags = $tags; $cache->checksum = $this->checksumProvider->getCurrentChecksum($tags); // Cache all items permanently. We handle expiration in our own logic. - return $this->memcache->set($this->key($cid), $cache); + return $this->memcache->set($cid, $cache); } /** @@ -208,10 +160,10 @@ class MemcacheBackend implements CacheBackendInterface { */ public function setMultiple(array $items) { foreach ($items as $cid => $item) { - $item += array( + $item += [ 'expire' => CacheBackendInterface::CACHE_PERMANENT, - 'tags' => array(), - ); + 'tags' => [], + ]; $this->set($cid, $item['data'], $item['expire'], $item['tags']); } @@ -221,7 +173,7 @@ class MemcacheBackend implements CacheBackendInterface { * {@inheritdoc} */ public function delete($cid) { - $this->memcache->delete($this->key($cid)); + $this->memcache->delete($cid); } /** @@ -229,7 +181,7 @@ class MemcacheBackend implements CacheBackendInterface { */ public function deleteMultiple(array $cids) { foreach ($cids as $cid) { - $this->memcache->delete($this->key($cid)); + $this->memcache->delete($cid); } } @@ -237,15 +189,14 @@ class MemcacheBackend implements CacheBackendInterface { * {@inheritdoc} */ public function deleteAll() { - // Invalidate all keys, as we can't actually delete all? - $this->invalidateAll(); + $this->lastBinDeletionTime = $this->timestampInvalidator->invalidateTimestamp($this->bin); } /** * {@inheritdoc} */ public function invalidate($cid) { - $this->invalidateMultiple((array) $cid); + $this->invalidateMultiple([$cid]); } /** @@ -266,7 +217,7 @@ class MemcacheBackend implements CacheBackendInterface { foreach ($cids as $cid) { if ($item = $this->get($cid)) { $item->expire = REQUEST_TIME - 1; - $this->memcache->set($this->key($cid), $item); + $this->memcache->set($cid, $item); } } } @@ -275,7 +226,7 @@ class MemcacheBackend implements CacheBackendInterface { * {@inheritdoc} */ public function invalidateAll() { - $this->memcache->flush(); + $this->invalidateTags(["memcache:$this->bin"]); } /** @@ -289,7 +240,7 @@ class MemcacheBackend implements CacheBackendInterface { * {@inheritdoc} */ public function removeBin() { - // Do nothing here too? + $this->lastBinDeletionTime = $this->timestampInvalidator->invalidateTimestamp($this->bin); } /** @@ -301,7 +252,7 @@ class MemcacheBackend implements CacheBackendInterface { } /** - * (@inheritdoc) + * {@inheritdoc} */ public function isEmpty() { // We do not know so err on the safe side? Not sure if we can know this? @@ -309,14 +260,54 @@ class MemcacheBackend implements CacheBackendInterface { } /** - * Returns a cache key prefixed with the current bin. + * Determines if a (micro)time is greater than the last bin deletion time. * - * @param string $cid + * @param float $item_microtime + * A given (micro)time. + * + * @internal + * + * @return bool + * TRUE if the (micro)time is greater than the last bin deletion time, FALSE + * otherwise. + */ + protected function timeIsGreaterThanBinDeletionTime($item_microtime) { + $last_bin_deletion = $this->getBinLastDeletionTime(); + + // If there is time, assume FALSE as there is no previous deletion time + // to compare with. + if (!$last_bin_deletion) { + return FALSE; + } + + return $item_microtime > $last_bin_deletion; + } + + /** + * Gets the last invalidation time for the bin. + * + * @internal * - * @return string + * @return float + * The last invalidation timestamp of the tag. */ - protected function key($cid) { - return $this->bin . '-' . $cid; + protected function getBinLastDeletionTime() { + if (!isset($this->lastBinDeletionTime)) { + $this->lastBinDeletionTime = $this->timestampInvalidator->getLastInvalidationTimestamp($this->bin); + } + + return $this->lastBinDeletionTime; + } + + /** + * Ensures a last bin deletion time has been set. + * + * @internal + */ + protected function ensureBinDeletionTimeIsSet() { + if (!$this->getBinLastDeletionTime()) { + $this->lastBinDeletionTime = $this->timestampInvalidator->invalidateTimestamp($this->bin); + } } }