X-Git-Url: http://git.vrable.net/?a=blobdiff_plain;f=statcache.cc;h=86886c0e4a68cb72483244895e45b142bb69ff5f;hb=bf947741ac8f65e74d594a1e14e94d90320b403e;hp=a0bee44fd14152fa34463240c5bf76637823f35b;hpb=4b89157cdec2da9a016a7ea0f511a0f3ff43f6dc;p=cumulus.git diff --git a/statcache.cc b/statcache.cc index a0bee44..86886c0 100644 --- a/statcache.cc +++ b/statcache.cc @@ -30,9 +30,9 @@ #include #include -#include "format.h" #include "ref.h" #include "statcache.h" +#include "util.h" using std::list; using std::map; @@ -117,9 +117,11 @@ void StatCache::ReadNext() std::istream &cache = *oldcache; map fields; + old_is_validated = false; old_mtime = -1; old_ctime = -1; old_inode = -1; + old_size = -1; old_checksum = ""; old_contents.clear(); @@ -129,6 +131,7 @@ void StatCache::ReadNext() end_of_cache = true; return; } + old_name = uri_decode(old_name); /* Start reading in the fields which follow the filename. */ string field = ""; @@ -162,12 +165,16 @@ void StatCache::ReadNext() } /* Parse the easy fields: mtime, ctime, inode, checksum, ... */ + if (fields.count("validated")) + old_is_validated = true; if (fields.count("mtime")) old_mtime = parse_int(fields["mtime"]); if (fields.count("ctime")) old_ctime = parse_int(fields["ctime"]); if (fields.count("inode")) old_inode = parse_int(fields["inode"]); + if (fields.count("size")) + old_size = parse_int(fields["size"]); old_checksum = fields["checksum"]; @@ -211,6 +218,10 @@ bool StatCache::Find(const string &path, const struct stat *stat_buf) if (old_name != path) return false; + /* Do we trust cached stat information? */ + if (!old_is_validated) + return false; + /* Check to see if the file is unchanged. */ if (stat_buf->st_mtime != old_mtime) return false; @@ -218,6 +229,8 @@ bool StatCache::Find(const string &path, const struct stat *stat_buf) return false; if ((long long)stat_buf->st_ino != old_inode) return false; + if (stat_buf->st_size != old_size) + return false; /* File looks to be unchanged. */ return true; @@ -227,10 +240,27 @@ bool StatCache::Find(const string &path, const struct stat *stat_buf) void StatCache::Save(const string &path, struct stat *stat_buf, const string &checksum, const list &blocks) { + /* Was this file in the old stat cache, and is the information unchanged? + * If so, mark the information "validated", which means we are confident + * that we can use it to accurately detect changes. (Stat information may + * not be updated if, for example, there are two writes within a single + * second and we happen to make the first stat call between them. However, + * if two stat calls separated in time agree, then we will trust the + * values.) */ + bool validated = false; + if (!end_of_cache && path == old_name) { + if (stat_buf->st_mtime == old_mtime + && stat_buf->st_ctime == old_ctime + && (long long)stat_buf->st_ino == old_inode + && old_checksum == checksum) + validated = true; + } + *newcache << uri_encode(path) << "\n"; *newcache << "mtime: " << encode_int(stat_buf->st_mtime) << "\n" << "ctime: " << encode_int(stat_buf->st_ctime) << "\n" << "inode: " << encode_int(stat_buf->st_ino) << "\n" + << "size: " << encode_int(stat_buf->st_size) << "\n" << "checksum: " << checksum << "\n"; *newcache << "blocks:"; @@ -241,5 +271,8 @@ void StatCache::Save(const string &path, struct stat *stat_buf, *newcache << " " << *i << "\n"; } + if (validated) + *newcache << "validated: true\n"; + *newcache << "\n"; }