diff options
-rw-r--r-- | src/libstore/build.cc | 4 | ||||
-rw-r--r-- | src/libstore/gc.cc | 2 | ||||
-rw-r--r-- | src/libstore/misc.cc | 4 | ||||
-rw-r--r-- | src/libstore/store.cc | 112 | ||||
-rw-r--r-- | src/libstore/store.hh | 6 | ||||
-rw-r--r-- | src/nix-store/main.cc | 4 |
6 files changed, 106 insertions, 26 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 64443d41a785..3785c7da7924 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -806,7 +806,7 @@ DerivationGoal::HookReply DerivationGoal::tryBuildHook() { s += *i; PathSet references; - queryReferences(*i, references); + queryReferences(noTxn, *i, references); for (PathSet::iterator j = references.begin(); j != references.end(); ++j) { @@ -1326,7 +1326,7 @@ void SubstitutionGoal::init() /* To maintain the closure invairant, we first have to realise the paths referenced by this one. */ - queryReferences(storePath, references); + queryReferences(noTxn, storePath, references); for (PathSet::iterator i = references.begin(); i != references.end(); ++i) diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 020712368f52..4d63d46ea1f5 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -279,7 +279,7 @@ static void dfsVisit(const PathSet & paths, const Path & path, PathSet references; if (isValidPath(path)) - queryReferences(path, references); + queryReferences(noTxn, path, references); for (PathSet::iterator i = references.begin(); i != references.end(); ++i) diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc index b20879178805..5f20ee277513 100644 --- a/src/libstore/misc.cc +++ b/src/libstore/misc.cc @@ -19,9 +19,9 @@ void computeFSClosure(const Path & storePath, PathSet references; if (flipDirection) - queryReferers(storePath, references); + queryReferers(noTxn, storePath, references); else - queryReferences(storePath, references); + queryReferences(noTxn, storePath, references); for (PathSet::iterator i = references.begin(); i != references.end(); ++i) diff --git a/src/libstore/store.cc b/src/libstore/store.cc index 693a388b3e1e..0c7702f973bd 100644 --- a/src/libstore/store.cc +++ b/src/libstore/store.cc @@ -325,21 +325,23 @@ void setReferences(const Transaction & txn, const Path & storePath, } -void queryReferences(const Path & storePath, PathSet & references) +void queryReferences(const Transaction & txn, + const Path & storePath, PathSet & references) { Paths references2; - if (!isRealisablePath(noTxn, storePath)) + if (!isRealisablePath(txn, storePath)) throw Error(format("path `%1%' is not valid") % storePath); - nixDB.queryStrings(noTxn, dbReferences, storePath, references2); + nixDB.queryStrings(txn, dbReferences, storePath, references2); references.insert(references2.begin(), references2.end()); } -void queryReferers(const Path & storePath, PathSet & referers) +void queryReferers(const Transaction & txn, + const Path & storePath, PathSet & referers) { - if (!isRealisablePath(noTxn, storePath)) + if (!isRealisablePath(txn, storePath)) throw Error(format("path `%1%' is not valid") % storePath); - PathSet referers2 = getReferers(noTxn, storePath); + PathSet referers2 = getReferers(txn, storePath); referers.insert(referers2.begin(), referers2.end()); } @@ -358,7 +360,7 @@ void setDeriver(const Transaction & txn, const Path & storePath, Path queryDeriver(const Transaction & txn, const Path & storePath) { - if (!isRealisablePath(noTxn, storePath)) + if (!isRealisablePath(txn, storePath)) throw Error(format("path `%1%' is not valid") % storePath); Path deriver; if (nixDB.queryString(txn, dbDerivers, storePath, deriver)) @@ -641,13 +643,8 @@ void verifyStore() validPaths.insert(path); } - /* !!! the code below does not allow transitive substitutes. - I.e., if B is a substitute of A, then B must be a valid path. - B cannot itself be invalid but have a substitute. */ - - /* "Usable" paths are those that are valid or have a substitute. - These are the paths that are allowed to appear in the - right-hand side of a sute mapping. */ + /* "Usable" paths are those that are valid or have a + substitute. */ PathSet usablePaths(validPaths); /* Check that the values of the substitute mappings are valid @@ -656,10 +653,91 @@ void verifyStore() nixDB.enumTable(txn, dbSubstitutes, subKeys); for (Paths::iterator i = subKeys.begin(); i != subKeys.end(); ++i) { Substitutes subs = readSubstitutes(txn, *i); - if (subs.size() > 0) - usablePaths.insert(*i); - else + if (!isStorePath(*i)) { + printMsg(lvlError, format("found substitutes for non-store path `%1%'") % *i); nixDB.delPair(txn, dbSubstitutes, *i); + } + else if (subs.size() == 0) + nixDB.delPair(txn, dbSubstitutes, *i); + else + usablePaths.insert(*i); + } + + /* Check the cleanup invariant: only usable paths can have + `references', `referers', or `derivers' entries. */ + + /* Check the `derivers' table. */ + Paths deriversKeys; + nixDB.enumTable(txn, dbDerivers, deriversKeys); + for (Paths::iterator i = deriversKeys.begin(); + i != deriversKeys.end(); ++i) + { + if (usablePaths.find(*i) == usablePaths.end()) { + printMsg(lvlError, format("found deriver entry for unusable path `%1%'") + % *i); + nixDB.delPair(txn, dbDerivers, *i); + } + else { + Path deriver = queryDeriver(txn, *i); + if (!isStorePath(deriver)) { + printMsg(lvlError, format("found corrupt deriver `%1%' for `%2%'") + % deriver % *i); + nixDB.delPair(txn, dbDerivers, *i); + } + } + } + + /* Check the `references' table. */ + Paths referencesKeys; + nixDB.enumTable(txn, dbReferences, referencesKeys); + for (Paths::iterator i = referencesKeys.begin(); + i != referencesKeys.end(); ++i) + { + if (usablePaths.find(*i) == usablePaths.end()) { + printMsg(lvlError, format("found references entry for unusable path `%1%'") + % *i); + nixDB.delPair(txn, dbReferences, *i); + } + else { + PathSet references; + queryReferences(txn, *i, references); + for (PathSet::iterator j = references.begin(); + j != references.end(); ++j) + { + PathSet referers = getReferers(txn, *j); + if (referers.find(*i) == referers.end()) { + printMsg(lvlError, format("missing referer mapping from `%1%' to `%2%'") + % *j % *i); + } + } + } + } + + /* Check the `referers' table. */ + Paths referersKeys; + nixDB.enumTable(txn, dbReferers, referersKeys); + for (Paths::iterator i = referersKeys.begin(); + i != referersKeys.end(); ++i) + { + if (usablePaths.find(*i) == usablePaths.end()) { + printMsg(lvlError, format("found referers entry for unusable path `%1%'") + % *i); + nixDB.delPair(txn, dbReferers, *i); + } + else { + PathSet referers; + queryReferers(txn, *i, referers); + for (PathSet::iterator j = referers.begin(); + j != referers.end(); ++j) + { + Paths references; + nixDB.queryStrings(txn, dbReferences, *j, references); + if (find(references.begin(), references.end(), *i) == references.end()) { + printMsg(lvlError, format("missing reference mapping from `%1%' to `%2%'") + % *j % *i); + } + } + } } txn.commit(); diff --git a/src/libstore/store.hh b/src/libstore/store.hh index 1f2b630e106c..e981ade1009b 100644 --- a/src/libstore/store.hh +++ b/src/libstore/store.hh @@ -90,11 +90,13 @@ void setReferences(const Transaction & txn, const Path & storePath, /* Queries the set of outgoing FS references for a store path. The result is not cleared. */ -void queryReferences(const Path & storePath, PathSet & references); +void queryReferences(const Transaction & txn, + const Path & storePath, PathSet & references); /* Queries the set of incoming FS references for a store path. The result is not cleared. */ -void queryReferers(const Path & storePath, PathSet & referers); +void queryReferers(const Transaction & txn, + const Path & storePath, PathSet & referers); /* Sets the deriver of a store path. Use with care! */ void setDeriver(const Transaction & txn, const Path & storePath, diff --git a/src/nix-store/main.cc b/src/nix-store/main.cc index f9bd3323f447..a3c1b8fa782e 100644 --- a/src/nix-store/main.cc +++ b/src/nix-store/main.cc @@ -215,8 +215,8 @@ static void opQuery(Strings opFlags, Strings opArgs) Path path = maybeUseOutput(*i, useOutput, forceRealise); if (query == qRequisites) storePathRequisites(path, includeOutputs, paths); - else if (query == qReferences) queryReferences(path, paths); - else if (query == qReferers) queryReferers(path, paths); + else if (query == qReferences) queryReferences(noTxn, path, paths); + else if (query == qReferers) queryReferers(noTxn, path, paths); else if (query == qReferersClosure) computeFSClosure(path, paths, true); } printPathSet(paths); |