Permalink
Browse files

Validate the freshness of stat items.

  • Loading branch information...
1 parent 158b05f commit 2ee3fe15b59db0b5b9b7784b9ebd0912217ed332 @davidstrauss davidstrauss committed Dec 12, 2012
Showing with 38 additions and 25 deletions.
  1. +11 −15 src/fusedav.c
  2. +27 −10 src/statcache.c
View
@@ -399,7 +399,7 @@ static int update_directory(const char *path, bool attempt_progessive_update, vo
else {
log_print(LOG_DEBUG, "Freshen PROPFIND failed: %s", ne_get_error(session));
}
-
+
free(update_path);
}
@@ -415,8 +415,9 @@ static int update_directory(const char *path, bool attempt_progessive_update, vo
}
stat_cache_delete_older(config->cache, path, min_generation);
}
-
+
// Mark the directory contents as updated.
+ log_print(LOG_DEBUG, "Marking directory %s as updated at timestamp %lu.", path, timestamp);
stat_cache_updated_children(config->cache, path, timestamp);
return 0;
}
@@ -434,8 +435,7 @@ static int dav_readdir(
path = path_cvt(path);
- //if (debug)
- // log_print(LOG_DEBUG, "getdir(%s)", path);
+ //log_print(LOG_DEBUG, "getdir(%s)", path);
f.buf = buf;
f.filler = filler;
@@ -514,10 +514,6 @@ static int get_stat(const char *path, struct stat *stbuf) {
// Check if we can directly hit this file in the stat cache.
if ((response = stat_cache_value_get(config->cache, path))) {
-
- // @TODO: Check that either the stat data itself of the containing
- // directory is fresh enough.
-
*stbuf = response->st;
free(response);
//print_stat(stbuf, "get_stat from cache");
@@ -528,7 +524,7 @@ static int get_stat(const char *path, struct stat *stbuf) {
// If it's the root directory, just do a single PROPFIND.
log_print(LOG_DEBUG, "Checking if path %s matches base directory: %s", path, base_directory);
- if (!config->refresh_dir_for_file_stat && strcmp(path, base_directory) == 0) {
+ if (!config->refresh_dir_for_file_stat || strcmp(path, base_directory) == 0) {
log_print(LOG_DEBUG, "Performing zero-depth PROPFIND on base directory: %s", base_directory);
if (simple_propfind_with_redirect(session, path, NE_DEPTH_ZERO, query_properties, getattr_propfind_callback, stbuf) != NE_OK) {
stat_cache_delete(config->cache, path);
@@ -544,7 +540,7 @@ static int get_stat(const char *path, struct stat *stbuf) {
// If it's not found, check the freshness of its directory.
parent_path = strip_trailing_slash(ne_path_parent(path), &is_dir);
-
+
log_print(LOG_DEBUG, "Getting parent path entry: %s", parent_path);
parent_children_update_ts = stat_cache_read_updated_children(config->cache, parent_path);
log_print(LOG_DEBUG, "Parent was updated: %lu", parent_children_update_ts);
@@ -555,7 +551,7 @@ static int get_stat(const char *path, struct stat *stbuf) {
update_directory(parent_path, (parent_children_update_ts > 0), &junk_value);
}
- // Try again to hit the file in the stat cache.
+ // Try again to hit the file in the stat cache.
if ((response = stat_cache_value_get(config->cache, path))) {
log_print(LOG_DEBUG, "Hit updated cache: %s", path);
*stbuf = response->st;
@@ -691,7 +687,7 @@ static int dav_mkdir(const char *path, mode_t mode) {
value.st.st_gid = getgid();
value.prepopulated = true;
stat_cache_value_set(config->cache, path, &value);
-
+
//stat_cache_delete(config->cache, path);
//stat_cache_delete_parent(config->cache, path);
@@ -817,7 +813,7 @@ static int dav_mknod(const char *path, mode_t mode, __unused dev_t rdev) {
//char tempfile[PATH_MAX];
//int fd;
//ne_session *session;
-
+
path = path_cvt(path);
if (debug)
log_print(LOG_DEBUG, "mknod(%s)", path);
@@ -1007,7 +1003,7 @@ static int dav_utimens(const char *path, const struct timespec tv[2]) {
goto finish;
}
- // @TODO: Before public release:Update the stat cache instead.
+ // @TODO: Update the stat cache instead.
stat_cache_delete(config->cache, path);
finish:
@@ -1753,7 +1749,7 @@ static int config_privileges(struct fusedav_config *config) {
}
log_print(LOG_DEBUG, "Set egid to %d (which is uid %d's primary gid).", u->pw_gid, u->pw_uid);
}
-
+
if (seteuid(u->pw_uid) < 0) {
log_print(LOG_ERR, "Can't drop uid to %d.", u->pw_uid);
return -1;
View
@@ -166,7 +166,7 @@ struct stat_cache_value *stat_cache_value_get(stat_cache_t *cache, const char *p
size_t vallen;
char *errptr = NULL;
//void *f;
- //time_t current_time;
+ time_t current_time;
key = path2key(path, false);
@@ -195,14 +195,28 @@ struct stat_cache_value *stat_cache_value_get(stat_cache_t *cache, const char *p
log_print(LOG_ERR, "Length %lu is not expected length %lu.", vallen, sizeof(struct stat_cache_value));
}
- /*
current_time = time(NULL);
+
+ // First, check against the stat item itself.
+ //log_print(LOG_DEBUG, "Current time: %lu", current_time);
if (current_time - value->updated > CACHE_TIMEOUT) {
- log_print(LOG_DEBUG, "%s too old", path);
- free(value);
- return NULL;
+ char *directory;
+ time_t directory_updated;
+ int is_dir;
+
+ //log_print(LOG_DEBUG, "Stat entry %s is %lu seconds old.", path, current_time - value->updated);
+
+ // If that's too old, check the last update of the directory.
+ directory = strip_trailing_slash(ne_path_parent(path), &is_dir);
+ directory_updated = stat_cache_read_updated_children(cache, directory);
+ //log_print(LOG_DEBUG, "Directory contents for %s are %lu seconds old.", directory, (current_time - directory_updated));
+ free(directory);
+ if (current_time - directory_updated > CACHE_TIMEOUT) {
+ log_print(LOG_DEBUG, "%s is too old.", path);
+ free(value);
+ return NULL;
+ }
}
- */
/*
if ((f = file_cache_get(path))) {
@@ -255,14 +269,17 @@ time_t stat_cache_read_updated_children(stat_cache_t *cache, const char *path) {
leveldb_readoptions_destroy(options);
if (errptr != NULL) {
- log_print(LOG_ERR, "leveldb_set error: %s", errptr);
+ log_print(LOG_ERR, "leveldb_get error: %s", errptr);
free(errptr);
- r = -1;
+ r = 0;
}
if (value == NULL) return 0;
r = *value;
+
+ //log_print(LOG_DEBUG, "Children for directory %s were updated at timestamp %lu.", path, r);
+
free(value);
return r;
}
@@ -471,11 +488,11 @@ int stat_cache_enumerate(stat_cache_t *cache, const char *path_prefix, void (*f)
//stat_cache_list_all(cache, path_prefix);
if (!force) {
timestamp = stat_cache_read_updated_children(cache, path_prefix);
-
+
if (timestamp == 0) {
return -STAT_CACHE_NO_DATA;
}
-
+
// Check for cache values which are too old; but timestamp = 0 needs to trigger below
current_time = time(NULL);
if (current_time - timestamp > CACHE_TIMEOUT) {

0 comments on commit 2ee3fe1

Please sign in to comment.