diff --git a/lix/legacy/build-remote.cc b/lix/legacy/build-remote.cc index a022776a1..2e4b3d15f 100644 --- a/lix/legacy/build-remote.cc +++ b/lix/legacy/build-remote.cc @@ -387,7 +387,7 @@ connected: // Should hold, because if the feature isn't enabled the set // of missing realisations should be empty experimentalFeatureSettings.require(Xp::CaDerivations); - store->registerDrvOutput(realisation); + aio.blockOn(store->registerDrvOutput(realisation)); } return 0; diff --git a/lix/libstore/binary-cache-store.cc b/lix/libstore/binary-cache-store.cc index c16ce970a..5bbdd74ac 100644 --- a/lix/libstore/binary-cache-store.cc +++ b/lix/libstore/binary-cache-store.cc @@ -502,11 +502,15 @@ std::shared_ptr BinaryCacheStore::queryRealisationUncached(co return std::make_shared(realisation); } -void BinaryCacheStore::registerDrvOutput(const Realisation& info) { +kj::Promise> BinaryCacheStore::registerDrvOutput(const Realisation& info) +try { if (diskCache) diskCache->upsertRealisation(getUri(), info); auto filePath = realisationsPrefix + "/" + info.id.to_string() + ".doi"; upsertFile(filePath, info.toJSON().dump(), "application/json"); + co_return result::success(); +} catch (...) { + co_return result::current_exception(); } ref BinaryCacheStore::getFSAccessor() diff --git a/lix/libstore/binary-cache-store.hh b/lix/libstore/binary-cache-store.hh index efa0bbdd0..9da939b85 100644 --- a/lix/libstore/binary-cache-store.hh +++ b/lix/libstore/binary-cache-store.hh @@ -144,7 +144,7 @@ public: const StorePathSet & references, RepairFlag repair) override; - void registerDrvOutput(const Realisation & info) override; + kj::Promise> registerDrvOutput(const Realisation & info) override; std::shared_ptr queryRealisationUncached(const DrvOutput &) override; diff --git a/lix/libstore/build/derivation-goal.cc b/lix/libstore/build/derivation-goal.cc index fe6cadcf0..020f86725 100644 --- a/lix/libstore/build/derivation-goal.cc +++ b/lix/libstore/build/derivation-goal.cc @@ -1192,7 +1192,7 @@ try { ); } signRealisation(newRealisation); - worker.store.registerDrvOutput(newRealisation); + TRY_AWAIT(worker.store.registerDrvOutput(newRealisation)); } outputPaths.insert(realisation.outPath); builtOutputs.emplace(outputName, realisation); @@ -1691,12 +1691,12 @@ try { // derivation, and the output path is valid, but we don't have // its realisation stored (probably because it has been built // without the `ca-derivations` experimental flag). - worker.store.registerDrvOutput( + TRY_AWAIT(worker.store.registerDrvOutput( Realisation { drvOutput, info.known->path, } - ); + )); } } if (info.known && info.known->isValid()) diff --git a/lix/libstore/build/drv-output-substitution-goal.cc b/lix/libstore/build/drv-output-substitution-goal.cc index 2fd43d5bc..ad9fd1f90 100644 --- a/lix/libstore/build/drv-output-substitution-goal.cc +++ b/lix/libstore/build/drv-output-substitution-goal.cc @@ -141,15 +141,15 @@ try { if (nrFailed > 0) { debug("The output path of the derivation output '%s' could not be substituted", id.to_string()); - return {WorkResult{ + co_return WorkResult{ nrNoSubstituters > 0 || nrIncompleteClosure > 0 ? ecIncompleteClosure : ecFailed, - }}; + }; } - worker.store.registerDrvOutput(*outputInfo); - return finished(); + TRY_AWAIT(worker.store.registerDrvOutput(*outputInfo)); + co_return TRY_AWAIT(finished()); } catch (...) { - return {result::current_exception()}; + co_return result::current_exception(); } kj::Promise> DrvOutputSubstitutionGoal::finished() noexcept diff --git a/lix/libstore/build/local-derivation-goal.cc b/lix/libstore/build/local-derivation-goal.cc index 58b583ac1..d928efb60 100644 --- a/lix/libstore/build/local-derivation-goal.cc +++ b/lix/libstore/build/local-derivation-goal.cc @@ -1151,10 +1151,10 @@ struct RestrictedStore : public virtual IndirectRootStore, public virtual GcStor return {result::current_exception()}; } - void registerDrvOutput(const Realisation & info) override + kj::Promise> registerDrvOutput(const Realisation & info) override // XXX: This should probably be allowed as a no-op if the realisation // corresponds to an allowed derivation - { throw Error("registerDrvOutput"); } + try { throw Error("registerDrvOutput"); } catch (...) { return {result::current_exception()}; } std::shared_ptr queryRealisationUncached(const DrvOutput & id) override // XXX: This should probably be allowed if the realisation corresponds to @@ -2508,7 +2508,7 @@ try { && drv->type().isPure()) { signRealisation(thisRealisation); - worker.store.registerDrvOutput(thisRealisation); + TRY_AWAIT(worker.store.registerDrvOutput(thisRealisation)); } builtOutputs.emplace(outputName, thisRealisation); } diff --git a/lix/libstore/daemon.cc b/lix/libstore/daemon.cc index cbfa18912..adee7a528 100644 --- a/lix/libstore/daemon.cc +++ b/lix/libstore/daemon.cc @@ -956,11 +956,11 @@ static void performOp(AsyncIoRoot & aio, TunnelLogger * logger, ref store if (GET_PROTOCOL_MINOR(clientVersion) < 31) { auto outputId = DrvOutput::parse(readString(from)); auto outputPath = StorePath(readString(from)); - store->registerDrvOutput(Realisation{ - .id = outputId, .outPath = outputPath}); + aio.blockOn(store->registerDrvOutput(Realisation{ + .id = outputId, .outPath = outputPath})); } else { auto realisation = WorkerProto::Serialise::read(*store, rconn); - store->registerDrvOutput(realisation); + aio.blockOn(store->registerDrvOutput(realisation)); } logger->stopWork(); break; diff --git a/lix/libstore/local-store.cc b/lix/libstore/local-store.cc index eb8333c12..f005a0d08 100644 --- a/lix/libstore/local-store.cc +++ b/lix/libstore/local-store.cc @@ -772,67 +772,80 @@ void canonicalisePathMetaData(const Path & path, } -void LocalStore::registerDrvOutput(const Realisation & info, CheckSigsFlag checkSigs) -{ +kj::Promise> +LocalStore::registerDrvOutput(const Realisation & info, CheckSigsFlag checkSigs) +try { experimentalFeatureSettings.require(Xp::CaDerivations); if (checkSigs == NoCheckSigs || !realisationIsUntrusted(info)) - registerDrvOutput(info); + TRY_AWAIT(registerDrvOutput(info)); else throw Error("cannot register realisation '%s' because it lacks a signature by a trusted key", info.outPath.to_string()); + co_return result::success(); +} catch (...) { + co_return result::current_exception(); } -void LocalStore::registerDrvOutput(const Realisation & info) -{ +kj::Promise> LocalStore::registerDrvOutput(const Realisation & info) +try { experimentalFeatureSettings.require(Xp::CaDerivations); - retrySQLite([&]() { - auto state = dbPool.get(); - if (auto oldR = queryRealisation_(*state, info.id)) { - if (info.isCompatibleWith(*oldR)) { - auto combinedSignatures = oldR->signatures; - combinedSignatures.insert(info.signatures.begin(), - info.signatures.end()); - state->stmts->UpdateRealisedOutput.use() - (concatStringsSep(" ", combinedSignatures)) + // NOLINTNEXTLINE(cppcoreguidelines-avoid-capturing-lambda-coroutines) + TRY_AWAIT(retrySQLite([&]() -> kj::Promise> { + try { + auto state = dbPool.get(); + if (auto oldR = queryRealisation_(*state, info.id)) { + if (info.isCompatibleWith(*oldR)) { + auto combinedSignatures = oldR->signatures; + combinedSignatures.insert(info.signatures.begin(), + info.signatures.end()); + state->stmts->UpdateRealisedOutput.use() + (concatStringsSep(" ", combinedSignatures)) + (info.id.strHash()) + (info.id.outputName) + .exec(); + } else { + throw Error("Trying to register a realisation of '%s', but we already " + "have another one locally.\n" + "Local: %s\n" + "Remote: %s", + info.id.to_string(), + printStorePath(oldR->outPath), + printStorePath(info.outPath) + ); + } + } else { + state->stmts->RegisterRealisedOutput.use() (info.id.strHash()) (info.id.outputName) + (printStorePath(info.outPath)) + (concatStringsSep(" ", info.signatures)) .exec(); - } else { - throw Error("Trying to register a realisation of '%s', but we already " - "have another one locally.\n" - "Local: %s\n" - "Remote: %s", - info.id.to_string(), - printStorePath(oldR->outPath), - printStorePath(info.outPath) - ); } - } else { - state->stmts->RegisterRealisedOutput.use() - (info.id.strHash()) - (info.id.outputName) - (printStorePath(info.outPath)) - (concatStringsSep(" ", info.signatures)) - .exec(); + for (auto & [outputId, depPath] : info.dependentRealisations) { + auto localRealisation = queryRealisationCore_(*state, outputId); + if (!localRealisation) + throw Error("unable to register the derivation '%s' as it " + "depends on the non existent '%s'", + info.id.to_string(), outputId.to_string()); + if (localRealisation->second.outPath != depPath) + throw Error("unable to register the derivation '%s' as it " + "depends on a realisation of '%s' that doesn’t" + "match what we have locally", + info.id.to_string(), outputId.to_string()); + state->stmts->AddRealisationReference.use() + (info.id.strHash()) + (info.id.outputName) + (outputId.strHash()) + (outputId.outputName) + .exec(); + } + co_return result::success(); + } catch (...) { + co_return result::current_exception(); } - for (auto & [outputId, depPath] : info.dependentRealisations) { - auto localRealisation = queryRealisationCore_(*state, outputId); - if (!localRealisation) - throw Error("unable to register the derivation '%s' as it " - "depends on the non existent '%s'", - info.id.to_string(), outputId.to_string()); - if (localRealisation->second.outPath != depPath) - throw Error("unable to register the derivation '%s' as it " - "depends on a realisation of '%s' that doesn’t" - "match what we have locally", - info.id.to_string(), outputId.to_string()); - state->stmts->AddRealisationReference.use() - (info.id.strHash()) - (info.id.outputName) - (outputId.strHash()) - (outputId.outputName) - .exec(); - } - }, always_progresses); + })); + co_return result::success(); +} catch (...) { + co_return result::current_exception(); } void LocalStore::cacheDrvOutputMapping( diff --git a/lix/libstore/local-store.hh b/lix/libstore/local-store.hh index 0fd2e5037..711793ae7 100644 --- a/lix/libstore/local-store.hh +++ b/lix/libstore/local-store.hh @@ -317,8 +317,9 @@ public: * Register the store path 'output' as the output named 'outputName' of * derivation 'deriver'. */ - void registerDrvOutput(const Realisation & info) override; - void registerDrvOutput(const Realisation & info, CheckSigsFlag checkSigs) override; + kj::Promise> registerDrvOutput(const Realisation & info) override; + kj::Promise> + registerDrvOutput(const Realisation & info, CheckSigsFlag checkSigs) override; void cacheDrvOutputMapping( DBState & state, const uint64_t deriver, diff --git a/lix/libstore/remote-store.cc b/lix/libstore/remote-store.cc index 653b78f7d..5fa0c2418 100644 --- a/lix/libstore/remote-store.cc +++ b/lix/libstore/remote-store.cc @@ -600,8 +600,8 @@ try { co_return result::current_exception(); } -void RemoteStore::registerDrvOutput(const Realisation & info) -{ +kj::Promise> RemoteStore::registerDrvOutput(const Realisation & info) +try { auto conn(getConnection()); conn->to << WorkerProto::Op::RegisterDrvOutput; if (GET_PROTOCOL_MINOR(conn->daemonVersion) < 31) { @@ -612,6 +612,9 @@ void RemoteStore::registerDrvOutput(const Realisation & info) conn->to << WorkerProto::write(*this, *conn, info); } conn.processStderr(); + co_return result::success(); +} catch (...) { + co_return result::current_exception(); } std::shared_ptr RemoteStore::queryRealisationUncached(const DrvOutput & id) diff --git a/lix/libstore/remote-store.hh b/lix/libstore/remote-store.hh index a78ece886..b672e0e36 100644 --- a/lix/libstore/remote-store.hh +++ b/lix/libstore/remote-store.hh @@ -112,7 +112,7 @@ public: const StorePathSet & references, RepairFlag repair) override; - void registerDrvOutput(const Realisation & info) override; + kj::Promise> registerDrvOutput(const Realisation & info) override; std::shared_ptr queryRealisationUncached(const DrvOutput &) override; diff --git a/lix/libstore/store-api.cc b/lix/libstore/store-api.cc index 4fc1ada0e..bac4a5158 100644 --- a/lix/libstore/store-api.cc +++ b/lix/libstore/store-api.cc @@ -1155,7 +1155,7 @@ try { processGraph( "copyPaths pool", TRY_AWAIT(Realisation::closure(srcStore, toplevelRealisations)), - [&](const Realisation & current) -> std::set { + [&](AsyncIoRoot & aio, const Realisation & current) -> std::set { std::set children; for (const auto & [drvOutput, _] : current.dependentRealisations) { auto currentChild = srcStore.queryRealisation(drvOutput); @@ -1168,8 +1168,8 @@ try { } return children; }, - [&](const Realisation& current) -> void { - dstStore.registerDrvOutput(current, checkSigs); + [&](AsyncIoRoot & aio, const Realisation& current) -> void { + aio.blockOn(dstStore.registerDrvOutput(current, checkSigs)); }); } catch (MissingExperimentalFeature & e) { // Don't fail if the remote doesn't support CA derivations is it might diff --git a/lix/libstore/store-api.hh b/lix/libstore/store-api.hh index 104e9219a..416b0bc79 100644 --- a/lix/libstore/store-api.hh +++ b/lix/libstore/store-api.hh @@ -589,10 +589,13 @@ public: * floating-ca derivations and their dependencies as there's no way to * retrieve this information otherwise. */ - virtual void registerDrvOutput(const Realisation & output) - { unsupported("registerDrvOutput"); } - virtual void registerDrvOutput(const Realisation & output, CheckSigsFlag checkSigs) - { return registerDrvOutput(output); } + virtual kj::Promise> registerDrvOutput(const Realisation & output) + try { unsupported("registerDrvOutput"); } catch (...) { return {result::current_exception()}; } + virtual kj::Promise> + registerDrvOutput(const Realisation & output, CheckSigsFlag checkSigs) + { + return registerDrvOutput(output); + } /** * Generate a NAR dump of a store path.