/*
 * 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 org.apache.geode.internal.statistics;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import edu.umd.cs.findbugs.annotations.SuppressWarnings;
import org.apache.logging.log4j.Logger;

import org.apache.geode.GemFireException;
import org.apache.geode.StatisticDescriptor;
import org.apache.geode.Statistics;
import org.apache.geode.StatisticsType;
import org.apache.geode.annotations.internal.MakeNotStatic;
import org.apache.geode.internal.io.RollingFileHandler;
import org.apache.geode.internal.logging.log4j.LogMarker;
import org.apache.geode.logging.internal.log4j.api.LogService;

/**
 * Captures sample of statistics. The SampleCollector contains maps of StatisticsTypes to
 * ResourceTypes and Statistics instances to ResourceInstances, each of which contains the actual
 * stat values of the sample. The {@link #sample(long)} operation determines what stats have
 * changed, adds in new types and instances, and updates the sampled stat values.
 * <p/>
 * SampleHandlers are registered with the SampleCollector. The handlers are notified of any changes
 * to statistics.
 * <p/>
 * Extracted from StatArchiveWriter.
 *
 * @since GemFire 7.0
 */
public class SampleCollector {

  private static final Logger logger = LogService.getLogger();

  /**
   * Singleton instance of SampleCollector set during initialization. This field simply points to
   * the latest initialized instance.
   */
  @MakeNotStatic
  private static SampleCollector instance;

  /**
   * The stat sampler using this collector to capture samples of stats
   */
  private final StatisticsSampler sampler;

  /**
   * The handlers that are registered for notification of stat samples
   */
  private final SampleHandlers sampleHandlers = new SampleHandlers();

  /**
   * Map of StatisticsType to ResourceType. Contains all currently known statistics types.
   */
  private final Map<StatisticsType, ResourceType> resourceTypeMap =
      new HashMap<StatisticsType, ResourceType>();

  /**
   * Map of Statistics to ResourceInstance. Contains all currently known statistics resources.
   */
  private final Map<Statistics, ResourceInstance> resourceInstMap =
      new HashMap<Statistics, ResourceInstance>();

  /**
   * Incremented to use as unique identifier to construct new ResourceType
   */
  private int resourceTypeId = 0;

  /**
   * Incremented to use as unique identifier to construct new ResourceInstance
   */
  private int resourceInstId = 0;

  /**
   * The number of statistics resources that existed during the latest sample
   */
  private int statResourcesModCount;

  /**
   * The StatArchiveHandler which is created during initialization
   */
  private StatArchiveHandler statArchiveHandler;

  /**
   * The StatArchiveHandler which is created on demand
   */
  private StatMonitorHandler statMonitorHandler;

  /**
   * Constructs a new instance.
   *
   * @param sampler the stat sampler using this collector
   */
  public SampleCollector(StatisticsSampler sampler) {
    this.sampler = sampler;
    if (sampler.getStatisticsModCount() == 0) {
      this.statResourcesModCount = -1;
    } else {
      this.statResourcesModCount = 0;
    }
  }

  /**
   * Returns the {@link StatMonitorHandler}. If one does not currently exist it will be created.
   *
   * @return the StatMonitorHandler for adding monitors
   * @throws IllegalStateException if no SampleCollector has been created and initialized yet
   */
  static StatMonitorHandler getStatMonitorHandler() {
    // sync SampleCollector.class and then instance.sampleHandlers
    synchronized (SampleCollector.class) {
      if (instance == null) {
        throw new IllegalStateException("Statistics sampler is not available");
      }
      synchronized (instance.sampleHandlers) {
        StatMonitorHandler handler = instance.statMonitorHandler;
        if (handler == null) {
          handler = new StatMonitorHandler();
          instance.addSampleHandler(handler);
          instance.statMonitorHandler = handler;
        }
        return handler;
      }
    }
  }

