Package sos.scheduler.managed

Source Code of sos.scheduler.managed.JobSchedulerManagedExecutableJob

/********************************************************* begin of preamble
**
** Copyright (C) 2003-2010 Software- und Organisations-Service GmbH.
** All rights reserved.
**
** This file may be used under the terms of either the
**
**   GNU General Public License version 2.0 (GPL)
**
**   as published by the Free Software Foundation
**   http://www.gnu.org/licenses/gpl-2.0.txt and appearing in the file
**   LICENSE.GPL included in the packaging of this file.
**
** or the
** 
**   Agreement for Purchase and Licensing
**
**   as offered by Software- und Organisations-Service GmbH
**   in the respective terms of supply that ship with this file.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
** IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
** THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
** POSSIBILITY OF SUCH DAMAGE.
********************************************************** end of preamble*/
package sos.scheduler.managed;

import java.io.BufferedReader;
import java.io.FileReader;

import sos.spooler.Order;
import sos.spooler.Subprocess;
import sos.spooler.Variable_set;

/**
* execute command files for managed orders
*
* order parameters:
* ignore_error (optional): bei true werden Fehler des executables ignoriert
* ignore_signal (optional): bei true werden R�ckgabesignale des executables ignoriert
* ignore_stderr (optional): bei true werden Zeichen in stdout nicht als Fehler behandelt
* timeout (optional): timeout f�r die Ausf�hrung des executables in Sekunden
* log_file (optional): Der Scheduler nimmt nach Beenden des Subprozesses den Inhalt
* dieser Datei in sein Protokoll
*
* environment variablen k�nnen �ber parameter mit dem Pr�fix env. gesetzt werden, z.B.:
* env.LD_LIBRARY_PATH
*
* @author andreas.pueschel@sos-berlin.com
* @since 1.0 2005-03-05
*/
public class JobSchedulerManagedExecutableJob extends JobSchedulerManagedJob {

  private BufferedReader    stdoutStream;
  private BufferedReader    stderrStream;

  private final String strOrderParamPrefix = "scheduler_order_";
  // aliases for parameters from ProcessSubprocessJob
  private  String[][]  inputParameterAliases  = { { strOrderParamPrefix + "ignore_stderr", "ignore_stderr" },
      { strOrderParamPrefix + "ignore_error", "ignore_error" },
      { strOrderParamPrefix + "ignore_signal", "ignore_signal" },
      { strOrderParamPrefix + "timeout", "timeout" },
      { strOrderParamPrefix + "priority_class", "priority_class" } };

  private final  String  conStd_err_output    = "std_err_output";
  private final  String  conStd_out_output    = "std_out_output";
  private final  String  conExit_code      = "exit_code";
 
  private  final String  conClassName  = "JobSchedulerManagedExecutableJob";

  private final String[][]  outputParameterAliases  = { { conStd_err_output, strOrderParamPrefix + "stderr_output" },
      { conStd_out_output, strOrderParamPrefix + "stdout_output" },
      { conExit_code, strOrderParamPrefix + "exit_code" } };

  /**
   * Initialize input and output streams
   */
  public boolean spooler_init() {
    try {
      FileReader fisOut = new FileReader(spooler_task.stdout_path());
      FileReader fisErr = new FileReader(spooler_task.stderr_path());
      stdoutStream = new BufferedReader(fisOut);
      stderrStream = new BufferedReader(fisErr);
    }
    catch (Exception e) {
      spooler_log.warn("failed to initialize stdout and stderr streams. " + e);
    }

    if (!super.spooler_init())
      return false;
    return true;
  }

