Search in sources :

Example 1 with Mapping

use of hudson.model.queue.MappingWorksheet.Mapping in project hudson-2.x by hudson.

the class Queue method pop.

/**
     * Called by the executor to fetch something to build next.
     * <p>
     * This method blocks until a next project becomes buildable.
     */
public synchronized WorkUnit pop() throws InterruptedException {
    final Executor exec = Executor.currentExecutor();
    if (exec instanceof OneOffExecutor) {
        OneOffExecutor ooe = (OneOffExecutor) exec;
        final WorkUnit wu = ooe.getWorkUnit();
        pendings.remove(wu.context.item);
        return wu;
    }
    try {
        while (true) {
            final JobOffer offer = new JobOffer(exec);
            long sleep = -1;
            // consider myself parked
            assert !parked.containsKey(exec);
            parked.put(exec, offer);
            // reuse executor thread to do a queue maintenance.
            // at the end of this we get all the buildable jobs
            // in the buildables field.
            maintain();
            // allocate buildable jobs to executors
            Iterator<BuildableItem> itr = buildables.iterator();
            while (itr.hasNext()) {
                BuildableItem p = itr.next();
                // one last check to make sure this build is not blocked.
                if (isBuildBlocked(p.task)) {
                    itr.remove();
                    blockedProjects.put(p.task, new BlockedItem(p));
                    continue;
                }
                List<JobOffer> candidates = new ArrayList<JobOffer>(parked.size());
                for (JobOffer j : parked.values()) if (j.canTake(p.task))
                    candidates.add(j);
                MappingWorksheet ws = new MappingWorksheet(p, candidates);
                Mapping m = loadBalancer.map(p.task, ws);
                if (m == null)
                    // check if we can execute other projects
                    continue;
                // found a matching executor. use it.
                WorkUnitContext wuc = new WorkUnitContext(p);
                m.execute(wuc);
                itr.remove();
                if (!wuc.getWorkUnits().isEmpty())
                    pendings.add(p);
            }
            if (!waitingList.isEmpty()) {
                // wait until the first item in the queue is due
                sleep = peek().timestamp.getTimeInMillis() - new GregorianCalendar().getTimeInMillis();
                // avoid wait(0)
                if (sleep < 100)
                    sleep = 100;
            }
            if (sleep == -1)
                offer.event.block();
            else
                offer.event.block(sleep);
            // retract the offer object
            assert parked.get(exec) == offer;
            parked.remove(exec);
            // am I woken up because I have a project to build?
            if (offer.workUnit != null) {
                // if so, just build it
                LOGGER.fine("Pop returning " + offer.workUnit + " for " + exec.getName());
                // TODO: I think this has to be done by the last executor that leaves the pop(), not by main executor
                if (offer.workUnit.isMainWork())
                    pendings.remove(offer.workUnit.context.item);
                return offer.workUnit;
            }
        // otherwise run a queue maintenance
        }
    } finally {
        // remove myself from the parked list
        JobOffer offer = parked.remove(exec);
        if (offer != null && offer.workUnit != null) {
            // we are already assigned a project, but now we can't handle it.
            offer.workUnit.context.abort(new AbortException());
        }
        // since this executor might have been chosen for
        // maintenance, schedule another one. Worst case
        // we'll just run a pointless maintenance, and that's
        // fine.
        scheduleMaintenance();
    }
}
Also used : WorkUnitContext(hudson.model.queue.WorkUnitContext) ArrayList(java.util.ArrayList) GregorianCalendar(java.util.GregorianCalendar) Mapping(hudson.model.queue.MappingWorksheet.Mapping) MappingWorksheet(hudson.model.queue.MappingWorksheet) WorkUnit(hudson.model.queue.WorkUnit) AbortException(hudson.AbortException)

Example 2 with Mapping

use of hudson.model.queue.MappingWorksheet.Mapping in project hudson-2.x by hudson.