  /**
   * Initializes this collector by creating a {@link StatArchiveHandler} and registering it as a
   * handler.
   *
   * @param config defines the configuration for the StatArchiveHandler
   * @param nanosTimeStamp the nanos time stamp to initialize stat archiver with
   * @param rollingFileHandler provides file rolling behavior
   */
  @SuppressWarnings(value = "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD",
      justification = "There is never more than one SampleCollector instance.")
  public void initialize(final StatArchiveHandlerConfig config, final long nanosTimeStamp,
      final RollingFileHandler rollingFileHandler) {
    synchronized (SampleCollector.class) {
      instance = this;
      synchronized (this.sampleHandlers) {
        StatArchiveHandler newStatArchiveHandler =
            new StatArchiveHandler(config, this, rollingFileHandler);
        this.statArchiveHandler = newStatArchiveHandler;
        addSampleHandler(newStatArchiveHandler);
        newStatArchiveHandler.initialize(nanosTimeStamp);
      }
    }
  }

  public boolean isInitialized() {
    synchronized (SampleCollector.class) {
      synchronized (this.sampleHandlers) {
        return instance == this;
      }
    }
  }

  /**
   * Adds a {@link SampleHandler} to this collector.
   *
   * @param handler the SampleHandler to add
   */
  public void addSampleHandler(SampleHandler handler) {
    this.sampleHandlers.addSampleHandler(handler);
  }

  /**
   * Removes a {@link SampleHandler} from this collector.
   *
   * @param handler the SampleHandler to remove
   */
  public void removeSampleHandler(SampleHandler handler) {
    this.sampleHandlers.removeSampleHandler(handler);
  }

  /**
   * Returns true if the specified SampleHandler is registered
   */
  public boolean containsSampleHandler(SampleHandler handler) {
    return this.sampleHandlers.contains(handler);
  }

  /**
   * Collect a sample of all statistics. Adds new statistics resources, removes destroyed statistics
   * resources, collects the latest stat values, and notifies SamplerHandlers of the sample.
   * <p/>
   * The timeStamp is an arbitrary nanoseconds time stamp only used for archiving to stats files.
   * The initial time in system milliseconds and the first NanoTimer timeStamp are both written to
   * the archive file. Thereafter only the NanoTimer timeStamp is written to the archive file for
   * each sample. The delta in nanos can be determined by comparing any nano timeStamp to the first
   * nano timeStamp written to the archive file. Adding this delta to the recorded initial time in
   * milliseconds provides the actual (non-arbitrary) time for each sample.
   *
   * @param nanosTimeStamp an arbitrary time stamp in nanoseconds for this sample
   */
  public void sample(long nanosTimeStamp) {
    final boolean isDebugEnabled_STATISTICS = logger.isTraceEnabled(LogMarker.STATISTICS_VERBOSE);
    if (isDebugEnabled_STATISTICS) {
      logger.trace(LogMarker.STATISTICS_VERBOSE, "SampleCollector#sample nanosTimeStamp={}",
          nanosTimeStamp);
    }
    List<MarkableSampleHandler> handlers = this.sampleHandlers.currentHandlers();
    if (isDebugEnabled_STATISTICS) {
      logger.trace(LogMarker.STATISTICS_VERBOSE, "SampleCollector#sample handlers={}", handlers);
    }
    sampleResources(handlers);

    List<ResourceInstance> updatedResources = new ArrayList<ResourceInstance>();
    for (ResourceInstance ri : this.resourceInstMap.values()) {
      StatisticDescriptor[] stats = ri.getResourceType().getStatisticDescriptors();
      if (ri.getStatistics().isClosed()) {
        continue;
      }

      // size updatedStats to same size as stats in case all stats changed
      int[] updatedStats = new int[stats.length];
      long[] statValues = ri.getPreviousStatValues();

      if (statValues == null) {
        statValues = new long[stats.length];
        for (int i = 0; i < stats.length; i++) {
          statValues[i] = ri.getRawStatValue(stats[i]);
          updatedStats[i] = i;
        }

      } else {
        statValues = Arrays.copyOf(statValues, statValues.length);
        int updatedStatsIdx = 0;
        for (int i = 0; i < stats.length; i++) {
          long value = ri.getRawStatValue(stats[i]);
          if (value != statValues[i]) {
            statValues[i] = value;
            updatedStats[updatedStatsIdx] = i;
            updatedStatsIdx++;
          }
        }
        // resize updatedStats to only contain the the stats which were updated
        updatedStats = Arrays.copyOf(updatedStats, updatedStatsIdx);
      }

      ri.setUpdatedStats(updatedStats);
      ri.setLatestStatValues(statValues);
      updatedResources.add(ri);
    }

    try {
      notifyAllHandlersOfSample(handlers, updatedResources, nanosTimeStamp);
    } catch (IllegalArgumentException e) {
      logger.warn(LogMarker.STATISTICS_MARKER,
          "Use of java.lang.System.nanoTime() resulted in a non-positive timestamp delta. Skipping notification of statistics sample.",
          e);
    }

    for (ResourceInstance ri : updatedResources) {
      ri.setPreviousStatValues(ri.getLatestStatValues());
    }
  }