  /**
   * process order
   */
  public boolean spooler_process() {

    Order order = null;
    orderPayload = null;
    String program = "";
    String logFile = "";
    String priorityClass = "normal";

    try {
      super.prepareParams();

      String command = "";
      try {
        if (orderJob) {
          command = JobSchedulerManagedObject.getOrderCommand(this.getConnection(), this);
          order = spooler_task.order();
        }
        if (command == null || command.trim().length() == 0) {
          command = JobSchedulerManagedObject.getJobCommand(this.getConnection(), this);
        }

        // overidden for custom implementation
        command = modifyCommand(command);

        if (command == null || command.trim().length() == 0)
          throw new Exception("command is empty");

      }
      catch (Exception e) {
        throw (new Exception("no executable command found for order:" + e));
      }
      getLogger().debug3("command before replacements:\n" + command);
      // if ( orderData == null || orderData.var("command") == null || orderData.var("command").toString().length() == 0)
      // throw (new Exception("no executable command found in order payload"));
      boolean ignoreError = false;
      boolean ignoreSignal = false;
      boolean ignoreStderr = false;
      boolean ignoreTimeout = false;

      boolean timedOut = false;
      boolean ownProcessGroup = false;

      if (orderPayload != null) {
        replaceAliases(orderPayload, inputParameterAliases);

        if (orderPayload.var("ignore_error") != null
            && (orderPayload.var("ignore_error").toString().equalsIgnoreCase("true") || orderPayload.var("ignore_error").equalsIgnoreCase("1") || orderPayload.var(
                "ignore_error")
                .equalsIgnoreCase("yes"))) {
          ignoreError = true;
        }
        if (orderPayload.var("ignore_signal") != null
            && (orderPayload.var("ignore_signal").toString().equalsIgnoreCase("true") || orderPayload.var("ignore_signal").equalsIgnoreCase("1") || orderPayload.var(
                "ignore_signal")
                .equalsIgnoreCase("yes"))) {
          ignoreSignal = true;
        }
        if (orderPayload.var("ignore_stderr") != null
            && (orderPayload.var("ignore_stderr").toString().equalsIgnoreCase("true") || orderPayload.var("ignore_stderr").equalsIgnoreCase("1") || orderPayload.var(
                "ignore_stderr")
                .equalsIgnoreCase("yes"))) {
          ignoreStderr = true;
        }
        if (orderPayload.var("ignore_timeout") != null
            && (orderPayload.var("ignore_timeout").toString().equalsIgnoreCase("true") || orderPayload.var("ignore_timeout").equalsIgnoreCase("1") || orderPayload.var(
                "ignore_timeout")
                .equalsIgnoreCase("yes"))) {
          ignoreTimeout = true;
        }
        if (orderPayload.var("own_process_group") != null
            && (orderPayload.var("own_process_group").toString().equalsIgnoreCase("true")
                || orderPayload.var("own_process_group").equalsIgnoreCase("1") || orderPayload.var("own_process_group").equalsIgnoreCase("yes"))) {
          ownProcessGroup = true;
        }
        if (orderPayload.var("log_file") != null && orderPayload.var("log_file").toString().length() > 0) {
          logFile = orderPayload.var("log_file").toString();
        }
        if (orderPayload.var("priority_class") != null && orderPayload.var("priority_class").toString().length() > 0) {
          priorityClass = orderPayload.var("priority_class").toString();
        }
        // for compatibility with ProcessSubprocessJob
        if (orderPayload.var("scheduler_order_command_parameters") != null
            && orderPayload.var("scheduler_order_command_parameters").toString().length() > 0) {
          command += " " + orderPayload.var("scheduler_order_command_parameters").toString();
        }
      }
      // the path of the interpreter is given with this parameter
      if (spooler_task.params().var("interpreter") != null && spooler_task.params().var("interpreter").length() > 0) {
        program = spooler_task.params().var("interpreter");
        spooler_log.debug3("Using interpreter: " + program);
      }

      spooler_log.debug3("current setting ignore_error: " + ignoreError);
      spooler_log.debug3("current setting ignore_signal: " + ignoreSignal);
      spooler_log.debug3("current setting own_process_group: " + ownProcessGroup);

      spooler_log.debug9("logFile.lentgh:" + logFile.length());
      if (logFile.length() > 0) {
        spooler_log.debug3("current setting log_file: " + logFile);
      }
      // parse environment variables

      /*if(orderData!=null && orderData.var("environment")!=null && orderData.var("environment").toString().length() > 0){
        String environment=orderData.var("environment").toString();
         Pattern envPattern = Pattern.compile("\\{[^\\}]*\\}");
          Matcher envMatcher = envPattern.matcher(environment);
          spooler_log.debug3("environment variables:");
          while(envMatcher.find()){
            String nameValueBr=envMatcher.group();
            String nameValue=nameValueBr.substring(1,nameValueBr.length()-1);
            spooler_log.debug3("  "+nameValue);
            String[] nameValueArr=nameValue.split("=");
            if (nameValueArr.length!=2){
              spooler_log.warn("Incorrect Syntax for Name=Value Pair.");
              continue;
            }
            subProc.set_environment(nameValueArr[0], nameValueArr[1]);
          }

      }*/

      // replace job-specific placeholders
      command = command.replaceAll("(\\$|�)\\{scheduler_order_job_name\\}", this.getJobName());
      command = command.replaceAll("(\\$|�)\\{scheduler_order_job_id\\}", Integer.toString(this.getJobId()));
      command = command.replaceAll("(\\$|�)\\{scheduler_id\\}", spooler.id());
      if (orderJob)
        if (order != null) {
            command = command.replaceAll("(\\$|�)\\{scheduler_order_id\\}", order.id());
        }

      // replace parameters
      if (orderPayload != null) {
        command = JobSchedulerManagedObject.replaceVariablesInCommand(command, orderPayload, getLogger());
      }

      // replace newlines
      command = command.replaceAll("\r\n", "\n");
      getLogger().debug3("Command after replacements:\n" + command);

      String[] commands = command.split("\n");
      getLogger().debug6("Found " + commands.length + " commands.");
      // neu: mit subprocess

      for (int i = 0; i < commands.length && !timedOut; i++) {
        Subprocess subProc = spooler_task.create_subprocess();
        subProc.set_own_process_group(ownProcessGroup);
        subProc.set_ignore_error(ignoreError);
        subProc.set_ignore_signal(ignoreSignal);
        subProc.set_priority_class(priorityClass);
        try {
          setEnvironment(orderPayload, subProc);
        }
        catch (Exception e) {
          throw new Exception("Error occured setting environment variables: " + e);
        }
        // execute interpreter
        if (program != null && program.length() > 0) {
          subProc.start(program + " " + commands[i]);
          spooler_log.info("executing \"" + program + " " + commands[i] + "\"");
        }
        else {
          subProc.start(commands[i]);
          spooler_log.info("executing \"" + commands[i] + "\"");
        }
        if (orderPayload != null && orderPayload.var("timeout") != null && orderPayload.var("timeout").toString().length() > 0
            && !orderPayload.var("timeout").toString().equals("0")) {
          spooler_log.info("executable file is launched with process id " + subProc.pid() + " for timeout in "
              + orderPayload.var("timeout").toString() + "s");
          boolean terminated = subProc.wait_for_termination(Double.parseDouble(orderPayload.var("timeout").toString()));
          if (!terminated) {
            spooler_log.info("timeout reached, process will be terminated.");
            subProc.kill();
            subProc.wait_for_termination();
            timedOut = true;
          }

        }
        else {
          spooler_log.info("executable file is launched with process id " + subProc.pid());
          subProc.wait_for_termination();

        }
        if (!timedOut)
          spooler_log.info("file executed");
        spooler_log.debug9("Exit code: " + subProc.exit_code());

        boolean stdErrEmpty = true;
        String stdErrString = "";
        String stdOutString = "";
        spooler_log.info("std_out for " + commands[i] + ":");
        while (stdoutStream != null && stdoutStream.ready()) {
          String stdOutLine = stdoutStream.readLine();
          spooler_log.info(stdOutLine);
          stdOutString += stdOutLine + "\n";
        }
        spooler_log.info("std_err for " + commands[i] + ":");

        while (stderrStream != null && stderrStream.ready()) {
          String stdErrLine = stderrStream.readLine();
          spooler_log.info(stdErrLine);
          if (stdErrLine.trim().length() > 0)
            stdErrEmpty = false;
          stdErrString += stdErrLine + "\n";
        }
        if (orderJob && order != null) {
          Variable_set realOrderPayload = order.params();
          SetVar(realOrderPayload, conStd_err_output, stdErrString);
          SetVar(realOrderPayload, conStd_out_output, stdOutString);
          SetVar(realOrderPayload, conExit_code, "" + subProc.exit_code());
          SetVar(realOrderPayload, "timed_out", "" + timedOut);
          // for compatibility with SubProcessJob
          SetVar(realOrderPayload, "scheduler_order_terminated", (!timedOut ? "true" : "false"));
          replaceAliases(realOrderPayload, outputParameterAliases);
        } // additionally set task parameters for use with copy-from:
        Variable_set taskParams = spooler_task.params();
        SetVar(taskParams, conStd_err_output, stdErrString);
        SetVar(taskParams, conStd_out_output, stdOutString);
        SetVar(taskParams, conExit_code, "" + subProc.exit_code());
        SetVar(taskParams, "timed_out", "" + timedOut);
        replaceAliases(taskParams, outputParameterAliases);

        if (timedOut && !ignoreTimeout) {
          throw new Exception("Process had to be killed because of timeout");
        }
        if ((subProc.exit_code() != 0)) {
          if (ignoreError)
            spooler_log.info("Command terminated with exit code: " + subProc.exit_code());
          else
            throw new Exception("Command terminated with exit code: " + subProc.exit_code());
        }
        if ((subProc.termination_signal() != 0)) {
          if (ignoreSignal)
            spooler_log.info("Command terminated with signal: " + subProc.termination_signal());
          else
            throw new Exception("Command terminated with signal: " + subProc.termination_signal());
        }
        if (!ignoreStderr && !stdErrEmpty) {
          throw new Exception("Command terminated with text in stderr:\n" + stdErrString);
        }

      }

      return orderJob;
    }
    catch (Exception e) {
      if (orderJob)
        spooler_log.warn("error occurred processing managed order ["
            + ((order != null) ? "Job Chain: " + order.job_chain().name() + ", ID:" + order.id() : "(none)") + "] : " + e);
      else
        spooler_log.warn("error occurred processing executable file: " + e);
      spooler_task.end();
      return false;
    }
    finally {
      if (logFile.length() > 0) {
        spooler_log.log_file(logFile);
      }
    }
  }

