You are here

function apdqc_async_data in Asynchronous Prefetch Database Query Cache 7

Used to get & parse async cached data.

Parameters

mixed $mysqli_result: Empty or an instance of mysqli_result.

string $table: Table name of the cache bin.

array $cids: Array of cache ids that you're looking for.

Return value

mixed The cached data if found.

3 calls to apdqc_async_data()
APDQCache::getMultiple in ./apdqc.cache.inc
Implements DrupalCacheInterface::getMultiple().
apdqc_init in ./apdqc.module
Implements hook_init().
apdqc_reap_async_query in ./apdqc.mysql.inc
Create a new MySQLi connection.
3 string references to 'apdqc_async_data'
APDQCache::clear in ./apdqc.cache.inc
Implements DrupalCacheInterface::clear().
APDQCache::getMultiple in ./apdqc.cache.inc
Implements DrupalCacheInterface::getMultiple().
apdqc_query in ./apdqc.mysql.inc
Runs a query in the database.

File

./apdqc.mysql.inc, line 41
APDQC Database interface code for MySQL database servers.

Code

function apdqc_async_data($mysqli_result = FALSE, $table = FALSE, $cids = array(), $log = TRUE) {

  // Get database query logger.
  if (!empty($log) && variable_get('devel_query_display', 0) && variable_get('apdqc_verbose_devel_output', APDQC_VERBOSE_DEVEL_OUTPUT)) {
    $logger = Database::getConnection()
      ->getLogger();
  }

  // Start timer if DB logger is enabled.
  if (!empty($logger)) {
    $query_start = microtime(TRUE);
  }

  // Use the advanced drupal_static() pattern, since this is called very often.
  static $local_storage;
  if (!isset($local_storage)) {
    $local_storage =& drupal_static('apdqc_async_data');
  }
  static $get_count;
  static $use_async_data;
  if (!isset($use_async_data)) {
    $do_not_use_async_data =& drupal_static('apdqc_async_data_do_not_use_async', array());
  }
  if (is_array($table)) {
    foreach ($table as $t) {
      if (is_array($do_not_use_async_data) && array_key_exists($t, $do_not_use_async_data) && !empty($do_not_use_async_data[$t])) {
        return array();
      }
    }
  }
  else {
    if (is_array($do_not_use_async_data) && array_key_exists($table, $do_not_use_async_data) && !empty($do_not_use_async_data[$table])) {
      return array();
    }
  }
  $output = array();
  if (!empty($mysqli_result) && $mysqli_result instanceof mysqli_result) {
    $rows = $mysqli_result
      ->fetch_all(MYSQLI_ASSOC);
    if (!is_array($cids) && !isset($cids['*'])) {
      $cids = array_flip($cids);
    }
    foreach ($rows as $row) {
      $local_storage[$row['bin']][$row['cid']] = $row;
      unset($cids[$row['cid']]);
    }

    // Save cache misses. This needs to be improved.
    if (!empty($cids) && !isset($cids['*'])) {
      if (!is_array($cids)) {
        $cids = array_flip($cids);
      }
      foreach ($cids as $key => $cid) {
        if (strpos($cid, '%') !== FALSE) {
          unset($cids[$key]);
        }
      }
      if (!empty($cids)) {
        foreach ($cids as $cid) {
          foreach ($table as $bin) {
            if (!isset($local_storage[$bin][$cid])) {
              $local_storage[$bin][$cid] = FALSE;
            }
          }
        }
      }
    }
    $logger = FALSE;
  }
  elseif (!empty($table) && !empty($cids) && !empty($local_storage) && is_array($local_storage)) {
    if (!isset($get_count)) {
      $get_count = 0;
    }
    ++$get_count;

    // This is the first run.
    // No session cookie.
    // The cache is enabled.
    // This page is cacheable.
    if ($get_count == 1 && !isset($_COOKIE[session_name()]) && variable_get('cache') && drupal_page_is_cacheable()) {

      // Check if blocked_ips var is not an array. If not, check if the
      // blocked_ips table is empty. If empty set the blocked_ips variable to an
      // empty array.
      $blocked_ips = variable_get('blocked_ips');
      if (!isset($blocked_ips) || !is_array($blocked_ips)) {

        // If the blocked_ips table is empty set the blocked_ips variable to
        // an empty array.
        $result = apdqc_query(array(
          'blocked_ips',
        ), array(), "SELECT 1 FROM " . apdqc_fast_prefix_tables('{' . apdqc_fast_escape_table('blocked_ips') . '}') . " LIMIT 1", array(
          'log' => FALSE,
        ));
        if (!empty($result) && $result instanceof mysqli_result) {
          $blocked_ips = $result
            ->fetch_row();
        }
        if (empty($result) || empty($blocked_ips)) {
          $GLOBALS['conf']['blocked_ips'] = array();
        }
      }

      // Prefetch the page cache.
      if (variable_get('cache_bootstrap_prefetch', CACHE_BOOTSTRAP_PREFETCH)) {
        if (apdqc_get_bin_class_name('cache_page') === 'APDQCache') {

          // Add in the page cache.
          $cid = apdqc_escape_string($GLOBALS['base_root'] . request_uri(), 'cache_page');
          $table_keys_cache_prefetch['cache_page'][] = $cid;

          // Run async query.
          apdqc_run_prefetch_array($table_keys_cache_prefetch, TRUE, FALSE);
        }
      }
    }
    if (is_string($table) && isset($local_storage[$table])) {
      foreach ($cids as $cid) {
        if (isset($local_storage[$table][$cid])) {
          $output[$cid] = $local_storage[$table][$cid];
          unset($output[$cid]['bin']);
        }
      }
    }
    if (empty($output)) {
      if (is_string($table)) {
        $new_data = apdqc_get_db_object(array(
          $table,
        ), $cids, array(
          'reap' => TRUE,
        ));
      }
      else {
        $new_data = apdqc_get_db_object($table, $cids, array(
          'reap' => TRUE,
        ));
      }
      if ($new_data) {
        $output = apdqc_async_data(FALSE, $table, $cids, FALSE);
      }
    }
  }

  // Stop timer & write to the log if DB logger is enabled.
  if (!empty($logger) && is_object($logger)) {
    $query_end = microtime(TRUE);
    $data = '';
    if (!empty($output)) {
      $hits = 0;
      $empty = 0;
      foreach ($output as $key => $value) {
        if ($value === FALSE) {
          $empty++;
        }
        else {
          $hits++;
        }
      }
      if (!empty($hits)) {
        $data .= "Prefetch: Hit {$hits} times. ";
      }
      if (!empty($empty)) {
        $data .= "Prefetch: empty hit {$empty} times. ";
      }
    }
    if (empty($data) && !empty($cids)) {
      $data .= "Prefetch: Miss. ";
    }
    $data .= ' ' . implode(', ', $cids);
    $data = trim($data);
    if (!empty($data)) {
      require_once 'apdqc.log.inc';
      $statement = new ApdqcFakeDatabaseStatement($data);
      $logger
        ->log($statement, array(), $query_end - $query_start);
    }
  }
  return $output;
}