/**
   * Indicates whether the provided job iteration has an acceptable CPU utilization.
   *
   * @param iteration The iteration for which to make the determination.
   * @return <CODE>true</CODE> if the CPU utilization for the provided iteration is acceptable, or
   *     <CODE>false</CODE> if not.
   * @throws SLAMDException If the provided iteration does not include sufficient CPU utilization
   *     data to make the determination.
   */
  private boolean isAcceptableReplicationLatency(Job iteration) throws SLAMDException {
    boolean latencyFound = false;

    String className = ReplicationLatencyResourceMonitor.class.getName();
    ResourceMonitorStatTracker[] monitorTrackers =
        iteration.getResourceMonitorStatTrackersForClass(className);

    for (int i = 0; i < monitorTrackers.length; i++) {
      StatTracker tracker = monitorTrackers[i].getStatTracker();
      String name = tracker.getDisplayName();

      if ((tracker instanceof TimeTracker)
          && name.endsWith(ReplicationLatencyResourceMonitor.STAT_TRACKER_REPLICATION_LATENCY)) {
        latencyFound = true;

        if (maxLatency > 0) {
          TimeTracker latencyTimer = (TimeTracker) tracker;
          double averageLatency = latencyTimer.getAverageDuration();
          if (averageLatency > maxLatency) {
            return false;
          }

          int[] intervalDurations = latencyTimer.getIntervalDurations();
          int[] intervalCounts = latencyTimer.getIntervalCounts();
          int numIntervals = intervalCounts.length;
          int quarterOfIntervals = numIntervals / 4;

          int firstTotal = 0;
          int firstCount = 0;
          int lastTotal = 0;
          int lastCount = 0;
          for (int j = 0; j < quarterOfIntervals; j++) {
            firstTotal += intervalDurations[j];
            firstCount += intervalCounts[j];
            lastTotal += intervalDurations[numIntervals - quarterOfIntervals + j];
            lastCount += intervalCounts[numIntervals - quarterOfIntervals + j];
          }

          if ((firstCount == 0) || (lastCount == 0)) {
            return false;
          }

          double firstAvg = 1.0 * firstTotal / firstCount;
          double lastAvg = 1.0 * lastTotal / lastCount;
          if (lastAvg > firstAvg) {
            double pctIncrease = (lastAvg - firstAvg) / firstAvg * 100.0;
            if (pctIncrease > maxIncrease) {
              return false;
            }
          }
        }
      }
    }

    if (!latencyFound) {
      throw new SLAMDException(
          "The provided job iteration did not include " + "any replication latency data.");
    }

    return true;
  }
  /**
   * Indicates whether the provided job iteration has an acceptable CPU utilization.
   *
   * @param iteration The iteration for which to make the determination.
   * @return <CODE>true</CODE> if the CPU utilization for the provided iteration is acceptable, or
   *     <CODE>false</CODE> if not.
   * @throws SLAMDException If the provided iteration does not include sufficient CPU utilization
   *     data to make the determination.
   */
  private boolean isAcceptableCPUUtilization(Job iteration) throws SLAMDException {
    SLAMDServer slamdServer = iteration.slamdServer;
    boolean utilizationFound = false;

    String className = VMStatResourceMonitor.class.getName();
    ResourceMonitorStatTracker[] monitorTrackers =
        iteration.getResourceMonitorStatTrackersForClass(className);
    for (int i = 0; i < monitorTrackers.length; i++) {
      StatTracker tracker = monitorTrackers[i].getStatTracker();
      String name = tracker.getDisplayName();

      if ((tracker instanceof StackedValueTracker)
          && name.endsWith(VMStatResourceMonitor.STAT_TRACKER_CPU_UTILIZATION)) {
        utilizationFound = true;
        StackedValueTracker utilizationTracker = (StackedValueTracker) tracker;
        double userTime =
            utilizationTracker.getAverageValue(VMStatResourceMonitor.UTILIZATION_CATEGORY_USER);
        double systemTime =
            utilizationTracker.getAverageValue(VMStatResourceMonitor.UTILIZATION_CATEGORY_SYSTEM);
        double busyTime = userTime + systemTime;

        switch (utilizationComponent) {
          case UTILIZATION_COMPONENT_USER_TIME:
            if (userTime > maxUtilization) {
              slamdServer.logMessage(
                  Constants.LOG_LEVEL_JOB_DEBUG,
                  "SingleStatisticWithCPUUtilization"
                      + "OptimizationAlgorithm.isAcceptableCPU"
                      + "Utilization("
                      + iteration.getJobID()
                      + ") returning false because user time of "
                      + userTime
                      + " for stat "
                      + tracker.getDisplayName()
                      + " exceeded the maximum allowed of "
                      + maxUtilization);
              return false;
            }
            break;
          case UTILIZATION_COMPONENT_SYSTEM_TIME:
            if (systemTime > maxUtilization) {
              slamdServer.logMessage(
                  Constants.LOG_LEVEL_JOB_DEBUG,
                  "SingleStatisticWithCPUUtilization"
                      + "OptimizationAlgorithm.isAcceptableCPU"
                      + "Utilization("
                      + iteration.getJobID()
                      + ") returning false because system time "
                      + "of "
                      + systemTime
                      + " for stat "
                      + tracker.getDisplayName()
                      + " exceeded the maximum allowed of "
                      + maxUtilization);
              return false;
            }
            break;
          case UTILIZATION_COMPONENT_BUSY_TIME:
            if (busyTime > maxUtilization) {
              slamdServer.logMessage(
                  Constants.LOG_LEVEL_JOB_DEBUG,
                  "SingleStatisticWithCPUUtilization"
                      + "OptimizationAlgorithm.isAcceptableCPU"
                      + "Utilization("
                      + iteration.getJobID()
                      + ") returning false because busy time of "
                      + busyTime
                      + " for stat "
                      + tracker.getDisplayName()
                      + " exceeded the maximum allowed of "
                      + maxUtilization);
              return false;
            }
            break;
          default:
            slamdServer.logMessage(
                Constants.LOG_LEVEL_JOB_DEBUG,
                "SingleStatisticWithCPUUtilization"
                    + "OptimizationAlgorithm.isAcceptableCPU"
                    + "Utilization("
                    + iteration.getJobID()
                    + ") returning false because an unknown "
                    + "utilization component of "
                    + utilizationComponent
                    + " is in use.");
            return false;
        }
      } else if ((tracker instanceof IntegerValueTracker)
              && ((utilizationComponent == UTILIZATION_COMPONENT_USER_TIME)
                  && name.endsWith(VMStatResourceMonitor.STAT_TRACKER_CPU_USER))
          || ((utilizationComponent == UTILIZATION_COMPONENT_SYSTEM_TIME)
              && name.endsWith(VMStatResourceMonitor.STAT_TRACKER_CPU_SYSTEM))
          || ((utilizationComponent == UTILIZATION_COMPONENT_BUSY_TIME)
              && name.endsWith(VMStatResourceMonitor.STAT_TRACKER_CPU_BUSY))) {
        utilizationFound = true;
        double value = ((IntegerValueTracker) tracker).getAverageValue();
        if (value > maxUtilization) {
          slamdServer.logMessage(
              Constants.LOG_LEVEL_JOB_DEBUG,
              "SingleStatisticWithCPUUtilization"
                  + "OptimizationAlgorithm.isAcceptableCPU"
                  + "Utilization("
                  + iteration.getJobID()
                  + ") returning false because value of "
                  + value
                  + " for stat "
                  + tracker.getDisplayName()
                  + " exceeded the maximum allowed of "
                  + maxUtilization);
          return false;
        }
      }
    }

    if (!utilizationFound) {
      throw new SLAMDException(
          "The provided job iteration did not include " + "any CPU utilization data.");
    }

    slamdServer.logMessage(
        Constants.LOG_LEVEL_JOB_DEBUG,
        "SingleStatisticWithCPUUtilizationOptimization"
            + "Algorithm.isAcceptableCPUUtilization("
            + iteration.getJobID()
            + ") returning true.");
    return true;
  }