You are here

public function ChainedFastBackend::getMultiple in Supercache 8

Same name and namespace in other branches
  1. 2.0.x src/Cache/ChainedFastBackend.php \Drupal\supercache\Cache\ChainedFastBackend::getMultiple()

Returns data from the persistent cache when given an array of cache IDs.

Parameters

array $cids: An array of cache IDs for the data to retrieve. This is passed by reference, and will have the IDs successfully returned from cache removed.

bool $allow_invalid: (optional) If TRUE, cache items may be returned even if they have expired or been invalidated. Such items may sometimes be preferred, if the alternative is recalculating the value stored in the cache, especially if another concurrent thread is already recalculating the same value. The "valid" property of the returned objects indicates whether the items are valid or not. Defaults to FALSE.

Return value

array An array of cache item objects indexed by cache ID.

Overrides CacheBackendInterface::getMultiple

See also

\Drupal\Core\Cache\CacheBackendInterface::get()

1 call to ChainedFastBackend::getMultiple()
ChainedFastBackend::get in src/Cache/ChainedFastBackend.php
Returns data from the persistent cache.

File

src/Cache/ChainedFastBackend.php, line 117
Contains \Drupal\supercache\Cache\ChainedFastBackend.

Class

ChainedFastBackend
Defines a backend with a fast and a consistent backend chain.

Namespace

Drupal\supercache\Cache

Code

public function getMultiple(&$cids, $allow_invalid = FALSE) {
  $cids_copy = $cids;
  $cache = array();

  // If we can determine the time at which the last write to the consistent
  // backend occurred (we might not be able to if it has been recently
  // flushed/restarted), then we can use that to validate items from the fast
  // backend, so try to get those first. Otherwise, we can't assume that
  // anything in the fast backend is valid, so don't even bother fetching
  // from there.
  $last_write_timestamp = $this
    ->getLastWrite();
  if ($last_write_timestamp) {

    // Items in the fast backend might be invalid based on their timestamp,
    // but we can't check the timestamp prior to getting the item, which
    // includes unserializing it. However, unserializing an invalid item can
    // throw an exception. For example, a __wakeup() implementation that
    // receives object properties containing references to code or data that
    // no longer exists in the application's current state.
    //
    // Unserializing invalid data, whether it throws an exception or not, is
    // a waste of time, but we only incur it while a cache invalidation has
    // not yet finished propagating to all the fast backend instances.
    //
    // Most cache backend implementations should not wrap their internal
    // get() implementations with a try/catch, because they have no reason to
    // assume that their data is invalid, and doing so would mask
    // unserialization errors of valid data. We do so here, only because the
    // fast backend is non-authoritative, and after discarding its
    // exceptions, we proceed to check the consistent (authoritative) backend
    // and allow exceptions from that to bubble up.
    try {
      $items = $this->fastBackend
        ->getMultiple($cids, $allow_invalid);
    } catch (\Exception $e) {
      $cids = $cids_copy;
      $items = array();
    }

    // Even if items were successfully fetched from the fast backend, they
    // are potentially invalid if older than the last time the bin was
    // written to in the consistent backend, so only keep ones that aren't.
    foreach ($items as $item) {
      if ($item->created < $last_write_timestamp) {
        $cids[array_search($item->cid, $cids_copy)] = $item->cid;
      }
      else {
        $cache[$item->cid] = $item;
      }
    }
  }

  // If there were any cache entries that were not available in the fast
  // backend, retrieve them from the consistent backend and store them in the
  // fast one.
  if ($cids) {
    $missing = array();
    foreach ($this->consistentBackend
      ->getMultiple($cids, $allow_invalid) as $item) {
      $cache[$item->cid] = $item;
      $missing[$item->cid] = (array) $item;
    }
    if (!empty($missing)) {

      // TODO: Expiration data from the consistent
      // backend is lost here. We are setting items
      // in the fast backend with permanent status...
      // But time based expirations are becoming less
      // relevant, and considering that the items
      // in the consistent backend will actually expire
      // properly, this might not be that of an issue.
      $this->fastBackend
        ->setMultiple($missing);
    }

    // This means that the persistent backend has no lastWriteTimestamp
    // but we were able to retrieve data from it....
    if (!$last_write_timestamp && !empty($missing)) {
      $this
        ->markAsOutdated();
    }
  }
  return $cache;
}