  public void close() {
    // sync SampleCollector.class and then this.sampleHandlers
    synchronized (SampleCollector.class) {
      synchronized (this.sampleHandlers) {
        if (logger.isTraceEnabled(LogMarker.STATISTICS_VERBOSE)) {
          logger.trace(LogMarker.STATISTICS_VERBOSE, "SampleCollector#close");
        }
        try {
          StatArchiveHandler handler = this.statArchiveHandler;
          if (handler != null) {
            handler.close();
          }
        } catch (GemFireException ignore) {
          logger.warn(LogMarker.STATISTICS_MARKER, "Statistic archiver shutdown failed because: {}",
              ignore.getMessage());
        }
        StatMonitorHandler handler = this.statMonitorHandler;
        if (handler != null) {
          handler.close();
        }
      }
      if (instance == this) {
        instance = null;
      }
    }
  }

  public void changeArchive(File newFile, long nanosTimeStamp) {
    synchronized (this.sampleHandlers) {
      if (logger.isTraceEnabled(LogMarker.STATISTICS_VERBOSE)) {
        logger.trace(LogMarker.STATISTICS_VERBOSE,
            "SampleCollector#changeArchive newFile={}, nanosTimeStamp={}", newFile, nanosTimeStamp);
      }
      StatArchiveHandler handler = this.statArchiveHandler;
      if (handler != null) {
        handler.changeArchiveFile(newFile, nanosTimeStamp);
      }
    }
  }

  @Override
  public String toString() {
    final StringBuilder sb = new StringBuilder(getClass().getName());
    sb.append("@").append(System.identityHashCode(this)).append("{");
    sb.append("sampler=").append(this.sampler);
    sb.append(", statResourcesModCount=").append(this.statResourcesModCount);
    sb.append(", resourceTypeId=").append(this.resourceTypeId);
    sb.append(", resourceInstId=").append(this.resourceInstId);
    sb.append(", resourceTypeMap.size()=").append(this.resourceTypeMap.size());
    sb.append(", resourceInstMap.size()=").append(this.resourceInstMap.size());
    sb.append("}");
    return sb.toString();
  }

  /**
   * For testing only
   */
  StatArchiveHandler getStatArchiveHandler() {
    synchronized (this.sampleHandlers) {
      return this.statArchiveHandler;
    }
  }

  protected List<MarkableSampleHandler> currentHandlersForTesting() {
    return this.sampleHandlers.currentHandlers();
  }

  /**
   * Detect and archive any new resource additions or deletions
   */
  private void sampleResources(List<MarkableSampleHandler> handlers) {
    final boolean isDebugEnabled_STATISTICS = logger.isTraceEnabled(LogMarker.STATISTICS_VERBOSE);
    if (isDebugEnabled_STATISTICS) {
      logger.trace(LogMarker.STATISTICS_VERBOSE, "SampleCollector#sampleResources handlers={}",
          handlers);
    }
    int newModCount = this.sampler.getStatisticsModCount();
    // TODO: what if one is deleted and one is added
    if (this.statResourcesModCount != newModCount) {
      this.statResourcesModCount = newModCount;
      int ignoreCount = 0;

      Statistics[] resources = this.sampler.getStatistics();
      for (int i = 0; i < resources.length; i++) {
        Statistics statistics = resources[i];

        // only notify marked/old handlers of new types or resources
        if (!this.resourceInstMap.containsKey(statistics)) {
          try {
            ResourceType type = getResourceType(handlers, statistics);
            ResourceInstance resource = allocateResourceInstance(type, statistics);
            notifyOldHandlersOfResource(handlers, resource);
          } catch (IgnoreResourceException ex) {
            ignoreCount++;
          }
        }
      }

      if (isDebugEnabled_STATISTICS) {
        logger.trace(LogMarker.STATISTICS_VERBOSE,
            "SampleCollector#sampleResources resources.length={}, ignoreCount={}", resources.length,
            ignoreCount);
      }
      List<ResourceInstance> ri = cleanupResources(resources, ignoreCount);
      notifyOldHandlers(handlers, ri);
    }

    // notify unmarked/new handlers but not marked/old handlers
    notifyNewHandlersOfResources(handlers, this.resourceTypeMap.values(),
        this.resourceInstMap.values());
  }

