lars 99/03/07 10:03:41
Modified: src/modules/standard mod_rewrite.c mod_rewrite.h src CHANGES . STATUS Log: speed up mod_rewrite... PR: 3160 Submitted by: Michael van Elst <[EMAIL PROTECTED]> Reviewed by: Jim, Ralf, Lars Revision Changes Path 1.136 +112 -37 apache-1.3/src/modules/standard/mod_rewrite.c Index: mod_rewrite.c =================================================================== RCS file: /export/home/cvs/apache-1.3/src/modules/standard/mod_rewrite.c,v retrieving revision 1.135 retrieving revision 1.136 diff -u -r1.135 -r1.136 --- mod_rewrite.c 1999/01/01 19:50:22 1.135 +++ mod_rewrite.c 1999/03/07 18:03:34 1.136 @@ -208,11 +208,7 @@ /* whether proxy module is available or not */ static int proxy_available; - /* the txt mapfile parsing stuff */ -static regex_t *lookup_map_txtfile_regexp = NULL; -static regmatch_t lookup_map_txtfile_regmatch[MAX_NMATCH]; - /* ** +-------------------------------------------------------+ ** | | @@ -952,10 +948,6 @@ /* check if proxy module is available */ proxy_available = (ap_find_linked_module("mod_proxy.c") != NULL); - /* precompile a static pattern - for the txt mapfile parsing */ - lookup_map_txtfile_regexp = ap_pregcomp(p, MAPFILE_PATTERN, REG_EXTENDED); - /* create the rewriting lockfile in the parent */ rewritelock_create(s, p); ap_register_cleanup(p, (void *)s, rewritelock_remove, ap_null_cleanup); @@ -2729,13 +2721,15 @@ else { rewritelog(r, 5, "map lookup FAILED: map=%s[txt] " "key=%s", s->name, key); + set_cache_string(cachep, s->name, CACHEMODE_TS, + st.st_mtime, key, ""); return NULL; } } else { rewritelog(r, 5, "cache lookup OK: map=%s[txt] key=%s " "-> val=%s", s->name, key, value); - return value; + return value[0] != '\0' ? value : NULL; } } else if (s->type == MAPTYPE_DBM) { @@ -2764,13 +2758,15 @@ else { rewritelog(r, 5, "map lookup FAILED: map=%s[dbm] " "key=%s", s->name, key); + set_cache_string(cachep, s->name, CACHEMODE_TS, + st.st_mtime, key, ""); return NULL; } } else { rewritelog(r, 5, "cache lookup OK: map=%s[dbm] key=%s " "-> val=%s", s->name, key, value); - return value; + return value[0] != '\0' ? value : NULL; } #else return NULL; @@ -2823,15 +2819,22 @@ else { rewritelog(r, 5, "map lookup FAILED: map=%s[txt] " "key=%s", s->name, key); + set_cache_string(cachep, s->name, CACHEMODE_TS, + st.st_mtime, key, ""); return NULL; } } else { rewritelog(r, 5, "cache lookup OK: map=%s[txt] key=%s " "-> val=%s", s->name, key, value); + } + if (value[0] != '\0') { + value = select_random_value_part(r, value); + rewritelog(r, 5, "randomly choosen the subvalue `%s'", value); + } + else { + value = NULL; } - value = select_random_value_part(r, value); - rewritelog(r, 5, "randomly choosen the subvalue `%s'", value); return value; } } @@ -2839,44 +2842,45 @@ return NULL; } - static char *lookup_map_txtfile(request_rec *r, char *file, char *key) { FILE *fp = NULL; char line[1024]; - char output[1024]; - char result[1024]; char *value = NULL; char *cpT; + size_t skip; char *curkey; char *curval; if ((fp = ap_pfopen(r->pool, file, "r")) == NULL) { - return NULL; + return NULL; } - ap_cpystrn(output, MAPFILE_OUTPUT, sizeof(output)); while (fgets(line, sizeof(line), fp) != NULL) { - if (line[strlen(line)-1] == '\n') { - line[strlen(line)-1] = '\0'; - } - if (regexec(lookup_map_txtfile_regexp, line, - lookup_map_txtfile_regexp->re_nsub+1, - lookup_map_txtfile_regmatch, 0) == 0) { - ap_cpystrn(result, ap_pregsub(r->pool, output, line, - lookup_map_txtfile_regexp->re_nsub+1, - lookup_map_txtfile_regmatch), - sizeof(result)); /* substitute in output */ - cpT = strchr(result, ','); - *cpT = '\0'; - curkey = result; - curval = cpT+1; - - if (strcmp(curkey, key) == 0) { - value = ap_pstrdup(r->pool, curval); - break; - } - } + if (line[0] == '#') + continue; /* ignore comments */ + cpT = line; + curkey = cpT; + skip = strcspn(cpT," \t\r\n"); + if (skip == 0) + continue; /* ignore lines that start with a space, tab, CR, or LF */ + cpT += skip; + *cpT = '\0'; + if (strcmp(curkey, key) != 0) + continue; /* key does not match... */ + + /* found a matching key; now extract and return the value */ + ++cpT; + skip = strspn(cpT, " \t\r\n"); + cpT += skip; + curval = cpT; + skip = strcspn(cpT, " \t\r\n"); + if (skip == 0) + continue; /* no value... */ + cpT += skip; + *cpT = '\0'; + value = ap_pstrdup(r->pool, curval); + break; } ap_pfclose(r->pool, fp); return value; @@ -3834,12 +3838,57 @@ return ap_pstrdup(c->pool, ce->value); } +static int cache_tlb_hash(char *key) +{ + unsigned long n; + char *p; + + n = 0; + for (p=key; *p != '\0'; ++p) { + n = n * 53711 + 134561 + (unsigned)(*p & 0xff); + } + + return n % CACHE_TLB_ROWS; +} + +static cacheentry *cache_tlb_lookup(cachetlbentry *tlb, cacheentry *elt, + char *key) +{ + int ix = cache_tlb_hash(key); + int i; + int j; + + for (i=0; i < CACHE_TLB_COLS; ++i) { + j = tlb[ix].t[i]; + if (j < 0) + return NULL; + if (strcmp(elt[j].key, key) == 0) + return &elt[j]; + } + return NULL; +} + +static void cache_tlb_replace(cachetlbentry *tlb, cacheentry *elt, + cacheentry *e) +{ + int ix = cache_tlb_hash(e->key); + int i; + + tlb = &tlb[ix]; + + for (i=1; i < CACHE_TLB_COLS; ++i) + tlb->t[i] = tlb->t[i-1]; + + tlb->t[0] = e - elt; +} + static void store_cache_string(cache *c, char *res, cacheentry *ce) { int i; int j; cachelist *l; cacheentry *e; + cachetlbentry *t; int found_list; found_list = 0; @@ -3848,11 +3897,22 @@ l = &(((cachelist *)c->lists->elts)[i]); if (strcmp(l->resource, res) == 0) { found_list = 1; + + e = cache_tlb_lookup((cachetlbentry *)l->tlb->elts, + (cacheentry *)l->entries->elts, ce->key); + if (e != NULL) { + e->time = ce->time; + e->value = ap_pstrdup(c->pool, ce->value); + return; + } + for (j = 0; j < l->entries->nelts; j++) { e = &(((cacheentry *)l->entries->elts)[j]); if (strcmp(e->key, ce->key) == 0) { e->time = ce->time; e->value = ap_pstrdup(c->pool, ce->value); + cache_tlb_replace((cachetlbentry *)l->tlb->elts, + (cacheentry *)l->entries->elts, e); return; } } @@ -3864,6 +3924,13 @@ l = ap_push_array(c->lists); l->resource = ap_pstrdup(c->pool, res); l->entries = ap_make_array(c->pool, 2, sizeof(cacheentry)); + l->tlb = ap_make_array(c->pool, CACHE_TLB_ROWS, + sizeof(cachetlbentry)); + for (i=0; i<CACHE_TLB_ROWS; ++i) { + t = &((cachetlbentry *)l->tlb->elts)[i]; + for (j=0; j<CACHE_TLB_COLS; ++j) + t->t[j] = -1; + } } /* create the new entry */ @@ -3874,6 +3941,8 @@ e->time = ce->time; e->key = ap_pstrdup(c->pool, ce->key); e->value = ap_pstrdup(c->pool, ce->value); + cache_tlb_replace((cachetlbentry *)l->tlb->elts, + (cacheentry *)l->entries->elts, e); return; } } @@ -3892,6 +3961,12 @@ for (i = 0; i < c->lists->nelts; i++) { l = &(((cachelist *)c->lists->elts)[i]); if (strcmp(l->resource, res) == 0) { + + e = cache_tlb_lookup((cachetlbentry *)l->tlb->elts, + (cacheentry *)l->entries->elts, key); + if (e != NULL) + return e; + for (j = 0; j < l->entries->nelts; j++) { e = &(((cacheentry *)l->entries->elts)[j]); if (strcmp(e->key, key) == 0) { 1.61 +14 -8 apache-1.3/src/modules/standard/mod_rewrite.h Index: mod_rewrite.h =================================================================== RCS file: /export/home/cvs/apache-1.3/src/modules/standard/mod_rewrite.h,v retrieving revision 1.60 retrieving revision 1.61 diff -u -r1.60 -r1.61 --- mod_rewrite.h 1999/01/28 07:15:18 1.60 +++ mod_rewrite.h 1999/03/07 18:03:37 1.61 @@ -219,6 +219,9 @@ #define CACHEMODE_TS 1<<0 #define CACHEMODE_TTL 1<<1 +#define CACHE_TLB_ROWS 1024 +#define CACHE_TLB_COLS 4 + #ifndef FALSE #define FALSE 0 #define TRUE !FALSE @@ -241,10 +244,6 @@ #define MAX_NMATCH 10 -#define MAPFILE_PATTERN "^([^ \t]+)[ \t]+([^ \t]+).*$" -#define MAPFILE_OUTPUT "$1,$2" - - /* ** ** our private data structures we handle with @@ -317,17 +316,23 @@ } rewrite_perdir_conf; - /* the cache structures */ - + /* the cache structures, + * a 4-way hash table with LRU functionality + */ typedef struct cacheentry { time_t time; char *key; char *value; } cacheentry; +typedef struct tlbentry { + int t[CACHE_TLB_COLS]; +} cachetlbentry; + typedef struct cachelist { char *resource; array_header *entries; + array_header *tlb; } cachelist; typedef struct cache { @@ -335,9 +340,10 @@ array_header *lists; } cache; - /* the regex structure for the - substitution of backreferences */ + /* the regex structure for the + * substitution of backreferences + */ typedef struct backrefinfo { char *source; int nsub; 1.1264 +10 -0 apache-1.3/src/CHANGES Index: CHANGES =================================================================== RCS file: /export/home/cvs/apache-1.3/src/CHANGES,v retrieving revision 1.1263 retrieving revision 1.1264 diff -u -r1.1263 -r1.1264 --- CHANGES 1999/03/07 15:35:14 1.1263 +++ CHANGES 1999/03/07 18:03:38 1.1264 @@ -1,5 +1,15 @@ Changes with Apache 1.3.5 + *) Enhanced mod_rewrite's mapfile handling: The in-core cache for text and + DBM format mapfiles now uses a 4-way hash table with LRU functionality. + Furthermore map lookups for non-existent keys are now cached as well. + Additionally "txt" maps are now parsed with simple string functions + instead of using ap_pregcomp(). As a side effect a bug that prevented + the usage of keys containing the "," character was fixed. + The changes drastically improve the performance when large rewrite maps + are in use. + [Michael van Elst <[EMAIL PROTECTED]>, Lars Eilebrecht] PR#3160 + *) Added ap_sub_req_method_uri() for doing a subrequest with a method other than GET, and const'd the definition of method in request_rec. [Greg Stein] 1.639 +1 -9 apache-1.3/STATUS Index: STATUS =================================================================== RCS file: /export/home/cvs/apache-1.3/STATUS,v retrieving revision 1.638 retrieving revision 1.639 diff -u -r1.638 -r1.639 --- STATUS 1999/03/07 16:56:49 1.638 +++ STATUS 1999/03/07 18:03:41 1.639 @@ -1,5 +1,5 @@ 1.3 STATUS: - Last modified at [$Date: 1999/03/07 16:56:49 $] + Last modified at [$Date: 1999/03/07 18:03:41 $] Release: @@ -113,14 +113,6 @@ * Ronald Tschalär's ap_uuencode() bugfix Message-ID: PR#3411 Status: Lars +1 (on concept), Dirkx +1 - - * Michael van Elst's patch [PR#3160] to improve mod_rewrite's - in-core cache handling by using a hash table. - Message-ID: <[EMAIL PROTECTED]> - Status: Lars +1, Jim +1, Ralf +1 (on concept, but because the code - change is not trivial I want to - first walk though it line by line - the next days before we commit it). * Juan Gallego's patch to add CSH-style modifiers (:h, :r, :t, :e) to mod_include's variable processing.