Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/hydra-queue-runner/dispatcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,9 @@ State::MachineReservation::MachineReservation(State & state, Step::ptr step, Mac
{
machine->state->currentJobs++;

for (auto & f : step->requiredSystemFeatures)
machine->state->featuresConsumption[f.first] += f.second;

{
auto machineTypes_(state.machineTypes.lock());
(*machineTypes_)[step->systemType].running++;
Expand All @@ -354,6 +357,9 @@ State::MachineReservation::~MachineReservation()
if (prev == 1)
machine->state->idleSince = time(0);

for (auto & f : step->requiredSystemFeatures)
machine->state->featuresConsumption[f.first] -= f.second;

{
auto machineTypes_(state.machineTypes.lock());
auto & machineType = (*machineTypes_)[step->systemType];
Expand Down
27 changes: 23 additions & 4 deletions src/hydra-queue-runner/hydra-queue-runner.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <iostream>
#include <thread>
#include <climits>

#include <sys/types.h>
#include <sys/stat.h>
Expand Down Expand Up @@ -109,12 +110,30 @@ void State::parseMachines(const std::string & contents)
else
machine->maxJobs = 1;
machine->speedFactor = atof(tokens[4].c_str());

if (tokens[5] == "-") tokens[5] = "";
machine->supportedFeatures = tokenizeString<StringSet>(tokens[5], ",");
for (auto & rf : tokenizeString<StringSet>(tokens[5], ",")) {
auto ft = tokenizeString<std::list<std::string>>(rf, ":");
unsigned int amount = UINT_MAX;
if (ft.size() == 2) // consumable info provided
amount = std::stoul(ft.back());
if (amount == 0)
amount = UINT_MAX;
machine->supportedFeatures[ft.front()] = amount;
}

if (tokens[6] == "-") tokens[6] = "";
machine->mandatoryFeatures = tokenizeString<StringSet>(tokens[6], ",");
for (auto & f : machine->mandatoryFeatures)
machine->supportedFeatures.insert(f);
for (auto & rf : tokenizeString<StringSet>(tokens[6], ",")) {
auto ft = tokenizeString<std::list<std::string>>(rf, ":");
unsigned int amount = UINT_MAX;
if (ft.size() == 2) // consumable info provided
amount = std::stoul(ft.back());
if (amount == 0)
amount = UINT_MAX;
machine->mandatoryFeatures[ft.front()] = amount;
machine->supportedFeatures[ft.front()] = amount;
}

if (tokens[7] != "" && tokens[7] != "-")
machine->sshPublicHostKey = base64Decode(tokens[7]);

Expand Down
20 changes: 15 additions & 5 deletions src/hydra-queue-runner/queue-monitor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -435,14 +435,24 @@ Step::ptr State::createStep(ref<Store> destStore,
step->systemType = step->drv.platform;
{
auto i = step->drv.env.find("requiredSystemFeatures");
StringSet features;
if (i != step->drv.env.end())
features = step->requiredSystemFeatures = tokenizeString<std::set<std::string>>(i->second);
StringSet rawFeatures;
std::map<std::string, unsigned int> features;
if (i != step->drv.env.end()) {
rawFeatures = tokenizeString<std::set<std::string>>(i->second);
for (auto & rf : rawFeatures) {
auto ft = tokenizeString<std::list<std::string>>(rf, ":");
unsigned int amount = 1;
if (ft.size() == 2) // consumable info provided
amount = std::stoul(ft.back());
features[ft.front()] = amount;
}
step->requiredSystemFeatures = features;
}
if (step->preferLocalBuild)
features.insert("local");
features["local"] = 1;
if (!features.empty()) {
step->systemType += ":";
step->systemType += concatStringsSep(",", features);
step->systemType += concatStringsSep(",", rawFeatures);
}
}

Expand Down
23 changes: 15 additions & 8 deletions src/hydra-queue-runner/state.hh
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ struct Step

nix::Path drvPath;
nix::Derivation drv;
std::set<std::string> requiredSystemFeatures;
std::map<std::string, unsigned int> requiredSystemFeatures;
bool preferLocalBuild;
bool isDeterministic;
std::string systemType; // concatenation of drv.platform and requiredSystemFeatures
Expand Down Expand Up @@ -220,14 +220,16 @@ struct Machine
bool enabled{true};

std::string sshName, sshKey;
std::set<std::string> systemTypes, supportedFeatures, mandatoryFeatures;
std::set<std::string> systemTypes;
std::map<std::string, unsigned int> supportedFeatures, mandatoryFeatures;
unsigned int maxJobs = 1;
float speedFactor = 1.0;
std::string sshPublicHostKey;

struct State {
typedef std::shared_ptr<State> ptr;
counter currentJobs{0};
std::map<std::string, counter> featuresConsumption;
counter nrStepsDone{0};
counter totalStepTime{0}; // total time for steps, including closure copying
counter totalStepBuildTime{0}; // total build time for steps
Expand All @@ -254,22 +256,27 @@ struct Machine
if (!systemTypes.count(step->drv.platform == "builtin" ? nix::settings.thisSystem : step->drv.platform))
return false;

/* Check that the step requires all mandatory features of this
/* Check that the step requires/consumes all mandatory features of this
machine. (Thus, a machine with the mandatory "benchmark"
feature will *only* execute steps that require
"benchmark".) The "preferLocalBuild" bit of a step is
mapped to the "local" feature; thus machines that have
"local" as a mandatory feature will only do
preferLocalBuild steps. */
for (auto & f : mandatoryFeatures)
if (!step->requiredSystemFeatures.count(f)
&& !(f == "local" && step->preferLocalBuild))
if (step->requiredSystemFeatures.find(f.first) == step->requiredSystemFeatures.end()
&& !(f.first == "local" && step->preferLocalBuild))
return false;

/* Check that the machine supports all features required by
the step. */
for (auto & f : step->requiredSystemFeatures)
if (!supportedFeatures.count(f)) return false;
the step, and has enough of each available. */
for (auto & f : step->requiredSystemFeatures) {
if (supportedFeatures.find(f.first) == supportedFeatures.end())
return false;
unsigned long current = state->featuresConsumption[f.first];
if (current + f.second > supportedFeatures[f.first])
return false;
}

return true;
}
Expand Down