]> granicus.if.org Git - apache/commitdiff
core: Speed up config parsing if using a very large number of config
authorStefan Fritsch <sf@apache.org>
Sat, 2 Oct 2010 14:44:20 +0000 (14:44 +0000)
committerStefan Fritsch <sf@apache.org>
Sat, 2 Oct 2010 14:44:20 +0000 (14:44 +0000)
files

PR: 50002
Submitted by: andrew cloudaccess net

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1003808 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
include/ap_mmn.h
include/util_cfgtree.h
server/config.c

diff --git a/CHANGES b/CHANGES
index c6b02a24f989628a6d5e37800bcc97c61b582cd4..cb7d447b18c261eef3cf4d34134493189ce8d999 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,9 @@ Changes with Apache 2.3.9
      Fix a denial of service attack against mod_reqtimeout.
      [Stefan Fritsch]
 
+  *) core: Speed up config parsing if using a very large number of config
+     files. PR 50002 [andrew cloudaccess net]
+
   *) mod_cache: Support the caching of HEAD requests. [Graham Leggett]
 
   *) htcacheclean: Allow the option to round up file sizes to a given
index f44a22beb7894bea9353143730690a769a4da29e..52076374237f9a5c8af7bc2897da39a5214c6581 100644 (file)
  * 20100923.1 (2.3.9-dev)  Add cache_status hook.
  * 20100923.2 (2.3.9-dev)  Add generate_log_id hook.
  *                         Make root parameter of ap_expr_eval() const.
+ * 20100923.3 (2.3.9-dev)  Add "last" member to ap_directive_t
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
 #define MODULE_MAGIC_NUMBER_MAJOR 20100923
 #endif
-#define MODULE_MAGIC_NUMBER_MINOR 2                     /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 3                     /* 0...n */
 
 /**
  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a
index 4da4c7dd1d9e2b1bc2dbe17209bd0eb43361ee95..791a5cc16c6bf25de26f2534e70c14bd5cc0b8c4 100644 (file)
@@ -64,6 +64,13 @@ struct ap_directive_t {
     const char *filename;
     /** The line number the directive was on */
     int line_num;
+
+    /** A short-cut towards the last directive node in the tree.
+     *  The value may not always be up-to-date but it always points to
+     *  somewhere in the tree, nearer to the tail.
+     *  This value is only set in the first node
+     */
+    struct ap_directive_t *last;
 };
 
 /**
index dc9b3b64a45cdd79dd364781487c02cdd9f2ec7b..a3d67f0b1d4fc81dac5a0f8f6351c0b30d32f761 100644 (file)
@@ -1284,11 +1284,30 @@ AP_DECLARE(const char *) ap_build_config(cmd_parms *parms,
     ap_directive_t *curr_parent = NULL;
     char *l = apr_palloc (temp_pool, MAX_STRING_LEN);
     const char *errmsg;
+    ap_directive_t **last_ptr = NULL;
+
+    if(current) {
+        /* If we have to traverse the whole tree again for every included
+         * config file, the required time grows as O(n^2) with the number of
+         * files. This can be a significant delay for large configurations.
+         * Therefore we cache a pointer to the last node.
+         */
+        last_ptr = &(current->last);
+
+        if(last_ptr && *last_ptr) {
+            current = *last_ptr;
+        }
+    }
 
     if (current != NULL) {
         while (current->next) {
             current = current->next;
         }
+
+        if(last_ptr) {
+            /* update cached pointer to last node */
+            *last_ptr = current;
+        }
     }
 
     while (!(ap_cfg_getline(l, MAX_STRING_LEN, parms->config_file))) {