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.