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