Skip to content

Commit

Permalink
[JENKINS-25938] Starting to use AsynchronousExecutable.
Browse files Browse the repository at this point in the history
Originally-Committed-As: ee2ca390e73004b411e133c1832b88e977b47f28
  • Loading branch information
jglick committed Mar 20, 2015
1 parent f44f3fc commit 149188b
Showing 1 changed file with 36 additions and 32 deletions.
Expand Up @@ -63,7 +63,10 @@
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.CheckForNull;
Expand All @@ -73,6 +76,8 @@
import jenkins.model.Jenkins;
import jenkins.model.lazy.BuildReference;
import jenkins.model.lazy.LazyBuildMixIn;
import jenkins.model.queue.Executable2;
import jenkins.util.Timer;
import org.jenkinsci.plugins.workflow.actions.LogAction;
import org.jenkinsci.plugins.workflow.flow.FlowDefinition;
import org.jenkinsci.plugins.workflow.flow.FlowExecution;
Expand All @@ -89,7 +94,7 @@

@SuppressWarnings("SynchronizeOnNonFinalField")
@edu.umd.cs.findbugs.annotations.SuppressWarnings("JLM_JSR166_UTILCONCURRENT_MONITORENTER") // completed is an unusual usage
public final class WorkflowRun extends Run<WorkflowJob,WorkflowRun> implements Queue.Executable, LazyBuildMixIn.LazyLoadingRun<WorkflowJob,WorkflowRun> {
public final class WorkflowRun extends Run<WorkflowJob,WorkflowRun> implements Executable2, LazyBuildMixIn.LazyLoadingRun<WorkflowJob,WorkflowRun> {

private static final Logger LOGGER = Logger.getLogger(WorkflowRun.class.getName());

Expand All @@ -108,8 +113,6 @@ public final class WorkflowRun extends Run<WorkflowJob,WorkflowRun> implements Q
};
private transient StreamBuildListener listener;
private transient AtomicBoolean completed;
/** Jenkins instance in effect when {@link #waitForCompletion} was last called. */
private transient Jenkins jenkins;
/** map from node IDs to log positions from which we should copy text */
private Map<String,Long> logsToCopy;

Expand Down Expand Up @@ -158,8 +161,7 @@ public WorkflowRun(WorkflowJob job, File dir) throws IOException {
*/
@Override public void run() {
if (!firstTime) {
waitForCompletion();
return;
throw sleep();
}
// Some code here copied from execute(RunExecution), but subsequently modified quite a bit.
try {
Expand All @@ -183,7 +185,6 @@ public WorkflowRun(WorkflowJob job, File dir) throws IOException {
logsToCopy = new LinkedHashMap<String,Long>();
execution.start();
executionPromise.set(execution);
waitForCompletion();
} catch (Throwable x) {
if (listener == null) {
LOGGER.log(Level.WARNING, this + " failed to start", x);
Expand All @@ -193,38 +194,42 @@ public WorkflowRun(WorkflowJob job, File dir) throws IOException {
setResult(Result.FAILURE);
executionPromise.setException(x);
}
throw sleep();
}

/**
* Sleeps until the run is finished, updating log messages periodically.
*/
void waitForCompletion() {
jenkins = Jenkins.getInstance();
synchronized (completed) {
while (!completed.get()) {
if (jenkins == null || jenkins.isTerminating()) {
LOGGER.log(Level.FINE, "shutting down, breaking waitForCompletion on {0}", this);
// Stop writing content, in case a new set of objects gets loaded after in-VM restart and starts writing to the same file:
listener.closeQuietly();
listener = new StreamBuildListener(new NullStream());
break;
}
private AsynchronousExecution sleep() {
final AsynchronousExecution asynchronousExecution = new AsynchronousExecution() {
@Override public void interrupt() {
try {
completed.wait(1000);
} catch (InterruptedException x) {
try {
execution.interrupt(Result.ABORTED);
} catch (Exception x2) {
LOGGER.log(Level.WARNING, null, x2);
execution.interrupt(Result.ABORTED);
} catch (Exception x2) {
LOGGER.log(Level.WARNING, null, x2);
}
getExecutor().recordCauseOfInterruption(WorkflowRun.this, listener);
}
};
final AtomicReference<ScheduledFuture<?>> copyLogsTask = new AtomicReference<ScheduledFuture<?>>();
copyLogsTask.set(Timer.get().scheduleAtFixedRate(new Runnable() {
@Override public void run() {
synchronized (completed) {
if (completed.get()) {
asynchronousExecution.completed(null);
copyLogsTask.get().cancel(false);
return;
}
Executor exec = Executor.currentExecutor();
if (exec != null) {
exec.recordCauseOfInterruption(this, listener);
Jenkins jenkins = Jenkins.getInstance();
if (jenkins == null || jenkins.isTerminating()) {
LOGGER.log(Level.FINE, "shutting down, breaking waitForCompletion on {0}", this);
// Stop writing content, in case a new set of objects gets loaded after in-VM restart and starts writing to the same file:
listener.closeQuietly();
listener = new StreamBuildListener(new NullStream());
return;
}
copyLogs();
}
copyLogs();
}
}
}, 1, 1, TimeUnit.SECONDS));
return asynchronousExecution;
}

@GuardedBy("completed")
Expand Down Expand Up @@ -421,7 +426,6 @@ private void finish(Result r) {
assert completed != null;
synchronized (completed) {
completed.set(true);
completed.notifyAll();
}
FlowExecutionList.get().unregister(execution.getOwner());
}
Expand Down

0 comments on commit 149188b

Please sign in to comment.