content: /*
   * Copyright (C) 2008 The Android Open Source Project
   *
   * 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.
   */
  
  import java.util.List;
  import java.util.ArrayList;
  import java.io.Serializable;
  
  /**
   * An operation with a duration. Could represent a class load or initialization.
   */
  class Operation implements Serializable {
  
      private static final long serialVersionUID = 0;
      
      /**
       * Type of operation.
       */
      enum Type {
          LOAD, INIT
      }
  
      /** Process this operation occurred in. */
      final Proc process;
  
      /** Start time for this operation. */
      final long startTimeNanos;
  
      /** Index of this operation relative to its process. */
      final int index;
  
      /** Type of operation. */
      final Type type;
  
      /** End time for this operation. */
      long endTimeNanos = -1;
  
      /** The class that this operation loaded or initialized. */
      final LoadedClass loadedClass;
  
      /** Other operations that occurred during this one. */
      final List<Operation> subops = new ArrayList<Operation>();
  
      /** Constructs a new operation. */
      Operation(Proc process, LoadedClass loadedClass, long startTimeNanos,
              int index, Type type) {
          this.process = process;
          this.loadedClass = loadedClass;
          this.startTimeNanos = startTimeNanos;
          this.index = index;
          this.type = type;
      }
  
      /**
       * Returns how long this class initialization and all the nested class
       * initializations took.
       */
      private long inclusiveTimeNanos() {
          if (endTimeNanos == -1) {
              throw new IllegalStateException("End time hasn't been set yet: "
                      + loadedClass.name);
          }
  
          return endTimeNanos - startTimeNanos;
      }
  
      /**
       * Returns how long this class initialization took.
       */
      int exclusiveTimeMicros() {
          long exclusive = inclusiveTimeNanos();
  
          for (Operation child : subops) {
              exclusive -= child.inclusiveTimeNanos();
          }
  
          if (exclusive < 0) {
              throw new AssertionError(loadedClass.name);
          }
  
          return nanosToMicros(exclusive);
      }
  
      /** Gets the median time that this operation took across all processes. */
      int medianExclusiveTimeMicros() {
          switch (type) {
              case LOAD: return loadedClass.medianLoadTimeMicros();
              case INIT: return loadedClass.medianInitTimeMicros();
              default: throw new AssertionError();
          }
      }
  
      /**
       * Converts nanoseconds to microseconds.
       *
       * @throws RuntimeException if overflow occurs
       */
      private static int nanosToMicros(long nanos) {
          long micros = nanos / 1000;
          int microsInt = (int) micros;
          if (microsInt != micros) {
              throw new RuntimeException("Integer overflow: " + nanos);
          }
          return microsInt;
      }
      
      /**
       * Primarily for debugger support
       */
      @Override
      public String toString() {
          StringBuilder sb = new StringBuilder();
          sb.append(type.toString());
          sb.append(' ');
          sb.append(loadedClass.toString());
          if (subops.size() > 0) {
              sb.append(" (");
              sb.append(subops.size());
              sb.append(" sub ops)");
          }
          return sb.toString();
      }
  
  }
  