From: André Malo Date: Sun, 27 Jul 2003 22:12:49 +0000 (+0000) Subject: Get a rid of the oversized cache. X-Git-Tag: pre_ajp_proxy~1349 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d4b1817c38a4a2d2e19498cb0ecf129e204dc8c6;p=apache Get a rid of the oversized cache. The new map-cache consists of a simple two-tiered apr_hash structure. cachep->maps contains entries for each map, which point to a hash with the actual values (map->entries). Each map->entries hash lives in a subpool of cachep->pool. The mtime is stored per map and if the map expires, we just clear map->pool and create a fresh map->entries hash structure. This removes a big chunk of code from mod_rewrite, improves readability and even the memory footprint of the cache. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@100801 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c index a403d2f302..5f8153792b 100644 --- a/modules/mappers/mod_rewrite.c +++ b/modules/mappers/mod_rewrite.c @@ -192,12 +192,6 @@ #define OPTION_NONE 1<<0 #define OPTION_INHERIT 1<<1 -#define CACHEMODE_TS 1<<0 -#define CACHEMODE_TTL 1<<1 - -#define CACHE_TLB_ROWS 1024 -#define CACHE_TLB_COLS 4 - #ifndef RAND_MAX #define RAND_MAX 32767 #endif @@ -293,33 +287,25 @@ typedef struct { } rewrite_request_conf; -/* the cache structures, - * a 4-way hash apr_table_t with LRU functionality +/* the (per-child) cache structures. */ -typedef struct cacheentry { - apr_time_t time; - char *key; - char *value; -} cacheentry; - -typedef struct tlbentry { - int t[CACHE_TLB_COLS]; -} cachetlbentry; - -typedef struct cachelist { - char *resource; - apr_array_header_t *entries; - apr_array_header_t *tlb; -} cachelist; - typedef struct cache { apr_pool_t *pool; - apr_array_header_t *lists; + apr_hash_t *maps; #if APR_HAS_THREADS apr_thread_mutex_t *lock; #endif } cache; +/* cached maps contain an mtime for the whole map and live in a subpool + * of the cachep->pool. That makes it easy to forget them if necessary. + */ +typedef struct { + apr_time_t mtime; + apr_pool_t *pool; + apr_hash_t *entries; +} cachedmap; + /* the regex structure for the * substitution of backreferences */ @@ -933,223 +919,110 @@ static char *subst_prefix_path(request_rec *r, char *input, char *match, * +-------------------------------------------------------+ */ -static int cache_tlb_hash(char *key) -{ - unsigned long n; - char *p; - - n = 0; - for (p = key; *p != '\0'; p++) { - n = ((n << 5) + n) ^ (unsigned long)(*p++); - } - - return n % CACHE_TLB_ROWS; -} - -static cacheentry *cache_tlb_lookup(cachetlbentry *tlb, cacheentry *elt, - char *key) +static void set_cache_value(const char *name, apr_time_t t, char *key, + char *val) { - 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 cacheentry *retrieve_cache_string(cache *c, const char *res, char *key) -{ - int i; - int j; - cachelist *l; - cacheentry *e; + cachedmap *map; + if (cachep) { #if APR_HAS_THREADS - apr_thread_mutex_lock(c->lock); + apr_thread_mutex_lock(cachep->lock); #endif + map = apr_hash_get(cachep->maps, name, APR_HASH_KEY_STRING); - for (i = 0; i < c->lists->nelts; i++) { - l = &(((cachelist *)c->lists->elts)[i]); - if (strcmp(l->resource, res) == 0) { + if (!map) { + apr_pool_t *p; - e = cache_tlb_lookup((cachetlbentry *)l->tlb->elts, - (cacheentry *)l->entries->elts, key); - if (e != NULL) { + if (apr_pool_create(&p, cachep->pool) != APR_SUCCESS) { #if APR_HAS_THREADS - apr_thread_mutex_unlock(c->lock); + apr_thread_mutex_unlock(cachep->lock); #endif - return e; + return; } - for (j = 0; j < l->entries->nelts; j++) { - e = &(((cacheentry *)l->entries->elts)[j]); - if (strcmp(e->key, key) == 0) { -#if APR_HAS_THREADS - apr_thread_mutex_unlock(c->lock); -#endif - return e; - } - } + map = apr_palloc(cachep->pool, sizeof(cachedmap)); + map->pool = p; + map->entries = apr_hash_make(map->pool); + map->mtime = t; + + apr_hash_set(cachep->maps, name, APR_HASH_KEY_STRING, map); } - } + else if (map->mtime != t) { + apr_pool_clear(map->pool); + map->entries = apr_hash_make(map->pool); + map->mtime = t; + } + + /* Now we should have a valid map->entries hash, where we + * can store our value. + * + * We need to copy the key and the value into OUR pool, + * so that we don't leave it during the r->pool cleanup. + */ + apr_hash_set(map->entries, + apr_pstrdup(map->pool, key), APR_HASH_KEY_STRING, + apr_pstrdup(map->pool, val)); + #if APR_HAS_THREADS - apr_thread_mutex_unlock(c->lock); + apr_thread_mutex_unlock(cachep->lock); #endif - return NULL; + } + + return; } -static void store_cache_string(cache *c, const char *res, cacheentry *ce) +static char *get_cache_value(const char *name, apr_time_t t, char *key, + apr_pool_t *p) { - int i; - int j; - cachelist *l; - cacheentry *e; - cachetlbentry *t; - int found_list; - -#if APR_HAS_THREADS - apr_thread_mutex_lock(c->lock); -#endif + cachedmap *map; + char *val = NULL; - found_list = 0; - /* first try to edit an existing entry */ - for (i = 0; i < c->lists->nelts; i++) { - 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 = apr_pstrdup(c->pool, ce->value); + if (cachep) { #if APR_HAS_THREADS - apr_thread_mutex_unlock(c->lock); + apr_thread_mutex_lock(cachep->lock); #endif - return; + map = apr_hash_get(cachep->maps, name, APR_HASH_KEY_STRING); + + if (map) { + /* if this map is outdated, forget it. */ + if (map->mtime != t) { + apr_pool_clear(map->pool); + map->entries = apr_hash_make(map->pool); + map->mtime = t; } - - 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 = apr_pstrdup(c->pool, ce->value); - cache_tlb_replace((cachetlbentry *)l->tlb->elts, - (cacheentry *)l->entries->elts, e); -#if APR_HAS_THREADS - apr_thread_mutex_unlock(c->lock); -#endif - return; + else { + val = apr_hash_get(map->entries, key, APR_HASH_KEY_STRING); + if (val) { + /* copy the cached value into the supplied pool, + * where it belongs (r->pool usually) + */ + val = apr_pstrdup(p, val); } } } - } - - /* create a needed new list */ - if (!found_list) { - l = apr_array_push(c->lists); - l->resource = apr_pstrdup(c->pool, res); - l->entries = apr_array_make(c->pool, 2, sizeof(cacheentry)); - l->tlb = apr_array_make(c->pool, CACHE_TLB_ROWS, - sizeof(cachetlbentry)); - for (i=0; itlb->elts)[i]; - for (j=0; jt[j] = -1; - } - } - /* create the new entry */ - for (i = 0; i < c->lists->nelts; i++) { - l = &(((cachelist *)c->lists->elts)[i]); - if (strcmp(l->resource, res) == 0) { - e = apr_array_push(l->entries); - e->time = ce->time; - e->key = apr_pstrdup(c->pool, ce->key); - e->value = apr_pstrdup(c->pool, ce->value); - cache_tlb_replace((cachetlbentry *)l->tlb->elts, - (cacheentry *)l->entries->elts, e); #if APR_HAS_THREADS - apr_thread_mutex_unlock(c->lock); + apr_thread_mutex_unlock(cachep->lock); #endif - return; - } } - /* not reached, but when it is no problem... */ -#if APR_HAS_THREADS - apr_thread_mutex_unlock(c->lock); -#endif - return; -} - -static void set_cache_string(cache *c, const char *res, int mode, apr_time_t t, - char *key, char *value) -{ - cacheentry ce; - - ce.time = t; - ce.key = key; - ce.value = value; - store_cache_string(c, res, &ce); - return; + return val; } -static char *get_cache_string(cache *c, const char *res, int mode, - apr_time_t t, char *key) +static int init_cache(apr_pool_t *p) { - cacheentry *ce; - - ce = retrieve_cache_string(c, res, key); - if (ce == NULL) { - return NULL; - } - if (mode & CACHEMODE_TS) { - if (t != ce->time) { - return NULL; - } - } - else if (mode & CACHEMODE_TTL) { - if (t > ce->time) { - return NULL; - } + cachep = apr_palloc(p, sizeof(cache)); + if (apr_pool_create(&cachep->pool, p) != APR_SUCCESS) { + cachep = NULL; /* turns off cache */ + return 0; } - return apr_pstrdup(c->pool, ce->value); -} -static cache *init_cache(apr_pool_t *p) -{ - cache *c; - - c = (cache *)apr_palloc(p, sizeof(cache)); - if (apr_pool_create(&c->pool, p) != APR_SUCCESS) { - return NULL; - } - c->lists = apr_array_make(c->pool, 2, sizeof(cachelist)); + cachep->maps = apr_hash_make(cachep->pool); #if APR_HAS_THREADS - (void)apr_thread_mutex_create(&(c->lock), APR_THREAD_MUTEX_DEFAULT, p); + (void)apr_thread_mutex_create(&(cachep->lock), APR_THREAD_MUTEX_DEFAULT, p); #endif - return c; + + return 1; } @@ -1563,7 +1436,7 @@ static char *lookup_map(request_rec *r, char *name, char *key) return NULL; } - value = get_cache_string(cachep, name, CACHEMODE_TS, st.mtime, key); + value = get_cache_value(name, st.mtime, key, r->pool); if (!value) { rewritelog(r, 6, "cache lookup FAILED, forcing new map lookup"); @@ -1571,13 +1444,13 @@ static char *lookup_map(request_rec *r, char *name, char *key) if (!value) { rewritelog(r, 5, "map lookup FAILED: map=%s[txt] key=%s", name, key); - set_cache_string(cachep, name, CACHEMODE_TS, st.mtime, key, ""); + set_cache_value(name, st.mtime, key, ""); return NULL; } - rewritelog(r, 5, "map lookup OK: map=%s key=%s[txt] -> val=%s", + rewritelog(r, 5, "map lookup OK: map=%s[txt] key=%s -> val=%s", name, key, value); - set_cache_string(cachep, name, CACHEMODE_TS, st.mtime, key, value); + set_cache_value(name, st.mtime, key, value); } else { rewritelog(r, 5, "cache lookup OK: map=%s[txt] key=%s -> val=%s", @@ -1604,7 +1477,7 @@ static char *lookup_map(request_rec *r, char *name, char *key) return NULL; } - value = get_cache_string(cachep, name, CACHEMODE_TS, st.mtime, key); + value = get_cache_value(name, st.mtime, key, r->pool); if (!value) { rewritelog(r, 6, "cache lookup FAILED, forcing new map lookup"); @@ -1612,13 +1485,13 @@ static char *lookup_map(request_rec *r, char *name, char *key) if (!value) { rewritelog(r, 5, "map lookup FAILED: map=%s[dbm] key=%s", name, key); - set_cache_string(cachep, name, CACHEMODE_TS, st.mtime, key, ""); + set_cache_value(name, st.mtime, key, ""); return NULL; } rewritelog(r, 5, "map lookup OK: map=%s[dbm] key=%s -> val=%s", name, key, value); - set_cache_string(cachep, name, CACHEMODE_TS, st.mtime, key, value); + set_cache_value(name, st.mtime, key, value); return value; } @@ -3945,7 +3818,10 @@ static void init_child(apr_pool_t *p, server_rec *s) } /* create the lookup cache */ - cachep = init_cache(p); + if (!init_cache(p)) { + ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, + "mod_rewrite: could not init map cache in child"); + } }