diff --git a/src/stat_cache.c b/src/stat_cache.c index 45d6139c..b0f72e53 100644 --- a/src/stat_cache.c +++ b/src/stat_cache.c @@ -245,88 +245,88 @@ static void stat_cache_invalidate_dir_tree(server *srv, const char *name, size_t static void stat_cache_handle_fdevent_in(server *srv, stat_cache_fam *scf) { - for (int i = 0, ndx; i || (i = FAMPending(&scf->fam)) > 0; --i) { - FAMEvent fe; - if (FAMNextEvent(&scf->fam, &fe) < 0) break; - - /* ignore events which may have been pending for - * paths recently cancelled via FAMCancelMonitor() */ - ndx = (int)(intptr_t)fe.userdata; - scf->dirs = splaytree_splay(scf->dirs, ndx); - if (!scf->dirs || scf->dirs->key != ndx) { - continue; - } - fam_dir_entry *fam_dir = scf->dirs->data; - if (FAMREQUEST_GETREQNUM(&fam_dir->req) - != FAMREQUEST_GETREQNUM(&fe.fr)) { - continue; - } + for (int i = 0, ndx; i || (i = FAMPending(&scf->fam)) > 0; --i) { + FAMEvent fe; + if (FAMNextEvent(&scf->fam, &fe) < 0) break; + + /* ignore events which may have been pending for + * paths recently cancelled via FAMCancelMonitor() */ + ndx = (int)(intptr_t)fe.userdata; + scf->dirs = splaytree_splay(scf->dirs, ndx); + if (!scf->dirs || scf->dirs->key != ndx) { + continue; + } + fam_dir_entry *fam_dir = scf->dirs->data; + if (FAMREQUEST_GETREQNUM(&fam_dir->req) + != FAMREQUEST_GETREQNUM(&fe.fr)) { + continue; + } - if (fe.filename[0] != '/') { - buffer * const n = fam_dir->name; - fam_dir_entry *fam_link; - size_t len; - switch(fe.code) { - case FAMCreated: - /* file created in monitored dir modifies dir and - * we should get a separate FAMChanged event for dir. - * Therefore, ignore file FAMCreated event here. - * Also, if FAMNoExists() is used, might get spurious - * FAMCreated events as changes are made e.g. in monitored - * sub-sub-sub dirs and the library discovers new (already - * existing) dir entries */ - continue; - case FAMChanged: - /* file changed in monitored dir does not modify dir */ - case FAMDeleted: - case FAMMoved: - /* file deleted or moved in monitored dir modifies dir, - * but FAM provides separate notification for that */ - - /* temporarily append filename to dir in fam_dir->name to - * construct path, then delete stat_cache entry (if any)*/ - len = buffer_string_length(n); - buffer_append_string_len(n, CONST_STR_LEN("/")); - buffer_append_string_len(n,fe.filename,strlen(fe.filename)); - /* (alternatively, could chose to stat() and update)*/ - stat_cache_invalidate_entry(srv, CONST_BUF_LEN(n)); - - fam_link = /*(check if might be symlink to monitored dir)*/ - stat_cache_sptree_find(&scf->dirs, CONST_BUF_LEN(n)); - if (fam_link && !buffer_is_equal(fam_link->name, n)) - fam_link = NULL; - - buffer_string_set_length(n, len); - - if (fam_link) { - /* replaced symlink changes containing dir */ - stat_cache_invalidate_entry(srv, CONST_BUF_LEN(n)); - /* handle symlink to dir as deleted dir below */ - fe.code = FAMDeleted; - fam_dir = fam_link; - break; - } - continue; - default: - continue; - } - } + if (fe.filename[0] != '/') { + buffer * const n = fam_dir->name; + fam_dir_entry *fam_link; + size_t len; + switch(fe.code) { + case FAMCreated: + /* file created in monitored dir modifies dir and + * we should get a separate FAMChanged event for dir. + * Therefore, ignore file FAMCreated event here. + * Also, if FAMNoExists() is used, might get spurious + * FAMCreated events as changes are made e.g. in monitored + * sub-sub-sub dirs and the library discovers new (already + * existing) dir entries */ + continue; + case FAMChanged: + /* file changed in monitored dir does not modify dir */ + case FAMDeleted: + case FAMMoved: + /* file deleted or moved in monitored dir modifies dir, + * but FAM provides separate notification for that */ + + /* temporarily append filename to dir in fam_dir->name to + * construct path, then delete stat_cache entry (if any)*/ + len = buffer_string_length(n); + buffer_append_string_len(n, CONST_STR_LEN("/")); + buffer_append_string_len(n,fe.filename,strlen(fe.filename)); + /* (alternatively, could chose to stat() and update)*/ + stat_cache_invalidate_entry(srv, CONST_BUF_LEN(n)); + + fam_link = /*(check if might be symlink to monitored dir)*/ + stat_cache_sptree_find(&scf->dirs, CONST_BUF_LEN(n)); + if (fam_link && !buffer_is_equal(fam_link->name, n)) + fam_link = NULL; + + buffer_string_set_length(n, len); + + if (fam_link) { + /* replaced symlink changes containing dir */ + stat_cache_invalidate_entry(srv, CONST_BUF_LEN(n)); + /* handle symlink to dir as deleted dir below */ + fe.code = FAMDeleted; + fam_dir = fam_link; + break; + } + continue; + default: + continue; + } + } - switch(fe.code) { - case FAMChanged: - stat_cache_invalidate_entry(srv, CONST_BUF_LEN(fam_dir->name)); - break; - case FAMDeleted: - case FAMMoved: - stat_cache_delete_tree(srv, CONST_BUF_LEN(fam_dir->name)); - fam_dir_invalidate_node(fam_dir); - fam_dir_invalidate_tree(scf->dirs, CONST_BUF_LEN(fam_dir->name)); - fam_dir_periodic_cleanup(srv); - break; - default: - break; - } - } + switch(fe.code) { + case FAMChanged: + stat_cache_invalidate_entry(srv, CONST_BUF_LEN(fam_dir->name)); + break; + case FAMDeleted: + case FAMMoved: + stat_cache_delete_tree(srv, CONST_BUF_LEN(fam_dir->name)); + fam_dir_invalidate_node(fam_dir); + fam_dir_invalidate_tree(scf->dirs, CONST_BUF_LEN(fam_dir->name)); + fam_dir_periodic_cleanup(srv); + break; + default: + break; + } + } } static handler_t stat_cache_handle_fdevent(server *srv, void *_fce, int revent)