  private void replaceAliases(Variable_set pOrderPayload, String[][] aliases) {
    if (pOrderPayload != null && aliases != null) {
      for (int i = 0; i < aliases.length; i++) {
        String aliasParam = aliases[i][0];
        String replacedParam = aliases[i][1];
        String aliasParamValue = pOrderPayload.value(aliasParam);
//        if (aliasParamValue != null && aliasParamValue.length() > 0) {
          if (aliasParamValue != null) {
          SetVar(pOrderPayload, replacedParam, aliasParamValue);
        }
        else {
          spooler_log.info("Variable not found: '" + aliasParam + "'.");
        }
      }
    }
  }

  /**
   *
   * \brief SetVar
   *
   * \details
   *
   * \return void
   *
   * @param objVars
   * @param strVarName
   * @param strVarValue
   */
  private void SetVar(final Variable_set objVars, final String strVarName, final String strVarValue) {
   
    final String  conMethodName  = conClassName + "::SetVar";
   
    objVars.set_var(strVarName, strVarValue);
    spooler_log.info(conMethodName + "Variable '" + strVarName + "' set to value '" + strVarValue + "'.");
   
  } // private void SetVar
 
  /**
   *
   * \brief modifyCommand
   *
   * \details
   *
   * \return String
   *
   * @param command
   * @return
   */
  protected String modifyCommand(String command) {
    // TODO Auto-generated method stub
    return command;
  }

