Login | Register
My pages Projects Community openCollabNet

Discussions > cvs > CVS update: joist/java/org/joist/util Command.java Debug.java Timer.java Trace.java

Project highlights: Architectural Overview

joist
Discussion topic

Back to topic list

CVS update: joist/java/org/joist/util Command.java Debug.java Timer.java Trace.java

Author ms
Full name zxcv
Date 2000-10-24 17:09:37 PDT
Message User: ms
  Date: 00/10/24 17:09:37

  Added: java/org/joist/util Command.java Debug.java Timer.java
                        Trace.java
  Log:
  The Carl Ludwig code now repackaged in org.joist.util
  Submitted by: Michael Salmon
  
  Revision Changes Path
  1.1 joist/java/org/joist​/util/Command.java
  
  Index: Command.java
  ====================​====================​====================​=======
  // Copyright (c) 1997 by CJ Software. All rights reserved.
  
  package org.joist.util;
  
  import java.io.*;
  import java.util.*;
  
  /**
   * Utility for invoking a subprocess and capturing its output.
   */
  public class Command
  {
      static final int EOF = -1;
  
      protected Vector env;
  
      /**
       * Creates a command object. The capacity is used to initial the environment
       * variable list. This is useful if the number of variables passed is expected
       * to be large.
       */
      public Command(int initialEnvCapacity)
      {
          env = new Vector(initialEnvCapacity);
      }
  
      /**
       * Creates a command object.
       */
      public Command()
      {
          env = new Vector();
      }
  
      /**
       * Adds the contents of the hashtable to the environment. The keys are the
       * variable names and the data the values.
       */
      public void addToEnv(Hashtable vars)
      {
          if (Trace.ON) Trace.start("Command​.addToEnv(Hashtable)​"); try {
  
          Enumeration e = vars.keys();
          while (e.hasMoreElements())
          {
              String name = (String)e.nextElement();
              env.addElement(new String(name + "=" + vars.get(name)));
          }
  
          } finally { if (Trace.ON) Trace.stop("Command.​addToEnv(Hashtable)"​); }
      }
  
      /**
       * Adds a list of name value pairs to the environment. They should be in the
       * form "NAME=VALUE".
       */
      public void addToEnv(String[] vars)
      {
          if (Trace.ON) Trace.start("Command​.addToEnv(String[])"​); try {
  
          for (int i = 0; i < vars.length; i++)
              env.addElement(vars[i]);
  
          } finally { if (Trace.ON) Trace.stop("Command.​addToEnv(String[])")​; }
      }
  
      /**
       * Prints the environment on standard output.
       */
      public void debugEnv()
      {
          Debug.log("env: " + env);
      }
  
      /**
       * Prints the environment to a file. In this case, the enviroment is written
       * in the form "export 'NAME'='VALUE'" suitable for sourcing by the Unix bourne
       * shell.
       */
      public void debugEnv(String file)
          throws IOException
      {
          FileWriter f = new FileWriter(file);
          Enumeration e = env.elements();
          while (e.hasMoreElements())
          {
              String pair = (String)e.nextElement();
              int i = pair.indexOf('=');
              String name = pair.substring(0, i);
              String value = pair.substring(i + 1);
              f.write("export \'" + name + "\'=\'" + value + "'\n");
          }
          f.close();
      }
  
      /**
       * Executes the command in a subprocess and returns the results. The command is
       * executed synchronously.
       */
      public void exec(String command, StringBuffer results)
          throws IOException
      {
          if (Trace.ON) Trace.start("Command.exec"); try {
  
          String temp[] = new String[env.size()];
          env.copyInto(temp);
          Runtime rt = Runtime.getRuntime();
          Process p = rt.exec(command, temp);
          InputStream is = new BufferedInputStream(​p.getInputStream());​
          int c;
          while ((c = is.read()) != EOF)
              results.append((char)c);
          is.close();
  
          } finally { if (Trace.ON) Trace.stop("Command.exec"); }
      }
  }
  
  
  
  1.1 joist/java/org/joist​/util/Debug.java
  
  Index: Debug.java
  ====================​====================​====================​=======
  // Copyright (c) 1997 by CJ Software. All rights reserved.
  
  package org.joist.util;
  
  import java.io.*;
  
  /**
      Useful debugging utilities. The value of ON is set at runtime via the property
      cj.debug=true. This is useful for creating optional debugging statements, as in:
      <blockquote>
      <pre>
      if (Debug.ON) Debug.log("Status message: " + message);
      </pre>
      </blockquote>
  */
  public class Debug
  {
      /** Set via cj.debug property. */
      public static final boolean ON = active();
  
      private static PrintStream errorStream = System.err;
      private static PrintStream logStream = System.out;
  
      /** Prints a message to the error stream. Date, time and thread name are added. */
      public static void error(String message)
      {
          print(errorStream, message);
      }
  
      /** Prints a message to the log stream. Date, time and thread name are added. */
      public static void log(String message)
      {
          print(logStream, message);
      }
  
      /** Sets the error stream. Defaults to standard error. */
      public static void setErrorStream(OutputStream os)
      {
          if (os != null) errorStream = new PrintStream(os);
      }
  
      /** Sets the log stream. Defaults to standard output. */
      public static void setLogStream(OutputStream os)
      {
          if (os != null) logStream = new PrintStream(os);
      }
  
      static boolean active()
      {
          String property = System.getProperty("cj.debug");
          if (property != null)
              return Boolean.valueOf(prop​erty).booleanValue()​;
          else
              return false;
      }
  
      static void print(PrintStream ps, String message)
      {
          // Add timestamp & thread name to the message.
          String temp = new String(
              (new java.util.Date()).toString()
              + " - " + Thread.currentThread​().getName()
              + " - " + message);
          ps.println(temp);
      }
  }
  
  
  
  
  1.1 joist/java/org/joist​/util/Timer.java
  
  Index: Timer.java
  ====================​====================​====================​=======
  // Copyright (c) 1997 by CJ Software. All rights reserved.
  
  package org.joist.util;
  
  import java.util.*;
  
  /**
      A stopwatch class. Measures real time in milliseconds.
  */
  public class Timer
  {
      Date startTime;
      double seconds;
      double totalSeconds;
  
      /**
          Creates a new timer. The timer does not start running until start is called.
      */
      public Timer()
      {
          reset();
      }
  
      /**
          Returns the time between start and stop. If the timer is running, it returns
          the time since start was called.
      */
      public double getSeconds()
      {
          return seconds + calcTime();
      }
  
      /**
          Returns the total time spent running since the timer was created. Useful for
          aggregating several invocations of start & stop.
      */
      public double getTotalSeconds()
      {
          return totalSeconds + calcTime();
      }
  
      /**
          Resets the timer. Both seconds and total seconds are cleared.
      */
      public void reset()
      {
          startTime = null;
          seconds = 0;
          totalSeconds = 0;
      }
  
      /**
          Starts the timer.
      */
      public void start()
      {
          if (timerRunning())
              return;
          startTime = new Date();
      }
  
      /**
          Stops the timer.
      */
      public void stop()
      {
          if (!timerRunning())
              return;
          seconds = calcTime();
          totalSeconds += seconds;
          startTime = null;
      }
  
      /**
          Returns true if the timer is running.
      */
      public boolean timerRunning()
      {
          return (startTime != null);
      }
  
      double calcTime()
      {
          if (!timerRunning())
              return 0.0;
          Date now = new Date();
          return (now.getTime() - startTime.getTime()) / 1000.0;
      }
  }
  
  
  
  1.1 joist/java/org/joist​/util/Trace.java
  
  Index: Trace.java
  ====================​====================​====================​=======
  // Copyright (c) 1997 by CJ Software. All rights reserved.
  
  package org.joist.util;
  
  import java.io.*;
  import java.text.*;
  import java.util.*;
  import gamelan.util.*;
  
  /**
   * Java trace facility. Useful for generating stack traces as a program executes.
   * Also times each function that is traced and can print out a summary performance
   * report. All timings are real (wall-clock) time. Below is an instrumented program
   * with some sample output. The try and finally blocks guarantee that the trace is
   * completed even if the method throws an exception:
   * <blockquote>
   * <pre>
   * import org.tigris.joist.util.*;
   * &nbsp;
   * class TraceTest
   * {
   * public static void main(String argv[])
   * throws InterruptedException
   * {
   * if (Trace.ON) Trace.start("main"); try {
   * &nbsp;
   * Thread.currentThread​().sleep(500);
   * f();
   * int i = g();
   * if (Debug.ON) Debug.log("i: " + i);
   * &nbsp;
   * } finally { if (Trace.ON) Trace.stop("main"); }
   * if (Trace.ON) Trace.printTotals();
   * }
   * &nbsp;
   * public static void f()
   * throws InterruptedException
   * {
   * if (Trace.ON) Trace.start("f"); try {
   * &nbsp;
   * Thread.currentThread​().sleep(200);
   * //throw new InterruptedException();
   * &nbsp;
   * } finally { if (Trace.ON) Trace.stop("f"); }
   * }
   * &nbsp;
   * public static int g()
   * throws InterruptedException
   * {
   * if (Trace.ON) Trace.start("g"); try {
   * &nbsp;
   * Thread.currentThread​().sleep(100);
   * f();
   * return 3;
   * &nbsp;
   * } finally { if (Trace.ON) Trace.stop("g"); }
   * }
   * }
   * &nbsp;
   * % java -Dcj.trace=true TraceTest
   * enter main-main
   * enter f-main
   * leave f-main 0.2s
   * enter g-main
   * enter f-main
   * leave f-main 0.2s
   * leave g-main 0.3s
   * leave main-main 1.011s
   * &nbsp;
   * Trace Totals
   * ------------
   * main 1 calls 1.011s total 1.011s avg.
   * g 1 calls 0.3s total 0.3s avg.
   * f 2 calls 0.4s total 0.2s avg.
   * </pre>
   * </blockquote>
   * Other properties which can be set are <b>cj.trace.de​tail</b>, which may be set to
   * false to disable the printing of enter/leave statements, and <b>cj.detail.p​attern</b>,
   * which will cause only the methods containing the string specified to be traced. You
   * may also set <b>cj.trace.lo​g</log> to the name of a file to redirect output to a file.
   */
  public class Trace
  {
      /** Set via the cj.trace property. */
      public static final boolean ON = active();
  
      private static final PrintWriter LOG = getLog();
      private static final boolean SHOW_DETAIL = showDetail();
      private static final String PATTERN = getPattern();
  
      private static final String ENTER = "enter ";
      private static final String LEAVE = "leave ";
      private static final String PAD = " ";
  
      private static NumberFormat format = getFormat();
      private static Hashtable levels = new Hashtable(); // entry per thread
      private static Hashtable timers = new Hashtable(); // entry per method+thread
      private static Hashtable totals = new Hashtable(); // entry per method
  
      /** Sorts and formats totals in a manner suitable for printing. */
      public static synchronized String getFormattedTotals()
      {
          // Sort the data from high to low time used.
          int i = 0;
          TraceData data[] = new TraceData[totals.size()];
          Enumeration e = totals.keys();
          while (e.hasMoreElements())
          {
              String method = (String)e.nextElement();
              TraceTotal t = (TraceTotal)totals.get(method);
              data[i++] = new TraceData(method, t);
          }
          HeapSort.sort(data);
          StringBuffer buf = new StringBuffer(512);
          buf.append("Trace Totals\n");
          buf.append("------------\n");
          for (i = 0; i < data.length; i++)
          {
              buf.append(
                  pad(data[i].method, 32, false) + " " +
                  pad(Integer.toString​(data[i].total.getCo​unt()), 4, true) + " calls " +
                  pad(format.format(da​ta[i].total.getTotal​()), 8, true) + "s total " +
                  pad(format.format(da​ta[i].total.getAvera​ge()), 8, true) + "s avg.\n");
          }
          return buf.toString();
      }
  
      /** Pads/truncates a string. */
      private static String pad(String s, int len, boolean rightJustify)
      {
          if (s.length() > len)
              s = s.substring(0, len-1) + '#';
          int padding = len - s.length();
          String pad = "";
          for (int i = 0; i < padding; i++)
              pad += " ";
          if (rightJustify)
              s = pad + s;
          else
              s = s + pad;
          return s;
      }
  
      /** Resets the trace totals data. */
      public static void reset()
      {
          totals.clear();
      }
  
      /** Begins trace of method. */
      public static void start(String method)
      {
          if (!doTrace(method))
              return;
  
          TraceKey key = new TraceKey(method);
          Timer t = (Timer)timers.get(key);
          if (t == null)
          {
              t = new Timer();
              timers.put(key, t);
          }
          TraceLevel l = (TraceLevel)levels.g​et(key.threadName);
          if (l == null)
          {
              l = new TraceLevel();
              levels.put(key.threadName, l);
          }
          if (SHOW_DETAIL)
          {
              String pad = new String();
              for (int i = 0; i < l.level; i++)
                  pad += PAD;
              LOG.println(pad + ENTER + key);
          }
          l.level++;
          t.start();
      }
  
      /** Ends trace of method. */
      public static void stop(String method)
      {
          if (!doTrace(method))
              return;
  
          TraceKey key = new TraceKey(method);
          Timer t = (Timer)timers.get(key);
          if (t == null)
          {
              System.err.println(
                  "Trace.stop: No trace started for " + key);
              return;
          }
          t.stop();
          TraceLevel l = (TraceLevel)levels.g​et(key.threadName);
          if (l == null)
          {
              System.err.println(
                  "Trace.stop: Internal error; no level for thread "
                  + key.threadName);
              return;
          }
          l.level--;
          if (SHOW_DETAIL)
          {
              String pad = new String();
              for (int i = 0; i < l.level; i++)
                  pad += PAD;
              LOG.println(pad + LEAVE + key + " " + t.getSeconds() + "s");
          }
          updateTotals(key.method, t.getSeconds());
      }
  
      /** Prints performance summary. */
      public static synchronized void printTotals()
      {
          printTotals(LOG);
      }
  
      /** Prints performance summary. */
      public static synchronized void printTotals(PrintStream ps)
      {
          printTotals(new PrintWriter(ps, true));
      }
  
      /** Prints performance summary. */
      public static synchronized void printTotals(PrintWriter writer)
      {
          writer.println("\n" + getFormattedTotals());
      }
  
      static boolean active()
      {
          String property = System.getProperty("cj.trace");
          if (property != null)
              return Boolean.valueOf(prop​erty).booleanValue()​;
          else
              return false;
      }
  
      static boolean doTrace(String method)
      {
          return (PATTERN == null || method.indexOf(PATTERN) != -1);
      }
  
      static NumberFormat getFormat()
      {
          NumberFormat format = NumberFormat.getInstance();
          format.setMinimumFra​ctionDigits(3);
          format.setMaximumFra​ctionDigits(3);
          return format;
      }
      
      static PrintWriter getLog()
      {
          try
          {
              String fileName = System.getProperty("​cj.trace.log");
              if (fileName != null && fileName.trim().length() > 0)
              {
                  return new PrintWriter(new FileWriter(fileName, true), true);
              }
          }
          catch (Exception e)
          {
              System.err.println("Can't open trace log: " + e);
          }
          return new PrintWriter(System.out, true);
      }
      
      static String getPattern()
      {
          return System.getProperty("​cj.trace.pattern");
      }
  
      static boolean showDetail()
      {
          String property = System.getProperty("​cj.trace.detail");
          if (property != null)
              return Boolean.valueOf(prop​erty).booleanValue()​;
          else
              return true;
      }
  
      static synchronized void updateTotals(String method, double seconds)
      {
          TraceTotal t = (TraceTotal)totals.get(method);
          if (t == null)
          {
              t = new TraceTotal();
              totals.put(method, t);
          }
          t.add(seconds);
      }
  }
  
  class TraceKey
  {
      String method;
      String threadName;
  
      TraceKey(String method)
      {
          this.method = method;
          this.threadName = Thread.currentThread​().getName();
      }
  
      public boolean equals(Object o)
      {
          return (this.getClass() == o.getClass()
              && this.method.equals((​(TraceKey)o).method)​
              && this.threadName.equa​ls(((TraceKey)o).thr​eadName));
      }
  
      public int hashCode()
      {
          return toString().hashCode();
      }
  
      public String toString()
      {
          return new String(method + "-" + threadName);
      }
  }
  
  class TraceLevel
  {
      int level = 0;
  }
  
  class TraceData implements gamelan.util.Comparable
  {
      String method;
      TraceTotal total;
  
      TraceData(String method, TraceTotal total)
      {
          this.method = method;
          this.total = total;
      }
  
      public int compareTo(gamelan.ut​il.Comparable comp)
      {
          // Reverse order sort.
          if (this.total.seconds < ((TraceData)comp).to​tal.seconds)
              return 1;
          else if (this.total.seconds > ((TraceData)comp).to​tal.seconds)
              return -1;
          else
              return 0;
      }
  }
  
  class TraceTotal
  {
      double seconds;
      int count;
  
      TraceTotal()
      {
          this.seconds = 0.0;
          count = 0;
      }
  
      void add(double seconds)
      {
          this.seconds += seconds;
          count++;
      }
  
      double getAverage()
      {
          return seconds / count;
      }
  
      int getCount()
      {
          return count;
      }
  
      double getTotal()
      {
          return seconds;
      }
  }

« Previous message in topic | 1 of 1 | Next message in topic »

Messages

Show all messages in topic

CVS update: joist/java/org/joist/util Command.java Debug.java Timer.java Trace.java ms zxcv 2000-10-24 17:09:37 PDT
Messages per page: