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