Browse Source

[stat_cache] interfaces to invalidate entries

personal/stbuehler/ci-build
Glenn Strauss 3 years ago
parent
commit
57470365a2
  1. 111
      src/stat_cache.c
  2. 3
      src/stat_cache.h

111
src/stat_cache.c

@ -207,6 +207,10 @@ static void fam_dir_prune_tree(stat_cache_fam * const scf,
} while (max_ndx == sizeof(keys)/sizeof(int));
}
/* declarations */
static void stat_cache_delete_tree(server *srv, const char *name, size_t len);
static void stat_cache_invalidate_entry(server *srv, const char *name, size_t len);
static handler_t stat_cache_handle_fdevent(server *srv, void *_fce, int revent) {
stat_cache_fam *scf = srv->stat_cache->scf;
UNUSED(_fce);
@ -230,6 +234,7 @@ static handler_t stat_cache_handle_fdevent(server *srv, void *_fce, int revent)
}
if (fe.filename[0] != '/') {
size_t len;
switch(fe.code) {
case FAMCreated:
/* file created in monitored dir modifies dir */
@ -238,12 +243,19 @@ static handler_t stat_cache_handle_fdevent(server *srv, void *_fce, int revent)
case FAMChanged:
/* file changed in monitored dir does not modify dir */
++fam_dir->version; /* however, current impl here needs this */
break;
case FAMDeleted:
case FAMMoved:
/* file deleted or moved in monitored dir modifies dir,
* but FAM provides separate notification for that */
++fam_dir->version;
/* temporarily append filename to dir in fam_dir->name to
* construct path, then delete stat_cache entry (if any)*/
len = buffer_string_length(fam_dir->name);
buffer_append_string_len(fam_dir->name, CONST_STR_LEN("/"));
buffer_append_string_len(fam_dir->name, fe.filename, strlen(fe.filename));
/* (alternatively, could chose to stat() and update)*/
stat_cache_invalidate_entry(srv, CONST_BUF_LEN(fam_dir->name));
buffer_string_set_length(fam_dir->name, len);
break;
default:
break;
@ -255,11 +267,13 @@ static handler_t stat_cache_handle_fdevent(server *srv, void *_fce, int revent)
switch(fe.code) {
case FAMChanged:
++fam_dir->version;
stat_cache_invalidate_entry(srv, CONST_BUF_LEN(fam_dir->name));
break;
case FAMDeleted:
case FAMMoved:
scf->dirs = splaytree_delete(scf->dirs, ndx);
fam_dir_prune_tree(scf, CONST_BUF_LEN(fam_dir->name));
stat_cache_delete_tree(srv, CONST_BUF_LEN(fam_dir->name));
fam_dir_entry_free(&scf->fam, fam_dir);
break;
default:
@ -594,6 +608,101 @@ const buffer * stat_cache_etag_get(stat_cache_entry *sce, etag_flags_t flags) {
return NULL;
}
void stat_cache_update_entry(server *srv, const char *name, size_t len,
struct stat *st, buffer *etagb)
{
if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_NONE) return;
force_assert(0 != len);
if (name[len-1] == '/') { if (0 == --len) len = 1; }
splay_tree **sptree = &srv->stat_cache->files;
stat_cache_entry *sce =
stat_cache_sptree_find(sptree, name, len);
if (sce && buffer_is_equal_string(sce->name, name, len)) {
sce->stat_ts = srv->cur_ts;
sce->st = *st;
buffer_copy_buffer(sce->etag, etagb);
}
}
void stat_cache_delete_entry(server *srv, const char *name, size_t len)
{
if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_NONE) return;
force_assert(0 != len);
if (name[len-1] == '/') { if (0 == --len) len = 1; }
splay_tree **sptree = &srv->stat_cache->files;
stat_cache_entry *sce = stat_cache_sptree_find(sptree, name, len);
if (sce && buffer_is_equal_string(sce->name, name, len)) {
stat_cache_entry_free(sce);
*sptree = splaytree_delete(*sptree, (*sptree)->key);
}
}
static void stat_cache_invalidate_entry(server *srv, const char *name, size_t len)
{
splay_tree **sptree = &srv->stat_cache->files;
stat_cache_entry *sce = stat_cache_sptree_find(sptree, name, len);
if (sce && buffer_is_equal_string(sce->name, name, len)) {
sce->stat_ts = 0;
}
}
/*
* walk though splay_tree and collect contents of dir tree.
* remove tagged entries in a second loop
*/
static void stat_cache_tag_dir_tree(splay_tree *t, const char *name, size_t len,
int *keys, int *ndx)
{
if (*ndx == 8192) return; /*(must match num array entries in keys[])*/
if (t->left) stat_cache_tag_dir_tree(t->left, name, len, keys, ndx);
if (t->right) stat_cache_tag_dir_tree(t->right, name, len, keys, ndx);
if (*ndx == 8192) return; /*(must match num array entries in keys[])*/
buffer *b = ((stat_cache_entry *)t->data)->name;
size_t blen = buffer_string_length(b);
if (blen > len && b->ptr[len] == '/' && 0 == memcmp(b->ptr, name, len))
keys[(*ndx)++] = t->key;
}
static void stat_cache_prune_dir_tree(stat_cache * const sc,
const char *name, size_t len)
{
int max_ndx, i;
int keys[8192]; /* 32k size on stack */
do {
if (!sc->files) return;
max_ndx = 0;
stat_cache_tag_dir_tree(sc->files, name, len, keys, &max_ndx);
for (i = 0; i < max_ndx; ++i) {
const int ndx = keys[i];
splay_tree *node = sc->files = splaytree_splay(sc->files, ndx);
if (node && node->key == ndx) {
stat_cache_entry_free(node->data);
sc->files = splaytree_delete(sc->files, ndx);
}
}
} while (max_ndx == sizeof(keys)/sizeof(int));
}
static void stat_cache_delete_tree(server *srv, const char *name, size_t len)
{
stat_cache_delete_entry(srv, name, len);
stat_cache_prune_dir_tree(srv->stat_cache, name, len);
}
void stat_cache_delete_dir(server *srv, const char *name, size_t len)
{
force_assert(0 != len);
if (name[len-1] == '/') { if (0 == --len) len = 1; }
#ifdef HAVE_FAM_H
if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM) {
fam_dir_node_delete(srv->stat_cache->scf, name, len);
fam_dir_prune_tree(srv->stat_cache->scf, name, len);
}
#endif
stat_cache_delete_tree(srv, name, len);
}
/***
*

3
src/stat_cache.h

@ -39,6 +39,9 @@ void stat_cache_free(struct stat_cache *fc);
const buffer * stat_cache_mimetype_by_ext(const connection *con, const char *name, size_t nlen);
const buffer * stat_cache_content_type_get(server *srv, connection *con, const buffer *name, stat_cache_entry *sce);
const buffer * stat_cache_etag_get(stat_cache_entry *sce, etag_flags_t flags);
void stat_cache_update_entry(server *srv, const char *name, size_t len, struct stat *st, buffer *etagb);
void stat_cache_delete_entry(server *srv, const char *name, size_t len);
void stat_cache_delete_dir(server *srv, const char *name, size_t len);
handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_cache_entry **sce);
int stat_cache_path_contains_symlink(server *srv, buffer *name);
int stat_cache_open_rdonly_fstat (buffer *name, struct stat *st, int symlinks);

Loading…
Cancel
Save