use of org.jenkinsci.plugins.workflow.graphanalysis.LinearBlockHoppingScanner in project workflow-cps-plugin by jenkinsci.
the class CpsBodyExecution method getCurrentExecutions.
@Override
public Collection<StepExecution> getCurrentExecutions() {
CpsThread t;
synchronized (this) {
t = thread;
if (t == null) {
return Collections.emptySet();
}
}
final SettableFuture<Collection<StepExecution>> result = SettableFuture.create();
t.getExecution().runInCpsVmThread(new FutureCallback<CpsThreadGroup>() {
@Override
public void onSuccess(CpsThreadGroup g) {
try {
List<StepExecution> executions = new ArrayList<>();
// cf. trick in CpsFlowExecution.getCurrentExecutions(true)
Map<FlowHead, CpsThread> m = new LinkedHashMap<>();
for (CpsThread t : g.threads.values()) {
m.put(t.head, t);
}
for (CpsThread t : m.values()) {
// TODO seems cumbersome to have to go through the flow graph to find out whether a head is a descendant of ours, yet FlowHead does not seem to retain a parent field
LinearBlockHoppingScanner scanner = new LinearBlockHoppingScanner();
scanner.setup(t.head.get());
for (FlowNode node : scanner) {
if (node.getId().equals(startNodeId)) {
// this head is inside this body execution
StepExecution execution = t.getStep();
if (execution != null) {
executions.add(execution);
}
break;
}
}
}
result.set(executions);
} catch (Exception x) {
result.setException(x);
}
}
@Override
public void onFailure(Throwable t) {
result.setException(t);
}
});
try {
return result.get(1, TimeUnit.MINUTES);
} catch (ExecutionException | InterruptedException | TimeoutException x) {
// TODO access to CpsThreadGroup.threads must be restricted to the CPS VM thread, but the API signature does not allow us to return a ListenableFuture or throw checked exceptions
throw new RuntimeException(x);
}
}
use of org.jenkinsci.plugins.workflow.graphanalysis.LinearBlockHoppingScanner in project workflow-cps-plugin by jenkinsci.
the class CpsBodyExecution method cancel.
@Override
public boolean cancel(final CauseOfInterruption... causes) {
// 'stopped' and 'thread' are updated atomically
CpsThread t;
synchronized (this) {
// already complete
if (isDone())
return false;
// TODO should perhaps rather override cancel(Throwable) and make this overload just delegate to that one
stopped = new FlowInterruptedException(Result.ABORTED, causes);
t = this.thread;
}
if (t != null) {
t.getExecution().runInCpsVmThread(new FutureCallback<CpsThreadGroup>() {
@Override
public void onSuccess(CpsThreadGroup g) {
// Similar to getCurrentExecutions but we want the raw CpsThread, not a StepExecution; cf. CpsFlowExecution.interrupt
Map<FlowHead, CpsThread> m = new LinkedHashMap<>();
for (CpsThread t : thread.group.threads.values()) {
m.put(t.head, t);
}
for (CpsThread t : Iterators.reverse(ImmutableList.copyOf(m.values()))) {
LinearBlockHoppingScanner scanner = new LinearBlockHoppingScanner();
scanner.setup(t.head.get());
for (FlowNode node : scanner) {
if (node.getId().equals(startNodeId)) {
t.stop(stopped);
break;
}
}
}
}
@Override
public void onFailure(Throwable t) {
LOGGER.log(Level.WARNING, "could not cancel " + context + " with " + Arrays.toString(causes), t);
}
});
} else {
// if it hasn't begun executing, we'll stop it when
// it begins.
}
return true;
}
Aggregations