@SuppressFBWarnings(value = "IS2_INCONSISTENT_SYNC", justification="Storage does not actually NEED to be synchronized but the rest does.") protected synchronized void initializeStorage() throws IOException { storage = createStorage(); heads = new TreeMap<Integer,FlowHead>(); for (Map.Entry<Integer,String> entry : headsSerial.entrySet()) { FlowHead h = new FlowHead(this, entry.getKey()); FlowNode n = storage.getNode(entry.getValue()); if (n != null) { h.setForDeserialize(storage.getNode(entry.getValue())); heads.put(h.getId(), h); } else { throw new IOException("Tried to load head FlowNodes for execution "+this.owner+" but FlowNode was not found in storage for head id:FlowNodeId "+entry.getKey()+":"+entry.getValue()); } } headsSerial = null; startNodes = new Stack<BlockStartNode>(); for (String id : startNodesSerial) { FlowNode node = storage.getNode(id); if (node != null) { startNodes.add((BlockStartNode) storage.getNode(id)); } else { // TODO if possible, consider trying to close out unterminated blocks using heads, to keep existing graph history throw new IOException( "Tried to load startNode FlowNodes for execution "+this.owner+" but FlowNode was not found in storage for FlowNode Id "+id); } } startNodesSerial = null; }
/** Verifies all the universal post-build cleanup was done, regardless of pass/fail state. */ static void verifyCompletedCleanly(Jenkins j, WorkflowRun run) throws Exception { // Assert that we have the appropriate flow graph entries FlowExecution exec = run.getExecution(); List<FlowNode> heads = exec.getCurrentHeads(); Assert.assertEquals(1, heads.size()); verifyNoTasksRunning(j); Assert.assertEquals(0, exec.getCurrentExecutions(false).get().size()); if (exec instanceof CpsFlowExecution) { CpsFlowExecution cpsFlow = (CpsFlowExecution)exec; assert cpsFlow.getStorage() != null; Assert.assertFalse("Should always be able to retrieve script", StringUtils.isEmpty(cpsFlow.getScript())); Assert.assertNull("We should have no Groovy shell left or that's a memory leak", cpsFlow.getShell()); Assert.assertNull("We should have no Groovy shell left or that's a memory leak", cpsFlow.getTrustedShell()); Assert.assertTrue(cpsFlow.done); assert cpsFlow.isComplete(); assert cpsFlow.heads.size() == 1; Map.Entry<Integer, FlowHead> finalHead = cpsFlow.heads.entrySet().iterator().next(); assert finalHead.getValue().get() instanceof FlowEndNode; Assert.assertEquals(cpsFlow.storage.getNode(finalHead.getValue().get().getId()), finalHead.getValue().get()); } verifyExecutionRemoved(run); }
@Override public FlowNode getNode(String id) throws IOException { return storage.getNode(id); }