Package tcg.plan

Source Code of tcg.plan.PlanStep

/**
* PlanStep.java
*
* Provide generic class for plan step implementation. Every plan step should extend
* this class.
*
* To implement a plan step, the new class must implement the following functions:
* - main(): provide main entry to run the step. This is also the legacy way of
*           running a plan step.
* - printVersion(): print plan step version
* - printUsage(): print help message
* - parseArgument2(): additional parameters specific to the plan step. Generic plan
*                     parameters are already handled by PlanStep class.
* - init(): what to do in init stage.
* - running(): what to do in running stage.
* - close(): what to do in closing stage.
*
* @author    Wahyu Yoga Pratama (yoga@thatcoolguy.com)
*
* @created      Nov 12, 2009
* @version    $$
*
* HISTORY:
* - 2009/11/12  Created.
*
* TODO:
*
*/

package tcg.plan;

import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

import org.apache.commons.cli.BasicParser;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

import org.apache.log4j.Logger; // Perform logging operations
import org.apache.log4j.NDC;

import tcg.common.LoggerManager;

public abstract class PlanStep
{
  protected static DateFormat DATE_FORMAT = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" );
  protected static int ERROR_THRESHOLD = 3;
 
  protected String exeId = "";
  protected String nodeId = "";
  protected int masterPortNo = 0;
  protected int agentPortNo = 0;
 
  protected Logger logger = LoggerManager.getLogger(PlanStep.class.toString());
 
  public void execute(String params)
  {
    String args[] = params.split(" ");
    this.execute(args);
  }
 
  //Parse child specific arguments
  protected abstract boolean parseArgument2(String args[]);
 
  //Perform different operation in different stage of running
  protected abstract boolean init();
  protected abstract boolean running();
  protected abstract boolean close();
 
  //Terminate the step. This will be called when PlanMaster wants to
  // abruptly terminate the step
  protected abstract void terminate();
 
  protected void execute(String args[])
  {
    //parse the argument
    if (!parseArguments(args))
    {
      return;
    }
   
    //add logging context
    NDC.push(exeId + ":" + nodeId + ":" + masterPortNo);
   
    //run any initialization
    updateExecutionState(StepExecutionState.INIT);
    if (!init())
    {
      updateExecutionState(StepExecutionState.STEPFAIL);
      NDC.pop();
      return;
    }
   
    //run the actual processing
    updateExecutionState(StepExecutionState.RUNNING);
    if (!running())
    {
      updateExecutionState(StepExecutionState.STEPFAIL);
      NDC.pop();
      return;
    }

    //end execution
    updateExecutionState(StepExecutionState.CLOSE);
    close();
   
    //remove logging context
    NDC.pop();
  }

  protected void setLogger(Logger logger)
  {
    this.logger = logger;
  }
 
  //I need to do this so that child class does not need to each print it out
  // in its printUsage()
  protected void printExpectedArguments()
  {
    System.out.println(" --plan-execution-id <plan-id>      Plan Execution ID");
    System.out.println(" --executed-node-id <node-id>       Executed Node ID");
    System.out.println(" --port-no <port-no>             Plan Master Port No");
    System.out.println(" --agent-port-no <port-no>          Plan Agent Port No");
  }
 
  private boolean parseArguments(String args[])
  {
    CommandLineParser cmdLnParser = new BasicParser();
    CommandLine cmdLn = null;
    Options optArgs = new Options();

    Option cmdLineArg1 =
        new Option("exeID", "PLAN Execution ID (required)");
    cmdLineArg1.setRequired(true);
    cmdLineArg1.setArgs(1);
    cmdLineArg1.setArgName("plan-execution-id");
    Option cmdLineArg2 =
        new Option("nodeID", "Executed Node ID (required)");
    cmdLineArg2.setRequired(true);
    cmdLineArg2.setArgs(1);
    cmdLineArg2.setArgName("executed-node-id");
    Option cmdLineArg3 =
        new Option("portNo", "PLAN Master listener port no (required)");
    cmdLineArg3.setRequired(true);
    cmdLineArg3.setArgs(1);
    cmdLineArg3.setArgName("port-no");
    Option cmdLineArg4 =
        new Option("agentPortNo", "PLAN Agent Port No (required)");
    cmdLineArg4.setRequired(true);
    cmdLineArg4.setArgs(1);
    cmdLineArg4.setArgName("agent-port-no");
   
    optArgs.addOption(cmdLineArg1);
    optArgs.addOption(cmdLineArg2);
    optArgs.addOption(cmdLineArg3);
    optArgs.addOption(cmdLineArg4);
   
    //parse the arguments
    try
    {
      cmdLn = cmdLnParser.parse(optArgs, args);
    }
    catch (ParseException pe)
    {
      logger.error("Can not parse arguments: " + pe.getMessage());
      HelpFormatter formatter = new HelpFormatter();
      formatter.printHelp( "Parameters:", optArgs );
      return false;
    }
   
    //get the valud
    exeId = cmdLn.getOptionValue("exeID");
    nodeId = cmdLn.getOptionValue("nodeID");
   
    try
    {
      masterPortNo = Integer.parseInt(cmdLn.getOptionValue("portNo"));
    }
    catch (NumberFormatException ne)
    {
      logger.error("Invalid plan master port no: " + cmdLn.getOptionValue("portNo"));
      return false;
    }
   
    try
    {
      agentPortNo = Integer.parseInt(cmdLn.getOptionValue("agent-port-no"));
    }
    catch (NumberFormatException ne)
    {
      logger.error("Invalid plan agent port no: "
              + cmdLn.getOptionValue("agent-port-no"));
      return false;
    }
       
    //pass to child subroutines
    return parseArgument2(args);
  }
 
  private boolean updateExecutionState(StepExecutionState state)
  {
    String msg = "";
   
    //build the message
    if (state == StepExecutionState.INIT)
    {
      msg = DATE_FORMAT.format(new java.util.Date()) + ",INIT," + nodeId;
    }
    else if (state == StepExecutionState.RUNNING)
    { 
      msg = DATE_FORMAT.format(new java.util.Date()) + ",RUNNING," + nodeId;
    }
    else if (state == StepExecutionState.CLOSE)
    {
      msg = DATE_FORMAT.format(new java.util.Date()) + ",CLOSE," + nodeId;
    }
    else
    {
      msg = DATE_FORMAT.format(new java.util.Date()) + ",STEPFAIL," + nodeId;
    }
   

    //plan master is always running locally
    InetAddress masterHost = null;
    try
    {
      masterHost = InetAddress.getLocalHost();
    }
    catch(Exception ex)
    {
      //this is very unlikely to happen!
      logger.error("Can not get localhost address: " + ex.getLocalizedMessage());
      return false;
    }
   
    //TODO: avoid opening the socket everytime. open once and reuse it if possible.
    boolean status = false;
    for (int i=0; i<ERROR_THRESHOLD && !status; i++)
    {
      try
      {
        // Create the socket
        Socket socket = new Socket(masterHost, masterPortNo);
        // Send a String
        OutputStreamWriter out = new OutputStreamWriter(socket.getOutputStream());
        out.write(msg);
        out.flush();
        // Close socket
        socket.close();
        // Successful
        status = true;
      }
      catch (Exception ex)
      {
        logger.warn("Can not notify plan master: " + ex.getLocalizedMessage());
      }
    }

    return status;
  }
 
  protected enum StepExecutionState
  {
    INIT,
    RUNNING,
    CLOSE,
    STEPFAIL;
  }
}

TOP

Related Classes of tcg.plan.PlanStep

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.