libstore: asyncify Store::registerDrvOutput
Change-Id: Ib8ba14ba2ce210714181dbb85ca8a42480a32c55
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -502,11 +502,15 @@ std::shared_ptr<const Realisation> BinaryCacheStore::queryRealisationUncached(co
|
||||
return std::make_shared<const Realisation>(realisation);
|
||||
}
|
||||
|
||||
void BinaryCacheStore::registerDrvOutput(const Realisation& info) {
|
||||
kj::Promise<Result<void>> 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<FSAccessor> BinaryCacheStore::getFSAccessor()
|
||||
|
||||
@@ -144,7 +144,7 @@ public:
|
||||
const StorePathSet & references,
|
||||
RepairFlag repair) override;
|
||||
|
||||
void registerDrvOutput(const Realisation & info) override;
|
||||
kj::Promise<Result<void>> registerDrvOutput(const Realisation & info) override;
|
||||
|
||||
std::shared_ptr<const Realisation> queryRealisationUncached(const DrvOutput &) override;
|
||||
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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<Result<Goal::WorkResult>> DrvOutputSubstitutionGoal::finished() noexcept
|
||||
|
||||
@@ -1151,10 +1151,10 @@ struct RestrictedStore : public virtual IndirectRootStore, public virtual GcStor
|
||||
return {result::current_exception()};
|
||||
}
|
||||
|
||||
void registerDrvOutput(const Realisation & info) override
|
||||
kj::Promise<Result<void>> 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<const Realisation> 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);
|
||||
}
|
||||
|
||||
@@ -956,11 +956,11 @@ static void performOp(AsyncIoRoot & aio, TunnelLogger * logger, ref<Store> 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<Realisation>::read(*store, rconn);
|
||||
store->registerDrvOutput(realisation);
|
||||
aio.blockOn(store->registerDrvOutput(realisation));
|
||||
}
|
||||
logger->stopWork();
|
||||
break;
|
||||
|
||||
+62
-49
@@ -772,67 +772,80 @@ void canonicalisePathMetaData(const Path & path,
|
||||
}
|
||||
|
||||
|
||||
void LocalStore::registerDrvOutput(const Realisation & info, CheckSigsFlag checkSigs)
|
||||
{
|
||||
kj::Promise<Result<void>>
|
||||
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<Result<void>> 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<Result<void>> {
|
||||
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(
|
||||
|
||||
@@ -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<Result<void>> registerDrvOutput(const Realisation & info) override;
|
||||
kj::Promise<Result<void>>
|
||||
registerDrvOutput(const Realisation & info, CheckSigsFlag checkSigs) override;
|
||||
void cacheDrvOutputMapping(
|
||||
DBState & state,
|
||||
const uint64_t deriver,
|
||||
|
||||
@@ -600,8 +600,8 @@ try {
|
||||
co_return result::current_exception();
|
||||
}
|
||||
|
||||
void RemoteStore::registerDrvOutput(const Realisation & info)
|
||||
{
|
||||
kj::Promise<Result<void>> 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<const Realisation> RemoteStore::queryRealisationUncached(const DrvOutput & id)
|
||||
|
||||
@@ -112,7 +112,7 @@ public:
|
||||
const StorePathSet & references,
|
||||
RepairFlag repair) override;
|
||||
|
||||
void registerDrvOutput(const Realisation & info) override;
|
||||
kj::Promise<Result<void>> registerDrvOutput(const Realisation & info) override;
|
||||
|
||||
std::shared_ptr<const Realisation> queryRealisationUncached(const DrvOutput &) override;
|
||||
|
||||
|
||||
@@ -1155,7 +1155,7 @@ try {
|
||||
processGraph<Realisation>(
|
||||
"copyPaths pool",
|
||||
TRY_AWAIT(Realisation::closure(srcStore, toplevelRealisations)),
|
||||
[&](const Realisation & current) -> std::set<Realisation> {
|
||||
[&](AsyncIoRoot & aio, const Realisation & current) -> std::set<Realisation> {
|
||||
std::set<Realisation> 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
|
||||
|
||||
@@ -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<Result<void>> registerDrvOutput(const Realisation & output)
|
||||
try { unsupported("registerDrvOutput"); } catch (...) { return {result::current_exception()}; }
|
||||
virtual kj::Promise<Result<void>>
|
||||
registerDrvOutput(const Realisation & output, CheckSigsFlag checkSigs)
|
||||
{
|
||||
return registerDrvOutput(output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a NAR dump of a store path.
|
||||
|
||||
Reference in New Issue
Block a user