#include <map>
#include <string>
-#include "format.h"
#include "ref.h"
#include "statcache.h"
+#include "util.h"
using std::list;
using std::map;
return pathcmp(slash1 + 1, slash2 + 1);
}
-void StatCache::Open(const char *path, const char *snapshot_name)
+void StatCache::Open(const char *path, const char *snapshot_name,
+ const char *snapshot_scheme)
{
oldpath = path;
oldpath += "/statcache";
+ if (snapshot_scheme != NULL)
+ oldpath = oldpath + "-" + snapshot_scheme;
newpath = oldpath + "." + snapshot_name;
oldcache = new ifstream(oldpath.c_str());
std::istream &cache = *oldcache;
map<string, string> fields;
+ old_is_validated = false;
old_mtime = -1;
old_ctime = -1;
old_inode = -1;
+ old_size = -1;
old_checksum = "";
old_contents.clear();
end_of_cache = true;
return;
}
+ old_name = uri_decode(old_name);
/* Start reading in the fields which follow the filename. */
string field = "";
}
/* 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"];
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;
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;
void StatCache::Save(const string &path, struct stat *stat_buf,
const string &checksum, const list<string> &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:";
*newcache << " " << *i << "\n";
}
+ if (validated)
+ *newcache << "validated: true\n";
+
*newcache << "\n";
}