summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2010-12-06 15:29:38 +0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2010-12-06 15:29:38 +0000
commit8062d3af30b27eb4d617c14856d4f3a173f8012e (patch)
treea1ab6dceb03955ec348092fd739d0fef4972e5e2
parentde79d23f76c13da820f7167cd980264b2de28bd2 (diff)
downloadguix-8062d3af30b27eb4d617c14856d4f3a173f8012e.tar.gz
* `nix-store --verify --check-contents': don't hold the global GC lock
  while checking the contents, since this operation can take a very
  long time to finish.  Also, fill in missing narSize fields in the DB
  while doing this.

-rw-r--r--src/libstore/local-store.cc57
-rw-r--r--src/libstore/local-store.hh3
2 files changed, 49 insertions, 11 deletions
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index 88548706b8..3782d1b169 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -353,6 +353,8 @@ void LocalStore::openDB(bool create)
     /* Prepare SQL statements. */
     stmtRegisterValidPath.create(db,
         "insert into ValidPaths (path, hash, registrationTime, deriver, narSize) values (?, ?, ?, ?, ?);");
+    stmtUpdatePathInfo.create(db,
+        "update ValidPaths set narSize = ? where path = ?;");
     stmtAddReference.create(db,
         "insert or replace into Refs (referrer, reference) values (?, ?);");
     stmtQueryPathInfo.create(db,
@@ -645,6 +647,21 @@ ValidPathInfo LocalStore::queryPathInfo(const Path & path)
 }
 
 
+/* Update path info in the database.  Currently only updated the
+   narSize field. */
+void LocalStore::updatePathInfo(const ValidPathInfo & info)
+{
+    SQLiteStmtUse use(stmtUpdatePathInfo);
+    if (info.narSize != 0)
+        stmtUpdatePathInfo.bind64(info.narSize);
+    else
+        stmtUpdatePathInfo.bind(); // null
+    stmtUpdatePathInfo.bind(info.path);
+    if (sqlite3_step(stmtUpdatePathInfo) != SQLITE_DONE)
+        throwSQLiteError(db, format("updating info of path `%1%' in database") % info.path);
+}
+
+
 unsigned long long LocalStore::queryValidPathId(const Path & path)
 {
     SQLiteStmtUse use(stmtQueryPathInfo);
@@ -1305,23 +1322,41 @@ void LocalStore::verifyStore(bool checkContents)
     foreach (PathSet::iterator, i, validPaths2)
         verifyPath(*i, store, done, validPaths);
 
+    /* Release the GC lock so that checking content hashes (which can
+       take ages) doesn't block the GC or builds. */
+    fdGCLock.close();
+
     /* Optionally, check the content hashes (slow). */
     if (checkContents) {
         printMsg(lvlInfo, "checking hashes...");
 
         foreach (PathSet::iterator, i, validPaths) {
-            ValidPathInfo info = queryPathInfo(*i);
-
-            /* Check the content hash (optionally - slow). */
-            printMsg(lvlTalkative, format("checking contents of `%1%'") % *i);
-            Hash current = hashPath(info.hash.type, *i).first;
-            if (current != info.hash) {
-                printMsg(lvlError, format("path `%1%' was modified! "
-                        "expected hash `%2%', got `%3%'")
-                    % *i % printHash(info.hash) % printHash(current));
-            }
+            try {
+                ValidPathInfo info = queryPathInfo(*i);
+
+                /* Check the content hash (optionally - slow). */
+                printMsg(lvlTalkative, format("checking contents of `%1%'") % *i);
+                HashResult current = hashPath(info.hash.type, *i);
+                
+                if (current.first != info.hash) {
+                    printMsg(lvlError, format("path `%1%' was modified! "
+                            "expected hash `%2%', got `%3%'")
+                        % *i % printHash(info.hash) % printHash(current.first));
+                } else {
+                    /* Fill in missing narSize fields (from old stores). */
+                    if (info.narSize == 0) {
+                        printMsg(lvlError, format("updating size field on `%1%' to %2%") % *i % current.second);
+                        info.narSize = current.second;
+                        updatePathInfo(info);
+                    }
+                }
             
-            /* !!! Check info.narSize */
+            } catch (Error & e) {
+                /* It's possible that the path got GC'ed, so ignore
+                   errors on invalid paths. */
+                if (isValidPath(*i)) throw;
+                printMsg(lvlError, format("warning: %1%") % e.msg());
+            }
         }
     }
 }
diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh
index 4076e59574..f270fb7239 100644
--- a/src/libstore/local-store.hh
+++ b/src/libstore/local-store.hh
@@ -203,6 +203,7 @@ private:
 
     /* Some precompiled SQLite statements. */
     SQLiteStmt stmtRegisterValidPath;
+    SQLiteStmt stmtUpdatePathInfo;
     SQLiteStmt stmtAddReference;
     SQLiteStmt stmtQueryPathInfo;
     SQLiteStmt stmtQueryReferences;
@@ -235,6 +236,8 @@ private:
     void verifyPath(const Path & path, const PathSet & store,
         PathSet & done, PathSet & validPaths);
 
+    void updatePathInfo(const ValidPathInfo & info);
+
     void upgradeStore6();
     PathSet queryValidPathsOld();
     ValidPathInfo queryPathInfoOld(const Path & path);