Author: eelco
Date: Tue Aug 31 11:47:31 2010
New Revision: 23557
URL: https://svn.nixos.org/websvn/nix/?rev=23557&sc=1

Log:
`nix-store --verify' improvements:
* If a path has disappeared, check its referrers first, and don't try
  to invalidate paths that have valid referrers.  Otherwise we get a
  foreign key constraint violation.
* Read the whole Nix store directory instead of statting each valid
  path, which is slower.
* Acquire the global GC lock.

Modified:
   nix/branches/sqlite/src/libstore/gc.cc
   nix/branches/sqlite/src/libstore/local-store.cc
   nix/branches/sqlite/src/libstore/local-store.hh

Modified: nix/branches/sqlite/src/libstore/gc.cc
==============================================================================
--- nix/branches/sqlite/src/libstore/gc.cc      Tue Aug 31 10:40:28 2010        
(r23556)
+++ nix/branches/sqlite/src/libstore/gc.cc      Tue Aug 31 11:47:31 2010        
(r23557)
@@ -1,6 +1,5 @@
 #include "globals.hh"
 #include "misc.hh"
-#include "pathlocks.hh"
 #include "local-store.hh"
 
 #include <boost/shared_ptr.hpp>
@@ -31,7 +30,7 @@
    read.  To be precise: when they try to create a new temporary root
    file, they will block until the garbage collector has finished /
    yielded the GC lock. */
-static int openGCLock(LockType lockType)
+int LocalStore::openGCLock(LockType lockType)
 {
     Path fnGCLock = (format("%1%/%2%")
         % nixStateDir % gcLockName).str();

Modified: nix/branches/sqlite/src/libstore/local-store.cc
==============================================================================
--- nix/branches/sqlite/src/libstore/local-store.cc     Tue Aug 31 10:40:28 
2010        (r23556)
+++ nix/branches/sqlite/src/libstore/local-store.cc     Tue Aug 31 11:47:31 
2010        (r23557)
@@ -1226,27 +1226,25 @@
 
 void LocalStore::verifyStore(bool checkContents)
 {
-    /* Check whether all valid paths actually exist. */
-    printMsg(lvlInfo, "checking path existence");
+    printMsg(lvlError, format("reading the Nix store..."));
 
-    PathSet validPaths2 = queryValidPaths(), validPaths;
+    /* Acquire the global GC lock to prevent a garbage collection. */
+    AutoCloseFD fdGCLock = openGCLock(ltWrite);
     
-    foreach (PathSet::iterator, i, validPaths2) {
-        checkInterrupt();
-        /* !!! invalidatePath() will probably fail due to the foreign
-           key constraints on the Ref table. */
-        if (!isStorePath(*i)) {
-            printMsg(lvlError, format("path `%1%' is not in the Nix store") % 
*i);
-            invalidatePath(*i);
-        } else if (!pathExists(*i)) {
-            printMsg(lvlError, format("path `%1%' disappeared") % *i);
-            invalidatePath(*i);
-        } else validPaths.insert(*i);
-    }
+    Paths entries = readDirectory(nixStore);
+    PathSet store(entries.begin(), entries.end());
+
+    /* Check whether all valid paths actually exist. */
+    printMsg(lvlInfo, "checking path existence...");
+
+    PathSet validPaths2 = queryValidPaths(), validPaths, done;
+
+    foreach (PathSet::iterator, i, validPaths2)
+        verifyPath(*i, store, done, validPaths);
 
     /* Optionally, check the content hashes (slow). */
     if (checkContents) {
-        printMsg(lvlInfo, "checking hashes");
+        printMsg(lvlInfo, "checking hashes...");
 
         foreach (PathSet::iterator, i, validPaths) {
             ValidPathInfo info = queryPathInfo(*i);
@@ -1264,6 +1262,45 @@
 }
 
 
+void LocalStore::verifyPath(const Path & path, const PathSet & store,
+    PathSet & done, PathSet & validPaths)
+{
+    checkInterrupt();
+    
+    if (done.find(path) != done.end()) return;
+    done.insert(path);
+
+    if (!isStorePath(path)) {
+        printMsg(lvlError, format("path `%1%' is not in the Nix store") % 
path);
+        invalidatePath(path);
+        return;
+    }
+
+    if (store.find(baseNameOf(path)) == store.end()) {
+        /* Check any referrers first.  If we can invalidate them
+           first, then we can invalidate this path as well. */
+        bool canInvalidate = true;
+        PathSet referrers; queryReferrers(path, referrers);
+        foreach (PathSet::iterator, i, referrers)
+            if (*i != path) {
+                verifyPath(*i, store, done, validPaths);
+                if (validPaths.find(*i) != validPaths.end())
+                    canInvalidate = false;
+            }
+
+        if (canInvalidate) {
+            printMsg(lvlError, format("path `%1%' disappeared, removing from 
database...") % path);
+            invalidatePath(path);
+        } else
+            printMsg(lvlError, format("path `%1%' disappeared, but it still 
has valid referrers!") % path);
+        
+        return;
+    }
+    
+    validPaths.insert(path);
+}
+
+
 /* Functions for upgrading from the pre-SQLite database. */
 
 PathSet LocalStore::queryValidPathsOld()

Modified: nix/branches/sqlite/src/libstore/local-store.hh
==============================================================================
--- nix/branches/sqlite/src/libstore/local-store.hh     Tue Aug 31 10:40:28 
2010        (r23556)
+++ nix/branches/sqlite/src/libstore/local-store.hh     Tue Aug 31 11:47:31 
2010        (r23557)
@@ -5,6 +5,7 @@
 
 #include "store-api.hh"
 #include "util.hh"
+#include "pathlocks.hh"
 
 
 class sqlite3;
@@ -16,8 +17,8 @@
 
 /* Nix store and database schema version.  Version 1 (or 0) was Nix <=
    0.7.  Version 2 was Nix 0.8 and 0.9.  Version 3 is Nix 0.10.
-   Version 4 is Nix 0.11.  Version 5 is Nix 0.12-0.14.  Version 6 is
-   Nix 0.15. */
+   Version 4 is Nix 0.11.  Version 5 is Nix 0.12-0.16.  Version 6 is
+   Nix 1.0. */
 const int nixSchemaVersion = 6;
 
 
@@ -233,6 +234,9 @@
 
     void invalidatePath(const Path & path);
 
+    void verifyPath(const Path & path, const PathSet & store,
+        PathSet & done, PathSet & validPaths);
+
     void upgradeStore6();
     PathSet queryValidPathsOld();
     ValidPathInfo queryPathInfoOld(const Path & path);
@@ -244,6 +248,8 @@
     bool isActiveTempFile(const GCState & state,
         const Path & path, const string & suffix);
         
+    int openGCLock(LockType lockType);
+    
     void startSubstituter(const Path & substituter,
         RunningSubstituter & runningSubstituter);
 
_______________________________________________
nix-commits mailing list
[email protected]
http://mail.cs.uu.nl/mailman/listinfo/nix-commits

Reply via email to