|
|
|
@ -107,9 +107,9 @@ static uint32_t hashme(const char *str, const size_t len)
|
|
|
|
|
#include <fam.h> |
|
|
|
|
|
|
|
|
|
typedef struct { |
|
|
|
|
FAMRequest *req; |
|
|
|
|
buffer *name; |
|
|
|
|
int version; |
|
|
|
|
FAMRequest req; |
|
|
|
|
} fam_dir_entry; |
|
|
|
|
|
|
|
|
|
typedef struct stat_cache_fam { |
|
|
|
@ -119,7 +119,7 @@ typedef struct stat_cache_fam {
|
|
|
|
|
|
|
|
|
|
int dir_ndx; |
|
|
|
|
fam_dir_entry *fam_dir; |
|
|
|
|
buffer *dir_name; /* for building the dirname from the filename */ |
|
|
|
|
size_t dirlen; /* for building the dirname from the filename */ |
|
|
|
|
fdnode *fdn; |
|
|
|
|
int fd; |
|
|
|
|
} stat_cache_fam; |
|
|
|
@ -140,11 +140,9 @@ static void fam_dir_entry_free(FAMConnection *fc, void *data) {
|
|
|
|
|
|
|
|
|
|
if (!fam_dir) return; |
|
|
|
|
|
|
|
|
|
FAMCancelMonitor(fc, fam_dir->req); |
|
|
|
|
FAMCancelMonitor(fc, &fam_dir->req); |
|
|
|
|
|
|
|
|
|
buffer_free(fam_dir->name); |
|
|
|
|
free(fam_dir->req); |
|
|
|
|
|
|
|
|
|
free(fam_dir); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -216,7 +214,6 @@ static handler_t stat_cache_handle_fdevent(server *srv, void *_fce, int revent)
|
|
|
|
|
|
|
|
|
|
static stat_cache_fam * stat_cache_init_fam(server *srv) { |
|
|
|
|
stat_cache_fam *scf = calloc(1, sizeof(*scf)); |
|
|
|
|
scf->dir_name = buffer_init(); |
|
|
|
|
scf->fd = -1; |
|
|
|
|
|
|
|
|
|
/* setup FAM */ |
|
|
|
@ -239,7 +236,6 @@ static stat_cache_fam * stat_cache_init_fam(server *srv) {
|
|
|
|
|
|
|
|
|
|
static void stat_cache_free_fam(stat_cache_fam *scf) { |
|
|
|
|
if (NULL == scf) return; |
|
|
|
|
buffer_free(scf->dir_name); |
|
|
|
|
|
|
|
|
|
while (scf->dirs) { |
|
|
|
|
splay_tree *node = scf->dirs; |
|
|
|
@ -256,29 +252,19 @@ static void stat_cache_free_fam(stat_cache_fam *scf) {
|
|
|
|
|
free(scf); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int buffer_copy_dirname(buffer *dst, const buffer *file) { |
|
|
|
|
size_t i; |
|
|
|
|
|
|
|
|
|
if (buffer_string_is_empty(file)) return -1; |
|
|
|
|
|
|
|
|
|
for (i = buffer_string_length(file); i > 0; i--) { |
|
|
|
|
if (file->ptr[i] == '/') { |
|
|
|
|
buffer_copy_string_len(dst, file->ptr, i); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static handler_t stat_cache_fam_dir_check(server *srv, stat_cache_fam *scf, stat_cache_entry *sce, const buffer *name) { |
|
|
|
|
if (0 != buffer_copy_dirname(scf->dir_name, name)) { |
|
|
|
|
char *slash = !buffer_string_is_empty(name) |
|
|
|
|
? strrchr(name->ptr, '/') |
|
|
|
|
: NULL; |
|
|
|
|
if (NULL == slash) { |
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "sb", |
|
|
|
|
"no '/' found in filename:", name); |
|
|
|
|
return HANDLER_ERROR; |
|
|
|
|
} |
|
|
|
|
scf->dirlen = (size_t)(slash - name->ptr); |
|
|
|
|
if (0 == scf->dirlen) scf->dirlen = 1; /* root dir ("/") */ |
|
|
|
|
|
|
|
|
|
scf->dir_ndx = hashme(CONST_BUF_LEN(scf->dir_name)); |
|
|
|
|
scf->dir_ndx = hashme(name->ptr, scf->dirlen); |
|
|
|
|
|
|
|
|
|
scf->dirs = splaytree_splay(scf->dirs, scf->dir_ndx); |
|
|
|
|
|
|
|
|
@ -286,7 +272,7 @@ static handler_t stat_cache_fam_dir_check(server *srv, stat_cache_fam *scf, stat
|
|
|
|
|
scf->fam_dir = scf->dirs->data; |
|
|
|
|
|
|
|
|
|
/* check whether we got a collision */ |
|
|
|
|
if (buffer_is_equal(scf->dir_name, scf->fam_dir->name)) { |
|
|
|
|
if (buffer_is_equal_string(scf->fam_dir->name, name->ptr, scf->dirlen)) { |
|
|
|
|
/* test whether a found file cache entry is still ok */ |
|
|
|
|
if ((NULL != sce) && (scf->fam_dir->version == sce->dir_version)) { |
|
|
|
|
/* the stat()-cache entry is still ok */ |
|
|
|
@ -309,15 +295,12 @@ static void stat_cache_fam_dir_monitor(server *srv, stat_cache_fam *scf, stat_ca
|
|
|
|
|
if (NULL == fam_dir) { |
|
|
|
|
fam_dir = fam_dir_entry_init(); |
|
|
|
|
|
|
|
|
|
buffer_copy_buffer(fam_dir->name, scf->dir_name); |
|
|
|
|
buffer_copy_string_len(fam_dir->name, name->ptr, scf->dirlen); |
|
|
|
|
|
|
|
|
|
fam_dir->version = 1; |
|
|
|
|
|
|
|
|
|
fam_dir->req = calloc(1, sizeof(FAMRequest)); |
|
|
|
|
force_assert(NULL != fam_dir); |
|
|
|
|
|
|
|
|
|
if (0 != FAMMonitorDirectory(&scf->fam, fam_dir->name->ptr, |
|
|
|
|
fam_dir->req, fam_dir)) { |
|
|
|
|
&fam_dir->req, fam_dir)) { |
|
|
|
|
|
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "sbsbs", |
|
|
|
|
"monitoring dir failed:", |
|
|
|
@ -326,7 +309,7 @@ static void stat_cache_fam_dir_monitor(server *srv, stat_cache_fam *scf, stat_ca
|
|
|
|
|
FamErrlist[FAMErrno]); |
|
|
|
|
|
|
|
|
|
fam_dir_entry_free(&scf->fam, fam_dir); |
|
|
|
|
fam_dir = NULL; |
|
|
|
|
return; |
|
|
|
|
} else { |
|
|
|
|
int osize = splaytree_size(scf->dirs); |
|
|
|
|
|
|
|
|
@ -347,10 +330,7 @@ static void stat_cache_fam_dir_monitor(server *srv, stat_cache_fam *scf, stat_ca
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* bind the fam_fc to the stat() cache entry */ |
|
|
|
|
|
|
|
|
|
if (fam_dir) { |
|
|
|
|
sce->dir_version = fam_dir->version; |
|
|
|
|
} |
|
|
|
|
sce->dir_version = fam_dir->version; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#endif |
|
|
|
|