From b795fd36c022e9002d09176a8691a4e393388edd Mon Sep 17 00:00:00 2001 From: Jan Kneschke Date: Wed, 14 Sep 2005 07:27:13 +0000 Subject: [PATCH] fixed hashing function to only generate unsigned values (fixes #251) git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-merge-1.4.x@702 152afb58-edef-0310-8abb-c4023f1b3aa9 --- src/stat_cache.c | 101 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 78 insertions(+), 23 deletions(-) diff --git a/src/stat_cache.c b/src/stat_cache.c index 33645a0f..c916403e 100644 --- a/src/stat_cache.c +++ b/src/stat_cache.c @@ -39,6 +39,11 @@ #define lstat stat #endif +#if 0 +/* enables debug code for testing if all nodes in the stat-cache as accessable */ +#define DEBUG_STAT_CACHE +#endif + /* * stat-cache * @@ -87,6 +92,17 @@ typedef struct { * - if we don't have a stat-cache entry for a directory, release it from the monitor */ +#ifdef DEBUG_STAT_CACHE +typedef struct { + int *ptr; + + size_t used; + size_t size; +} fake_keys; + +static fake_keys ctrl; +#endif + stat_cache *stat_cache_init(void) { stat_cache *fc = NULL; @@ -104,6 +120,10 @@ stat_cache *stat_cache_init(void) { #endif #endif +#ifdef DEBUG_STAT_CACHE + ctrl.size = 0; +#endif + return fc; } @@ -159,17 +179,14 @@ void stat_cache_free(stat_cache *sc) { while (sc->files) { int osize; splay_tree *node = sc->files; + stat_cache_entry *sce = node->data; osize = sc->files->size; stat_cache_entry_free(node->data); sc->files = splaytree_delete(sc->files, node->key); - if (osize == 1) { - assert(NULL == sc->files); - } else { - assert(osize == (sc->files->size + 1)); - } + assert(osize - 1 == splaytree_size(sc->files)); } buffer_free(sc->dir_name); @@ -215,13 +232,16 @@ static int stat_cache_attr_get(buffer *buf, char *name) { } #endif -static int hashme(buffer *str) { - int hash = 0; +/* the famous DJB hash function for strings */ +static uint32_t hashme(buffer *str) { + uint32_t hash = 5381; const char *s; for (s = str->ptr; *s; s++) { - hash = hash * 53 + *s; + hash = ((hash << 5) + hash) + *s; } + hash &= ~(1 << 31); /* strip the highest bit */ + return hash; } @@ -271,16 +291,12 @@ handler_t stat_cache_handle_fdevent(void *_srv, void *_fce, int revent) { node = sc->dirs; if (node && (node->key == ndx)) { - int osize = sc->dirs->size; + int osize = splaytree_size(sc->dirs); fam_dir_entry_free(node->data); sc->dirs = splaytree_delete(sc->dirs, ndx); - if (osize == 1) { - assert(NULL == sc->dirs); - } else { - assert(osize == (sc->dirs->size + 1)); - } + assert(osize - 1 == splaytree_size(sc->dirs)); } break; default: @@ -339,6 +355,7 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_ stat_cache_entry *sce = NULL; stat_cache *sc; struct stat st; + size_t i; int file_ndx; splay_tree *file_node = NULL; @@ -354,7 +371,18 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_ file_ndx = hashme(name); sc->files = splaytree_splay(sc->files, file_ndx); +#ifdef DEBUG_STAT_CACHE + for (i = 0; i < ctrl.used; i++) { + if (ctrl.ptr[i] == file_ndx) break; + } +#endif + if (sc->files && (sc->files->key == file_ndx)) { +#ifdef DEBUG_STAT_CACHE + /* it was in the cache */ + assert(i < ctrl.used); +#endif + /* we have seen this file already and * don't stat() it again in the same second */ @@ -384,6 +412,13 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_ file_node = NULL; } + } else { +#ifdef DEBUG_STAT_CACHE + if (i != ctrl.used) { + fprintf(stderr, "%s.%d: %08x was already inserted but not found in cache, %s\n", __FILE__, __LINE__, file_ndx, name->ptr); + } + assert(i == ctrl.used); +#endif } #ifdef HAVE_FAM_H @@ -445,9 +480,22 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_ buffer_copy_string_buffer(sce->name, name); sc->files = splaytree_insert(sc->files, file_ndx, sce); +#ifdef DEBUG_STAT_CACHE + if (ctrl.size == 0) { + ctrl.size = 16; + ctrl.used = 0; + ctrl.ptr = malloc(ctrl.size * sizeof(*ctrl.ptr)); + } else if (ctrl.size == ctrl.used) { + ctrl.size += 16; + ctrl.ptr = realloc(ctrl.ptr, ctrl.size * sizeof(*ctrl.ptr)); + } + + ctrl.ptr[ctrl.used++] = file_ndx; assert(sc->files); - assert(osize == (sc->files->size - 1)); + assert(sc->files->data == sce); + assert(osize + 1 == splaytree_size(sc->files)); +#endif } sce->st = st; @@ -486,7 +534,7 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_ if (!dir_node) { fam_dir = fam_dir_entry_init(); fam_dir->fc = sc->fam; - + buffer_copy_string_buffer(fam_dir->name, sc->dir_name); fam_dir->version = 1; @@ -511,6 +559,7 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_ sc->dirs = splaytree_insert(sc->dirs, dir_ndx, fam_dir); assert(sc->dirs); + assert(sc->dirs->data == fam_dir); assert(osize == (sc->dirs->size - 1)); } } else { @@ -550,7 +599,7 @@ static int stat_cache_tag_old_entries(server *srv, splay_tree *t, int *keys, siz sce = t->data; - if (srv->cur_ts - sce->stat_ts > 10) { + if (srv->cur_ts - sce->stat_ts > 2) { keys[(*ndx)++] = t->key; } @@ -559,7 +608,7 @@ static int stat_cache_tag_old_entries(server *srv, splay_tree *t, int *keys, siz int stat_cache_trigger_cleanup(server *srv) { stat_cache *sc; - size_t max_ndx = 0, i; + size_t max_ndx = 0, i, j; int *keys; sc = srv->stat_cache; @@ -579,16 +628,22 @@ int stat_cache_trigger_cleanup(server *srv) { node = sc->files; if (node && (node->key == ndx)) { - int osize = sc->files->size; + int osize = splaytree_size(sc->files); + stat_cache_entry *sce = node->data; stat_cache_entry_free(node->data); sc->files = splaytree_delete(sc->files, ndx); - if (osize == 1) { - assert(NULL == sc->files); - } else { - assert(osize == (sc->files->size + 1)); +#ifdef DEBUG_STAT_CACHE + for (j = 0; j < ctrl.used; j++) { + if (ctrl.ptr[j] == ndx) { + ctrl.ptr[j] = ctrl.ptr[--ctrl.used]; + break; + } } + + assert(osize - 1 == splaytree_size(sc->files)); +#endif } }