Skip to content

Commit

Permalink
[JENKINS-10944] Merge branch 'master' into FlyweightTask-JENKINS-10944
Browse files Browse the repository at this point in the history
(cherry picked from commit 1a80973)
  • Loading branch information
jglick authored and olivergondza committed Mar 2, 2015
1 parent 56795ba commit ff26bb8
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 21 deletions.
2 changes: 1 addition & 1 deletion core/src/main/java/hudson/model/LoadBalancer.java
Expand Up @@ -140,7 +140,7 @@ protected LoadBalancer sanitize() {
return new LoadBalancer() {
@Override
public Mapping map(Task task, MappingWorksheet worksheet) {
if (Queue.ifBlockedByHudsonShutdown(task)) {
if (Queue.isBlockedByShutdown(task)) {
// if we are quieting down, don't start anything new so that
// all executors will be eventually free.
return null;
Expand Down
64 changes: 47 additions & 17 deletions core/src/main/java/hudson/model/Queue.java
Expand Up @@ -106,7 +106,6 @@

import jenkins.model.Jenkins;
import jenkins.security.QueueItemAuthenticator;
import jenkins.security.QueueItemAuthenticatorConfiguration;
import jenkins.util.AtmostOneTaskExecutor;
import org.acegisecurity.AccessDeniedException;
import org.acegisecurity.Authentication;
Expand Down Expand Up @@ -1098,8 +1097,11 @@ public synchronized void maintain() {
for (BlockedItem p : new ArrayList<BlockedItem>(blockedProjects.values())) {// copy as we'll mutate the list
if (!isBuildBlocked(p) && allowNewBuildableTask(p.task)) {
// ready to be executed
p.leave(this);
makeBuildable(new BuildableItem(p));
Runnable r = makeBuildable(new BuildableItem(p));
if (r != null) {
p.leave(this);
r.run();
}
}
}
}
Expand All @@ -1115,7 +1117,12 @@ public synchronized void maintain() {
Task p = top.task;
if (!isBuildBlocked(top) && allowNewBuildableTask(p)) {
// ready to be executed immediately
makeBuildable(new BuildableItem(top));
Runnable r = makeBuildable(new BuildableItem(top));
if (r != null) {
r.run();
} else {
new BlockedItem(top).enter(this);
}
} else {
// this can't be built now because another build is in progress
// set this project aside.
Expand Down Expand Up @@ -1164,10 +1171,14 @@ public synchronized void maintain() {
}
}

private void makeBuildable(BuildableItem p) {
if(Jenkins.FLYWEIGHT_SUPPORT && p.task instanceof FlyweightTask && !ifBlockedByHudsonShutdown(p.task)) {


/**
* Tries to make an item ready to build.
* @param p a proposed buildable item
* @return a thunk to actually prepare it (after leaving an earlier list), or null if it cannot be run now
*/
private @CheckForNull Runnable makeBuildable(final BuildableItem p) {
if (p.task instanceof FlyweightTask) {
if (!isBlockedByShutdown(p.task)) {
Jenkins h = Jenkins.getInstance();
Map<Node,Integer> hashSource = new HashMap<Node, Integer>(h.getNodes().size());

Expand All @@ -1183,19 +1194,27 @@ private void makeBuildable(BuildableItem p) {

Label lbl = p.getAssignedLabel();
for (Node n : hash.list(p.task.getFullDisplayName())) {
Computer c = n.toComputer();
final Computer c = n.toComputer();
if (c==null || c.isOffline()) continue;
if (lbl!=null && !lbl.contains(n)) continue;
if (n.canTake(p) != null) continue;
c.startFlyWeightTask(new WorkUnitContext(p).createWorkUnit(p.task));
makePending(p);
return;
return new Runnable() {
@Override public void run() {
c.startFlyWeightTask(new WorkUnitContext(p).createWorkUnit(p.task));
makePending(p);
}
};
}
}
// if the execution get here, it means we couldn't schedule it anywhere.
// so do the scheduling like other normal jobs.
return null;
} else { // regular heavyweight task
return new Runnable() {
@Override public void run() {
p.enter(Queue.this);
}
};
}

p.enter(this);
}


Expand All @@ -1211,7 +1230,18 @@ private boolean makePending(BuildableItem p) {
return pendings.add(p);
}

/** @deprecated Use {@link #isBlockedByShutdown} instead. */
public static boolean ifBlockedByHudsonShutdown(Task task) {
return isBlockedByShutdown(task);
}

/**
* Checks whether a task should not be scheduled because {@link Jenkins#isQuietingDown()}.
* @param task some queue task
* @return true if {@link Jenkins#isQuietingDown()} unless this is a {@link NonBlockingTask}
* @since TODO
*/
public static boolean isBlockedByShutdown(Task task) {
return Jenkins.getInstance().isQuietingDown() && !(task instanceof NonBlockingTask);
}

Expand All @@ -1235,7 +1265,7 @@ public interface FlyweightTask extends Task {}
/**
* Marks {@link Task}s that are not affected by the {@linkplain Jenkins#isQuietingDown()} quieting down},
* because these tasks keep other tasks executing.
*
* @see #isBlockedByShutdown
* @since 1.336
*/
public interface NonBlockingTask extends Task {}
Expand Down Expand Up @@ -1926,7 +1956,7 @@ public BuildableItem(NotWaitingItem ni) {

public CauseOfBlockage getCauseOfBlockage() {
Jenkins jenkins = Jenkins.getInstance();
if(ifBlockedByHudsonShutdown(task))
if(isBlockedByShutdown(task))
return CauseOfBlockage.fromMessage(Messages._Queue_HudsonIsAboutToShutDown());

Label label = getAssignedLabel();
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/java/jenkins/model/Jenkins.java
Expand Up @@ -4179,9 +4179,9 @@ public static VersionNumber getVersion() {
public static boolean PARALLEL_LOAD = Configuration.getBooleanConfigParameter("parallelLoad", true);
public static boolean KILL_AFTER_LOAD = Configuration.getBooleanConfigParameter("killAfterLoad", false);
/**
* Enabled by default as of 1.337. Will keep it for a while just in case we have some serious problems.
* @deprecated No longer used.
*/
public static boolean FLYWEIGHT_SUPPORT = Configuration.getBooleanConfigParameter("flyweightSupport", true);
public static boolean FLYWEIGHT_SUPPORT = true;

/**
* Tentative switch to activate the concurrent build behavior.
Expand Down
47 changes: 46 additions & 1 deletion test/src/test/java/hudson/model/QueueTest.java
Expand Up @@ -353,6 +353,49 @@ public void testFlyweightTasksWithoutMasterExecutors() throws Exception {
assertEquals(1, runs.size());
assertEquals("slave0", runs.get(0).getBuiltOnStr());
}

@Issue("JENKINS-10944")
@Test public void flyweightTasksBlockedByShutdown() throws Exception {
r.jenkins.doQuietDown(true, 0);
AtomicInteger cnt = new AtomicInteger();
TestFlyweightTask task = new TestFlyweightTask(cnt, null);
assertTrue(Queue.isBlockedByShutdown(task));
r.jenkins.getQueue().schedule2(task, 0);
r.jenkins.getQueue().maintain();
r.jenkins.doCancelQuietDown();
assertFalse(Queue.isBlockedByShutdown(task));
r.waitUntilNoActivity();
assertEquals(1, cnt.get());
assert task.exec instanceof OneOffExecutor : task.exec;
}

@Issue("JENKINS-24519")
@Test public void flyweightTasksBlockedBySlave() throws Exception {
Label label = Label.get("myslave");
AtomicInteger cnt = new AtomicInteger();
TestFlyweightTask task = new TestFlyweightTask(cnt, label);
r.jenkins.getQueue().schedule2(task, 0);
r.jenkins.getQueue().maintain();
r.createSlave(label);
r.waitUntilNoActivity();
assertEquals(1, cnt.get());
assert task.exec instanceof OneOffExecutor : task.exec;
}

private static class TestFlyweightTask extends TestTask implements Queue.FlyweightTask {
Executor exec;
private final Label assignedLabel;
TestFlyweightTask(AtomicInteger cnt, Label assignedLabel) {
super(cnt);
this.assignedLabel = assignedLabel;
}
@Override protected void doRun() {
exec = Executor.currentExecutor();
}
@Override public Label getAssignedLabel() {
return assignedLabel;
}
}

public void testTaskEquality() throws Exception {
AtomicInteger cnt = new AtomicInteger();
Expand All @@ -364,7 +407,7 @@ public void testTaskEquality() throws Exception {
waitUntilNoActivity();
assertEquals(1, cnt.get());
}
private static final class TestTask extends AbstractQueueTask {
private static class TestTask extends AbstractQueueTask {
private final AtomicInteger cnt;
TestTask(AtomicInteger cnt) {
this.cnt = cnt;
Expand All @@ -387,11 +430,13 @@ private static final class TestTask extends AbstractQueueTask {
@Override public Node getLastBuiltOn() {return null;}
@Override public long getEstimatedDuration() {return -1;}
@Override public ResourceList getResourceList() {return new ResourceList();}
protected void doRun() {}
@Override public Executable createExecutable() throws IOException {
return new Executable() {
@Override public SubTask getParent() {return TestTask.this;}
@Override public long getEstimatedDuration() {return -1;}
@Override public void run() {
doRun();
cnt.incrementAndGet();
}
};
Expand Down

0 comments on commit ff26bb8

Please sign in to comment.