/** Destroy all services. */ public void destroy() { XLog log = new XLog(LogFactory.getLog(getClass())); log.trace("Shutting down"); boolean deleteRuntimeDir = false; if (conf != null) { deleteRuntimeDir = conf.getBoolean(CONF_DELETE_RUNTIME_DIR, false); } if (services != null) { List<Service> list = new ArrayList<Service>(services.values()); Collections.reverse(list); for (Service service : list) { try { log.trace("Destroying service[{0}]", service.getInterface()); if (service.getInterface() == XLogService.class) { log.info("Shutdown"); } service.destroy(); } catch (Throwable ex) { log.error( "Error destroying service[{0}], {1}", service.getInterface(), ex.getMessage(), ex); } } } if (deleteRuntimeDir) { try { IOUtils.delete(new File(runtimeDir)); } catch (IOException ex) { log.error("Error deleting runtime directory [{0}], {1}", runtimeDir, ex.getMessage(), ex); } } services = null; conf = null; SERVICES = null; }
/** * Get NodeDef from workflow instance * * @param executionPath execution path * @return node def */ public NodeDef getNodeDef(String executionPath) { NodeInstance nodeJob = executionPaths.get(executionPath); NodeDef nodeDef = null; if (nodeJob == null) { log.error("invalid execution path [{0}]", executionPath); } else { nodeDef = def.getNode(nodeJob.nodeName); if (nodeDef == null) { log.error("invalid transition [{0}]", nodeJob.nodeName); } } return nodeDef; }
public static String getPassword(Configuration conf, String name) { if (getPasswordMethod != null) { try { char[] pass = (char[]) getPasswordMethod.invoke(conf, name); return new String(pass); } catch (IllegalAccessException e) { log.error(e); throw new IllegalArgumentException("Could not load password for [" + name + "]", e); } catch (InvocationTargetException e) { log.error(e); throw new IllegalArgumentException("Could not load password for [" + name + "]", e); } } else { return conf.get(name); } }
public synchronized boolean signal(String executionPath, String signalValue) throws WorkflowException { ParamChecker.notEmpty(executionPath, "executionPath"); ParamChecker.notNull(signalValue, "signalValue"); log.debug( XLog.STD, "Signaling job execution path [{0}] signal value [{1}]", executionPath, signalValue); if (status != Status.RUNNING) { throw new WorkflowException(ErrorCode.E0716); } NodeInstance nodeJob = executionPaths.get(executionPath); if (nodeJob == null) { status = Status.FAILED; log.error("invalid execution path [{0}]", executionPath); } NodeDef nodeDef = null; if (!status.isEndState()) { nodeDef = def.getNode(nodeJob.nodeName); if (nodeDef == null) { status = Status.FAILED; log.error("invalid transition [{0}]", nodeJob.nodeName); } } if (!status.isEndState()) { NodeHandler nodeHandler = newInstance(nodeDef.getHandlerClass()); boolean exiting = true; Context context = new Context(nodeDef, executionPath, signalValue); if (!nodeJob.started) { try { nodeHandler.loopDetection(context); exiting = nodeHandler.enter(context); nodeJob.started = true; } catch (WorkflowException ex) { status = Status.FAILED; List<String> killedNodes = terminateNodes(Status.KILLED); if (killedNodes.size() > 1) { log.warn( XLog.STD, "Workflow completed [{0}], killing [{1}] running nodes", status, killedNodes.size()); } throw ex; } } if (exiting) { List<String> pathsToStart = new ArrayList<String>(); List<String> fullTransitions; try { fullTransitions = nodeHandler.multiExit(context); int last = fullTransitions.size() - 1; // TEST THIS if (last >= 0) { String transitionTo = getTransitionNode(fullTransitions.get(last)); if (nodeDef instanceof ForkNodeDef) { transitionTo = "*"; // WF action cannot hold all transitions for a fork. // transitions are hardcoded in the WF app. } persistentVars.put( nodeDef.getName() + WorkflowInstance.NODE_VAR_SEPARATOR + TRANSITION_TO, transitionTo); } } catch (WorkflowException ex) { status = Status.FAILED; throw ex; } if (context.status == Status.KILLED) { status = Status.KILLED; log.debug(XLog.STD, "Completing job, kill node [{0}]", nodeJob.nodeName); } else { if (context.status == Status.FAILED) { status = Status.FAILED; log.debug(XLog.STD, "Completing job, fail node [{0}]", nodeJob.nodeName); } else { if (context.status == Status.SUCCEEDED) { status = Status.SUCCEEDED; log.debug(XLog.STD, "Completing job, end node [{0}]", nodeJob.nodeName); } /* else if (context.status == Status.SUSPENDED) { status = Status.SUSPENDED; log.debug(XLog.STD, "Completing job, end node [{0}]", nodeJob.nodeName); } */ else { for (String fullTransition : fullTransitions) { // this is the whole trick for forking, we need the // executionpath and the transition // in the case of no forking last element of // executionpath is different from transition // in the case of forking they are the same log.debug( XLog.STD, "Exiting node [{0}] with transition[{1}]", nodeJob.nodeName, fullTransition); String execPathFromTransition = getExecutionPath(fullTransition); String transition = getTransitionNode(fullTransition); def.validateTransition(nodeJob.nodeName, transition); NodeInstance nodeJobInPath = executionPaths.get(execPathFromTransition); if ((nodeJobInPath == null) || (!transition.equals(nodeJobInPath.nodeName))) { // TODO explain this IF better // If the WfJob is signaled with the parent // execution executionPath again // The Fork node will execute again.. and replace // the Node WorkflowJobBean // so this is required to prevent that.. // Question : Should we throw an error in this case // ?? executionPaths.put(execPathFromTransition, new NodeInstance(transition)); pathsToStart.add(execPathFromTransition); } } // signal all new synch transitions for (String pathToStart : pathsToStart) { signal(pathToStart, "::synch::"); } } } } } } if (status.isEndState()) { if (status == Status.FAILED) { List<String> failedNodes = terminateNodes(status); log.warn( XLog.STD, "Workflow completed [{0}], failing [{1}] running nodes", status, failedNodes.size()); } else { List<String> killedNodes = terminateNodes(Status.KILLED); if (killedNodes.size() > 1) { log.warn( XLog.STD, "Workflow completed [{0}], killing [{1}] running nodes", status, killedNodes.size()); } } } return status.isEndState(); }