/*
 * 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.
 */
/*
 * ConcurrentHashMap implementation adapted from JSR 166 backport
 * (http://backport-jsr166.sourceforge.net) JDK5 version release 3.1 with modifications to use
 * generics where appropriate: backport-util-concurrent-Java60-3.1-src.tar.gz
 *
 * Primary change is to allow HashEntry be an interface so that custom HashEntry implementations can
 * be plugged in. These HashEntry objects are now assumed to be immutable in the sense that they
 * cannot and should not be cloned in a rehash, and the rehash mechanism has been recoded using
 * locking for that. For Geode, this is now used to plugin the RegionEntry implementation directly
 * as a HashEntry instead of having it as a value and then HashEntry as a separate object having
 * references to key/value which reduces the entry overhead substantially. Other change is to add a
 * "create" method that creates a new object using the {@link MapCallback} interface only if
 * required unlike "putIfAbsent" that requires a pre-built object that may ultimately be thrown
 * away. Also added a "removeConditionally" method that allows for evaluation of an arbitrary
 * condition before removal from the map (unlike the normal "remove" that can only check for
 * equality with a provided object). In addition, the segments are now locked using read-write
 * locks. File has been reformatted to conform to GemStone conventions. GemStone additions have been
 * marked with "GemStone addition". GemStone changes have been marked with "GemStone change(s)".
 *
 * Original license follows below.
 */
/*
 * Written by Doug Lea with assistance from members of JCP JSR-166 Expert Group and released to the
 * public domain, as explained at http://creativecommons.org/licenses/publicdomain
 */
package org.apache.geode.internal.util.concurrent;

import java.io.IOException;
import java.io.Serializable;
import java.util.AbstractCollection;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.apache.geode.CancelException;
import org.apache.geode.internal.cache.RegionEntry;
import org.apache.geode.internal.cache.entries.OffHeapRegionEntry;
import org.apache.geode.internal.cache.wan.GatewaySenderEventImpl;
import org.apache.geode.internal.offheap.OffHeapRegionEntryHelper;
import org.apache.geode.internal.size.SingleObjectSizer;
import org.apache.geode.internal.util.ArrayUtils;
import org.apache.geode.logging.internal.executors.LoggingThread;

/**
 * A hash table supporting full concurrency of retrievals and adjustable expected concurrency for
 * updates. This class obeys the same functional specification as {@link java.util.Hashtable}, and
 * includes versions of methods corresponding to each method of <tt>Hashtable</tt>. However, even
 * though all operations are thread-safe, retrieval operations do <em>not</em> entail locking, and
 * there is <em>not</em> any support for locking the entire table in a way that prevents all access.
 * This class is fully interoperable with <tt>Hashtable</tt> in programs that rely on its thread
 * safety but not on its synchronization details.
 *
 * <p>
 * Retrieval operations (including <tt>get</tt>) generally do not block, so may overlap with update
 * operations (including <tt>put</tt> and <tt>remove</tt>). Retrievals reflect the results of the
 * most recently <em>completed</em> update operations holding upon their onset. For aggregate
 * operations such as <tt>putAll</tt> and <tt>clear</tt>, concurrent retrievals may reflect
 * insertion or removal of only some entries. Similarly, Iterators and Enumerations return elements
 * reflecting the state of the hash table at some point at or since the creation of the
 * iterator/enumeration. They do <em>not</em> throw
 * {@link java.util.ConcurrentModificationException}. However, iterators are designed to be used by
 * only one thread at a time.
 *
 * <p>
 * The allowed concurrency among update operations is guided by the optional
 * <tt>concurrencyLevel</tt> constructor argument (default <tt>16</tt>), which is used as a hint for
 * internal sizing. The table is internally partitioned to try to permit the indicated number of
 * concurrent updates without contention. Because placement in hash tables is essentially random,
 * the actual concurrency will vary. Ideally, you should choose a value to accommodate as many
 * threads as will ever concurrently modify the table. Using a significantly higher value than you
 * need can waste space and time, and a significantly lower value can lead to thread contention. But
 * overestimates and underestimates within an order of magnitude do not usually have much noticeable
 * impact. A value of one is appropriate when it is known that only one thread will modify and all
 * others will only read. Also, resizing this or any other kind of hash table is a relatively slow
 * operation, so, when possible, it is a good idea to provide estimates of expected table sizes in
 * constructors.
 *
 * <p>
 * This class and its views and iterators implement all of the <em>optional</em> methods of the
 * {@link Map} and {@link Iterator} interfaces.
 *
 * <p>
 * Like {@link java.util.Hashtable} but unlike {@link java.util.HashMap}, this class does
 * <em>not</em> allow <tt>null</tt> to be used as a key or value.
 *
 * <p>
 * This class is a member of the <a href="{@docRoot} /../technotes/guides/collections/index.html">
 * Java Collections Framework</a>.
 *
 * <p>
 * Modifications made to the Java {@link java.util.Hashtable} implementation
 * are indicated using comments to mark the beginning and end of Geode changes.
 *
 * @since Java 1.5
 * @author Doug Lea
 * @param <K> the type of keys maintained by this map
 * @param <V> the type of mapped values
 */
