From 1957c641e5e04b1fcd503b84511d097aa2d101c5 Mon Sep 17 00:00:00 2001 From: Angie Byron <webchick@24967.no-reply.drupal.org> Date: Sun, 2 Aug 2009 06:48:24 +0000 Subject: [PATCH] #523298 by catch: Speed up static caching in drupal_lookup_path(). --- includes/path.inc | 83 ++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 44 deletions(-) diff --git a/includes/path.inc b/includes/path.inc index 8c640520e1b0..945733865cd7 100644 --- a/includes/path.inc +++ b/includes/path.inc @@ -45,94 +45,91 @@ function drupal_path_initialize() { */ function drupal_lookup_path($action, $path = '', $path_language = '') { global $language; - // $map is an array with language keys, holding arrays of Drupal paths to alias relations - $map = &drupal_static(__FUNCTION__, array()); - $no_src = &drupal_static(__FUNCTION__ . ':no_src', array()); - $whitelist = &drupal_static(__FUNCTION__ . ':whitelist'); - $system_paths = &drupal_static(__FUNCTION__ . ':system_paths'); - $no_aliases = &drupal_static(__FUNCTION__ . ':no_alias', array()); - $first_call = &drupal_static(__FUNCTION__ . ':first_call', TRUE); + $cache = &drupal_static(__FUNCTION__, array( + 'map' => array(), + 'no_src' => array(), + 'whitelist' => NULL, + 'system_paths' => array(), + 'no_aliases' => array(), + 'first_call' => TRUE, + )); // Retrieve the path alias whitelist. - if (!isset($whitelist)) { - $whitelist = variable_get('path_alias_whitelist', NULL); - if (!isset($whitelist)) { - $whitelist = drupal_path_alias_whitelist_rebuild(); + if (!isset($cache['whitelist'])) { + $cache['whitelist'] = variable_get('path_alias_whitelist', NULL); + if (!isset($cache['whitelist'])) { + $cache['whitelist'] = drupal_path_alias_whitelist_rebuild(); } } $path_language = $path_language ? $path_language : $language->language; if ($action == 'wipe') { - $map = array(); - $no_src = array(); - $system_paths = array(); - $no_aliases = array(); - - $whitelist = drupal_path_alias_whitelist_rebuild(); + $cache = array(); + $cache['whitelist'] = drupal_path_alias_whitelist_rebuild(); } - elseif ($whitelist && $path != '') { + elseif ($cache['whitelist'] && $path != '') { if ($action == 'alias') { // During the first call to drupal_lookup_path() per language, load the // expected system paths for the page from cache. - if ($first_call) { - $first_call = FALSE; + if (!empty($cache['first_call'])) { + $cache['first_call'] = FALSE; - $map[$path_language] = array(); + $cache['map'][$path_language] = array(); // Load system paths from cache. $cid = current_path(); - if ($cache = cache_get($cid, 'cache_path')) { - $system_paths = $cache->data; + if ($cached = cache_get($cid, 'cache_path')) { + $cache['system_paths'] = $cached->data; // Now fetch the aliases corresponding to these system paths. // We order by ASC and overwrite array keys to ensure the correct // alias is used when there are multiple aliases per path. - $map[$path_language] = db_query("SELECT src, dst FROM {url_alias} WHERE src IN(:system) AND language IN(:language, '') ORDER BY language ASC, pid ASC", array( - ':system' => $system_paths, + $cache['map'][$path_language] = db_query("SELECT src, dst FROM {url_alias} WHERE src IN (:system) AND language IN (:language, '') ORDER BY language ASC, pid ASC", array( + ':system' => $cache['system_paths'], ':language' => $path_language ))->fetchAllKeyed(); // Keep a record of paths with no alias to avoid querying twice. - $no_aliases[$path_language] = array_flip(array_diff_key($system_paths, array_keys($map[$path_language]))); + $cache['no_aliases'][$path_language] = array_flip(array_diff_key($cache['system_paths'], array_keys($cache['map'][$path_language]))); } } // If the alias has already been loaded, return it. - if (isset($map[$path_language][$path])) { - return $map[$path_language][$path]; + if (isset($cache['map'][$path_language][$path])) { + return $cache['map'][$path_language][$path]; } // Check the path whitelist, if the top_level part before the first / // is not in the list, then there is no need to do anything further, // it is not in the database. - elseif (!isset($whitelist[strtok($path, '/')])) { + elseif (!isset($cache['whitelist'][strtok($path, '/')])) { return FALSE; } // For system paths which were not cached, query aliases individually. - else if (!isset($no_aliases[$path_language][$path])) { + else if (!isset($cache['no_aliases'][$path_language][$path])) { // Get the most fitting result falling back with alias without language - $alias = db_query("SELECT dst FROM {url_alias} WHERE src = :src AND language IN(:language, '') ORDER BY language DESC, pid DESC", array( + $alias = db_query("SELECT dst FROM {url_alias} WHERE src = :src AND language IN (:language, '') ORDER BY language DESC, pid DESC", array( ':src' => $path, ':language' => $path_language ))->fetchField(); - $map[$path_language][$path] = $alias; + $cache['map'][$path_language][$path] = $alias; return $alias; } } // Check $no_src for this $path in case we've already determined that there // isn't a path that has this alias - elseif ($action == 'source' && !isset($no_src[$path_language][$path])) { + elseif ($action == 'source' && !isset($cache['no_src'][$path_language][$path])) { // Look for the value $path within the cached $map $src = ''; - if (!isset($map[$path_language]) || !($src = array_search($path, $map[$path_language]))) { + if (!isset($cache['map'][$path_language]) || !($src = array_search($path, $cache['map'][$path_language]))) { // Get the most fitting result falling back with alias without language - if ($src = db_query("SELECT src FROM {url_alias} WHERE dst = :dst AND language IN(:language, '') ORDER BY language DESC, pid DESC", array( + if ($src = db_query("SELECT src FROM {url_alias} WHERE dst = :dst AND language IN (:language, '') ORDER BY language DESC, pid DESC", array( ':dst' => $path, ':language' => $path_language)) ->fetchField()) { - $map[$path_language][$src] = $path; + $cache['map'][$path_language][$src] = $path; } else { // We can't record anything into $map because we do not have a valid // index and there is no need because we have not learned anything // about any Drupal path. Thus cache to $no_src. - $no_src[$path_language][$path] = TRUE; + $cache['no_src'][$path_language][$path] = TRUE; } } return $src; @@ -153,15 +150,13 @@ function drupal_lookup_path($action, $path = '', $path_language = '') { function drupal_cache_system_paths() { // Check if the system paths for this page were loaded from cache in this // request to avoid writing to cache on every request. - $system_paths = &drupal_static('drupal_lookup_path:system_paths', array()); - if (!$system_paths) { - // The static $map array used by drupal_lookup_path() includes all - // system paths for the page request. - $map = &drupal_static('drupal_lookup_path', array()); - + $cache = &drupal_static('drupal_lookup_path', array()); + if (!$cache['system_paths']) { // Generate a cache ID (cid) specifically for this page. $cid = current_path(); - if ($paths = current($map)) { + // The static $map array used by drupal_lookup_path() includes all + // system paths for the page request. + if ($paths = current($cache['map'])) { $data = array_keys($paths); $expire = REQUEST_TIME + (60 * 60 * 24); cache_set($cid, $data, 'cache_path', $expire); -- GitLab