Load the queue in order of global priority

This commit is contained in:
Eelco Dolstra 2015-08-11 02:14:11 +02:00
parent 97f11baa8d
commit b7965df928

View file

@ -59,12 +59,17 @@ void State::getQueuedBuilds(Connection & conn, std::shared_ptr<StoreAPI> store,
/* Grab the queued builds from the database, but don't process /* Grab the queued builds from the database, but don't process
them yet (since we don't want a long-running transaction). */ them yet (since we don't want a long-running transaction). */
std::multimap<Path, Build::ptr> newBuilds; std::vector<BuildID> newIDs;
std::map<BuildID, Build::ptr> newBuildsByID;
std::multimap<Path, BuildID> newBuildsByPath;
{ {
pqxx::work txn(conn); pqxx::work txn(conn);
auto res = txn.parameterized("select id, project, jobset, job, drvPath, maxsilent, timeout, timestamp, globalPriority from Builds where id > $1 and finished = 0 order by id")(lastBuildId).exec(); auto res = txn.parameterized
("select id, project, jobset, job, drvPath, maxsilent, timeout, timestamp, globalPriority from Builds "
"where id > $1 and finished = 0 order by globalPriority desc, id")
(lastBuildId).exec();
for (auto const & row : res) { for (auto const & row : res) {
auto builds_(builds.lock()); auto builds_(builds.lock());
@ -85,7 +90,9 @@ void State::getQueuedBuilds(Connection & conn, std::shared_ptr<StoreAPI> store,
build->globalPriority = row["globalPriority"].as<int>(); build->globalPriority = row["globalPriority"].as<int>();
build->jobset = createJobset(txn, build->projectName, build->jobsetName); build->jobset = createJobset(txn, build->projectName, build->jobsetName);
newBuilds.emplace(std::make_pair(build->drvPath, build)); newIDs.push_back(id);
newBuildsByID[id] = build;
newBuildsByPath.emplace(std::make_pair(build->drvPath, id));
} }
} }
@ -96,6 +103,7 @@ void State::getQueuedBuilds(Connection & conn, std::shared_ptr<StoreAPI> store,
createBuild = [&](Build::ptr build) { createBuild = [&](Build::ptr build) {
printMsg(lvlTalkative, format("loading build %1% (%2%)") % build->id % build->fullJobName()); printMsg(lvlTalkative, format("loading build %1% (%2%)") % build->id % build->fullJobName());
nrAdded++; nrAdded++;
newBuildsByID.erase(build->id);
if (!store->isValidPath(build->drvPath)) { if (!store->isValidPath(build->drvPath)) {
/* Derivation has been GC'ed prematurely. */ /* Derivation has been GC'ed prematurely. */
@ -124,13 +132,11 @@ void State::getQueuedBuilds(Connection & conn, std::shared_ptr<StoreAPI> store,
if build A depends on build B with top-level step X, then X if build A depends on build B with top-level step X, then X
will be "accounted" to B in doBuildStep(). */ will be "accounted" to B in doBuildStep(). */
for (auto & r : newSteps) { for (auto & r : newSteps) {
while (true) { auto i = newBuildsByPath.find(r->drvPath);
auto i = newBuilds.find(r->drvPath); if (i == newBuildsByPath.end()) continue;
if (i == newBuilds.end()) break; auto j = newBuildsByID.find(i->second);
Build::ptr b = i->second; if (j == newBuildsByID.end()) continue;
newBuilds.erase(i); createBuild(j->second);
createBuild(b);
}
} }
/* If we didn't get a step, it means the step's outputs are /* If we didn't get a step, it means the step's outputs are
@ -219,9 +225,10 @@ void State::getQueuedBuilds(Connection & conn, std::shared_ptr<StoreAPI> store,
/* Now instantiate build steps for each new build. The builder /* Now instantiate build steps for each new build. The builder
threads can start building the runnable build steps right away, threads can start building the runnable build steps right away,
even while we're still processing other new builds. */ even while we're still processing other new builds. */
while (!newBuilds.empty()) { for (auto id : newIDs) {
auto build = newBuilds.begin()->second; auto i = newBuildsByID.find(id);
newBuilds.erase(newBuilds.begin()); if (i == newBuildsByID.end()) continue;
auto build = i->second;
newRunnable.clear(); newRunnable.clear();
nrAdded = 0; nrAdded = 0;