Package edu.ucsd.hep.rootrunnerutil

Source Code of edu.ucsd.hep.rootrunnerutil.ROOTRunnerOld

/*
* Copyright 2011 University of California, San Diego.
*
* Licensed 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 edu.ucsd.hep.rootrunnerutil;

import edu.ucsd.hep.rootrunnerutil.misc.InputStreamDumper;
import edu.ucsd.hep.rootrunnerutil.misc.InputStreamFanOut;
import edu.ucsd.hep.rootrunnerutil.shell.ShellPipeCommandRunner;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;

/**
* creates and follows the ROOT process (older implementation)
* @author holzner
*/
public class ROOTRunnerOld extends ROOTRunner
{

  /** the output (temporary) directory where ROOT should write the
   *  output files to
   */
  private File outputStoreDir;

  //----------------------------------------------------------------------

  public ROOTRunnerOld()
  {
    this((List<PipeCommandRunnerListener>) null, null, null, null);
  }

  //----------------------------------------------------------------------

  /** @param shell_initialization_commands is prepended to the root command
   *  (without any spaces or separators)
   *
   * @param commandRunnerListenerFactories is a list of factories for creating
   *        objects that will be notified whenever some lines are read or written
   *        to the ROOT process. Can be null (this is equivalent to
   *        an empty list)
   *
   * @param shell_initialization_commands commands executed on the shell before starting ROOT
   */
  public ROOTRunnerOld(List<PipeCommandRunnerListener> commandRunnerListeners,
    String root_cmd_args,
    String shell_initialization_commands,
    PipeCommandRunnerWorkerFactory runnerFactory)
  {
    if (commandRunnerListeners == null)
      this.commandRunnerListeners = new ArrayList<PipeCommandRunnerListener>();
    else
      this.commandRunnerListeners = new ArrayList<PipeCommandRunnerListener>(commandRunnerListeners);
   
    // remove all null listeners (which can come in from the other constructor
    // being called with a null pointer)
    for (Iterator<PipeCommandRunnerListener> it = this.commandRunnerListeners.iterator();
         it.hasNext();)
    {
      if (it.next() == null)
        it.remove();
    }

   
    this.runnerFactory = runnerFactory;

    if (root_cmd_args != null)
      this.root_cmd_args = root_cmd_args;
    else
      this.root_cmd_args = "-b";
    this.initialization_commands = shell_initialization_commands;

    // start the pipe to ROOT right now
    getROOTPipe();

    // TODO: we should make sure that the ROOT process is killed
    //       on program exit: see http://www.exampledepot.com/egs/java.lang/ExitHook.html

  }

  //----------------------------------------------------------------------
  /** convenience constructor for just one PipeCommandRunnerListenerFactory */
  public ROOTRunnerOld(PipeCommandRunnerListener commandRunnerListener,
    String root_cmd_args,
    String shell_initialization_commands,
    PipeCommandRunnerWorkerFactory runnerFactory)
  {
    this(AHUtils.makeList(commandRunnerListener),
      root_cmd_args,
      shell_initialization_commands,
      runnerFactory);
  }
 
  //----------------------------------------------------------------------

  private File makeROOTstartFile(String fullCmd) throws IOException
  {
    File cmd_script = AHUtils.writeTextToTemporaryFile(
      "#!/bin/sh" + "\n"
      + fullCmd + " 2>&1\n",
      "cmd",
      ".sh"); // merge stdout and stderr for the moment

    cmd_script.setExecutable(true);
    cmd_script.deleteOnExit();

    return cmd_script;
   
  }
 
  //----------------------------------------------------------------------

