Browse Source

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
svn/tags/lighttpd-1.4.6
Jan Kneschke 17 years ago
parent
commit
b795fd36c0
  1. 101
      src/stat_cache.c

101
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
}
}

Loading…
Cancel
Save