]> granicus.if.org Git - apache/commitdiff
The ap_add_input_filter/ap_add_output_filter functions do an O(n) scan
authorJustin Erenkrantz <jerenkrantz@apache.org>
Tue, 4 Sep 2001 06:50:52 +0000 (06:50 +0000)
committerJustin Erenkrantz <jerenkrantz@apache.org>
Tue, 4 Sep 2001 06:50:52 +0000 (06:50 +0000)
through the list of registered filters.  This patch replaces the linear
list with a hash table for better performance.
Submitted by: Brian Pane <bpane@pacbell.net>
Reviewed by: Justin Erenkrantz

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

server/util_filter.c

index 3735632db1deb753367f5599526c1b56a8629f73..4ae809c38fe126fcbe332e97cc09f8ea8e41de53 100644 (file)
 
 #define APR_WANT_STRFUNC
 #include "apr_want.h"
+#include "apr_lib.h"
+#include "apr_hash.h"
+#include "apr_strings.h"
 
 #include "httpd.h"
 #include "http_log.h"
 #include "util_filter.h"
 
 /* ### make this visible for direct manipulation?
- * ### use a hash table
  */
-static ap_filter_rec_t *registered_output_filters = NULL;
-static ap_filter_rec_t *registered_input_filters = NULL;
+static apr_hash_t *registered_output_filters = NULL;
+static apr_hash_t *registered_input_filters = NULL;
 
 /* NOTE: Apache's current design doesn't allow a pool to be passed thu,
    so we depend on a global to hold the correct pool
@@ -92,16 +94,20 @@ static apr_status_t filter_cleanup(void *ctx)
 static void register_filter(const char *name,
                             ap_filter_func filter_func,
                             ap_filter_type ftype,
-                            ap_filter_rec_t **reg_filter_list)
+                            apr_hash_t **reg_filter_set)
 {
     ap_filter_rec_t *frec = apr_palloc(FILTER_POOL, sizeof(*frec));
 
-    frec->name = name;
+    if (!*reg_filter_set) {
+        *reg_filter_set = apr_hash_make(FILTER_POOL);
+    }
+
+    frec->name = apr_pstrdup(FILTER_POOL, name);
+    ap_str_tolower((char *)frec->name);
     frec->filter_func = filter_func;
     frec->ftype = ftype;
 
-    frec->next = *reg_filter_list;
-    *reg_filter_list = frec;
+    apr_hash_set(*reg_filter_set, frec->name, APR_HASH_KEY_STRING, frec);
 
     apr_pool_cleanup_register(FILTER_POOL, NULL, filter_cleanup, apr_pool_cleanup_null);
 }
@@ -126,12 +132,26 @@ AP_DECLARE(void) ap_register_output_filter(const char *name,
 
 static ap_filter_t *add_any_filter(const char *name, void *ctx, 
                                   request_rec *r, conn_rec *c, 
-                                  ap_filter_rec_t *frec,
+                   apr_hash_t *reg_filter_set,
                                   ap_filter_t **r_filters,
                                   ap_filter_t **c_filters)
 {
-    for (; frec != NULL; frec = frec->next) {
-        if (!strcasecmp(name, frec->name)) {
+    if (reg_filter_set) {
+        ap_filter_rec_t *frec;
+        int len = strlen(name);
+        int size = len + 1;
+        char name_lower[size];
+        char *dst = name_lower;
+        const char *src = name;
+
+        /* Normalize the name to all lowercase to match register_filter() */
+        do {
+            *dst++ = apr_tolower(*src++);
+        } while (--size);
+
+        frec = (ap_filter_rec_t *)apr_hash_get(reg_filter_set,
+                                               name_lower, len);
+        if (frec) {
             apr_pool_t *p = r ? r->pool : c->pool;
             ap_filter_t *f = apr_pcalloc(p, sizeof(*f));
             ap_filter_t **outf = r ? r_filters : c_filters;