diff -urN ./includes/common.inc ../drupal-6.13-pathcache/includes/common.inc --- ./includes/common.inc 2009-07-01 15:51:55.000000000 -0500 +++ ../drupal-6.13-pathcache/includes/common.inc 2009-07-14 09:19:12.000000000 -0500 @@ -1581,7 +1581,7 @@ if (variable_get('cache', CACHE_DISABLED) != CACHE_DISABLED) { page_set_cache(); } - + drupal_cache_system_paths(); module_invoke_all('exit'); } diff -urN ./includes/path.inc ../drupal-6.13-pathcache/includes/path.inc --- ./includes/path.inc 2008-10-13 16:06:41.000000000 -0500 +++ ../drupal-6.13-pathcache/includes/path.inc 2009-07-14 17:22:04.000000000 -0500 @@ -46,7 +46,12 @@ 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 - static $map = array(), $no_src = array(), $count; + $map = &drupal_static(__FUNCTION__, array()); + $no_src = &drupal_static(__FUNCTION__ . ':no_src', array()); + $count = &drupal_static(__FUNCTION__ . ':count'); + $system_paths = &drupal_static(__FUNCTION__ . ':system_paths'); + $no_aliases = &drupal_static(__FUNCTION__ . ':no_alias', array()); + $first_call = &drupal_static(__FUNCTION__ . ':first_call', TRUE); $path_language = $path_language ? $path_language : $language->language; @@ -59,16 +64,43 @@ $map = array(); $no_src = array(); $count = NULL; + $system_paths = array(); + $no_aliases = array(); } elseif ($count > 0 && $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; + $map[$path_language] = array(); + // Load system paths from cache. + $cid = $_GET['q']; + if ($cache = cache_get($cid, 'cache_path')) { + // 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. + $system_paths = $cache->data; + $placeholders = db_placeholders($system_paths, 'varchar'); + $result = db_query("SELECT src, dst FROM {url_alias} WHERE src IN($placeholders) AND language IN(%s, '') ORDER BY language ASC", $system_paths, $path_language + ); + while ($record = db_fetch_object($result)) { + $map[$path_language][$record->src] = $record->dst; + } + // Keep a record of paths with no alias to avoid querying twice. + $no_aliases[$path_language] = array_flip(array_diff($system_paths, array_keys($map[$path_language]))); + } + } + // If the alias has already been loaded, return it. if (isset($map[$path_language][$path])) { return $map[$path_language][$path]; } - // Get the most fitting result falling back with alias without language - $alias = db_result(db_query("SELECT dst FROM {url_alias} WHERE src = '%s' AND language IN('%s', '') ORDER BY language DESC", $path, $path_language)); - $map[$path_language][$path] = $alias; - return $alias; + // For system paths which were not cached, query aliases individually. + else if (!isset($no_aliases[$path_language][$path])) { + $alias = db_result(db_query("SELECT dst FROM {url_alias} WHERE src = '%s' AND language IN('%s', '') ORDER BY language DESC", $path, $path_language)); + $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 @@ -95,6 +127,33 @@ } /** + * Cache system paths for a page. + * + * Cache an array of the system paths available on each page. We assume + * that aiases will be needed for the majority of these paths during + * subsequent requests, and load them in a single query during + * drupal_lookup_path(). + */ +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()); + + // Generate a cache ID (cid) specifically for this page. + $cid = $_GET['q']; + if ($paths = current($map)) { + $data = array_keys($paths); + $expire = REQUEST_TIME + (60 * 60 * 24); + cache_set($cid, $data, 'cache_path', $expire); + } + } +} + +/** * Given an internal Drupal path, return the alias set by the administrator. * * @param $path @@ -241,3 +300,45 @@ } return preg_match($regexps[$patterns], $path); } + +/** + * Central static variable storage. + * + * @param $name + * Globally unique name for the variable. For a function with only one static, + * variable, the function name (e.g. via the PHP magic __FUNCTION__ constant) + * is recommended. For a function with multiple static variables add a + * distinguishing suffix to the function name for each one. + * @param $default_value + * Optional default value. + * @param $reset + * TRUE to reset a specific named variable, or all variables if $name is NULL. + * Resetting every variable should only be used, for example, for running + * unit tests with a clean environment. Should be used only though via + * function drupal_static_reset(). + * + * @return + * Returns a variable by reference if $reset is FALSE. + */ +function &drupal_static($name, $default_value = NULL, $reset = FALSE) { + static $data = array(); + + // Reset a single value, or all values. + if ($reset) { + if (isset($name)) { + unset($data[$name]); + } + else { + $data = array(); + } + // We must return a reference to a variable. + $dummy = NULL; + return $dummy; + } + + if (!isset($data[$name])) { + $data[$name] = $default_value; + } + + return $data[$name]; +} diff -urN ./modules/system/system.install ../drupal-6.13-pathcache/modules/system/system.install --- ./modules/system/system.install 2009-07-01 15:51:56.000000000 -0500 +++ ../drupal-6.13-pathcache/modules/system/system.install 2009-07-14 09:50:46.000000000 -0500 @@ -565,6 +565,8 @@ $schema['cache_page']['description'] = 'Cache table used to store compressed pages for anonymous users, if page caching is enabled.'; $schema['cache_menu'] = $schema['cache']; $schema['cache_menu']['description'] = 'Cache table for the menu system to store router information as well as generated link trees for various menu/page/user combinations.'; + $schema['cache_path'] = $schema['cache']; + $schema['cache_path']['description'] = 'Cache table for path alias lookup.'; $schema['files'] = array( 'description' => 'Stores information for uploaded files.', @@ -2596,6 +2598,16 @@ return $ret; } + /** + * Create the cache_path table. + */ +function system_update_6052() { + $ret = array(); + $schema['cache_path'] = drupal_get_schema_unprocessed('system', 'cache'); + $schema['cache_path']['description'] = t('Cache table used for path alias lookups.'); + db_create_table($ret, 'cache_path', $schema['cache_path']); + return $ret; +} /** * @} End of "defgroup updates-6.x-extra"