From de66d7b2b405d267ecb48871cc46dd5405e196b1 Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Sat, 1 Feb 2025 21:24:35 +0100 Subject: [PATCH] libstore: asyncify Store::verifyStore Change-Id: I12d5f348aa5a253d409b45db8a6bbb18754450c0 --- lix/legacy/nix-store.cc | 2 +- lix/libstore/daemon.cc | 2 +- lix/libstore/local-store.cc | 34 +++++++++++++++++++++++----------- lix/libstore/local-store.hh | 4 ++-- lix/libstore/remote-store.cc | 8 +++++--- lix/libstore/remote-store.hh | 2 +- lix/libstore/store-api.hh | 5 ++++- 7 files changed, 37 insertions(+), 20 deletions(-) diff --git a/lix/legacy/nix-store.cc b/lix/legacy/nix-store.cc index c76c54b45..909a3c115 100644 --- a/lix/legacy/nix-store.cc +++ b/lix/legacy/nix-store.cc @@ -748,7 +748,7 @@ static void opVerify(AsyncIoRoot & aio, Strings opFlags, Strings opArgs) else if (i == "--repair") repair = Repair; else throw UsageError("unknown flag '%1%'", i); - if (store->verifyStore(checkContents, repair)) { + if (aio.blockOn(store->verifyStore(checkContents, repair))) { warn("not all store errors were fixed"); throw Exit(1); } diff --git a/lix/libstore/daemon.cc b/lix/libstore/daemon.cc index 00fc99ac3..aca828057 100644 --- a/lix/libstore/daemon.cc +++ b/lix/libstore/daemon.cc @@ -854,7 +854,7 @@ static void performOp(AsyncIoRoot & aio, TunnelLogger * logger, ref store logger->startWork(); if (repair && !trusted) throw Error("you are not privileged to repair paths"); - bool errors = store->verifyStore(checkContents, (RepairFlag) repair); + bool errors = aio.blockOn(store->verifyStore(checkContents, (RepairFlag) repair)); logger->stopWork(); to << errors; break; diff --git a/lix/libstore/local-store.cc b/lix/libstore/local-store.cc index c88a79305..4a47c2ce0 100644 --- a/lix/libstore/local-store.cc +++ b/lix/libstore/local-store.cc @@ -8,6 +8,7 @@ #include "lix/libstore/nar-info.hh" #include "lix/libutil/async.hh" #include "lix/libutil/references.hh" +#include "lix/libutil/result.hh" #include "lix/libutil/topo-sort.hh" #include "lix/libutil/signals.hh" #include "lix/libutil/finally.hh" @@ -1517,8 +1518,8 @@ void LocalStore::invalidatePathChecked(const StorePath & path) } -bool LocalStore::verifyStore(bool checkContents, RepairFlag repair) -{ +kj::Promise> LocalStore::verifyStore(bool checkContents, RepairFlag repair) +try { printInfo("reading the Nix store..."); bool errors = false; @@ -1553,7 +1554,7 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair) StorePathSet done; for (auto & i : queryAllValidPaths()) - verifyPath(i, storePathsInStoreDir, done, validPaths, repair, errors); + TRY_AWAIT(verifyPath(i, storePathsInStoreDir, done, validPaths, repair, errors)); } /* Optionally, check the content hashes (slow). */ @@ -1598,7 +1599,7 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair) if (info->narHash != nullHash && info->narHash != current.first) { printError("path '%s' was modified! expected hash '%s', got '%s'", printStorePath(i), info->narHash.to_string(Base::Base32, true), current.first.to_string(Base::Base32, true)); - if (repair) RUN_ASYNC_IN_NEW_THREAD(repairPath(i)); else errors = true; + if (repair) TRY_AWAIT(repairPath(i)); else errors = true; } else { bool update = false; @@ -1636,16 +1637,24 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair) } } - return errors; + co_return errors; +} catch (...) { + co_return result::current_exception(); } -void LocalStore::verifyPath(const StorePath & path, const StorePathSet & storePathsInStoreDir, - StorePathSet & done, StorePathSet & validPaths, RepairFlag repair, bool & errors) -{ +kj::Promise> LocalStore::verifyPath( + const StorePath & path, + const StorePathSet & storePathsInStoreDir, + StorePathSet & done, + StorePathSet & validPaths, + RepairFlag repair, + bool & errors +) +try { checkInterrupt(); - if (!done.insert(path).second) return; + if (!done.insert(path).second) co_return result::success(); if (!storePathsInStoreDir.count(path)) { /* Check any referrers first. If we can invalidate them @@ -1669,7 +1678,7 @@ void LocalStore::verifyPath(const StorePath & path, const StorePathSet & storePa printError("path '%s' disappeared, but it still has valid referrers!", pathS); if (repair) try { - RUN_ASYNC_IN_NEW_THREAD(repairPath(path)); + TRY_AWAIT(repairPath(path)); } catch (Error & e) { logWarning(e.info()); errors = true; @@ -1677,10 +1686,13 @@ void LocalStore::verifyPath(const StorePath & path, const StorePathSet & storePa else errors = true; } - return; + co_return result::success(); } validPaths.insert(std::move(path)); + co_return result::success(); +} catch (...) { + co_return result::current_exception(); } diff --git a/lix/libstore/local-store.hh b/lix/libstore/local-store.hh index 534036ac9..79bb3b3ec 100644 --- a/lix/libstore/local-store.hh +++ b/lix/libstore/local-store.hh @@ -273,7 +273,7 @@ public: */ void optimisePath(const Path & path, RepairFlag repair); - bool verifyStore(bool checkContents, RepairFlag repair) override; + kj::Promise> verifyStore(bool checkContents, RepairFlag repair) override; /** * Register the validity of a path, i.e., that `path` exists, that @@ -340,7 +340,7 @@ private: */ void invalidatePathChecked(const StorePath & path); - void verifyPath(const StorePath & path, const StorePathSet & store, + kj::Promise> verifyPath(const StorePath & path, const StorePathSet & store, StorePathSet & done, StorePathSet & validPaths, RepairFlag repair, bool & errors); std::shared_ptr queryPathInfoInternal(DBState & state, const StorePath & path); diff --git a/lix/libstore/remote-store.cc b/lix/libstore/remote-store.cc index f4a6913ee..7bf2d24d1 100644 --- a/lix/libstore/remote-store.cc +++ b/lix/libstore/remote-store.cc @@ -795,12 +795,14 @@ void RemoteStore::optimiseStore() } -bool RemoteStore::verifyStore(bool checkContents, RepairFlag repair) -{ +kj::Promise> RemoteStore::verifyStore(bool checkContents, RepairFlag repair) +try { auto conn(getConnection()); conn->to << WorkerProto::Op::VerifyStore << checkContents << repair; conn.processStderr(); - return readInt(conn->from); + return {readInt(conn->from)}; +} catch (...) { + return {result::current_exception()}; } diff --git a/lix/libstore/remote-store.hh b/lix/libstore/remote-store.hh index f878504a5..49001a034 100644 --- a/lix/libstore/remote-store.hh +++ b/lix/libstore/remote-store.hh @@ -137,7 +137,7 @@ public: void optimiseStore() override; - bool verifyStore(bool checkContents, RepairFlag repair) override; + kj::Promise> verifyStore(bool checkContents, RepairFlag repair) override; /** * The default instance would schedule the work on the client side, but diff --git a/lix/libstore/store-api.hh b/lix/libstore/store-api.hh index 7957d00a0..f4710747b 100644 --- a/lix/libstore/store-api.hh +++ b/lix/libstore/store-api.hh @@ -706,7 +706,10 @@ public: * * @return true if errors remain. */ - virtual bool verifyStore(bool checkContents, RepairFlag repair = NoRepair) { return false; }; + virtual kj::Promise> verifyStore(bool checkContents, RepairFlag repair = NoRepair) + { + return {false}; + } /** * @return An object to access files in the Nix store.