the class BackFiller method makeTentativePlan.

private TentativePlan makeTentativePlan(BuildableItem bi) {
    if (recursion)
        return null;
    recursion = true;
    try {
        // pretend for now that all executors are available and decide some assignment that's executable.
        List<PseudoExecutorSlot> slots = new ArrayList<PseudoExecutorSlot>();
        for (Computer c : Hudson.getInstance().getComputers()) {
            if (c.isOffline())
                continue;
            for (Executor e : c.getExecutors()) {
                slots.add(new PseudoExecutorSlot(e));
            }
        }
        // also ignore all load predictions as we just want to figure out some executable assignment
        // and we are not trying to figure out if this task is executable right now.
        MappingWorksheet worksheet = new MappingWorksheet(bi, slots, Collections.<LoadPredictor>emptyList());
        Mapping m = Hudson.getInstance().getQueue().getLoadBalancer().map(bi.task, worksheet);
        if (m == null)
            return null;
        // figure out how many executors we need on each computer?
        Map<Computer, Integer> footprint = new HashMap<Computer, Integer>();
        for (Entry<WorkChunk, ExecutorChunk> e : m.toMap().entrySet()) {
            Computer c = e.getValue().computer;
            Integer v = footprint.get(c);
            if (v == null)
                v = 0;
            v += e.getKey().size();
            footprint.put(c, v);
        }
        // the point of a tentative plan is to displace other jobs to create a point in time
        // where this task can start executing. An incorrectly estimated duration is not
        // a problem in this regard, as we just need enough idle executors in the right moment.
        // The downside of guessing the duration wrong is that we can end up creating tentative plans
        // afterward that may be incorrect, but those plans will be rebuilt.
        long d = bi.task.getEstimatedDuration();
        if (d <= 0)
            d = TimeUnit2.MINUTES.toMillis(5);
        TimeRange slot = new TimeRange(System.currentTimeMillis(), d);
        // start executing this guy.
        for (Entry<Computer, Integer> e : footprint.entrySet()) {
            Computer computer = e.getKey();
            Timeline timeline = new Timeline();
            for (LoadPredictor lp : LoadPredictor.all()) {
                for (FutureLoad fl : Iterables.limit(lp.predict(worksheet, computer, slot.start, slot.end), 100)) {
                    timeline.insert(fl.startTime, fl.startTime + fl.duration, fl.numExecutors);
                }
            }
            Long x = timeline.fit(slot.start, slot.duration, computer.countExecutors() - e.getValue());
            // if no suitable range was found in [slot.start,slot.end), slot.end would be a good approximation
            if (x == null)
                x = slot.end;
            slot = slot.shiftTo(x);
        }
        TentativePlan tp = new TentativePlan(footprint, slot);
        bi.addAction(tp);
        return tp;
    } finally {
        recursion = false;
    }
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Mapping(hudson.model.queue.MappingWorksheet.Mapping) Executor(hudson.model.Executor) Computer(hudson.model.Computer) ExecutorChunk(hudson.model.queue.MappingWorksheet.ExecutorChunk) WorkChunk(hudson.model.queue.MappingWorksheet.WorkChunk)

Aggregations

Mapping (hudson.model.queue.MappingWorksheet.Mapping)2 ArrayList (java.util.ArrayList)2 AbortException (hudson.AbortException)1 Computer (hudson.model.Computer)1 Executor (hudson.model.Executor)1 MappingWorksheet (hudson.model.queue.MappingWorksheet)1 ExecutorChunk (hudson.model.queue.MappingWorksheet.ExecutorChunk)1 WorkChunk (hudson.model.queue.MappingWorksheet.WorkChunk)1 WorkUnit (hudson.model.queue.WorkUnit)1 WorkUnitContext (hudson.model.queue.WorkUnitContext)1 GregorianCalendar (java.util.GregorianCalendar)1 HashMap (java.util.HashMap)1