/** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.airavata.workflow.engine.interpretor; import com.google.common.eventbus.Subscribe; import org.apache.airavata.common.exception.AiravataException; import org.apache.airavata.common.exception.ApplicationSettingsException; import org.apache.airavata.common.utils.AiravataUtils; import org.apache.airavata.common.utils.ServerSettings; import org.apache.airavata.common.utils.StringUtil; import org.apache.airavata.common.utils.XMLUtil; import org.apache.airavata.common.utils.listener.AbstractActivityListener; import org.apache.airavata.messaging.core.MessageContext; import org.apache.airavata.messaging.core.Publisher; import org.apache.airavata.model.application.io.OutputDataObjectType; import org.apache.airavata.model.messaging.event.*; import org.apache.airavata.model.process.ProcessModel; import org.apache.airavata.model.status.ExperimentState; import org.apache.airavata.model.status.ProcessState; import org.apache.airavata.model.util.ExperimentModelUtil; import org.apache.airavata.model.experiment.*; import org.apache.airavata.orchestrator.cpi.OrchestratorService; import org.apache.airavata.registry.core.experiment.catalog.impl.RegistryFactory; import org.apache.airavata.registry.cpi.ExpCatChildDataType; import org.apache.airavata.registry.cpi.ExperimentCatalog; import org.apache.airavata.registry.cpi.ExperimentCatalogModelType; import org.apache.airavata.registry.cpi.RegistryException; import org.apache.airavata.workflow.engine.invoker.DynamicInvoker; import org.apache.airavata.workflow.engine.invoker.Invoker; import org.apache.airavata.workflow.engine.util.AmazonUtil; import org.apache.airavata.workflow.engine.util.InterpreterUtil; import org.apache.airavata.workflow.engine.util.ProxyMonitorPublisher; import org.apache.airavata.workflow.model.component.Component; import org.apache.airavata.workflow.model.component.amazon.InstanceComponent; import org.apache.airavata.workflow.model.component.amazon.TerminateInstanceComponent; import org.apache.airavata.workflow.model.component.dynamic.DynamicComponent; import org.apache.airavata.workflow.model.component.system.*; import org.apache.airavata.workflow.model.component.ws.WSComponent; import org.apache.airavata.workflow.model.exceptions.WorkflowException; import org.apache.airavata.workflow.model.exceptions.WorkflowRuntimeException; import org.apache.airavata.workflow.model.graph.ControlPort; import org.apache.airavata.workflow.model.graph.DataPort; import org.apache.airavata.workflow.model.graph.Node; import org.apache.airavata.workflow.model.graph.Node.NodeExecutionState; import org.apache.airavata.workflow.model.graph.dynamic.BasicTypeMapping; import org.apache.airavata.workflow.model.graph.dynamic.DynamicNode; import org.apache.airavata.workflow.model.graph.impl.EdgeImpl; import org.apache.airavata.workflow.model.graph.impl.NodeImpl; import org.apache.airavata.workflow.model.graph.subworkflow.SubWorkflowNode; import org.apache.airavata.workflow.model.graph.system.*; import org.apache.airavata.workflow.model.graph.ws.WSGraph; import org.apache.airavata.workflow.model.graph.ws.WSNode; import org.apache.airavata.workflow.model.graph.ws.WSPort; import org.apache.airavata.workflow.model.wf.Workflow; import org.apache.airavata.workflow.model.wf.WorkflowExecutionState; import org.apache.thrift.TException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import java.net.URL; import java.sql.Timestamp; import java.util.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; public class WorkflowInterpreter implements AbstractActivityListener{ private static final Logger log = LoggerFactory.getLogger(WorkflowInterpreter.class); public static final String WORKFLOW_STARTED = "Workflow Running"; public static final String WORKFLOW_FINISHED = "Workflow Finished"; private final Publisher publisher; private WorkflowInterpreterConfiguration config; private Map<Node, Invoker> invokerMap = new HashMap<Node, Invoker>(); private List<Node> invokedNode = new ArrayList<Node>(); private WorkflowInterpreterInteractor interactor; private Map<Node,ProcessModel> nodeInstanceList; private ExperimentModel experiment; private ExperimentCatalog experimentCatalog; public void setGatewayId(String gatewayId) { this.gatewayId = gatewayId; } public String getGatewayId() { return gatewayId; } private String gatewayId; private OrchestratorService.Client orchestratorClient; private Map<String, Node> awaitingTasks; private Map<Node, Map<String,String>> nodeOutputData; public static ThreadLocal<WorkflowInterpreterConfiguration> workflowInterpreterConfigurationThreadLocal = new ThreadLocal<WorkflowInterpreterConfiguration>(); private String credentialStoreToken; /** * @param experiment * @param credentialStoreToken * @param config * @param orchestratorClient */ public WorkflowInterpreter(ExperimentModel experiment, String credentialStoreToken, WorkflowInterpreterConfiguration config, OrchestratorService.Client orchestratorClient, Publisher publisher) { this.setConfig(config); this.setExperiment(experiment); this.setCredentialStoreToken(credentialStoreToken); this.interactor = new SSWorkflowInterpreterInteractorImpl(); this.orchestratorClient = orchestratorClient; this.publisher = publisher; // if gateway id is not set, we will get it from airavata server properties if (gatewayId == null){ try { gatewayId = ServerSettings.getDefaultUserGateway(); } catch (ApplicationSettingsException e) { log.error("error while reading airavata-server properties..", e); } } //TODO set act of provenance nodeInstanceList=new HashMap<Node, WorkflowNodeDetails>(); setWorkflowInterpreterConfigurationThreadLocal(config); awaitingTasks = new HashMap<String, Node>(); nodeOutputData = new HashMap<Node, Map<String,String>>(); ProxyMonitorPublisher.registerListener(this); } public WorkflowInterpreterInteractor getInteractor(){ return this.interactor; } private void notifyViaInteractor(WorkflowExecutionMessage messageType, Object data) { interactor.notify(messageType, config, data); } private Object getInputViaInteractor(WorkflowExecutionMessage messageType, Object data) throws Exception { return interactor.retrieveData(messageType, config, data); } private ExperimentCatalog getExperimentCatalog() throws RegistryException{ if (experimentCatalog ==null){ experimentCatalog = RegistryFactory.getDefaultExpCatalog(); } return experimentCatalog; // return new TmpRegistry(); } private void updateWorkflowNodeStatus(WorkflowNodeDetails node, WorkflowNodeState state) throws RegistryException{ WorkflowNodeStatus status = ExperimentModelUtil.createWorkflowNodeStatus(state); node.setWorkflowNodeStatus(status); getExperimentCatalog().update(ExperimentCatalogModelType.WORKFLOW_NODE_STATUS, status, node.getNodeInstanceId()); } private void updateExperimentStatus(ExperimentState state){ // node.setWorkflowNodeStatus(ExperimentModelUtil.createWorkflowNodeStatus(state)); //TODO trigger node status update } /** * @throws WorkflowException * @throws RegistryException */ public void scheduleDynamically() throws WorkflowException, RegistryException, AiravataException { try { this.getWorkflow().setExecutionState(WorkflowExecutionState.RUNNING); ArrayList<Node> inputNodes = this.getInputNodesDynamically(); List<InputDataObjectType> experimentInputs = experiment.getExperimentInputs(); Map<String,String> inputDataStrings=new HashMap<String, String>(); for (InputDataObjectType dataObjectType : experimentInputs) { inputDataStrings.put(dataObjectType.getName(), dataObjectType.getValue()); } for (Node node : inputNodes) { publishNodeStatusChange(WorkflowNodeState.EXECUTING,node.getID(),experiment.getExperimentID()); if (inputDataStrings.containsKey(node.getID())){ ((InputNode)node).setDefaultValue(inputDataStrings.get(node.getID())); } else { log.warn("value for node not found "+node.getName()); } } for (int i = 0; i < inputNodes.size(); ++i) { Node node = inputNodes.get(i); invokedNode.add(node); node.setState(NodeExecutionState.FINISHED); publishNodeStatusChange(WorkflowNodeState.INVOKED, node.getID(), experiment.getExperimentID()); notifyViaInteractor(WorkflowExecutionMessage.NODE_STATE_CHANGED, null); String portId= ((InputNode) node).getID(); Object portValue = ((InputNode) node).getDefaultValue(); DataType dataType = ((InputNode) node).getDataType(); //Saving workflow input Node data before running the workflow WorkflowNodeDetails workflowNode = createWorkflowNodeDetails(node); InputDataObjectType elem = new InputDataObjectType(); elem.setName(portId); elem.setValue(portValue == null ? null : portValue.toString()); elem.setType(dataType); workflowNode.addToNodeInputs(elem); getExperimentCatalog().update(ExperimentCatalogModelType.WORKFLOW_NODE_DETAIL, workflowNode, workflowNode.getNodeInstanceId()); updateWorkflowNodeStatus(workflowNode, WorkflowNodeState.COMPLETED); publishNodeStatusChange(WorkflowNodeState.COMPLETED, node.getID(), experiment.getExperimentID()); } while (this.getWorkflow().getExecutionState() != WorkflowExecutionState.STOPPED) { ArrayList<Thread> threadList = new ArrayList<Thread>(); if (getRemainNodesDynamically() == 0) { notifyViaInteractor(WorkflowExecutionMessage.EXECUTION_STATE_CHANGED, WorkflowExecutionState.STOPPED); } // ok we have paused sleep if (this.getWorkflow().getExecutionState() == WorkflowExecutionState.PAUSED) { log.info("Workflow execution "+experiment.getExperimentID()+" is paused."); while (this.getWorkflow().getExecutionState() == WorkflowExecutionState.PAUSED) { try { Thread.sleep(400); } catch (InterruptedException e) { log.error(e.getMessage(), e); } } if (this.getWorkflow().getExecutionState() == WorkflowExecutionState.STOPPED) { continue; } log.info("Workflow execution "+experiment.getExperimentID()+" is resumed."); } // get task list and execute them ArrayList<Node> readyNodes = this.getReadyNodesDynamically(); for (final Node node : readyNodes) { if (node.isBreak()) { this.notifyPause(); break; } if (this.getWorkflow().getExecutionState() == WorkflowExecutionState.PAUSED || this.getWorkflow().getExecutionState() == WorkflowExecutionState.STOPPED) { break; } WorkflowNodeDetails workflowNodeDetails = createWorkflowNodeDetails(node); // Since this is an independent node execution we can run these nodes in separate threads. Thread th = new Thread() { public synchronized void run() { try { executeDynamically(node); } catch (WorkflowException e) { log.error("Error execution workflow Node : " + node.getID()); return; } catch (TException e) { log.error(e.getMessage(), e); } catch (RegistryException e) { log.error(e.getMessage(), e); } catch (AiravataException e) { log.error(e.getMessage(), e); } } }; updateWorkflowNodeStatus(workflowNodeDetails, WorkflowNodeState.INVOKED); publishNodeStatusChange(WorkflowNodeState.INVOKED, node.getID(), experiment.getExperimentID()); threadList.add(th); th.start(); if (this.getWorkflow().getExecutionState() == WorkflowExecutionState.STEP) { this.getWorkflow().setExecutionState(WorkflowExecutionState.PAUSED); //TODO update experiment state to suspend break; } } //This thread waits until parallel nodes get finished to send the outputs dynamically. for(Thread th:threadList){ try { th.join(); } catch (InterruptedException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } } // Above statement set the nodeCount back to 0. // TODO commented this for foreach, fix this. sendOutputsDynamically(); // Dry run sleep a lil bit to release load if (readyNodes.size() == 0) { // when there are no ready nodes and no running nodes // and there are failed nodes then workflow is stuck because // of failure // so we should pause the execution if (InterpreterUtil.getRunningNodeCountDynamically(this.getGraph()) == 0 /**&& InterpreterUtil.getFailedNodeCountDynamically(this.getGraph()) != 0**/) { //Since airavata only support workflow interpreter server mode we do not want to keep thread in sleep mode // continuously, so we make the workflow stop when there's nothing to do. this.getWorkflow().setExecutionState(WorkflowExecutionState.STOPPED); } try { Thread.sleep(400); } catch (InterruptedException e) { log.error("Workflow Excecution is interrupted !"); return; } } } if (InterpreterUtil.getFailedNodeCountDynamically(this.getGraph()) == 0) { if (this.config.isActOnProvenance()) { try { // this.getConfig().getConfiguration().getAiravataAPI().getProvenanceManager().setWorkflowInstanceStatus( // this.config.getTopic(), this.config.getTopic(), State.FINISHED); updateExperimentStatus(ExperimentState.COMPLETED); } catch (Exception e) { throw new WorkflowException(e); } // System.out.println(this.config.getConfiguration().getJcrComponentRegistry().getExperimentCatalog().getWorkflowStatus(this.topic)); } } else { if (this.config.isActOnProvenance()) { // this.getConfig().getConfiguration().getAiravataAPI().getProvenanceManager(). // setWorkflowInstanceStatus(this.config.getTopic(),this.config.getTopic(), State.FAILED); updateExperimentStatus(ExperimentState.FAILED); } } UUID uuid = UUID.randomUUID(); notifyViaInteractor(WorkflowExecutionMessage.EXECUTION_TASK_START, new WorkflowInterpreterInteractor.TaskNotification("Stop Workflow", "Cleaning up resources for Workflow", uuid.toString())); // Send Notification for output values finish(); // Sleep to provide for notification delay try { Thread.sleep(1000); } catch (InterruptedException e) { log.error(e.getMessage(), e); } notifyViaInteractor(WorkflowExecutionMessage.EXECUTION_TASK_END, new WorkflowInterpreterInteractor.TaskNotification("Stop Workflow", "Cleaning up resources for Workflow", uuid.toString())); } catch (RuntimeException e) { // we reset all the state cleanup(); raiseException(e); } finally{ cleanup(); this.getWorkflow().setExecutionState(WorkflowExecutionState.NONE); ExperimentStatusChangeEvent event = new ExperimentStatusChangeEvent(ExperimentState.COMPLETED, experiment.getExperimentId(), gatewayId); MessageContext msgCtx = new MessageContext(event, MessageType.EXPERIMENT, AiravataUtils.getId("EXPERIMENT"), gatewayId); msgCtx.setUpdatedTime(new Timestamp(Calendar.getInstance().getTimeInMillis())); publisher.publish(msgCtx); } } private void publishNodeStatusChange(ProcessState state, String nodeId , String expId) throws AiravataException { if (publisher != null) { MessageContext msgCtx = new MessageContext(new ProcessStatusChangeEvent(state, new ProcessIdentifier(nodeId, expId, gatewayId)), MessageType.PROCESS, AiravataUtils.getId("NODE"), gatewayId); msgCtx.setUpdatedTime(new Timestamp(Calendar.getInstance().getTimeInMillis())); publisher.publish(msgCtx); } else { log.warn("Failed to publish workflow status change, publisher is null"); } } private WorkflowNodeDetails createWorkflowNodeDetails(Node node) throws RegistryException { WorkflowNodeDetails workflowNode = ExperimentModelUtil.createWorkflowNode(node.getName(), null); ExecutionUnit executionUnit = ExecutionUnit.APPLICATION; String executionData = null; if (node instanceof InputNode){ executionUnit = ExecutionUnit.INPUT; } else if (node instanceof OutputNode){ executionUnit = ExecutionUnit.OUTPUT; } if (node instanceof WSNode){ executionUnit = ExecutionUnit.APPLICATION; executionData = ((WSNode)node).getComponent().getApplication().getApplicationId(); } workflowNode.setExecutionUnit(executionUnit); workflowNode.setExecutionUnitData(executionData); workflowNode.setNodeInstanceId((String) getExperimentCatalog().add(ExpCatChildDataType.WORKFLOW_NODE_DETAIL, workflowNode, getExperiment().getExperimentID())); nodeInstanceList.put(node, workflowNode); setupNodeDetailsInput(node, workflowNode); return workflowNode; } /** * @param e */ public void raiseException(Throwable e) { notifyViaInteractor(WorkflowExecutionMessage.EXECUTION_ERROR, e); } /** * */ private void notifyPause() { if (this.getWorkflow().getExecutionState() != WorkflowExecutionState.RUNNING && this.getWorkflow().getExecutionState() != WorkflowExecutionState.STEP) { throw new WorkflowRuntimeException("Cannot pause when not running"); } notifyViaInteractor(WorkflowExecutionMessage.EXECUTION_STATE_CHANGED, WorkflowExecutionState.PAUSED); } public void cleanup() { this.getWorkflow().setExecutionState(WorkflowExecutionState.STOPPED); notifyViaInteractor(WorkflowExecutionMessage.EXECUTION_CLEANUP, null); } private void sendOutputsDynamically() throws WorkflowException, RegistryException, AiravataException { ArrayList<Node> outputNodes = getReadyOutputNodesDynamically(); if (outputNodes.size() != 0) { LinkedList<Object> outputValues = new LinkedList<Object>(); LinkedList<String> outputKeywords = new LinkedList<String>(); for (Node node : outputNodes) { // Change it to processing state so we will not pic it up in the // next run // even if the next run runs before the notification arrives WorkflowNodeDetails workflowNodeDetails = createWorkflowNodeDetails(node); // workflowNodeDetails.setNodeInstanceId((String)getExperimentCatalog().add(ChildDataType.WORKFLOW_NODE_DETAIL, workflowNodeDetails, getExperiment().getExperimentID())); node.setState(NodeExecutionState.EXECUTING); updateWorkflowNodeStatus(workflowNodeDetails, WorkflowNodeState.EXECUTING); publishNodeStatusChange(WorkflowNodeState.EXECUTING, node.getID(), experiment.getExperimentID()); // OutputNode node = (OutputNode) outputNode; List<DataPort> inputPorts = node.getInputPorts(); for (DataPort dataPort : inputPorts) { Object val = InterpreterUtil.findInputFromPort(dataPort); if (null == val) { throw new WorkFlowInterpreterException("Unable to find output for the node:" + node.getID()); } // This is ok because the outputnodes always got only one // input if (val instanceof org.xmlpull.v1.builder.XmlElement) { ((OutputNode) node).setDescription(XMLUtil.xmlElementToString((org.xmlpull.v1.builder.XmlElement) val)); } else { ((OutputNode) node).setDescription(val.toString()); } // Saving output Node data in to database // WorkflowNodeType workflowNodeType = new WorkflowNodeType(); // workflowNodeType.setNodeType(WorkflowNodeType.WorkflowNode.OUTPUTNODE); // WorkflowInstanceNode workflowInstanceNode = new WorkflowInstanceNode(new WorkflowExecution(config.getTopic(), config.getTopic()), node.getID()); String portname = node.getName(); String portValue = ((OutputNode) node).getDescription(); // this.getConfig().getConfiguration().getAiravataAPI().getProvenanceManager().setWorkflowInstanceNodeOutput(workflowInstanceNode, portname + "=" + portValue); // this.getConfig().getConfiguration().getAiravataAPI().getProvenanceManager().setWorkflowNodeType(workflowInstanceNode, workflowNodeType); OutputDataObjectType elem = new OutputDataObjectType(); elem.setName(portname); elem.setValue(portValue); workflowNodeDetails.addToNodeOutputs(elem); getExperimentCatalog().update(ExperimentCatalogModelType.WORKFLOW_NODE_DETAIL, workflowNodeDetails, workflowNodeDetails.getNodeInstanceId()); if (this.config.isActOnProvenance()) { //TODO do provanence thing // try { // if (val instanceof String) { // this.getConfig().getConfiguration().getAiravataAPI().getProvenanceManager() // .saveWorkflowExecutionOutput(this.config.getTopic(), node.getName(), val.toString()); // } else if (val instanceof org.xmlpull.v1.builder.XmlElement) { // this.getConfig() // .getConfiguration() // .getAiravataAPI().getProvenanceManager() // .saveWorkflowExecutionOutput(this.config.getTopic(), node.getName(), // XMLUtil.xmlElementToString((org.xmlpull.v1.builder.XmlElement) val)); // } // outputValues.add(val); // outputKeywords.add(dataPort.getID()); // } catch (AiravataAPIInvocationException e) { // e.printStackTrace(); // To change body of catch // // statement use File | // // Settings | File // // Templates. // } } } node.setState(NodeExecutionState.FINISHED); publishNodeStatusChange(WorkflowNodeState.COMPLETED, node.getID(), experiment.getExperimentID()); updateWorkflowNodeStatus(workflowNodeDetails, WorkflowNodeState.COMPLETED); notifyViaInteractor(WorkflowExecutionMessage.NODE_STATE_CHANGED, null); } } } private void finish() throws WorkflowException, RegistryException { ArrayList<Node> outoutNodes = new ArrayList<Node>(); List<NodeImpl> nodes = this.getGraph().getNodes(); for (Node node : nodes) { if (node instanceof OutputNode) { if (node.getInputPort(0).getFromNode().getState()== NodeExecutionState.FINISHED) { outoutNodes.add(node); } else { // The workflow is incomplete so return without sending // workflowFinished return; } } } LinkedList<Object> outputValues = new LinkedList<Object>(); LinkedList<String> outputKeywords = new LinkedList<String>(); for (Node outputNode : outoutNodes) { OutputNode node = (OutputNode) outputNode; List<DataPort> inputPorts = node.getInputPorts(); for (DataPort dataPort : inputPorts) { Object val = InterpreterUtil.findInputFromPort(dataPort, this.invokerMap); ; if (null == val) { throw new WorkFlowInterpreterException("Unable to find output for the node:" + node.getID()); } WorkflowNodeDetails workflowNodeDetails = nodeInstanceList.get(node); OutputDataObjectType elem = new OutputDataObjectType(); elem.setName(node.getName()); elem.setValue(val.toString()); workflowNodeDetails.addToNodeOutputs(elem); try { getExperimentCatalog().update(ExperimentCatalogModelType.WORKFLOW_NODE_DETAIL, workflowNodeDetails, workflowNodeDetails.getNodeInstanceId()); } catch (RegistryException e) { log.error(e.getMessage(), e); } updateWorkflowNodeStatus(workflowNodeDetails, WorkflowNodeState.COMPLETED); } } } private void executeDynamically(final Node node) throws WorkflowException, TException, RegistryException, AiravataException { node.setState(NodeExecutionState.EXECUTING); invokedNode.add(node); updateWorkflowNodeStatus(nodeInstanceList.get(node), WorkflowNodeState.EXECUTING); publishNodeStatusChange(WorkflowNodeState.EXECUTING, node.getID(), experiment.getExperimentID()); Component component = node.getComponent(); if (component instanceof SubWorkflowComponent) { handleSubWorkComponent(node); } else if (component instanceof WSComponent) { handleWSComponent(node); } else if (component instanceof DynamicComponent) { handleDynamicComponent(node); } else if (component instanceof ForEachComponent) { handleForEach(node); } else if (component instanceof IfComponent) { handleIf(node); } else if (component instanceof EndifComponent) { handleEndIf(node); } else if (component instanceof DoWhileComponent) { handleDoWhile(node); }else if (component instanceof EndDoWhileComponent) { // Component is handled in DoWhileHandler after eval condition } else if (component instanceof InstanceComponent) { handleAmazonInstance(node); } else if (component instanceof TerminateInstanceComponent) { handleAmazonTerminateInstance(node); } else { throw new WorkFlowInterpreterException("Encountered Node that cannot be executed:" + node); } } private void handleAmazonTerminateInstance(final Node node) throws WorkflowException { Object inputVal = InterpreterUtil.findInputFromPort(node.getInputPort(0), this.invokerMap); String instanceId = inputVal.toString(); /* * Terminate instance */ AmazonUtil.terminateInstances(instanceId); // set color to done node.setState(NodeExecutionState.FINISHED); } private void handleAmazonInstance(final Node node) { //TODO for (ControlPort ports : node.getControlOutPorts()) { ports.setConditionMet(true); } } private void handleDoWhile(final Node node) { // Executor thread is shutdown inside as thread gets killed when you // shutdown ExecutorService threadExecutor = Executors.newSingleThreadExecutor(); DoWhileHandler doWhileHandler = new DoWhileHandler((DoWhileNode) node, this.invokerMap, getWaitingNodesDynamically(), getFinishedNodesDynamically(), this, threadExecutor); threadExecutor.submit(doWhileHandler); } private void handleSubWorkComponent(Node node) throws WorkflowException { //TODO we will not support this in 0.13 notifyViaInteractor(WorkflowExecutionMessage.OPEN_SUBWORKFLOW, node); // setting the inputs Workflow subWorkflow = ((SubWorkflowNode) node).getWorkflow(); ArrayList<Node> subWorkflowInputNodes = getInputNodes(subWorkflow); List<DataPort> inputPorts = node.getInputPorts(); for (DataPort port : inputPorts) { Object inputVal = InterpreterUtil.findInputFromPort(port, this.invokerMap); if (null == inputVal) { throw new WorkFlowInterpreterException("Unable to find inputs for the subworkflow node node:" + node.getID()); } for (Iterator<Node> iterator = subWorkflowInputNodes.iterator(); iterator.hasNext();) { InputNode inputNode = (InputNode) iterator.next(); if (inputNode.getName().equals(port.getName())) { inputNode.setDefaultValue(inputVal); } } } for (Iterator<Node> iterator = subWorkflowInputNodes.iterator(); iterator.hasNext();) { InputNode inputNode = (InputNode) iterator.next(); if (inputNode.getDefaultValue() == null) { throw new WorkFlowInterpreterException("Input not set for :" + inputNode.getID()); } } try { WorkflowInterpreter subworkflowInterpreter = (WorkflowInterpreter) getInputViaInteractor( WorkflowExecutionMessage.INPUT_WORKFLOWINTERPRETER_FOR_WORKFLOW, subWorkflow); subworkflowInterpreter.scheduleDynamically(); } catch (Exception e) { throw new WorkflowException(e); } } private OrchestratorService.Client getOrchestratorClient(){ return orchestratorClient; } protected void handleWSComponent(Node node) throws WorkflowException, TException, RegistryException { TaskDetails taskDetails = createTaskDetails(node); log.debug("Launching task , node = " + node.getName() + " node id = " + node.getID()); getOrchestratorClient().launchTask(taskDetails.getTaskID(), getCredentialStoreToken()); } private void addToAwaitingTaskList(String taskId, Node node){ synchronized (awaitingTasks) { awaitingTasks.put(taskId, node); } } private boolean isTaskAwaiting(String taskId){ boolean result; synchronized (awaitingTasks) { result = awaitingTasks.containsKey(taskId); } return result; } private Node getAwaitingNodeForTask(String taskId){ Node node; synchronized (awaitingTasks) { node = awaitingTasks.get(taskId); } return node; } private void removeAwaitingTask(String taskId){ synchronized (awaitingTasks) { awaitingTasks.remove(taskId); } } private void handleDynamicComponent(Node node) throws WorkflowException { DynamicComponent dynamicComponent = (DynamicComponent) node.getComponent(); String className = dynamicComponent.getClassName(); String operationName = dynamicComponent.getOperationName(); URL implJarLocation = dynamicComponent.getImplJarLocation(); DynamicNode dynamicNode = (DynamicNode) node; LinkedList<Object> inputs = new LinkedList<Object>(); List<DataPort> inputPorts = dynamicNode.getInputPorts(); for (DataPort dataPort : inputPorts) { Object inputVal = InterpreterUtil.findInputFromPort(dataPort, this.invokerMap); /* * Set type after get input value, and override inputValue if output * type is array */ Node fromNode = dataPort.getFromNode(); DataType type = null; if (fromNode instanceof InputNode) { type = DataType.STRING; } else if (fromNode instanceof ConstantNode) { type = ((ConstantNode) fromNode).getType(); } else if ((dataPort.getFromPort() instanceof WSPort) && BasicTypeMapping.isArrayType(((WSPort) dataPort.getFromPort()).getComponentPort().getElement())) { Invoker fromInvoker = this.invokerMap.get(fromNode); // inputVal = BasicTypeMapping.getOutputArray(XmlConstants.BUILDER.parseFragmentFromString(fromInvoker.getOutputs().toString()), dataPort // .getFromPort().getName(), BasicTypeMapping.getSimpleTypeIndex(((DataPort) dataPort.getFromPort()).getType())); type = ((DataPort) dataPort.getFromPort()).getType(); } else { type = ((DataPort) dataPort.getFromPort()).getType(); } if (null == inputVal) { throw new WorkFlowInterpreterException("Unable to find inputs for the node:" + node.getID()); } // inputs.add(BasicTypeMapping.getObjectOfType(type, inputVal)); } DynamicInvoker dynamicInvoker = new DynamicInvoker(className, implJarLocation, operationName, inputs.toArray()); this.invokerMap.put(node, dynamicInvoker); dynamicInvoker.setup(); dynamicInvoker.invoke(); node.setState(NodeExecutionState.FINISHED); } private void handleForEach(Node node) throws WorkflowException { final ForEachNode forEachNode = (ForEachNode) node; EndForEachNode endForEachNode = null; Collection<Node> repeatNodes = node.getOutputPort(0).getToNodes(); // we will support only one for now if (repeatNodes.size() != 1) { throw new WorkFlowInterpreterException("Only one node allowed inside foreach"); } Iterator<Node> iterator = repeatNodes.iterator(); if (iterator.hasNext()) { Node middleNode = iterator.next(); // forEachNode should point to a WSNode and should have only one // output if ((!(middleNode instanceof WSNode)) && (!(middleNode instanceof SubWorkflowNode))) { throw new WorkFlowInterpreterException("Encountered Node inside foreach that is not a WSNode" + middleNode); } else if (middleNode instanceof SubWorkflowNode) { /* Get the EndforEach Node of the Subworkflow */ Iterator<Node> subWorkflowOut = middleNode.getOutputPort(0).getToNodes().iterator(); while (subWorkflowOut.hasNext()) { Node node2 = subWorkflowOut.next(); if (node2 instanceof EndForEachNode) { endForEachNode = (EndForEachNode) node2; } } final LinkedList<String> listOfValues = new LinkedList<String>(); InterpreterUtil.getInputsForForEachNode(forEachNode, listOfValues, this.invokerMap); final Integer[] inputNumbers = InterpreterUtil.getNumberOfInputsForForEachNode(forEachNode, this.invokerMap); Workflow workflow1 = ((SubWorkflowNode) middleNode).getWorkflow(); List<NodeImpl> nodes = workflow1.getGraph().getNodes(); List<Node> wsNodes = new ArrayList<Node>(); /* Take the List of WSNodes in the subworkflow */ for (NodeImpl subWorkflowNode : nodes) { if (subWorkflowNode instanceof WSNode) { wsNodes.add(subWorkflowNode); } } for (int i = 0; i < wsNodes.size(); i++) { final WSNode node1 = (WSNode) wsNodes.get(i); SystemComponentInvoker systemInvoker = null; List<DataPort> outputPorts1 = node1.getOutputPorts(); List<Node> endForEachNodes = new ArrayList<Node>(); for (DataPort port : outputPorts1) { Iterator<Node> endForEachNodeItr1 = port.getToNodes().iterator(); while (endForEachNodeItr1.hasNext()) { Node node2 = endForEachNodeItr1.next(); if (node2 instanceof EndForEachNode) { endForEachNodes.add(node2); } else if (node2 instanceof OutputNode) { // intentionally left noop } else { throw new WorkFlowInterpreterException("Found More than one node inside foreach"); } } } final List<Node> finalEndForEachNodes = endForEachNodes; Iterator<Node> endForEachNodeItr1 = node1.getOutputPort(0).getToNodes().iterator(); while (endForEachNodeItr1.hasNext()) { Node node2 = endForEachNodeItr1.next(); // Start reading input came for foreach node int parallelRuns = listOfValues.size() * node1.getOutputPorts().size(); if (listOfValues.size() > 0) { forEachNode.setState(NodeExecutionState.EXECUTING); node1.setState(NodeExecutionState.EXECUTING); List<DataPort> outputPorts = node1.getOutputPorts(); final AtomicInteger counter = new AtomicInteger(); for (Node endFor : endForEachNodes) { systemInvoker = new SystemComponentInvoker(); this.invokerMap.put(endFor, systemInvoker); } final Map<Node, Invoker> finalMap = this.invokerMap; new Thread() { @Override public void run() { try { runInThread(listOfValues, forEachNode, node1, finalEndForEachNodes, finalMap, counter, inputNumbers); } catch (WorkflowException e) { log.error(e.getLocalizedMessage(), e); } catch (RegistryException e) { log.error(e.getMessage(), e); } catch (TException e) { log.error(e.getMessage(), e); } } }.start(); while (counter.intValue() < parallelRuns) { try { Thread.sleep(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } // if (!(node2 instanceof OutputNode)) { // listOfValues.removeAll(listOfValues); // String output = (String) systemInvoker.getOutput(node1.getOutputPort(0).getName()); // XmlElement xmlElement = XMLUtil.stringToXmlElement("<result>" + output + "</result>"); // Iterator iterator1 = xmlElement.children().iterator(); // while (iterator1.hasNext()) { // Object next1 = iterator1.next(); // if (next1 instanceof XmlElement) { // listOfValues.add((String) ((XmlElement) next1).children().iterator().next()); // } // } // } } } } // we have finished execution so end foreach is finished // todo this has to be done in a separate thread endForEachNode.setState(NodeExecutionState.FINISHED); middleNode.setState(NodeExecutionState.FINISHED); node.setState(NodeExecutionState.FINISHED); } else { // First node after foreach should end with EndForEachNode List<DataPort> outputPorts1 = middleNode.getOutputPorts(); List<Node> endForEachNodes = new ArrayList<Node>(); for (DataPort port : outputPorts1) { Iterator<Node> endForEachNodeItr1 = port.getToNodes().iterator(); while (endForEachNodeItr1.hasNext()) { Node node2 = endForEachNodeItr1.next(); if (node2 instanceof EndForEachNode) { endForEachNodes.add(node2); } else if (node2 instanceof OutputNode) { // intentionally left noop } else { throw new WorkFlowInterpreterException("Found More than one node inside foreach"); } } } final List<Node> finalEndForEachNodes = endForEachNodes; final Node foreachWSNode = middleNode; final LinkedList<String> listOfValues = new LinkedList<String>(); // Start reading input came for foreach node InterpreterUtil.getInputsForForEachNode(forEachNode, listOfValues, this.invokerMap); final Integer[] inputNumbers = InterpreterUtil.getNumberOfInputsForForEachNode(forEachNode, this.invokerMap); int parallelRuns = createInputValues(listOfValues, inputNumbers).size() * outputPorts1.size(); if (listOfValues.size() > 0) { forEachNode.setState(NodeExecutionState.EXECUTING); foreachWSNode.setState(NodeExecutionState.EXECUTING); List<DataPort> outputPorts = middleNode.getOutputPorts(); final AtomicInteger counter = new AtomicInteger(); for (Node endFor : endForEachNodes) { final SystemComponentInvoker systemInvoker = new SystemComponentInvoker(); this.invokerMap.put(endFor, systemInvoker); } final Map<Node, Invoker> finalInvokerMap = this.invokerMap; new Thread() { @Override public void run() { try { runInThread(listOfValues, forEachNode, foreachWSNode, finalEndForEachNodes, finalInvokerMap, counter, inputNumbers); } catch (WorkflowException e) { log.error(e.getLocalizedMessage(), e); } catch (RegistryException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (TException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }.start(); while (counter.intValue() < parallelRuns) { try { Thread.sleep(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } // we have finished execution so end foreach is finished // todo this has to be done in a separate thread middleNode.setState(NodeExecutionState.FINISHED); for (Node endForEach : endForEachNodes) { endForEach.setState(NodeExecutionState.FINISHED); } } else { throw new WorkFlowInterpreterException("No array values found for foreach"); } } } } private void handleIf(Node node) throws WorkflowException { IfNode ifNode = (IfNode) node; /* * Get all input to check condition */ String booleanExpression = ifNode.getXPath(); if (booleanExpression == null) { throw new WorkFlowInterpreterException("XPath for if cannot be null"); } List<DataPort> inputPorts = node.getInputPorts(); int i = 0; for (DataPort port : inputPorts) { Object inputVal = InterpreterUtil.findInputFromPort(port, this.invokerMap); if (null == inputVal) { throw new WorkFlowInterpreterException("Unable to find inputs for the node:" + node.getID()); } booleanExpression = booleanExpression.replaceAll("\\$" + i, "'" + inputVal + "'"); } // Now the XPath expression try { XPathFactory xpathFact = XPathFactory.newInstance(); XPath xpath = xpathFact.newXPath(); Boolean result = (Boolean) xpath.evaluate(booleanExpression, booleanExpression, XPathConstants.BOOLEAN); /* * Set control port to make execution flow continue according to * condition */ for (ControlPort controlPort : node.getControlOutPorts()) { if (controlPort.getName().equals(IfComponent.TRUE_PORT_NAME)) { controlPort.setConditionMet(result.booleanValue()); } else if (controlPort.getName().equals(IfComponent.FALSE_PORT_NAME)) { controlPort.setConditionMet(!result.booleanValue()); } } node.setState(NodeExecutionState.FINISHED); } catch (XPathExpressionException e) { throw new WorkFlowInterpreterException("Cannot evaluate XPath in If Condition: " + booleanExpression); } } private void handleEndIf(Node node) throws WorkflowException { EndifNode endIfNode = (EndifNode) node; SystemComponentInvoker invoker = new SystemComponentInvoker(); List<DataPort> ports = endIfNode.getOutputPorts(); for (int outputPortIndex = 0, inputPortIndex = 0; outputPortIndex < ports.size(); outputPortIndex++, inputPortIndex = inputPortIndex + 2) { Object inputVal = InterpreterUtil.findInputFromPort(endIfNode.getInputPort(inputPortIndex), this.invokerMap); Object inputVal2 = InterpreterUtil.findInputFromPort(endIfNode.getInputPort(inputPortIndex + 1), this.invokerMap); if ((inputVal == null && inputVal2 == null) || (inputVal != null && inputVal2 != null)) { throw new WorkFlowInterpreterException("EndIf gets wrong input number" + "Port:" + inputPortIndex + " and " + (inputPortIndex + 1)); } Object value = inputVal != null ? inputVal : inputVal2; invoker.addOutput(endIfNode.getOutputPort(outputPortIndex).getID(), value); } this.invokerMap.put(node, invoker); node.setState(NodeExecutionState.FINISHED); } private String createInvokerForEachSingleWSNode(Node foreachWSNode, WSComponent wsComponent) throws WorkflowException, RegistryException, TException { TaskDetails taskDetails = createTaskDetails(foreachWSNode); getOrchestratorClient().launchTask(taskDetails.getTaskID(), getCredentialStoreToken()); return taskDetails.getTaskID(); } private void setupNodeDetailsInput(Node node, WorkflowNodeDetails nodeDetails){ List<DataPort> inputPorts = node.getInputPorts(); for (DataPort dataPort : inputPorts) { Node fromNode = dataPort.getFromNode(); String portInputValue = null; if (fromNode instanceof InputNode){ portInputValue = (String) ((InputNode) fromNode).getDefaultValue(); } else if (fromNode instanceof WSNode){ Map<String, String> outputData = nodeOutputData.get(fromNode); portInputValue = outputData.get(dataPort.getName()); if (portInputValue == null) { portInputValue = outputData.get(dataPort.getEdge(0).getFromPort().getName()); } } // 123456789 InputDataObjectType elem = new InputDataObjectType(); elem.setName(dataPort.getName()); elem.setValue(portInputValue); if (dataPort instanceof WSPort) { WSPort port = (WSPort) dataPort; elem.setInputOrder(port.getComponentPort().getInputOrder()); elem.setApplicationArgument( (port.getComponentPort().getApplicationArgument() != null ? port.getComponentPort().getApplicationArgument() : "")); elem.setType(port.getType()); } nodeDetails.addToNodeInputs(elem); } try { getExperimentCatalog().update(ExperimentCatalogModelType.WORKFLOW_NODE_DETAIL, nodeDetails, nodeDetails.getNodeInstanceId()); } catch (RegistryException e) { log.error(e.getMessage(), e); } } private void setupNodeDetailsOutput(Node node){ WorkflowNodeDetails nodeDetails = nodeInstanceList.get(node); List<DataPort> outputPorts = node.getOutputPorts(); Map<String, String> outputData = nodeOutputData.get(node); for (DataPort dataPort : outputPorts) { String portInputValue = outputData.get(dataPort.getName()); OutputDataObjectType elem = new OutputDataObjectType(); elem.setName(dataPort.getName()); elem.setValue(portInputValue); nodeDetails.addToNodeOutputs(elem); } try { getExperimentCatalog().update(ExperimentCatalogModelType.WORKFLOW_NODE_DETAIL, nodeDetails, nodeDetails.getNodeInstanceId()); } catch (RegistryException e) { log.error(e.getMessage(), e); } } private TaskDetails createTaskDetails(Node node) throws RegistryException { setupNodeDetailsInput(node, nodeInstanceList.get(node)); TaskDetails taskDetails = ExperimentModelUtil.cloneTaskFromWorkflowNodeDetails(experiment, nodeInstanceList.get(node)); taskDetails.setTaskID(getExperimentCatalog().add(ExpCatChildDataType.TASK_DETAIL, taskDetails,nodeInstanceList.get(node).getNodeInstanceId()).toString()); addToAwaitingTaskList(taskDetails.getTaskID(), node); return taskDetails; } private void runInThread(final LinkedList<String> listOfValues, ForEachNode forEachNode, final Node middleNode, List<Node> endForEachNodes, Map<Node, Invoker> tempInvoker, AtomicInteger counter, final Integer[] inputNumber) throws WorkflowException, RegistryException, TException { final LinkedList<String> taskIdList = new LinkedList<String>(); if (inputNumber.length > 1) { List<String> inputValues = createInputValues(listOfValues, inputNumber); for (final Iterator<String> iterator = inputValues.iterator(); iterator.hasNext();) { final String input = iterator.next(); WSComponent wsComponent = (WSComponent) middleNode.getComponent(); final String invoker2 = createInvokerForEachSingleWSNode(middleNode, wsComponent); taskIdList.add(invoker2); try { Thread.sleep(3000); } catch (InterruptedException e) { log.error(e.getLocalizedMessage(), e); } } } else { String invoker = null; for (Iterator<String> iterator = listOfValues.iterator(); iterator.hasNext();) { String input = iterator.next(); WSComponent wsComponent = (WSComponent) middleNode.getComponent(); taskIdList.add(invoker); // find inputs List<DataPort> inputPorts = middleNode.getInputPorts(); // for (DataPort port : inputPorts) { // Object inputVal = InterpreterUtil.findInputFromPort(port, this.invokerMap); // /* // * Handle ForEachNode // */ // Node fromNode = port.getFromNode(); // // if (fromNode instanceof ForEachNode) { // inputVal = WorkflowInputUtil.parseValue((WSComponentPort) port.getComponentPort(), input); // // } // // if (null == inputVal) { // throw new WorkFlowInterpreterException("Unable to find inputs for the node:" + middleNode.getID()); // } // } invoker = createInvokerForEachSingleWSNode(middleNode, wsComponent); } } // String arrayElementName = foreachWSNode.getOperationName() + // "ArrayResponse"; // String outputStr = "<" + arrayElementName + ">"; // invokerMap size and endForEachNodes size can be difference // because we can create endForEachNode with n number of input/output // ports so always have to use // middleNode.getOutputPorts when iterate String[] outputStr = new String[middleNode.getOutputPorts().size()]; int i = 0; for (DataPort port : middleNode.getOutputPorts()) { String outputString = ""; // for (Iterator<Invoker> iterator = taskIdList.iterator(); iterator.hasNext();) { // Invoker workflowInvoker = iterator.next(); // // // / // Object output = workflowInvoker.getOutput(port.getName()); // if (output instanceof org.xmlpull.v1.builder.XmlElement) { // org.xmlpull.v1.builder.XmlElement element = (org.xmlpull.v1.builder.XmlElement) ((org.xmlpull.v1.builder.XmlElement) output).children() // .next(); // outputString += "\n" + XMLUtil.xmlElementToString(element); // } else { // outputString += "\n<value>" + output + "</value>"; // } // counter.incrementAndGet(); // } outputStr[i] = outputString; System.out.println(outputStr[i]); i++; } i = 0; // outputStr += "\n</" + arrayElementName + ">"; int outputPortIndex = 0; for (DataPort port : middleNode.getOutputPorts()) { for (Node endForEachNode : endForEachNodes) { if (tempInvoker.get(endForEachNode) != null) { if (!(endForEachNode instanceof OutputNode)) { ((SystemComponentInvoker) tempInvoker.get(endForEachNode)).addOutput(port.getName(), outputStr[i]); } } outputPortIndex++; } i++; } forEachNode.setState(NodeExecutionState.FINISHED); } private List<String> createInputValues(LinkedList<String> listOfValues, Integer[] inputNumbers) throws WorkflowException { List<String> inputValues = null; try { inputValues = new ArrayList<String>(); if (inputNumbers.length == 1) { return listOfValues; } if (this.config.isRunWithCrossProduct()) { for (int i = 0; i < inputNumbers[0]; i++) { for (int j = 0; j < inputNumbers[1]; j++) { inputValues.add(listOfValues.get(i) + StringUtil.DELIMETER + listOfValues.get(inputNumbers[0] + j)); } } } else { List<String[]> inputList = new ArrayList<String[]>(); int startIndex = 0; for (int input = 0; input < inputNumbers.length; input++) { String[] inputArray = new String[inputNumbers[input]]; for (int travers = 0; travers < inputNumbers[input]; travers++) { inputArray[travers] = listOfValues.get(startIndex++); } inputList.add(inputArray); } int inputSize = 1; for (String[] inputArrays : inputList) { if (inputArrays.length != 1) { inputSize = inputArrays.length; } } List<String[]> finalInputList = new ArrayList<String[]>(); for (String[] inputArrays : inputList) { if (inputArrays.length == 1) { String[] fullArray = new String[inputSize]; for (int i = 0; i < fullArray.length; i++) { fullArray[i] = inputArrays[0]; } finalInputList.add(fullArray); } else { finalInputList.add(inputArrays); } } for (int i = 0; i < inputSize; i++) { String inputValue = ""; for (String[] array : finalInputList) { inputValue = inputValue + StringUtil.DELIMETER + StringUtil.quoteString(array[i]); } inputValue = inputValue.replaceFirst(StringUtil.DELIMETER , ""); inputValues.add(inputValue); } } } catch (ArrayIndexOutOfBoundsException e) { throw new WorkflowException("Wrong number of Inputs to For EachNode"); } return inputValues; } private ArrayList<Node> getReadyOutputNodesDynamically() { ArrayList<Node> list = new ArrayList<Node>(); List<NodeImpl> nodes = this.getGraph().getNodes(); for (Node node : nodes) { if (node instanceof OutputNode && node.getState()==NodeExecutionState.WAITING && node.getInputPort(0).getFromNode().getState()== NodeExecutionState.FINISHED) { list.add(node); } } return list; } private int getRemainNodesDynamically() { return InterpreterUtil.getWaitingNodeCountDynamically(this.getGraph()) + InterpreterUtil.getRunningNodeCountDynamically(this.getGraph()); } private ArrayList<Node> getInputNodesDynamically() { return getInputNodes(this.getWorkflow()); } private ArrayList<Node> getInputNodes(Workflow wf) { ArrayList<Node> list = new ArrayList<Node>(); List<NodeImpl> nodes = wf.getGraph().getNodes(); for (Node node : nodes) { String name = node.getComponent().getName(); if (InputComponent.NAME.equals(name) || ConstantComponent.NAME.equals(name) || S3InputComponent.NAME.equals(name)) { list.add(node); } } return list; } private ArrayList<Node> getReadyNodesDynamically() { ArrayList<Node> list = new ArrayList<Node>(); ArrayList<Node> waiting = InterpreterUtil.getWaitingNodesDynamically(this.getGraph()); // ArrayList<Node> finishedNodes = InterpreterUtil.getFinishedNodesDynamically(this.getGraph()); // This is to support repeat the same application in the workflow. List<String> finishedNodeIds = InterpreterUtil.getFinishedNodesIds(this.getGraph()); for (Node node : waiting) { Component component = node.getComponent(); if (component instanceof WSComponent || component instanceof DynamicComponent || component instanceof SubWorkflowComponent || component instanceof ForEachComponent || component instanceof EndForEachComponent || component instanceof IfComponent || component instanceof InstanceComponent) { /* * Check for control ports from other node */ ControlPort control = node.getControlInPort(); boolean controlDone = true; if (control != null) { for (EdgeImpl edge : control.getEdges()) { controlDone = controlDone && (finishedNodeIds.contains(edge.getFromPort().getNode().getID()) // amazon component use condition met to check // whether the control port is done // FIXME I changed the "||" to a "&&" in the following since thats the only this // that makes sense and if anyone found a scenario it should be otherwise pls fix || ((ControlPort) edge.getFromPort()).isConditionMet()); } } /* * Check for input ports */ List<DataPort> inputPorts = node.getInputPorts(); boolean inputsDone = true; for (DataPort dataPort : inputPorts) { inputsDone = inputsDone && finishedNodeIds.contains(dataPort.getFromNode().getID()); } if (inputsDone && controlDone) { list.add(node); } } else if (component instanceof EndifComponent) { /* * EndIfComponent can run if number of input equals to number of * output that it expects */ int expectedOutput = node.getOutputPorts().size(); int actualInput = 0; List<DataPort> inputPorts = node.getInputPorts(); for (DataPort dataPort : inputPorts) { if (finishedNodeIds.contains(dataPort.getFromNode().getID())) actualInput++; } if (expectedOutput == actualInput) { list.add(node); } } else if (component instanceof TerminateInstanceComponent) { /* * All node connected to controlIn port must be done */ ControlPort control = node.getControlInPort(); boolean controlDone = true; if (control != null) { for (EdgeImpl edge : control.getEdges()) { controlDone = controlDone && finishedNodeIds.contains(edge.getFromPort().getFromNode().getID()); } } /* * Check for input ports */ List<DataPort> inputPorts = node.getInputPorts(); boolean inputsDone = true; for (DataPort dataPort : inputPorts) { inputsDone = inputsDone && finishedNodeIds.contains(dataPort.getFromNode().getID()); } if (inputsDone && controlDone) { list.add(node); } } else if (InputComponent.NAME.equals(component.getName()) || DifferedInputComponent.NAME.equals(component.getName()) || S3InputComponent.NAME.equals(component.getName()) || OutputComponent.NAME.equals(component.getName()) || MemoComponent.NAME.equals(component.getName()) || component instanceof EndDoWhileComponent) { // no op } else if (component instanceof DoWhileComponent) { ControlPort control = node.getControlInPort(); boolean controlDone = true; if (control != null) { for (EdgeImpl edge : control.getEdges()) { controlDone = controlDone && finishedNodeIds.contains(edge.getFromPort().getFromNode().getID()); } } if (controlDone) { list.add(node); } } else { throw new WorkFlowInterpreterException("Component Not handled :" + component.getName()); } } notifyViaInteractor(WorkflowExecutionMessage.HANDLE_DEPENDENT_NODES_DIFFERED_INPUTS, this.getGraph()); return list; } public Workflow getWorkflow() { return this.config.getWorkflow(); } public WorkflowInterpreterConfiguration getConfig() { return config; } public void setConfig(WorkflowInterpreterConfiguration config) { this.config = config; } private WSGraph getGraph() { return this.getWorkflow().getGraph(); } private ArrayList<Node> getFinishedNodesDynamically() { return this.getNodesWithState(NodeExecutionState.FINISHED); } private ArrayList<Node> getWaitingNodesDynamically() { return this.getNodesWithState(NodeExecutionState.WAITING); } private ArrayList<Node> getNodesWithState(NodeExecutionState state) { ArrayList<Node> list = new ArrayList<Node>(); List<NodeImpl> nodes = getGraph().getNodes(); for (Node node : nodes) { if (state==node.getState()) { list.add(node); } } return list; } public static void setWorkflowInterpreterConfigurationThreadLocal(WorkflowInterpreterConfiguration workflowInterpreterConfiguration) { WorkflowInterpreter.workflowInterpreterConfigurationThreadLocal.set(workflowInterpreterConfiguration); } public static WorkflowInterpreterConfiguration getWorkflowInterpreterConfiguration() { return workflowInterpreterConfigurationThreadLocal.get(); } public ExperimentModel getExperiment() { return experiment; } public void setExperiment(ExperimentModel experiment) { this.experiment = experiment; } public String getCredentialStoreToken() { return credentialStoreToken; } public void setCredentialStoreToken(String credentialStoreToken) { this.credentialStoreToken = credentialStoreToken; } @Override public void setup(Object... configurations) { } @Subscribe public void taskOutputChanged(TaskOutputChangeEvent taskOutputEvent){ String taskId = taskOutputEvent.getTaskIdentity().getTaskId(); if (isTaskAwaiting(taskId)){ ProcessState state=ProcessState.COMPLETED; Node node = getAwaitingNodeForTask(taskId); List<OutputDataObjectType> applicationOutputs = taskOutputEvent.getOutput(); Map<String, String> outputData = new HashMap<String, String>(); for (OutputDataObjectType outputObj : applicationOutputs) { List<DataPort> outputPorts = node.getOutputPorts(); for (DataPort dataPort : outputPorts) { if (dataPort.getName().equals(outputObj.getName())){ outputData.put(outputObj.getName(), outputObj.getValue()); } } } nodeOutputData.put(node, outputData); setupNodeDetailsOutput(node); node.setState(NodeExecutionState.FINISHED); try { publishNodeStatusChange(WorkflowNodeState.COMPLETED, node.getID(), experiment.getExperimentID()); updateWorkflowNodeStatus(nodeInstanceList.get(node), state); } catch (RegistryException e) { log.error(e.getMessage(), e); } catch (AiravataException e) { log.error(e.getMessage(), e); } } } @Subscribe public void taskStatusChanged(TaskStatusChangeEvent taskStatus){ String taskId = taskStatus.getTaskIdentity().getTaskId(); if (isTaskAwaiting(taskId)){ WorkflowNodeState state=WorkflowNodeState.UNKNOWN; Node node = getAwaitingNodeForTask(taskId); switch(taskStatus.getState()){ case CANCELED: ; break; case COMPLETED: //task has completed //but we'll wait for outputdata break; case CONFIGURING_WORKSPACE: break; case FAILED: state = WorkflowNodeState.FAILED; node.setState(NodeExecutionState.FAILED); break; case EXECUTING: case WAITING: case PRE_PROCESSING: case POST_PROCESSING: case OUTPUT_DATA_STAGING: case INPUT_DATA_STAGING: state = WorkflowNodeState.EXECUTING; node.setState(NodeExecutionState.EXECUTING); break; case STARTED: break; case CANCELING: state = WorkflowNodeState.CANCELING; break; default: break; } try { if (state != WorkflowNodeState.UNKNOWN) { updateWorkflowNodeStatus(nodeInstanceList.get(node), state); } } catch (RegistryException e) { log.error(e.getMessage(), e); } } } }