BYVRA54QBKHLFOPIRBJKZZI7JYBYHSOK7MIA3TUZTALZQJGG3G7QC 4VYY2ADPFENPAC36FJCSEMEHOPL6E2T4RPXJKYVF47DFKAO6PLIAC DIEY5USNXFN6O2ARZ5IPBS2VX4OH7KE4RMX2JWAWTVMMSYA6GREAC BG6PEOB2M2Y56QPVMELU7VNNCGNMSQ2K6ATBUCPJLKPLTDWNJQ5AC 5AIYUMTBY6TFQTBRP3MJ2PYWUMRF57I77NIVWYE74UMEVQMBWZVQC NAYQT2GTCJPBFRSK7CBFX655F2NGTBPICJSCYG2CSCQ5NRDHZG6QC HH3LID6L4WJZV6NEDVCLPCO6KF2NLUUV3VJPFNJUQZCIESK3JYSQC OCZ4LSGGSCMSLGC3C32D5JUYYHS5CIPOKOAMADEFAFZOFXJ3YY3AC N4IROACVZ4MU73J5SM6WXJMKQSFR3VN5SOKENNNZNEGMTGB2Q3HAC AF74AH2SUN3FKWNP6ZMAL7Q5T6R5WJDWOPQFZA6SS52L7PWPCWNAC VZKB5CIEW7Z5YBRYFKIFBQODBCG2NPGGXU3F3VQ3BNKGP5WYCPBQC YR2IM6Y5XA6XDFBWJUFSVNMQQKLIW6A2LDS4F77A3OZLEMBACCRAC GS4BE6TB6GH2JUZJHDPHL6YG7J7YYESF3YOZJZ2CFABXUTO4VYPQC 5LBMP7GAY5IIOX75M62BRGKXS4BNIQRDBCYLM4PHI773KRABTL2QC AUMIJSEOUDEGOCN3YSBD7KXOWE2CD2HN2VHS54FWUBMGRUBJHDXQC 73YR46NJNYZQKHA3QDJCAZYAKC2CGEF5LIS44NOIPDZU6FX6BDPQC DWFTK56EAGNPSKWWWY5MFPATQWO5PZGHF5D53JOEJ2DG5NLLYRBQC CNLNT3T4IXU42GAC64CU5CEDTDLM2SHSJZEVHTMOCWYFXSQNC76QC LE4VZIY5VZ52FOP5QQRIJINWIMWTAPRTZTGO77JXUEPGRPRSQYMAC FITVNQ2SVM6KSOF5P3HHWJYQ3WMQYDJGAONCBIZ7OF7CPXGMA36QC 6EO3HVNAAVJLBYTBSHXQADDTYF7JJU3ANHS5SKHSSROOW4AXIZ4AC A2GL5FOZ3UJ2NM5RPRWTNPFTKLBA54B2UC6UIYO4M3N3RFNC4BTAC HHOMBU7GGRAEXODSDY3WUHQGOSQ35OTGRNBWKKAS2D4YEIZTTNUAC 7LB6QBXYOGU43UDLJDJQZFGT4XDALULXDF3WX3WWHL7X3JTB54CQC TDSBTZKXDJNCDBIMSVJQPB5P2QVQ6FWYLZSZU5RJR77DL2JQD4FAC SL3WSRACCX2IMJHHLTRAUQT7QDLCOKYLVO2FEHWIHXM5GPKSRJTQC UVNTWTWGQOFKDAJ2ROJYT4U2N4EUXKNWZWPHOM42WPLUL4ALXRJQC unsigned int magic = readInt(from);if (magic != SERVE_MAGIC_2)throw Error(format("protocol mismatch with ‘nix-store --serve’ on ‘%1%’") % machine->sshName);remoteVersion = readInt(from);if (GET_PROTOCOL_MAJOR(remoteVersion) != 0x200)throw Error(format("unsupported ‘nix-store --serve’ protocol version on ‘%1%’") % machine->sshName);if (GET_PROTOCOL_MINOR(remoteVersion) >= 1)sendDerivation = false;
try {to << SERVE_MAGIC_1 << 0x202;to.flush();unsigned int magic = readInt(from);if (magic != SERVE_MAGIC_2)throw Error(format("protocol mismatch with ‘nix-store --serve’ on ‘%1%’") % machine->sshName);remoteVersion = readInt(from);if (GET_PROTOCOL_MAJOR(remoteVersion) != 0x200)throw Error(format("unsupported ‘nix-store --serve’ protocol version on ‘%1%’") % machine->sshName);if (GET_PROTOCOL_MINOR(remoteVersion) >= 1)sendDerivation = false;
} catch (EndOfFile & e) {child.pid.wait(true);
} catch (EndOfFile & e) {child.pid.wait(true);string s = chomp(readFile(result.logFile));throw Error(format("cannot connect to ‘%1%’: %2%") % machine->sshName % s);}
auto now = std::chrono::system_clock::now();if (info->consecutiveFailures == 0 || info->lastFailure < now - std::chrono::seconds(30)) {info->consecutiveFailures = std::min(info->consecutiveFailures + 1, (unsigned int) 4);info->lastFailure = now;int delta = retryInterval * powf(retryBackoff, info->consecutiveFailures - 1) + (rand() % 30);printMsg(lvlInfo, format("will disable machine ‘%1%’ for %2%s") % machine->sshName % delta);info->disabledUntil = now + std::chrono::seconds(delta);}
info->consecutiveFailures = 0;
string s = chomp(readFile(result.logFile));throw Error(format("cannot connect to ‘%1%’: %2%") % machine->sshName % s);}{auto info(machine->state->connectInfo.lock());info->consecutiveFailures = 0;}/* Gather the inputs. If the remote side is Nix <= 1.9, we have tocopy the entire closure of ‘drvPath’, as well as the requiredoutputs of the input derivations. On Nix > 1.9, we only need tocopy the immediate sources of the derivation and the requiredoutputs of the input derivations. */PathSet inputs;BasicDerivation basicDrv(step->drv);
/* Gather the inputs. If the remote side is Nix <= 1.9, we have tocopy the entire closure of ‘drvPath’, as well as the requiredoutputs of the input derivations. On Nix > 1.9, we only need tocopy the immediate sources of the derivation and the requiredoutputs of the input derivations. */PathSet inputs;BasicDerivation basicDrv(step->drv);
for (auto & input : step->drv.inputDrvs) {Derivation drv2 = readDerivation(input.first);for (auto & name : input.second) {auto i = drv2.outputs.find(name);if (i == drv2.outputs.end()) continue;inputs.insert(i->second.path);basicDrv.inputSrcs.insert(i->second.path);
for (auto & input : step->drv.inputDrvs) {Derivation drv2 = readDerivation(input.first);for (auto & name : input.second) {auto i = drv2.outputs.find(name);if (i == drv2.outputs.end()) continue;inputs.insert(i->second.path);basicDrv.inputSrcs.insert(i->second.path);}
/* Ensure that the inputs exist in the destination store. This isa no-op for regular stores, but for the binary cache store,this will copy the inputs to the binary cache from the localstore. */destStore->buildPaths(basicDrv.inputSrcs);
/* Ensure that the inputs exist in the destination store. This isa no-op for regular stores, but for the binary cache store,this will copy the inputs to the binary cache from the localstore. */destStore->buildPaths(basicDrv.inputSrcs);
/* Copy the input closure. */if (/* machine->sshName != "localhost" */ true) {auto mc1 = std::make_shared<MaintainCount>(nrStepsWaiting);std::lock_guard<std::mutex> sendLock(machine->state->sendLock);mc1.reset();MaintainCount mc2(nrStepsCopyingTo);printMsg(lvlDebug, format("sending closure of ‘%1%’ to ‘%2%’") % step->drvPath % machine->sshName);
/* Copy the input closure. */if (/* machine->sshName != "localhost" */ true) {auto mc1 = std::make_shared<MaintainCount>(nrStepsWaiting);std::lock_guard<std::mutex> sendLock(machine->state->sendLock);mc1.reset();MaintainCount mc2(nrStepsCopyingTo);printMsg(lvlDebug, format("sending closure of ‘%1%’ to ‘%2%’") % step->drvPath % machine->sshName);
result.overhead += std::chrono::duration_cast<std::chrono::milliseconds>(now2 - now1).count();}
result.overhead += std::chrono::duration_cast<std::chrono::milliseconds>(now2 - now1).count();}
/* Do the build. */printMsg(lvlDebug, format("building ‘%1%’ on ‘%2%’") % step->drvPath % machine->sshName);
/* Do the build. */printMsg(lvlDebug, format("building ‘%1%’ on ‘%2%’") % step->drvPath % machine->sshName);
if (sendDerivation)to << cmdBuildPaths << PathSet({step->drvPath});elseto << cmdBuildDerivation << step->drvPath << basicDrv;to << maxSilentTime << buildTimeout;if (GET_PROTOCOL_MINOR(remoteVersion) >= 2)to << 64 * 1024 * 1024; // == maxLogSizeto.flush();
if (sendDerivation)to << cmdBuildPaths << PathSet({step->drvPath});elseto << cmdBuildDerivation << step->drvPath << basicDrv;to << maxSilentTime << buildTimeout;if (GET_PROTOCOL_MINOR(remoteVersion) >= 2)to << 64 * 1024 * 1024; // == maxLogSizeto.flush();
result.startTime = time(0);int res;{MaintainCount mc(nrStepsBuilding);res = readInt(from);}result.stopTime = time(0);
result.startTime = time(0);int res;{MaintainCount mc(nrStepsBuilding);res = readInt(from);}result.stopTime = time(0);
if (sendDerivation) {if (res) {result.errorMsg = (format("%1% on ‘%2%’") % readString(from) % machine->sshName).str();if (res == 100) {result.stepStatus = bsFailed;result.canCache = true;
if (sendDerivation) {if (res) {result.errorMsg = (format("%1% on ‘%2%’") % readString(from) % machine->sshName).str();if (res == 100) {result.stepStatus = bsFailed;result.canCache = true;}else if (res == 101) {result.stepStatus = bsTimedOut;}else {result.stepStatus = bsAborted;result.canRetry = true;}return;
else if (res == 101) {result.stepStatus = bsTimedOut;}else {result.stepStatus = bsAborted;result.canRetry = true;
result.stepStatus = bsSuccess;} else {result.errorMsg = readString(from);switch ((BuildResult::Status) res) {case BuildResult::Built:result.stepStatus = bsSuccess;break;case BuildResult::Substituted:case BuildResult::AlreadyValid:result.stepStatus = bsSuccess;result.isCached = true;break;case BuildResult::PermanentFailure:result.stepStatus = bsFailed;result.canCache = true;result.errorMsg = "";break;case BuildResult::InputRejected:case BuildResult::OutputRejected:result.stepStatus = bsFailed;result.canCache = true;break;case BuildResult::TransientFailure:result.stepStatus = bsFailed;result.canRetry = true;result.errorMsg = "";break;case BuildResult::CachedFailure: // cached on the build machineresult.stepStatus = bsCachedFailure;result.canCache = true;result.errorMsg = "";break;case BuildResult::TimedOut:result.stepStatus = bsTimedOut;result.errorMsg = "";break;case BuildResult::MiscFailure:result.stepStatus = bsAborted;result.canRetry = true;break;case BuildResult::LogLimitExceeded:result.stepStatus = bsLogLimitExceeded;break;default:result.stepStatus = bsAborted;break;
result.stepStatus = bsSuccess;} else {result.errorMsg = readString(from);switch ((BuildResult::Status) res) {case BuildResult::Built:result.stepStatus = bsSuccess;break;case BuildResult::Substituted:case BuildResult::AlreadyValid:result.stepStatus = bsSuccess;result.isCached = true;break;case BuildResult::PermanentFailure:result.stepStatus = bsFailed;result.canCache = true;result.errorMsg = "";break;case BuildResult::InputRejected:case BuildResult::OutputRejected:result.stepStatus = bsFailed;result.canCache = true;break;case BuildResult::TransientFailure:result.stepStatus = bsFailed;result.canRetry = true;result.errorMsg = "";break;case BuildResult::CachedFailure: // cached on the build machineresult.stepStatus = bsCachedFailure;result.canCache = true;result.errorMsg = "";break;case BuildResult::TimedOut:result.stepStatus = bsTimedOut;result.errorMsg = "";break;case BuildResult::MiscFailure:result.stepStatus = bsAborted;result.canRetry = true;break;case BuildResult::LogLimitExceeded:result.stepStatus = bsLogLimitExceeded;break;default:result.stepStatus = bsAborted;break;
result.errorMsg = "";/* If the path was substituted or already valid, then we didn'tget a build log. */if (result.isCached) {printMsg(lvlInfo, format("outputs of ‘%1%’ substituted or already valid on ‘%2%’") % step->drvPath % machine->sshName);unlink(result.logFile.c_str());result.logFile = "";
/* If the path was substituted or already valid, then we didn'tget a build log. */if (result.isCached) {printMsg(lvlInfo, format("outputs of ‘%1%’ substituted or already valid on ‘%2%’") % step->drvPath % machine->sshName);unlink(result.logFile.c_str());result.logFile = "";}
auto now1 = std::chrono::steady_clock::now();
/* Copy the output paths. */if (/* machine->sshName != "localhost" */ true) {MaintainCount mc(nrStepsCopyingFrom);
PathSet outputs;for (auto & output : step->drv.outputs)outputs.insert(output.second.path);
auto now1 = std::chrono::steady_clock::now();
/* Query the size of the output paths. */size_t totalNarSize = 0;to << cmdQueryPathInfos << outputs;to.flush();while (true) {if (readString(from) == "") break;readString(from); // deriverreadStrings<PathSet>(from); // referencesreadLongLong(from); // download sizetotalNarSize += readLongLong(from);}
PathSet outputs;for (auto & output : step->drv.outputs)outputs.insert(output.second.path);
if (totalNarSize > maxOutputSize) {result.stepStatus = bsNarSizeLimitExceeded;return;}
/* Query the size of the output paths. */size_t totalNarSize = 0;to << cmdQueryPathInfos << outputs;to.flush();while (true) {if (readString(from) == "") break;readString(from); // deriverreadStrings<PathSet>(from); // referencesreadLongLong(from); // download sizetotalNarSize += readLongLong(from);}
printMsg(lvlDebug, format("copying outputs of ‘%s’ from ‘%s’ (%d bytes)")% step->drvPath % machine->sshName % totalNarSize);
if (totalNarSize > maxOutputSize) {result.stepStatus = bsNarSizeLimitExceeded;return;}
/* Block until we have the required amount of memoryavailable. FIXME: only need this for binary cachedestination stores. */auto resStart = std::chrono::steady_clock::now();auto memoryReservation(memoryTokens.get(totalNarSize));auto resStop = std::chrono::steady_clock::now();
printMsg(lvlDebug, format("copying outputs of ‘%s’ from ‘%s’ (%d bytes)")% step->drvPath % machine->sshName % totalNarSize);
auto resMs = std::chrono::duration_cast<std::chrono::milliseconds>(resStop - resStart).count();if (resMs >= 1000)printMsg(lvlError, format("warning: had to wait %d ms for %d memory tokens for %s")% resMs % totalNarSize % step->drvPath);
/* Block until we have the required amount of memoryavailable. FIXME: only need this for binary cachedestination stores. */auto resStart = std::chrono::steady_clock::now();auto memoryReservation(memoryTokens.get(totalNarSize));auto resStop = std::chrono::steady_clock::now();
result.accessor = destStore->getFSAccessor();
auto resMs = std::chrono::duration_cast<std::chrono::milliseconds>(resStop - resStart).count();if (resMs >= 1000)printMsg(lvlError, format("warning: had to wait %d ms for %d memory tokens for %s")% resMs % totalNarSize % step->drvPath);
to << cmdExportPaths << 0 << outputs;to.flush();destStore->importPaths(false, from, result.accessor);
result.overhead += std::chrono::duration_cast<std::chrono::milliseconds>(now2 - now1).count();
} catch (Error & e) {/* Disable this machine until a certain period of time haspassed. This period increases on every consecutivefailure. However, don't count failures that occurred soonafter the last one (to take into account steps started inparallel). */auto info(machine->state->connectInfo.lock());auto now = std::chrono::system_clock::now();if (info->consecutiveFailures == 0 || info->lastFailure < now - std::chrono::seconds(30)) {info->consecutiveFailures = std::min(info->consecutiveFailures + 1, (unsigned int) 4);info->lastFailure = now;int delta = retryInterval * powf(retryBackoff, info->consecutiveFailures - 1) + (rand() % 30);printMsg(lvlInfo, format("will disable machine ‘%1%’ for %2%s") % machine->sshName % delta);info->disabledUntil = now + std::chrono::seconds(delta);}throw;