public class CustomEntryConcurrentHashMap<K, V> extends AbstractMap<K, V>
    implements ConcurrentMapWithReusableEntries<K, V>, Serializable {

  private static final long serialVersionUID = -7056732555635108300L;

  /*
   * The basic strategy is to subdivide the table among Segments, each of which itself is a
   * concurrently readable hash table.
   */

  /* ---------------- Constants -------------- */

  /**
   * The default initial capacity for this table, used when not otherwise specified in a
   * constructor.
   */
  public static final int DEFAULT_INITIAL_CAPACITY = 16;

  /**
   * The default load factor for this table, used when not otherwise specified in a constructor.
   */
  public static final float DEFAULT_LOAD_FACTOR = 0.75f;

  /**
   * The default concurrency level for this table, used when not otherwise specified in a
   * constructor.
   */
  public static final int DEFAULT_CONCURRENCY_LEVEL = 16;

  /**
   * The maximum capacity, used if a higher value is implicitly specified by either of the
   * constructors with arguments. MUST be a power of two <= 1<<30 to ensure that entries are
   * indexable using ints.
   */
  static final int MAXIMUM_CAPACITY = 1 << 30;

  /**
   * The maximum number of segments to allow; used to bound constructor arguments.
   */
  static final int MAX_SEGMENTS = 1 << 16; // slightly conservative

  /**
   * Number of unsynchronized retries in size and containsValue methods before resorting to locking.
   * This is used to avoid unbounded retries if tables undergo continuous modification which would
   * make it impossible to obtain an accurate result.
   */
  static final int RETRIES_BEFORE_LOCK = 2;

  // Geode addition
  /**
   * Token object to indicate that {@link #remove(Object)} does not need to compare against provided
   * value before removing from segment.
   */
  private static final Object NO_OBJECT_TOKEN = new Object();

  // End Geode addition

  /* ---------------- Fields -------------- */

  /**
   * Mask value for indexing into segments. The upper bits of a key's hash code are used to choose
   * the segment.
   */
  final int segmentMask;

  /**
   * Shift value for indexing within segments.
   */
  final int segmentShift;

  /**
   * The segments, each of which is a specialized hash table
   */
  final Segment<K, V>[] segments;

  /**
   * {@link HashEntryCreator} for the map to create {@link HashEntry}s.
   */
  final HashEntryCreator<K, V> entryCreator;

  /**
   * If true then use equals for comparing key and value equality else use reference-equality like
   * an {@link IdentityHashMap}.
   */
  final boolean compareValues;

  transient Set<K> keySet;
  transient Set<Map.Entry<K, V>> entrySet;
  transient Set<Map.Entry<K, V>> reusableEntrySet; // Geode addition
  transient Collection<V> values;

  /* ---------------- Small Utilities -------------- */

  /**
   * Applies a supplemental hash function to a given hashCode, which defends against poor quality
   * hash functions. This is critical because ConcurrentHashMap uses power-of-two length hash
   * tables, that otherwise encounter collisions for hashCodes that do not differ in lower or upper
   * bits.
   */
  public static int keyHash(final Object o, final boolean compareValues) {
    int h = compareValues ? o.hashCode() : System.identityHashCode(o);
    // Spread bits to regularize both segment and index locations,
    // using variant of single-word Wang/Jenkins hash.
    h += (h << 15) ^ 0xffffcd7d;
    h ^= (h >>> 10);
    h += (h << 3);
    h ^= (h >>> 6);
    h += (h << 2) + (h << 14);
    return h ^ (h >>> 16);
  }

  /**
   * Returns the segment that should be used for key with given hash
   *
   * @param hash the hash code for the key
   * @return the segment
   */
  Segment<K, V> segmentFor(final int hash) {
    if (this.segmentMask == 0) {
      return this.segments[0];
    }
    return this.segments[(hash >>> this.segmentShift) & this.segmentMask];
  }

  /* ---------------- Inner Classes -------------- */

  // Geode addition
  // Geode changed HashEntry to be an interface with original HashEntry
  // as the default implementation HashEntryImpl.

  /**
   * [sumedh] Interface for ConcurrentHashMap list entry. Note that this is never exported out as a
   * user-visible Map.Entry.
   *
   * Made this public so RegionEntries can directly implement this to reduce memory overhead of
   * separate
   * {@link org.apache.geode.internal.util.concurrent.CustomEntryConcurrentHashMap.HashEntry}
   * objects for each entry in the map.
   */
  public interface HashEntry<K, V> {

    /**
     * Get the key object for this entry.
     */
    K getKey();

    /**
     * Return true if the entry's key is equal to k. GemFire addition to deal with inline keys.
     */
    boolean isKeyEqual(Object k);

    /**
     * Get the value for this entry.
     */
    V getMapValue();

    /**
     * Set the value for this entry.
     */
    void setMapValue(V newValue);

    /**
     * Get the hash value for this entry.
     */
    int getEntryHash();

    /**
     * Get the next entry, if any, in the linear chain.
     */
    HashEntry<K, V> getNextEntry();

    /**
     * Set the next entry in the linear chain.
     */
    void setNextEntry(HashEntry<K, V> n);
  }

  /**
   * ConcurrentHashMap list entry. Note that this is never exported out as a user-visible Map.Entry.
   *
   * Because the value field is volatile, not final, it is legal wrt the Java Memory Model for an
   * unsynchronized reader to see null instead of initial value when read via a data race. Although
   * a reordering leading to this is not likely to ever actually occur, the
   * Segment.readValueUnderLock method is used as a backup in case a null (pre-initialized) value is
   * ever seen in an unsynchronized access method.
   */
  static class HashEntryImpl<K, V> implements HashEntry<K, V> {

    protected final K key;

    protected final int hash;

    protected volatile V value;

    protected HashEntry<K, V> next;

    private final HashEntry<K, V> wrappedEntry;

    HashEntryImpl(final K key, final int hash, final HashEntry<K, V> next, final V value,
        final HashEntry<K, V> wrappedEntry) {
      this.key = key;
      this.hash = hash;
      this.next = next;
      this.value = value;
      this.wrappedEntry = wrappedEntry;
    }

    /**
     * @see CustomEntryConcurrentHashMap.HashEntry#getKey()
     */
    @Override
    public K getKey() {
      return this.key;
    }

    /**
     * @see CustomEntryConcurrentHashMap.HashEntry#getMapValue()
     */
    @Override
    public V getMapValue() {
      return this.value;
    }

    /**
     * @see CustomEntryConcurrentHashMap.HashEntry#setMapValue(Object)
     */
    @Override
    public void setMapValue(V newValue) {
      this.value = newValue;
    }

    /**
     * @see CustomEntryConcurrentHashMap.HashEntry#getEntryHash()
     */
    @Override
    public int getEntryHash() {
      return this.hash;
    }

    /**
     * @see CustomEntryConcurrentHashMap.HashEntry#getNextEntry()
     */
    @Override
    public HashEntry<K, V> getNextEntry() {
      return this.next;
    }

    /**
     * @see CustomEntryConcurrentHashMap.HashEntry#setNextEntry
     */
    @Override
    public void setNextEntry(final HashEntry<K, V> n) {
      this.next = n;
    }

    @Override
    public boolean isKeyEqual(Object k) {
      return k.equals(getKey());
    }
  }

  /**
   * Interface to enable creation of new
   * {@link org.apache.geode.internal.util.concurrent.CustomEntryConcurrentHashMap.HashEntry}
   * objects by caller. This can be used, for example, to return GemFire RegionEntries directly.
   */
  public interface HashEntryCreator<K, V> {

    /**
     * Create a new
     * {@link org.apache.geode.internal.util.concurrent.CustomEntryConcurrentHashMap.HashEntry}
     * given the key, hash, value and next element.
     */
    HashEntry<K, V> newEntry(K key, int hash, HashEntry<K, V> next, V value);

    /**
     * Get the hashCode for given key object.
     */
    int keyHashCode(Object key, boolean compareValues);
  }

  // End Geode addition

  /**
   * Segments are specialized versions of hash tables. This subclasses from ReentrantLock
   * opportunistically, just to simplify some locking and avoid separate construction.
   */
  static class Segment<K, V> extends ReentrantReadWriteLock implements Serializable {

    /*
     * Segments maintain a table of entry lists that are ALWAYS kept in a consistent state, so can
     * be read without locking. Next fields of nodes are immutable (final). All list additions are
     * performed at the front of each bin. This makes it easy to check changes, and also fast to
     * traverse. When nodes would otherwise be changed, new nodes are created to replace them. This
     * works well for hash tables since the bin lists tend to be short. (The average length is less
     * than two for the default load factor threshold.)
     *
     * Read operations can thus proceed without locking, but rely on selected uses of volatiles to
     * ensure that completed write operations performed by other threads are noticed. For most
     * purposes, the "count" field, tracking the number of elements, serves as that volatile
     * variable ensuring visibility. This is convenient because this field needs to be read in many
     * read operations anyway:
     *
     * - All (unsynchronized) read operations must first read the "count" field, and should not look
     * at table entries if it is 0.
     *
     * - All (synchronized) write operations should write to the "count" field after structurally
     * changing any bin. The operations must not take any action that could even momentarily cause a
     * concurrent read operation to see inconsistent data. This is made easier by the nature of the
     * read operations in Map. For example, no operation can reveal that the table has grown but the
     * threshold has not yet been updated, so there are no atomicity requirements for this with
     * respect to reads.
     *
     * As a guide, all critical volatile reads and writes to the count field are marked in code
     * comments.
     */

    private static final long serialVersionUID = -6972364566212065192L;

    /**
     * The number of elements in this segment's region.
     */
    transient volatile int count;

    /**
     * Number of updates that alter the size of the table. This is used during bulk-read methods to
     * make sure they see a consistent snapshot: If modCounts change during a traversal of segments
     * computing size or checking containsValue, then we might have an inconsistent view of state so
     * (usually) must retry.
     */
    transient int modCount;

    /**
     * The table is rehashed when its size exceeds this threshold. (The value of this field is
     * always <tt>(int)(capacity *
     * loadFactor)</tt>.)
     */
    transient int threshold;

    /**
     * The per-segment table.
     */
    transient volatile HashEntry<K, V>[] table;

    /**
     * The load factor for the hash table. Even though this value is same for all segments, it is
     * replicated to avoid needing links to outer object.
     *
     * @serial
     */
    final float loadFactor;

    // Geode addition

    /**
     * {@link org.apache.geode.internal.util.concurrent.CustomEntryConcurrentHashMap.HashEntryCreator}
     * for the map to create
     * {@link org.apache.geode.internal.util.concurrent.CustomEntryConcurrentHashMap.HashEntry}s.
     */
    final HashEntryCreator<K, V> entryCreator;

    /**
     * Lock used when updating the
     * {@link org.apache.geode.internal.util.concurrent.CustomEntryConcurrentHashMap.HashEntry#getNextEntry()}
     * link of an entry.
     */
    final ReentrantReadWriteLock listUpdateLock;

    // End Geode addition

    Segment(final int initialCapacity, final float lf, final HashEntryCreator<K, V> entryCreator) {
      this.loadFactor = lf;
      this.entryCreator = entryCreator;
      this.listUpdateLock = new ReentrantReadWriteLock();
      setTable(Segment.<K, V>newEntryArray(initialCapacity));
    }

    @SuppressWarnings("unchecked")
    static <K, V> Segment<K, V>[] newArray(final int i) {
      return new Segment[i];
    }

    // Geode added the method below
    @SuppressWarnings("unchecked")
    static <K, V> HashEntry<K, V>[] newEntryArray(final int size) {
      return new HashEntry[size];
    }

    /**
     * Sets table to new HashEntry array. Call only while holding lock or in constructor.
     */
    void setTable(final HashEntry<K, V>[] newTable) {
      this.threshold = (int) (newTable.length * this.loadFactor);
      this.table = newTable;
    }

    /**
     * Returns properly casted first entry of bin for given hash.
     */
    HashEntry<K, V> getFirst(final int hash) {
      final HashEntry<K, V>[] tab = this.table;
      return tab[hash & (tab.length - 1)];
    }

    /**
     * Reads value field of an entry under lock. Called if value field ever appears to be null. This
     * is possible only if a compiler happens to reorder a HashEntry initialization with its table
     * assignment, which is legal under memory model but is not known to ever occur.
     */
    V readValueUnderLock(final HashEntry<K, V> e) {
      final ReentrantReadWriteLock.ReadLock readLock = super.readLock();
      readLock.lock();
      final V v = e.getMapValue();
      readLock.unlock();
      return v;
    }

    /**
     * Added for GemFire since it stores some keys inline.
     */
    protected boolean equalityKeyCompare(final Object key, final HashEntry<K, V> mapEntry) {
      return mapEntry.isKeyEqual(key);
    }

    protected boolean equalityCompare(final Object v1, final Object v2) {
      return v1.equals(v2);
    }

    protected boolean equalityCompareWithNulls(final Object key, final Object mapKey) {
      if (key != mapKey) {
        if (key != null) {
          return key.equals(mapKey);
        }
        return false;
      }
      return true;
    }

    /* Specialized implementations of map methods */

    V get(final Object key, final int hash) {
      if (this.count != 0) { // read-volatile
        // Geode change to acquire the read lock on list updates
        final ReentrantReadWriteLock.ReadLock listLock = this.listUpdateLock.readLock();
        listLock.lock();
        boolean lockAcquired = true;
        HashEntry<K, V> e = getFirst(hash);
        try {
          while (e != null) {
            if (e.getEntryHash() == hash && equalityKeyCompare(key, e)) {
              final V v = e.getMapValue();
              if (v != null) {
                return v;
              }
              listLock.unlock();
              lockAcquired = false;
              return readValueUnderLock(e); // recheck
            }
            e = e.getNextEntry();
          }
        } finally {
          if (lockAcquired) {
            listLock.unlock();
          }
        }
      }
      return null;
    }

    V getNoLock(final Object key, final int hash, final boolean lockListForRead) {
      if (this.count != 0) { // read-volatile
        // Geode change to acquire the read lock on list updates
        ReentrantReadWriteLock.ReadLock listLock = null;
        if (lockListForRead) {
          listLock = this.listUpdateLock.readLock();
          listLock.lock();
        }
        HashEntry<K, V> e = getFirst(hash);
        try {
          while (e != null) {
            if (e.getEntryHash() == hash && equalityKeyCompare(key, e)) {
              return e.getMapValue();
            }
            e = e.getNextEntry();
          }
        } finally {
          if (lockListForRead) {
            listLock.unlock();
          }
        }
      }
      return null;
    }

    boolean containsKey(final Object key, final int hash) {
      if (this.count != 0) { // read-volatile
        // Geode change to acquire the read lock on list updates
        final ReentrantReadWriteLock.ReadLock listLock = this.listUpdateLock.readLock();
        listLock.lock();
        HashEntry<K, V> e = getFirst(hash);
        try {
          while (e != null) {
            if (e.getEntryHash() == hash && equalityKeyCompare(key, e)) {
              return true;
            }
            e = e.getNextEntry();
          }
        } finally {
          listLock.unlock();
        }
      }
      return false;
    }

    boolean containsValue(final Object value) {
      if (this.count != 0) { // read-volatile
        // Geode change to acquire the read lock on list updates
        ReentrantReadWriteLock.ReadLock readLock = this.listUpdateLock.readLock();
        RETRYLOOP: for (;;) {
          readLock.lock();
          final HashEntry<K, V>[] tab = this.table;
          final int len = tab.length;
          for (int i = 0; i < len; i++) {
            for (HashEntry<K, V> e = tab[i]; e != null; e = e.getNextEntry()) {
              V v = e.getMapValue();
              if (v == null) {
                // Geode changes BEGIN
                // go back and retry from the very start with segment read lock
                readLock.unlock();
                readLock = super.readLock();
                continue RETRYLOOP;
                /*
                 * (original code) v = readValueUnderLock(e);
                 */
                // Geode changes END
              }
              if (equalityCompare(value, v)) {
                readLock.unlock();
                return true;
              }
            }
          }
          readLock.unlock();
          return false;
        }
      }
      return false;
    }

    boolean replace(final K key, final int hash, final V oldValue, final V newValue) {
      final ReentrantReadWriteLock.WriteLock writeLock = super.writeLock();
      writeLock.lock();
      try {
        HashEntry<K, V> e = getFirst(hash);
        while (e != null && (e.getEntryHash() != hash || !equalityKeyCompare(key, e))) {
          e = e.getNextEntry();
        }

        boolean replaced = false;
        if (e != null && equalityCompare(oldValue, e.getMapValue())) {
          replaced = true;
          e.setMapValue(newValue);
        }
        return replaced;
      } finally {
        writeLock.unlock();
      }
    }

    V replace(final K key, final int hash, final V newValue) {
      final ReentrantReadWriteLock.WriteLock writeLock = super.writeLock();
      writeLock.lock();
      try {
        HashEntry<K, V> e = getFirst(hash);
        while (e != null && (e.getEntryHash() != hash || !equalityKeyCompare(key, e))) {
          e = e.getNextEntry();
        }

        V oldValue = null;
        if (e != null) {
          oldValue = e.getMapValue();
          e.setMapValue(newValue);
        }
        return oldValue;
      } finally {
        writeLock.unlock();
      }
    }

    V put(final K key, final int hash, final V value, final boolean onlyIfAbsent) {
      final ReentrantReadWriteLock.WriteLock writeLock = super.writeLock();
      writeLock.lock();
      try {
        int c = this.count;
        if (c++ > this.threshold) {
          rehash();
        }
        final HashEntry<K, V>[] tab = this.table;
        final int index = hash & (tab.length - 1);
        final HashEntry<K, V> first = tab[index];
        HashEntry<K, V> e = first;
        while (e != null && (e.getEntryHash() != hash || !equalityKeyCompare(key, e))) {
          e = e.getNextEntry();
        }

        final V oldValue;
        if (e != null) {
          oldValue = e.getMapValue();
          if (!onlyIfAbsent) {
            e.setMapValue(value);
          }
        } else {
          oldValue = null;
          ++this.modCount;
          tab[index] = this.entryCreator.newEntry(key, hash, first, value);
          this.count = c; // write-volatile
        }
        return oldValue;
      } finally {
        writeLock.unlock();
      }
    }

    // Geode additions

    <C, P> V create(final K key, final int hash, final MapCallback<K, V, C, P> valueCreator,
        final C context, final P createParams, final boolean lockForRead) {
      // TODO: This can be optimized by having a special lock implementation
      // that will allow upgrade from read to write lock atomically. This can
      // cause a deadlock if two readers try to simultaneously upgrade, so the
      // upgrade should be a tryLock that will fall back to the usual way if
      // unsuccessful. The advantage of that approach is that "equals" calls in
      // the list can be avoided completely if tryLock succeeds (i.e. presumably
      // the common case of no overlap on a segment concurrently). OTOH it will
      // not be as efficient when get succeeds without a read lock (existing
      // entry) that will not need to wait for any writers.
      if (!lockForRead) {
        final V v = getNoLock(key, hash, true);
        if (v != null) {
          return v;
        }
      } else {
        final ReentrantReadWriteLock.ReadLock readLock = super.readLock();
        readLock.lock();
        try {
          final V v = getNoLock(key, hash, false);
          if (v != null) {
            // invoke the callback before returning
            valueCreator.oldValueRead(v);
            return v;
          }
        } finally {
          readLock.unlock();
        }
      }

      final ReentrantReadWriteLock.WriteLock writeLock = super.writeLock();
      writeLock.lock();
      try {
        int c = this.count;
        if (c++ > this.threshold) {
          rehash();
        }
        final HashEntry<K, V>[] tab = this.table;
        final int index = hash & (tab.length - 1);
        final HashEntry<K, V> first = tab[index];
        HashEntry<K, V> e = first;
        while (e != null && (e.getEntryHash() != hash || !equalityKeyCompare(key, e))) {
          e = e.getNextEntry();
        }

        final V currentValue;
        if (e == null) {
          ++this.modCount;
          currentValue = valueCreator.newValue(key, context, createParams);
          tab[index] = this.entryCreator.newEntry(key, hash, first, currentValue);
          this.count = c; // write-volatile
          return currentValue;
        } else {
          currentValue = e.getMapValue();
          if (lockForRead) {
            // invoke the callback before returning an existing value
            valueCreator.oldValueRead(currentValue);
          }
          return currentValue;
        }
      } finally {
        writeLock.unlock();
      }
    }

    V get(final Object key, final int hash, final MapCallback<K, V, ?, ?> readCallback) {
      final ReentrantReadWriteLock.ReadLock readLock = super.readLock();
      readLock.lock();
      try {
        if (this.count != 0) { // read-volatile
          HashEntry<K, V> e = getFirst(hash);
          while (e != null) {
            if (e.getEntryHash() == hash && equalityKeyCompare(key, e)) {
              final V v = e.getMapValue();
              if (v != null) {
                if (readCallback != null) {
                  readCallback.oldValueRead(v);
                }
                return v;
              }
            }
            e = e.getNextEntry();
          }
        }
      } finally {
        readLock.unlock();
      }
      return null;
    }

    // End Geode additions

    void rehash() {
      final HashEntry<K, V>[] oldTable = this.table;
      final int oldCapacity = oldTable.length;
      if (oldCapacity >= MAXIMUM_CAPACITY) {
        return;
      }

      /*
       * Reclassify nodes in each list to new Map. Because we are using power-of-two expansion, the
       * elements from each bin must either stay at same index, or move with a power of two offset.
       * We eliminate unnecessary node creation by catching cases where old nodes can be reused
       * because their next fields won't change. Statistically, at the default threshold, only about
       * one-sixth of them need cloning when a table doubles. The nodes they replace will be garbage
       * collectable as soon as they are no longer referenced by any reader thread that may be in
       * the midst of traversing table right now.
       */

      final HashEntry<K, V>[] newTable = newEntryArray(oldCapacity << 1);
      this.threshold = (int) (newTable.length * this.loadFactor);
      final int sizeMask = newTable.length - 1;
      for (int i = 0; i < oldCapacity; i++) {
        // We need to guarantee that any existing reads of old Map can
        // proceed. So we cannot yet null out each bin.
        final HashEntry<K, V> e = oldTable[i];

        if (e != null) {
          final HashEntry<K, V> next = e.getNextEntry();
          final int idx = e.getEntryHash() & sizeMask;

          // Single node on list
          if (next == null) {
            newTable[idx] = e;
          } else {
            // Reuse trailing consecutive sequence at same slot
            HashEntry<K, V> lastRun = e;
            int lastIdx = idx;
            for (HashEntry<K, V> last = next; last != null; last = last.getNextEntry()) {
              final int k = last.getEntryHash() & sizeMask;
              if (k != lastIdx) {
                lastIdx = k;
                lastRun = last;
              }
            }
            newTable[lastIdx] = lastRun;

            // Clone all remaining nodes
            // Geode changes BEGIN
            // update the next entry instead of cloning the nodes in newTable;
            // this is primarily because we don't want to change
            // the underlying RegionEntry that may be used elsewhere;
            // however we create new wrapper entries for old table so that
            // iterators can continue on old table without blocking updates
            // for indefinite periods
            HashEntryImpl<K, V> newe, newp = null, newFirst = null;
            HashEntry<K, V> nextp;
            // Bug 44155 - we need to clone all of the entries, not just
            // the entries leading up to lastRun, because the entries
            // in the last run may have their next pointers changed
            // by a later rehash.
            for (HashEntry<K, V> p = e; p != null; p = nextp) {
              newe = new HashEntryImpl<K, V>(p.getKey(), p.getEntryHash(),
                  (nextp = p.getNextEntry()), p.getMapValue(), p);
              if (newp != null) {
                newp.setNextEntry(newe);
              } else {
                newFirst = newe;
              }
              newp = newe;
            }
            // take the listUpdate write lock before updating the next refs
            final ReentrantReadWriteLock.WriteLock listWriteLock = this.listUpdateLock.writeLock();
            listWriteLock.lock();
            try {
              if (newFirst != null) {
                this.table[i] = newFirst; // deliberately using volatile write
              }
              for (HashEntry<K, V> p = e; p != lastRun; p = nextp) {
                final int k = p.getEntryHash() & sizeMask;
                final HashEntry<K, V> n = newTable[k];
                nextp = p.getNextEntry();
                p.setNextEntry(n);
                newTable[k] = p;
              }
            } finally {
              listWriteLock.unlock();
            }
            /*
             * (original code) for (HashEntry<K, V> p = e; p != lastRun; p = p.next) { final int k =
             * p.hash & sizeMask; final HashEntry<K, V> n = newTable[k]; newTable[k] =
             * this.entryCreator.newEntry(p.key, p.hash, n, p.value); }
             */
            // Geode changes END
          }
        }
      }
      this.table = newTable;
    }

    /**
     * Remove; match on key only if value null, else match both.
     */
    // Geode change
    // added "condition" and "removeParams" parameters
    <C, P> V remove(final Object key, final int hash, final Object value,
        final MapCallback<K, V, C, P> condition, final C context, final P removeParams) {
      // End Geode change
      final ReentrantReadWriteLock.WriteLock writeLock = super.writeLock();
      writeLock.lock();
      try {
        final int c = this.count - 1;
        final HashEntry<K, V>[] tab = this.table;
        final int index = hash & (tab.length - 1);
        final HashEntry<K, V> first = tab[index];
        HashEntry<K, V> e = first;
        // Geode change
        // the entry previous to the matched one, if any
        HashEntry<K, V> p = null;
        while (e != null && (e.getEntryHash() != hash || !equalityKeyCompare(key, e))) {
          e = e.getNextEntry();
          if (p == null) {
            p = first;
          } else {
            p = p.getNextEntry();
          }
        }

        V oldValue = null;
        if (e != null) {
          final V v = e.getMapValue();
          // Geode change
          // allow for passing in a null object for comparison during remove;
          // also invoke the provided condition to check for removal
          if ((value == NO_OBJECT_TOKEN || equalityCompareWithNulls(v, value))
              && (condition == null || condition.doRemoveValue(v, context, removeParams))) {
            // End Geode change
            oldValue = v;
            // All entries following removed node can stay in list,
            // but all preceding ones need to be cloned.
            ++this.modCount;
            // Geode changes BEGIN
            // update the next entry instead of cloning the nodes
            // this is primarily because we don't want to change
            // the underlying RegionEntry that may be used elsewhere
            final ReentrantReadWriteLock.WriteLock listWriteLock = this.listUpdateLock.writeLock();
            listWriteLock.lock();
            try {
              if (p == null) {
                tab[index] = e.getNextEntry();
              } else {
                p.setNextEntry(e.getNextEntry());
              }
            } finally {
              listWriteLock.unlock();
            }
            /*
             * (original code) HashEntry<K, V> newFirst = e.next; for (HashEntry<K, V> p = first; p
             * != e; p = p.next) { newFirst = this.entryCreator.newEntry(p.key, p.hash, newFirst,
             * p.value); } tab[index] = newFirst;
             */
            // Geode changes END
            this.count = c; // write-volatile
          }
        }
        return oldValue;
      } finally {
        writeLock.unlock();
      }
    }

    /**
     * Geode added the clearedEntries param and the result
     */
    ArrayList<HashEntry<?, ?>> clear(ArrayList<HashEntry<?, ?>> clearedEntries) {
      if (this.count != 0) {
        final ReentrantReadWriteLock.WriteLock writeLock = super.writeLock();
        writeLock.lock();
        try {
          final HashEntry<K, V>[] tab = this.table;
          // Geode changes BEGIN
          if (clearedEntries == null) {
            final boolean checkForGatewaySenderEvent =
                OffHeapRegionEntryHelper.doesClearNeedToCheckForOffHeap();
            if (checkForGatewaySenderEvent) {
              clearedEntries = new ArrayList<HashEntry<?, ?>>();
            } else {
              // see if we have a map with off-heap region entries
              for (HashEntry<K, V> he : tab) {
                if (he != null) {
                  if (he instanceof OffHeapRegionEntry) {
                    clearedEntries = new ArrayList<HashEntry<?, ?>>();
                  }
                  // after the first non-null entry we are done
                  break;
                }
              }
            }
          }
          if (clearedEntries == null) {
            Arrays.fill(tab, null);
          } else {
            for (int i = 0; i < tab.length; i++) {
              HashEntry<K, V> he = tab[i];
              if (he == null)
                continue;
              tab[i] = null;
              clearedEntries.add(he);
            }
            // Geode changes END
          }
          ++this.modCount;
          this.count = 0; // write-volatile
        } finally {
          writeLock.unlock();
        }
      }
      return clearedEntries; // Geode change
    }
  }

  /**
   * Extension of
   * {@link org.apache.geode.internal.util.concurrent.CustomEntryConcurrentHashMap.Segment} using
   * reference-equality comparison for key, value equality instead of equals method.
   *
   * swale
   *
   * @since GemFire 7.0
   */
  static class IdentitySegment<K, V> extends Segment<K, V> implements Serializable {

    private static final long serialVersionUID = 3086228147110819882L;

    IdentitySegment(final int initialCapacity, final float lf,
        final HashEntryCreator<K, V> entryCreator) {
      super(initialCapacity, lf, entryCreator);
    }

    @SuppressWarnings("unchecked")
    static <K, V> IdentitySegment<K, V>[] newArray(final int i) {
      return new IdentitySegment[i];
    }

    @Override
    protected boolean equalityKeyCompare(final Object key, final HashEntry<K, V> mapEntry) {
      return key == mapEntry.getKey();
    }

    @Override
    protected boolean equalityCompare(final Object key, final Object mapKey) {
      return key == mapKey;
    }

    @Override
    protected boolean equalityCompareWithNulls(final Object key, final Object mapKey) {
      return key == mapKey;
    }
  }

  /* ---------------- Public operations -------------- */

  /**
   * Creates a new, empty map with the specified initial capacity, load factor and concurrency
   * level.
   *
   * @param initialCapacity the initial capacity. The implementation performs internal sizing to
   *        accommodate this many elements.
   * @param loadFactor the load factor threshold, used to control resizing. Resizing may be
   *        performed when the average number of elements per bin exceeds this threshold.
   * @param concurrencyLevel the estimated number of concurrently updating threads. The
   *        implementation performs internal sizing to try to accommodate this many threads.
   * @throws IllegalArgumentException if the initial capacity is negative or the load factor or
   *         concurrencyLevel are nonpositive.
   */
  public CustomEntryConcurrentHashMap(final int initialCapacity, final float loadFactor,
      final int concurrencyLevel) {
    this(initialCapacity, loadFactor, concurrencyLevel, false, null);
  }

  // Geode addition

  /**
   * Creates a new, empty map with the specified initial capacity, load factor and concurrency
   * level.
   *
   * @param initialCapacity the initial capacity. The implementation performs internal sizing to
   *        accommodate this many elements.
   * @param loadFactor the load factor threshold, used to control resizing. Resizing may be
   *        performed when the average number of elements per bin exceeds this threshold.
   * @param concurrencyLevel the estimated number of concurrently updating threads. The
   *        implementation performs internal sizing to try to accommodate this many threads.
   * @param isIdentityMap if true then this will use reference-equality instead of equals like an
   *        {@link IdentityHashMap}
   * @throws IllegalArgumentException if the initial capacity is negative or the load factor or
   *         concurrencyLevel are nonpositive.
   */
  public CustomEntryConcurrentHashMap(final int initialCapacity, final float loadFactor,
      final int concurrencyLevel, final boolean isIdentityMap) {
    this(initialCapacity, loadFactor, concurrencyLevel, isIdentityMap, null);
  }

  /**
   * Creates a new, empty map with the specified initial capacity, load factor, concurrency level
   * and custom {@link HashEntryCreator}.
   *
   * @param initialCapacity the initial capacity. The implementation performs internal sizing to
   *        accommodate this many elements.
   * @param loadFactor the load factor threshold, used to control resizing. Resizing may be
   *        performed when the average number of elements per bin exceeds this threshold.
   * @param concurrencyLevel the estimated number of concurrently updating threads. The
   *        implementation performs internal sizing to try to accommodate this many threads.
   * @param isIdentityMap if true then this will use reference-equality instead of equals like an
   *        {@link IdentityHashMap}
   * @param entryCreator a custom {@link HashEntryCreator} for creating the map entries
   *
   * @throws IllegalArgumentException if the initial capacity is negative or the load factor or
   *         concurrencyLevel are nonpositive.
   */
  public CustomEntryConcurrentHashMap(int initialCapacity, final float loadFactor,
      int concurrencyLevel, final boolean isIdentityMap, HashEntryCreator<K, V> entryCreator) {
    if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0) {
      throw new IllegalArgumentException();
    }

    if (concurrencyLevel > MAX_SEGMENTS) {
      concurrencyLevel = MAX_SEGMENTS;
    }

    // Find power-of-two sizes best matching arguments
    int sshift = 0;
    int ssize = 1;
    if (concurrencyLevel > 1) {
      while (ssize < concurrencyLevel) {
        ++sshift;
        ssize <<= 1;
      }
    }
    this.segmentShift = 32 - sshift;
    this.segmentMask = ssize - 1;

    if (initialCapacity > MAXIMUM_CAPACITY) {
      initialCapacity = MAXIMUM_CAPACITY;
    }
    int c = initialCapacity / ssize;
    if (c * ssize < initialCapacity) {
      ++c;
    }
    int cap = 1;
    while (cap < c) {
      cap <<= 1;
    }

    if (entryCreator == null) {
      entryCreator = new DefaultHashEntryCreator<K, V>();
    }
    if (!isIdentityMap) {
      this.compareValues = true;
      this.segments = Segment.newArray(ssize);
      this.entryCreator = entryCreator;
      for (int i = 0; i < ssize; ++i) {
        this.segments[i] = new Segment<K, V>(cap, loadFactor, entryCreator);
      }
    } else {
      this.compareValues = false;
      this.segments = IdentitySegment.newArray(ssize);
      this.entryCreator = entryCreator;
      for (int i = 0; i < ssize; ++i) {
        this.segments[i] = new IdentitySegment<K, V>(cap, loadFactor, entryCreator);
      }
    }
  }

  static class DefaultHashEntryCreator<K, V> implements HashEntryCreator<K, V>, Serializable {

    private static final long serialVersionUID = 3765680607280951726L;

    @Override
    public HashEntry<K, V> newEntry(final K key, final int hash, final HashEntry<K, V> next,
        final V value) {
      return new HashEntryImpl<K, V>(key, hash, next, value, null);
    }

    @Override
    public int keyHashCode(final Object key, final boolean compareValues) {
      return keyHash(key, compareValues);
    }
  }

  // End Geode addition

  /**
   * Creates a new, empty map with the specified initial capacity and load factor and with the
   * default concurrencyLevel (16).
   *
   * @param initialCapacity The implementation performs internal sizing to accommodate this many
   *        elements.
   * @param loadFactor the load factor threshold, used to control resizing. Resizing may be
   *        performed when the average number of elements per bin exceeds this threshold.
   * @throws IllegalArgumentException if the initial capacity of elements is negative or the load
   *         factor is nonpositive
   *
   * @since GemFire 1.6
   */
  public CustomEntryConcurrentHashMap(final int initialCapacity, final float loadFactor) {
    this(initialCapacity, loadFactor, DEFAULT_CONCURRENCY_LEVEL, false);
  }

  /**
   * Creates a new, empty map with the specified initial capacity, and with default load factor
   * (0.75) and concurrencyLevel (16).
   *
   * @param initialCapacity the initial capacity. The implementation performs internal sizing to
   *        accommodate this many elements.
   * @throws IllegalArgumentException if the initial capacity of elements is negative.
   */
  public CustomEntryConcurrentHashMap(final int initialCapacity) {
    this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL, false);
  }

  /**
   * Creates a new, empty map with a default initial capacity (16), load factor (0.75) and
   * concurrencyLevel (16).
   */
  public CustomEntryConcurrentHashMap() {
    this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL, false);
  }

  /**
   * Creates a new map with the same mappings as the given map. The map is created with a capacity
   * of 1.5 times the number of mappings in the given map or 16 (whichever is greater), and a
   * default load factor (0.75) and concurrencyLevel (16).
   *
   * @param m the map
   */
  public CustomEntryConcurrentHashMap(final Map<? extends K, ? extends V> m) {
    this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1, DEFAULT_INITIAL_CAPACITY),
        DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL, false);
    putAll(m);
  }

  /**
   * Returns <tt>true</tt> if this map contains no key-value mappings.
   *
   * @return <tt>true</tt> if this map contains no key-value mappings
   */
  @Override
  public boolean isEmpty() {
    final Segment<K, V>[] segments = this.segments;
    /*
     * We keep track of per-segment modCounts to avoid ABA problems in which an element in one
     * segment was added and in another removed during traversal, in which case the table was never
     * actually empty at any point. Note the similar use of modCounts in the size() and
     * containsValue() methods, which are the only other methods also susceptible to ABA problems.
     */
    final int[] mc = new int[segments.length];
    int mcsum = 0;
    for (int i = 0; i < segments.length; ++i) {
      if (segments[i].count != 0) {
        return false;
      } else {
        mcsum += mc[i] = segments[i].modCount;
      }
    }
    // If mcsum happens to be zero, then we know we got a snapshot
    // before any modifications at all were made. This is
    // probably common enough to bother tracking.
    if (mcsum != 0) {
      for (int i = 0; i < segments.length; ++i) {
        if (segments[i].count != 0 || mc[i] != segments[i].modCount) {
          return false;
        }
      }
    }
    return true;
  }

  /**
   * Returns the number of key-value mappings in this map. If the map contains more than
   * <tt>Integer.MAX_VALUE</tt> elements, returns <tt>Integer.MAX_VALUE</tt>.
   *
   * @return the number of key-value mappings in this map
   */
  @Override
  @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "UL_UNRELEASED_LOCK",
      justification = "The lock() calls are followed by unlock() calls without finally-block. Leaving this as is because it's lifted from JDK code and we want to minimize changes.")
  public int size() {
    final Segment<K, V>[] segments = this.segments;
    long sum = 0;
    long check = 0;
    final int[] mc = new int[segments.length];
    // Try a few times to get accurate count. On failure due to
    // continuous async changes in table, resort to locking.
    for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) {
      check = 0;
      sum = 0;
      int mcsum = 0;
      for (int i = 0; i < segments.length; ++i) {
        sum += segments[i].count;
        mcsum += mc[i] = segments[i].modCount;
      }
      if (mcsum != 0) {
        for (int i = 0; i < segments.length; ++i) {
          check += segments[i].count;
          if (mc[i] != segments[i].modCount) {
            check = -1; // force retry
            break;
          }
        }
      }
      if (check == sum) {
        break;
      }
    }
    if (check != sum) { // Resort to locking all segments
      sum = 0;
      for (int i = 0; i < segments.length; ++i) {
        segments[i].readLock().lock();
      }
      for (int i = 0; i < segments.length; ++i) {
        sum += segments[i].count;
      }
      for (int i = 0; i < segments.length; ++i) {
        segments[i].readLock().unlock();
      }
    }
    if (sum > Integer.MAX_VALUE) {
      return Integer.MAX_VALUE;
    } else {
      return (int) sum;
    }
  }

  /**
   * Returns the value to which the specified key is mapped, or {@code null} if this map contains no
   * mapping for the key.
   *
   * <p>
   * More formally, if this map contains a mapping from a key {@code k} to a value {@code v} such
   * that {@code key.equals(k)}, then this method returns {@code v}; otherwise it returns
   * {@code null}. (There can be at most one such mapping.)
   *
   * @throws NullPointerException if the specified key is null
   */
  @Override
  public V get(final Object key) {
    // throws NullPointerException if key null
    final int hash = this.entryCreator.keyHashCode(key, this.compareValues);
    return segmentFor(hash).get(key, hash);
  }

  /**
   * Tests if the specified object is a key in this table.
   *
   * @param key possible key
   * @return <tt>true</tt> if and only if the specified object is a key in this table, as determined
   *         by the <tt>equals</tt> method; <tt>false</tt> otherwise.
   * @throws NullPointerException if the specified key is null
   */
  @Override
  public boolean containsKey(final Object key) {
    // throws NullPointerException if key null
    final int hash = this.entryCreator.keyHashCode(key, this.compareValues);
    return segmentFor(hash).containsKey(key, hash);
  }

  /**
   * Returns <tt>true</tt> if this map maps one or more keys to the specified value. Note: This
   * method requires a full internal traversal of the hash table, and so is much slower than method
   * <tt>containsKey</tt>.
   *
   * @param value value whose presence in this map is to be tested
   * @return <tt>true</tt> if this map maps one or more keys to the specified value
   * @throws NullPointerException if the specified value is null
   */
  @Override
  @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "UL_UNRELEASED_LOCK",
      justification = "Leaving this as is because it's lifted from JDK code and we want to minimize changes.")
  public boolean containsValue(final Object value) {
    if (value == null) {
      throw new NullPointerException();
    }

    // See explanation of modCount use above

    final Segment<K, V>[] segments = this.segments;
    final int[] mc = new int[segments.length];

    // Try a few times without locking
    for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) {
      int mcsum = 0;
      for (int i = 0; i < segments.length; ++i) {
        mcsum += mc[i] = segments[i].modCount;
        if (segments[i].containsValue(value)) {
          return true;
        }
      }
      boolean cleanSweep = true;
      if (mcsum != 0) {
        for (int i = 0; i < segments.length; ++i) {
          if (mc[i] != segments[i].modCount) {
            cleanSweep = false;
            break;
          }
        }
      }
      if (cleanSweep) {
        return false;
      }
    }
    // Resort to locking all segments
    for (int i = 0; i < segments.length; ++i) {
      segments[i].readLock().lock();
    }
    boolean found = false;
    try {
      for (int i = 0; i < segments.length; ++i) {
        if (segments[i].containsValue(value)) {
          found = true;
          break;
        }
      }
    } finally {
      for (int i = 0; i < segments.length; ++i) {
        segments[i].readLock().unlock();
      }
    }
    return found;
  }

  /**
   * Legacy method testing if some key maps into the specified value in this table. This method is
   * identical in functionality to {@link #containsValue}, and exists solely to ensure full
   * compatibility with class {@link java.util.Hashtable}, which supported this method prior to
   * introduction of the Java Collections framework.
   *
   * @param value a value to search for
   * @return <tt>true</tt> if and only if some key maps to the <tt>value</tt> argument in this table
   *         as determined by the <tt>equals</tt> method; <tt>false</tt> otherwise
   * @throws NullPointerException if the specified value is null
   */
  public boolean contains(final Object value) {
    return containsValue(value);
  }

  /**
   * Maps the specified key to the specified value in this table. Neither the key nor the value can
   * be null.
   *
   * <p>
   * The value can be retrieved by calling the <tt>get</tt> method with a key that is equal to the
   * original key.
   *
   * @param key key with which the specified value is to be associated
   * @param value value to be associated with the specified key
   * @return the previous value associated with <tt>key</tt>, or <tt>null</tt> if there was no
   *         mapping for <tt>key</tt>
   * @throws NullPointerException if the specified key or value is null
   */
  @Override
  public V put(final K key, final V value) {
    if (value == null) {
      throw new NullPointerException();
    }
    // throws NullPointerException if key null
    final int hash = this.entryCreator.keyHashCode(key, this.compareValues);
    return segmentFor(hash).put(key, hash, value, false);
  }

  /**
   * {@inheritDoc}
   *
   * @return the previous value associated with the specified key, or <tt>null</tt> if there was no
   *         mapping for the key
   * @throws NullPointerException if the specified key or value is null
   */
  @Override
  public V putIfAbsent(final K key, final V value) {
    if (value == null) {
      throw new NullPointerException();
    }
    // throws NullPointerException if key null
    final int hash = this.entryCreator.keyHashCode(key, this.compareValues);
    return segmentFor(hash).put(key, hash, value, true);
  }

  // Geode addition

  /**
   * Create a given key, value mapping if the key does not exist in the map else do nothing. The
   * difference between this method and {@link #putIfAbsent(Object, Object)} is that latter always
   * acquires a write lock on the segment which this acquires a write lock only if entry was not
   * found. In other words this method is more efficient for the case when number of entries is
   * small and same entries are being updated repeatedly.
   *
   * @return true if the key was successfully put in the map or false if there was an existing
   *         mapping for the key in the map
   *
   * @throws NullPointerException if the specified key is null
   */
  public boolean create(final K key, final V value) {
    // throws NullPointerException if key null
    final int hash = this.entryCreator.keyHashCode(key, this.compareValues);
    final Segment<K, V> seg = segmentFor(hash);
    if (seg.containsKey(key, hash)) {
      return false;
    }
    return seg.put(key, hash, value, true) == null;
  }

  /**
   * Factory to create a value on demand for
   * {@link #create(Object, MapCallback, Object, Object, boolean)} rather than requiring a pre-built
   * object as in {@link #putIfAbsent(Object, Object)} that may be ultimately thrown away.
   * <p>
   * Also allows invoking a method when removing from map by a call to
   * {@link #removeConditionally(Object, MapCallback, Object, Object)}.
   *
   * @since GemFire 7.0
   *
   * @param <K> the type of key of the map
   * @param <V> the type of value of the map
   * @param <C> the type of context parameter passed to the creation/removal methods
   * @param <P> the type of extra parameter passed to the creation/removal methods
   */
  public interface MapCallback<K, V, C, P> {

    /**
     * Create a new instance of the value object given the key and provided parameters for
     * construction.
     *
     * @param key the key for which the value is being created
     * @param context any context in which this method has been invoked
     * @param createParams parameters, if any, required for construction of a new value object
     */
    V newValue(K key, C context, P createParams);

    /**
     * Invoked when an existing value in map is read by the
     * {@link #create(Object, MapCallback, Object, Object, boolean)} method in the segment when
     * segment is locked for read, or by
     *
     * @param value the value read by create that will be returned
     */
    void oldValueRead(V value);

    /**
     * Check if the existing value should be removed by the
     * {@link CustomEntryConcurrentHashMap#removeConditionally} method.
     *
     * @param value the value to be removed from the map
     * @param context any context in which this method has been invoked
     * @param removeParams parameters, if any, to be passed for cleanup of the object
     */
    boolean doRemoveValue(V value, C context, P removeParams);
  }

  /**
   * Simple adapter class providing empty default implementations for
   * {@link org.apache.geode.internal.util.concurrent.CustomEntryConcurrentHashMap.MapCallback}.
   */
  public static class MapCallbackAdapter<K, V, C, P> implements MapCallback<K, V, C, P> {

    /**
     * @see MapCallback#newValue
     */
    @Override
    public V newValue(K key, C context, P createParams) {
      return null;
    }

    /**
     * @see MapCallback#oldValueRead
     */
    @Override
    public void oldValueRead(V value) {}

    /**
     * @see MapCallback#doRemoveValue
     */
    @Override
    public boolean doRemoveValue(V value, C context, P removeParams) {
      return true;
    }
  }

  /**
   * Like {@link #putIfAbsent(Object, Object)} but creates the value only if none present rather
   * than requiring a passed in pre-created object that may ultimately be thrown away. Also takes
   * read lock on the segment, if required, to provide better guarantees w.r.t. remove/replace that
   * checks against old value when the value may be changed structurally by reading (e.g. a list as
   * value changed after a call to this method).
   *
   * @param key key with which the specified value is to be associated
   * @param valueCreator factory object to create the value to be associated with the specified key,
   *        if required
   * @param context the context in which this method has been invoked and passed to
   *        <code>valueCreator</code> {@link MapCallback#newValue} method to create the new instance
   * @param createParams parameters to be passed to the <code>valueCreator</code>
   *        {@link MapCallback#newValue} method to create the new instance
   * @param lockForRead if passed as true, then the read from the map prior to creation is done
   *        under the segment read lock; this provides better guarantees with respect to other
   *        threads that may be manipulating the value object in place after reading from the map
   *
   * @return the previous value associated with the specified key, or the new value obtained by
   *         invoking {@link MapCallback#newValue} if there was no mapping for the key; this is
   *         paired with the segment read lock
   *
   * @throws NullPointerException if the specified key or value is null
   */
  public <C, P> V create(final K key, final MapCallback<K, V, C, P> valueCreator, final C context,
      final P createParams, final boolean lockForRead) {
    // throws NullPointerException if key null
    final int hash = this.entryCreator.keyHashCode(key, this.compareValues);
    return segmentFor(hash).create(key, hash, valueCreator, context, createParams, lockForRead);
  }

  /**
   * Returns the value to which the specified key is mapped, or {@code null} if this map contains no
   * mapping for the key.
   *
   * <p>
   * More formally, if this map contains a mapping from a key {@code k} to a value {@code v} such
   * that {@code key.equals(k)}, then this method returns {@code v}; otherwise it returns
   * {@code null}. (There can be at most one such mapping.)
   *
   * <p>
   * This variant locks the segment for reading and if the given {@link MapCallback} is non-null
   * then its {@link MapCallback#oldValueRead(Object)} method is invoked in the lock.
   *
   * @throws NullPointerException if the specified key is null
   */
  public V get(final Object key, final MapCallback<K, V, ?, ?> readCallback) {
    // throws NullPointerException if key null
    final int hash = this.entryCreator.keyHashCode(key, this.compareValues);
    return segmentFor(hash).get(key, hash, readCallback);
  }

  /**
   * Removes the entry for a key only if the given condition ( {@link MapCallback#doRemoveValue}
   * evaluates to true. This is equivalent to:
   *
   * <pre>
   * if (map.containsKey(key) &amp;&amp; condition.doRemoveInstance(map.get(key), removeParams)) {
   *   map.remove(key);
   *   return true;
   * } else {
   *   return false;
   * }
   * </pre>
   *
   * except that the action is performed atomically.
   *
   * @param key key with which the specified value is associated
   * @param condition {@link MapCallback#doRemoveValue} is invoked and checked inside the segment
   *        lock if removal should be done
   * @param context the context in which this method has been invoked and passed to
   *        <code>condition</code> {@link MapCallback#doRemoveValue} method to create the new
   *        instance
   * @param removeParams parameters to be passed to the <code>onSuccess</code> parameter
   *
   * @return the previous value associated with <tt>key</tt>, or <tt>null</tt> if there was no
   *         mapping for <tt>key</tt>
   *
   * @throws UnsupportedOperationException if the <tt>remove</tt> operation is not supported by this
   *         map
   * @throws ClassCastException if the key or value is of an inappropriate type for this map
   *         (optional)
   * @throws NullPointerException if the specified key or value is null, and this map does not
   *         permit null keys or values (optional)
   */
  public <C, P> V removeConditionally(final Object key, final MapCallback<K, V, C, P> condition,
      final C context, final P removeParams) {
    // throws NullPointerException if key null
    final int hash = this.entryCreator.keyHashCode(key, this.compareValues);
    return segmentFor(hash).remove(key, hash, NO_OBJECT_TOKEN, condition, context, removeParams);
  }

  // End Geode addition

  /**
   * Copies all of the mappings from the specified map to this one. These mappings replace any
   * mappings that this map had for any of the keys currently in the specified map.
   *
   * @param m mappings to be stored in this map
   */
  @Override
  public void putAll(final Map<? extends K, ? extends V> m) {
    for (final Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
      put(e.getKey(), e.getValue());
    }
  }

  /**
   * Removes the key (and its corresponding value) from this map. This method does nothing if the
   * key is not in the map.
   *
   * @param key the key that needs to be removed
   * @return the previous value associated with <tt>key</tt>, or <tt>null</tt> if there was no
   *         mapping for <tt>key</tt>
   * @throws NullPointerException if the specified key is null
   */
  @Override
  public V remove(final Object key) {
    // throws NullPointerException if key null
    final int hash = this.entryCreator.keyHashCode(key, this.compareValues);
    return segmentFor(hash).remove(key, hash, NO_OBJECT_TOKEN, null, null, null);
  }

  /**
   * {@inheritDoc}
   *
   * @throws NullPointerException if the specified key is null
   */
  @Override
  public boolean remove(final Object key, final Object value) {
    if (value == null) {
      return false;
    }
    // throws NullPointerException if key null
    final int hash = this.entryCreator.keyHashCode(key, this.compareValues);
    return segmentFor(hash).remove(key, hash, value, null, null, null) != null;
  }

  /**
   * {@inheritDoc}
   *
   * @throws NullPointerException if any of the arguments are null
   */
  @Override
  public boolean replace(final K key, final V oldValue, final V newValue) {
    if (oldValue == null || newValue == null) {
      throw new NullPointerException();
    }
    // throws NullPointerException if key null
    final int hash = this.entryCreator.keyHashCode(key, this.compareValues);
    return segmentFor(hash).replace(key, hash, oldValue, newValue);
  }

  /**
   * {@inheritDoc}
   *
   * @return the previous value associated with the specified key, or <tt>null</tt> if there was no
   *         mapping for the key
   * @throws NullPointerException if the specified key or value is null
   */
  @Override
  public V replace(final K key, final V value) {
    if (value == null) {
      throw new NullPointerException();
    }
    // throws NullPointerException if key null
    final int hash = this.entryCreator.keyHashCode(key, this.compareValues);
    return segmentFor(hash).replace(key, hash, value);
  }

  // Geode addition
  @Override
  public void clearWithExecutor(Executor executor) {
    ArrayList<HashEntry<?, ?>> entries = null;
    try {
      for (int i = 0; i < this.segments.length; ++i) {
        entries = this.segments[i].clear(entries);
      }
    } finally {
      if (entries != null) {
        final ArrayList<HashEntry<?, ?>> clearedEntries = entries;
        Runnable runnable;
        if (OffHeapRegionEntryHelper.doesClearNeedToCheckForOffHeap()) {
          runnable = new Runnable() {
            @Override
            public void run() {
              for (HashEntry<?, ?> he : clearedEntries) {
                for (HashEntry<?, ?> p = he; p != null; p = p.getNextEntry()) {
                  if (p instanceof RegionEntry) {
                    synchronized (p) {
                      GatewaySenderEventImpl.release(((RegionEntry) p).getValue()); // OFFHEAP
                    }
                  }
                }
              }
            }
          };
        } else {
          runnable = new Runnable() {
            @Override
            public void run() {
              for (HashEntry<?, ?> he : clearedEntries) {
                for (HashEntry<?, ?> p = he; p != null; p = p.getNextEntry()) {
                  synchronized (p) {
                    ((OffHeapRegionEntry) p).release();
                  }
                }
              }
            }
          };
        }
        boolean submitted = false;
        if (executor != null) {
          try {
            executor.execute(runnable);
            submitted = true;
          } catch (RejectedExecutionException e) {
            // fall through with submitted false
          } catch (CancelException e) {
            // fall through with submitted false
          } catch (NullPointerException e) {
            // fall through with submitted false
          }
        }
        if (!submitted) {
          String name = this.getClass().getSimpleName() + "@" + this.hashCode() + " Clear Thread";
          Thread thread = new LoggingThread(name, runnable);
          thread.start();
        }
      }
    }
  }

  /**
   * Removes all of the mappings from this map.
   */
  @Override
  public void clear() {
    clearWithExecutor(null);
  }
  // End Geode addition

  /**
   * Returns a {@link Set} view of the keys contained in this map. The set is backed by the map, so
   * changes to the map are reflected in the set, and vice-versa. The set supports element removal,
   * which removes the corresponding mapping from this map, via the <tt>Iterator.remove</tt>,
   * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt> operations. It
   * does not support the <tt>add</tt> or <tt>addAll</tt> operations.
   *
   * <p>
   * The view's <tt>iterator</tt> is a "weakly consistent" iterator that will never throw
   * {@link java.util.ConcurrentModificationException}, and guarantees to traverse elements as they
   * existed upon construction of the iterator, and may (but is not guaranteed to) reflect any
   * modifications subsequent to construction.
   */
  @Override
  public Set<K> keySet() {
    final Set<K> ks = this.keySet;
    return (ks != null) ? ks : (this.keySet = new KeySet());
  }

  /**
   * Returns a {@link Collection} view of the values contained in this map. The collection is backed
   * by the map, so changes to the map are reflected in the collection, and vice-versa. The
   * collection supports element removal, which removes the corresponding mapping from this map, via
   * the <tt>Iterator.remove</tt>, <tt>Collection.remove</tt>, <tt>removeAll</tt>,
   * <tt>retainAll</tt>, and <tt>clear</tt> operations. It does not support the <tt>add</tt> or
   * <tt>addAll</tt> operations.
   *
   * <p>
   * The view's <tt>iterator</tt> is a "weakly consistent" iterator that will never throw
   * {@link java.util.ConcurrentModificationException}, and guarantees to traverse elements as they
   * existed upon construction of the iterator, and may (but is not guaranteed to) reflect any
   * modifications subsequent to construction.
   */
  @Override
  public Collection<V> values() {
    final Collection<V> vs = this.values;
    return (vs != null) ? vs : (this.values = new Values());
  }

  /**
   * Returns a {@link Set} view of the mappings contained in this map. The set is backed by the map,
   * so changes to the map are reflected in the set, and vice-versa. The set supports element
   * removal, which removes the corresponding mapping from the map, via the
   * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt>, and
   * <tt>clear</tt> operations. It does not support the <tt>add</tt> or <tt>addAll</tt> operations.
   *
   * <p>
   * The view's <tt>iterator</tt> is a "weakly consistent" iterator that will never throw
   * {@link java.util.ConcurrentModificationException}, and guarantees to traverse elements as they
   * existed upon construction of the iterator, and may (but is not guaranteed to) reflect any
   * modifications subsequent to construction.
   */
  @Override
  public Set<Map.Entry<K, V>> entrySet() {
    final Set<Map.Entry<K, V>> es = this.entrySet;
    return (es != null) ? es : (this.entrySet = new EntrySet(false));
  }

  // Geode addition

  @Override
  public Set<Map.Entry<K, V>> entrySetWithReusableEntries() {
    final Set<Map.Entry<K, V>> es = this.reusableEntrySet;
    return (es != null) ? es : (this.reusableEntrySet = new EntrySet(true));
  }

  // End Geode addition

  /**
   * Returns an enumeration of the keys in this table.
   *
   * @return an enumeration of the keys in this table
   * @see #keySet()
   */
  public Enumeration<K> keys() {
    return new KeyIterator();
  }

  /**
   * Returns an enumeration of the values in this table.
   *
   * @return an enumeration of the values in this table
   * @see #values()
   */
  public Enumeration<V> elements() {
    return new ValueIterator();
  }

  /* ---------------- Iterator Support -------------- */

  abstract class HashIterator {

    int currentSegmentIndex;

    int nextTableIndex;

    // Geode changed HashEntry<K, V>[] currentTable to currentSegment
    HashEntry<K, V>[] currentTable;

    HashEntry<K, V> nextEntry;

    HashEntry<K, V> lastReturned;

    final ArrayList<HashEntry<K, V>> currentList;

    int currentListIndex;

    HashIterator() {
      this.currentSegmentIndex = CustomEntryConcurrentHashMap.this.segments.length;
      this.nextTableIndex = -1;
      this.currentList = new ArrayList<HashEntry<K, V>>(5);
      this.currentListIndex = 0;
      advance();
    }

    public boolean hasMoreElements() {
      return hasNext();
    }

    void advance() {
      // Geode changes BEGIN
      if (this.currentListIndex < this.currentList.size()) {
        this.nextEntry = this.currentList.get(this.currentListIndex++);
        return;
      }

      this.nextEntry = null;
      if (this.nextTableIndex >= 0) {
        final Segment<K, V> seg =
            CustomEntryConcurrentHashMap.this.segments[this.currentSegmentIndex];
        final ReentrantReadWriteLock.ReadLock listLock = seg.listUpdateLock.readLock();
        listLock.lock();
        try {
          do {
            if ((this.nextEntry = currentTable[this.nextTableIndex--]) != null) {
              copyEntriesToList();
              return;
            }
          } while (this.nextTableIndex >= 0);
        } finally {
          listLock.unlock();
        }
      }
      /*
       * (original code) if (this.nextEntry != null && (this.nextEntry =
       * this.nextEntry.getNextEntry()) != null) { return; }
       *
       * while (this.nextTableIndex >= 0) { if ((this.nextEntry =
       * this.currentTable[this.nextTableIndex--]) != null) { return; } }
       */
      // Geode changes END

      while (this.currentSegmentIndex > 0) {
        final Segment<K, V> seg =
            CustomEntryConcurrentHashMap.this.segments[--this.currentSegmentIndex];
        if (seg.count != 0) {
          this.currentTable = seg.table;
          final ReentrantReadWriteLock.ReadLock listLock = seg.listUpdateLock.readLock();
          listLock.lock();
          try {
            for (int j = currentTable.length - 1; j >= 0; --j) {
              if ((this.nextEntry = currentTable[j]) != null) {
                this.nextTableIndex = j - 1;
                copyEntriesToList();
                return;
              }
            }
          } finally {
            listLock.unlock();
          }
        }
      }
    }

    // Geode added the method below
    /**
     * Copy the tail of list of current matched entry ({@link #nextEntry}) to a temporary list, so
     * that the read lock can be released after the copy.
     *
     * Read lock on {@link #currentSegmentIndex}'s listUpdateLock should already be acquired.
     */
    private void copyEntriesToList() {
      assert segments[currentSegmentIndex] != null : "unexpected null currentSegment";
      assert segments[currentSegmentIndex].listUpdateLock.getReadLockCount() > 0;

      this.currentList.clear();
      this.currentListIndex = 0;
      for (HashEntry<K, V> p = this.nextEntry.getNextEntry(); p != null; p = p.getNextEntry()) {
        this.currentList.add(p);
      }
    }

    public boolean hasNext() {
      return this.nextEntry != null;
    }

    HashEntry<K, V> nextEntry() {
      if (this.nextEntry == null) {
        throw new NoSuchElementException();
      }
      this.lastReturned = this.nextEntry;
      advance();
      return this.lastReturned;
    }

    public void remove() {
      if (this.lastReturned == null) {
        throw new IllegalStateException();
      }
      CustomEntryConcurrentHashMap.this.remove(this.lastReturned.getKey());
      this.lastReturned = null;
    }
  }

  class KeyIterator extends HashIterator implements Iterator<K>, Enumeration<K> {

    @Override
    public K next() {
      return super.nextEntry().getKey();
    }

    @Override
    public K nextElement() {
      return super.nextEntry().getKey();
    }
  }

  class ValueIterator extends HashIterator implements Iterator<V>, Enumeration<V> {

    @Override
    public V next() {
      return super.nextEntry().getMapValue();
    }

    @Override
    public V nextElement() {
      return super.nextEntry().getMapValue();
    }
  }

  /**
   * An Entry maintaining a key and a value. The value may be changed using the <tt>setValue</tt>
   * method. This class facilitates the process of building custom map implementations. For example,
   * it may be convenient to return arrays of <tt>SimpleEntry</tt> instances in method
   * <tt>Map.entrySet().toArray</tt>.
   */
  public class SimpleReusableEntry implements Map.Entry<K, V>, Serializable {

    private static final long serialVersionUID = 1591026397367910439L;

    protected K key; // Geode change; made non-final to enable reuse

    private V value;

    /**
     * Creates an entry representing a mapping from the specified key to the specified value.
     *
     * @param key the key represented by this entry
     * @param value the value represented by this entry
     */
    public SimpleReusableEntry(final K key, final V value) {
      this.key = key;
      this.value = value;
    }

    /**
     * Creates an entry representing the same mapping as the specified entry.
     *
     * @param entry the entry to copy
     */
    public SimpleReusableEntry(final Entry<? extends K, ? extends V> entry) {
      this.key = entry.getKey();
      this.value = entry.getValue();
    }

    /**
     * Returns the key corresponding to this entry.
     *
     * @return the key corresponding to this entry
     */
    @Override
    public K getKey() {
      return this.key;
    }

    /**
     * Returns the value corresponding to this entry.
     *
     * @return the value corresponding to this entry
     */
    @Override
    public V getValue() {
      return this.value;
    }

    /**
     * Replaces the value corresponding to this entry with the specified value.
     *
     * @param value new value to be stored in this entry
     * @return the old value corresponding to the entry
     */
    @Override
    public V setValue(final V value) {
      final V oldValue = this.value;
      this.value = value;
      return oldValue;
    }

    /**
     * Compares the specified object with this entry for equality. Returns {@code true} if the given
     * object is also a map entry and the two entries represent the same mapping. More formally, two
     * entries {@code e1} and {@code e2} represent the same mapping if
     *
     * <pre>
     * (e1.getKey() == null ? e2.getKey() == null : e1.getKey().equals(e2.getKey()))
     *     &amp;&amp; (e1.getValue() == null ? e2.getValue() == null : e1.getValue().equals(e2.getValue()))
     * </pre>
     *
     * This ensures that the {@code equals} method works properly across different implementations
     * of the {@code Map.Entry} interface.
     *
     * @param o object to be compared for equality with this map entry
     * @return {@code true} if the specified object is equal to this map entry
     * @see #hashCode
     */
    @Override
    public boolean equals(final Object o) {
      if (!(o instanceof Map.Entry<?, ?>)) {
        return false;
      }
      final Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
      if (CustomEntryConcurrentHashMap.this.compareValues) {
        return ArrayUtils.objectEquals(this.key, e.getKey())
            && ArrayUtils.objectEquals(this.value, e.getValue());
      }
      return this.key == e.getKey() && this.value == e.getValue();
    }

    /**
     * Returns the hash code value for this map entry. The hash code of a map entry {@code e} is
     * defined to be:
     *
     * <pre>
     * (e.getKey() == null ? 0 : e.getKey().hashCode())
     *     &circ; (e.getValue() == null ? 0 : e.getValue().hashCode())
     * </pre>
     *
     * This ensures that {@code e1.equals(e2)} implies that {@code e1.hashCode()==e2.hashCode()} for
     * any two Entries {@code e1} and {@code e2}, as required by the general contract of
     * {@link Object#hashCode}.
     *
     * @return the hash code value for this map entry
     * @see #equals
     */
    @Override
    public int hashCode() {
      if (CustomEntryConcurrentHashMap.this.compareValues) {
        return (this.key != null ? this.key.hashCode() : 0)
            ^ (this.value != null ? this.value.hashCode() : 0);
      }
      return System.identityHashCode(this.key) ^ System.identityHashCode(this.value);
    }

    /**
     * Returns a String representation of this map entry. This implementation returns the string
     * representation of this entry's key followed by the equals character ("<tt>=</tt>") followed
     * by the string representation of this entry's value.
     *
     * @return a String representation of this map entry
     */
    @Override
    public String toString() {
      return this.key + "=" + this.value;
    }
  }

  /**
   * Custom Entry class used by EntryIterator.next(), that relays setValue changes to the underlying
   * map.
   */
  class WriteThroughEntry extends SimpleReusableEntry {

    private static final long serialVersionUID = -6364816773849437756L;

    /**
     * Creates an entry representing a mapping from the specified key to the specified value.
     *
     * @param key the key represented by this entry
     * @param value the value represented by this entry
     */
    WriteThroughEntry(final K key, final V value) {
      super(key, value);
    }

    /**
     * Set our entry's value and write through to the map. The value to return is somewhat arbitrary
     * here. Since a WriteThroughEntry does not necessarily track asynchronous changes, the most
     * recent "previous" value could be different from what we return (or could even have been
     * removed in which case the put will re-establish). We do not and cannot guarantee more.
     */
    @Override
    public V setValue(final V value) {
      if (value == null) {
        throw new NullPointerException();
      }
      final V v = super.setValue(value);
      CustomEntryConcurrentHashMap.this.put(getKey(), value);
      return v;
    }
  }

  class EntryIterator extends HashIterator implements Iterator<Map.Entry<K, V>> {

    // Geode change
    // added possibility to reuse a single Map.Entry for entire iteration
    final WriteThroughEntry reusableEntry;

    EntryIterator(final WriteThroughEntry reusableEntry) {
      this.reusableEntry = reusableEntry;
    }

    @Override
    public Map.Entry<K, V> next() {
      final HashEntry<K, V> e = super.nextEntry();
      if (this.reusableEntry != null) {
        this.reusableEntry.key = e.getKey();
        this.reusableEntry.setValue(e.getMapValue());
        return this.reusableEntry;
      }
      return new WriteThroughEntry(e.getKey(), e.getMapValue());
    }
    // End Geode change
  }

  class KeySet extends AbstractSet<K> {

    @Override
    public Iterator<K> iterator() {
      return new KeyIterator();
    }

    @Override
    public int size() {
      return CustomEntryConcurrentHashMap.this.size();
    }

    @Override
    public boolean contains(final Object o) {
      return CustomEntryConcurrentHashMap.this.containsKey(o);
    }

    @Override
    public boolean remove(final Object o) {
      return CustomEntryConcurrentHashMap.this.remove(o) != null;
    }

    @Override
    public void clear() {
      CustomEntryConcurrentHashMap.this.clear();
    }
  }

  class Values extends AbstractCollection<V> {

    @Override
    public Iterator<V> iterator() {
      return new ValueIterator();
    }

    @Override
    public int size() {
      return CustomEntryConcurrentHashMap.this.size();
    }

    @Override
    public boolean contains(final Object o) {
      return CustomEntryConcurrentHashMap.this.containsValue(o);
    }

    @Override
    public void clear() {
      CustomEntryConcurrentHashMap.this.clear();
    }
  }

  class EntrySet extends AbstractSet<Map.Entry<K, V>> {

    // Geode change
    // added possibility to reuse a single Map.Entry for entire iteration
    final WriteThroughEntry reusableEntry;

    EntrySet(final boolean useReusableEntry) {
      if (useReusableEntry) {
        this.reusableEntry = new WriteThroughEntry(null, null);
      } else {
        this.reusableEntry = null;
      }
    }

    @Override
    public Iterator<Map.Entry<K, V>> iterator() {
      return new EntryIterator(this.reusableEntry);
    }

    // End Geode change

    @Override
    public boolean contains(final Object o) {
      if (!(o instanceof Map.Entry)) {
        return false;
      }
      final Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
      final V v = CustomEntryConcurrentHashMap.this.get(e.getKey());
      if (CustomEntryConcurrentHashMap.this.compareValues) {
        return v != null && v.equals(e.getValue());
      }
      return v == e.getValue();
    }

    @Override
    public boolean remove(final Object o) {
      if (!(o instanceof Map.Entry)) {
        return false;
      }
      final Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
      return CustomEntryConcurrentHashMap.this.remove(e.getKey(), e.getValue());
    }

    @Override
    public int size() {
      return CustomEntryConcurrentHashMap.this.size();
    }

    @Override
    public void clear() {
      CustomEntryConcurrentHashMap.this.clear();
    }
  }

  /* ---------------- Serialization Support -------------- */

  /**
   * Save the state of the <tt>ConcurrentHashMap</tt> instance to a stream (i.e., serialize it).
   *
   * @param s the stream
   * @serialData the key (Object) and value (Object) for each key-value mapping, followed by a null
   *             pair. The key-value mappings are emitted in no particular order.
   */
  private void writeObject(final java.io.ObjectOutputStream s) throws IOException {
    s.defaultWriteObject();

    for (int k = 0; k < this.segments.length; ++k) {
      final Segment<K, V> seg = this.segments[k];
      final ReentrantReadWriteLock.ReadLock readLock = seg.readLock();
      readLock.lock();
      try {
        final HashEntry<K, V>[] tab = seg.table;
        for (int i = 0; i < tab.length; ++i) {
          for (HashEntry<K, V> e = tab[i]; e != null; e = e.getNextEntry()) {
            s.writeObject(e.getKey());
            s.writeObject(e.getMapValue());
          }
        }
      } finally {
        readLock.unlock();
      }
    }
    s.writeObject(null);
    s.writeObject(null);
  }

  /**
   * Reconstitute the <tt>ConcurrentHashMap</tt> instance from a stream (i.e., deserialize it).
   *
   * @param s the stream
   */
  @SuppressWarnings("unchecked")
  private void readObject(final java.io.ObjectInputStream s)
      throws IOException, ClassNotFoundException {
    s.defaultReadObject();

    // Initialize each segment to be minimally sized, and let grow.
    for (int i = 0; i < this.segments.length; ++i) {
      this.segments[i].setTable(new HashEntry[1]);
    }

    // Read the keys and values, and put the mappings in the table
    for (;;) {
      final K key = (K) s.readObject();
      final V value = (V) s.readObject();
      if (key == null) {
        break;
      }
      put(key, value);
    }
  }

  public long estimateMemoryOverhead(SingleObjectSizer sizer) {

    long totalOverhead = sizer.sizeof(this);
    for (int i = 0; i < this.segments.length; ++i) {
      final Segment<K, V> seg = this.segments[i];
      totalOverhead += sizer.sizeof(seg);
    }

    return totalOverhead;
  }
}
