Index: CHANGELOG.txt
===================================================================
RCS file: /cvs/drupal/drupal/CHANGELOG.txt,v
retrieving revision 1.79
diff -U3 -r1.79 CHANGELOG.txt
--- CHANGELOG.txt 5 May 2005 22:22:45 -0000 1.79
+++ CHANGELOG.txt 12 May 2005 02:17:39 -0000
@@ -13,6 +13,7 @@
     * added support for private profile fields.
 - performance:
     * added 'loose caching' option for high-traffic sites.
+    * improved performance of path aliasing.

 Drupal 4.6.0, 2005-04-15
 ------------------------
Index: database/updates.inc
===================================================================
RCS file: /cvs/drupal/drupal/database/updates.inc,v
retrieving revision 1.117
diff -U3 -r1.117 updates.inc
--- database/updates.inc  10 May 2005 20:48:32 -0000  1.117
+++ database/updates.inc  12 May 2005 02:17:40 -0000
@@ -114,7 +114,8 @@
   "2005-05-06" => "update_135",
   "2005-05-08" => "update_136",
   "2005-05-09" => "update_137",
-  "2005-05-10" => "update_138"
+  "2005-05-10" => "update_138",
+  "2005-05-11" => "update_139"
 );

 function update_32() {
@@ -2482,6 +2483,18 @@
   return $ret;
 }

+function update_139() {
+  $ret = array();
+
+  if ($GLOBALS['db_type'] == 'mysql') {
+    $ret[] = update_sql("ALTER TABLE {url_alias} ADD INDEX (src)");
+  }
+  elseif ($GLOBALS['db_type'] == 'pgsql') {
+    $ret[] = update_sql("CREATE INDEX url_alias_src ON {url_alias}(src)");
+  }
+  return $ret;
+}
+
 function update_sql($sql) {
   $edit = $_POST["edit"];
   $result = db_query($sql);
Index: includes/bootstrap.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/bootstrap.inc,v
retrieving revision 1.46
diff -U3 -r1.46 bootstrap.inc
--- includes/bootstrap.inc  12 Apr 2005 16:55:11 -0000  1.46
+++ includes/bootstrap.inc  12 May 2005 02:17:41 -0000
@@ -386,7 +386,7 @@
   // print $name. '<br />';
   static $files = array();

-  if ($files[$type][$name]) {
+  if (isset($files[$type][$name])) {
     return TRUE;
   }

@@ -403,32 +403,64 @@
 }

 /**
- * Return an array mapping path aliases to their internal Drupal paths.
- */
-function drupal_get_path_map($action = '') {
-  static $map = NULL;
-
-  if ($action == 'rebuild') {
-    $map = NULL;
-  }
-
-  if (is_null($map)) {
-    $map = array();  // Make $map non-null in case no aliases are defined.
-    $result = db_query('SELECT * FROM {url_alias}');
-    while ($data = db_fetch_object($result)) {
-      $map[$data->dst] = $data->src;
+ * Given an alias, return its Drupal system URL if one exists. Given a Drupal
+ * system URL return its alias if one exists.
+ *
+ * @param $action
+ *   One of the following values:
+ *   - wipe: Delete the alias cache.
+ *   - src: Indicates that given a Drupal system URL, return an alias if one exists.
+ *   - alias: Indicates that given an path alias, return the Drupal system URL if one exists.
+ * @param $path
+ *   The path to investigate for corresponding aliases or system URLs.
+ */
+function drupal_lookup_path($action = '', $path = '') {
+  static $map = array();
+  static $numset = NULL;
+
+  if ($numset === NULL) {
+    $numset = db_result(db_query('SELECT COUNT(pid) FROM {url_alias}'));
+  }
+
+  if ($action == 'wipe') {
+    $map = array();
+  }
+  elseif ($numset > 0) {
+    if ($action == 'src') {
+      if ($alias = array_search($path, $map)) {
+        return $alias;
+      }
+      elseif ($data = db_fetch_object(db_query("SELECT * FROM {url_alias} WHERE src = '%s'", $path))) {
+        $map[$data->dst] = $data->src;
+        return $data->dst;
+      }
+      else {
+        $map[$path] = $path;
+      }
+    }
+    elseif ($action == 'alias') {
+      if (isset($map[$path])) {
+        return $map[$path];
+      }
+      elseif ($data = db_fetch_object(db_query("SELECT * FROM {url_alias} WHERE dst = '%s'", $path))) {
+        $map[$data->dst] = $data->src;
+        return $data->src;
+      }
+      else {
+        $map[$path] = $path;
+      }
     }
   }

-  return $map;
+  return FALSE;
 }

 /**
  * Given an internal Drupal path, return the alias set by the administrator.
  */
 function drupal_get_path_alias($path) {
-  if (($map = drupal_get_path_map()) && ($newpath = array_search($path, $map))) {
-    return $newpath;
+  if ($alias = drupal_lookup_path('src', $path)) {
+    return $alias;
   }
   elseif (function_exists('conf_url_rewrite')) {
     return conf_url_rewrite($path, 'outgoing');
@@ -586,7 +618,7 @@
     $arguments = explode('/', $_GET['q']);
   }

-  if (array_key_exists($index, $arguments)) {
+  if ($arguments[$index] !== NULL) {
     return $arguments[$index];
   }
 }
Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.440
diff -U3 -r1.440 common.inc
--- includes/common.inc 7 May 2005 01:48:06 -0000 1.440
+++ includes/common.inc 12 May 2005 02:17:42 -0000
@@ -80,18 +80,18 @@
 }

 /**
- * Regenerate the path map from the information in the database.
+ * Clear out the path map.
  */
 function drupal_rebuild_path_map() {
-  drupal_get_path_map('rebuild');
+  drupal_lookup_path('wipe');
 }

 /**
  * Given a path alias, return the internal path it represents.
  */
 function drupal_get_normal_path($path) {
-  if (($map = drupal_get_path_map()) && isset($map[$path])) {
-    return $map[$path];
+  if ($src = drupal_lookup_path('alias', $path)) {
+    return $src;
   }
   elseif (function_exists('conf_url_rewrite')) {
     return conf_url_rewrite($path, 'incoming');
@@ -1531,7 +1531,7 @@
  *   An HTML string ready for insertion in a tag.
  */
 function drupal_attributes($attributes = array()) {
-  if ($attributes) {
+  if (is_array($attributes)) {
     $t = array();
     foreach ($attributes as $key => $value) {
       $t[] = $key .'="'. check_plain($value) .'"';