  /** default implementation for starting ROOT */
  protected void startROOT() throws Exception
  {
//    String cmd = rootCmd + " " + (root_cmd_args != null ? root_cmd_args : "");
//    if (initialization_commands != null)
//      cmd = initialization_commands + cmd;
//
//    if (mergeStdoutStderr)
//      cmd += " 2>&1";

    String cmd = rootCmd + " " + (root_cmd_args != null ? root_cmd_args : "");
    if (initialization_commands != null)
      cmd = initialization_commands + "\n" + cmd;
    // File cmd_script = makeROOTstartFile(cmd);
   
    if (this.runnerFactory != null)
      root_pipe = new PipeCommandRunner(runnerFactory.makeWorker(
        cmd
        // cmd_script.getAbsolutePath()
          )
        );
    else
      root_pipe = new PipeCommandRunner(new ShellPipeCommandRunner(
        cmd
        //cmd_script.getAbsolutePath()
        )
        );

   
   
//    if (this.runnerFactory != null)
//      root_pipe = new PipeCommandRunner(runnerFactory.makeWorker("root"));
//    else
//      root_pipe = new PipeCommandRunner(new ShellPipeCommandRunnerWithCommonsExec("root"));
   
   
    this.root_stdout_for_checkpointing = root_pipe.getCommandStdoutStream();//.getROOTStdoutStream();
   
   
    // for debugging
    {
      List<InputStream> isClones = InputStreamFanOut.makeClones(root_stdout_for_checkpointing, 2);
      root_stdout_for_checkpointing = isClones.get(0);

      InputStreamDumper debugDumper = new InputStreamDumper(System.err, isClones.get(1), "GOT FROM ROOT:");
      debugDumper.start();
    }
   
    // for each listener factory, create a listener
    for (PipeCommandRunnerListener listener : this.commandRunnerListeners)
    {
      root_pipe.addListener(listener);
    }
 

//    System.out.println("STARTING ROOT: " + cmd);
//      root_pipe.writeLine(cmd);
   
 

    // wait for ROOT prompt
    this.waitForLine(Pattern.compile(Pattern.quote("W E L C O M E  to  R O O T")));
  }

  //----------------------------------------------------------------------

  public File getOutputStoreDir()
  {
    if (this.outputStoreDir == null)
      outputStoreDir = getROOTPipe().makeTemporaryDirectory();

    return outputStoreDir;
  }

  //----------------------------------------------------------------------

  /** this is not used anywhere current in RooFitExplorer and maybe intended when running root
   *  over ssh ? */
  public byte[] getOutputFileContent(String fname)
  {
    return getROOTPipe().getOutputFileContent(fname);
  }

  //----------------------------------------------------------------------
 
  public void waitForCommandOutput() throws IOException
  {
    while (this.root_stdout_for_checkpointing.available() <= 0)
    {
      try
      {
        Thread.sleep(100);

        // check whether the process died
        if (this.root_pipe.hasExited())
          throw new Error("root process already exited while waiting for completion");

      } catch (InterruptedException ex)
      {
      }

    }     
  }
 
  //----------------------------------------------------------------------

  public String waitForLine(Pattern regexp) throws IOException
  {
    BufferedReader reader = new BufferedReader(new InputStreamReader(this.root_stdout_for_checkpointing));
    try
    {
    while (true)
    {
      while (!reader.ready())
      {
        try
        {
          Thread.sleep(100);

          // check whether the process died
          if (this.root_pipe.hasExited())
            throw new Error("root process already exited while waiting for completion");

        } catch (InterruptedException ex)
        {
        }
      }

      // this alone should already be sufficient as this will block
      // until the stream is 'ready'
      String line = reader.readLine();
      if (line == null)
        throw new Error("end program output reached");

      // TODO: we should deal with other situations here:
      //   - crashes
      //   - EOF
      if (regexp.matcher(line).find())
        return line;
    } // eternal loop
    }
    finally
    {
      // reader.close();
    }
  }

  //----------------------------------------------------------------------
  /** waits for the current command pipes to complete. Does this
   *  by telling root to write a string to the output stream
   *  and waits until it can read it from ROOT's stdout
   */
  public String waitForCompletion()
  {
    // period after which another 'MARKER' is sent (seems to
    // be ignored or not printed when it is sent too fast)
    final long retryPeriod = 100000;

    // period between checks for available input
    final long waitingPeriod = 10;

    try
    {
      BufferedReader reader = new BufferedReader(new InputStreamReader(this.root_stdout_for_checkpointing));

      List<String> linesRead = new ArrayList<String>();
     
      while (true)
      {
        if (this.root_pipe.hasExited())
          throw new Error("root process already exited");

        long nextMarkerSending = new Date().getTime() + retryPeriod;

        Marker marker = this.sendMarker();

        while (new Date().getTime() < nextMarkerSending)
        {
       
          while (new Date().getTime() < nextMarkerSending && !reader.ready())
          {
            try
            {
              Thread.sleep(waitingPeriod);

              // check whether the process died
              if (this.root_pipe.hasExited())
                throw new Error("root process already exited while waiting for completion");

            } catch (InterruptedException ex)
            {
            }
          }

          if (! reader.ready())
            break;
         
          // this alone should already be sufficient as this will block
          // until the stream is 'ready'
          String line = reader.readLine();
          if (line == null)
            continue;

          // TODO: we should deal with other situations here:
          //   - crashes
          //   - EOF
          if (line.equals(marker.getString()))
          {
            return AHUtils.linesToSingleString(linesRead);
          }
         
          linesRead.add(line);
         
        } // while we should not send a new marker
      } // eternal loop
    
     
    } catch (IOException ex)
    {
      Logger.getLogger(ROOTRunnerOld.class.getName()).log(Level.SEVERE, null, ex);
      return null;
    }

  }
  //----------------------------------------------------------------------
 