  /**
   * Cleanup
   */
  public void spooler_exit() {

    super.spooler_exit();
  }

  private void setEnvironment(Variable_set vars, Subprocess proc) throws Exception {
    if (vars == null || vars.xml() == null || vars.xml().length() == 0)
      return;
    String[] keys = vars.names().split(";");
    for (int i = 0; i < keys.length; i++) {
      String parameterName = keys[i];
      String parameterValue = vars.var(keys[i]);
      if (parameterName.startsWith("env.")) {
        proc.set_environment(parameterName.substring(4), parameterValue);
      }
    }
    if (vars.value("scheduler_file_path") != null && vars.value("scheduler_file_path").length() > 0) {
      proc.set_environment("SCHEDULER_TRIGGER_FILE", vars.value("scheduler_file_path"));
    }
    if (vars.value("scheduler_order_additional_envvars") != null && vars.value("scheduler_order_additional_envvars").length() > 0) {
      getLogger().debug3("Setting additional envvars.");
      String[] envVarKeys = vars.value("scheduler_order_additional_envvars").split(";");
      for (int i = 0; i < envVarKeys.length; i++) {
        String key = envVarKeys[i];
        String value = vars.value(key);
        if (value != null && value.length() > 0)
          proc.set_environment(key, value);
      }
    }
  }

}
TOP

Related Classes of sos.scheduler.managed.JobSchedulerManagedExecutableJob

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.