You are here

class MemcachedBackend in Memcache Storage 8

Hierarchy

Expanded class hierarchy of MemcachedBackend

File

src/MemcachedBackend.php, line 10

Namespace

Drupal\memcache_storage
View source
class MemcachedBackend implements CacheBackendInterface {

  /**
   * Cache bin name.
   *
   * @var string
   */
  protected $bin;

  /**
   * An object that handles memcached requests.
   * Point your attention that it is not \Memcache or \Memcached object.
   *
   * @var \Drupal\memcache_storage\DrupalMemcachedInterface
   */
  protected $memcached;

  /**
   * Drupal settings object.
   *
   * @var \Drupal\Core\Site\Settings
   */
  protected $settings;

  /**
   * An object that handles invalidation by tags.
   *
   * @var \Drupal\Core\Cache\CacheTagsChecksumInterface
   */
  protected $checksumProvider;

  /**
   * Contructs MemcachedBackend object.
   *
   * @param $bin
   *   Cache bin name.
   *
   * @param \Drupal\memcache_storage\DrupalMemcachedInterface $memcached
   *   An object that handles memcached requests.
   *   Point your attention that it is not \Memcache or \Memcached object.
   *
   * @param \Drupal\Core\Site\Settings $settings
   *   Drupal settings object.
   *
   * @param \Drupal\Core\Cache\CacheTagsChecksumInterface $checksum_provider
   *   An object that handles invalidation by tags.
   */
  public function __construct($bin, DrupalMemcachedInterface $memcached, Settings $settings, CacheTagsChecksumInterface $checksum_provider) {
    $this->bin = $bin;
    $this->memcached = $memcached;
    $this->settings = $settings;
    $this->checksumProvider = $checksum_provider;
  }

  /**
   * {@inheritdoc}
   */
  public function get($cid, $allow_invalid = FALSE) {
    $cids = array(
      $cid,
    );
    $cache = $this
      ->getMultiple($cids, $allow_invalid);
    return reset($cache);
  }

  /**
   * {@inheritdoc}
   */
  public function getMultiple(&$cids, $allow_invalid = FALSE) {

    // Handover get operation to the DrupalMemcache(d) object.
    $cache = $this->memcached
      ->getMulti($cids, $this->bin);

    // Make sure that every item and its cache tags were not expired.
    foreach ($cache as $cid => $item) {
      if (!$this
        ->isValid($item) && !$allow_invalid) {
        unset($cache[$cid]);
      }
    }

    // Remove items from the referenced $cids array that we are returning,
    // per comment in Drupal\Core\Cache\CacheBackendInterface::getMultiple().
    $cids = array_diff($cids, array_keys($cache));
    return $cache;
  }

  /**
   * Validates a cached item.
   *
   * Checks that items are either permanent or did not expire.
   */
  protected function isValid($cache) {
    if (!isset($cache->data)) {
      return FALSE;
    }

    // Check expire time.
    $cache->valid = $cache->expire == Cache::PERMANENT || $cache->expire >= REQUEST_TIME;

    // Make sure that cache tags were not expired.
    if (!$this->checksumProvider
      ->isValid($cache->checksum, $cache->tags)) {
      $cache->valid = FALSE;
    }
    return $cache->valid;
  }

