Updated all the contrib modules to their latest versions.
[yaffs-website] / web / modules / contrib / memcache / src / MemcacheBackend.php
index 13b6da731136ec91fc050cc20a0da5ce7618629d..d85de8e7504505c223095bf174b14e44d3643084 100644 (file)
@@ -1,16 +1,11 @@
 <?php
 
-/**
- * @file
- * Contains \Drupal\memcache\MemcacheBackend.
- */
-
 namespace Drupal\memcache;
 
-use Drupal\Core\Cache\Cache;
+use Drupal\Component\Assertion\Inspector;
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Cache\CacheTagsChecksumInterface;
-use Drupal\Core\Lock\LockBackendInterface;
+use Drupal\memcache\Invalidator\TimestampInvalidatorInterface;
 
 /**
  * Defines a Memcache cache backend.
@@ -25,11 +20,11 @@ class MemcacheBackend implements CacheBackendInterface {
   protected $bin;
 
   /**
-   * The lock count.
+   * The (micro)time the bin was last deleted.
    *
-   * @var int
+   * @var float
    */
-  protected $lockCount = 0;
+  protected $lastBinDeletionTime;
 
   /**
    * The memcache wrapper object.
@@ -39,53 +34,45 @@ class MemcacheBackend implements CacheBackendInterface {
   protected $memcache;
 
   /**
-   * The lock backend that should be used.
-   *
-   * @var \Drupal\Core\Lock\LockBackendInterface
-   */
-  protected $lock;
-
-  /**
-   * The Settings instance.
+   * The cache tags checksum provider.
    *
-   * @var \Drupal\memcache\DrupalMemcacheConfig
+   * @var \Drupal\Core\Cache\CacheTagsChecksumInterface|\Drupal\Core\Cache\CacheTagsInvalidatorInterface
    */
-  protected $settings;
+  protected $checksumProvider;
 
   /**
-   * The cache tags checksum provider.
+   * The timestamp invalidation provider.
    *
-   * @var \Drupal\Core\Cache\CacheTagsChecksumInterface
+   * @var \Drupal\memcache\Invalidator\TimestampInvalidatorInterface
    */
-  protected $checksumProvider;
+  protected $timestampInvalidator;
 
   /**
    * Constructs a MemcacheBackend object.
-   *\Drupal\Core\Site\Settings
+   *
    * @param string $bin
    *   The bin name.
    * @param \Drupal\memcache\DrupalMemcacheInterface $memcache
    *   The memcache object.
-   * @param \Drupal\Core\Lock\LockBackendInterface $lock
-   *   The lock backend.
-   * @param \Drupal\memcache\DrupalMemcacheConfig $settings
-   *   The settings instance.
    * @param \Drupal\Core\Cache\CacheTagsChecksumInterface $checksum_provider
    *   The cache tags checksum service.
+   * @param \Drupal\memcache\Invalidator\TimestampInvalidatorInterface $timestamp_invalidator
+   *   The timestamp invalidation provider.
    */
-  public function __construct($bin, DrupalMemcacheInterface $memcache, LockBackendInterface $lock, DrupalMemcacheConfig $settings, CacheTagsChecksumInterface $checksum_provider) {
+  public function __construct($bin, DrupalMemcacheInterface $memcache, CacheTagsChecksumInterface $checksum_provider, TimestampInvalidatorInterface $timestamp_invalidator) {
     $this->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);
+    }
   }
 
 }