geode-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kl...@apache.org
Subject [17/24] incubator-geode git commit: GEODE-1781: refactor internal statistics classes
Date Thu, 18 Aug 2016 16:30:51 GMT
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/750996a0/geode-core/src/main/java/com/gemstone/gemfire/internal/StatArchiveReader.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/StatArchiveReader.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/StatArchiveReader.java
deleted file mode 100644
index 0947b0d..0000000
--- a/geode-core/src/main/java/com/gemstone/gemfire/internal/StatArchiveReader.java
+++ /dev/null
@@ -1,3338 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 com.gemstone.gemfire.internal;
-
-import com.gemstone.gemfire.GemFireIOException;
-import com.gemstone.gemfire.InternalGemFireException;
-import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
-import com.gemstone.gemfire.internal.logging.DateFormatter;
-
-import java.io.BufferedInputStream;
-import java.io.DataInputStream;
-import java.io.EOFException;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.text.DateFormat;
-import java.text.NumberFormat;
-import java.text.SimpleDateFormat;
-import java.util.AbstractList;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.SimpleTimeZone;
-import java.util.TimeZone;
-import java.util.zip.GZIPInputStream;
-
-/**
- * StatArchiveReader provides APIs to read statistic snapshots from an archive
- * file.
- */
-public class StatArchiveReader implements StatArchiveFormat {
-  
-  protected static final NumberFormat nf = NumberFormat.getNumberInstance();
-  static {
-    nf.setMaximumFractionDigits(2);
-    nf.setGroupingUsed(false);
-  }
-
-  private final StatArchiveFile[] archives;
-  private boolean dump;
-  private boolean closed = false;
-
-  /**
-   * Creates a StatArchiveReader that will read the named archive file.
-   * @param autoClose if its <code>true</code> then the reader will close
-   *   input files as soon as it finds their end.
-   * @throws IOException if <code>archiveName</code> could not be opened
-   * read, or closed.
-   */
-  public StatArchiveReader(File[] archiveNames, ValueFilter[] filters, boolean autoClose)
-    throws IOException
-  {
-    this.archives = new StatArchiveFile[archiveNames.length];
-    this.dump = Boolean.getBoolean("StatArchiveReader.dumpall");
-    for (int i=0; i < archiveNames.length; i++) {
-      this.archives[i] = new StatArchiveFile(this, archiveNames[i], dump, filters);
-    }
-
-    update(false, autoClose);
-    
-    if (this.dump || Boolean.getBoolean("StatArchiveReader.dump")) {
-      this.dump(new PrintWriter(System.out));
-    }
-  }
-
-  /**
-   * Creates a StatArchiveReader that will read the named archive file.
-   * @throws IOException if <code>archiveName</code> could not be opened
-   * read, or closed.
-   */
-  public StatArchiveReader(String archiveName) throws IOException {
-    this(new File[]{new File(archiveName)}, null, false);
-  }
-
-  /**
-   * Returns an array of stat values that match the specified spec.
-   * If nothing matches then an empty array is returned.
-   */
-  public StatValue[] matchSpec(StatSpec spec) {
-    if (spec.getCombineType() == StatSpec.GLOBAL) {
-      StatValue[] allValues = matchSpec(new RawStatSpec(spec));
-      if (allValues.length == 0) {
-        return allValues;
-      } else {
-        ComboValue cv = new ComboValue(allValues);
-        // need to save this in reader's combo value list
-        return new StatValue[]{cv};
-      }
-    } else {
-      List l = new ArrayList();
-      StatArchiveReader.StatArchiveFile[] archives = getArchives();
-      for (int i=0; i < archives.length; i++) {
-        StatArchiveFile f = archives[i];
-        if (spec.archiveMatches(f.getFile())) {
-          f.matchSpec(spec, l);
-        }
-      }
-      StatValue[] result = new StatValue[l.size()];
-      return (StatValue[])l.toArray(result);
-    }
-  }
-  
-  /**
-   * Checks to see if any archives have changed since the StatArchiverReader
-   * instance was created or last updated. If an archive has additional
-   * samples then those are read the resource instances maintained by the
-   * reader are updated.
-   * <p>Once closed a reader can no longer be updated.
-   * @return true if update read some new data.
-   * @throws IOException if an archive could not be opened
-   * read, or closed.
-   */
-  public boolean update() throws IOException {
-    return update(true, false);
-  }
-  private boolean update(boolean doReset, boolean autoClose) throws IOException {
-    if (this.closed) {
-      return false;
-    }
-    boolean result = false;
-    StatArchiveReader.StatArchiveFile[] archives = getArchives();
-    for (int i=0; i < archives.length; i++) {
-      StatArchiveFile f = archives[i];
-      if (f.update(doReset)) {
-        result = true;
-      }
-      if (autoClose) {
-        f.close();
-      }
-    }
-    return result;
-  }
-
-  /**
-   * Returns an unmodifiable list of all the {@link ResourceInst}
-   * this reader contains.
-   */
-  public List getResourceInstList() {
-    return new ResourceInstList();
-  }
-
-  public StatArchiveFile[] getArchives() {
-    return this.archives;
-  }
-  
-  /**
-   * Closes all archives.
-   */
-  public void close() throws IOException {
-    if (!this.closed) {
-      StatArchiveReader.StatArchiveFile[] archives = getArchives();
-      for (int i=0; i < archives.length; i++) {
-        StatArchiveFile f = archives[i];
-        f.close();
-      }
-      this.closed = true;
-    }
-  }
-
-  private int getMemoryUsed()  {
-    int result = 0;
-    StatArchiveReader.StatArchiveFile[] archives = getArchives();
-    for (int i=0; i < archives.length; i++) {
-      StatArchiveFile f = archives[i];
-      result += f.getMemoryUsed();
-    }
-    return result;
-  }
-
-  private void dump(PrintWriter stream) {
-    StatArchiveReader.StatArchiveFile[] archives = getArchives();
-    for (int i=0; i < archives.length; i++) {
-      StatArchiveFile f = archives[i];
-      f.dump(stream);
-    }
-  }
-
-  protected static double bitsToDouble(int type, long bits) {
-    switch (type) {
-    case BOOLEAN_CODE:
-    case BYTE_CODE:
-    case CHAR_CODE:
-    case WCHAR_CODE:
-    case SHORT_CODE:
-    case INT_CODE:
-    case LONG_CODE:
-      return bits;
-    case FLOAT_CODE:
-      return Float.intBitsToFloat((int)bits);
-    case DOUBLE_CODE:
-      return Double.longBitsToDouble(bits);
-    default:
-      throw new InternalGemFireException(LocalizedStrings.StatArchiveReader_UNEXPECTED_TYPECODE_0.toLocalizedString(Integer.valueOf(type)));
-    }
-  }
-  
-  /**
-   * Simple utility to read and dump statistic archive.
-   */
-  public static void main(String args[]) throws IOException {
-    String archiveName = null;
-    if (args.length > 1) {
-      System.err.println("Usage: [archiveName]");
-      System.exit(1);
-    } else if (args.length == 1) {
-      archiveName = args[0];
-    } else {
-      archiveName = "statArchive.gfs";
-    }
-    StatArchiveReader reader = new StatArchiveReader(archiveName);
-    System.out.println("DEBUG: memory used = " + reader.getMemoryUsed());
-    reader.close();
-  }
-
-  /**
-   * Wraps an instance of StatSpec but alwasy returns a combine type of NONE.
-   */
-  private static class RawStatSpec implements StatSpec {
-    private final StatSpec spec;
-    RawStatSpec(StatSpec wrappedSpec) {
-      this.spec = wrappedSpec;
-    }
-    public int getCombineType() {
-      return StatSpec.NONE;
-    }
-    public boolean typeMatches(String typeName) {
-      return spec.typeMatches(typeName);
-    }
-    public boolean statMatches(String statName) {
-      return spec.statMatches(statName);
-    }
-    public boolean instanceMatches(String textId, long numericId) {
-      return spec.instanceMatches(textId, numericId);
-    }
-    public boolean archiveMatches(File archive) {
-      return spec.archiveMatches(archive);
-    }
-  }
-    
-  private class ResourceInstList extends AbstractList {
-    protected ResourceInstList() {
-      // nothing needed.
-    }
-    @Override
-    public Object get(int idx) {
-      int archiveIdx = 0;
-      StatArchiveReader.StatArchiveFile[] archives = getArchives();
-      for (int i=0; i < archives.length; i++) {
-        StatArchiveFile f = archives[i];
-        if (idx < (archiveIdx + f.resourceInstSize)) {
-          return f.resourceInstTable[idx - archiveIdx];
-        }
-        archiveIdx += f.resourceInstSize;
-      }
-      return null;
-    }
-    @Override
-    public int size() {
-      int result = 0;
-      StatArchiveReader.StatArchiveFile[] archives = getArchives();
-      for (int i=0; i < archives.length; i++) {
-        result += archives[i].resourceInstSize;
-      }
-      return result;
-    }
-  }
-
-  /**
-   * Describes a single statistic.
-   */
-  public static class StatDescriptor {
-    private boolean loaded;
-    private String name;
-    private final int offset;
-    private final boolean isCounter;
-    private final boolean largerBetter;
-    private final byte typeCode;
-    private String units;
-    private String desc;
-
-    protected void dump(PrintWriter stream) {
-      stream.println("  " + name + ": type=" + typeCode + " offset=" + offset
-                     + (isCounter? " counter" : "")
-                     + " units=" + units
-                     + " largerBetter=" + largerBetter
-                     + " desc=" + desc);
-    }
-    
-    protected StatDescriptor(String name, int offset, boolean isCounter,
-                           boolean largerBetter,
-                           byte typeCode, String units, String desc) {
-      this.loaded = true;
-      this.name = name;
-      this.offset = offset;
-      this.isCounter = isCounter;
-      this.largerBetter = largerBetter;
-      this.typeCode = typeCode;
-      this.units = units;
-      this.desc = desc;
-    }
-    public boolean isLoaded() {
-      return this.loaded;
-    }
-    void unload() {
-      this.loaded = false;
-      this.name = null;
-      this.units = null;
-      this.desc = null;
-    }
-    /**
-     * Returns the type code of this statistic.
-     * It will be one of the following values:
-     * <ul>
-     * <li> {@link #BOOLEAN_CODE}
-     * <li> {@link #WCHAR_CODE}
-     * <li> {@link #CHAR_CODE}
-     * <li> {@link #BYTE_CODE}
-     * <li> {@link #SHORT_CODE}
-     * <li> {@link #INT_CODE}
-     * <li> {@link #LONG_CODE}
-     * <li> {@link #FLOAT_CODE}
-     * <li> {@link #DOUBLE_CODE}
-     * </ul>
-     */
-    public byte getTypeCode() {
-      return this.typeCode;
-    }
-    /**
-     * Returns the name of this statistic.
-     */
-    public String getName() {
-      return this.name;
-    }
-    /**
-     * Returns true if this statistic's value will always increase.
-     */
-    public boolean isCounter() {
-      return this.isCounter;
-    }
-    /**
-     * Returns true if larger values indicate better performance.
-     */
-    public boolean isLargerBetter() {
-      return this.largerBetter;
-    }
-    /**
-     * Returns a string that describes the units this statistic measures.
-     */
-    public String getUnits() {
-      return this.units;
-    }
-    /**
-     * Returns a textual description of this statistic.
-     */
-    public String getDescription() {
-      return this.desc;
-    }
-    /**
-     * Returns the offset of this stat in its type.
-     */
-    public int getOffset() {
-      return this.offset;
-    }
-  }
-
-  public static interface StatValue {
-    /**
-     * {@link StatArchiveReader.StatValue} filter that causes the
-     * statistic values to be unfiltered. This causes the raw values
-     * written to the archive to be used.
-     * <p>This is the default filter for non-counter statistics.
-     * To determine if a statistic is not a counter use {@link StatArchiveReader.StatDescriptor#isCounter}.  */
-    public static final int FILTER_NONE = 0;
-    /**
-     * {@link StatArchiveReader.StatValue} filter that causes the
-     * statistic values to be filtered to reflect how often they
-     * change per second.  Since the difference between two samples is
-     * used to calculate the value this causes the {@link StatArchiveReader.StatValue}
-     * to have one less sample than {@link #FILTER_NONE}. The instance
-     * time stamp that does not have a per second value is the
-     * instance's first time stamp {@link
-     * StatArchiveReader.ResourceInst#getFirstTimeMillis}.
-     * <p>This is the default filter for counter statistics.
-     * To determine if a statistic is a counter use {@link StatArchiveReader.StatDescriptor#isCounter}.  */
-    public static final int FILTER_PERSEC = 1;
-    /**
-     * {@link StatArchiveReader.StatValue} filter that causes the
-     * statistic values to be filtered to reflect how much they
-     * changed between sample periods.  Since the difference between
-     * two samples is used to calculate the value this causes the
-     * {@link StatArchiveReader.StatValue} to have one less sample than {@link
-     * #FILTER_NONE}. The instance time stamp that does not have a per
-     * second value is the instance's first time stamp {@link
-     * StatArchiveReader.ResourceInst#getFirstTimeMillis}.
-     */
-    public static final int FILTER_PERSAMPLE = 2;
-    /**
-     * Creates and returns a trimmed version of this stat value.
-     * Any samples taken before <code>startTime</code> and after
-     * <code>endTime</code> are discarded from the resulting value.
-     * Set a time parameter to <code>-1</code> to not trim that side.
-     */
-    public StatValue createTrimmed(long startTime, long endTime);
-    /**
-     * Returns true if value has data that has been trimmed off it
-     * by a start timestamp.
-     */
-    public boolean isTrimmedLeft();
-    /**
-     * Gets the {@link StatArchiveReader.ResourceType type} of the
-     * resources that this value belongs to.
-     */
-    public ResourceType getType();
-    /**
-     * Gets the {@link StatArchiveReader.ResourceInst resources} that this value
-     * belongs to.
-     */
-    public ResourceInst[] getResources();
-    /**
-     * Returns an array of timestamps for each unfiltered snapshot in this value.
-     * Each returned time stamp is the number of millis since
-     * midnight, Jan 1, 1970 UTC.
-     */
-    public long[] getRawAbsoluteTimeStamps();
-    /**
-     * Returns an array of timestamps for each unfiltered snapshot in this value.
-     * Each returned time stamp is the number of millis since
-     * midnight, Jan 1, 1970 UTC.
-     * The resolution is seconds.
-     */
-    public long[] getRawAbsoluteTimeStampsWithSecondRes();
-    /**
-     * Returns an array of doubles containing the unfiltered value of this
-     * statistic for each point in time that it was sampled.
-     */
-    public double[] getRawSnapshots();
-    /**
-     * Returns an array of doubles containing the filtered value of this
-     * statistic for each point in time that it was sampled.
-     */
-    public double[] getSnapshots();
-    /**
-     * Returns the number of samples taken of this statistic's value.
-     */
-    public int getSnapshotsSize();
-    /**
-     * Returns the smallest of all the samples taken of this statistic's value.
-     */
-    public double getSnapshotsMinimum();
-    /**
-     * Returns the largest of all the samples taken of this statistic's value.
-     */
-    public double getSnapshotsMaximum();
-    /**
-     * Returns the average of all the samples taken of this statistic's value.
-     */
-    public double getSnapshotsAverage();
-    /**
-     * Returns the standard deviation of all the samples taken of this statistic's value.
-     */
-    public double getSnapshotsStandardDeviation();
-    /**
-     * Returns the most recent value of all the samples taken of this statistic's value.
-     */
-    public double getSnapshotsMostRecent();
-    /**
-     * Returns true if sample whose value was different from previous values
-     * has been added to this StatValue since the last time this method was
-     * called.
-     */
-    public boolean hasValueChanged();
-    /**
-     * Returns the current filter used to calculate this statistic's values.
-     * It will be one of these values:
-     * <ul>
-     * <li> {@link #FILTER_NONE}
-     * <li> {@link #FILTER_PERSAMPLE}
-     * <li> {@link #FILTER_PERSEC}
-     * </ul>
-     */
-    public int getFilter();
-    /**
-     * Sets the current filter used to calculate this statistic's values.
-     * The default filter is {@link #FILTER_NONE} unless the statistic
-     * is a counter, {@link StatArchiveReader.StatDescriptor#isCounter},
-     * in which case its {@link #FILTER_PERSEC}.
-     * @param filter It must be one of these values:
-     * <ul>
-     * <li> {@link #FILTER_NONE}
-     * <li> {@link #FILTER_PERSAMPLE}
-     * <li> {@link #FILTER_PERSEC}
-     * </ul>
-     * @throws IllegalArgumentException if <code>filter</code> is not a valid filter constant.
-     */
-    public void setFilter(int filter);
-    /**
-     * Returns a description of this statistic.
-     */
-    public StatDescriptor getDescriptor();
-  }
-
-  protected static abstract class AbstractValue implements StatValue {
-    protected StatDescriptor descriptor;
-    protected int filter;
-
-    protected long startTime = -1;
-    protected long endTime = -1;
-
-    protected boolean statsValid = false;
-    protected int size;
-    protected double min;
-    protected double max;
-    protected double avg;
-    protected double stddev;
-    protected double mostRecent;
-
-    public void calcStats() {
-      if (!statsValid) {
-        getSnapshots();
-      }
-    }
-
-    public int getSnapshotsSize() {
-      calcStats();
-      return this.size;
-    }
-    public double getSnapshotsMinimum() {
-      calcStats();
-      return this.min;
-    }
-    public double getSnapshotsMaximum() {
-      calcStats();
-      return this.max;
-    }
-    public double getSnapshotsAverage() {
-      calcStats();
-      return this.avg;
-    }
-    public double getSnapshotsStandardDeviation() {
-      calcStats();
-      return this.stddev;
-    }
-    public double getSnapshotsMostRecent() {
-      calcStats();
-      return this.mostRecent;
-    }
-    public StatDescriptor getDescriptor() {
-      return this.descriptor;
-    }
-    public int getFilter() {
-      return this.filter;
-    }
-
-    public void setFilter(int filter) {
-      if (filter != this.filter) {
-        if (filter != FILTER_NONE
-            && filter != FILTER_PERSEC
-            && filter != FILTER_PERSAMPLE) {
-          throw new IllegalArgumentException(LocalizedStrings.StatArchiveReader_FILTER_VALUE_0_MUST_BE_1_2_OR_3
-              .toLocalizedString(
-              new Object[] {
-                  Integer.valueOf(filter),
-                  Integer.valueOf(FILTER_NONE),
-                  Integer.valueOf(FILTER_PERSEC),
-                  Integer.valueOf(FILTER_PERSAMPLE)}));
-        }
-        this.filter = filter;
-        this.statsValid = false;
-      }
-    }
-
-    /**
-     * Calculates each stat given the result of calling getSnapshots
-     */
-    protected void calcStats(double[] values) {
-      if (statsValid) {
-        return;
-      }
-      size = values.length;
-      if (size == 0) {
-        min = 0.0;
-        max = 0.0;
-        avg = 0.0;
-        stddev = 0.0;
-        mostRecent = 0.0;
-      } else {
-        min = values[0];
-        max = values[0];
-        mostRecent = values[values.length-1];
-        double total = values[0];
-        for (int i=1; i < size; i++) {
-          total += values[i];
-          if (values[i] < min) {
-            min = values[i];
-          } else if (values[i] > max) {
-            max = values[i];
-          }
-        }
-        avg = total / size;
-        stddev = 0.0;
-        if (size > 1) {
-          for (int i=0; i < size; i++) {
-            double dv = values[i] - avg;
-            stddev += (dv*dv);
-          }
-          stddev /= (size - 1);
-          stddev = Math.sqrt(stddev);
-        }
-      }
-      statsValid = true;
-    }
-
-    /**
-     * Returns a string representation of this object.
-     */
-    @Override
-    public String toString() {
-      calcStats();
-      StringBuffer result = new StringBuffer();
-      result.append(getDescriptor().getName());
-      String units = getDescriptor().getUnits();
-      if (units != null && units.length() > 0) {
-        result.append(' ').append(units);
-      }
-      if (filter == FILTER_PERSEC) {
-        result.append("/sec");
-      } else if (filter == FILTER_PERSAMPLE) {
-        result.append("/sample");
-      }
-      result.append(": samples=")
-        .append(getSnapshotsSize());
-      if (startTime != -1) {
-        result.append(" startTime=\"")
-          .append(new Date(startTime))
-          .append("\"");
-      }
-      if (endTime != -1) {
-        result.append(" endTime=\"")
-          .append(new Date(endTime))
-          .append("\"");
-      }
-      result.append(" min=")
-        .append(nf.format(min));
-      result.append(" max=")
-        .append(nf.format(max));
-      result.append(" average=")
-        .append(nf.format(avg));
-      result.append(" stddev=")
-        .append(nf.format(stddev));
-      result.append(" last=") // for bug 42532
-        .append(nf.format(mostRecent));
-      return result.toString();
-    }
-  }
-  
-  /**
-   * A ComboValue is a value that is the logical combination of
-   * a set of other stat values.
-   * <p> For now ComboValue has a simple implementation that does not
-   * suppport updates.
-   */
-  private static class ComboValue extends AbstractValue {
-    private final ResourceType type;
-    private final StatValue[] values;
-    /**
-     * Creates a ComboValue by adding all the specified values together.
-     */
-    ComboValue(List valueList) {
-      this((StatValue[])valueList.toArray(new StatValue[valueList.size()]));
-    }
-    /**
-     * Creates a ComboValue by adding all the specified values together.
-     */
-    ComboValue(StatValue[] values) {
-      this.values = values;
-      this.filter = this.values[0].getFilter();
-      String typeName = this.values[0].getType().getName();
-      String statName = this.values[0].getDescriptor().getName();
-      int bestTypeIdx = 0;
-      for (int i=1; i < this.values.length; i++) {
-        if (this.filter != this.values[i].getFilter()) {
-          /* I'm not sure why this would happen.
-           * If it really can happen then this code should change
-           * the filter since a client has no way to select values
-           * based on the filter.
-           */
-          throw new IllegalArgumentException(LocalizedStrings.StatArchiveReader_CANT_COMBINE_VALUES_WITH_DIFFERENT_FILTERS.toLocalizedString());
-        }
-        if (!typeName.equals(this.values[i].getType().getName())) {
-          throw new IllegalArgumentException(LocalizedStrings.StatArchiveReader_CANT_COMBINE_VALUES_WITH_DIFFERENT_TYPES.toLocalizedString());
-        }
-        if (!statName.equals(this.values[i].getDescriptor().getName())) {
-          throw new IllegalArgumentException(LocalizedStrings.StatArchiveReader_CANT_COMBINE_DIFFERENT_STATS.toLocalizedString());
-        }
-        if (this.values[i].getDescriptor().isCounter()) {
-          // its a counter which is not the default
-          if (!this.values[i].getDescriptor().isLargerBetter()) {
-            // this guy has non-defaults for both use him
-            bestTypeIdx = i;
-          } else if (this.values[bestTypeIdx].getDescriptor().isCounter()
-                     == this.values[bestTypeIdx].getDescriptor().isLargerBetter()) {
-            // as long as we haven't already found a guy with defaults
-            // make this guy the best type
-              bestTypeIdx = i;
-          }
-        } else {
-          // its a gauge, see if it has a non-default largerBetter
-          if (this.values[i].getDescriptor().isLargerBetter()) {
-            // as long as we haven't already found a guy with defaults
-            if (this.values[bestTypeIdx].getDescriptor().isCounter()
-                == this.values[bestTypeIdx].getDescriptor().isLargerBetter()) {
-              // make this guy the best type
-              bestTypeIdx = i;
-            }
-          }
-        }
-      }
-      this.type = this.values[bestTypeIdx].getType();
-      this.descriptor = this.values[bestTypeIdx].getDescriptor();
-    }
-    private ComboValue(ComboValue original, long startTime, long endTime) {
-      this.startTime = startTime;
-      this.endTime = endTime;
-      this.type = original.getType();
-      this.descriptor = original.getDescriptor();
-      this.filter = original.getFilter();
-      this.values = new StatValue[original.values.length];
-      for (int i=0; i < this.values.length; i++) {
-        this.values[i] = original.values[i].createTrimmed(startTime, endTime);
-      }
-    }
-    public StatValue createTrimmed(long startTime, long endTime) {
-      if (startTime == this.startTime && endTime == this.endTime) {
-        return this;
-      } else {
-        return new ComboValue(this, startTime, endTime);
-      }
-    }
-    public ResourceType getType() {
-      return this.type;
-    }
-    public ResourceInst[] getResources() {
-      Set set = new HashSet();
-      for (int i=0; i < values.length; i++) {
-        set.addAll(Arrays.asList(values[i].getResources()));
-      }
-      ResourceInst[] result = new ResourceInst[set.size()];
-      return (ResourceInst[])set.toArray(result);
-    }
-    public boolean hasValueChanged() {
-      return true;
-    }
-    
-    public static boolean closeEnough(long v1, long v2, long delta) {
-      return (v1 == v2) || ((Math.abs(v1-v2)/2) <= delta);
-    }
-    /**
-     * Return true if v is closer to prev.
-     * Return false if v is closer to next.
-     * Return true if v is the same distance from both.
-     */
-    public static boolean closer(long v, long prev, long next) {
-      return Math.abs(v-prev) <= Math.abs(v-next);
-    }
-      
-
-    /**
-     * Return true if the current ts must be inserted instead of
-     * being mapped to the tsAtInsertPoint
-     */
-    private static boolean mustInsert(int nextIdx, long[] valueTimeStamps, long tsAtInsertPoint) {
-      return (nextIdx < valueTimeStamps.length)
-        && (valueTimeStamps[nextIdx] <= tsAtInsertPoint);
-    }
-    
-    public long[] getRawAbsoluteTimeStampsWithSecondRes() {
-      return getRawAbsoluteTimeStamps();
-    }
-    
-    public long[] getRawAbsoluteTimeStamps() {
-      if (values.length == 0) {
-        return new long[0];
-      }
-//       for (int i=0; i < values.length; i++) {
-//         System.out.println("DEBUG: inst# " + i + " has "
-//                            + values[i].getRawAbsoluteTimeStamps().length
-//                            + " timestamps");
-//       }
-      long[] valueTimeStamps = values[0].getRawAbsoluteTimeStamps();
-      int tsCount = valueTimeStamps.length + 1;
-      long[] ourTimeStamps = new long[(tsCount*2) + 1];
-      System.arraycopy(valueTimeStamps, 0, ourTimeStamps, 0, valueTimeStamps.length);
-      // Note we add a MAX sample to make the insert logic simple
-      ourTimeStamps[valueTimeStamps.length] = Long.MAX_VALUE;
-      for (int i=1; i < values.length; i++) {
-        valueTimeStamps = values[i].getRawAbsoluteTimeStamps();
-        if (valueTimeStamps.length == 0) {
-          continue;
-        }
-        int ourIdx = 0;
-        int j=0;
-        long tsToInsert = valueTimeStamps[0] - 1000; // default to 1 second
-        if (valueTimeStamps.length > 1) {
-          tsToInsert = valueTimeStamps[0] - (valueTimeStamps[1] - valueTimeStamps[0]);
-        }
-        // tsToInsert is now initialized to a value that we can pretend
-        // was the previous timestamp inserted.
-        while (j < valueTimeStamps.length) {
-          long timeDelta = (valueTimeStamps[j] - tsToInsert) / 2;
-          tsToInsert = valueTimeStamps[j];
-          long tsAtInsertPoint = ourTimeStamps[ourIdx];
-          while (tsToInsert > tsAtInsertPoint
-                 && !closeEnough(tsToInsert, tsAtInsertPoint, timeDelta)) {
-//             System.out.println("DEBUG: skipping " + ourIdx + " because it was not closeEnough");
-            ourIdx++;
-            tsAtInsertPoint = ourTimeStamps[ourIdx];
-          }
-          if (closeEnough(tsToInsert, tsAtInsertPoint, timeDelta)
-              && !mustInsert(j+1, valueTimeStamps, tsAtInsertPoint)) {
-            // It was already in our list so just go to the next one
-            j++;
-            ourIdx++; // never put the next timestamp at this index
-            while (!closer(tsToInsert, ourTimeStamps[ourIdx-1], ourTimeStamps[ourIdx])
-                && !mustInsert(j, valueTimeStamps, ourTimeStamps[ourIdx])) {
-//               System.out.println("DEBUG: skipping mergeTs[" + (ourIdx-1) + "]="
-//                                  + tsAtInsertPoint + " because it was closer to the next one");
-              ourIdx++; // it is closer to the next one so skip forward on more
-            }
-          } else {
-            // its not in our list so add it
-            int endRunIdx=j+1;
-            while (endRunIdx < valueTimeStamps.length
-                   && valueTimeStamps[endRunIdx] < tsAtInsertPoint
-                   && !closeEnough(valueTimeStamps[endRunIdx], tsAtInsertPoint, timeDelta)) {
-              endRunIdx++;
-            }
-            int numToCopy = endRunIdx - j;
-//             System.out.println("DEBUG: tsToInsert=" + tsToInsert
-//                                + " tsAtInsertPoint=" + tsAtInsertPoint
-//                                + " timeDelta=" + timeDelta
-//                                + " vDelta=" + (Math.abs(tsToInsert-tsAtInsertPoint)/2)
-//                                + " numToCopy=" + numToCopy);
-//             if (j > 0) {
-//               System.out.println("DEBUG: prevTsToInsert=" + valueTimeStamps[j-1]);
-//             }
-//             if (ourIdx > 0) {
-//               System.out.println("DEBUG ourTimeStamps[" + (ourIdx-1) + "]=" + ourTimeStamps[ourIdx-1]);
-//             }
-
-//             if (numToCopy > 1) {
-//               System.out.println("DEBUG: endRunTs=" + valueTimeStamps[endRunIdx-1]);
-//             }
-            if (tsCount+numToCopy > ourTimeStamps.length) {
-              // grow our timestamp array
-              long[] tmp = new long[(tsCount+numToCopy)*2];
-              System.arraycopy(ourTimeStamps, 0, tmp, 0, tsCount);
-              ourTimeStamps = tmp;
-            }
-            // make room for insert
-            System.arraycopy(ourTimeStamps, ourIdx,
-                             ourTimeStamps, ourIdx+numToCopy,
-                             tsCount-ourIdx);
-            // insert the elements
-            if (numToCopy == 1) {
-              ourTimeStamps[ourIdx] = valueTimeStamps[j];
-            } else {
-              System.arraycopy(valueTimeStamps, j,
-                               ourTimeStamps, ourIdx,
-                               numToCopy);
-            }
-            ourIdx += numToCopy;
-            tsCount += numToCopy;
-            // skip over all inserted elements 
-            j += numToCopy;
-          }
-//           System.out.println("DEBUG: inst #" + i
-//                              + " valueTs[" + (j-1) + "]=" + tsToInsert
-//                              + " found/inserted at"
-//                              + " mergeTs[" + (ourIdx-1) + "]=" + ourTimeStamps[ourIdx-1]);
-        }
-      }
-//       for (int i=0; i < tsCount; i++) {
-//         System.out.println("DEBUG: mergedTs[" + i + "]=" + ourTimeStamps[i]);
-//         if (i > 0 && ourTimeStamps[i] <= ourTimeStamps[i-1]) {
-//           System.out.println("DEBUG: ERROR ts was not greater than previous");
-//         }
-//       }
-      // Now make one more pass over all the timestamps and make sure they
-      // will all fit into the current merged timestamps in ourTimeStamps
-//       boolean changed;
-//       do {
-//         changed = false;
-//         for (int i=0; i < values.length; i++) {
-//           valueTimeStamps = values[i].getRawAbsoluteTimeStamps();
-//           if (valueTimeStamps.length == 0) {
-//             continue;
-//           }
-//           int ourIdx = 0;
-//           for (int j=0; j < valueTimeStamps.length; j++) {
-//             while ((ourIdx < (tsCount-1))
-//                    && !isClosest(valueTimeStamps[j], ourTimeStamps, ourIdx)) {
-//               ourIdx++;
-//             }
-//             if (ourIdx == (tsCount-1)) {
-//               // we are at the end so we need to append all our remaining stamps [j..valueTimeStamps.length-1]
-//               // and then reappend the Long.MAX_VALUE that
-//               // is currently at tsCount-1
-//               int numToCopy = valueTimeStamps.length - j;
-//               if (tsCount+numToCopy > ourTimeStamps.length) {
-//                 // grow our timestamp array
-//                 long[] tmp = new long[tsCount+numToCopy+1];
-//                 System.arraycopy(ourTimeStamps, 0, tmp, 0, tsCount);
-//                 ourTimeStamps = tmp;
-//               }
-//               System.arraycopy(valueTimeStamps, j,
-//                                ourTimeStamps, ourIdx,
-//                                numToCopy);
-//               tsCount += numToCopy;
-//               ourTimeStamps[tsCount-1] = Long.MAX_VALUE;
-//               //changed = true;
-//               System.out.println("DEBUG: had to add " + numToCopy
-//                                  + " timestamps for inst#" + i + " starting at index " + j + " starting with ts=" + valueTimeStamps[j]);
-//               break; // our of the for j loop since we just finished off this guy
-//             } else {
-//               ourIdx++;
-//             }
-//           }
-//         }
-//       } while (changed);
-      // remove the max ts we added
-      tsCount--;
-      {
-        int startIdx = 0;
-        int endIdx = tsCount-1;
-        if (startTime != -1) {
-//           for (int i=0; i < tsCount; i++) {
-//             if (ourTimeStamps[i] >= startTime) {
-//               break;
-//             }
-//             startIdx++;
-//           }
-          Assert.assertTrue(ourTimeStamps[startIdx] >= startTime);
-        }
-        if (endTime != -1) {
-//           endIdx = startIdx-1;
-//           for (int i=startIdx; i < tsCount; i++) {
-//             if (ourTimeStamps[i] >= endTime) {
-//               break;
-//             }
-//             endIdx++;
-//           }
-          Assert.assertTrue(endIdx == startIdx-1 || ourTimeStamps[endIdx] < endTime);
-        }
-        tsCount = (endIdx-startIdx) + 1;
-        
-        // shrink and trim our timestamp array
-        long[] tmp = new long[tsCount];
-        System.arraycopy(ourTimeStamps, startIdx, tmp, 0, tsCount);
-        ourTimeStamps = tmp;
-      }
-      return ourTimeStamps;
-    }
-    public double[] getRawSnapshots() {
-      return getRawSnapshots(getRawAbsoluteTimeStamps());
-    }
-    /**
-     * Returns true if the timeStamp at curIdx is the one that ts is
-     * the closest to.
-     * We know that timeStamps[curIdx-1], if it exists, was not the closest.
-     */
-    private static boolean isClosest(long ts, long[] timeStamps, int curIdx) {
-      if (curIdx >= (timeStamps.length - 1)) {
-        // curIdx is the last one so it must be the closest
-        return true;
-      }
-      if (ts == timeStamps[curIdx]) {
-        return true;
-      }
-      return closer(ts, timeStamps[curIdx], timeStamps[curIdx+1]);
-    }
-
-    public boolean isTrimmedLeft() {
-      for (int i=0; i < this.values.length; i++) {
-        if (this.values[i].isTrimmedLeft()) {
-          return true;
-        }
-      }
-      return false;
-    }
-
-    private double[] getRawSnapshots(long[] ourTimeStamps) {
-      double[] result = new double[ourTimeStamps.length];
-//       System.out.println("DEBUG: producing " + result.length + " values");
-      if (result.length > 0) {
-        for (int i=0; i < values.length; i++) {
-          long[] valueTimeStamps = values[i].getRawAbsoluteTimeStamps();
-          double[] valueSnapshots = values[i].getRawSnapshots();
-          double currentValue = 0.0;
-          int curIdx = 0;
-          if (values[i].isTrimmedLeft() && valueSnapshots.length > 0) {
-            currentValue = valueSnapshots[0];
-          }
-//           System.out.println("DEBUG: inst#" + i + " has " + valueSnapshots.length + " values");
-          for (int j=0; j < valueSnapshots.length; j++) {
-//             System.out.println("DEBUG: Doing v with"
-//                                + " vTs[" + j + "]=" + valueTimeStamps[j]
-//                                + " at mergeTs[" + curIdx + "]=" + ourTimeStamps[curIdx]);
-            while (!isClosest(valueTimeStamps[j], ourTimeStamps, curIdx)) {
-              if (descriptor.isCounter()) {
-                result[curIdx] += currentValue;
-              }
-//               System.out.println("DEBUG: skipping curIdx=" + curIdx
-//                                  + " valueTimeStamps[" + j + "]=" + valueTimeStamps[j]
-//                                  + " ourTimeStamps[" + curIdx + "]=" + ourTimeStamps[curIdx]
-//                                  + " ourTimeStamps[" + (curIdx+1) + "]=" + ourTimeStamps[curIdx+1]);
-                                 
-              curIdx++;
-            }
-            if (curIdx >= result.length) {
-              // Add this to workaround bug 30288
-              int samplesSkipped = valueSnapshots.length - j;
-              StringBuffer msg = new StringBuffer(100);
-              msg.append("WARNING: dropping last ");
-              if (samplesSkipped == 1) {
-                msg.append("sample because it");
-              } else {
-                msg.append(samplesSkipped).append(" samples because they");
-              }
-              msg.append(" could not fit in the merged result.");
-              System.out.println(msg.toString());
-              break;
-            }
-            currentValue = valueSnapshots[j];
-            result[curIdx] += currentValue;
-            curIdx++;
-          }
-          if (descriptor.isCounter()) {
-            for (int j=curIdx; j < result.length; j++) {
-              result[j] += currentValue;
-            }
-          }
-        }
-      }
-      return result;
-    }
-    public double[] getSnapshots() {
-      double[] result;
-      if (filter != FILTER_NONE) {
-        long[] timestamps = getRawAbsoluteTimeStamps();
-        double[] snapshots = getRawSnapshots(timestamps);
-        if (snapshots.length <= 1) {
-          return new double[0];
-        }
-        result = new double[snapshots.length - 1];
-        for (int i=0; i < result.length; i++) {
-          double valueDelta = snapshots[i+1] - snapshots[i];
-          if (filter == FILTER_PERSEC) {
-            long timeDelta = timestamps[i+1] - timestamps[i];
-            result[i] = valueDelta / (timeDelta / 1000.0);
-//             if (result[i] > valueDelta) {
-//               System.out.println("DEBUG:  timeDelta     was " + timeDelta + " ms.");
-//               System.out.println("DEBUG: valueDelta     was " + valueDelta);
-//               System.out.println("DEBUG: valueDelta/sec was " + result[i]);
-//             }
-          } else {
-            result[i] = valueDelta;
-          }
-        }
-      } else {
-        result = getRawSnapshots();
-      }
-      calcStats(result);
-      return result;
-    }
-  }
-  
-  /**
-   * Provides the value series related to a single statistics.
-   */
-  private static class SimpleValue extends AbstractValue {
-    private final ResourceInst resource;
-
-    private boolean useNextBits = false;
-    private long nextBits;
-    private final BitSeries series;
-    private boolean valueChangeNoticed = false;
-
-
-    public StatValue createTrimmed(long startTime, long endTime) {
-      if (startTime == this.startTime && endTime == this.endTime) {
-        return this;
-      } else {
-        return new SimpleValue(this, startTime, endTime);
-      }
-    }
-
-    protected SimpleValue(ResourceInst resource, StatDescriptor sd) {
-      this.resource = resource;
-      if (sd.isCounter()) {
-        this.filter = FILTER_PERSEC;
-      } else {
-        this.filter = FILTER_NONE;
-      }
-      this.descriptor = sd;
-      this.series = new BitSeries();
-      this.statsValid = false;
-    }
-
-    private SimpleValue(SimpleValue in, long startTime, long endTime) {
-      this.startTime = startTime;
-      this.endTime = endTime;
-      this.useNextBits = in.useNextBits;
-      this.nextBits = in.nextBits;
-      this.resource = in.resource;
-      this.series = in.series;
-      this.descriptor = in.descriptor;
-      this.filter = in.filter;
-      this.statsValid = false;
-      this.valueChangeNoticed = true;
-    }
-
-    public ResourceType getType() {
-      return this.resource.getType();
-    }
-    
-    public ResourceInst[] getResources() {
-      return new ResourceInst[] {this.resource};
-    }
-
-    public boolean isTrimmedLeft() {
-      return getStartIdx() != 0;
-    }
-    
-    private int getStartIdx() {
-      int startIdx = 0;
-      if (startTime != -1) {
-        long startTimeStamp = startTime - resource.getTimeBase();
-        long[] timestamps = resource.getAllRawTimeStamps();
-        for (int i=resource.getFirstTimeStampIdx();
-             i < resource.getFirstTimeStampIdx() + series.getSize();
-             i++) {
-          if (timestamps[i] >= startTimeStamp) {
-            break;
-          }
-          startIdx++;
-        }
-      }
-      return startIdx;
-    }
-    private int getEndIdx(int startIdx) {
-      int endIdx = series.getSize()-1;
-      if (endTime != -1) {
-        long endTimeStamp = endTime - resource.getTimeBase();
-        long[] timestamps = resource.getAllRawTimeStamps();
-        endIdx = startIdx-1;
-        for (int i=resource.getFirstTimeStampIdx()+startIdx;
-             i < resource.getFirstTimeStampIdx() + series.getSize();
-             i++) {
-          if (timestamps[i] >= endTimeStamp) {
-            break;
-          }
-          endIdx++;
-        }
-        Assert.assertTrue(endIdx == startIdx-1 || timestamps[endIdx] < endTimeStamp);
-      }
-      return endIdx;
-    }
-    public double[] getSnapshots() {
-      double[] result;
-      int startIdx = getStartIdx();
-      int endIdx = getEndIdx(startIdx);
-      int resultSize=(endIdx-startIdx) + 1;
-      
-      if (filter != FILTER_NONE && resultSize > 1) {
-        long[] timestamps = null;
-        if (filter == FILTER_PERSEC) {
-          timestamps = resource.getAllRawTimeStamps();
-        }
-        result = new double[resultSize-1];
-        int tsIdx = resource.getFirstTimeStampIdx()+startIdx;
-        double[] values = series.getValuesEx(descriptor.getTypeCode(), startIdx, resultSize);
-        for (int i=0; i < result.length; i++) {
-          double valueDelta = values[i+1] - values[i];
-          if (filter == FILTER_PERSEC) {
-            double timeDelta = (timestamps[tsIdx+i+1] - timestamps[tsIdx+i]); // millis
-            valueDelta /= (timeDelta / 1000); // per second
-          }
-          result[i] = valueDelta;
-        }
-      } else {
-        result = series.getValuesEx(descriptor.getTypeCode(), startIdx, resultSize);
-      }
-      calcStats(result);
-      return result;
-    }
-    
-    public double[] getRawSnapshots() {
-      int startIdx = getStartIdx();
-      int endIdx = getEndIdx(startIdx);
-      int resultSize=(endIdx-startIdx) + 1;
-      return series.getValuesEx(descriptor.getTypeCode(), startIdx, resultSize);
-    }
-
-    public long[] getRawAbsoluteTimeStampsWithSecondRes() {
-      long[] result = getRawAbsoluteTimeStamps();
-      for (int i=0; i < result.length; i++) {
-        result[i] += 500;
-        result[i] /= 1000;
-        result[i] *= 1000;
-      }
-      return result;
-    }
-
-    public long[] getRawAbsoluteTimeStamps() {
-      int startIdx = getStartIdx();
-      int endIdx = getEndIdx(startIdx);
-      int resultSize=(endIdx-startIdx) + 1;
-      if (resultSize <= 0) {
-        return new long[0];
-      } else {
-        long[] result = new long[resultSize];
-        long[] timestamps = resource.getAllRawTimeStamps();
-        int tsIdx = resource.getFirstTimeStampIdx()+startIdx;
-        long base = resource.getTimeBase();
-        for (int i=0; i < resultSize; i++) {
-          result[i] = base + timestamps[tsIdx+i];
-        }
-        return result;
-      }
-    }
-
-    public boolean hasValueChanged() {
-      if (valueChangeNoticed) {
-        valueChangeNoticed = false;
-        return true;
-      } else {
-        return false;
-      }
-    }
-    protected int getMemoryUsed() {
-      int result = 0;
-      if (series != null) {
-        result += series.getMemoryUsed();
-      }
-      return result;
-    }
-
-    protected void dump(PrintWriter stream) {
-      calcStats();
-      stream.print("  " + descriptor.getName() + "=");
-      stream.print("[size=" + getSnapshotsSize()
-                   + " min=" + nf.format(min)
-                   + " max=" + nf.format(max)
-                   + " avg=" + nf.format(avg)
-                   + " stddev=" + nf.format(stddev) + "]");
-      if (Boolean.getBoolean("StatArchiveReader.dumpall")) {
-        series.dump(stream);
-      } else {
-        stream.println();
-      }
-    }
-    
-    protected void shrink() {
-      this.series.shrink();
-    }
-
-    protected void initialValue(long v) {
-      this.series.initialBits(v);
-    }
-    protected void prepareNextBits(long bits) {
-      useNextBits = true;
-      nextBits = bits;
-    }
-    protected void addSample() {
-      statsValid = false;
-      if (useNextBits) {
-        useNextBits = false;
-        series.addBits(nextBits);
-        valueChangeNoticed = true;
-      } else {
-        series.addBits(0);
-      }
-    }
-  }
-
-  private static abstract class BitInterval {
-    /** Returns number of items added to values */
-    abstract int fill(double[] values, int valueOffset, int typeCode, int skipCount);
-    abstract void dump(PrintWriter stream);
-    abstract boolean attemptAdd(long addBits, long addInterval, int addCount);
-    int getMemoryUsed() {
-      return 0;
-    }
-
-    protected int count;
-
-    public final int getSampleCount() {
-      return this.count;
-    }
-    
-    static BitInterval create(long bits, long interval, int count) {
-      if (interval == 0) {
-        if (bits <= Integer.MAX_VALUE && bits >= Integer.MIN_VALUE) {
-          return new BitZeroIntInterval((int)bits, count);
-        } else {
-          return new BitZeroLongInterval(bits, count);
-        }
-      } else if (count <= 3) {
-        if (interval <= Byte.MAX_VALUE && interval >= Byte.MIN_VALUE) {
-          return new BitExplicitByteInterval(bits, interval, count);
-        } else if (interval <= Short.MAX_VALUE && interval >= Short.MIN_VALUE) {
-          return new BitExplicitShortInterval(bits, interval, count);
-        } else if (interval <= Integer.MAX_VALUE && interval >= Integer.MIN_VALUE) {
-          return new BitExplicitIntInterval(bits, interval, count);
-        } else {
-          return new BitExplicitLongInterval(bits, interval, count);
-        }
-      } else {
-        boolean smallBits = false;
-        boolean smallInterval = false;
-        if (bits <= Integer.MAX_VALUE && bits >= Integer.MIN_VALUE) {
-          smallBits = true;
-        }
-        if (interval <= Integer.MAX_VALUE && interval >= Integer.MIN_VALUE) {
-          smallInterval = true;
-        }
-        if (smallBits) {
-          if (smallInterval) {
-            return new BitNonZeroIntIntInterval((int)bits, (int)interval, count);
-          } else {
-            return new BitNonZeroIntLongInterval((int)bits, interval, count);
-          }
-        } else {
-          if (smallInterval) {
-            return new BitNonZeroLongIntInterval(bits, (int)interval, count);
-          } else {
-            return new BitNonZeroLongLongInterval(bits, interval, count);
-          }
-        }
-      }
-    }
-  }
-
-  private static abstract class BitNonZeroInterval extends BitInterval {
-    @Override
-    int getMemoryUsed() {
-      return super.getMemoryUsed() + 4;
-    }
-    abstract long getBits();
-    abstract long getInterval();
-    
-    @Override
-    int fill(double[] values, int valueOffset, int typeCode, int skipCount) {
-      int fillcount = values.length - valueOffset; // space left in values
-      int maxCount = count - skipCount; // maximum values this interval can produce
-      if (fillcount > maxCount) {
-        fillcount = maxCount;
-      }
-      long base = getBits();
-      long interval = getInterval();
-      base += skipCount * interval;
-      for (int i=0; i < fillcount; i++) {
-        values[valueOffset+i] = bitsToDouble(typeCode, base);
-        base += interval;
-      }
-      return fillcount;
-    }
-
-    @Override
-    void dump(PrintWriter stream) {
-      stream.print(getBits());
-      if (count > 1) {
-        long interval = getInterval();
-        if (interval != 0) {
-          stream.print("+=" + interval);
-        }
-        stream.print("r" + count);
-      }
-    }
-    BitNonZeroInterval(int count) {
-      this.count = count;
-    }
-    @Override
-    boolean attemptAdd(long addBits, long addInterval, int addCount) {
-      // addCount >= 2; count >= 2
-      if (addInterval == getInterval()) {
-        if (addBits == (getBits() + (addInterval * (count-1)))) {
-          count += addCount;
-          return true;
-        }
-      }
-      return false;
-    }
-  }
-  
-  private static class BitNonZeroIntIntInterval extends BitNonZeroInterval {
-    int bits;
-    int interval;
-
-    @Override
-    int getMemoryUsed() {
-      return super.getMemoryUsed() + 8;
-    }
-    @Override
-    long getBits() {
-      return this.bits;
-    }
-    @Override
-    long getInterval() {
-      return this.interval;
-    }
-
-    BitNonZeroIntIntInterval(int bits, int interval, int count) {
-      super(count);
-      this.bits = bits;
-      this.interval = interval;
-    }
-  }
-  
-  private static class BitNonZeroIntLongInterval extends BitNonZeroInterval {
-    int bits;
-    long interval;
-
-    @Override
-    int getMemoryUsed() {
-      return super.getMemoryUsed() + 12;
-    }
-    @Override
-    long getBits() {
-      return this.bits;
-    }
-    @Override
-    long getInterval() {
-      return this.interval;
-    }
-
-    BitNonZeroIntLongInterval(int bits, long interval, int count) {
-      super(count);
-      this.bits = bits;
-      this.interval = interval;
-    }
-  }
-  
-  private static class BitNonZeroLongIntInterval extends BitNonZeroInterval {
-    long bits;
-    int interval;
-
-    @Override
-    int getMemoryUsed() {
-      return super.getMemoryUsed() + 12;
-    }
-    @Override
-    long getBits() {
-      return this.bits;
-    }
-    @Override
-    long getInterval() {
-      return this.interval;
-    }
-
-    BitNonZeroLongIntInterval(long bits, int interval, int count) {
-      super(count);
-      this.bits = bits;
-      this.interval = interval;
-    }
-  }
-  
-  private static class BitNonZeroLongLongInterval extends BitNonZeroInterval {
-    long bits;
-    long interval;
-
-    @Override
-    int getMemoryUsed() {
-      return super.getMemoryUsed() + 16;
-    }
-    @Override
-    long getBits() {
-      return this.bits;
-    }
-    @Override
-    long getInterval() {
-      return this.interval;
-    }
-
-    BitNonZeroLongLongInterval(long bits, long interval, int count) {
-      super(count);
-      this.bits = bits;
-      this.interval = interval;
-    }
-  }
-
-  private static abstract class BitZeroInterval extends BitInterval {
-    @Override
-    int getMemoryUsed() {
-      return super.getMemoryUsed() + 4;
-    }
-    abstract long getBits();
-    
-    @Override
-    int fill(double[] values, int valueOffset, int typeCode, int skipCount) {
-      int fillcount = values.length - valueOffset; // space left in values
-      int maxCount = count - skipCount; // maximum values this interval can produce
-      if (fillcount > maxCount) {
-        fillcount = maxCount;
-      }
-      double value = bitsToDouble(typeCode, getBits());
-      for (int i=0; i < fillcount; i++) {
-        values[valueOffset+i] = value;
-      }
-      return fillcount;
-    }
-
-    @Override
-    void dump(PrintWriter stream) {
-      stream.print(getBits());
-      if (count > 1) {
-        stream.print("r" + count);
-      }
-    }
-    BitZeroInterval(int count) {
-      this.count = count;
-    }
-    @Override
-    boolean attemptAdd(long addBits, long addInterval, int addCount) {
-      // addCount >= 2; count >= 2
-      if (addInterval == 0 && addBits == getBits()) {
-        count += addCount;
-        return true;
-      }
-      return false;
-    }
-  }
-  
-  private static class BitZeroIntInterval extends BitZeroInterval {
-    int bits;
-
-    @Override
-    int getMemoryUsed() {
-      return super.getMemoryUsed() + 4;
-    }
-    @Override
-    long getBits() {
-      return bits;
-    }
-    BitZeroIntInterval(int bits, int count) {
-      super(count);
-      this.bits = bits;
-    }
-  }
-  
-  private static class BitZeroLongInterval extends BitZeroInterval {
-    long bits;
-
-    @Override
-    int getMemoryUsed() {
-      return super.getMemoryUsed() + 8;
-    }
-    @Override
-    long getBits() {
-      return bits;
-    }
-    BitZeroLongInterval(long bits, int count) {
-      super(count);
-      this.bits = bits;
-    }
-  }
-
-  private static class BitExplicitByteInterval extends BitInterval {
-    long firstValue;
-    long lastValue;
-    byte[] bitIntervals = null;
-
-    @Override
-    int getMemoryUsed() {
-      int result = super.getMemoryUsed() + 4 + 8 + 8 + 4;
-      if (bitIntervals != null) {
-        result += bitIntervals.length;
-      }
-      return result;
-    }
-    @Override
-    int fill(double[] values, int valueOffset, int typeCode, int skipCount) {
-      int fillcount = values.length - valueOffset; // space left in values
-      int maxCount = count - skipCount; // maximum values this interval can produce
-      if (fillcount > maxCount) {
-        fillcount = maxCount;
-      }
-      long bitValue = firstValue;
-      for (int i=0; i < skipCount; i++) {
-        bitValue += bitIntervals[i];
-      }
-      for (int i=0; i < fillcount; i++) {
-        bitValue += bitIntervals[skipCount+i];
-        values[valueOffset+i] = bitsToDouble(typeCode, bitValue);
-      }
-      return fillcount;
-    }
-
-    @Override
-    void dump(PrintWriter stream) {
-      stream.print("(byteIntervalCount=" + count + " start=" + firstValue);
-      for (int i=0; i < count; i++) {
-        if (i != 0) {
-          stream.print(", ");
-        }
-        stream.print(bitIntervals[i]);
-      }
-      stream.print(")");
-    }
-    BitExplicitByteInterval(long bits, long interval, int addCount) {
-      count = addCount;
-      firstValue = bits;
-      lastValue = bits + (interval * (addCount-1));
-      bitIntervals = new byte[count*2];
-      bitIntervals[0] = 0;
-      for (int i=1; i < count; i++) {
-        bitIntervals[i] = (byte)interval;
-      }
-    }
-    @Override
-    boolean attemptAdd(long addBits, long addInterval, int addCount) {
-      // addCount >= 2; count >= 2
-      if (addCount <= 11) {
-        if (addInterval <= Byte.MAX_VALUE && addInterval >= Byte.MIN_VALUE) {
-          long firstInterval = addBits - lastValue;
-          if (firstInterval <= Byte.MAX_VALUE && firstInterval >= Byte.MIN_VALUE) {
-            lastValue = addBits + (addInterval * (addCount-1));
-            if ((count + addCount) >= bitIntervals.length) {
-              byte[] tmp = new byte[(count+addCount)*2];
-              System.arraycopy(bitIntervals, 0, tmp, 0, bitIntervals.length);
-              bitIntervals = tmp;
-            }
-            bitIntervals[count++] = (byte)firstInterval;
-            for (int i=1; i < addCount; i++) {
-              bitIntervals[count++] = (byte)addInterval;
-            }
-            return true;
-          }
-        }
-      }
-      return false;
-    }
-  }
-  
-  private static class BitExplicitShortInterval extends BitInterval {
-    long firstValue;
-    long lastValue;
-    short[] bitIntervals = null;
-
-    @Override
-    int getMemoryUsed() {
-      int result = super.getMemoryUsed() + 4 + 8 + 8 + 4;
-      if (bitIntervals != null) {
-        result += bitIntervals.length * 2;
-      }
-      return result;
-    }
-
-    @Override
-    int fill(double[] values, int valueOffset, int typeCode, int skipCount) {
-      int fillcount = values.length - valueOffset; // space left in values
-      int maxCount = count - skipCount; // maximum values this interval can produce
-      if (fillcount > maxCount) {
-        fillcount = maxCount;
-      }
-      long bitValue = firstValue;
-      for (int i=0; i < skipCount; i++) {
-        bitValue += bitIntervals[i];
-      }
-      for (int i=0; i < fillcount; i++) {
-        bitValue += bitIntervals[skipCount+i];
-        values[valueOffset+i] = bitsToDouble(typeCode, bitValue);
-      }
-      return fillcount;
-    }
-
-    @Override
-    void dump(PrintWriter stream) {
-      stream.print("(shortIntervalCount=" + count + " start=" + firstValue);
-      for (int i=0; i < count; i++) {
-        if (i != 0) {
-          stream.print(", ");
-        }
-        stream.print(bitIntervals[i]);
-      }
-      stream.print(")");
-    }
-    BitExplicitShortInterval(long bits, long interval, int addCount) {
-      count = addCount;
-      firstValue = bits;
-      lastValue = bits + (interval * (addCount-1));
-      bitIntervals = new short[count*2];
-      bitIntervals[0] = 0;
-      for (int i=1; i < count; i++) {
-        bitIntervals[i] = (short)interval;
-      }
-    }
-    @Override
-    boolean attemptAdd(long addBits, long addInterval, int addCount) {
-      // addCount >= 2; count >= 2
-      if (addCount <= 6) {
-        if (addInterval <= Short.MAX_VALUE && addInterval >= Short.MIN_VALUE) {
-          long firstInterval = addBits - lastValue;
-          if (firstInterval <= Short.MAX_VALUE && firstInterval >= Short.MIN_VALUE) {
-            lastValue = addBits + (addInterval * (addCount-1));
-            if ((count + addCount) >= bitIntervals.length) {
-              short[] tmp = new short[(count+addCount)*2];
-              System.arraycopy(bitIntervals, 0, tmp, 0, bitIntervals.length);
-              bitIntervals = tmp;
-            }
-            bitIntervals[count++] = (short)firstInterval;
-            for (int i=1; i < addCount; i++) {
-              bitIntervals[count++] = (short)addInterval;
-            }
-            return true;
-          }
-        }
-      }
-      return false;
-    }
-  }
-  
-  private static class BitExplicitIntInterval extends BitInterval {
-    long firstValue;
-    long lastValue;
-    int[] bitIntervals = null;
-
-    @Override
-    int getMemoryUsed() {
-      int result = super.getMemoryUsed() + 4 + 8 + 8 + 4;
-      if (bitIntervals != null) {
-        result += bitIntervals.length * 4;
-      }
-      return result;
-    }
-
-    @Override
-    int fill(double[] values, int valueOffset, int typeCode, int skipCount) {
-      int fillcount = values.length - valueOffset; // space left in values
-      int maxCount = count - skipCount; // maximum values this interval can produce
-      if (fillcount > maxCount) {
-        fillcount = maxCount;
-      }
-      long bitValue = firstValue;
-      for (int i=0; i < skipCount; i++) {
-        bitValue += bitIntervals[i];
-      }
-      for (int i=0; i < fillcount; i++) {
-        bitValue += bitIntervals[skipCount+i];
-        values[valueOffset+i] = bitsToDouble(typeCode, bitValue);
-      }
-      return fillcount;
-    }
-
-    @Override
-    void dump(PrintWriter stream) {
-      stream.print("(intIntervalCount=" + count + " start=" + firstValue);
-      for (int i=0; i < count; i++) {
-        if (i != 0) {
-          stream.print(", ");
-        }
-        stream.print(bitIntervals[i]);
-      }
-      stream.print(")");
-    }
-    BitExplicitIntInterval(long bits, long interval, int addCount) {
-      count = addCount;
-      firstValue = bits;
-      lastValue = bits + (interval * (addCount-1));
-      bitIntervals = new int[count*2];
-      bitIntervals[0] = 0;
-      for (int i=1; i < count; i++) {
-        bitIntervals[i] = (int)interval;
-      }
-    }
-    @Override
-    boolean attemptAdd(long addBits, long addInterval, int addCount) {
-      // addCount >= 2; count >= 2
-      if (addCount <= 4) {
-        if (addInterval <= Integer.MAX_VALUE && addInterval >= Integer.MIN_VALUE) {
-          long firstInterval = addBits - lastValue;
-          if (firstInterval <= Integer.MAX_VALUE && firstInterval >= Integer.MIN_VALUE) {
-            lastValue = addBits + (addInterval * (addCount-1));
-            if ((count + addCount) >= bitIntervals.length) {
-              int[] tmp = new int[(count+addCount)*2];
-              System.arraycopy(bitIntervals, 0, tmp, 0, bitIntervals.length);
-              bitIntervals = tmp;
-            }
-            bitIntervals[count++] = (int)firstInterval;
-            for (int i=1; i < addCount; i++) {
-              bitIntervals[count++] = (int)addInterval;
-            }
-            return true;
-          }
-        }
-      }
-      return false;
-    }
-  }
-  
-  private static class BitExplicitLongInterval extends BitInterval {
-    long[] bitArray = null;
-
-    @Override
-    int getMemoryUsed() {
-      int result = super.getMemoryUsed() + 4 + 4;
-      if (bitArray != null) {
-        result += bitArray.length * 8;
-      }
-      return result;
-    }
-
-    @Override
-    int fill(double[] values, int valueOffset, int typeCode, int skipCount) {
-      int fillcount = values.length - valueOffset; // space left in values
-      int maxCount = count - skipCount; // maximum values this interval can produce
-      if (fillcount > maxCount) {
-        fillcount = maxCount;
-      }
-      for (int i=0; i < fillcount; i++) {
-        values[valueOffset+i] = bitsToDouble(typeCode, bitArray[skipCount+i]);
-      }
-      return fillcount;
-    }
-
-    @Override
-    void dump(PrintWriter stream) {
-      stream.print("(count=" + count + " ");
-      for (int i=0; i < count; i++) {
-        if (i != 0) {
-          stream.print(", ");
-        }
-        stream.print(bitArray[i]);
-      }
-      stream.print(")");
-    }
-    BitExplicitLongInterval(long bits, long interval, int addCount) {
-      count = addCount;
-      bitArray = new long[count*2];
-      for (int i=0; i < count; i++) {
-        bitArray[i] = bits;
-        bits += interval;
-      }
-    }
-    @Override
-    boolean attemptAdd(long addBits, long addInterval, int addCount) {
-      // addCount >= 2; count >= 2
-      if (addCount <= 3) {
-        if ((count + addCount) >= bitArray.length) {
-          long[] tmp = new long[(count+addCount)*2];
-          System.arraycopy(bitArray, 0, tmp, 0, bitArray.length);
-          bitArray = tmp;
-        }
-        for (int i=0; i < addCount; i++) {
-          bitArray[count++] = addBits;
-          addBits += addInterval;
-        }
-        return true;
-      }
-      return false;
-    }
-  }
-                                  
-  private static class BitSeries {
-    int count; // number of items in this series
-    long currentStartBits;
-    long currentEndBits;
-    long currentInterval;
-    int currentCount;
-    int intervalIdx; // index of most recent BitInterval
-    BitInterval intervals[];
-
-    /**
-     * Returns the amount of memory used to implement this series.
-     */
-    protected int getMemoryUsed() {
-      int result = 4 + 8 + 8 + 8 + 4 + 4 + 4;
-      if (intervals != null) {
-        result += 4 * intervals.length;
-        for (int i=0; i <= intervalIdx; i++) {
-          result += intervals[i].getMemoryUsed();
-        }
-      }
-      return result;
-    }
-    
-    public double[] getValues(int typeCode) {
-      return getValuesEx(typeCode, 0, getSize());
-    }
-    /**
-     * Gets the first "resultSize" values of this series
-     * skipping over the first "samplesToSkip" ones.
-     * The first value in a series is at index 0.
-     * The maximum result size can be obtained by calling "getSize()".
-     */
-    public double[] getValuesEx(int typeCode, int samplesToSkip, int resultSize) {
-      double[] result = new double[resultSize];
-      int firstInterval = 0;
-      int idx = 0;
-      while (samplesToSkip > 0
-             && firstInterval <= intervalIdx
-             && intervals[firstInterval].getSampleCount() <= samplesToSkip) {
-        samplesToSkip -= intervals[firstInterval].getSampleCount();
-        firstInterval++;
-      }
-      for (int i=firstInterval; i <= intervalIdx; i++) {
-        idx += intervals[i].fill(result, idx, typeCode, samplesToSkip);
-        samplesToSkip = 0;
-      }
-      if (currentCount != 0) {
-        idx += BitInterval.create(currentStartBits, currentInterval, currentCount).fill(result, idx, typeCode, samplesToSkip);
-      }
-      // assert
-      if (idx != resultSize) {
-        throw new InternalGemFireException(LocalizedStrings.StatArchiveReader_GETVALUESEX_DIDNT_FILL_THE_LAST_0_ENTRIES_OF_ITS_RESULT.toLocalizedString(Integer.valueOf(resultSize-idx)));
-      }
-      return result;
-    }
-    
-    void dump(PrintWriter stream) {
-      stream.print("[size=" + count + " intervals=" + (intervalIdx+1)
-                   + " memused=" + getMemoryUsed() + " ");
-      for (int i=0; i <= intervalIdx; i++) {
-        if (i != 0) {
-          stream.print(", ");
-        }
-        intervals[i].dump(stream);
-      }
-      if (currentCount != 0) {
-        if (intervalIdx != -1) {
-          stream.print(", ");
-        }
-        BitInterval.create(currentStartBits, currentInterval, currentCount).dump(stream);
-      }
-      stream.println("]");
-    }
-    
-    BitSeries() {
-      count = 0;
-      currentStartBits = 0;
-      currentEndBits = 0;
-      currentInterval = 0;
-      currentCount = 0;
-      intervalIdx = -1;
-      intervals = null;
-    }
-
-    void initialBits(long bits) {
-      this.currentEndBits = bits;
-    }
-    
-    int getSize() {
-      return this.count;
-    }
-    
-    void addBits(long deltaBits) {
-      long bits = currentEndBits + deltaBits;
-      if (currentCount == 0) {
-        currentStartBits = bits;
-        currentCount = 1;
-      } else if (currentCount == 1) {
-        currentInterval = deltaBits;
-        currentCount++;
-      } else if (deltaBits == currentInterval) {
-        currentCount++;
-      } else {
-        // we need to move currentBits into a BitInterval
-        if (intervalIdx == -1) {
-          intervals = new BitInterval[2];
-          intervalIdx = 0;
-          intervals[0] = BitInterval.create(currentStartBits, currentInterval, currentCount);
-        } else {
-          if (!intervals[intervalIdx].attemptAdd(currentStartBits, currentInterval, currentCount)) {
-            // wouldn't fit in current bit interval so add a new one
-            intervalIdx++;
-            if (intervalIdx >= intervals.length) {
-              BitInterval[] tmp = new BitInterval[intervals.length * 2];
-              System.arraycopy(intervals, 0, tmp, 0, intervals.length);
-              intervals = tmp;
-            }
-            intervals[intervalIdx] = BitInterval.create(currentStartBits, currentInterval, currentCount);
-          }
-        }
-        // now start a new currentBits
-        currentStartBits = bits;
-        currentCount = 1;
-      }
-      currentEndBits = bits;
-      count++;
-    }
-    /**
-     * Free up any unused memory
-     */
-    void shrink() {
-      if (intervals != null) {
-        int currentSize = intervalIdx+1;
-        if (currentSize < intervals.length) {
-          BitInterval[] tmp = new BitInterval[currentSize];
-          System.arraycopy(intervals, 0, tmp, 0, currentSize);
-          intervals = tmp;
-        }
-      }
-    }
-  }
-  
-  private static class TimeStampSeries {
-    static private final int GROW_SIZE = 256;
-    int count; // number of items in this series
-    long base; // millis since midnight, Jan 1, 1970 UTC.
-    long[] timeStamps = new long[GROW_SIZE]; // elapsed millis from base
-
-    void dump(PrintWriter stream) {
-      stream.print("[size=" + count);
-      for (int i=0; i < count; i++) {
-        if (i != 0) {
-          stream.print(", ");
-          stream.print(timeStamps[i]-timeStamps[i-1]);
-        } else {
-          stream.print(" " + timeStamps[i]);
-        }
-      }
-      stream.println("]");
-    }
-
-    void shrink() {
-      if (count < timeStamps.length) {
-        long[] tmp = new long[count];
-        System.arraycopy(timeStamps, 0, tmp, 0, count);
-        timeStamps = tmp;
-      }
-    }
-    
-    TimeStampSeries() {
-      count = 0;
-      base = 0;
-    }
-    
-    void setBase(long base) {
-      this.base = base;
-    }
-
-    int getSize() {
-      return this.count;
-    }
-    
-    void addTimeStamp(int ts) {
-      if (count >= timeStamps.length) {
-        long[] tmp = new long[timeStamps.length + GROW_SIZE];
-        System.arraycopy(timeStamps, 0, tmp, 0, timeStamps.length);
-        timeStamps = tmp;
-      }
-      if (count != 0) {
-        timeStamps[count] = timeStamps[count-1] + ts;
-      } else {
-        timeStamps[count] = ts;
-      }
-      count++;
-    }
-    
-    long getBase() {
-      return this.base;
-    }
-    /** Provides direct access to underlying data.
-     * Do not modify contents and use getSize() to keep from reading
-     * past end of array.
-     */
-    long[] getRawTimeStamps() {
-      return this.timeStamps;
-    }
-    long getMilliTimeStamp(int idx) {
-      return this.base + this.timeStamps[idx];
-    }
-    /**
-     * Returns an array of time stamp values the first of which
-     * has the specified index.
-     * Each returned time stamp is the number of millis since
-     * midnight, Jan 1, 1970 UTC.
-     */
-    double[] getTimeValuesSinceIdx(int idx) {
-      int resultSize = this.count - idx;
-      double[] result = new double[resultSize];
-      for (int i=0; i < resultSize; i++) {
-        result[i] = getMilliTimeStamp(idx+i);
-      }
-      return result;
-    }
-  }
-
-  /**
-   * Defines a statistic resource type. Each resource instance must be
-   * of a single type. The type defines what statistics each instance
-   * of it will support. The type also has a description of itself.
-   */
-  public static class ResourceType {
-    private boolean loaded;
-//    private final int id;
-    private final String name;
-    private String desc;
-    private final StatDescriptor[] stats;
-    private Map descriptorMap;
-
-    public void dump(PrintWriter stream) {
-      if (loaded) {
-        stream.println(name + ": " + desc);
-        for (int i=0; i < stats.length; i++) {
-          stats[i].dump(stream);
-        }
-      }
-    }
-    
-    protected ResourceType(int id, String name, int statCount) {
-      this.loaded = false;
-//      this.id = id;
-      this.name = name;
-      this.desc = null;
-      this.stats = new StatDescriptor[statCount];
-      this.descriptorMap = null;
-    }
-
-    protected ResourceType(int id, String name, String desc, int statCount) {
-      this.loaded = true;
-//      this.id = id;
-      this.name = name;
-      this.desc = desc;
-      this.stats = new StatDescriptor[statCount];
-      this.descriptorMap = new HashMap();
-    }
-    public boolean isLoaded() {
-      return this.loaded;
-    }
-    /**
-     * Frees up any resources no longer needed after the archive file is closed.
-     * Returns true if this guy is no longer needed.
-     */
-    protected boolean close() {
-      if (isLoaded()) {
-        for (int i=0; i < stats.length; i++) {
-          if (stats[i] != null) {
-            if (!stats[i].isLoaded()) {
-              stats[i] = null;
-            }
-          }
-        }
-        return false;
-      } else {
-        return true;
-      }
-    }
-    
-    void unload() {
-      this.loaded = false;
-      this.desc = null;
-      for (int i=0; i < this.stats.length; i++) {
-        this.stats[i].unload();
-      }
-      this.descriptorMap.clear();
-      this.descriptorMap = null;
-    }
-
-    protected void addStatDescriptor(StatArchiveFile archive, int offset, String name, boolean isCounter,
-                                   boolean largerBetter,
-                                   byte typeCode, String units, String desc) {
-      StatDescriptor descriptor = new StatDescriptor(name, offset, isCounter, largerBetter, typeCode, units, desc);
-      this.stats[offset] = descriptor;
-      if (archive.loadStatDescriptor(descriptor, this)) {
-        descriptorMap.put(name, descriptor);
-      }
-    }
-
-//    private int getId() {
-//      return this.id;
-//    }
-    /**
-     * Returns the name of this resource type.
-     */
-    public String getName() {
-      return this.name;
-    }
-    /**
-     * Returns an array of descriptors for each statistic this resource
-     * type supports.
-     */
-    public StatDescriptor[] getStats() {
-      return this.stats;
-    }
-    /**
-     * Gets a stat descriptor contained in this type given the stats name.
-     * @param name the name of the stat to find in the current type
-     * @return the descriptor that matches the name or null if the type
-     * does not have a stat of the given name
-     */
-    public StatDescriptor getStat(String name) {
-      return (StatDescriptor)descriptorMap.get(name);
-    }
-    /**
-     * Returns a description of this resource type.
-     */
-    public String getDescription() {
-      return this.desc;
-    }
-
-    @Override
-    public int hashCode() {
-      final int prime = 31;
-      int result = 1;
-      result = prime * result + ((name == null) ? 0 : name.hashCode());
-      return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-      if (this == obj)
-        return true;
-      if (obj == null)
-        return false;
-      if (getClass() != obj.getClass())
-        return false;
-      ResourceType other = (ResourceType) obj;
-      if (name == null) {
-        if (other.name != null)
-          return false;
-      } else if (!name.equals(other.name))
-        return false;
-      return true;
-    }
-  }
-
-  /**
-   * Describes some global information about the archive.
-   */
-  public static class ArchiveInfo {
-    private final StatArchiveFile archive;
-    private final byte archiveVersion;
-    private final long startTimeStamp; // in milliseconds
-    private final long systemStartTimeStamp; // in milliseconds
-    private final int timeZoneOffset;
-    private final String timeZoneName;
-    private final String systemDirectory;
-    private final long systemId;
-    private final String productVersion;
-    private final String os;
-    private final String machine;
-
-    public ArchiveInfo(StatArchiveFile archive, byte archiveVersion,
-                       long startTimeStamp, long systemStartTimeStamp,
-                       int timeZoneOffset,String timeZoneName,
-                       String systemDirectory, long systemId,
-                       String productVersion, String os, String machine) {
-      this.archive = archive;
-      this.archiveVersion = archiveVersion;
-      this.startTimeStamp = startTimeStamp;
-      this.systemStartTimeStamp = systemStartTimeStamp;
-      this.timeZoneOffset = timeZoneOffset;
-      this.timeZoneName = timeZoneName;
-      this.systemDirectory = systemDirectory;
-      this.systemId = systemId;
-      this.productVersion = productVersion;
-      this.os = os;
-      this.machine = machine;
-      archive.setTimeZone(getTimeZone());
-    }
-
-    /**
-     * Returns the difference, measured in milliseconds, between the time
-     * the archive file was create and midnight, January 1, 1970 UTC.
-     */
-    public long getStartTimeMillis() {
-      return this.startTimeStamp;
-    }
-    /**
-     * Returns the difference, measured in milliseconds, between the time
-     * the archived system was started and midnight, January 1, 1970 UTC.
-     */
-    public long getSystemStartTimeMillis() {
-      return this.systemStartTimeStamp;
-    }
-    /**
-     * Returns a numeric id of the archived system.  It can be used in
-     * conjunction with the {@link #getSystemStartTimeMillis} to
-     * uniquely identify an archived system.
-     */
-    public long getSystemId() {
-      return this.systemId;
-    }
-    /**
-     * Returns a string describing the operating system the archive was
-     * written on.
-     */
-    public String getOs() {
-      return this.os;
-    }
-    /**
-     * Returns a string describing the machine the archive was
-     * written on.
-     */
-    public String getMachine() {
-      return this.machine;
-    }
-    /**
-     * Returns  the time zone used when the archive was created.
-     * This can be used to print timestamps in the same time zone
-     * that was in effect when the archive was created.
-     */
-    public TimeZone getTimeZone() {
-      TimeZone result = TimeZone.getTimeZone(this.timeZoneName);
-      if (result.getRawOffset() != this.timeZoneOffset) {
-        result = new SimpleTimeZone(this.timeZoneOffset, this.timeZoneName);
-      }
-      return result;
-    }
-    /**
-     * Returns a string containing the version of the product that wrote
-     * this archive.
-     */
-    public String getProductVersion() {
-      return this.productVersion;
-    }
-    /**
-     * Returns a numeric code that represents the format version used to
-     * encode the archive as a stream of bytes.
-     */
-    public int getArchiveFormatVersion() {
-      return this.archiveVersion;
-    }
-    /**
-     * Returns a string describing the system that this archive recorded.
-     */
-    public String getSystem() {
-      return this.systemDirectory;
-    }
-    /**
-     * Return the name of the file this archive was stored in or
-     * an empty string if the archive was not stored in a file.
-     */
-    public String getArchiveFileName() {
-      if (this.archive != null) {
-        return this.archive.getFile().getPath();
-      } else {
-        return "";
-      }
-    }
-
-    /**
-     * Returns a string representation of this object.
-     */
-    @Override
-    public String toString() {
-      StringWriter sw = new StringWriter();
-      this.dump(new PrintWriter(sw));
-      return sw.toString();
-    }
-    
-    protected void dump(PrintWriter stream) {
-      if (archive != null) {
-        stream.println("archive=" + archive.getFile());
-      }
-      stream.println("archiveVersion=" + archiveVersion);
-      if (archive != null) {
-        stream.println("startDate=" + archive.formatTimeMillis(startTimeStamp));
-      }
-      // stream.println("startTimeStamp=" + startTimeStamp +" tz=" + timeZoneName + " tzOffset=" + timeZoneOffset);
-      // stream.println("timeZone=" + getTimeZone().getDisplayName());
-      stream.println("systemDirectory=" + systemDirectory);
-      if (archive != null) {
-        stream.println("systemStartDate=" + archive.formatTimeMillis(systemStartTimeStamp));
-      }
-      stream.println("systemId=" + systemId);
-      stream.println("productVersion=" + productVersion);
-      stream.println("osInfo=" + os);
-      stream.println("machineInfo=" + machine);
-    }
-  }
-
-  /**
-   * Defines a single instance of a resource type.
-   */
-  public static class ResourceInst {
-    private final boolean loaded;
-    private final StatArchiveFile archive;
-//    private final int uniqueId;
-    private final ResourceType type;
-    private final String name;
-    private final long id;
-    private boolean active = true;
-    private final SimpleValue[] values;
-    private int firstTSidx = -1;
-    private int lastTSidx = -1;
-
-    /**
-     * Returns the approximate amount of memory used to implement this object.
-     */
-    protected int getMemoryUsed() {
-      int result = 0;
-      if (values != null) {
-        for (int i=0; i < values.length; i++) {
-          result += this.values[i].getMemoryUsed();
-        }
-      }
-      return result;
-    }
-
-    public StatArchiveReader getReader() {
-      return archive.getReader();
-    }
-    /**
-     * Returns a string representation of this object.
-     */
-    @Override
-    public String toString() {
-      StringBuffer result = new StringBuffer();
-      result.append(name)
-        .append(", ")
-        .append(id)
-        .append(", ")
-        .append(type.getName())
-        .append(": \"")
-        .append(archive.formatTimeMillis(getFirstTimeMillis()))
-        .append('\"');
-      if (!active) {
-        result.append(" inactive");
-      }
-      result.append(" samples="+ getSampleCount());
-      return result.toString();
-    }
-    /**
-     * Returns the number of times this resource instance has been sampled.
-     */
-    public int getSampleCount() {
-      if (active) {
-        return archive.getTimeStamps().getSize() - firstTSidx;
-      } else {
-        return (lastTSidx+1) - firstTSidx;
-      }
-    }
-
-    public StatArchiveFile getArchive() {
-      return this.archive;
-    }
-    
-    protected void dump(PrintWriter stream) {
-      stream.println(name + ":"
-                     + " file=" + getArchive().getFile()
-                     + " id=" + id
-                     + (active? "" : " deleted")
-                     + " start=" + archive.formatTimeMillis(getFirstTimeMillis()));
-      for (int i=0; i < values.length; i++) {
-        values[i].dump(stream);
-      }
-    }
-
-    protected ResourceInst(StatArchiveFile archive, int uniqueId, String name, long id, ResourceType type, boolean loaded) {
-      this.loaded = loaded;
-      this.archive = archive;
-//      this.uniqueId = uniqueId;
-      this.name = name;
-      this.id = id;
-      Assert.assertTrue(type != null);
-      this.type = type;
-      if (loaded) {
-        StatDescriptor[] stats = type.getStats();
-        this.values = new SimpleValue[stats.length];
-        for (int i=0; i < stats.length; i++) {
-          if (archive.loadStat(stats[i], this)) {
-            this.values[i] = new SimpleValue(this, stats[i]);
-          } else {
-            this.values[i] = null;
-          }
-        }
-      } else {
-        this.values = null;
-      }
-    }
-
-    void matchSpec(StatSpec spec, List matchedValues) {
-      if (spec.typeMatches(this.type.getName())) {
-        if (spec.instanceMatches(this.getName(), this.getId())) {
-          for (int statIdx=0; statIdx < values.length; statIdx++) {
-            if (values[statIdx] != null) {
-              if (spec.statMatches(values[statIdx].getDescriptor().getName())) {
-                matchedValues.add(values[statIdx]);
-              }
-            }
-          }
-        }
-      }
-    }
-
-    protected void initialValue(int statOffset, long v) {
-      if (this.values != null && this.values[statOffset] != null) {
-        this.values[statOffset].initialValue(v);
-      }
-    }
-    /**
-     * Returns true if sample was added.
-     */
-    protected boolean addValueSample(int statOffset, long statDeltaBits) {
-      if (this.values != null && this.values[statOffset] != null) {
-        this.values[statOffset].prepareNextBits(statDeltaBits);
-        return true;
-      } else {
-        return false;
-      }
-    }
-    
-    public boolean isLoaded() {
-      return this.loaded;
-    }
-
-    /**
-     * Frees up any resources no longer needed after the archive file is closed.
-     * Returns true if this guy is no longer needed.
-     */
-    protected boolean close() {
-      if (isLoaded()) {
-        for (int i=0; i < values.length; i++) {
-          if (values[i] != null) {
-            values[i].shrink();
-          }
-        }
-        return false;
-      } else {
-        return true;
-      }
-    }
-
-    protected int getFirstTimeStampIdx() {
-      return this.firstTSidx;
-    }
-    protected long[] getAllRawTimeStamps() {
-      return archive.getTimeStamps().getRawTimeStamps();
-    }
-    protected long getTimeBase() {
-      return archive.getTimeStamps().getBase();
-    }
-    /**
-     * Returns an array of doubles containing the timestamps at which
-     * this instances samples where taken. Each of these timestamps
-     * is the difference, measured in milliseconds, between the sample
-     * time and midnight, January 1, 1970 UTC.
-     * Although these values are double they can safely be converted
-     * to <code>long</code> with no loss of information.
-     */
-    public double[] getSnapshotTimesMillis() {
-      return archive.getTimeStamps().getTimeValuesSinceIdx(firstTSidx);
-    }
-    /**
-     * Returns an array of statistic value descriptors. Each element
-     * of the array describes the corresponding statistic this instance
-     * supports. The <code>StatValue</code> instances can be used to
-     * obtain the actual sampled values of the instances statistics.
-     */
-    public StatValue[] getStatValues() {
-      return this.values;
-    }
-    /**
-     * Gets the value of the stat in the current instance given the stat name.
-     * @param name the name of the stat to find in the current instance
-     * @return the value that matches the name or null if the instance
-     * does not have a stat of the given name
-     *
-     */
-    public StatValue getStatValue(String name) {
-      StatValue result = null;
-      StatDescriptor desc = getType().getStat(name);
-      if (desc != null) {
-        result = values[desc.getOffset()];
-      }
-      return result;
-    }
-
-    /**
-     * Returns the name of this instance.
-     */
-    public String getName() {
-      return this.name;
-    }
-    /**
-     * Returns the id of this instance.
-     */
-    public long getId() {
-      return this.id;
-    }
-    /**
-     * Returns the difference, measured in milliseconds, between the time
-     * of the instance's first sample and midnight, January 1, 1970 UTC.
-     */
-    public long getFirstTimeMillis() {
-      return archive.getTimeStamps().getMilliTimeStamp(firstTSidx);
-    }
-    /**
-     * Returns resource type of this instance.
-     */
-    public ResourceType getType() {
-      return this.type;
-    }
-    protected void makeInactive() {
-      this.active = false;
-      lastTSidx = archive.getTimeStamps().getSize() - 1;
-      close(); // this frees up unused memory now that no more samples
-    }
-    /**
-     * Returns true if archive might still have future samples for this instance.
-     */
-    public boolean isActive() {
-      return this.active;
-    }
-    protected void addTimeStamp() {
-      if (this.loaded) {
-        if (firstTSidx == -1) {
-          firstTSidx = archive.getTimeStamps().getSize() - 1;
-        }
-        for (int i=0; i < values.length; i++) {
-          if (values[i] != null) {
-            values[i].addSample();
-          }
-        }
-      }
-    }
-
-    @Override
-    public int hashCode() {
-      final int prime = 31;
-      int result = 1;
-      result = prime * result + (int) (id ^ (id >>> 32));
-      result = prime * result + ((name == null) ? 0 : name.hashCode());
-      result = prime * result + ((type == null) ? 0 : type.hashCode());
-      return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-      if (this == obj)
-        return true;
-      if (obj == null)
-        return false;
-      if (getClass() != obj.getCl

<TRUNCATED>


Mime
View raw message