Skip to content

Commit

Permalink
[FIXED JENKINS-47438] Keep track of recent approvals to prevent race …
Browse files Browse the repository at this point in the history
…conditions
  • Loading branch information
stephenc committed Oct 15, 2017
1 parent 9b3018f commit b8b07c1
Showing 1 changed file with 51 additions and 1 deletion.
Expand Up @@ -32,6 +32,14 @@
import hudson.model.Queue;
import hudson.model.queue.CauseOfBlockage;
import hudson.model.queue.QueueTaskDispatcher;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import jenkins.model.Jenkins;

/**
Expand All @@ -40,16 +48,48 @@
@SuppressWarnings("unused") // instantiated by Jenkins
@Extension
public class ThrottleComputationQueueTaskDispatcher extends QueueTaskDispatcher {

private static final long ONE_SECOND_OF_NANOS = TimeUnit.SECONDS.toNanos(1);
private static int LIMIT = Math.max(1,
Math.min(
Integer.getInteger(ThrottleComputationQueueTaskDispatcher.class.getName() + ".LIMIT", 5),
Runtime.getRuntime().availableProcessors() * 4
)
);
private final List<NonBlockedDetails> nonBlocked = new ArrayList<>();

/**
* {@inheritDoc}
*/
@Override
public CauseOfBlockage canRun(Queue.Item item) {
if (item.task instanceof ComputedFolder) {
if (indexingCount() > 5) {
long now = System.nanoTime();
int approvedCount;
boolean found;
synchronized (nonBlocked) {
approvedCount = 0;
found = false;
for (Iterator<NonBlockedDetails> i = nonBlocked.iterator(); i.hasNext(); ) {
NonBlockedDetails details = i.next();
Queue.Item task = details.task.get();
if (task == null) {
i.remove();
} else if (now - details.when > ONE_SECOND_OF_NANOS) {
i.remove();
} else {
approvedCount++;
found = found || task == item;
}
}
}
if (!found && indexingCount() + approvedCount > LIMIT) {
// TODO make the limit configurable
return CauseOfBlockage.fromMessage(Messages._ThrottleComputationQueueTaskDispatcher_MaxConcurrentIndexing());
}
synchronized (nonBlocked) {
nonBlocked.add(new NonBlockedDetails(now, item));
}
}
return null;
}
Expand Down Expand Up @@ -92,4 +132,14 @@ public int indexingCount(@CheckForNull Node node) {
return result;
}

private static class NonBlockedDetails {
private final long when;
private final WeakReference<Queue.Item> task;

public NonBlockedDetails(long when, Queue.Item task) {
this.when = when;
this.task = new WeakReference<Queue.Item>(task);
}
}

}

0 comments on commit b8b07c1

Please sign in to comment.