  private ResourceType getResourceType(List<MarkableSampleHandler> handlers, Statistics statistics)
      throws IgnoreResourceException {
    final boolean isDebugEnabled_STATISTICS = logger.isTraceEnabled(LogMarker.STATISTICS_VERBOSE);
    if (isDebugEnabled_STATISTICS) {
      logger.trace(LogMarker.STATISTICS_VERBOSE, "SampleCollector#getResourceType statistics={}",
          statistics);
    }
    StatisticsType type = statistics.getType();
    if (type == null) {
      // bug 30707
      if (isDebugEnabled_STATISTICS) {
        logger.trace(LogMarker.STATISTICS_VERBOSE,
            "SampleCollector#getResourceType type={}, throwing IgnoreResourceException", type);
      }
      throw new IgnoreResourceException();
    }
    ResourceType resourceType = null;
    try {
      resourceType = (ResourceType) this.resourceTypeMap.get(type);
    } catch (NullPointerException ex) {
      // bug 30716
      if (isDebugEnabled_STATISTICS) {
        logger.trace(LogMarker.STATISTICS_VERBOSE,
            "SampleCollector#getResourceType resourceTypeMap.get threw NPE, throwing NullPointerException");
      }
      throw new IgnoreResourceException();
    }
    if (resourceType == null) {
      resourceType = allocateResourceType(handlers, type);
      notifyOldHandlersOfResourceType(handlers, resourceType);
    }
    return resourceType;
  }

  private ResourceType allocateResourceType(List<MarkableSampleHandler> handlers,
      StatisticsType type) throws IgnoreResourceException {
    if (logger.isTraceEnabled(LogMarker.STATISTICS_VERBOSE)) {
      logger.trace(LogMarker.STATISTICS_VERBOSE, "SampleCollector#allocateResourceType type={}",
          type);
    }
    ResourceType resourceType = new ResourceType(this.resourceTypeId, type);
    this.resourceTypeMap.put(type, resourceType);
    this.resourceTypeId++;
    return resourceType;
  }

  private ResourceInstance allocateResourceInstance(ResourceType type, Statistics s) {
    if (logger.isTraceEnabled(LogMarker.STATISTICS_VERBOSE)) {
      logger.trace(LogMarker.STATISTICS_VERBOSE,
          "SampleCollector#allocateResourceInstance type={}, s={}", type, s);
    }
    ResourceInstance resourceInstance = new ResourceInstance(this.resourceInstId, s, type);
    this.resourceInstMap.put(s, resourceInstance);
    this.resourceInstId++;
    return resourceInstance;
  }

  private List<ResourceInstance> cleanupResources(Statistics[] resources, int ignoreCount) {
    final boolean isDebugEnabled_STATISTICS = logger.isTraceEnabled(LogMarker.STATISTICS_VERBOSE);
    if (isDebugEnabled_STATISTICS) {
      logger.trace(LogMarker.STATISTICS_VERBOSE,
          "SampleCollector#cleanupResources resources.length={}, ignoreCount={}", resources.length,
          ignoreCount);
    }
    int resourcesToDelete = this.resourceInstMap.size() - (resources.length - ignoreCount);
    if (isDebugEnabled_STATISTICS) {
      logger.trace(LogMarker.STATISTICS_VERBOSE,
          "SampleCollector#cleanupResources resourcesToDelete={}", resourcesToDelete);
    }
    if (resourcesToDelete == 0) {
      return Collections.<ResourceInstance>emptyList();
    }

    // some resource instances need to be removed
    List<ResourceInstance> resourcesRemoved = new ArrayList<ResourceInstance>();
    List<Statistics> resourceList = Arrays.asList(resources);
    Iterator<Map.Entry<Statistics, ResourceInstance>> it =
        this.resourceInstMap.entrySet().iterator();

    while (it.hasNext() && resourcesToDelete > 0) {
      Map.Entry<Statistics, ResourceInstance> e = it.next();
      Statistics key = (Statistics) e.getKey();
      if (!resourceList.contains(key)) {
        key.close();
        ResourceInstance inst = (ResourceInstance) e.getValue();
        resourcesRemoved.add(inst);
        resourcesToDelete--;
        it.remove();
      }
    }
    if (isDebugEnabled_STATISTICS) {
      logger.trace(LogMarker.STATISTICS_VERBOSE,
          "SampleCollector#cleanupResources resourcesRemoved={}", resourcesRemoved);
    }
    return resourcesRemoved;
  }

