You are here

public function APDQCache::getMultiple in Asynchronous Prefetch Database Query Cache 7

Implements DrupalCacheInterface::getMultiple().

We handle garbage collection differently; this method is reimplemented only to remove a call to the garbageCollection() method.

Overrides DrupalDatabaseCache::getMultiple

File

./apdqc.cache.inc, line 328
Extends Drupal's default database cache so async queries happen.

Class

APDQCache
A pretty darn quick cache implementation of Drupal's default cache backend.

Code

public function getMultiple(&$cids) {
  try {
    $gc_frequency = variable_get('cache_garbage_collection_frequency', CACHE_GARBAGE_COLLECTION_FREQUENCY);
    if (empty($gc_frequency)) {

      // Garbage collection necessary when enforcing a minimum cache lifetime.
      $this
        ->garbageCollection($this->bin);
    }
    $query_cids = $cids;
    $prefetch = array();
    $result = array();
    if (variable_get('cache_bootstrap_prefetch', CACHE_BOOTSTRAP_PREFETCH) || defined('APDQC_PREFETCH') && variable_get('apdqc_prefetch', APDQC_PREFETCH)) {
      $prefetch = apdqc_async_data(FALSE, $this->bin, $cids);
      $query_cids = array_diff($cids, array_keys($prefetch));
      $prefetch = array_values($prefetch);
    }
    $result = array();
    if (!empty($query_cids)) {

      // Build query.
      $query = Database::getConnection()
        ->prefixTables("SELECT cid, data, created, expire, serialized FROM {" . db_escape_table($this->bin) . "}");

      // If this is the cache_bootstrap bin and the cid is variables, get
      // the bootstrap_modules & lookup_cache ids as well.
      if ($this->bin === 'cache_bootstrap' && $query_cids[0] === 'variables' && count($query_cids) == 1) {
        $query_cids[] = 'bootstrap_modules';
        $query_cids[] = 'lookup_cache';
        $query_cids[] = 'system_list';
        $query_cids[] = 'module_implements';
        $bootstrap = TRUE;
      }
      foreach ($query_cids as $cid) {
        $escaped_cids[] = apdqc_escape_string($cid);
      }
      $escaped_cids = "'" . implode("', '", $escaped_cids) . "'";
      $query .= " WHERE cid IN ({$escaped_cids})";

      // Run query.
      $result = apdqc_query(array(
        $this->bin,
      ), $query_cids, $query, array(
        'fetch_all' => TRUE,
      ));
    }
    if (is_string($result) && $result === 'NO DB') {

      // When serving cached pages, the overhead of using db_select() was
      // found to add around 30% overhead to the request. Since $this->bin is
      // a variable, this means the call to db_query() here uses a
      // concatenated string. This is highly discouraged under any other
      // circumstances, and is used here only due to the performance overhead
      // we would incur otherwise. When serving an uncached page, the overhead
      // of using db_select() is a much smaller proportion of the request.
      // @codingStandardsIgnoreLine
      $result = db_query('SELECT cid, data, created, expire, serialized FROM {' . db_escape_table($this->bin) . '} WHERE cid IN (:cids)', array(
        ':cids' => $cids,
      ));
    }
    else {
      $result = array_merge($result, $prefetch);
    }
    $cache = array();
    if (!empty($result)) {
      foreach ($result as $item) {

        // Skip empty items.
        if (empty($item)) {
          continue;
        }
        if (!empty($bootstrap) && is_array($item) && ($item['cid'] === 'bootstrap_modules' || $item['cid'] === 'lookup_cache' || $item['cid'] === 'system_list' || $item['cid'] === 'module_implements')) {
          $local_storage =& drupal_static('apdqc_async_data');
          $item['bin'] = $this->bin;
          $local_storage[$this->bin][$item['cid']] = $item;
          continue;
        }

        // Convert to an object to mirror db_query if needed.
        if (is_array($item)) {
          $item = (object) $item;
        }
        $item = $this
          ->prepareItem($item);
        if ($item) {
          $cache[$item->cid] = $item;
        }
      }
    }
    $cids = array_diff($cids, array_keys($cache));
    return $cache;
  } catch (Exception $e) {

    // If the database is never going to be available, cache requests should
    // return FALSE in order to allow exception handling to occur.
    return array();
  }
}