public @Nonnull CpsBodyInvoker newBodyInvoker(@Nonnull BodyReference body) { return new CpsBodyInvoker(this,body); }
/** * Evaluates the body but grow the {@link FlowNode}s on the same head as the current thread. * * The net effect is as if the body evaluation happens in the same thread as in the caller thread. */ @CpsVmThreadOnly /*package*/ void launch(CpsThread currentThread) { launch(currentThread, currentThread.head); }
@Override public boolean start() throws Exception { TaskAction taskAction = new TaskActionImpl(node, step.name); StepContext context = this.getContext(); if (context.hasBody()) { ((CpsBodyInvoker) context.newBodyInvoker()) .withStartAction(taskAction) .withCallback(new TaskBodyExecutionWrapper(taskAction, context)) .withDisplayName(step.name).start(); } else { LOG.warning("Task pipeline step without body is deprecated and " + "may be subject for removal in a future release"); node.addAction(taskAction); getContext().onSuccess(null); } node.addAction(new LabelAction(step.name)); if (node.getAction(TimingAction.class) == null) { node.addAction(new TimingAction()); } return false; }
@Override public boolean start() throws Exception { CpsStepContext cps = (CpsStepContext) getContext(); if (parallelStep.closures.isEmpty()) { cps.get(TaskListener.class).getLogger().println("No branches to run"); cps.onSuccess(Collections.<String,Object>emptyMap()); return true; } CpsThread t = CpsThread.current(); ResultHandler r = new ResultHandler(cps, this, parallelStep.isFailFast()); for (Entry<String,Closure> e : parallelStep.closures.entrySet()) { BodyExecution body = cps.newBodyInvoker(t.getGroup().export(e.getValue())) .withStartAction(new ParallelLabelAction(e.getKey())) .withCallback(r.callbackFor(e.getKey())) .start(); bodies.add(body); } return false; }
@Override public boolean start() throws Exception { CpsStepContext cps = (CpsStepContext) getContext(); CpsThread t = CpsThread.current(); CpsFlowExecution execution = t.getExecution(); String text = cwd.child(step.getPath()).readToString(); String clazz = execution.getNextScriptName(step.getPath()); String newText = ReplayAction.replace(execution, clazz); if (newText != null) { listener.getLogger().println("Replacing Groovy text with edited version"); text = newText; } Script script; try { script = execution.getShell().parse(text); } catch (MultipleCompilationErrorsException e) { // Convert to a serializable exception, see JENKINS-40109. throw new CpsCompilationErrorsException(e); } // execute body as another thread that shares the same head as this thread // as the body can pause. cps.newBodyInvoker(t.getGroup().export(script)) .withDisplayName(step.getPath()) .withCallback(BodyExecutionCallback.wrap(cps)) .start(); // when the body is done, the load step is done return false; }
@Override public boolean start() throws Exception { Closure body = ScriptBytecodeAdapter.getMethodPointer(this, "bodyBlock"); CpsStepContext cps = (CpsStepContext) getContext(); CpsThread t = CpsThread.current(); cps.newBodyInvoker(t.getGroup().export(body)) .withCallback(BodyExecutionCallback.wrap(cps)) .start(); return false; } }
@Override public void onSuccess(CpsThreadGroup g) { CpsThread thread = owner.getThread(g); if (thread != null) { launch(thread); } }
private void invokeBody(CpsThread cur) { // prepare enough heads for all the bodies // the first one can reuse the current thread, but other ones need to create new heads // we want to do this first before starting body so that the order of heads preserve // natural ordering. // TODO give this javadocs worth a darn, because this is how we create parallel branches and the docs are cryptic as can be! // Also we need to double-check this logic because this might cause a failure of persistence FlowHead[] heads = new FlowHead[context.bodyInvokers.size()]; for (int i = 0; i < heads.length; i++) { heads[i] = i==0 ? cur.head : cur.head.fork(); } int idx=0; for (CpsBodyInvoker b : context.bodyInvokers) { // don't collect the first head, which is what we borrowed from our parent. FlowHead h = heads[idx]; b.launch(cur, h); context.bodyHeads.add(h.getId()); idx++; } context.bodyInvokers.clear(); }