  private void notifyAllHandlersOfSample(List<MarkableSampleHandler> handlers,
      List<ResourceInstance> updatedResources, long nanosTimeStamp) {
    final boolean isDebugEnabled_STATISTICS = logger.isTraceEnabled(LogMarker.STATISTICS_VERBOSE);
    if (isDebugEnabled_STATISTICS) {
      logger.trace(LogMarker.STATISTICS_VERBOSE,
          "SampleCollector#notifyAllHandlersOfSample timeStamp={}", nanosTimeStamp);
    }
    if (isDebugEnabled_STATISTICS) {
      logger.trace(LogMarker.STATISTICS_VERBOSE,
          "SampleCollector#notifyAllHandlersOfSample updatedResources.size()={}, handlers={}",
          updatedResources.size(), handlers);
    }
    for (MarkableSampleHandler handler : handlers) {
      handler.sampled(nanosTimeStamp, Collections.unmodifiableList(updatedResources));
    }
  }

  private void notifyNewHandlersOfResources(List<MarkableSampleHandler> handlers,
      Collection<ResourceType> types, Collection<ResourceInstance> resources) {
    final boolean isDebugEnabled_STATISTICS = logger.isTraceEnabled(LogMarker.STATISTICS_VERBOSE);
    if (isDebugEnabled_STATISTICS) {
      logger.trace(LogMarker.STATISTICS_VERBOSE,
          "SampleCollector#notifyNewHandlersOfResources ri.size()={}", resources.size());
    }
    int count = 0;
    for (MarkableSampleHandler handler : handlers) {
      if (!handler.isMarked()) {
        List<ResourceType> allocatedResourceTypes = new ArrayList<ResourceType>();
        for (ResourceInstance resourceInstance : resources) {
          ResourceType resourceType = resourceInstance.getResourceType();
          if (!allocatedResourceTypes.contains(resourceType)) {
            // allocatedResourceType...
            handler.allocatedResourceType(resourceType);
            allocatedResourceTypes.add(resourceType);
          }
          // allocatedResourceInstance...
          handler.allocatedResourceInstance(resourceInstance);
        }
        for (ResourceType resourceType : types) {
          if (!allocatedResourceTypes.contains(resourceType)) {
            handler.allocatedResourceType(resourceType);
          }
        }
        handler.mark();
        count++;
      }
    }
    if (isDebugEnabled_STATISTICS) {
      logger.trace(LogMarker.STATISTICS_VERBOSE,
          "SampleCollector#notifyNewHandlersOfResources notified {} new handlers", count);
    }
  }

  private void notifyOldHandlersOfResource(List<MarkableSampleHandler> handlers,
      ResourceInstance resource) {
    final boolean isDebugEnabled_STATISTICS = logger.isTraceEnabled(LogMarker.STATISTICS_VERBOSE);
    if (isDebugEnabled_STATISTICS) {
      logger.trace(LogMarker.STATISTICS_VERBOSE,
          "SampleCollector#notifyOldHandlersOfResource resource={}", resource);
    }
    int count = 0;
    for (MarkableSampleHandler handler : handlers) {
      if (handler.isMarked()) {
        handler.allocatedResourceInstance(resource);
        count++;
      }
    }
    if (isDebugEnabled_STATISTICS) {
      logger.trace(LogMarker.STATISTICS_VERBOSE,
          "SampleCollector#notifyOldHandlersOfResource notified {} old handlers", count);
    }
  }

