diff options
author | John Ericson <John.Ericson@Obsidian.Systems> | 2023-08-02 13:39:29 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-02 13:39:29 -0400 |
commit | 3723363697b3908a2f58dce3e706783b1c783414 (patch) | |
tree | 7708a84722bbf09cc83b0b5b7bb2af2f5e58f74e | |
parent | d00469ebf94dba4ae30120c1ba36085ac20443b8 (diff) | |
parent | 66550878dffe2a4bf55ea7ab694738aa14e6a01e (diff) |
Merge pull request #8765 from NixLayeredStore/refactor-store-verify
More cleanups for `LocalStore::verifyPath`
-rw-r--r-- | src/libstore/local-store.cc | 38 | ||||
-rw-r--r-- | src/libstore/local-store.hh | 2 |
2 files changed, 28 insertions, 12 deletions
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index f78bd44ca..40a3bc194 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -1499,17 +1499,33 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair) auto fdGCLock = openGCLock(); FdLock gcLock(fdGCLock.get(), ltRead, true, "waiting for the big garbage collector lock..."); - StringSet store; - for (auto & i : readDirectory(realStoreDir)) store.insert(i.name); + StorePathSet validPaths; - /* Check whether all valid paths actually exist. */ - printInfo("checking path existence..."); + { + StorePathSet storePathsInStoreDir; + /* Why aren't we using `queryAllValidPaths`? Because that would + tell us about all the paths than the database knows about. Here we + want to know about all the store paths in the store directory, + regardless of what the database thinks. + + We will end up cross-referencing these two sources of truth (the + database and the filesystem) in the loop below, in order to catch + invalid states. + */ + for (auto & i : readDirectory(realStoreDir)) { + try { + storePathsInStoreDir.insert({i.name}); + } catch (BadStorePath &) { } + } - StorePathSet validPaths; - StorePathSet done; + /* Check whether all valid paths actually exist. */ + printInfo("checking path existence..."); + + StorePathSet done; - for (auto & i : queryAllValidPaths()) - verifyPath(i, store, done, validPaths, repair, errors); + for (auto & i : queryAllValidPaths()) + verifyPath(i, storePathsInStoreDir, done, validPaths, repair, errors); + } /* Optionally, check the content hashes (slow). */ if (checkContents) { @@ -1595,21 +1611,21 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair) } -void LocalStore::verifyPath(const StorePath & path, const StringSet & store, +void LocalStore::verifyPath(const StorePath & path, const StorePathSet & storePathsInStoreDir, StorePathSet & done, StorePathSet & validPaths, RepairFlag repair, bool & errors) { checkInterrupt(); if (!done.insert(path).second) return; - if (!store.count(std::string(path.to_string()))) { + if (!storePathsInStoreDir.count(path)) { /* Check any referrers first. If we can invalidate them first, then we can invalidate this path as well. */ bool canInvalidate = true; StorePathSet referrers; queryReferrers(path, referrers); for (auto & i : referrers) if (i != path) { - verifyPath(i, store, done, validPaths, repair, errors); + verifyPath(i, storePathsInStoreDir, done, validPaths, repair, errors); if (validPaths.count(i)) canInvalidate = false; } diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index c9b570eaa..e97195f5b 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -314,7 +314,7 @@ private: */ void invalidatePathChecked(const StorePath & path); - void verifyPath(const StorePath & path, const StringSet & store, + void verifyPath(const StorePath & path, const StorePathSet & store, StorePathSet & done, StorePathSet & validPaths, RepairFlag repair, bool & errors); std::shared_ptr<const ValidPathInfo> queryPathInfoInternal(State & state, const StorePath & path); |