Start steps in order of ascending build ID

[?]
Aug 10, 2015, 12:50 PM
46ADBTMQAHQAPW3OCI24F4I5DVK5N5QVHUA4TQVB6HFN337CHAVQC

Dependencies

  • [2] 4I2HF4L3 Unindent
  • [3] MHVIT4JY Split hydra-queue-runner.cc more
  • [4] YR2IM6Y5 Temporarily disable machines after a connection failure
  • [*] 24BMQDZA Start of single-process hydra-queue-runner
  • [*] HJOEIMLR Refactor

Change contents

  • edit in src/hydra-queue-runner/dispatcher.cc at line 1
    [3.14628]
    [3.14629]
    #include <iostream>
  • edit in src/hydra-queue-runner/dispatcher.cc at line 57
    [2.627]
    [2.627]
    /* Start steps until we're out of steps or slots. */
  • edit in src/hydra-queue-runner/dispatcher.cc at line 59
    [2.669][2.669:670]()
  • edit in src/hydra-queue-runner/dispatcher.cc at line 108
    [2.2621][3.16932:16933](),[3.16932][3.16932:16933](),[3.16933][2.2622:2846](),[2.2846][3.17237:17238](),[3.17237][3.17237:17238](),[3.17238][2.2847:3047]()
    /* Find a machine with a free slot and find a step to run
    on it. Once we find such a pair, we restart the outer
    loop because the machine sorting will have changed. */
    keepGoing = false;
    for (auto & mi : machinesSorted) {
    // FIXME: can we lose a wakeup if a builder exits concurrently?
    if (mi.machine->state->currentJobs >= mi.machine->maxJobs) continue;
  • edit in src/hydra-queue-runner/dispatcher.cc at line 109
    [3.17451]
    [2.3048]
    /* Sort the runnable steps by priority. FIXME: O(n lg n);
    obviously, it would be better to keep a runnable queue sorted
    by priority. */
    std::vector<Step::ptr> runnableSorted;
    {
  • replacement in src/hydra-queue-runner/dispatcher.cc at line 115
    [2.3093][2.3093:3296](),[2.3296][3.17589:17590](),[3.17589][3.17589:17590]()
    //printMsg(lvlDebug, format("%1% runnable builds") % runnable_->size());
    /* FIXME: we're holding the runnable lock too long
    here. This could be more efficient. */
    [2.3093]
    [2.3297]
    runnableSorted.reserve(runnable_->size());
  • replacement in src/hydra-queue-runner/dispatcher.cc at line 119
    [3.17716][2.3410:3451]()
    /* Delete dead steps. */
    [3.17716]
    [2.3451]
    /* Remove dead steps. */
  • replacement in src/hydra-queue-runner/dispatcher.cc at line 125
    [3.17837][2.3574:3755]()
    /* Can this machine do this step? */
    if (!mi.machine->supportsStep(step)) {
    ++i;
    continue;
    }
    [3.17837]
    [3.18020]
    ++i;
  • edit in src/hydra-queue-runner/dispatcher.cc at line 134
    [2.4105][3.18137:18166](),[3.18137][3.18137:18166]()
    ++i;
  • edit in src/hydra-queue-runner/dispatcher.cc at line 136
    [3.18222]
    [2.4106]
    }
    runnableSorted.push_back(step);
    }
    }
    sort(runnableSorted.begin(), runnableSorted.end(),
    [](const Step::ptr & a, const Step::ptr & b)
    {
    auto a_(a->state.lock());
    auto b_(b->state.lock()); // FIXME: deadlock?
    return a_->lowestBuildID < b_->lowestBuildID;
    });
    /* Find a machine with a free slot and find a step to run
    on it. Once we find such a pair, we restart the outer
    loop because the machine sorting will have changed. */
    keepGoing = false;
    for (auto & mi : machinesSorted) {
    if (mi.machine->state->currentJobs >= mi.machine->maxJobs) continue;
    for (auto & step : runnableSorted) {
    /* Can this machine do this step? */
    if (!mi.machine->supportsStep(step)) continue;
    /* Let's do this step. Remove it from the runnable
    list. FIXME: O(n). */
    {
    auto runnable_(runnable.lock());
    bool removed = false;
    for (auto i = runnable_->begin(); i != runnable_->end(); )
    if (i->lock() == step) {
    i = runnable_->erase(i);
    removed = true;
    break;
    } else ++i;
    assert(removed);
  • edit in src/hydra-queue-runner/dispatcher.cc at line 180
    [2.4326][2.4326:4367]()
    i = runnable_->erase(i);
  • edit in src/hydra-queue-runner/hydra-queue-runner.cc at line 204
    [6.13998]
    [6.17669]
    }
    void visitDependencies(std::function<void(Step::ptr)> visitor, Step::ptr start)
    {
    std::set<Step::ptr> queued;
    std::queue<Step::ptr> todo;
    todo.push(start);
    while (!todo.empty()) {
    auto step = todo.front();
    todo.pop();
    visitor(step);
    auto state(step->state.lock());
    for (auto & dep : state->deps)
    if (queued.find(dep) == queued.end()) {
    queued.insert(dep);
    todo.push(dep);
    }
    }
  • edit in src/hydra-queue-runner/queue-monitor.cc at line 230
    [3.28327]
    [3.28327]
    /* Update the lowest build ID field of each dependency. This
    is used by the dispatcher to start steps in order of build
    ID. */
    visitDependencies([&](const Step::ptr & step) {
    auto step_(step->state.lock());
    step_->lowestBuildID = std::min(step_->lowestBuildID, build->id);
    }, build->toplevel);
  • edit in src/hydra-queue-runner/state.hh at line 115
    [7.3082]
    [7.3082]
    /* The lowest build ID depending on this step. */
    BuildID lowestBuildID{std::numeric_limits<BuildID>::max()};
  • edit in src/hydra-queue-runner/state.hh at line 133
    [7.3265]
    [7.3265]
    /* Call ‘visitor’ for a step and all its dependencies. */
    void visitDependencies(std::function<void(Step::ptr)> visitor, Step::ptr step);
  • edit in src/hydra-queue-runner/state.hh at line 136
    [7.3266]
    [7.3266]