  private void notifyOldHandlersOfResourceType(List<MarkableSampleHandler> handlers,
      ResourceType type) {
    final boolean isDebugEnabled_STATISTICS = logger.isTraceEnabled(LogMarker.STATISTICS_VERBOSE);
    if (isDebugEnabled_STATISTICS) {
      logger.trace(LogMarker.STATISTICS_VERBOSE,
          "SampleCollector#notifyOldHandlersOfResourceType type={}", type);
    }
    int count = 0;
    for (MarkableSampleHandler handler : handlers) {
      if (handler.isMarked()) {
        handler.allocatedResourceType(type);
        count++;
      }
    }
    if (isDebugEnabled_STATISTICS) {
      logger.trace(LogMarker.STATISTICS_VERBOSE,
          "SampleCollector#notifyOldHandlersOfResourceType notified {} old handlers", count);
    }
  }

  private void notifyOldHandlers(List<MarkableSampleHandler> handlers, List<ResourceInstance> ri) {
    final boolean isDebugEnabled_STATISTICS = logger.isTraceEnabled(LogMarker.STATISTICS_VERBOSE);
    if (isDebugEnabled_STATISTICS) {
      logger.trace(LogMarker.STATISTICS_VERBOSE, "SampleCollector#notifyOldHandlers ri={}", ri);
    }
    int count = 0;
    for (ResourceInstance resource : ri) {
      for (MarkableSampleHandler handler : handlers) {
        if (handler.isMarked()) {
          handler.destroyedResourceInstance(resource);
          count++;
        }
      }
    }
    if (isDebugEnabled_STATISTICS) {
      logger.trace(LogMarker.STATISTICS_VERBOSE,
          "SampleCollector#notifyOldHandlers notified {} old handlers", count);
    }
  }

  /**
   * For testing only
   */
  StatMonitorHandler getStatMonitorHandlerSnapshot() {
    synchronized (this.sampleHandlers) {
      return this.statMonitorHandler;
    }
  }

  /**
   * @since GemFire 7.0
   */
  public class MarkableSampleHandler implements SampleHandler {

    private final SampleHandler sampleHandler;
    private boolean mark = false;

    public MarkableSampleHandler(SampleHandler sampleHandler) {
      if (sampleHandler == null) {
        throw new NullPointerException("SampleHandler is null");
      }
      this.sampleHandler = sampleHandler;
    }

    public boolean isMarked() {
      if (logger.isTraceEnabled(LogMarker.STATISTICS_VERBOSE)) {
        logger.trace(LogMarker.STATISTICS_VERBOSE,
            "MarkableSampleHandler#isMarked returning {} for {}", this.mark, this);
      }
      return this.mark;
    }

    public void mark() {
      if (logger.isTraceEnabled(LogMarker.STATISTICS_VERBOSE)) {
        logger.trace(LogMarker.STATISTICS_VERBOSE, "MarkableSampleHandler#mark marking {}", this);
      }
      this.mark = true;
    }

    public SampleHandler getSampleHandler() {
      return this.sampleHandler;
    }

    @Override
    public void sampled(long nanosTimeStamp, List<ResourceInstance> resourceInstances) {
      this.sampleHandler.sampled(nanosTimeStamp, resourceInstances);
    }

    @Override
    public void allocatedResourceType(ResourceType resourceType) {
      this.sampleHandler.allocatedResourceType(resourceType);
    }

    @Override
    public void allocatedResourceInstance(ResourceInstance resourceInstance) {
      this.sampleHandler.allocatedResourceInstance(resourceInstance);
    }

    @Override
    public void destroyedResourceInstance(ResourceInstance resourceInstance) {
      this.sampleHandler.destroyedResourceInstance(resourceInstance);
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + this.sampleHandler.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;
      }
      MarkableSampleHandler other = (MarkableSampleHandler) obj;
      return this.sampleHandler == other.sampleHandler;
    }

