geode-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kl...@apache.org
Subject [15/23] incubator-geode git commit: GEODE-1781: repackage internal statistics classes and refactor statistics tests
Date Mon, 15 Aug 2016 18:43:43 GMT
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/866bacec/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/DummyStatisticsImpl.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/DummyStatisticsImpl.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/DummyStatisticsImpl.java
new file mode 100644
index 0000000..b5c5ec1
--- /dev/null
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/DummyStatisticsImpl.java
@@ -0,0 +1,242 @@
+/*
+ * 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.statistics;
+
+import java.util.function.DoubleSupplier;
+import java.util.function.IntSupplier;
+import java.util.function.LongSupplier;
+
+import com.gemstone.gemfire.*;
+
+/**
+ * An implementation of {@link Statistics} that does nothing.
+ * Setting the "gemfire.statsDisabled" to true causes it to be used.
+ *
+ * @see <A href="package-summary.html#statistics">Package introduction</A>
+ *
+ *
+ * @since GemFire 3.0
+ *
+ */
+public class DummyStatisticsImpl implements Statistics {
+  
+  private final StatisticsType type;
+  private final String textId;
+  private final long numericId;
+
+  ///////////////////////  Constructors  ///////////////////////
+
+  /**
+   * Creates a new statistics instance of the given type
+   *
+   * @param type
+   *        A description of the statistics
+   */
+  public DummyStatisticsImpl(StatisticsType type, String textId, long numericId) {
+    this.type = type;
+    this.textId = textId;
+    this.numericId = numericId;
+  }
+
+  public final void close() {
+  }
+
+  ////////////////////////  accessor Methods  ///////////////////////
+
+  public final int nameToId(String name) {
+    return this.type.nameToId(name);
+  }
+
+  public final StatisticDescriptor nameToDescriptor(String name) {
+    return this.type.nameToDescriptor(name);
+  }
+
+  public final long getUniqueId() {
+    return 0;
+  }
+
+  public final StatisticsType getType() {
+    return this.type;
+  }
+
+  public final String getTextId() {
+    return this.textId;
+  }
+  public final long getNumericId() {
+    return this.numericId;
+  }
+  public final boolean isAtomic() {
+    return true;
+  }
+  public final boolean isClosed() {
+    return false;
+  }
+  
+  ////////////////////////  set() Methods  ///////////////////////
+
+  public final void setInt(int id, int value) {
+  }
+
+  public final void setInt(StatisticDescriptor descriptor, int value) {
+  }
+
+  public final void setInt(String name, int value) {
+  }
+
+  public final void setLong(int id, long value) {
+  }
+
+  public final void setLong(StatisticDescriptor descriptor, long value) {
+  }
+
+  public final void setLong(String name, long value) {
+  }
+
+  public final void setDouble(int id, double value) {
+  }
+
+  public final void setDouble(StatisticDescriptor descriptor, double value) {
+  }
+
+  public final void setDouble(String name, double value) {
+  }
+
+  ///////////////////////  get() Methods  ///////////////////////
+
+  public final int getInt(int id) {
+    return 0;
+  }
+
+  public final int getInt(StatisticDescriptor descriptor) {
+    return 0;
+  }
+
+  public final int getInt(String name) {
+    return 0;
+  }
+
+  public final long getLong(int id) {
+    return 0;
+  }
+
+  public final long getLong(StatisticDescriptor descriptor) {
+    return 0;
+  }
+
+  public final long getLong(String name) {
+    return 0;
+  }
+
+  public final double getDouble(int id) {
+    return 0.0;
+  }
+
+  public final double getDouble(StatisticDescriptor descriptor) {
+    return 0.0;
+  }
+
+  public final double getDouble(String name) {
+    return 0.0;
+  }
+
+  private static final Number dummyNumber = Integer.valueOf(0);
+
+  public final Number get(StatisticDescriptor descriptor) {
+    return dummyNumber; 
+  }
+
+  public final Number get(String name) {
+    return dummyNumber; 
+  }
+
+  public final long getRawBits(StatisticDescriptor descriptor) {
+    return 0;
+  }
+
+  public final long getRawBits(String name) {
+    return 0;
+  }
+
+  ////////////////////////  inc() Methods  ////////////////////////
+
+  public final void incInt(int id, int delta) {
+  }
+
+  public final void incInt(StatisticDescriptor descriptor, int delta) {
+  }
+
+  public final void incInt(String name, int delta) {
+  }
+
+  public final void incLong(int id, long delta) {
+  }
+
+  public final void incLong(StatisticDescriptor descriptor, long delta) {
+  }
+
+  public final void incLong(String name, long delta) {
+  }
+
+  public final void incDouble(int id, double delta) {
+  }
+
+  public final void incDouble(StatisticDescriptor descriptor, double delta) {
+  }
+
+  public final void incDouble(String name, double delta) {
+  }
+
+  @Override
+  public IntSupplier setIntSupplier(final int id, final IntSupplier supplier) {
+    return null;
+  }
+
+  @Override
+  public IntSupplier setIntSupplier(final String name, final IntSupplier supplier) {
+    return null;
+  }
+
+  @Override
+  public IntSupplier setIntSupplier(final StatisticDescriptor descriptor, final IntSupplier supplier) {
+    return null;
+  }
+
+  @Override public LongSupplier setLongSupplier(final int id, final LongSupplier supplier) {
+    return null;
+  }
+
+  @Override public LongSupplier setLongSupplier(final String name, final LongSupplier supplier) {
+    return null;
+  }
+
+  @Override public LongSupplier setLongSupplier(final StatisticDescriptor descriptor, final LongSupplier supplier) {
+    return null;
+  }
+
+  @Override public DoubleSupplier setDoubleSupplier(final int id, final DoubleSupplier supplier) {
+    return null;
+  }
+
+  @Override public DoubleSupplier setDoubleSupplier(final String name, final DoubleSupplier supplier) {
+    return null;
+  }
+
+  @Override
+  public DoubleSupplier setDoubleSupplier(final StatisticDescriptor descriptor, final DoubleSupplier supplier) {
+    return null;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/866bacec/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/GemFireStatSampler.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/GemFireStatSampler.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/GemFireStatSampler.java
new file mode 100644
index 0000000..c723b0c
--- /dev/null
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/GemFireStatSampler.java
@@ -0,0 +1,507 @@
+/*
+ * 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.statistics;
+
+import com.gemstone.gemfire.Statistics;
+import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
+import com.gemstone.gemfire.distributed.internal.membership.InternalDistributedMember;
+import com.gemstone.gemfire.internal.GemFireVersion;
+import com.gemstone.gemfire.internal.OSProcess;
+import com.gemstone.gemfire.internal.PureJavaMode;
+import com.gemstone.gemfire.internal.admin.ListenerIdMap;
+import com.gemstone.gemfire.internal.admin.remote.StatListenerMessage;
+import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
+import com.gemstone.gemfire.internal.logging.LogService;
+import com.gemstone.gemfire.internal.logging.log4j.LocalizedMessage;
+import com.gemstone.gemfire.internal.logging.log4j.LogMarker;
+import com.gemstone.gemfire.internal.statistics.platform.OsStatisticsFactory;
+import com.gemstone.gemfire.internal.statistics.platform.ProcessStats;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.logging.log4j.Logger;
+
+/**
+ * GemFireStatSampler adds listeners and rolling archives to HostStatSampler.
+ * <p>
+ * The StatisticsManager is implemented by DistributedSystem.
+ * 
+ */
+public final class GemFireStatSampler extends HostStatSampler {
+
+  private static final Logger logger = LogService.getLogger();
+  
+  private final ListenerIdMap listeners = new ListenerIdMap();
+  
+  // TODO: change the listener maps to be copy-on-write
+  
+  private final Map<LocalStatListenerImpl, Boolean> localListeners = 
+      new ConcurrentHashMap<LocalStatListenerImpl, Boolean>();
+  
+  private final Map<InternalDistributedMember, List<RemoteStatListenerImpl>> recipientToListeners = 
+      new HashMap<InternalDistributedMember, List<RemoteStatListenerImpl>>();
+  
+  private final InternalDistributedSystem con;
+  
+  private int nextListenerId = 1;
+  private ProcessStats processStats = null;
+
+  //////////////////////  Constructors  //////////////////////
+
+  public GemFireStatSampler(InternalDistributedSystem con) {
+    super(con.getCancelCriterion(), new StatSamplerStats(con, con.getId()));
+    this.con = con;
+  }
+  
+  /**
+   * Returns the <code>ProcessStats</code> for this Java VM.  Note
+   * that <code>null</code> will be returned if operating statistics
+   * are disabled.
+   *
+   * @since GemFire 3.5
+   */
+  public final ProcessStats getProcessStats() {
+    return this.processStats;
+  }
+  
+  @Override
+  public String getProductDescription() {
+    return "GemFire " + GemFireVersion.getGemFireVersion()
+           + " #" + GemFireVersion.getBuildId()
+           + " as of " + GemFireVersion.getSourceDate();
+  }
+
+  public int addListener(InternalDistributedMember recipient, long resourceId, String statName) {
+    int result = getNextListenerId();
+    synchronized (listeners) {
+      while (listeners.get(result) != null) {
+        // previous one was still being used
+        result = getNextListenerId();
+      }
+      RemoteStatListenerImpl sl = RemoteStatListenerImpl.create(result, recipient, 
+          resourceId, statName, this);
+      listeners.put(result, sl);
+      List<RemoteStatListenerImpl> l = recipientToListeners.get(recipient);
+      if (l == null) {
+        l = new ArrayList<RemoteStatListenerImpl>();
+        recipientToListeners.put(recipient, l);
+      }
+      l.add(sl);
+    }
+    return result;
+  }
+  
+  public boolean removeListener(int listenerId) {
+    synchronized (listeners) {
+      RemoteStatListenerImpl sl = (RemoteStatListenerImpl)listeners.remove(listenerId);
+      if (sl != null) {
+        List<RemoteStatListenerImpl> l = recipientToListeners.get(sl.getRecipient());
+        l.remove(sl);
+      }
+      return sl != null;
+    }
+  }
+
+  public void removeListenersByRecipient(InternalDistributedMember recipient) {
+    synchronized (listeners) {
+      List<RemoteStatListenerImpl> l = recipientToListeners.get(recipient);
+      if (l != null && l.size() != 0) {
+        for (RemoteStatListenerImpl sl : l) {
+          listeners.remove(sl.getListenerId());
+        }
+        recipientToListeners.remove(recipient);
+      }
+    }
+  }
+
+  public void addLocalStatListener(LocalStatListener l, Statistics stats, String statName) {
+    LocalStatListenerImpl sl = null;
+    synchronized (LocalStatListenerImpl.class) {
+      sl = LocalStatListenerImpl.create(l, stats, statName);
+    }
+    this.localListeners.put(sl, Boolean.TRUE);
+  }
+
+  public boolean removeLocalStatListener(LocalStatListener listener) {
+    Iterator<Map.Entry<LocalStatListenerImpl, Boolean>> it = 
+                  this.localListeners.entrySet().iterator();
+    while (it.hasNext()) {
+      Map.Entry<LocalStatListenerImpl, Boolean> entry = it.next();
+      if (listener.equals(entry.getKey().getListener())) {
+        it.remove();
+        return true;
+      }
+    }
+    return false;
+  }
+
+  public Set<LocalStatListenerImpl> getLocalListeners() {
+    return this.localListeners.keySet();
+  }
+  
+  @Override
+  public final File getArchiveFileName() {
+    return this.con.getConfig().getStatisticArchiveFile();
+  }
+  
+  @Override
+  public final long getArchiveFileSizeLimit() {
+    if (fileSizeLimitInKB()) {
+      // use KB instead of MB to speed up rolling for testing
+      return ((long)this.con.getConfig().getArchiveFileSizeLimit()) * (1024);
+    } else {
+      return ((long)this.con.getConfig().getArchiveFileSizeLimit()) * (1024*1024);
+    }
+  }
+  
+  @Override
+  public final long getArchiveDiskSpaceLimit() {
+    if (fileSizeLimitInKB()) {
+      // use KB instead of MB to speed up removal for testing
+      return ((long)this.con.getConfig().getArchiveDiskSpaceLimit()) * (1024);
+    } else {
+      return ((long)this.con.getConfig().getArchiveDiskSpaceLimit()) * (1024*1024);
+    }
+  }
+  
+  @Override
+  protected void checkListeners() {
+    checkLocalListeners();
+    synchronized (listeners) {
+      if (listeners.size() == 0) {
+        return;
+      }
+      long timeStamp = System.currentTimeMillis();
+      Iterator<Map.Entry<InternalDistributedMember, List<RemoteStatListenerImpl>>> it1 = 
+          recipientToListeners.entrySet().iterator();
+      while (it1.hasNext()) {
+        if (stopRequested()) return;
+        Map.Entry<InternalDistributedMember, List<RemoteStatListenerImpl>> me = 
+            it1.next();
+        List<RemoteStatListenerImpl> l = me.getValue();
+        if (l.size() > 0) {
+          InternalDistributedMember recipient = (InternalDistributedMember)me.getKey();
+          StatListenerMessage msg =
+            StatListenerMessage.create(timeStamp, l.size());
+          msg.setRecipient(recipient);
+          for (RemoteStatListenerImpl statListener : l) {
+            if (getStatisticsManager().statisticsExists(statListener.getStatId())) {
+              statListener.checkForChange(msg);
+            } else {
+              // its stale; indicate this with a negative listener id
+              // fix for bug 29405
+              msg.addChange(-statListener.getListenerId(), 0);
+            }
+          }
+          this.con.getDistributionManager().putOutgoing(msg);
+        }
+      }
+    }
+  }
+  
+  @Override
+  protected final int getSampleRate() {
+    return this.con.getConfig().getStatisticSampleRate();
+  }
+  
+  @Override
+  public final boolean isSamplingEnabled() {
+    return this.con.getConfig().getStatisticSamplingEnabled();
+  }
+  
+  @Override
+  protected final StatisticsManager getStatisticsManager() {
+    return this.con;
+  }
+  
+  @Override
+  protected final OsStatisticsFactory getOsStatisticsFactory() {
+    return this.con;
+  }
+  
+  @Override
+  protected final long getSpecialStatsId() {
+    long statId = OSProcess.getId();
+    if (statId == 0 || statId == -1) {
+      statId = getStatisticsManager().getId();
+    }
+    return statId;
+  }
+  
+  @Override
+  protected final void initProcessStats(long id) {
+    if (PureJavaMode.osStatsAreAvailable()) {
+      if (osStatsDisabled()) {
+        logger.info(LogMarker.STATISTICS, LocalizedMessage.create(LocalizedStrings.GemFireStatSampler_OS_STATISTIC_COLLECTION_DISABLED_BY_OSSTATSDISABLED_SYSTEM_PROPERTY));
+      } else {
+        int retVal = HostStatHelper.initOSStats();
+        if ( retVal != 0 ) {
+          logger.error(LogMarker.STATISTICS, LocalizedMessage.create(LocalizedStrings.GemFireStatSampler_OS_STATISTICS_FAILED_TO_INITIALIZE_PROPERLY_SOME_STATS_MAY_BE_MISSING_SEE_BUGNOTE_37160)); 
+        }
+        HostStatHelper.newSystem(getOsStatisticsFactory());
+        String statName = getStatisticsManager().getName();
+        if (statName == null || statName.length() == 0) {
+          statName = "javaApp" + getStatisticsManager().getId();
+        }
+        Statistics stats = HostStatHelper.newProcess(getOsStatisticsFactory(), id, statName + "-proc");
+        this.processStats = HostStatHelper.newProcessStats(stats); 
+      }
+    }
+  }
+
+ @Override
+  protected final void sampleProcessStats(boolean prepareOnly) {
+    if (prepareOnly || osStatsDisabled() || !PureJavaMode.osStatsAreAvailable()) {
+      return;
+    }
+    List<Statistics> l = getStatisticsManager().getStatsList();
+    if (l == null) {
+      return;
+    }
+    if (stopRequested()) return;
+    HostStatHelper.readyRefreshOSStats();
+    Iterator<Statistics> it = l.iterator();
+    while (it.hasNext()) {
+      if (stopRequested()) return;
+      StatisticsImpl s = (StatisticsImpl)it.next();
+      if (s.usesSystemCalls()) {
+        HostStatHelper.refresh((LocalStatisticsImpl)s);
+      }
+    }
+  }
+
+ @Override
+  protected final void closeProcessStats() {
+    if (PureJavaMode.osStatsAreAvailable()) {
+      if (!osStatsDisabled()) {
+        if (this.processStats != null) {
+          this.processStats.close();
+        }
+        HostStatHelper.closeOSStats();
+      }
+    }
+  }
+
+  private void checkLocalListeners() {
+    for (LocalStatListenerImpl st : this.localListeners.keySet()) {
+      if (getStatisticsManager().statisticsExists(st.getStatId())) {
+        st.checkForChange();
+      }
+    }
+  }
+  
+  private int getNextListenerId() {
+    int result = nextListenerId++;
+    if (nextListenerId < 0) {
+      nextListenerId = 1;
+    }
+    return result;
+  }
+    
+  protected static abstract class StatListenerImpl {
+    protected Statistics stats;
+    protected StatisticDescriptorImpl stat;
+    protected boolean oldValueInitialized = false;
+    protected long oldValue;
+
+    public long getStatId() {
+      if (this.stats.isClosed()) {
+        return -1;
+      } else {
+        return this.stats.getUniqueId();
+      }
+    }
+    
+    protected abstract double getBitsAsDouble(long bits);
+  }
+
+  protected static abstract class LocalStatListenerImpl extends StatListenerImpl {
+    private LocalStatListener listener;
+    
+    public LocalStatListener getListener() {
+      return this.listener;
+    }
+    
+    static LocalStatListenerImpl create(LocalStatListener l, Statistics stats, String statName) {
+      LocalStatListenerImpl result = null;
+      StatisticDescriptorImpl stat = (StatisticDescriptorImpl)stats.nameToDescriptor(statName);
+      switch (stat.getTypeCode()) {
+      case StatisticDescriptorImpl.BYTE:
+      case StatisticDescriptorImpl.SHORT:
+      case StatisticDescriptorImpl.INT:
+      case StatisticDescriptorImpl.LONG:
+        result = new LocalLongStatListenerImpl();
+        break;
+      case StatisticDescriptorImpl.FLOAT:
+        result = new LocalFloatStatListenerImpl();
+        break;
+      case StatisticDescriptorImpl.DOUBLE:
+        result = new LocalDoubleStatListenerImpl();
+        break;
+      default:
+        throw new RuntimeException("Illegal field type " + stats.getType() + " for statistic");
+      }
+      result.stats = stats;
+      result.stat = stat;
+      result.listener = l;
+      return result;
+    }
+    
+    /**
+     * Checks to see if the value of the stat has changed. If it has then 
+     * the local listener is fired
+     */
+    public void checkForChange() {
+      long currentValue = stats.getRawBits(stat);
+      if (oldValueInitialized) {
+        if (currentValue == oldValue) {
+          return;
+        }
+      } else {
+        oldValueInitialized = true;
+      }
+      oldValue = currentValue;
+      listener.statValueChanged(getBitsAsDouble(currentValue));
+    }
+  }
+  
+  protected static class LocalLongStatListenerImpl extends LocalStatListenerImpl {
+    @Override
+    protected double getBitsAsDouble(long bits) {
+      return bits;
+    }
+  }
+
+  protected static class LocalFloatStatListenerImpl extends LocalStatListenerImpl {
+    @Override
+    protected double getBitsAsDouble(long bits) {
+      return Float.intBitsToFloat((int)bits);
+    }
+  }
+  
+  protected static class LocalDoubleStatListenerImpl extends LocalStatListenerImpl {
+    @Override
+    protected double getBitsAsDouble(long bits) {
+      return Double.longBitsToDouble(bits);
+    }
+  }
+
+  /**
+   * Used to register a StatListener.
+   */
+  protected static abstract class RemoteStatListenerImpl extends StatListenerImpl{
+    private int listenerId;
+    private InternalDistributedMember recipient;
+
+    @Override
+    public final int hashCode() {
+      return listenerId;
+    }
+    
+    @Override
+    public final boolean equals(Object o) {
+      if (o == null) {
+        return false;
+      }
+      if (o instanceof RemoteStatListenerImpl) {
+        return listenerId == ((RemoteStatListenerImpl)o).listenerId;
+      } else {
+        return false;
+      }
+    }
+
+    public int getListenerId() {
+      return this.listenerId;
+    }
+    
+    public InternalDistributedMember getRecipient() {
+      return this.recipient;
+    }
+    
+    static RemoteStatListenerImpl create(int listenerId, InternalDistributedMember recipient, long resourceId, String statName, HostStatSampler sampler) {
+      RemoteStatListenerImpl result = null;
+      Statistics stats = sampler.getStatisticsManager().findStatistics(resourceId);
+      StatisticDescriptorImpl stat = (StatisticDescriptorImpl)stats.nameToDescriptor(statName);
+      switch (stat.getTypeCode()) {
+      case StatisticDescriptorImpl.BYTE:
+      case StatisticDescriptorImpl.SHORT:
+      case StatisticDescriptorImpl.INT:
+      case StatisticDescriptorImpl.LONG:
+        result = new LongStatListenerImpl();
+        break;
+      case StatisticDescriptorImpl.FLOAT:
+        result = new FloatStatListenerImpl();
+        break;
+      case StatisticDescriptorImpl.DOUBLE:
+        result = new DoubleStatListenerImpl();
+        break;
+      default:
+        throw new RuntimeException(LocalizedStrings.GemFireStatSampler_ILLEGAL_FIELD_TYPE_0_FOR_STATISTIC.toLocalizedString(stats.getType()));
+      }
+      result.stats = stats;
+      result.stat = stat;
+      result.listenerId = listenerId;
+      result.recipient = recipient;
+      return result;
+    }
+    
+    /**
+     * Checks to see if the value of the stat has changed. If it has then it
+     * adds that change to the specified message.
+     */
+    public void checkForChange(StatListenerMessage msg) {
+      long currentValue = stats.getRawBits(stat);
+      if (oldValueInitialized) {
+        if (currentValue == oldValue) {
+          return;
+        }
+      } else {
+        oldValueInitialized = true;
+      }
+      oldValue = currentValue;
+      msg.addChange(listenerId, getBitsAsDouble(currentValue));
+    }
+  }
+
+  protected static class LongStatListenerImpl extends RemoteStatListenerImpl {
+    @Override
+    protected double getBitsAsDouble(long bits) {
+      return bits;
+    }
+  }
+
+  protected static class FloatStatListenerImpl extends RemoteStatListenerImpl {
+    @Override
+    protected double getBitsAsDouble(long bits) {
+      return Float.intBitsToFloat((int)bits);
+    }
+  }
+  
+  protected static class DoubleStatListenerImpl extends RemoteStatListenerImpl {
+    @Override
+    protected double getBitsAsDouble(long bits) {
+      return Double.longBitsToDouble(bits);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/866bacec/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/HostStatHelper.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/HostStatHelper.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/HostStatHelper.java
new file mode 100644
index 0000000..b52eaae
--- /dev/null
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/HostStatHelper.java
@@ -0,0 +1,303 @@
+/*
+ * 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.statistics;
+
+import com.gemstone.gemfire.*;
+//import com.gemstone.gemfire.util.*;
+import com.gemstone.gemfire.internal.PureJavaMode;
+import com.gemstone.gemfire.internal.SocketCreator;
+import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
+import com.gemstone.gemfire.internal.statistics.platform.LinuxProcFsStatistics;
+import com.gemstone.gemfire.internal.statistics.platform.LinuxProcessStats;
+import com.gemstone.gemfire.internal.statistics.platform.LinuxSystemStats;
+import com.gemstone.gemfire.internal.statistics.platform.OSXProcessStats;
+import com.gemstone.gemfire.internal.statistics.platform.OSXSystemStats;
+import com.gemstone.gemfire.internal.statistics.platform.OsStatisticsFactory;
+import com.gemstone.gemfire.internal.statistics.platform.ProcessStats;
+import com.gemstone.gemfire.internal.statistics.platform.SolarisProcessStats;
+import com.gemstone.gemfire.internal.statistics.platform.SolarisSystemStats;
+import com.gemstone.gemfire.internal.statistics.platform.WindowsProcessStats;
+import com.gemstone.gemfire.internal.statistics.platform.WindowsSystemStats;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * Provides native methods which fetch operating system statistics.
+ */
+public class HostStatHelper {
+  static final int SOLARIS_CODE = 1; // Sparc Solaris
+  static final int WINDOWS_CODE = 2;
+  static final int LINUX_CODE = 3; // x86 Linux
+  static final int OSX_CODE = 4;  // Mac OS X
+
+  static final int PROCESS_STAT_FLAG = 1;
+  static final int SYSTEM_STAT_FLAG = 2;
+  
+  static final int osCode;
+
+  static {
+    String osName = System.getProperty("os.name", "unknown");
+    if (! PureJavaMode.osStatsAreAvailable()) {
+      throw new RuntimeException(LocalizedStrings.HostStatHelper_HOSTSTATHELPER_NOT_ALLOWED_IN_PURE_JAVA_MODE.toLocalizedString());
+    } else if (osName.equals("SunOS")) {
+      osCode = SOLARIS_CODE;
+    } else if (osName.startsWith("Windows")) {
+      osCode = WINDOWS_CODE;
+    } else if (osName.startsWith("Linux")) {
+      osCode = LINUX_CODE;
+    } else if (osName.equals("Mac OS X")) { 
+      osCode = OSX_CODE;
+    } else {
+      throw new InternalGemFireException(LocalizedStrings.HostStatHelper_UNSUPPORTED_OS_0_SUPPORTED_OSS_ARE_SUNOSSPARC_SOLARIS_LINUXX86_AND_WINDOWS.toLocalizedString(osName));
+    }
+  }
+  public static boolean isWindows() {
+    return osCode == WINDOWS_CODE;
+  }
+  public static boolean isUnix() {
+    return osCode != WINDOWS_CODE;
+  }
+  public static boolean isSolaris() {
+    return osCode == SOLARIS_CODE;
+  }
+  public static boolean isLinux() {
+    return osCode == LINUX_CODE;
+  }
+  public static boolean isOSX() {
+      return osCode == OSX_CODE;
+  }
+  
+  private HostStatHelper() {
+    // instances are not allowed
+  }
+
+  static int initOSStats() {
+    if(isLinux()) {
+      return LinuxProcFsStatistics.init();
+    } else {
+      return HostStatHelper.init();
+    }
+  }
+  
+  static void closeOSStats() {
+    if(isLinux()) {
+      LinuxProcFsStatistics.close();
+    } else {
+      HostStatHelper.close();
+    }
+  }
+  
+  static void readyRefreshOSStats() {
+    if(isLinux()) {
+      LinuxProcFsStatistics.readyRefresh();
+    } else {
+      HostStatHelper.readyRefresh();
+    }
+  }
+  
+  /**
+   * Allocates and initializes any resources required to sample
+   * operating system statistics.
+   * returns 0 if initialization succeeded
+   */
+  private static native int init();
+  /**
+   * Frees up resources used by this class. Once close is called this
+   * class can no longer be used.
+   */
+  private static native void close();
+  /**
+   * Should be called before any calls to the refresh methods.
+   * On some platforms if this is not called then the refesh methods
+   * will just keep returning the same old data.
+   */
+  private static native void readyRefresh();
+  /**
+   * Refreshes the specified process stats instance by fetching
+   * the current OS values for the given stats and storing them in the instance.
+   */
+  private static void refreshProcess(LocalStatisticsImpl s) {
+    int pid = (int)s.getNumericId();
+    if(isLinux()) {
+      LinuxProcFsStatistics.refreshProcess(pid, s._getIntStorage(), s._getLongStorage(), s._getDoubleStorage());
+    } else {
+      refreshProcess(pid, s._getIntStorage(), s._getLongStorage(), s._getDoubleStorage());
+    }  
+  }
+  private static native void refreshProcess(int pid, int[] ints, long[] longs, double[] doubles);
+  /**
+   * Refreshes the specified system stats instance by fetching
+   * the current OS values for the local machine and storing them in
+   * the instance.
+   */
+  private static void refreshSystem(LocalStatisticsImpl s) {
+    if(isLinux()) {
+      LinuxProcFsStatistics.refreshSystem(s._getIntStorage(), s._getLongStorage(), s._getDoubleStorage());
+    } else {
+      refreshSystem(s._getIntStorage(), s._getLongStorage(), s._getDoubleStorage());
+    }
+  }
+  private static native void refreshSystem(int[] ints, long[] longs, double[] doubles);
+
+  /**
+   * The call should have already checked to make sure
+   * usesSystemCalls returns true.
+   */
+  public static void refresh(LocalStatisticsImpl stats) {
+    int flags = stats.getOsStatFlags();
+    if ((flags & PROCESS_STAT_FLAG) != 0) {
+      HostStatHelper.refreshProcess(stats);
+    } else if ((flags & SYSTEM_STAT_FLAG) != 0) {
+      HostStatHelper.refreshSystem(stats);
+    } else {
+      throw new RuntimeException(LocalizedStrings.HostStatHelper_UNEXPECTED_OS_STATS_FLAGS_0.toLocalizedString(Integer.valueOf(flags)));
+    }
+  }
+  
+  /**
+   * Creates and returns a {@link Statistics} with
+   * the given pid and name. The resource's stats will contain a snapshot
+   * of the current statistic values for the specified process.
+   */
+  public static Statistics newProcess(OsStatisticsFactory f, long pid, String name) {
+    Statistics stats;
+    switch (osCode) {
+    case SOLARIS_CODE:
+      stats = f.createOsStatistics(SolarisProcessStats.getType(),
+                                   name, pid, PROCESS_STAT_FLAG);
+      break;
+    case LINUX_CODE:
+      stats = f.createOsStatistics(LinuxProcessStats.getType(),
+                                   name, pid, PROCESS_STAT_FLAG);
+      break;
+    case OSX_CODE:
+        stats = f.createOsStatistics(OSXProcessStats.getType(),
+                                     name, pid, PROCESS_STAT_FLAG);
+        break;
+    case WINDOWS_CODE:
+      stats = f.createOsStatistics(WindowsProcessStats.getType(),
+                                   name, pid, PROCESS_STAT_FLAG);
+      break;
+    default:
+      throw new InternalGemFireException(LocalizedStrings.HostStatHelper_UNHANDLED_OSCODE_0_HOSTSTATHELPERNEWPROCESS.toLocalizedString(Integer.valueOf(osCode)));
+    }
+    // Note we don't call refreshProcess since we only want the manager to do that
+    return stats;
+  }
+
+  /**
+   * Creates a new <code>ProcessStats</code> instance that wraps the
+   * given <code>Statistics</code>.
+   *
+   * @see #newProcess
+   * @since GemFire 3.5
+   */
+  static ProcessStats newProcessStats(Statistics stats) {
+    switch (osCode) {
+    case SOLARIS_CODE:
+      return SolarisProcessStats.createProcessStats(stats);
+
+    case LINUX_CODE:
+      return LinuxProcessStats.createProcessStats(stats);
+
+    case WINDOWS_CODE:
+      return WindowsProcessStats.createProcessStats(stats);
+
+    case OSX_CODE:
+        return OSXProcessStats.createProcessStats(stats);
+        
+    default:
+      throw new InternalGemFireException(LocalizedStrings.HostStatHelper_UNHANDLED_OSCODE_0_HOSTSTATHELPERNEWPROCESSSTATS.toLocalizedString(Integer.valueOf(osCode)));
+    }
+  }
+
+  /**
+   * Creates and returns a {@link Statistics} with the current
+   * machine's stats. The resource's stats will contain a snapshot
+   * of the current statistic values for the local machine.
+   */
+  static void newSystem(OsStatisticsFactory f) {
+    Statistics stats;
+    switch (osCode) {
+    case SOLARIS_CODE:
+      stats = f.createOsStatistics(SolarisSystemStats.getType(),
+                                   getHostSystemName(),
+                                   getHostSystemId(),
+                                   SYSTEM_STAT_FLAG);
+      break;
+    case LINUX_CODE:
+      stats = f.createOsStatistics(LinuxSystemStats.getType(),
+                                   getHostSystemName(),
+                                   getHostSystemId(),
+                                   SYSTEM_STAT_FLAG);
+      break;
+    case WINDOWS_CODE:
+      stats = f.createOsStatistics(WindowsSystemStats.getType(),
+                                   getHostSystemName(),
+                                   getHostSystemId(),
+                                   SYSTEM_STAT_FLAG);
+      break;
+    case OSX_CODE:
+      stats = f.createOsStatistics(OSXSystemStats.getType(),
+                                     getHostSystemName(),
+                                     getHostSystemId(),
+                                     SYSTEM_STAT_FLAG);
+      break;
+    default:
+      throw new InternalGemFireException(LocalizedStrings.HostStatHelper_UNHANDLED_OSCODE_0_HOSTSTATHELPERNEWSYSTEM.toLocalizedString(Integer.valueOf(osCode)));
+    }
+    if (stats instanceof LocalStatisticsImpl) {
+      refreshSystem((LocalStatisticsImpl)stats);
+    } // otherwise its a Dummy implementation so do nothing
+  }
+
+  /**
+   * @return this machine's fully qualified hostname 
+   *         or "unknownHostName" if one cannot be found.
+   */
+  private static String getHostSystemName() {
+    String hostname = "unknownHostName";
+    try {
+      InetAddress addr = SocketCreator.getLocalHost();
+      hostname = addr.getCanonicalHostName();
+    } catch (UnknownHostException uhe) {
+    }
+    return hostname;
+  }
+  
+  /** 
+   * Generate a systemid based off of the ip address of the host.
+   * This duplicates the common implementation of 
+   * <code>long gethostid(void) </code>.
+   * Punt on the ipv6 case and just use the same algorithm.
+   * @return a psuedo unique id based on the ip address
+   */
+  private static long getHostSystemId() {
+    long id = 0L;
+    try {
+      InetAddress host = SocketCreator.getLocalHost();
+      byte[] addr = host.getAddress();
+      id = (addr[1] & 0xFFL) << 24 |  
+           (addr[0] & 0xFFL) << 16 |  
+           (addr[3] & 0xFFL) << 8  |  
+           (addr[2] & 0xFFL) << 0;
+    } catch (UnknownHostException uhe) {
+    }
+    return id;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/866bacec/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/HostStatSampler.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/HostStatSampler.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/HostStatSampler.java
new file mode 100644
index 0000000..d414d2c
--- /dev/null
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/HostStatSampler.java
@@ -0,0 +1,549 @@
+/*
+ * 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.statistics;
+
+import com.gemstone.gemfire.CancelCriterion;
+import com.gemstone.gemfire.CancelException;
+import com.gemstone.gemfire.Statistics;
+import com.gemstone.gemfire.SystemFailure;
+import com.gemstone.gemfire.distributed.internal.DistributionConfig;
+import com.gemstone.gemfire.internal.NanoTimer;
+import com.gemstone.gemfire.internal.SocketCreator;
+import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
+import com.gemstone.gemfire.internal.logging.LogService;
+import com.gemstone.gemfire.internal.logging.LoggingThreadGroup;
+import com.gemstone.gemfire.internal.logging.log4j.LocalizedMessage;
+import com.gemstone.gemfire.internal.logging.log4j.LogMarker;
+import com.gemstone.gemfire.internal.statistics.platform.OsStatisticsFactory;
+import com.gemstone.gemfire.internal.util.concurrent.StoppableCountDownLatch;
+import org.apache.logging.log4j.Logger;
+
+import java.io.File;
+import java.net.UnknownHostException;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * HostStatSampler implements a thread which will monitor, sample, and archive
+ * statistics. It only has the common functionality that any sampler needs.
+
+ */
+public abstract class HostStatSampler 
+    implements Runnable, StatisticsSampler, StatArchiveHandlerConfig {
+
+  private static final Logger logger = LogService.getLogger();
+
+  public static final String TEST_FILE_SIZE_LIMIT_IN_KB_PROPERTY = DistributionConfig.GEMFIRE_PREFIX + "stats.test.fileSizeLimitInKB";
+  public static final String OS_STATS_DISABLED_PROPERTY = "osStatsDisabled";
+
+  protected static final String INITIALIZATION_TIMEOUT_PROPERTY = DistributionConfig.GEMFIRE_PREFIX + "statSamplerInitializationTimeout";
+  protected static final int INITIALIZATION_TIMEOUT_DEFAULT = 30000;
+  protected static final long INITIALIZATION_TIMEOUT_MILLIS = 
+      Long.getLong(INITIALIZATION_TIMEOUT_PROPERTY, INITIALIZATION_TIMEOUT_DEFAULT);
+  
+  /** 
+   * Used to check if the sampler thread wake-up is delayed, and log a warning if it is delayed by longer than 
+   * the amount of milliseconds specified by this property. The value of 0 disables the check. 
+   */
+  private static final long STAT_SAMPLER_DELAY_THRESHOLD = Long.getLong(DistributionConfig.GEMFIRE_PREFIX + "statSamplerDelayThreshold", 3000);
+  private static final long STAT_SAMPLER_DELAY_THRESHOLD_NANOS = NanoTimer.millisToNanos(STAT_SAMPLER_DELAY_THRESHOLD);
+  
+  private static final int MIN_MS_SLEEP = 1;
+  
+  private static final int WAIT_FOR_SLEEP_INTERVAL = 10;
+  
+  private static Thread statThread = null;
+
+  private volatile boolean stopRequested = false;
+  
+  private final boolean osStatsDisabled = Boolean.getBoolean(OS_STATS_DISABLED_PROPERTY);
+  private final boolean fileSizeLimitInKB;
+  private final StatSamplerStats samplerStats;
+  
+  private VMStatsContract vmStats;
+  private SampleCollector sampleCollector;
+
+  /**
+   * Used to signal thread that are waiting for the stat sampler to be initialized.
+   */
+  private final StoppableCountDownLatch statSamplerInitializedLatch;
+
+  private final CancelCriterion stopper;
+
+  private final CallbackSampler callbackSampler;
+  
+  protected HostStatSampler(CancelCriterion stopper, 
+                            StatSamplerStats samplerStats) {
+    this.stopper = stopper;
+    this.statSamplerInitializedLatch = new StoppableCountDownLatch(this.stopper, 1);
+    this.samplerStats = samplerStats;
+    this.fileSizeLimitInKB = Boolean.getBoolean(TEST_FILE_SIZE_LIMIT_IN_KB_PROPERTY);
+    this.callbackSampler = new CallbackSampler(stopper, samplerStats);
+  }
+  
+  public final StatSamplerStats getStatSamplerStats() {
+    return this.samplerStats;
+  }
+  
+  /**
+   * Returns the number of times a statistics resource has been add or deleted.
+   */
+  @Override
+  public final int getStatisticsModCount() {
+    return getStatisticsManager().getStatListModCount();
+  }
+
+  /**
+   * Returns an array of all the current statistic resource instances.
+   */
+  @Override
+  public final Statistics[] getStatistics() {
+    return getStatisticsManager().getStatistics();
+  }
+
+  /**
+   * Returns a unique id for the sampler's system.
+   */
+  @Override
+  public final long getSystemId() {
+    return getStatisticsManager().getId();
+  }
+
+  /**
+   * Returns the time this sampler's system was started.
+   */
+  @Override
+  public final long getSystemStartTime() {
+    return getStatisticsManager().getStartTime();
+  }
+
+  /**
+   * Returns the path to this sampler's system directory; if it has one.
+   */
+  @Override
+  public final String getSystemDirectoryPath() {
+    try {
+      return SocketCreator.getHostName(SocketCreator.getLocalHost());
+    } catch (UnknownHostException ignore) {
+      return "";
+    }
+  }
+
+  @Override
+  public boolean waitForSample(long timeout) throws InterruptedException {
+    final long endTime = System.currentTimeMillis() + timeout;
+    final int startSampleCount = this.samplerStats.getSampleCount();
+    while (System.currentTimeMillis() < endTime && 
+        this.samplerStats.getSampleCount() <= startSampleCount) {
+      Thread.sleep(WAIT_FOR_SLEEP_INTERVAL);
+    }
+    return this.samplerStats.getSampleCount() > startSampleCount;
+  }
+
+  @Override
+  public SampleCollector waitForSampleCollector(long timeout) throws InterruptedException {
+    final long endTime = System.currentTimeMillis() + timeout;
+    while (System.currentTimeMillis() < endTime && 
+        this.sampleCollector == null || !this.sampleCollector.isInitialized()) {
+      Thread.sleep(WAIT_FOR_SLEEP_INTERVAL);
+    }
+    return this.sampleCollector;
+  }
+  
+  /**
+   * This service's main loop
+   */
+  @Override
+  public final void run() {
+    NanoTimer timer = new NanoTimer();
+
+    final boolean isDebugEnabled_STATISTICS = logger.isTraceEnabled(LogMarker.STATISTICS);
+    if (isDebugEnabled_STATISTICS) {
+      logger.trace(LogMarker.STATISTICS, "HostStatSampler started");
+    }
+    boolean latchCountedDown = false;
+    try {
+      initSpecialStats();
+      
+      this.sampleCollector = new SampleCollector(this);
+      this.sampleCollector.initialize(this, NanoTimer.getTime());
+      
+      this.statSamplerInitializedLatch.countDown();
+      latchCountedDown = true;
+
+      timer.reset();
+      // subtract getNanoRate from lastTS to force a quick initial sample
+      long nanosLastTimeStamp = timer.getLastResetTime() - getNanoRate();
+      while (!stopRequested()) {
+        SystemFailure.checkFailure();
+        if (Thread.currentThread().isInterrupted()) {
+          break;
+        }
+        final long nanosBeforeSleep = timer.getLastResetTime();
+        final long nanosToDelay = nanosLastTimeStamp + getNanoRate();
+        delay(timer, nanosToDelay);
+        nanosLastTimeStamp = timer.getLastResetTime();
+        if (!stopRequested() && isSamplingEnabled()) {
+          final long nanosTimeStamp = timer.getLastResetTime();
+          final long nanosElapsedSleeping = nanosTimeStamp - nanosBeforeSleep;
+          checkElapsedSleepTime(nanosElapsedSleeping);
+          if (stopRequested()) break;
+          sampleSpecialStats(false);
+          if (stopRequested()) break;
+          checkListeners();
+          if (stopRequested()) break;
+          
+          this.sampleCollector.sample(nanosTimeStamp);
+          
+          final long nanosSpentWorking = timer.reset();
+          accountForTimeSpentWorking(nanosSpentWorking, nanosElapsedSleeping);
+        } else if (!stopRequested() && !isSamplingEnabled()) {
+          sampleSpecialStats(true); // fixes bug 42527
+        }
+      }
+    } 
+    catch (InterruptedException ex) {
+      // Silently exit
+    }
+    catch (CancelException ex) {
+      // Silently exit
+    }
+    catch (RuntimeException ex) {
+      logger.fatal(LogMarker.STATISTICS, ex.getMessage(), ex);
+      throw ex;
+    } 
+    catch (VirtualMachineError err) {
+      SystemFailure.initiateFailure(err);
+      // If this ever returns, rethrow the error.  We're poisoned
+      // now, so don't let this thread continue.
+      throw err;
+    }
+    catch (Error ex) {
+      // Whenever you catch Error or Throwable, you must also
+      // catch VirtualMachineError (see above).  However, there is
+      // _still_ a possibility that you are dealing with a cascading
+      // error condition, so you also need to check to see if the JVM
+      // is still usable:
+      SystemFailure.checkFailure();
+      logger.fatal(LogMarker.STATISTICS, ex.getMessage(), ex);
+      throw ex;
+    } finally {
+      try {
+      closeSpecialStats();
+      if (this.sampleCollector != null) {
+        this.sampleCollector.close();
+      }
+      } finally {
+        if (!latchCountedDown) {
+          // Make sure the latch gets counted down since
+          // other threads wait for this to indicate that 
+          // the sampler is initialized.
+          this.statSamplerInitializedLatch.countDown();
+        }
+      }
+      if (isDebugEnabled_STATISTICS) {
+        logger.trace(LogMarker.STATISTICS, "HostStatSampler stopped");
+      }
+    }
+  }
+
+  /**
+   * Starts the main thread for this service.
+   * @throws IllegalStateException if an instance of the {@link #statThread} is still running from a previous DistributedSystem.
+   */
+  public final void start() {
+    synchronized(HostStatSampler.class) { 
+      if (statThread != null) {
+        try {
+          int msToWait = getSampleRate() + 100;
+          statThread.join(msToWait);
+        } catch (InterruptedException ex) {
+          Thread.currentThread().interrupt();
+        } 
+        if (statThread.isAlive()) {
+          throw new IllegalStateException(LocalizedStrings.HostStatSampler_STATISTICS_SAMPLING_THREAD_IS_ALREADY_RUNNING_INDICATING_AN_INCOMPLETE_SHUTDOWN_OF_A_PREVIOUS_CACHE.toLocalizedString());
+        }
+      }  
+      ThreadGroup group = 
+        LoggingThreadGroup.createThreadGroup("StatSampler Threads");
+
+      this.callbackSampler.start(getStatisticsManager(), group, getSampleRate(), TimeUnit.MILLISECONDS);
+      statThread = new Thread(group, this);
+      statThread.setName(statThread.getName() + " StatSampler");
+      statThread.setPriority(Thread.MAX_PRIORITY);
+      statThread.setDaemon(true);
+      statThread.start();
+      // fix #46310 (race between management and sampler init) by waiting for init here
+      try {
+        waitForInitialization(INITIALIZATION_TIMEOUT_MILLIS);
+      } catch (InterruptedException e) {
+        Thread.currentThread().interrupt();
+      }
+    }
+  }
+  
+  /**
+   * Tell this service's main thread to terminate.
+   */
+  public final void stop() {
+    stop(true);
+  }
+  private final void stop(boolean interruptIfAlive) {
+    synchronized (HostStatSampler.class) {
+      this.callbackSampler.stop();
+      if ( statThread == null) {
+        return; 
+      }
+
+      this.stopRequested = true;
+      synchronized (this) {
+        this.notifyAll();
+      }
+      try {
+        statThread.join(5000);
+      } catch (InterruptedException ignore) {
+        //It is important that we shutdown so we'll continue trying for another 2 seconds
+        try {
+          statThread.join(2000);
+        } catch (InterruptedException ex) {
+        } finally {
+          Thread.currentThread().interrupt();
+        }
+      } finally {
+        if ( statThread.isAlive() ) {
+          if (interruptIfAlive) {
+            // It is still alive so interrupt the thread
+            statThread.interrupt();
+            stop(false);
+          } else {
+            logger.warn(LogMarker.STATISTICS, LocalizedMessage.create(LocalizedStrings.HostStatSampler_HOSTSTATSAMPLER_THREAD_COULD_NOT_BE_STOPPED));
+          }
+        } else {
+          this.stopRequested = false;
+          statThread = null;
+        }
+      }
+    }
+  }
+  
+  public final boolean isAlive() {
+    synchronized (HostStatSampler.class) {
+      return statThread != null && statThread.isAlive();
+    }
+  }
+
+  /**
+   * Waits for the special statistics to be initialized. For tests, please
+   * use {@link #waitForInitialization(long)} instead.
+   *
+   * @see #initSpecialStats
+   * @since GemFire 3.5
+   */
+  public final void waitForInitialization() throws InterruptedException {
+    this.statSamplerInitializedLatch.await();
+  }
+  
+  /**
+   * Waits for the special statistics to be initialized. This overridden
+   * version of {@link #waitForInitialization()} should always be used
+   * within tests.
+   *
+   * @see #initSpecialStats
+   * @since GemFire 7.0
+   */
+  public final boolean waitForInitialization(long ms) throws InterruptedException {
+    return this.statSamplerInitializedLatch.await(ms);
+  }
+  
+  public final void changeArchive(File newFile) {
+    this.sampleCollector.changeArchive(newFile, NanoTimer.getTime());
+  }
+  
+  /**
+   * Returns the <code>VMStatsContract</code> for this VM.
+   *
+   * @since GemFire 3.5
+   */
+  public final VMStatsContract getVMStats() {
+    return this.vmStats;
+  }
+
+  @Override
+  public String toString() {
+    final StringBuilder sb = new StringBuilder(getClass().getName());
+    sb.append("@").append(System.identityHashCode(this));
+    return sb.toString();
+  }
+
+  protected abstract void checkListeners();
+
+  /**
+   * Gets the sample rate in milliseconds
+   */
+  protected abstract int getSampleRate();
+  
+  /**
+   * Returns true if sampling is enabled.
+   */
+  public abstract boolean isSamplingEnabled();
+  
+  /**
+   * Returns the statistics manager using this sampler.
+   */
+  protected abstract StatisticsManager getStatisticsManager();
+
+  protected OsStatisticsFactory getOsStatisticsFactory() {
+    return null;
+  }
+  
+  protected void initProcessStats(long id) {
+    // do nothing by default
+  }
+  
+  protected void sampleProcessStats(boolean prepareOnly) {
+    // do nothing by default
+  }
+  
+  protected void closeProcessStats() {
+    // do nothing by default
+  }
+
+  protected long getSpecialStatsId() {
+    return getStatisticsManager().getId();
+  }
+  
+  protected final boolean fileSizeLimitInKB() {
+    return this.fileSizeLimitInKB;
+  }
+  
+  protected final boolean osStatsDisabled() {
+    return this.osStatsDisabled;
+  }
+  
+  protected final boolean stopRequested() {
+    return stopper.isCancelInProgress() || this.stopRequested;
+  }
+
+  public final SampleCollector getSampleCollector() {
+    return this.sampleCollector;
+  }
+  
+  /**
+   * Initialize any special sampler stats
+   */
+  private synchronized void initSpecialStats() {
+    // add a vm resource
+    long id = getSpecialStatsId();
+    this.vmStats = VMStatsContractFactory.create(getStatisticsManager(), id);
+    initProcessStats(id);
+  }
+
+  /**
+   * Closes down anything initialied by initSpecialStats.
+   */
+  private synchronized void closeSpecialStats() {
+    if (this.vmStats != null) {
+      this.vmStats.close();
+    }
+    closeProcessStats();
+  }
+  
+  /**
+   * Called when this sampler has spent some time working and wants
+   * it to be accounted for.
+   */
+  private void accountForTimeSpentWorking(long nanosSpentWorking, 
+                                          long nanosSpentSleeping) {
+    this.samplerStats.tookSample(
+        nanosSpentWorking, getStatisticsManager().getStatisticsCount(), nanosSpentSleeping);
+  }
+  
+  /**
+   * @param timer a NanoTimer used to compute the elapsed delay
+   * @param nanosToDelay the timestamp to delay until it is the current time
+   */
+  private void delay(NanoTimer timer, final long nanosToDelay) throws InterruptedException {
+    timer.reset();
+    long now = timer.getLastResetTime();
+    long remainingNanos = nanosToDelay - now;
+    if (remainingNanos <= 0) {
+      remainingNanos = NanoTimer.millisToNanos(MIN_MS_SLEEP);
+    }
+    while (remainingNanos > 0 && !stopRequested()) {
+      long ms = NanoTimer.nanosToMillis(remainingNanos);
+      if (ms <= 0) {
+        Thread.yield();
+      } else {
+        if (ms > MIN_MS_SLEEP) {
+          ms -= MIN_MS_SLEEP;
+        }
+        synchronized (this) {
+          if (stopRequested()) {
+            // check stopRequested inside the sync to prevent a race in which the wait misses the stopper's notify.
+            return;
+          }
+          this.wait(ms); // spurious wakeup ok
+        }
+      }
+      timer.reset();
+      now = timer.getLastResetTime();
+      remainingNanos = nanosToDelay - now;
+    }
+  }
+  
+  private long getNanoRate() {
+    return NanoTimer.millisToNanos(getSampleRate());
+  }
+  
+  /**
+   * Collect samples of any operating system statistics
+   * 
+   * @param prepareOnly
+   *          set to true if you only want to call prepareForSample
+   */
+  private void sampleSpecialStats(boolean prepareOnly) {
+    List<Statistics> statsList = getStatisticsManager().getStatsList();
+    for (Statistics s : statsList) {
+      if (stopRequested()) return;
+      if (s instanceof StatisticsImpl) {
+        ((StatisticsImpl)s).prepareForSample();
+      }
+    }
+
+    if (!prepareOnly && this.vmStats != null) {
+      if (stopRequested()) return;
+      this.vmStats.refresh();
+    }
+    sampleProcessStats(prepareOnly);
+  }
+
+  /**
+   * Check the elapsed sleep time upon wakeup, and log a warning if it is longer than the delay
+   * threshold.
+   * 
+   * @param elapsedSleepTime duration of sleep in nanoseconds
+   */
+  private void checkElapsedSleepTime(long elapsedSleepTime) {
+    if (STAT_SAMPLER_DELAY_THRESHOLD > 0) {
+      final long wakeupDelay = elapsedSleepTime - getNanoRate();
+      if (wakeupDelay > STAT_SAMPLER_DELAY_THRESHOLD_NANOS) {
+        this.samplerStats.incJvmPauses();
+        logger.warn(LogMarker.STATISTICS, LocalizedMessage.create(LocalizedStrings.HostStatSampler_STATISTICS_SAMPLING_THREAD_DETECTED_A_WAKEUP_DELAY_OF_0_MS_INDICATING_A_POSSIBLE_RESOURCE_ISSUE, NanoTimer.nanosToMillis(wakeupDelay)));
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/866bacec/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/IgnoreResourceException.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/IgnoreResourceException.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/IgnoreResourceException.java
index 2abf4b8..4e6e562 100755
--- a/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/IgnoreResourceException.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/IgnoreResourceException.java
@@ -22,7 +22,7 @@ import com.gemstone.gemfire.GemFireCheckedException;
  * Indicates that a Statistics resource instance with a null StatisticsType
  * should be ignored by the statistics sampler.
  * <p/>
- * Extracted from {@link com.gemstone.gemfire.internal.StatArchiveWriter}.
+ * Extracted from {@link StatArchiveWriter}.
  * 
  * @since GemFire 7.0
  */

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/866bacec/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/InternalStatisticsDisabledException.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/InternalStatisticsDisabledException.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/InternalStatisticsDisabledException.java
new file mode 100644
index 0000000..bba2b49
--- /dev/null
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/InternalStatisticsDisabledException.java
@@ -0,0 +1,69 @@
+/*
+ * 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.statistics;
+
+import com.gemstone.gemfire.GemFireCheckedException;
+
+/**
+ * Thrown if statistics are requested when statistics are disabled on the
+ * region.
+ *
+ *
+ *
+ * @see com.gemstone.gemfire.cache.AttributesFactory#setStatisticsEnabled(boolean)
+ * @see com.gemstone.gemfire.cache.RegionAttributes#getStatisticsEnabled
+ * @see com.gemstone.gemfire.cache.Region#getStatistics
+ * @see com.gemstone.gemfire.cache.Region.Entry#getStatistics
+ * @since GemFire 3.0
+ */
+public class InternalStatisticsDisabledException extends GemFireCheckedException {
+private static final long serialVersionUID = 4146181546364258311L;
+  
+  /**
+   * Creates a new instance of <code>StatisticsDisabledException</code> without detail message.
+   */
+  public InternalStatisticsDisabledException() {
+  }
+  
+  
+  /**
+   * Constructs an instance of <code>StatisticsDisabledException</code> with the specified detail message.
+   * @param msg the detail message
+   */
+  public InternalStatisticsDisabledException(String msg) {
+    super(msg);
+  }
+  
+  /**
+   * Constructs an instance of <code>StatisticsDisabledException</code> with the specified detail message
+   * and cause.
+   * @param msg the detail message
+   * @param cause the causal Throwable
+   */
+  public InternalStatisticsDisabledException(String msg, Throwable cause) {
+    super(msg, cause);
+  }
+  
+  /**
+   * Constructs an instance of <code>StatisticsDisabledException</code> with the specified cause.
+   * @param cause the causal Throwable
+   */
+  public InternalStatisticsDisabledException(Throwable cause) {
+    super(cause);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/866bacec/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/LocalStatListener.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/LocalStatListener.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/LocalStatListener.java
new file mode 100644
index 0000000..0942e78
--- /dev/null
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/LocalStatListener.java
@@ -0,0 +1,40 @@
+/*
+ * 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.statistics;
+
+/**
+ * Implement this interface to receive call back when a stat value has changed.
+ * The listener has to be registered with statSampler. This can be done in the
+ * following manner:
+ * <code>
+ * InternalDistributedSystem internalSystem = (InternalDistributedSystem)cache
+ *                                                      .getDistributedSystem();
+ * final GemFireStatSampler sampler = internalSystem.getStatSampler();          
+ * sampler.addLocalStatListener(l, stats, statName);
+ * </code>
+ * 
+ *
+ */
+public interface LocalStatListener {
+  /**
+   * Invoked when the value of a statistic has changed
+   *
+   * @param value
+   *        The new value of the statistic 
+   */
+  public void statValueChanged( double value );
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/866bacec/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/LocalStatisticsFactory.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/LocalStatisticsFactory.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/LocalStatisticsFactory.java
new file mode 100644
index 0000000..489894b
--- /dev/null
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/LocalStatisticsFactory.java
@@ -0,0 +1,103 @@
+/*
+ * 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.statistics;
+
+import org.apache.logging.log4j.Logger;
+
+import com.gemstone.gemfire.CancelCriterion;
+import com.gemstone.gemfire.Statistics;
+import com.gemstone.gemfire.StatisticsFactory;
+import com.gemstone.gemfire.StatisticsType;
+import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
+import com.gemstone.gemfire.internal.logging.LogService;
+import com.gemstone.gemfire.internal.logging.log4j.LocalizedMessage;
+import com.gemstone.gemfire.internal.logging.log4j.LogMarker;
+import com.gemstone.gemfire.internal.statistics.AbstractStatisticsFactory;
+import com.gemstone.gemfire.internal.statistics.DummyStatisticsImpl;
+import com.gemstone.gemfire.internal.statistics.SimpleStatSampler;
+import com.gemstone.gemfire.internal.statistics.StatisticsManager;
+
+/**
+ * A standalone implementation of {@link StatisticsFactory}.
+ * It can be used in contexts that do not have the GemFire product
+ * or in vm's that do not have a distributed system nor a gemfire connection.
+ *
+ */
+public class LocalStatisticsFactory extends AbstractStatisticsFactory
+    implements StatisticsFactory, StatisticsManager {
+
+  private static final Logger logger = LogService.getLogger();
+  
+  public static final String STATS_DISABLE_NAME_PROPERTY = "stats.disable";
+
+  private final SimpleStatSampler sampler;
+  private final boolean statsDisabled;
+
+  public LocalStatisticsFactory(CancelCriterion stopper) {
+    super(initId(), initName(), initStartTime());
+    
+    this.statsDisabled = Boolean.getBoolean(STATS_DISABLE_NAME_PROPERTY);
+    if (statsDisabled) {
+      this.sampler = null;
+      logger.info(LogMarker.STATISTICS, LocalizedMessage.create(LocalizedStrings.LocalStatisticsFactory_STATISTIC_COLLECTION_IS_DISABLED_USE_DSTATSDISABLEFALSE_TO_TURN_ON_STATISTICS));
+    } else if (stopper != null) {
+      this.sampler = new SimpleStatSampler(stopper, this);
+      this.sampler.start();
+    } else {
+      this.sampler = null;
+    }
+  }
+  
+  protected static long initId() {
+    return Thread.currentThread().hashCode();
+  }
+  
+  protected static String initName() {
+    return System.getProperty("stats.name", Thread.currentThread().getName());
+  }
+  
+  protected static long initStartTime() {
+    return System.currentTimeMillis();
+  }
+  
+ protected SimpleStatSampler getStatSampler() {
+    return this.sampler;
+  }
+
+  @Override
+  public void close() {
+    if (this.sampler != null) {
+      this.sampler.stop();
+    }
+  }
+  
+  @Override
+  protected Statistics createOsStatistics(StatisticsType type, String textId, long numericId, int osStatFlags) {
+    if (this.statsDisabled) {
+      return new DummyStatisticsImpl(type, textId, numericId);
+    }
+    return super.createOsStatistics(type, textId, numericId, osStatFlags);
+  }
+
+  @Override
+  public Statistics createAtomicStatistics(StatisticsType type, String textId, long numericId) {
+    if (this.statsDisabled) {
+      return new DummyStatisticsImpl(type, textId, numericId);
+    }
+    return super.createAtomicStatistics(type, textId, numericId);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/866bacec/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/LocalStatisticsImpl.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/LocalStatisticsImpl.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/LocalStatisticsImpl.java
new file mode 100644
index 0000000..4c8733a
--- /dev/null
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/LocalStatisticsImpl.java
@@ -0,0 +1,272 @@
+/*
+ * 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.statistics;
+
+import com.gemstone.gemfire.*;
+import com.gemstone.gemfire.internal.OSProcess;
+import com.gemstone.gemfire.internal.statistics.StatisticsImpl;
+import com.gemstone.gemfire.internal.statistics.StatisticsManager;
+import com.gemstone.gemfire.internal.statistics.StatisticsTypeImpl;
+//import com.gemstone.gemfire.util.IntArray;
+//import com.gemstone.gemfire.util.LongArray;
+
+/**
+ * An implementation of {@link Statistics} that stores its statistics
+ * in local java memory.
+ *
+ * @see <A href="package-summary.html#statistics">Package introduction</A>
+ *
+ *
+ * @since GemFire 3.0
+ *
+ */
+public class LocalStatisticsImpl extends StatisticsImpl {
+
+  /** In JOM Statistics, the values of the int statistics */
+  private final int[] intStorage;
+
+  /** In JOM Statistics, the values of the long statistics */
+  private final long[] longStorage;
+
+  /** In JOM Statistics, the values of the double statistics */
+  private final double[] doubleStorage;
+
+  /** An array containing the JOM object used to lock a int statistic when
+   * it is incremented. */
+  private transient final Object[] intLocks;
+
+  /** An array containing the JOM object used to lock a long statistic when
+   * it is incremented. */
+  private transient final Object[] longLocks;
+
+  /** An array containing the JOM object used to lock a double statistic when
+   * it is incremented. */
+  private transient final Object[] doubleLocks;
+
+  /** The StatisticsFactory that created this instance */
+  private final StatisticsManager dSystem;
+  
+  ///////////////////////  Constructors  ///////////////////////
+
+  /**
+   * Creates a new statistics instance of the given type
+   *
+   * @param type
+   *        A description of the statistics
+   * @param textId
+   *        Text that identifies this statistic when it is monitored
+   * @param numericId
+   *        A number that displayed when this statistic is monitored
+   * @param uniqueId
+   *        A number that uniquely identifies this instance
+   * @param atomicIncrements
+   *        Are increment operations atomic?  If only one application
+   *        thread increments a statistic, then a <code>false</code>
+   *        value may yield better performance.
+   * @param osStatFlags
+   *        Non-zero if stats require system calls to collect them; for internal use only
+   * @param system
+   *        The distributed system that determines whether or not these
+   *        statistics are stored (and collected) in GemFire shared
+   *        memory or in the local VM
+   */
+  public LocalStatisticsImpl(StatisticsType type, String textId,
+                             long numericId,
+                             long uniqueId,
+                             boolean atomicIncrements,
+                             int osStatFlags,
+                             StatisticsManager system) {
+    super(type, calcTextId(system, textId), calcNumericId(system, numericId),
+          uniqueId, osStatFlags);
+
+    this.dSystem = system;
+
+    StatisticsTypeImpl realType = (StatisticsTypeImpl)type;
+    int intCount = realType.getIntStatCount();
+    int longCount = realType.getLongStatCount();
+    int doubleCount = realType.getDoubleStatCount();
+
+    if (intCount > 0) {
+      this.intStorage = new int[intCount];
+      if (atomicIncrements) {
+        this.intLocks = new Object[intCount];
+        for (int i = 0; i < intLocks.length; i++) {
+          intLocks[i] = new Object();
+        }
+      } else {
+        this.intLocks = null;
+      }
+    } else {
+      this.intStorage = null;
+      this.intLocks = null;
+    }
+
+    if (longCount > 0) {
+      this.longStorage = new long[longCount];
+      if (atomicIncrements) {
+        this.longLocks = new Object[longCount];
+        for (int i = 0; i < longLocks.length; i++) {
+          longLocks[i] = new Object();
+        }
+      } else {
+        this.longLocks = null;
+      }
+    } else {
+      this.longStorage = null;
+      this.longLocks = null;
+    }
+
+    if (doubleCount > 0) {
+      this.doubleStorage = new double[doubleCount];
+      if (atomicIncrements) {
+        this.doubleLocks = new Object[doubleCount];
+        for (int i = 0; i < doubleLocks.length; i++) {
+          doubleLocks[i] = new Object();
+        }
+      } else {
+        this.doubleLocks = null;
+      }
+    } else {
+      this.doubleStorage = null;
+      this.doubleLocks = null;
+    }
+  }
+
+  //////////////////////  Static Methods  //////////////////////
+
+  private static long calcNumericId(StatisticsManager system, long userValue) {
+    if (userValue != 0) {
+      return userValue;
+    } else {
+      long result = OSProcess.getId(); // fix for bug 30239
+      if (result == 0) {
+        if (system != null) {
+          result = system.getId();
+        }
+      }
+      return result;
+    }
+  }
+
+  private static String calcTextId(StatisticsManager system, String userValue) {
+    if (userValue != null && !userValue.equals("")) {
+      return userValue;
+    } else {
+      if (system != null) {
+        return system.getName();
+      } else {
+        return "";
+      }
+    }
+  }
+
+  //////////////////////  Instance Methods  //////////////////////
+
+  @Override
+  public final boolean isAtomic() {
+    return intLocks != null || longLocks != null || doubleLocks != null;
+  }
+
+  @Override
+  public void close() {
+    super.close();
+    if (this.dSystem != null) {
+      dSystem.destroyStatistics(this);
+    }
+  }
+
+  ////////////////////////  store() Methods  ///////////////////////
+
+  @Override
+  protected final void _setInt(int offset, int value) {
+    this.intStorage[offset] = value;
+  }
+
+  @Override
+  protected final void _setLong(int offset, long value) {
+    this.longStorage[offset] = value;
+  }
+
+  @Override
+  protected final void _setDouble(int offset, double value) {
+    this.doubleStorage[offset] = value;
+  }
+
+  ///////////////////////  get() Methods  ///////////////////////
+
+  @Override
+  protected final int _getInt(int offset) {
+    return this.intStorage[offset];
+  }
+
+  @Override
+  protected final long _getLong(int offset) {
+    return this.longStorage[offset];
+  }
+
+  @Override
+  protected final double _getDouble(int offset) {
+    return this.doubleStorage[offset];
+  }
+
+  ////////////////////////  inc() Methods  ////////////////////////
+
+  @Override
+  protected final void _incInt(int offset, int delta) {
+    if (this.intLocks != null) {
+      synchronized (this.intLocks[offset]) {
+        this.intStorage[offset] += delta;
+      }
+    } else {
+      this.intStorage[offset] += delta;
+    }
+  }
+
+  @Override
+  protected final void _incLong(int offset, long delta) {
+    if (this.longLocks != null) {
+      synchronized (this.longLocks[offset]) {
+        this.longStorage[offset] += delta;
+      }
+    } else {
+      this.longStorage[offset] += delta;
+    }
+  }
+
+  @Override
+  protected final void _incDouble(int offset, double delta) {
+    if (this.doubleLocks != null) {
+      synchronized (this.doubleLocks[offset]) {
+        this.doubleStorage[offset] += delta;
+      }
+    } else {
+      this.doubleStorage[offset] += delta;
+    }
+  }
+
+  /////////////////// internal package methods //////////////////
+
+  final int[] _getIntStorage() {
+    return this.intStorage;
+  }
+  final long[] _getLongStorage() {
+    return this.longStorage;
+  }
+  final double[] _getDoubleStorage() {
+    return this.doubleStorage;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/866bacec/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/ResourceInstance.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/ResourceInstance.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/ResourceInstance.java
index 0de95e2..6d63d3c 100755
--- a/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/ResourceInstance.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/ResourceInstance.java
@@ -24,7 +24,7 @@ import com.gemstone.gemfire.Statistics;
  * instances depending on the statistics type. The ResourceInstance holds
  * an array of the latest stat values.
  * <p/>
- * Extracted from {@link com.gemstone.gemfire.internal.StatArchiveWriter}.
+ * Extracted from {@link StatArchiveWriter}.
  * 
  * @since GemFire 7.0
  */

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/866bacec/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/ResourceType.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/ResourceType.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/ResourceType.java
index d401969..fcdc1a0 100755
--- a/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/ResourceType.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/ResourceType.java
@@ -24,7 +24,7 @@ import com.gemstone.gemfire.StatisticsType;
  * each ResourceInstance. The ResourceType holds an array of 
  * StatisticDescriptors for its StatisticsType.
  * <p/>
- * Extracted from {@link com.gemstone.gemfire.internal.StatArchiveWriter}.
+ * Extracted from {@link StatArchiveWriter}.
  *  
  * @since GemFire 7.0
  */

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/866bacec/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/SimpleStatSampler.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/SimpleStatSampler.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/SimpleStatSampler.java
new file mode 100644
index 0000000..599d42c
--- /dev/null
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/SimpleStatSampler.java
@@ -0,0 +1,112 @@
+/*
+ * 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.statistics;
+
+import java.io.File;
+
+import org.apache.logging.log4j.Logger;
+
+import com.gemstone.gemfire.CancelCriterion;
+import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
+import com.gemstone.gemfire.internal.logging.LogService;
+import com.gemstone.gemfire.internal.logging.log4j.LocalizedMessage;
+import com.gemstone.gemfire.internal.logging.log4j.LogMarker;
+
+/**
+ * SimpleStatSampler is a functional implementation of HostStatSampler
+ * that samples statistics stored in local java memory and does not
+ * require any native code or additional GemFire features.
+ * <p>
+ * The StatisticsManager may be implemented by LocalStatisticsFactory and does
+ * not require a GemFire connection.
+
+ */
+public class SimpleStatSampler extends HostStatSampler {
+
+  private static final Logger logger = LogService.getLogger();
+  
+  public static final String ARCHIVE_FILE_NAME_PROPERTY = "stats.archive-file";
+  public static final String FILE_SIZE_LIMIT_PROPERTY = "stats.file-size-limit";
+  public static final String DISK_SPACE_LIMIT_PROPERTY = "stats.disk-space-limit";
+  public static final String SAMPLE_RATE_PROPERTY = "stats.sample-rate";
+  
+  public static final String DEFAULT_ARCHIVE_FILE_NAME = "stats.gfs";
+  public static final long DEFAULT_FILE_SIZE_LIMIT = 0;
+  public static final long DEFAULT_DISK_SPACE_LIMIT = 0;
+  public static final int DEFAULT_SAMPLE_RATE = 1000;
+  
+  private final File archiveFileName = new File(System.getProperty(ARCHIVE_FILE_NAME_PROPERTY, DEFAULT_ARCHIVE_FILE_NAME));
+  private final long archiveFileSizeLimit = Long.getLong(FILE_SIZE_LIMIT_PROPERTY, DEFAULT_FILE_SIZE_LIMIT).longValue() * (1024*1024);
+  private final long archiveDiskSpaceLimit = Long.getLong(DISK_SPACE_LIMIT_PROPERTY, DEFAULT_DISK_SPACE_LIMIT).longValue() * (1024*1024);
+  private final int sampleRate = Integer.getInteger(SAMPLE_RATE_PROPERTY, DEFAULT_SAMPLE_RATE).intValue();
+
+  private final StatisticsManager sm;
+
+  public SimpleStatSampler(CancelCriterion stopper, StatisticsManager sm) {
+    super(stopper, new StatSamplerStats(sm, sm.getId()));
+    this.sm = sm;
+    logger.info(LogMarker.STATISTICS, LocalizedMessage.create(LocalizedStrings.SimpleStatSampler_STATSSAMPLERATE_0, getSampleRate()));
+  }
+
+  @Override
+  protected void checkListeners() {
+    // do nothing
+  }
+  
+  @Override
+  public File getArchiveFileName() {
+    return this.archiveFileName;
+  }
+  
+  @Override
+  public long getArchiveFileSizeLimit() {
+    if (fileSizeLimitInKB()) {
+      return this.archiveFileSizeLimit / 1024;
+    } else {
+      return this.archiveFileSizeLimit;
+    }
+  }
+  
+  @Override
+  public long getArchiveDiskSpaceLimit() {
+    if (fileSizeLimitInKB()) {
+      return this.archiveDiskSpaceLimit / 1024;
+    } else {
+      return this.archiveDiskSpaceLimit;
+    }
+  }
+  
+  @Override
+  public String getProductDescription() {
+    return "Unknown product";
+  }
+
+  @Override
+  protected StatisticsManager getStatisticsManager() {
+    return this.sm;
+  }
+  
+  @Override
+  protected int getSampleRate() {
+    return this.sampleRate;
+  }
+  
+  @Override
+  public boolean isSamplingEnabled() {
+    return true;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/866bacec/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/StatArchiveDescriptor.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/StatArchiveDescriptor.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/StatArchiveDescriptor.java
index 6d6624a..54d6af0 100755
--- a/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/StatArchiveDescriptor.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/statistics/StatArchiveDescriptor.java
@@ -18,11 +18,11 @@ package com.gemstone.gemfire.internal.statistics;
 
 /**
  * Descriptor containing all of the parameters required to construct a new
- * instance of a {@link com.gemstone.gemfire.internal.StatArchiveWriter}. 
+ * instance of a {@link StatArchiveWriter}.
  * This describes the statistics archive.
  * <p/>
  * This is a constructor parameter object for {@link 
- * com.gemstone.gemfire.internal.StatArchiveWriter}. 
+ * StatArchiveWriter}.
  * <p/>
  * {@link StatArchiveDescriptor.Builder} is used for constructing instances
  * instead of a constructor with many similar parameters (ie, multiple Strings


Mime
View raw message