예제 #1
0
  @Override
  public void readFields(DataInput dIn) throws IOException {
    instanceId = dIn.readUTF();

    // Hadoop Configuration has to get its act right
    int len = dIn.readInt();
    byte[] array = new byte[len];
    dIn.readFully(array);
    ByteArrayInputStream bais = new ByteArrayInputStream(array);
    conf = new XConfiguration(bais);

    def = new LiteWorkflowApp();
    def.readFields(dIn);
    status = Status.valueOf(dIn.readUTF());
    int numExPaths = dIn.readInt();
    for (int x = 0; x < numExPaths; x++) {
      String path = dIn.readUTF();
      String nodeName = dIn.readUTF();
      boolean isStarted = dIn.readBoolean();
      NodeInstance nodeInstance = new NodeInstance(nodeName);
      nodeInstance.started = isStarted;
      executionPaths.put(path, nodeInstance);
    }
    int numVars = dIn.readInt();
    for (int x = 0; x < numVars; x++) {
      String vName = dIn.readUTF();
      String vVal = readBytesAsString(dIn);
      persistentVars.put(vName, vVal);
    }
    refreshLog();
  }
예제 #2
0
 private List<String> terminateNodes(Status endStatus) {
   List<String> endNodes = new ArrayList<String>();
   for (Map.Entry<String, NodeInstance> entry : executionPaths.entrySet()) {
     if (entry.getValue().started) {
       NodeDef nodeDef = def.getNode(entry.getValue().nodeName);
       if (!(nodeDef instanceof ControlNodeDef)) {
         NodeHandler nodeHandler = newInstance(nodeDef.getHandlerClass());
         try {
           if (endStatus == Status.KILLED) {
             nodeHandler.kill(new Context(nodeDef, entry.getKey(), null));
           } else {
             if (endStatus == Status.FAILED) {
               nodeHandler.fail(new Context(nodeDef, entry.getKey(), null));
             }
           }
           endNodes.add(nodeDef.getName());
         } catch (Exception ex) {
           log.warn(
               XLog.STD,
               "Error Changing node state to [{0}] for Node [{1}]",
               endStatus.toString(),
               nodeDef.getName(),
               ex);
         }
       }
     }
   }
   return endNodes;
 }
예제 #3
0
  @Override
  public void write(DataOutput dOut) throws IOException {
    dOut.writeUTF(instanceId);

    // Hadoop Configuration has to get its act right
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    conf.writeXml(baos);
    baos.close();
    byte[] array = baos.toByteArray();
    dOut.writeInt(array.length);
    dOut.write(array);

    def.write(dOut);
    dOut.writeUTF(status.toString());
    dOut.writeInt(executionPaths.size());
    for (Map.Entry<String, NodeInstance> entry : executionPaths.entrySet()) {
      dOut.writeUTF(entry.getKey());
      dOut.writeUTF(entry.getValue().nodeName);
      dOut.writeBoolean(entry.getValue().started);
    }
    dOut.writeInt(persistentVars.size());
    for (Map.Entry<String, String> entry : persistentVars.entrySet()) {
      dOut.writeUTF(entry.getKey());
      writeStringAsBytes(entry.getValue(), dOut);
    }
  }
예제 #4
0
 private void refreshLog() {
   XLog.Info.get().setParameter(XLogService.USER, conf.get(OozieClient.USER_NAME));
   XLog.Info.get().setParameter(XLogService.GROUP, conf.get(OozieClient.GROUP_NAME));
   XLog.Info.get().setParameter(DagXLogInfoService.APP, def.getName());
   XLog.Info.get().setParameter(DagXLogInfoService.TOKEN, conf.get(OozieClient.LOG_TOKEN, ""));
   XLog.Info.get().setParameter(DagXLogInfoService.JOB, instanceId);
   log = XLog.getLog(getClass());
 }
예제 #5
0
 /**
  * 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;
 }
예제 #6
0
 private List<String> killNodes() {
   List<String> killedNodes = new ArrayList<String>();
   for (Map.Entry<String, NodeInstance> entry : executionPaths.entrySet()) {
     String node = entry.getKey();
     NodeInstance nodeInstance = entry.getValue();
     if (nodeInstance.started) {
       NodeDef nodeDef = def.getNode(nodeInstance.nodeName);
       NodeHandler nodeHandler = newInstance(nodeDef.getHandlerClass());
       try {
         nodeHandler.kill(new Context(nodeDef, node, null));
         killedNodes.add(nodeDef.getName());
       } catch (Exception ex) {
         log.warn(XLog.STD, "Error killing node [{0}]", nodeDef.getName(), ex);
       }
     }
   }
   return killedNodes;
 }
예제 #7
0
 private String failNode(String nodeName) {
   String failedNode = null;
   for (Map.Entry<String, NodeInstance> entry : executionPaths.entrySet()) {
     String node = entry.getKey();
     NodeInstance nodeInstance = entry.getValue();
     if (nodeInstance.started && nodeInstance.nodeName.equals(nodeName)) {
       NodeDef nodeDef = def.getNode(nodeInstance.nodeName);
       NodeHandler nodeHandler = newInstance(nodeDef.getHandlerClass());
       try {
         nodeHandler.fail(new Context(nodeDef, node, null));
         failedNode = nodeDef.getName();
         nodeInstance.started = false;
       } catch (Exception ex) {
         log.warn(XLog.STD, "Error failing node [{0}]", nodeDef.getName(), ex);
       }
       return failedNode;
     }
   }
   return failedNode;
 }
예제 #8
0
  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();
  }