  //----------------------------------------------------------------------

  /** runs one single command and retrieves its output.
   *
   *  Currently this is implemented by using ROOT's redirection after
   * the semicolon, so the given command must be a simple statement,
   * no loops or if statements and must not contain a semicolon grouping
   * several statements.
   *
   * @param string
   * @return
   */
  private synchronized String getCommandOutputClassic(String cmd) throws IOException
  {
    // create a temporary file to be written to
    //
    // note: redirecting into a separate file each time
    //       this method is called does not work for numbers
    //       above around 1000 times. This is because of
    //       a bug in TUnixSystem::RedirectOutput(..)
    //       which does not close the previous file in all cases
    //       (see http://savannah.cern.ch/bugs/?96935 )
    //
    //       The bug seems not to appear when not running
    //       with output redirection into a pipe or a file
    //
    //       Note that it's also quite cumbersome to leave
    //       the output file redirected to always the same file:
    //       we would have to scan for the marker line mixed with
    //       the output (as we would not redirect back to the
    //       normal stdout for the marker)
    File fout = File.createTempFile("ROOTRunner", ".txt");
   
    // run the command
    // this seems to be problematic when waiting for completion
    // afterwards ?!
    // this.writeLine(cmd + "; >" + fout.getAbsolutePath());
    // this.writeLine(cmd);

    // see http://root.cern.ch/root/html/TSystem.html#TSystem:RedirectOutput
    //
    // note that in this form this does not play well with
    // calling code which also modifies the output
    //
    this.writeLine("gSystem->RedirectOutput(\"" + fout.getAbsolutePath() + "\");");
   
    this.writeLine(cmd);
    // re-establish stdout
    this.writeLine("gSystem->RedirectOutput(0);");
   
   
    this.waitForCompletion();
   
    // read the temporary file and return its content
    // TODO: who deletes the temporary file ?
   
    return AHUtils.readFile(fout.getAbsolutePath());
   
  }

  //----------------------------------------------------------------------

  /** version which tries to avoid using gSystem->RedirectOutput(..).
  
   *  This is actually quite similar to what expect is doing...
   */
  private synchronized String getCommandOutputBetter(String cmd) throws IOException
  {
    clearPrompt();
   
    // synchronize first
    System.out.println("first synchronization");
    this.waitForCompletion();

    this.writeLine(cmd);

    System.out.println("second synchronization");
    return this.waitForCompletion();
   
  }

  //----------------------------------------------------------------------

  /** note that this is NOT intended for binary output but
   *  only for line-oriented output.
   */
  public String getCommandOutput(String cmd) throws IOException
  {
    return this.getCommandOutputBetter(cmd);
  }
 
  //----------------------------------------------------------------------

  /** this is mostly for testing/debugging purposes: add the possibility
   *  to add a PipeCommandRunnerListener to the pipe to ROOT.
   * @param listener
   */
  public void addCommandPipeListener(PipeCommandRunnerListener listener)
  {
    this.root_pipe.addListener(listener);
  }

  @Override
  public List<String> getMultipleCommandsOutputBatch(List<String> cmds) throws IOException
  {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  @Override
  public byte[] readFile(String fname) throws IOException
  {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  @Override
  public String createTempFile(String prefix, String suffix) throws IOException
  {
    throw new UnsupportedOperationException("Not supported yet.");
  }

}
TOP

Related Classes of edu.ucsd.hep.rootrunnerutil.ROOTRunnerOld

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.