Index: main.c
===================================================================
RCS file: /cvsroot/squid/squid/src/main.c,v
retrieving revision 1.1.1.4.2.9
diff -u -r1.1.1.4.2.9 main.c
--- main.c	2000/10/17 09:14:24	1.1.1.4.2.9
+++ main.c	2000/10/20 12:35:31
@@ -101,7 +101,8 @@
 	"       -F        Don't serve any requests until store is rebuilt.\n"
 	"       -N        No daemon mode.\n"
 	"       -R        Do not set REUSEADDR on port.\n"
-	"       -S        Double-check swap during rebuild.\n"
+	"       -S force  Force double-check swap during rebuild.\n"
+        "       -S reportonly Force double-check but do not attempt repair.\n"
 	"       -V        Virtual host httpd-accelerator.\n"
 	"       -X        Force full debugging.\n"
 	"       -Y        Only return UDP_HIT or UDP_MISS_NOFETCH during fast reload.\n",
@@ -115,7 +116,7 @@
     extern char *optarg;
     int c;
 
-    while ((c = getopt(argc, argv, "CDFNRSVYXa:d:f:hk:m::su:vz?")) != -1) {
+    while ((c = getopt(argc, argv, "CDFNRS:VYXa:d:f:hk:m::su:vz?")) != -1) {
 	switch (c) {
 	case 'C':
 	    opt_catch_signals = 0;
@@ -133,7 +134,14 @@
 	    opt_reuseaddr = 0;
 	    break;
 	case 'S':
-	    opt_store_doublecheck = 1;
+            if ((int) strlen(optarg) < 1) 
+                usage();
+            else if (!strncmp(optarg, "force", strlen(optarg)))
+                opt_store_doublecheck = 1; /* trigger a doublecheck on startup */
+            else if (!strncmp(optarg, "reportonly", strlen(optarg)))
+                opt_store_doublecheck = 2; /* trigger a doublecheck that doesn't repair */ 
+            else
+                usage();
 	    break;
 	case 'V':
 	    vhost_mode = 1;
Index: store_rebuild.c
===================================================================
RCS file: /cvsroot/squid/squid/src/store_rebuild.c,v
retrieving revision 1.1.1.4.2.2
diff -u -r1.1.1.4.2.2 store_rebuild.c
--- store_rebuild.c	2000/05/03 18:45:35	1.1.1.4.2.2
+++ store_rebuild.c	2000/10/20 12:35:31
@@ -65,6 +65,7 @@
 	    store_dirs_rebuilding--;
 	    assert(0 == store_dirs_rebuilding);
 	    if (opt_store_doublecheck)
+            /* we want to assert here because the storeFScode should auto-clean the entries */
 		assert(store_errors == 0);
 	    if (store_digest)
 		storeDigestNoteStoreReady();
@@ -83,8 +84,10 @@
 	    if (e->swap_filen < 0)
 		continue;
 	    if (opt_store_doublecheck)
-		if (storeCleanupDoubleCheck(e))
+		if (storeCleanupDoubleCheck(e)){
+                    /* this should never happen as the storeFScode should auto-clean */
 		    store_errors++;
+                }    
 	    EBIT_SET(e->flags, ENTRY_VALIDATED);
 	    /*
 	     * Only set the file bit if we know its a valid entry
@@ -112,6 +115,8 @@
     counts.invalid += dc->invalid;
     counts.badflags += dc->badflags;
     counts.bad_log_op += dc->bad_log_op;
+    counts.missingcount += dc->missingcount;
+    counts.filesizemismatchcount += dc->filesizemismatchcount;
     counts.zero_object_sz += dc->zero_object_sz;
     /*
      * When store_dirs_rebuilding == 1, it means we are done reading
@@ -130,6 +135,8 @@
     debug(20, 1) ("  %7d Objects cancelled.\n", counts.cancelcount);
     debug(20, 1) ("  %7d Duplicate URLs purged.\n", counts.dupcount);
     debug(20, 1) ("  %7d Swapfile clashes avoided.\n", counts.clashcount);
+    debug(20, 1) ("  %7d Missing files ignored.\n", counts.missingcount);
+    debug(20, 1) ("  %7d Incorrect length swapfiles %s.\n", counts.filesizemismatchcount, (opt_store_doublecheck==2) ? "ignored" : "unlinked");
     debug(20, 1) ("  Took %3.1f seconds (%6.1f objects/sec).\n", dt,
 	(double) counts.objcount / (dt > 0.0 ? dt : 1.0));
     debug(20, 1) ("Beginning Validation Procedure\n");
Index: structs.h
===================================================================
RCS file: /cvsroot/squid/squid/src/structs.h,v
retrieving revision 1.1.1.4.2.18
diff -u -r1.1.1.4.2.18 structs.h
--- structs.h	2000/10/17 09:14:25	1.1.1.4.2.18
+++ structs.h	2000/10/20 12:35:42
@@ -1841,6 +1841,8 @@
     int cancelcount;		/* # SWAP_LOG_DEL objects purged */
     int invalid;		/* # bad lines */
     int badflags;		/* # bad e->flags */
+    int missingcount;		/* # swapfiles not on disk */
+    int filesizemismatchcount;  /* # swapfiles with a wrong size */
     int bad_log_op;
     int zero_object_sz;
 };
Index: fs/ufs/store_dir_ufs.c
===================================================================
RCS file: /cvsroot/squid/squid/src/fs/ufs/Attic/store_dir_ufs.c,v
retrieving revision 1.1.8.8
diff -u -r1.1.8.8 store_dir_ufs.c
--- fs/ufs/store_dir_ufs.c	2000/10/17 09:14:25	1.1.8.8
+++ fs/ufs/store_dir_ufs.c	2000/10/20 12:35:48
@@ -117,6 +117,7 @@
 static int storeUfsDirIs(SwapDir * sd);
 static int storeUfsFilenoBelongsHere(int fn, int F0, int F1, int F2);
 static int storeUfsCleanupDoubleCheck(SwapDir *, StoreEntry *);
+static int storeUfsCheckFile(SwapDir * sd, sfileno filn, size_t swap_file_sz );
 static void storeUfsDirStats(SwapDir *, StoreEntry *);
 static void storeUfsDirInitBitmap(SwapDir *);
 static int storeUfsDirValidFileno(SwapDir *, sfileno, int);
@@ -522,6 +523,7 @@
     int count;
     int used;			/* is swapfile already in use? */
     int disk_entry_newer;	/* is the log entry newer than current entry? */
+    int file_bad;
     double x;
     assert(rb != NULL);
     /* load a number of objects per invocation */
@@ -604,7 +606,20 @@
 	 * appear to have a newer entry?  Compare 'lastref' from the
 	 * swap log to e->lastref. */
 	disk_entry_newer = e ? (s.lastref > e->lastref ? 1 : 0) : 0;
-	if (used && !disk_entry_newer) {
+        if (!used && (rb->flags.need_to_validate || opt_store_doublecheck)){
+            file_bad = storeUfsCheckFile(SD, s.swap_filen, s.swap_file_sz);
+        } else 
+            file_bad = 0;
+        if (file_bad){
+            if (file_bad==-2){
+                  if (opt_store_doublecheck != 2) 
+                      storeUfsDirUnlinkFile(SD, s.swap_filen);
+                  rb->counts.filesizemismatchcount++; 
+                  continue;
+            }
+            rb->counts.missingcount++;
+            continue;
+	}else if (used && !disk_entry_newer) {
 	    /* log entry is old, ignore it */
 	    rb->counts.clashcount++;
 	    continue;
@@ -667,19 +682,19 @@
 	    /* load new */
 	    (void) 0;
 	}
-	/* update store_swap_size */
-	rb->counts.objcount++;
-	e = storeUfsDirAddDiskRestore(SD, s.key,
-	    s.swap_filen,
-	    s.swap_file_sz,
-	    s.expires,
-	    s.timestamp,
-	    s.lastref,
-	    s.lastmod,
-	    s.refcount,
-	    s.flags,
-	    (int) rb->flags.clean);
-	storeDirSwapLog(e, SWAP_LOG_ADD);
+       /* update store_swap_size */
+       rb->counts.objcount++;
+       e = storeUfsDirAddDiskRestore(SD, s.key,
+           s.swap_filen,
+           s.swap_file_sz,
+           s.expires,
+           s.timestamp,
+           s.lastref,
+           s.lastmod,
+           s.refcount,
+           s.flags,
+           (int) rb->flags.clean);
+       storeDirSwapLog(e, SWAP_LOG_ADD);
     }
     eventAdd("storeRebuild", storeUfsDirRebuildFromSwapLog, rb, 0.0, 1);
 }
@@ -1577,28 +1592,39 @@
 static int
 storeUfsCleanupDoubleCheck(SwapDir * sd, StoreEntry * e)
 {
+    int rv= storeUfsCheckFile(sd, e->swap_filen, e->swap_file_sz);
+    if (rv) storeEntryDump(e, 0);
+    return rv;
+}
+
+/*
+ * storeUfsCheckFile
+ *
+ * This is called by storerebuildFromSwapLog if -S was given on the command line. or a Dirty state is found
+ */
+static int
+storeUfsCheckFile(SwapDir * sd, sfileno filen, size_t swap_file_sz )
+{
     struct stat sb;
 
-    if (stat(storeUfsDirFullPath(sd, e->swap_filen, NULL), &sb) < 0) {
-	debug(20, 0) ("storeUfsCleanupDoubleCheck: MISSING SWAP FILE\n");
-	debug(20, 0) ("storeUfsCleanupDoubleCheck: FILENO %08X\n", e->swap_filen);
-	debug(20, 0) ("storeUfsCleanupDoubleCheck: PATH %s\n",
-	    storeUfsDirFullPath(sd, e->swap_filen, NULL));
-	storeEntryDump(e, 0);
-	return -1;
+    if (stat(storeUfsDirFullPath(sd, filen, NULL), &sb) < 0) {
+        debug(20, 1) ("storeUfsCheckFile: MISSING SWAP FILE\n");
+        debug(20, 1) ("storeUfsCheckFile: FILENO %08X\n", filen);
+        debug(20, 1) ("storeUfsCheckFile: PATH %s\n", storeUfsDirFullPath(sd, filen, NULL));
+
+        return -1;
+    }
+    if (swap_file_sz != sb.st_size) {
+        debug(20, 1) ("storeUfsCheckFile: SIZE MISMATCH\n");
+        debug(20, 1) ("storeUfsCheckFile: FILENO %08X\n", filen);
+        debug(20, 1) ("storeUfsCheckFile: PATH %s\n", storeUfsDirFullPath(sd, filen, NULL));
+        debug(20, 1) ("storeUfsCheckFile: ENTRY SIZE: %d, FILE SIZE: %d\n", swap_file_sz, (int) sb.st_size);
+        return -2;
     }
-    if (e->swap_file_sz != sb.st_size) {
-	debug(20, 0) ("storeUfsCleanupDoubleCheck: SIZE MISMATCH\n");
-	debug(20, 0) ("storeUfsCleanupDoubleCheck: FILENO %08X\n", e->swap_filen);
-	debug(20, 0) ("storeUfsCleanupDoubleCheck: PATH %s\n",
-	    storeUfsDirFullPath(sd, e->swap_filen, NULL));
-	debug(20, 0) ("storeUfsCleanupDoubleCheck: ENTRY SIZE: %d, FILE SIZE: %d\n",
-	    e->swap_file_sz, (int) sb.st_size);
-	storeEntryDump(e, 0);
-	return -1;
-    }
     return 0;
 }
+
+
 
 /*
  * storeUfsDirParse

