forked from lix-project/hydra
Factor more stuff out
This commit is contained in:
parent
2f494b7834
commit
9f1b911625
|
@ -188,6 +188,87 @@ std::pair<Path, AutoCloseFD> openLogFile(const std::string & logDir, const Store
|
||||||
return {std::move(logFile), std::move(logFD)};
|
return {std::move(logFile), std::move(logFD)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handshake(Machine::Connection & conn, unsigned int repeats)
|
||||||
|
{
|
||||||
|
conn.to << SERVE_MAGIC_1 << 0x204;
|
||||||
|
conn.to.flush();
|
||||||
|
|
||||||
|
unsigned int magic = readInt(conn.from);
|
||||||
|
if (magic != SERVE_MAGIC_2)
|
||||||
|
throw Error("protocol mismatch with ‘nix-store --serve’ on ‘%1%’", conn.machine->sshName);
|
||||||
|
conn.remoteVersion = readInt(conn.from);
|
||||||
|
if (GET_PROTOCOL_MAJOR(conn.remoteVersion) != 0x200)
|
||||||
|
throw Error("unsupported ‘nix-store --serve’ protocol version on ‘%1%’", conn.machine->sshName);
|
||||||
|
if (GET_PROTOCOL_MINOR(conn.remoteVersion) < 3 && repeats > 0)
|
||||||
|
throw Error("machine ‘%1%’ does not support repeating a build; please upgrade it to Nix 1.12", conn.machine->sshName);
|
||||||
|
}
|
||||||
|
|
||||||
|
StorePathSet sendInputs(
|
||||||
|
State & state,
|
||||||
|
Step & step,
|
||||||
|
Store & localStore,
|
||||||
|
Store & destStore,
|
||||||
|
Machine::Connection & conn,
|
||||||
|
unsigned int & overhead,
|
||||||
|
counter & nrStepsWaiting,
|
||||||
|
counter & nrStepsCopyingTo
|
||||||
|
)
|
||||||
|
{
|
||||||
|
|
||||||
|
StorePathSet inputs;
|
||||||
|
BasicDerivation basicDrv(*step.drv);
|
||||||
|
|
||||||
|
for (auto & p : step.drv->inputSrcs)
|
||||||
|
inputs.insert(p);
|
||||||
|
|
||||||
|
for (auto & input : step.drv->inputDrvs) {
|
||||||
|
auto drv2 = localStore.readDerivation(input.first);
|
||||||
|
for (auto & name : input.second) {
|
||||||
|
if (auto i = get(drv2.outputs, name)) {
|
||||||
|
auto outPath = i->path(localStore, drv2.name, name);
|
||||||
|
inputs.insert(*outPath);
|
||||||
|
basicDrv.inputSrcs.insert(*outPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure that the inputs exist in the destination store. This is
|
||||||
|
a no-op for regular stores, but for the binary cache store,
|
||||||
|
this will copy the inputs to the binary cache from the local
|
||||||
|
store. */
|
||||||
|
if (localStore.getUri() != destStore.getUri()) {
|
||||||
|
StorePathSet closure;
|
||||||
|
localStore.computeFSClosure(step.drv->inputSrcs, closure);
|
||||||
|
copyPaths(localStore, destStore, closure, NoRepair, NoCheckSigs, NoSubstitute);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto mc1 = std::make_shared<MaintainCount<counter>>(nrStepsWaiting);
|
||||||
|
mc1.reset();
|
||||||
|
MaintainCount<counter> mc2(nrStepsCopyingTo);
|
||||||
|
|
||||||
|
printMsg(lvlDebug, "sending closure of ‘%s’ to ‘%s’",
|
||||||
|
localStore.printStorePath(step.drvPath), conn.machine->sshName);
|
||||||
|
|
||||||
|
auto now1 = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
/* Copy the input closure. */
|
||||||
|
if (conn.machine->isLocalhost()) {
|
||||||
|
StorePathSet closure;
|
||||||
|
destStore.computeFSClosure(inputs, closure);
|
||||||
|
copyPaths(destStore, localStore, closure, NoRepair, NoCheckSigs, NoSubstitute);
|
||||||
|
} else {
|
||||||
|
copyClosureTo(conn.machine->state->sendLock, destStore, conn.from, conn.to, inputs, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto now2 = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
overhead += std::chrono::duration_cast<std::chrono::milliseconds>(now2 - now1).count();
|
||||||
|
}
|
||||||
|
|
||||||
|
return inputs;
|
||||||
|
}
|
||||||
|
|
||||||
void State::buildRemote(ref<Store> destStore,
|
void State::buildRemote(ref<Store> destStore,
|
||||||
Machine::ptr machine, Step::ptr step,
|
Machine::ptr machine, Step::ptr step,
|
||||||
unsigned int maxSilentTime, unsigned int buildTimeout, unsigned int repeats,
|
unsigned int maxSilentTime, unsigned int buildTimeout, unsigned int repeats,
|
||||||
|
@ -230,33 +311,21 @@ void State::buildRemote(ref<Store> destStore,
|
||||||
process. Meh. */
|
process. Meh. */
|
||||||
});
|
});
|
||||||
|
|
||||||
FdSource from(child.from.get());
|
Machine::Connection conn;
|
||||||
FdSink to(child.to.get());
|
conn.from = child.from.get();
|
||||||
|
conn.to = child.to.get();
|
||||||
|
conn.machine = machine;
|
||||||
|
|
||||||
Finally updateStats([&]() {
|
Finally updateStats([&]() {
|
||||||
bytesReceived += from.read;
|
bytesReceived += conn.from.read;
|
||||||
bytesSent += to.written;
|
bytesSent += conn.to.written;
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Handshake. */
|
|
||||||
unsigned int remoteVersion;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
to << SERVE_MAGIC_1 << 0x204;
|
handshake(conn, repeats);
|
||||||
to.flush();
|
|
||||||
|
|
||||||
unsigned int magic = readInt(from);
|
|
||||||
if (magic != SERVE_MAGIC_2)
|
|
||||||
throw Error("protocol mismatch with ‘nix-store --serve’ on ‘%1%’", machine->sshName);
|
|
||||||
remoteVersion = readInt(from);
|
|
||||||
if (GET_PROTOCOL_MAJOR(remoteVersion) != 0x200)
|
|
||||||
throw Error("unsupported ‘nix-store --serve’ protocol version on ‘%1%’", machine->sshName);
|
|
||||||
if (GET_PROTOCOL_MINOR(remoteVersion) < 3 && repeats > 0)
|
|
||||||
throw Error("machine ‘%1%’ does not support repeating a build; please upgrade it to Nix 1.12", machine->sshName);
|
|
||||||
|
|
||||||
} catch (EndOfFile & e) {
|
} catch (EndOfFile & e) {
|
||||||
child.pid.wait();
|
child.pid.wait();
|
||||||
string s = chomp(readFile(result.logFile));
|
std::string s = chomp(readFile(result.logFile));
|
||||||
throw Error("cannot connect to ‘%1%’: %2%", machine->sshName, s);
|
throw Error("cannot connect to ‘%1%’: %2%", machine->sshName, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,61 +341,12 @@ void State::buildRemote(ref<Store> destStore,
|
||||||
outputs of the input derivations. */
|
outputs of the input derivations. */
|
||||||
updateStep(ssSendingInputs);
|
updateStep(ssSendingInputs);
|
||||||
|
|
||||||
StorePathSet inputs;
|
StorePathSet inputs = sendInputs(*this, *step, *localStore, *destStore, conn, result.overhead, nrStepsWaiting, nrStepsCopyingTo);
|
||||||
BasicDerivation basicDrv(*step->drv);
|
|
||||||
|
|
||||||
for (auto & p : step->drv->inputSrcs)
|
|
||||||
inputs.insert(p);
|
|
||||||
|
|
||||||
for (auto & input : step->drv->inputDrvs) {
|
|
||||||
auto drv2 = localStore->readDerivation(input.first);
|
|
||||||
for (auto & name : input.second) {
|
|
||||||
if (auto i = get(drv2.outputs, name)) {
|
|
||||||
auto outPath = i->path(*localStore, drv2.name, name);
|
|
||||||
inputs.insert(*outPath);
|
|
||||||
basicDrv.inputSrcs.insert(*outPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ensure that the inputs exist in the destination store. This is
|
|
||||||
a no-op for regular stores, but for the binary cache store,
|
|
||||||
this will copy the inputs to the binary cache from the local
|
|
||||||
store. */
|
|
||||||
if (localStore != std::shared_ptr<Store>(destStore)) {
|
|
||||||
StorePathSet closure;
|
|
||||||
localStore->computeFSClosure(step->drv->inputSrcs, closure);
|
|
||||||
copyPaths(*localStore, *destStore, closure, NoRepair, NoCheckSigs, NoSubstitute);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
auto mc1 = std::make_shared<MaintainCount<counter>>(nrStepsWaiting);
|
|
||||||
mc1.reset();
|
|
||||||
MaintainCount<counter> mc2(nrStepsCopyingTo);
|
|
||||||
|
|
||||||
printMsg(lvlDebug, "sending closure of ‘%s’ to ‘%s’",
|
|
||||||
localStore->printStorePath(step->drvPath), machine->sshName);
|
|
||||||
|
|
||||||
auto now1 = std::chrono::steady_clock::now();
|
|
||||||
|
|
||||||
/* Copy the input closure. */
|
|
||||||
if (machine->isLocalhost()) {
|
|
||||||
StorePathSet closure;
|
|
||||||
destStore->computeFSClosure(inputs, closure);
|
|
||||||
copyPaths(*destStore, *localStore, closure, NoRepair, NoCheckSigs, NoSubstitute);
|
|
||||||
} else {
|
|
||||||
copyClosureTo(machine->state->sendLock, *destStore, from, to, inputs, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto now2 = std::chrono::steady_clock::now();
|
|
||||||
|
|
||||||
result.overhead += std::chrono::duration_cast<std::chrono::milliseconds>(now2 - now1).count();
|
|
||||||
}
|
|
||||||
|
|
||||||
logFileDel.cancel();
|
logFileDel.cancel();
|
||||||
|
|
||||||
/* Truncate the log to get rid of messages about substitutions
|
/* Truncate the log to get rid of messages about substitutions
|
||||||
etc. on the remote system. */
|
etc. on the remote system. */
|
||||||
if (lseek(logFD.get(), SEEK_SET, 0) != 0)
|
if (lseek(logFD.get(), SEEK_SET, 0) != 0)
|
||||||
throw SysError("seeking to the start of log file ‘%s’", result.logFile);
|
throw SysError("seeking to the start of log file ‘%s’", result.logFile);
|
||||||
|
|
||||||
|
@ -342,31 +362,31 @@ void State::buildRemote(ref<Store> destStore,
|
||||||
|
|
||||||
updateStep(ssBuilding);
|
updateStep(ssBuilding);
|
||||||
|
|
||||||
to << cmdBuildDerivation << localStore->printStorePath(step->drvPath);
|
conn.to << cmdBuildDerivation << localStore->printStorePath(step->drvPath);
|
||||||
writeDerivation(to, *localStore, basicDrv);
|
writeDerivation(conn.to, *localStore, BasicDerivation(*step->drv));
|
||||||
to << maxSilentTime << buildTimeout;
|
conn.to << maxSilentTime << buildTimeout;
|
||||||
if (GET_PROTOCOL_MINOR(remoteVersion) >= 2)
|
if (GET_PROTOCOL_MINOR(conn.remoteVersion) >= 2)
|
||||||
to << maxLogSize;
|
conn.to << maxLogSize;
|
||||||
if (GET_PROTOCOL_MINOR(remoteVersion) >= 3) {
|
if (GET_PROTOCOL_MINOR(conn.remoteVersion) >= 3) {
|
||||||
to << repeats // == build-repeat
|
conn.to << repeats // == build-repeat
|
||||||
<< step->isDeterministic; // == enforce-determinism
|
<< step->isDeterministic; // == enforce-determinism
|
||||||
}
|
}
|
||||||
to.flush();
|
conn.to.flush();
|
||||||
|
|
||||||
result.startTime = time(0);
|
result.startTime = time(0);
|
||||||
int res;
|
int res;
|
||||||
{
|
{
|
||||||
MaintainCount<counter> mc(nrStepsBuilding);
|
MaintainCount<counter> mc(nrStepsBuilding);
|
||||||
res = readInt(from);
|
res = readInt(conn.from);
|
||||||
}
|
}
|
||||||
result.stopTime = time(0);
|
result.stopTime = time(0);
|
||||||
|
|
||||||
result.errorMsg = readString(from);
|
result.errorMsg = readString(conn.from);
|
||||||
if (GET_PROTOCOL_MINOR(remoteVersion) >= 3) {
|
if (GET_PROTOCOL_MINOR(conn.remoteVersion) >= 3) {
|
||||||
result.timesBuilt = readInt(from);
|
result.timesBuilt = readInt(conn.from);
|
||||||
result.isNonDeterministic = readInt(from);
|
result.isNonDeterministic = readInt(conn.from);
|
||||||
auto start = readInt(from);
|
auto start = readInt(conn.from);
|
||||||
auto stop = readInt(from);
|
auto stop = readInt(conn.from);
|
||||||
if (start && start) {
|
if (start && start) {
|
||||||
/* Note: this represents the duration of a single
|
/* Note: this represents the duration of a single
|
||||||
round, rather than all rounds. */
|
round, rather than all rounds. */
|
||||||
|
@ -374,8 +394,8 @@ void State::buildRemote(ref<Store> destStore,
|
||||||
result.stopTime = stop;
|
result.stopTime = stop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (GET_PROTOCOL_MINOR(remoteVersion) >= 6) {
|
if (GET_PROTOCOL_MINOR(conn.remoteVersion) >= 6) {
|
||||||
worker_proto::read(*localStore, from, Phantom<DrvOutputs> {});
|
worker_proto::read(*localStore, conn.from, Phantom<DrvOutputs> {});
|
||||||
}
|
}
|
||||||
switch ((BuildResult::Status) res) {
|
switch ((BuildResult::Status) res) {
|
||||||
case BuildResult::Built:
|
case BuildResult::Built:
|
||||||
|
@ -451,19 +471,19 @@ void State::buildRemote(ref<Store> destStore,
|
||||||
/* Get info about each output path. */
|
/* Get info about each output path. */
|
||||||
std::map<StorePath, ValidPathInfo> infos;
|
std::map<StorePath, ValidPathInfo> infos;
|
||||||
size_t totalNarSize = 0;
|
size_t totalNarSize = 0;
|
||||||
to << cmdQueryPathInfos;
|
conn.to << cmdQueryPathInfos;
|
||||||
worker_proto::write(*localStore, to, outputs);
|
worker_proto::write(*localStore, conn.to, outputs);
|
||||||
to.flush();
|
conn.to.flush();
|
||||||
while (true) {
|
while (true) {
|
||||||
auto storePathS = readString(from);
|
auto storePathS = readString(conn.from);
|
||||||
if (storePathS == "") break;
|
if (storePathS == "") break;
|
||||||
auto deriver = readString(from); // deriver
|
auto deriver = readString(conn.from); // deriver
|
||||||
auto references = worker_proto::read(*localStore, from, Phantom<StorePathSet> {});
|
auto references = worker_proto::read(*localStore, conn.from, Phantom<StorePathSet> {});
|
||||||
readLongLong(from); // download size
|
readLongLong(conn.from); // download size
|
||||||
auto narSize = readLongLong(from);
|
auto narSize = readLongLong(conn.from);
|
||||||
auto narHash = Hash::parseAny(readString(from), htSHA256);
|
auto narHash = Hash::parseAny(readString(conn.from), htSHA256);
|
||||||
auto ca = parseContentAddressOpt(readString(from));
|
auto ca = parseContentAddressOpt(readString(conn.from));
|
||||||
readStrings<StringSet>(from); // sigs
|
readStrings<StringSet>(conn.from); // sigs
|
||||||
ValidPathInfo info(localStore->parseStorePath(storePathS), narHash);
|
ValidPathInfo info(localStore->parseStorePath(storePathS), narHash);
|
||||||
assert(outputs.count(info.path));
|
assert(outputs.count(info.path));
|
||||||
info.references = references;
|
info.references = references;
|
||||||
|
@ -502,10 +522,10 @@ void State::buildRemote(ref<Store> destStore,
|
||||||
lambda function only gets executed if someone tries to read
|
lambda function only gets executed if someone tries to read
|
||||||
from source2, we will send the command from here rather
|
from source2, we will send the command from here rather
|
||||||
than outside the lambda. */
|
than outside the lambda. */
|
||||||
to << cmdDumpStorePath << localStore->printStorePath(path);
|
conn.to << cmdDumpStorePath << localStore->printStorePath(path);
|
||||||
to.flush();
|
conn.to.flush();
|
||||||
|
|
||||||
TeeSource tee(from, sink);
|
TeeSource tee(conn.from, sink);
|
||||||
extractNarData(tee, localStore->printStorePath(path), narMembers);
|
extractNarData(tee, localStore->printStorePath(path), narMembers);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue