aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/remote-store.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstore/remote-store.cc')
-rw-r--r--src/libstore/remote-store.cc199
1 files changed, 168 insertions, 31 deletions
diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc
index e7ffa6595..96a29155c 100644
--- a/src/libstore/remote-store.cc
+++ b/src/libstore/remote-store.cc
@@ -1,7 +1,9 @@
#include "serialise.hh"
#include "util.hh"
#include "path-with-outputs.hh"
+#include "gc-store.hh"
#include "remote-fs-accessor.hh"
+#include "build-result.hh"
#include "remote-store.hh"
#include "worker-protocol.hh"
#include "archive.hh"
@@ -89,6 +91,35 @@ void write(const Store & store, Sink & out, const DrvOutput & drvOutput)
}
+BuildResult read(const Store & store, Source & from, Phantom<BuildResult> _)
+{
+ auto path = worker_proto::read(store, from, Phantom<DerivedPath> {});
+ BuildResult res { .path = path };
+ res.status = (BuildResult::Status) readInt(from);
+ from
+ >> res.errorMsg
+ >> res.timesBuilt
+ >> res.isNonDeterministic
+ >> res.startTime
+ >> res.stopTime;
+ res.builtOutputs = worker_proto::read(store, from, Phantom<DrvOutputs> {});
+ return res;
+}
+
+void write(const Store & store, Sink & to, const BuildResult & res)
+{
+ worker_proto::write(store, to, res.path);
+ to
+ << res.status
+ << res.errorMsg
+ << res.timesBuilt
+ << res.isNonDeterministic
+ << res.startTime
+ << res.stopTime;
+ worker_proto::write(store, to, res.builtOutputs);
+}
+
+
std::optional<StorePath> read(const Store & store, Source & from, Phantom<std::optional<StorePath>> _)
{
auto s = readString(from);
@@ -549,7 +580,6 @@ ref<const ValidPathInfo> RemoteStore::addCAToStore(
try {
conn->to.written = 0;
- conn->to.warn = true;
connections->incCapacity();
{
Finally cleanup([&]() { connections->decCapacity(); });
@@ -560,7 +590,6 @@ ref<const ValidPathInfo> RemoteStore::addCAToStore(
dumpString(contents, conn->to);
}
}
- conn->to.warn = false;
conn.processStderr();
} catch (SysError & e) {
/* Daemon closed while we were sending the path. Probably OOM
@@ -643,6 +672,23 @@ void RemoteStore::addToStore(const ValidPathInfo & info, Source & source,
void RemoteStore::addMultipleToStore(
+ PathsSource & pathsToCopy,
+ Activity & act,
+ RepairFlag repair,
+ CheckSigsFlag checkSigs)
+{
+ auto source = sinkToSource([&](Sink & sink) {
+ sink << pathsToCopy.size();
+ for (auto & [pathInfo, pathSource] : pathsToCopy) {
+ pathInfo.write(sink, *this, 16);
+ pathSource->drainInto(sink);
+ }
+ });
+
+ addMultipleToStore(*source, repair, checkSigs);
+}
+
+void RemoteStore::addMultipleToStore(
Source & source,
RepairFlag repair,
CheckSigsFlag checkSigs)
@@ -687,36 +733,34 @@ void RemoteStore::registerDrvOutput(const Realisation & info)
void RemoteStore::queryRealisationUncached(const DrvOutput & id,
Callback<std::shared_ptr<const Realisation>> callback) noexcept
{
- auto conn(getConnection());
+ try {
+ auto conn(getConnection());
- if (GET_PROTOCOL_MINOR(conn->daemonVersion) < 27) {
- warn("the daemon is too old to support content-addressed derivations, please upgrade it to 2.4");
- try {
- callback(nullptr);
- } catch (...) { return callback.rethrow(); }
- }
+ if (GET_PROTOCOL_MINOR(conn->daemonVersion) < 27) {
+ warn("the daemon is too old to support content-addressed derivations, please upgrade it to 2.4");
+ return callback(nullptr);
+ }
- conn->to << wopQueryRealisation;
- conn->to << id.to_string();
- conn.processStderr();
+ conn->to << wopQueryRealisation;
+ conn->to << id.to_string();
+ conn.processStderr();
- auto real = [&]() -> std::shared_ptr<const Realisation> {
- if (GET_PROTOCOL_MINOR(conn->daemonVersion) < 31) {
- auto outPaths = worker_proto::read(
- *this, conn->from, Phantom<std::set<StorePath>> {});
- if (outPaths.empty())
- return nullptr;
- return std::make_shared<const Realisation>(Realisation { .id = id, .outPath = *outPaths.begin() });
- } else {
- auto realisations = worker_proto::read(
- *this, conn->from, Phantom<std::set<Realisation>> {});
- if (realisations.empty())
- return nullptr;
- return std::make_shared<const Realisation>(*realisations.begin());
- }
- }();
+ auto real = [&]() -> std::shared_ptr<const Realisation> {
+ if (GET_PROTOCOL_MINOR(conn->daemonVersion) < 31) {
+ auto outPaths = worker_proto::read(
+ *this, conn->from, Phantom<std::set<StorePath>> {});
+ if (outPaths.empty())
+ return nullptr;
+ return std::make_shared<const Realisation>(Realisation { .id = id, .outPath = *outPaths.begin() });
+ } else {
+ auto realisations = worker_proto::read(
+ *this, conn->from, Phantom<std::set<Realisation>> {});
+ if (realisations.empty())
+ return nullptr;
+ return std::make_shared<const Realisation>(*realisations.begin());
+ }
+ }();
- try {
callback(std::shared_ptr<const Realisation>(real));
} catch (...) { return callback.rethrow(); }
}
@@ -745,17 +789,24 @@ static void writeDerivedPaths(RemoteStore & store, ConnectionHandle & conn, cons
}
}
-void RemoteStore::buildPaths(const std::vector<DerivedPath> & drvPaths, BuildMode buildMode, std::shared_ptr<Store> evalStore)
+void RemoteStore::copyDrvsFromEvalStore(
+ const std::vector<DerivedPath> & paths,
+ std::shared_ptr<Store> evalStore)
{
if (evalStore && evalStore.get() != this) {
/* The remote doesn't have a way to access evalStore, so copy
the .drvs. */
RealisedPath::Set drvPaths2;
- for (auto & i : drvPaths)
+ for (auto & i : paths)
if (auto p = std::get_if<DerivedPath::Built>(&i))
drvPaths2.insert(p->drvPath);
copyClosure(*evalStore, *this, drvPaths2);
}
+}
+
+void RemoteStore::buildPaths(const std::vector<DerivedPath> & drvPaths, BuildMode buildMode, std::shared_ptr<Store> evalStore)
+{
+ copyDrvsFromEvalStore(drvPaths, evalStore);
auto conn(getConnection());
conn->to << wopBuildPaths;
@@ -772,6 +823,92 @@ void RemoteStore::buildPaths(const std::vector<DerivedPath> & drvPaths, BuildMod
readInt(conn->from);
}
+std::vector<BuildResult> RemoteStore::buildPathsWithResults(
+ const std::vector<DerivedPath> & paths,
+ BuildMode buildMode,
+ std::shared_ptr<Store> evalStore)
+{
+ copyDrvsFromEvalStore(paths, evalStore);
+
+ std::optional<ConnectionHandle> conn_(getConnection());
+ auto & conn = *conn_;
+
+ if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 34) {
+ conn->to << wopBuildPathsWithResults;
+ writeDerivedPaths(*this, conn, paths);
+ conn->to << buildMode;
+ conn.processStderr();
+ return worker_proto::read(*this, conn->from, Phantom<std::vector<BuildResult>> {});
+ } else {
+ // Avoid deadlock.
+ conn_.reset();
+
+ // Note: this throws an exception if a build/substitution
+ // fails, but meh.
+ buildPaths(paths, buildMode, evalStore);
+
+ std::vector<BuildResult> results;
+
+ for (auto & path : paths) {
+ std::visit(
+ overloaded {
+ [&](const DerivedPath::Opaque & bo) {
+ results.push_back(BuildResult {
+ .status = BuildResult::Substituted,
+ .path = bo,
+ });
+ },
+ [&](const DerivedPath::Built & bfd) {
+ BuildResult res {
+ .status = BuildResult::Built,
+ .path = bfd,
+ };
+
+ OutputPathMap outputs;
+ auto drv = evalStore->readDerivation(bfd.drvPath);
+ const auto outputHashes = staticOutputHashes(*evalStore, drv); // FIXME: expensive
+ const auto drvOutputs = drv.outputsAndOptPaths(*this);
+ for (auto & output : bfd.outputs) {
+ auto outputHash = get(outputHashes, output);
+ if (!outputHash)
+ throw Error(
+ "the derivation '%s' doesn't have an output named '%s'",
+ printStorePath(bfd.drvPath), output);
+ auto outputId = DrvOutput{ *outputHash, output };
+ if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations)) {
+ auto realisation =
+ queryRealisation(outputId);
+ if (!realisation)
+ throw Error(
+ "cannot operate on an output of unbuilt "
+ "content-addressed derivation '%s'",
+ outputId.to_string());
+ res.builtOutputs.emplace(realisation->id, *realisation);
+ } else {
+ // If ca-derivations isn't enabled, assume that
+ // the output path is statically known.
+ const auto drvOutput = get(drvOutputs, output);
+ assert(drvOutput);
+ assert(drvOutput->second);
+ res.builtOutputs.emplace(
+ outputId,
+ Realisation {
+ .id = outputId,
+ .outPath = *drvOutput->second,
+ });
+ }
+ }
+
+ results.push_back(res);
+ }
+ },
+ path.raw());
+ }
+
+ return results;
+ }
+}
+
BuildResult RemoteStore::buildDerivation(const StorePath & drvPath, const BasicDerivation & drv,
BuildMode buildMode)
@@ -781,7 +918,7 @@ BuildResult RemoteStore::buildDerivation(const StorePath & drvPath, const BasicD
writeDerivation(conn->to, *this, drv);
conn->to << buildMode;
conn.processStderr();
- BuildResult res;
+ BuildResult res { .path = DerivedPath::Built { .drvPath = drvPath } };
res.status = (BuildResult::Status) readInt(conn->from);
conn->from >> res.errorMsg;
if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 29) {