1 /* LBS: An LFS-inspired filesystem backup system Copyright (C) 2007 Michael
4 * To speed backups, we maintain a "stat cache" containing selected information
5 * about all regular files, including modification times and the list of blocks
6 * that comprised the file in the last backup. If the file has not changed
7 * according to a stat() call, we may re-use the information contained in the
8 * stat cache instead of re-reading the entire file. It is always safe to
9 * discard information from the stat cache; this will only cause a file to be
10 * re-read to determine that it contains the same data as before.
12 * The stat cache is stored in a file called "statcache" in the local backup
13 * directory. During a backup, a new statcache file is written out with a
14 * suffix based on the current time; at the end of a successful backup this
15 * file is renamed over the original statcache file.
17 * The information in the statcache file is stored in sorted order as we
18 * traverse the filesystem, so that we can read and write it in a purely
19 * streaming manner. (This is why we don't include the information in the
20 * SQLite local database; doing so is likely less efficient.)
32 #include "statcache.h"
39 void StatCache::Open(const char *path, const char *snapshot_name)
42 oldpath += "/statcache";
43 newpath = oldpath + "." + snapshot_name;
46 newcache = new ofstream(newpath.c_str());
49 void StatCache::Close()
56 if (rename(newpath.c_str(), oldpath.c_str()) < 0) {
57 fprintf(stderr, "Error renaming statcache from %s to %s: %m\n",
58 newpath.c_str(), oldpath.c_str());
62 /* Save stat information about a regular file for future invocations. */
63 void StatCache::Save(const string &path, struct stat *stat_buf,
64 const string &checksum, const list<string> &blocks)
66 *newcache << uri_encode(path) << "\n";
67 *newcache << "mtime: " << encode_int(stat_buf->st_mtime) << "\n"
68 << "ctime: " << encode_int(stat_buf->st_ctime) << "\n"
69 << "inode: " << encode_int(stat_buf->st_ino) << "\n"
70 << "checksum: " << checksum << "\n";
72 *newcache << "blocks:";
73 for (list<string>::const_iterator i = blocks.begin();
74 i != blocks.end(); ++i) {
75 *newcache << " " << *i << "\n";