    @Override
    public String toString() {
      final StringBuilder sb = new StringBuilder(getClass().getName());
      sb.append("@").append(System.identityHashCode(this)).append("{");
      sb.append("mark=").append(this.mark);
      sb.append(", sampleHandler=").append(this.sampleHandler);
      return sb.toString();
    }
  }

  /**
   * @since GemFire 7.0
   */
  public class SampleHandlers implements Iterable<MarkableSampleHandler> {

    private volatile List<MarkableSampleHandler> currentHandlers =
        Collections.<MarkableSampleHandler>emptyList();

    public SampleHandlers() {}

    /**
     * For test usage only.
     */
    public MarkableSampleHandler getMarkableSampleHandler(SampleHandler handler) {
      if (contains(handler)) {
        for (MarkableSampleHandler markableSamplerHandler : currentHandlers()) {
          if (markableSamplerHandler.sampleHandler == handler) {
            return markableSamplerHandler;
          }
        }
      }
      return null;
    }

    public boolean contains(SampleHandler handler) {
      MarkableSampleHandler markableHandler = new MarkableSampleHandler(handler);
      return this.currentHandlers.contains(markableHandler);
    }

    public List<MarkableSampleHandler> currentHandlers() {
      // optimized for read (no copy and unmodifiable)
      return this.currentHandlers;
    }

    @Override
    public Iterator<MarkableSampleHandler> iterator() {
      // optimized for read (no copy and unmodifiable)
      return this.currentHandlers.iterator();
    }

    public Iterator<MarkableSampleHandler> markedIterator() {
      return new MarkableIterator(true);
    }

    public Iterator<MarkableSampleHandler> unmarkedIterator() {
      return new MarkableIterator(false);
    }

    public boolean addSampleHandler(SampleHandler handler) {
      synchronized (this) {
        boolean added = false;
        MarkableSampleHandler markableHandler = new MarkableSampleHandler(handler);
        List<MarkableSampleHandler> oldHandlers = this.currentHandlers;
        if (!oldHandlers.contains(markableHandler)) {
          if (logger.isTraceEnabled(LogMarker.STATISTICS_VERBOSE)) {
            logger.trace(LogMarker.STATISTICS_VERBOSE,
                "SampleHandlers#addSampleHandler adding markableHandler to {}", this);
          }
          List<MarkableSampleHandler> newHandlers =
              new ArrayList<MarkableSampleHandler>(oldHandlers);
          added = newHandlers.add(markableHandler);
          this.currentHandlers = Collections.unmodifiableList(newHandlers);
        }
        return added;
      }
    }

    public boolean removeSampleHandler(SampleHandler handler) {
      synchronized (this) {
        boolean removed = false;
        MarkableSampleHandler markableHandler = new MarkableSampleHandler(handler);
        List<MarkableSampleHandler> oldHandlers = this.currentHandlers;
        if (oldHandlers.contains(markableHandler)) {
          if (logger.isTraceEnabled(LogMarker.STATISTICS_VERBOSE)) {
            logger.trace(LogMarker.STATISTICS_VERBOSE,
                "SampleHandlers#removeSampleHandler removing markableHandler from {}", this);
          }
          List<MarkableSampleHandler> newHandlers =
              new ArrayList<MarkableSampleHandler>(oldHandlers);
          removed = newHandlers.remove(markableHandler);
          this.currentHandlers = Collections.unmodifiableList(newHandlers);
        }
        return removed;
      }
    }

    protected int countMarkableSampleHandlers(SampleHandler handler) {
      int count = 0;
      List<MarkableSampleHandler> list = currentHandlers();
      for (MarkableSampleHandler wrapper : list) {
        if (wrapper.getSampleHandler() == handler) {
          count++;
        }
      }
      return count;
    }

    @Override
    public String toString() {
      final StringBuilder sb = new StringBuilder(getClass().getName());
      sb.append("@").append(System.identityHashCode(this)).append("{");
      sb.append("currentHandlers=").append(this.currentHandlers);
      return sb.toString();
    }

    private class MarkableIterator implements Iterator<MarkableSampleHandler> {

      private final Iterator<MarkableSampleHandler> iterator;

      public MarkableIterator(boolean marked) {
        List<MarkableSampleHandler> matchingHandlers = new ArrayList<MarkableSampleHandler>();
        List<MarkableSampleHandler> handlers = SampleHandlers.this.currentHandlers();
        for (MarkableSampleHandler handler : handlers) {
          if (handler.isMarked() == marked) {
            matchingHandlers.add(handler);
          }
        }
        this.iterator = matchingHandlers.iterator();
      }

      @Override
      public boolean hasNext() {
        return this.iterator.hasNext();
      }

      @Override
      public MarkableSampleHandler next() {
        return this.iterator.next();
      }

      @Override
      public void remove() {
        throw new UnsupportedOperationException("remove operation is not supported");
      }
    }
  }
}
