1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-15 06:52:43 +01:00
nix/src/libstore/worker-protocol.cc
Graham Christensen e4f62e4608 Apply clang-format universally.
* It is tough to contribute to a project that doesn't use a formatter,
* It is extra hard to contribute to a project which has configured the formatter, but ignores it for some files
* Code formatting makes it harder to hide obscure / weird bugs by accident or on purpose,

Let's rip the bandaid off?

Note that PRs currently in flight should be able to be merged relatively easily by applying `clang-format` to their tip prior to merge.
2025-07-18 12:47:27 -04:00

281 lines
9.5 KiB
C++

#include "nix/util/serialise.hh"
#include "nix/store/path-with-outputs.hh"
#include "nix/store/store-api.hh"
#include "nix/store/build-result.hh"
#include "nix/store/worker-protocol.hh"
#include "nix/store/worker-protocol-impl.hh"
#include "nix/util/archive.hh"
#include "nix/store/path-info.hh"
#include <chrono>
#include <nlohmann/json.hpp>
namespace nix {
/* protocol-specific definitions */
BuildMode WorkerProto::Serialise<BuildMode>::read(const StoreDirConfig & store, WorkerProto::ReadConn conn)
{
auto temp = readNum<uint8_t>(conn.from);
switch (temp) {
case 0:
return bmNormal;
case 1:
return bmRepair;
case 2:
return bmCheck;
default:
throw Error("Invalid build mode");
}
}
void WorkerProto::Serialise<BuildMode>::write(
const StoreDirConfig & store, WorkerProto::WriteConn conn, const BuildMode & buildMode)
{
switch (buildMode) {
case bmNormal:
conn.to << uint8_t{0};
break;
case bmRepair:
conn.to << uint8_t{1};
break;
case bmCheck:
conn.to << uint8_t{2};
break;
default:
assert(false);
};
}
std::optional<TrustedFlag>
WorkerProto::Serialise<std::optional<TrustedFlag>>::read(const StoreDirConfig & store, WorkerProto::ReadConn conn)
{
auto temp = readNum<uint8_t>(conn.from);
switch (temp) {
case 0:
return std::nullopt;
case 1:
return {Trusted};
case 2:
return {NotTrusted};
default:
throw Error("Invalid trusted status from remote");
}
}
void WorkerProto::Serialise<std::optional<TrustedFlag>>::write(
const StoreDirConfig & store, WorkerProto::WriteConn conn, const std::optional<TrustedFlag> & optTrusted)
{
if (!optTrusted)
conn.to << uint8_t{0};
else {
switch (*optTrusted) {
case Trusted:
conn.to << uint8_t{1};
break;
case NotTrusted:
conn.to << uint8_t{2};
break;
default:
assert(false);
};
}
}
std::optional<std::chrono::microseconds> WorkerProto::Serialise<std::optional<std::chrono::microseconds>>::read(
const StoreDirConfig & store, WorkerProto::ReadConn conn)
{
auto tag = readNum<uint8_t>(conn.from);
switch (tag) {
case 0:
return std::nullopt;
case 1:
return std::optional<std::chrono::microseconds>{std::chrono::microseconds(readNum<int64_t>(conn.from))};
default:
throw Error("Invalid optional tag from remote");
}
}
void WorkerProto::Serialise<std::optional<std::chrono::microseconds>>::write(
const StoreDirConfig & store,
WorkerProto::WriteConn conn,
const std::optional<std::chrono::microseconds> & optDuration)
{
if (!optDuration.has_value()) {
conn.to << uint8_t{0};
} else {
conn.to << uint8_t{1} << optDuration.value().count();
}
}
DerivedPath WorkerProto::Serialise<DerivedPath>::read(const StoreDirConfig & store, WorkerProto::ReadConn conn)
{
auto s = readString(conn.from);
if (GET_PROTOCOL_MINOR(conn.version) >= 30) {
return DerivedPath::parseLegacy(store, s);
} else {
return parsePathWithOutputs(store, s).toDerivedPath();
}
}
void WorkerProto::Serialise<DerivedPath>::write(
const StoreDirConfig & store, WorkerProto::WriteConn conn, const DerivedPath & req)
{
if (GET_PROTOCOL_MINOR(conn.version) >= 30) {
conn.to << req.to_string_legacy(store);
} else {
auto sOrDrvPath = StorePathWithOutputs::tryFromDerivedPath(req);
std::visit(
overloaded{
[&](const StorePathWithOutputs & s) { conn.to << s.to_string(store); },
[&](const StorePath & drvPath) {
throw Error(
"trying to request '%s', but daemon protocol %d.%d is too old (< 1.29) to request a derivation file",
store.printStorePath(drvPath),
GET_PROTOCOL_MAJOR(conn.version),
GET_PROTOCOL_MINOR(conn.version));
},
[&](std::monostate) {
throw Error(
"wanted to build a derivation that is itself a build product, but protocols do not support that. Try upgrading the Nix on the other end of this connection");
},
},
sOrDrvPath);
}
}
KeyedBuildResult
WorkerProto::Serialise<KeyedBuildResult>::read(const StoreDirConfig & store, WorkerProto::ReadConn conn)
{
auto path = WorkerProto::Serialise<DerivedPath>::read(store, conn);
auto br = WorkerProto::Serialise<BuildResult>::read(store, conn);
return KeyedBuildResult{
std::move(br),
/* .path = */ std::move(path),
};
}
void WorkerProto::Serialise<KeyedBuildResult>::write(
const StoreDirConfig & store, WorkerProto::WriteConn conn, const KeyedBuildResult & res)
{
WorkerProto::write(store, conn, res.path);
WorkerProto::write(store, conn, static_cast<const BuildResult &>(res));
}
BuildResult WorkerProto::Serialise<BuildResult>::read(const StoreDirConfig & store, WorkerProto::ReadConn conn)
{
BuildResult res;
res.status = static_cast<BuildResult::Status>(readInt(conn.from));
conn.from >> res.errorMsg;
if (GET_PROTOCOL_MINOR(conn.version) >= 29) {
conn.from >> res.timesBuilt >> res.isNonDeterministic >> res.startTime >> res.stopTime;
}
if (GET_PROTOCOL_MINOR(conn.version) >= 37) {
res.cpuUser = WorkerProto::Serialise<std::optional<std::chrono::microseconds>>::read(store, conn);
res.cpuSystem = WorkerProto::Serialise<std::optional<std::chrono::microseconds>>::read(store, conn);
}
if (GET_PROTOCOL_MINOR(conn.version) >= 28) {
auto builtOutputs = WorkerProto::Serialise<DrvOutputs>::read(store, conn);
for (auto && [output, realisation] : builtOutputs)
res.builtOutputs.insert_or_assign(std::move(output.outputName), std::move(realisation));
}
return res;
}
void WorkerProto::Serialise<BuildResult>::write(
const StoreDirConfig & store, WorkerProto::WriteConn conn, const BuildResult & res)
{
conn.to << res.status << res.errorMsg;
if (GET_PROTOCOL_MINOR(conn.version) >= 29) {
conn.to << res.timesBuilt << res.isNonDeterministic << res.startTime << res.stopTime;
}
if (GET_PROTOCOL_MINOR(conn.version) >= 37) {
WorkerProto::write(store, conn, res.cpuUser);
WorkerProto::write(store, conn, res.cpuSystem);
}
if (GET_PROTOCOL_MINOR(conn.version) >= 28) {
DrvOutputs builtOutputs;
for (auto & [output, realisation] : res.builtOutputs)
builtOutputs.insert_or_assign(realisation.id, realisation);
WorkerProto::write(store, conn, builtOutputs);
}
}
ValidPathInfo WorkerProto::Serialise<ValidPathInfo>::read(const StoreDirConfig & store, ReadConn conn)
{
auto path = WorkerProto::Serialise<StorePath>::read(store, conn);
return ValidPathInfo{
std::move(path),
WorkerProto::Serialise<UnkeyedValidPathInfo>::read(store, conn),
};
}
void WorkerProto::Serialise<ValidPathInfo>::write(
const StoreDirConfig & store, WriteConn conn, const ValidPathInfo & pathInfo)
{
WorkerProto::write(store, conn, pathInfo.path);
WorkerProto::write(store, conn, static_cast<const UnkeyedValidPathInfo &>(pathInfo));
}
UnkeyedValidPathInfo WorkerProto::Serialise<UnkeyedValidPathInfo>::read(const StoreDirConfig & store, ReadConn conn)
{
auto deriver = readString(conn.from);
auto narHash = Hash::parseAny(readString(conn.from), HashAlgorithm::SHA256);
UnkeyedValidPathInfo info(narHash);
if (deriver != "")
info.deriver = store.parseStorePath(deriver);
info.references = WorkerProto::Serialise<StorePathSet>::read(store, conn);
conn.from >> info.registrationTime >> info.narSize;
if (GET_PROTOCOL_MINOR(conn.version) >= 16) {
conn.from >> info.ultimate;
info.sigs = readStrings<StringSet>(conn.from);
info.ca = ContentAddress::parseOpt(readString(conn.from));
}
return info;
}
void WorkerProto::Serialise<UnkeyedValidPathInfo>::write(
const StoreDirConfig & store, WriteConn conn, const UnkeyedValidPathInfo & pathInfo)
{
conn.to << (pathInfo.deriver ? store.printStorePath(*pathInfo.deriver) : "")
<< pathInfo.narHash.to_string(HashFormat::Base16, false);
WorkerProto::write(store, conn, pathInfo.references);
conn.to << pathInfo.registrationTime << pathInfo.narSize;
if (GET_PROTOCOL_MINOR(conn.version) >= 16) {
conn.to << pathInfo.ultimate << pathInfo.sigs << renderContentAddress(pathInfo.ca);
}
}
WorkerProto::ClientHandshakeInfo
WorkerProto::Serialise<WorkerProto::ClientHandshakeInfo>::read(const StoreDirConfig & store, ReadConn conn)
{
WorkerProto::ClientHandshakeInfo res;
if (GET_PROTOCOL_MINOR(conn.version) >= 33) {
res.daemonNixVersion = readString(conn.from);
}
if (GET_PROTOCOL_MINOR(conn.version) >= 35) {
res.remoteTrustsUs = WorkerProto::Serialise<std::optional<TrustedFlag>>::read(store, conn);
} else {
// We don't know the answer; protocol to old.
res.remoteTrustsUs = std::nullopt;
}
return res;
}
void WorkerProto::Serialise<WorkerProto::ClientHandshakeInfo>::write(
const StoreDirConfig & store, WriteConn conn, const WorkerProto::ClientHandshakeInfo & info)
{
if (GET_PROTOCOL_MINOR(conn.version) >= 33) {
assert(info.daemonNixVersion);
conn.to << *info.daemonNixVersion;
}
if (GET_PROTOCOL_MINOR(conn.version) >= 35) {
WorkerProto::write(store, conn, info.remoteTrustsUs);
}
}
} // namespace nix