Add the --rebuild-statcache option.
authorMichael Vrable <mvrable@cs.ucsd.edu>
Mon, 14 Jul 2008 22:49:18 +0000 (15:49 -0700)
committerMichael Vrable <mvrable@turin.ucsd.edu>
Mon, 14 Jul 2008 22:49:18 +0000 (15:49 -0700)
Add an option which forces cumulus to re-read all files, even if they seem
not to have changed.

This has two main purposes: first, it helps to rebuild the contents of the
statcache from data actually on disk, and as such is useful for adding
object size annotations to files which haven't changed (ordinarily, the
straight re-use of data from the statcache prevents this).

Second, it can be used to detect some simple forms of data corruption; if a
file has not changed (according to stat information) but the checksum
doesn't match the old value in the statcache file, a warning is printed.

scandir.cc

index a2a7a49..10e908b 100644 (file)
@@ -96,6 +96,8 @@ std::list<string> searches;         // Directories we don't want to save, but
 
 bool relative_paths = true;
 
+bool flag_rebuild_statcache = false;
+
 /* Whether verbose output is enabled. */
 bool verbose = false;
 
@@ -154,7 +156,9 @@ int64_t dumpfile(int fd, dictionary &file_info, const string &path,
     if (found)
         old_blocks = metawriter->get_blocks();
 
-    if (found && metawriter->is_unchanged(&stat_buf)) {
+    if (found
+        && !flag_rebuild_statcache
+        && metawriter->is_unchanged(&stat_buf)) {
         cached = true;
 
         /* If any of the blocks in the object have been expired, then we should
@@ -285,6 +289,22 @@ int64_t dumpfile(int fd, dictionary &file_info, const string &path,
         file_info["checksum"] = hash.checksum_str();
     }
 
+    // Sanity check: if we are rebuilding the statcache, but the file looks
+    // like it hasn't changed, then the newly-computed checksum should match
+    // the checksum in the statcache.  If not, we have possible disk corruption
+    // and report a warning.
+    if (flag_rebuild_statcache) {
+        if (found && file_info["checksum"] != metawriter->get_checksum()) {
+            fprintf(stderr,
+                    "Warning: Checksum for %s does not match expected value\n"
+                    "    expected: %s\n"
+                    "    actual:   %s\n",
+                    path.c_str(),
+                    metawriter->get_checksum().c_str(),
+                    file_info["checksum"].c_str());
+        }
+    }
+
     if (verbose && status != NULL)
         printf("    [%s]\n", status);
 
@@ -639,6 +659,7 @@ int main(int argc, char *argv[])
             {"full-metadata", 0, 0, 0},     // 8
             {"tmpdir", 1, 0, 0},            // 9
             {"upload-script", 1, 0, 0},     // 10
+            {"rebuild-statcache", 0, 0, 0}, // 11
             // Aliases for short options
             {"verbose", 0, 0, 'v'},
             {NULL, 0, 0, 0},
@@ -690,6 +711,9 @@ int main(int argc, char *argv[])
             case 10:    // --upload-script
                 backup_script = optarg;
                 break;
+            case 11:    // --rebuild-statcache
+                flag_rebuild_statcache = true;
+                break;
             default:
                 fprintf(stderr, "Unhandled long option!\n");
                 return 1;