  /**
   * {@inheritdoc}
   */
  public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = []) {
    $this
      ->setMultiple([
      $cid => [
        'data' => $data,
        'expire' => $expire,
        'tags' => $tags,
      ],
    ]);
  }

  /**
   * {@inheritdoc}
   */
  public function setMultiple(array $items) {
    $values = array();
    foreach ($items as $cid => $item) {

      // All items should have expiration data and initialized tags value.
      $item += array(
        'expire' => CacheBackendInterface::CACHE_PERMANENT,
        'tags' => array(),
      );
      assert('\\Drupal\\Component\\Assertion\\Inspector::assertAllStrings($item[\'tags\'])', 'Cache Tags must be strings.');

      // Organize tags.
      $item['tags'] = array_unique($item['tags']);
      sort($item['tags']);

      // Create a new object which will be passed to the memcached server for
      // storage.
      $value = new \stdClass();
      $value->cid = $cid;
      $value->expire = $item['expire'];
      $value->created = round(microtime(TRUE), 3);
      $value->tags = $item['tags'];
      $value->checksum = $this->checksumProvider
        ->getCurrentChecksum($item['tags']);
      $value->data = $item['data'];
      $values[] = $value;
    }
    if (empty($values)) {
      return TRUE;
    }

    // Handover set operation to DrupalMemcache(d) object.
    return $this->memcached
      ->setMulti($values, $this->bin);
  }

  /**
   * {@inheritdoc}
   */
  public function delete($cid) {
    $this
      ->deleteMultiple(array(
      $cid,
    ));
  }

  /**
   * {@inheritdoc}
   */
  public function deleteMultiple(array $cids) {
    $this->memcached
      ->deleteMulti($cids, $this->bin);
  }

  /**
   * {@inheritdoc}
   */
  public function deleteAll() {
    $this->memcached
      ->flush($this->bin);
  }

  /**
   * {@inheritdoc}
   */
  public function invalidate($cid) {
    $this
      ->invalidateMultiple(array(
      $cid,
    ));
  }

  /**
   * {@inheritdoc}
   */
  public function invalidateMultiple(array $cids) {
    $this
      ->deleteMultiple($cids);
  }

  /**
   * {@inheritdoc}
   */
  public function invalidateAll() {
    $this
      ->deleteAll();
  }

  /**
   * {@inheritdoc}
   */
  public function garbageCollection() {

    // Nothing to do here, because memcached wipes expired items itself.
  }

  /**
   * We could just leave this method empty, because memcached
   * doesn't support real deletion of cache bin. But instead
   * we increase the bin internal index to catch the case when
   * the bin was removed and then added again.
   */
  public function removeBin() {
    $this->memcached
      ->flush($this->bin);
  }

}

Members

Namesort descending Modifiers Type Description Overrides
CacheBackendInterface::CACHE_PERMANENT constant Indicates that the item should never be removed unless explicitly deleted.
MemcachedBackend::$bin protected property Cache bin name.
MemcachedBackend::$checksumProvider protected property An object that handles invalidation by tags.
MemcachedBackend::$memcached protected property An object that handles memcached requests. Point your attention that it is not \Memcache or \Memcached object.
MemcachedBackend::$settings protected property Drupal settings object.
MemcachedBackend::delete public function Deletes an item from the cache. Overrides CacheBackendInterface::delete
MemcachedBackend::deleteAll public function Deletes all cache items in a bin. Overrides CacheBackendInterface::deleteAll
MemcachedBackend::deleteMultiple public function Deletes multiple items from the cache. Overrides CacheBackendInterface::deleteMultiple
MemcachedBackend::garbageCollection public function Performs garbage collection on a cache bin. Overrides CacheBackendInterface::garbageCollection
MemcachedBackend::get public function Returns data from the persistent cache. Overrides CacheBackendInterface::get
MemcachedBackend::getMultiple public function Returns data from the persistent cache when given an array of cache IDs. Overrides CacheBackendInterface::getMultiple
MemcachedBackend::invalidate public function Marks a cache item as invalid. Overrides CacheBackendInterface::invalidate
MemcachedBackend::invalidateAll public function Marks all cache items as invalid. Overrides CacheBackendInterface::invalidateAll
MemcachedBackend::invalidateMultiple public function Marks cache items as invalid. Overrides CacheBackendInterface::invalidateMultiple
MemcachedBackend::isValid protected function Validates a cached item.
MemcachedBackend::removeBin public function We could just leave this method empty, because memcached doesn't support real deletion of cache bin. But instead we increase the bin internal index to catch the case when the bin was removed and then added again. Overrides CacheBackendInterface::removeBin
MemcachedBackend::set public function Stores data in the persistent cache. Overrides CacheBackendInterface::set
MemcachedBackend::setMultiple public function Store multiple items in the persistent cache. Overrides CacheBackendInterface::setMultiple
MemcachedBackend::__construct public function Contructs MemcachedBackend object.