use of hudson.model.queue.WorkUnitContext 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();
}
}
Aggregations