/*
 * 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.cache;

import static org.apache.geode.internal.cache.LocalRegion.InitializationLevel.AFTER_INITIAL_IMAGE;
import static org.apache.geode.internal.cache.LocalRegion.InitializationLevel.ANY_INIT;
import static org.apache.geode.internal.cache.LocalRegion.InitializationLevel.BEFORE_INITIAL_IMAGE;
import static org.apache.geode.internal.lang.SystemUtils.getLineSeparator;
import static org.apache.geode.internal.offheap.annotations.OffHeapIdentifier.ENTRY_EVENT_NEW_VALUE;
import static org.apache.geode.util.internal.UncheckedUtils.uncheckedCast;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.regex.Pattern;

import javax.transaction.RollbackException;
import javax.transaction.Status;
import javax.transaction.SystemException;
import javax.transaction.Transaction;

import org.apache.logging.log4j.Logger;

import org.apache.geode.CancelCriterion;
import org.apache.geode.CancelException;
import org.apache.geode.CopyHelper;
import org.apache.geode.DataSerializable;
import org.apache.geode.DataSerializer;
import org.apache.geode.Delta;
import org.apache.geode.DeltaSerializationException;
import org.apache.geode.InternalGemFireError;
import org.apache.geode.InternalGemFireException;
import org.apache.geode.LogWriter;
import org.apache.geode.Statistics;
import org.apache.geode.SystemFailure;
import org.apache.geode.admin.internal.SystemMemberCacheEventProcessor;
import org.apache.geode.annotations.Immutable;
import org.apache.geode.annotations.VisibleForTesting;
import org.apache.geode.annotations.internal.MakeNotStatic;
import org.apache.geode.cache.AttributesMutator;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.CacheClosedException;
import org.apache.geode.cache.CacheEvent;
import org.apache.geode.cache.CacheException;
import org.apache.geode.cache.CacheListener;
import org.apache.geode.cache.CacheLoader;
import org.apache.geode.cache.CacheLoaderException;
import org.apache.geode.cache.CacheRuntimeException;
import org.apache.geode.cache.CacheWriter;
import org.apache.geode.cache.CacheWriterException;
import org.apache.geode.cache.CustomExpiry;
import org.apache.geode.cache.DataPolicy;
import org.apache.geode.cache.DiskAccessException;
import org.apache.geode.cache.DiskStoreFactory;
import org.apache.geode.cache.DiskWriteAttributes;
import org.apache.geode.cache.DiskWriteAttributesFactory;
import org.apache.geode.cache.EntryDestroyedException;
import org.apache.geode.cache.EntryExistsException;
import org.apache.geode.cache.EntryNotFoundException;
import org.apache.geode.cache.EvictionAttributes;
import org.apache.geode.cache.ExpirationAttributes;
import org.apache.geode.cache.FailedSynchronizationException;
import org.apache.geode.cache.InterestRegistrationEvent;
import org.apache.geode.cache.InterestResultPolicy;
import org.apache.geode.cache.LoaderHelper;
import org.apache.geode.cache.LowMemoryException;
import org.apache.geode.cache.Operation;
import org.apache.geode.cache.PartitionedRegionStorageException;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionAttributes;
import org.apache.geode.cache.RegionDestroyedException;
import org.apache.geode.cache.RegionEvent;
import org.apache.geode.cache.RegionExistsException;
import org.apache.geode.cache.RegionReinitializedException;
import org.apache.geode.cache.Scope;
import org.apache.geode.cache.TimeoutException;
import org.apache.geode.cache.TransactionException;
import org.apache.geode.cache.TransactionId;
import org.apache.geode.cache.client.PoolManager;
import org.apache.geode.cache.client.ServerOperationException;
import org.apache.geode.cache.client.SubscriptionNotEnabledException;
import org.apache.geode.cache.client.internal.Connection;
import org.apache.geode.cache.client.internal.Endpoint;
import org.apache.geode.cache.client.internal.PoolImpl;
import org.apache.geode.cache.client.internal.ServerRegionProxy;
import org.apache.geode.cache.control.ResourceManager;
import org.apache.geode.cache.execute.Function;
import org.apache.geode.cache.execute.ResultCollector;
import org.apache.geode.cache.partition.PartitionRegionHelper;
import org.apache.geode.cache.persistence.ConflictingPersistentDataException;
import org.apache.geode.cache.query.FunctionDomainException;
import org.apache.geode.cache.query.Index;
import org.apache.geode.cache.query.IndexMaintenanceException;
import org.apache.geode.cache.query.IndexType;
import org.apache.geode.cache.query.MultiIndexCreationException;
import org.apache.geode.cache.query.NameResolutionException;
import org.apache.geode.cache.query.QueryException;
import org.apache.geode.cache.query.QueryInvalidException;
import org.apache.geode.cache.query.QueryInvocationTargetException;
import org.apache.geode.cache.query.QueryService;
import org.apache.geode.cache.query.SelectResults;
import org.apache.geode.cache.query.TypeMismatchException;
import org.apache.geode.cache.query.internal.DefaultQuery;
import org.apache.geode.cache.query.internal.DefaultQueryService;
import org.apache.geode.cache.query.internal.ExecutionContext;
import org.apache.geode.cache.query.internal.cq.CqService;
import org.apache.geode.cache.query.internal.index.IndexCreationData;
import org.apache.geode.cache.query.internal.index.IndexManager;
import org.apache.geode.cache.query.internal.index.IndexProtocol;
import org.apache.geode.cache.query.internal.index.IndexUtils;
import org.apache.geode.cache.util.ObjectSizer;
import org.apache.geode.cache.wan.GatewaySender;
import org.apache.geode.distributed.DistributedMember;
import org.apache.geode.distributed.internal.DistributionAdvisor;
import org.apache.geode.distributed.internal.DistributionManager;
import org.apache.geode.distributed.internal.DistributionStats;
import org.apache.geode.distributed.internal.InternalDistributedSystem;
import org.apache.geode.distributed.internal.ResourceEvent;
import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
import org.apache.geode.internal.Assert;
import org.apache.geode.internal.ClassLoadUtil;
import org.apache.geode.internal.HeapDataOutputStream;
import org.apache.geode.internal.cache.CacheDistributionAdvisor.CacheProfile;
import org.apache.geode.internal.cache.DiskInitFile.DiskRegionFlag;
import org.apache.geode.internal.cache.FilterRoutingInfo.FilterInfo;
import org.apache.geode.internal.cache.InitialImageOperation.GIIStatus;
import org.apache.geode.internal.cache.PutAllPartialResultException.PutAllPartialResult;
import org.apache.geode.internal.cache.RegionMap.ARMLockTestHook;
import org.apache.geode.internal.cache.control.InternalResourceManager;
import org.apache.geode.internal.cache.control.InternalResourceManager.ResourceType;
import org.apache.geode.internal.cache.control.MemoryEvent;
import org.apache.geode.internal.cache.control.MemoryThresholds;
import org.apache.geode.internal.cache.control.ResourceListener;
import org.apache.geode.internal.cache.entries.DiskEntry;
import org.apache.geode.internal.cache.event.EventTracker;
import org.apache.geode.internal.cache.event.NonDistributedEventTracker;
import org.apache.geode.internal.cache.eviction.EvictableEntry;
import org.apache.geode.internal.cache.eviction.EvictionController;
import org.apache.geode.internal.cache.eviction.EvictionCounters;
import org.apache.geode.internal.cache.execute.DistributedRegionFunctionExecutor;
import org.apache.geode.internal.cache.execute.DistributedRegionFunctionResultSender;
import org.apache.geode.internal.cache.execute.LocalResultCollector;
import org.apache.geode.internal.cache.execute.RegionFunctionContextImpl;
import org.apache.geode.internal.cache.execute.ServerToClientFunctionResultSender;
import org.apache.geode.internal.cache.ha.ThreadIdentifier;
import org.apache.geode.internal.cache.partitioned.Bucket;
import org.apache.geode.internal.cache.partitioned.RedundancyAlreadyMetException;
import org.apache.geode.internal.cache.partitioned.colocation.ColocationLoggerFactory;
import org.apache.geode.internal.cache.persistence.DefaultDiskDirs;
import org.apache.geode.internal.cache.persistence.DiskRegionView;
import org.apache.geode.internal.cache.persistence.PersistentMemberID;
import org.apache.geode.internal.cache.persistence.query.IndexMap;
import org.apache.geode.internal.cache.persistence.query.mock.IndexMapImpl;
import org.apache.geode.internal.cache.tier.InterestType;
import org.apache.geode.internal.cache.tier.sockets.CacheClientNotifier;
import org.apache.geode.internal.cache.tier.sockets.ClientHealthMonitor;
import org.apache.geode.internal.cache.tier.sockets.ClientProxyMembershipID;
import org.apache.geode.internal.cache.tier.sockets.ClientTombstoneMessage;
import org.apache.geode.internal.cache.tier.sockets.ClientUpdateMessage;
import org.apache.geode.internal.cache.tier.sockets.VersionedObjectList;
import org.apache.geode.internal.cache.versions.ConcurrentCacheModificationException;
import org.apache.geode.internal.cache.versions.RegionVersionHolder;
import org.apache.geode.internal.cache.versions.RegionVersionVector;
import org.apache.geode.internal.cache.versions.VersionSource;
import org.apache.geode.internal.cache.versions.VersionStamp;
import org.apache.geode.internal.cache.versions.VersionTag;
import org.apache.geode.internal.cache.wan.AbstractGatewaySender;
import org.apache.geode.internal.lang.SystemPropertyHelper;
import org.apache.geode.internal.logging.log4j.LogMarker;
import org.apache.geode.internal.offheap.OffHeapHelper;
import org.apache.geode.internal.offheap.ReferenceCountHelper;
import org.apache.geode.internal.offheap.Releasable;
import org.apache.geode.internal.offheap.StoredObject;
import org.apache.geode.internal.offheap.annotations.Released;
import org.apache.geode.internal.offheap.annotations.Retained;
import org.apache.geode.internal.offheap.annotations.Unretained;
import org.apache.geode.internal.sequencelog.EntryLogger;
import org.apache.geode.internal.serialization.KnownVersion;
import org.apache.geode.internal.statistics.StatisticsClock;
import org.apache.geode.internal.util.concurrent.CopyOnWriteHashMap;
import org.apache.geode.internal.util.concurrent.FutureResult;
import org.apache.geode.internal.util.concurrent.StoppableCountDownLatch;
import org.apache.geode.logging.internal.log4j.api.LogService;
import org.apache.geode.pdx.JSONFormatter;
import org.apache.geode.pdx.PdxInstance;
import org.apache.geode.util.internal.GeodeGlossary;

/**
 * Implementation of a local scoped-region. Note that this class has a different meaning starting
 * with 3.0. In previous versions, a LocalRegion was the representation of a region in the VM.
 * Starting with 3.0, a LocalRegion is a non-distributed region. The subclass DistributedRegion adds
 * distribution behavior.
 */
public class LocalRegion extends AbstractRegion implements LoaderHelperFactory,
    ResourceListener<MemoryEvent>, InternalPersistentRegion {

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

  @Override
  public boolean isRegionInvalid() {
    return regionInvalid;
  }

  /**
   * Set to true after an invalidate region expiration so we don't get multiple expirations
   */
  @Override
  public void setRegionInvalid(boolean regionInvalid) {
    this.regionInvalid = regionInvalid;
  }

  /**
   * Prevents access to this region until it is done initializing, except for some special
   * initializing operations such as replying to create region messages In JDK 1.5 we will use
   * java.util.concurrent.CountDownLatch instead of org.apache.geode.internal.util.CountDownLatch.
   */
  @Override
  public StoppableCountDownLatch getInitializationLatchBeforeGetInitialImage() {
    return initializationLatchBeforeGetInitialImage;
  }

  @Override
  public StoppableCountDownLatch getInitializationLatchAfterGetInitialImage() {
    return initializationLatchAfterGetInitialImage;
  }

  // initialization level
  public enum InitializationLevel {
    AFTER_INITIAL_IMAGE, BEFORE_INITIAL_IMAGE, ANY_INIT
  }

  /**
   * thread local to indicate that this thread should bypass the initialization Latch
   */
  private static final ThreadLocal<InitializationLevel> initializationThread =
      ThreadLocal.withInitial(() -> AFTER_INITIAL_IMAGE);

  private Object regionUserAttribute;

  private final Map<Object, Object> entryUserAttributes = new ConcurrentHashMap<>();

  private final String regionName;

  private final LocalRegion parentRegion;

  /**
   * set to true only if isDestroyed is also true and region is about to be recreated due to
   * reinitialization by loading of a snapshot, etc.
   */
  private volatile boolean reinitialized_old;

  protected volatile boolean isDestroyed;

  /**
   * In case of parallel wan, when a destroy is called on userPR, it waits for parallelQueue to
   * drain and then destroys parallelQueue. In this time if operation like put happens on userPR
   * then it will keep on building parallel queue increasing time of userPR to get destroyed.this
   * volatile boolean will block such put operation by throwing RegionDestroyedException
   */
  volatile boolean isDestroyedForParallelWAN;

  /**
   * set to true after snapshot is loaded, to help get initial image make sure this is the right
   * incarnation of this region
   */
  private volatile boolean reinitialized_new;

  /**
   * Lock used to prevent multiple concurrent destroy region operations
   */
  private Semaphore destroyLock;

  /**
   * GuardedBy regionExpiryLock.
   */
  private RegionTTLExpiryTask regionTTLExpiryTask;

  /**
   * GuardedBy regionExpiryLock.
   */
  private RegionIdleExpiryTask regionIdleExpiryTask;

  private final Object regionExpiryLock = new Object();

  /**
   * GuardedBy regionExpiryLock. Keeps track of how many txs are writing to this region.
   */
  private int txRefCount;

  private volatile boolean regionInvalid;

  /**
   * TODO: make this private and introduce wrappers
   */
  public final RegionMap entries;

  /**
   * Set to true if this region supports transaction else false.
   */
  private final boolean supportsTX;

  /**
   * tracks region-level version information for members
   */
  private final RegionVersionVector versionVector;

  private static final Pattern[] QUERY_PATTERNS = new Pattern[] {
      Pattern.compile("^\\(*select .*",
          Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE | Pattern.DOTALL),
      Pattern.compile("^import .*",
          Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE | Pattern.DOTALL)};

  public static final String EXPIRY_MS_PROPERTY =
      GeodeGlossary.GEMFIRE_PREFIX + "EXPIRY_UNITS_MS";

  /**
   * Used by unit tests to set expiry to milliseconds instead of the default seconds. Used in
   * ExpiryTask.
   *
   * @since GemFire 5.0
   */
  @VisibleForTesting
  final boolean EXPIRY_UNITS_MS;

  private final EntryEventFactory entryEventFactory;
  private final RegionMapConstructor regionMapConstructor;

  /**
   * contains Regions themselves // marked volatile to make sure it is fully initialized before
   * being // accessed; (actually should be final)
   */
  private final ConcurrentMap subregions;

  private final Object subregionsLock = new Object();

  private final StoppableCountDownLatch initializationLatchBeforeGetInitialImage;

  private final StoppableCountDownLatch initializationLatchAfterGetInitialImage;

  /**
   * Used to hold off cache listener events until the afterRegionCreate is called
   *
   * @since GemFire 5.0
   */
  private final StoppableCountDownLatch afterRegionCreateEventLatch;

  /**
   * Set to true the first time isInitialized returns true.
   */
  private volatile boolean initialized;

  /**
   * Used for accessing region data on disk
   */
  private final DiskRegion diskRegion;

  /**
   * Used for serializing netSearch and netLoad on a per key basis. CM <Object, Future>
   */
  private final ConcurrentMap getFutures = new ConcurrentHashMap();

  /**
   * TODO: This boolean needs to be made true if the test needs to receive a synchronous callback
   * just after clear on map is done. Its visibility is default so that only tests present in
   * org.apache.geode.internal.cache will be able to see it
   */
  @MakeNotStatic("This is modified in production code")
  public static boolean ISSUE_CALLBACKS_TO_CACHE_OBSERVER;

  /**
   * A flag used to indicate that this Region is being used as an administrative Region, holding
   * meta-data for a PartitionedRegion
   */
  private final boolean isUsedForPartitionedRegionAdmin;

  private final boolean isUsedForPartitionedRegionBucket;

  private final boolean isUsedForMetaRegion;

  private final boolean isMetaRegionWithTransactions;

  private final boolean isUsedForSerialGatewaySenderQueue;

  private final boolean isUsedForParallelGatewaySenderQueue;

  private final AbstractGatewaySender serialGatewaySender;

  /**
   * The factory used to create the LoaderHelper when a loader is invoked
   */
  final LoaderHelperFactory loaderHelperFactory;

  /**
   * Allow for different CachePerfStats locations... primarily for PartitionedRegions
   */
  private final CachePerfStats cachePerfStats;

  private final boolean hasOwnStats;

  private final ImageState imageState;

  private final EventTracker eventTracker;

  /**
   * Register interest count to track if any register interest is in progress for this region. This
   * count will be incremented when register interest starts and decremented when register interest
   * finishes.
   * <p>
   * since always written while holding an exclusive write lock and only read while holding a read
   * lock it does not need to be atomic or protected by any other sync.
   * <p>
   * GuardedBy {@link #imageState}
   */
  private int riCnt;

  /**
   * Map of subregion full paths to serial numbers. These are subregions that were destroyed when
   * this region was destroyed. This map remains null until this region is destroyed.
   */
  private volatile HashMap destroyedSubregionSerialNumbers;

  /**
   * This boolean is true when a member who has this region is running low on memory. It is used to
   * reject region operations.
   */
  private final AtomicBoolean memoryThresholdReached = new AtomicBoolean(false);

  /**
   * Lock for updating PR MetaData on client side
   * <p>
   * TODO: move this to ClientMetadataService into {@code Map<Region, Lock>}
   */
  private final Lock clientMetaDataLock = new ReentrantLock();

  /**
   * Lock for updating the cache service profile for the region.
   */
  private final Lock cacheServiceProfileUpdateLock = new ReentrantLock();

  public void executeSynchronizedOperationOnCacheProfiles(Runnable operation) {
    cacheServiceProfileUpdateLock.lock();
    try {
      operation.run();
    } finally {
      cacheServiceProfileUpdateLock.unlock();
    }
  }

  private final CancelCriterion stopper = createStopper();

  private CancelCriterion createStopper() {
    return new Stopper();
  }

  private final TestCallable testCallable;

  /**
   * ThreadLocal used to set the current region being initialized.
   *
   * Currently used by the OpLog layer.
   */
  private static final ThreadLocal<LocalRegion> initializingRegion = new ThreadLocal<>();

  /**
   * Get the current initializing region as set in the ThreadLocal.
   *
   * Note that this value is cleared after the initialization of LocalRegion is done so is valid
   * only for the duration of region creation and initialization.
   */
  static LocalRegion getInitializingRegion() {
    return initializingRegion.get();
  }

  @Override
  public CancelCriterion getCancelCriterion() {
    return stopper;
  }

  private final CopyOnWriteHashMap<String, CacheServiceProfile> cacheServiceProfiles =
      new CopyOnWriteHashMap<>();

  private static String calcFullPath(String regionName, Region parentRegion) {
    StringBuilder buf;
    if (parentRegion == null) {
      buf = new StringBuilder(regionName.length() + 1);
    } else {
      String parentFull = parentRegion.getFullPath();
      buf = new StringBuilder(parentFull.length() + regionName.length() + 1);
      buf.append(parentFull);
    }
    buf.append(Region.SEPARATOR).append(regionName);
    return buf.toString();
  }

  protected LocalRegion(String regionName, RegionAttributes attrs, LocalRegion parentRegion,
      InternalCache cache, InternalRegionArguments internalRegionArgs,
      StatisticsClock statisticsClock) throws DiskAccessException {
    this(regionName, attrs, parentRegion, cache, internalRegionArgs, new LocalRegionDataView(),
        statisticsClock);
  }

  protected LocalRegion(String regionName, RegionAttributes attrs, LocalRegion parentRegion,
      InternalCache cache, InternalRegionArguments internalRegionArgs,
      InternalDataView internalDataView, StatisticsClock statisticsClock)
      throws DiskAccessException {
    this(regionName, attrs, parentRegion, cache, internalRegionArgs, internalDataView,
        RegionMapFactory::createVM, new DefaultServerRegionProxyConstructor(),
        new DefaultEntryEventFactory(), poolName -> (PoolImpl) PoolManager.find(poolName),
        (LocalRegion region) -> new RegionPerfStats(
            cache.getInternalDistributedSystem().getStatisticsManager(),
            "RegionStats-" + regionName, cache.getCachePerfStats(),
            region, cache.getMeterRegistry(), statisticsClock),
        statisticsClock);
  }

  @VisibleForTesting
  LocalRegion(String regionName, RegionAttributes attrs, LocalRegion parentRegion,
      InternalCache cache, InternalRegionArguments internalRegionArgs,
      InternalDataView internalDataView, RegionMapConstructor regionMapConstructor,
      ServerRegionProxyConstructor serverRegionProxyConstructor,
      EntryEventFactory entryEventFactory, PoolFinder poolFinder,
      java.util.function.Function<LocalRegion, RegionPerfStats> regionPerfStatsFactory,
      StatisticsClock statisticsClock)
      throws DiskAccessException {
    super(cache, attrs, regionName, internalRegionArgs, poolFinder, statisticsClock);

    this.regionMapConstructor = regionMapConstructor;
    this.entryEventFactory = entryEventFactory;

    EXPIRY_UNITS_MS = parentRegion != null ? parentRegion.EXPIRY_UNITS_MS
        : Boolean.getBoolean(EXPIRY_MS_PROPERTY);

    Assert.assertTrue(regionName != null, "regionName must not be null");
    sharedDataView = internalDataView;
    this.regionName = regionName;
    this.parentRegion = parentRegion;
    fullPath = calcFullPath(regionName, parentRegion);

    String myName = getFullPath();
    if (internalRegionArgs.getPartitionedRegion() != null) {
      myName = internalRegionArgs.getPartitionedRegion().getFullPath();
    }
    offHeap = attrs.getOffHeap() || Boolean.getBoolean(myName + ":OFF_HEAP");
    if (getOffHeap()) {
      if (cache.getOffHeapStore() == null) {
        throw new IllegalStateException(
            String.format(
                "The region %s was configured to use off heap memory but no off heap memory was configured",
                myName));
      }
    }

    initializationLatchBeforeGetInitialImage = new StoppableCountDownLatch(stopper, 1);
    initializationLatchAfterGetInitialImage = new StoppableCountDownLatch(stopper, 1);
    afterRegionCreateEventLatch = new StoppableCountDownLatch(stopper, 1);

    if (internalRegionArgs.getUserAttribute() != null) {
      setUserAttribute(internalRegionArgs.getUserAttribute());
    }
    initializingRegion.set(this);

    diskStoreImpl = findDiskStore(attrs, internalRegionArgs);
    diskRegion = createDiskRegion(internalRegionArgs);
    entries = createRegionMap(internalRegionArgs);
    subregions = new ConcurrentHashMap();

    if (internalRegionArgs.getCachePerfStatsHolder() != null) {
      HasCachePerfStats cachePerfStatsHolder = internalRegionArgs.getCachePerfStatsHolder();
      hasOwnStats = cachePerfStatsHolder.hasOwnStats();
      cachePerfStats = cachePerfStatsHolder.getCachePerfStats();
    } else {
      if (attrs.getPartitionAttributes() != null || isInternalRegion()
          || internalRegionArgs.isUsedForMetaRegion()) {
        hasOwnStats = false;
        cachePerfStats = cache.getCachePerfStats();
      } else {
        hasOwnStats = true;
        cachePerfStats = regionPerfStatsFactory.apply(this);
      }
    }

    // we only need a destroy lock if this is a root
    if (parentRegion == null) {
      initRoot();
    }

    if (internalRegionArgs.getLoaderHelperFactory() != null) {
      loaderHelperFactory = internalRegionArgs.getLoaderHelperFactory();
    } else {
      loaderHelperFactory = this;
    }

    isUsedForPartitionedRegionAdmin = internalRegionArgs.isUsedForPartitionedRegionAdmin();
    isUsedForPartitionedRegionBucket = internalRegionArgs.isUsedForPartitionedRegionBucket();
    isUsedForMetaRegion = internalRegionArgs.isUsedForMetaRegion();
    isMetaRegionWithTransactions = internalRegionArgs.isMetaRegionWithTransactions();
    isUsedForSerialGatewaySenderQueue = internalRegionArgs.isUsedForSerialGatewaySenderQueue();
    isUsedForParallelGatewaySenderQueue =
        internalRegionArgs.isUsedForParallelGatewaySenderQueue();
    serialGatewaySender = internalRegionArgs.getSerialGatewaySender();
    if (internalRegionArgs.getCacheServiceProfiles() != null) {
      addCacheServiceProfiles(internalRegionArgs);
    }

    if (!isUsedForMetaRegion && !isUsedForPartitionedRegionAdmin
        && !isUsedForPartitionedRegionBucket && !isUsedForSerialGatewaySenderQueue
        && !isUsedForParallelGatewaySenderQueue) {
      filterProfile = new FilterProfile(this);
    }

    // initialize client to server proxy
    serverRegionProxy =
        getPoolName() != null ? serverRegionProxyConstructor.create(this) : null;
    imageState = new UnsharedImageState(getPoolName() != null,
        getDataPolicy().withReplication() || getDataPolicy().isPreloaded(),
        getAttributes().getDataPolicy().withPersistence(), stopper);

    // prevent internal regions from participating in a TX
    supportsTX = !isSecret() && !isUsedForPartitionedRegionAdmin() && !isUsedForMetaRegion()
        || isMetaRegionWithTransactions();

    testCallable = internalRegionArgs.getTestCallable();
    eventTracker = createEventTracker();

    versionVector = createRegionVersionVector();
  }

  private void addCacheServiceProfiles(InternalRegionArguments internalRegionArgs) {
    cacheServiceProfileUpdateLock.lock();
    try {
      cacheServiceProfiles.putAll(internalRegionArgs.getCacheServiceProfiles());
    } finally {
      cacheServiceProfileUpdateLock.unlock();
    }
  }

  protected EventTracker createEventTracker() {
    return NonDistributedEventTracker.getInstance();
  }

  private RegionMap createRegionMap(InternalRegionArguments internalRegionArgs) {
    RegionMap result = null;
    if (diskRegion != null) {
      result = diskRegion.useExistingRegionMap(this);
    }
    if (result == null) {
      RegionMap.Attributes ma = new RegionMap.Attributes();
      ma.statisticsEnabled = statisticsEnabled;
      ma.loadFactor = loadFactor;
      ma.initialCapacity = initialCapacity;
      ma.concurrencyLevel = concurrencyLevel;
      result = regionMapConstructor.create(this, ma, internalRegionArgs);
    }
    return result;
  }

  /**
   * Other region classes may track events using different mechanisms than EventTrackers or may not
   * track events at all
   */
  public EventTracker getEventTracker() {
    return eventTracker;
  }

  /**
   * returns the regions version-vector
   */
  @Override
  public RegionVersionVector getVersionVector() {
    return versionVector;
  }

  /**
   * returns object used to guard the size() operation during tombstone removal
   */
  Object getSizeGuard() {
    if (!getConcurrencyChecksEnabled()) {
      return new Object();
    }
    return fullPath; // avoids creating another sync object - could be anything unique to
    // this region
  }

  protected RegionVersionVector createRegionVersionVector() {
    if (getConcurrencyChecksEnabled()) {
      return createVersionVector();
    }
    return null;
  }

  /**
   * initializes a new version vector for this region
   */
  private RegionVersionVector createVersionVector() {
    RegionVersionVector regionVersionVector = RegionVersionVector.create(getVersionMember(), this);

    if (getDataPolicy().withPersistence()) {
      // copy the versions that we have recovered from disk into
      // the version vector.
      RegionVersionVector diskVector = diskRegion.getRegionVersionVector();
      regionVersionVector.recordVersions(diskVector.getCloneForTransmission());
    } else if (!getDataPolicy().withStorage()) {
      // version vectors are currently only necessary in empty regions for
      // tracking canonical member IDs
      regionVersionVector.turnOffRecordingForEmptyRegion();
    }
    if (serverRegionProxy != null) {
      regionVersionVector.setIsClientVector();
    }
    cache.getDistributionManager().addMembershipListener(regionVersionVector);
    return regionVersionVector;
  }

  @Override
  protected void updateEntryExpiryPossible() {
    super.updateEntryExpiryPossible();
    if (!isEntryExpiryPossible()) {
      // since expiration is no longer possible cleanup the tasks
      cancelAllEntryExpiryTasks();
    }
  }

  boolean isCacheClosing() {
    return cache.isClosed();
  }

  @Override
  public RegionEntry getRegionEntry(Object key) {
    return entries.getEntry(key);
  }

  /**
   * Test hook - returns the version stamp for an entry in the form of a version tag
   *
   * @return the entry version information
   */
  @Override
  public VersionTag getVersionTag(Object key) {
    Region.Entry entry = getEntry(key, true);
    VersionTag tag = null;
    if (entry instanceof EntrySnapshot) {
      tag = ((EntrySnapshot) entry).getVersionTag();
    } else if (entry instanceof NonTXEntry) {
      tag = ((NonTXEntry) entry).getRegionEntry().getVersionStamp().asVersionTag();
    }
    return tag;
  }

  /**
   * removes any destroyed entries from the region and clear the destroyedKeys assert: Caller must
   * be holding writeLock on is
   */
  private void destroyEntriesAndClearDestroyedKeysSet() {
    ImageState imageState = getImageState();
    Iterator iterator = imageState.getDestroyedEntries();
    while (iterator.hasNext()) {
      Object key = iterator.next();
      // destroy the entry which has value Token.DESTROYED
      // If it is Token.DESTROYED then only destroy it.
      entries.removeIfDestroyed(key);
    }
  }

  /**
   * @since GemFire 5.7
   */
  private final ServerRegionProxy serverRegionProxy;

  private final InternalDataView sharedDataView;

  @Override
  public ServerRegionProxy getServerProxy() {
    return serverRegionProxy;
  }

  @Override
  public boolean hasServerProxy() {
    return serverRegionProxy != null;
  }

  /**
   * Returns true if the ExpiryTask is currently allowed to expire.
   */
  protected boolean isExpirationAllowed(ExpiryTask expiry) {
    return true;
  }

  void performExpiryTimeout(ExpiryTask expiryTask) throws CacheException {
    if (expiryTask != null) {
      expiryTask.basicPerformTimeout(false);
    }
  }

  private void initRoot() {
    destroyLock = new Semaphore(1);
  }

  public void handleMarker() {
    RegionEventImpl event = new RegionEventImpl(this, Operation.MARKER, null, false, getMyId(),
        false /* generate EventID */);

    dispatchListenerEvent(EnumListenerEvent.AFTER_REGION_LIVE, event);
  }

  @Override
  public AttributesMutator getAttributesMutator() {
    checkReadiness();
    return this;
  }

  @Override
  public Region createSubregion(String subregionName, RegionAttributes aRegionAttributes)
      throws RegionExistsException, TimeoutException {
    try {
      return createSubregion(subregionName, aRegionAttributes,
          new InternalRegionArguments().setDestroyLockFlag(true).setRecreateFlag(false));
    } catch (IOException | ClassNotFoundException e) {
      // only happens when loading a snapshot, not here
      throw new InternalGemFireError(
          "unexpected exception", e);
    }
  }

  /**
   * Returns the member id of my distributed system
   *
   * @since GemFire 5.0
   */
  @Override
  public InternalDistributedMember getMyId() {
    return cache.getInternalDistributedSystem().getDistributedMember();
  }

  @Override
  public VersionSource getVersionMember() {
    if (getDataPolicy().withPersistence()) {
      return getDiskStore().getDiskStoreID();
    }
    return cache.getInternalDistributedSystem().getDistributedMember();
  }

  // TODO: createSubregion method is too complex for IDE to analyze
  @Override
  public Region createSubregion(String subregionName, RegionAttributes regionAttributes,
      InternalRegionArguments internalRegionArgs)
      throws RegionExistsException, TimeoutException, IOException, ClassNotFoundException {

    checkReadiness();
    cache.invokeRegionBefore(this, subregionName, regionAttributes, internalRegionArgs);

    final InputStream snapshotInputStream = internalRegionArgs.getSnapshotInputStream();
    final boolean getDestroyLock = internalRegionArgs.getDestroyLockFlag();
    final InternalDistributedMember imageTarget = internalRegionArgs.getImageTarget();

    LocalRegion newRegion = null;
    try {
      if (getDestroyLock) {
        acquireDestroyLock();
      }
      LocalRegion existing;
      try {
        if (isDestroyed()) {
          if (reinitialized_old) {
            throw new RegionReinitializedException(toString(), getFullPath());
          }
          throw new RegionDestroyedException(toString(), getFullPath());
        }
        RegionNameValidation.validate(subregionName, internalRegionArgs);

        validateSubregionAttributes(regionAttributes);

        // lock down the subregionsLock
        // to prevent other threads from adding a region to it in toRegion
        // but don't wait on initialization while synchronized (distributed
        // deadlock)
        synchronized (subregionsLock) {

          existing = (LocalRegion) subregions.get(subregionName);

          if (existing == null) {
            if (regionAttributes.getScope().isDistributed()
                && internalRegionArgs.isUsedForPartitionedRegionBucket()) {
              final PartitionedRegion pr = internalRegionArgs.getPartitionedRegion();
              internalRegionArgs.setUserAttribute(pr.getUserAttribute());
              if (pr.isShadowPR()) {
                newRegion = new BucketRegionQueue(subregionName, regionAttributes, this, cache,
                    internalRegionArgs, getStatisticsClock());
              } else {
                newRegion = new BucketRegion(subregionName, regionAttributes, this, cache,
                    internalRegionArgs, getStatisticsClock());
              }
            } else if (regionAttributes.getPartitionAttributes() != null) {
              newRegion = new PartitionedRegion(subregionName, regionAttributes, this, cache,
                  internalRegionArgs, getStatisticsClock(), ColocationLoggerFactory.create());
            } else {
              boolean local = regionAttributes.getScope().isLocal();
              newRegion = local
                  ? new LocalRegion(subregionName, regionAttributes, this, cache,
                      internalRegionArgs, getStatisticsClock())
                  : new DistributedRegion(subregionName, regionAttributes, this, cache,
                      internalRegionArgs, getStatisticsClock());
            }
            Object previousValue = subregions.putIfAbsent(subregionName, newRegion);

            Assert.assertTrue(previousValue == null);

            Assert.assertTrue(!newRegion.isInitialized());

            if (logger.isDebugEnabled()) {
              logger.debug("Subregion created: {}", newRegion.getFullPath());
            }
            if (snapshotInputStream != null || imageTarget != null
                || internalRegionArgs.getRecreateFlag()) {
              cache.regionReinitialized(newRegion);
            }

          }
        }
      } finally {
        if (getDestroyLock) {
          releaseDestroyLock();
        }
      }

      if (existing != null) {
        // now outside of synchronization we must wait for appropriate
        // initialization on existing region before returning a reference to
        // it
        existing.waitOnInitialization();
        throw new RegionExistsException(existing);
      }

      boolean success = false;
      try {
        newRegion.checkReadiness();
        cache.setRegionByPath(newRegion.getFullPath(), newRegion);
        if (regionAttributes instanceof UserSpecifiedRegionAttributes) {
          internalRegionArgs
              .setIndexes(((UserSpecifiedRegionAttributes) regionAttributes).getIndexes());
        }

        // releases initialization Latches
        newRegion.initialize(snapshotInputStream, imageTarget, internalRegionArgs);

        // register the region with resource manager to get memory events
        if (!newRegion.isInternalRegion()) {
          if (!newRegion.isDestroyed) {
            cache.getInternalResourceManager().addResourceListener(ResourceType.MEMORY,
                newRegion);

            if (!newRegion.getOffHeap()) {
              newRegion.initialCriticalMembers(
                  cache.getInternalResourceManager().getHeapMonitor().getState().isCritical(),
                  cache.getResourceAdvisor().adviseCriticalMembers());
            } else {
              newRegion.initialCriticalMembers(
                  cache.getInternalResourceManager().getHeapMonitor().getState().isCritical()
                      || cache.getInternalResourceManager().getOffHeapMonitor().getState()
                          .isCritical(),
                  cache.getResourceAdvisor().adviseCriticalMembers());
            }

            // synchronization would be done on ManagementAdapter.regionOpLock
            // instead of destroyLock in LocalRegion? ManagementAdapter is one
            // of the Resource Event listeners

            InternalDistributedSystem system = cache.getInternalDistributedSystem();
            system.handleResourceEvent(ResourceEvent.REGION_CREATE, newRegion);
          }
        }
        success = true;
      } catch (CancelException | RegionDestroyedException | RedundancyAlreadyMetException e) {
        // don't print a call stack
        throw e;
      } catch (RuntimeException validationException) {
        logger
            .warn(String.format("Initialization failed for Region %s", getFullPath()),
                validationException);
        throw validationException;
      } finally {
        if (!success) {
          cache.setRegionByPath(newRegion.getFullPath(), null);
          initializationFailed(newRegion);
          cache.getInternalResourceManager(false).removeResourceListener(newRegion);
        }
      }

      newRegion.postCreateRegion();
    } finally {
      // make sure region initialization latch is open regardless
      // before returning;
      // if the latch is not open at this point, then an exception must
      // have occurred
      if (newRegion != null && !newRegion.isInitialized()) {
        if (logger.isDebugEnabled()) {
          logger.debug("Region initialize latch is closed, Error must have occurred");
        }
      }
    }

    cache.invokeRegionAfter(newRegion);
    return newRegion;
  }

  @Override
  public void create(Object key, Object value, Object aCallbackArgument)
      throws TimeoutException, EntryExistsException, CacheWriterException {
    long startPut = getStatisticsClock().getTime();
    @Released
    EntryEventImpl event = newCreateEntryEvent(key, value, aCallbackArgument);
    try {
      validatedCreate(event, startPut);
    } finally {
      event.release();
    }
  }

  private void validatedCreate(EntryEventImpl event, long startPut)
      throws TimeoutException, EntryExistsException, CacheWriterException {

    if (event.getEventId() == null && generateEventID()) {
      event.setNewEventId(cache.getDistributedSystem());
    }
    // Only make create with null a local invalidate for
    // normal regions. Otherwise, it will become a distributed invalidate.
    if (getDataPolicy() == DataPolicy.NORMAL) {
      event.setLocalInvalid(true);
    }
    discoverJTA();
    if (!basicPut(event, true, // ifNew
        false, // ifOld
        null, // expectedOldValue
        true // requireOldValue TODO txMerge why is oldValue required for
    // create? I think so that the EntryExistsException will have it.
    )) {
      throw new EntryExistsException(event.getKey().toString(), event.getOldValue());
    }
    if (!getDataView().isDeferredStats()) {
      getCachePerfStats().endPut(startPut, false);
    }
  }

  @Retained
  private EntryEventImpl newCreateEntryEvent(Object key, Object value, Object aCallbackArgument) {

    validateArguments(key, value, aCallbackArgument);
    checkReadiness();
    checkForLimitedOrNoAccess();

    return entryEventFactory
        .create(this, Operation.CREATE, key, value, aCallbackArgument, false, getMyId())
        .setCreate(true);
  }

  /**
   * The default Region implementation will generate EvenTID in the EntryEvent object. This method
   * is overridden in special Region objects like HARegion or
   * SingleWriteSingleReadRegionQueue.SingleReadWriteMetaRegion to return false as the event
   * propagation from those regions do not need EventID objects
   *
   * @return boolean indicating whether to generate eventID or not
   */
  @Override
  public boolean generateEventID() {
    return !isUsedForPartitionedRegionAdmin();
  }

  @Override
  public Object destroy(Object key, Object aCallbackArgument)
      throws TimeoutException, EntryNotFoundException, CacheWriterException {
    @Released
    EntryEventImpl event = newDestroyEntryEvent(key, aCallbackArgument);
    try {
      return validatedDestroy(key, event);
    } finally {
      event.release();
    }
  }

  /**
   * Destroys entry without performing validations. Call this after validating key, callback arg,
   * and runtime state.
   */
  Object validatedDestroy(Object key, EntryEventImpl event)
      throws TimeoutException, EntryNotFoundException, CacheWriterException {
    if (event.getEventId() == null && generateEventID()) {
      event.setNewEventId(cache.getDistributedSystem());
    }
    basicDestroy(event, true, // cacheWrite
        null); // expectedOldValue
    if (event.isOldValueOffHeap()) {
      return null;
    }
    return handleNotAvailable(event.getOldValue());
  }

  @Retained
  EntryEventImpl newDestroyEntryEvent(Object key, Object aCallbackArgument) {
    validateKey(key);
    checkReadiness();
    checkForLimitedOrNoAccess();

    return entryEventFactory.create(this, Operation.DESTROY, key, null,
        aCallbackArgument, false, getMyId());
  }

  @Override
  public void destroyRegion(Object aCallbackArgument)
      throws CacheWriterException, TimeoutException {
    cache.invokeBeforeDestroyed(this);
    getDataView().checkSupportsRegionDestroy();
    checkForLimitedOrNoAccess();

    RegionEventImpl event = new RegionEventImpl(this, Operation.REGION_DESTROY, aCallbackArgument,
        false, getMyId(), generateEventID());
    basicDestroyRegion(event, true);
  }

  @Override
  public InternalDataView getDataView() {
    final TXStateInterface tx = getTXState();
    if (tx == null) {
      return sharedDataView;
    }
    return tx;
  }

  /**
   * Fetch the de-serialized value from non-transactional state.
   *
   * @param keyInfo to which the value is associated
   * @param updateStats true if the entry stats should be updated.
   * @param disableCopyOnRead if true then disable copy on read
   * @param preferCachedDeserializable true if the preferred result form is CachedDeserializable
   * @param clientEvent client's event, if any (for version tag retrieval)
   * @param returnTombstones whether destroyed entries should be returned
   * @param retainResult if true then the result may be a retained off-heap reference
   * @return the value for the given key
   */
  public Object getDeserializedValue(RegionEntry regionEntry, final KeyInfo keyInfo,
      final boolean updateStats, boolean disableCopyOnRead, boolean preferCachedDeserializable,
      EntryEventImpl clientEvent, boolean returnTombstones, boolean retainResult) {
    if (diskRegion != null) {
      diskRegion.setClearCountReference();
    }
    try {
      if (regionEntry == null) {
        regionEntry = entries.getEntry(keyInfo.getKey());
      }
      // skip updating the stats if the value is null
      // TODO - We need to clean up the callers of the this class so that we can
      // update the statistics here, where it would make more sense.
      if (regionEntry == null) {
        return null;
      }
      final Object value;
      if (clientEvent != null && regionEntry.getVersionStamp() != null) {
        // defer the lruUpdateCallback to prevent a deadlock
        final boolean disabled = entries.disableLruUpdateCallback();
        try {
          synchronized (regionEntry) {
            // value & version must be obtained atomically
            clientEvent.setVersionTag(regionEntry.getVersionStamp().asVersionTag());
            value = getDeserialized(regionEntry, updateStats, disableCopyOnRead,
                preferCachedDeserializable, retainResult);
          }
        } finally {
          if (disabled) {
            entries.enableLruUpdateCallback();
          }
          try {
            entries.lruUpdateCallback();
          } catch (DiskAccessException dae) {
            handleDiskAccessException(dae);
            throw dae;
          }
        }
      } else {
        value = getDeserialized(regionEntry, updateStats, disableCopyOnRead,
            preferCachedDeserializable, retainResult);
      }
      if (logger.isTraceEnabled() && !(this instanceof HARegion)) {
        logger.trace(
            "getDeserializedValue for {} returning version: {} returnTombstones: {} value: {}",
            keyInfo.getKey(), regionEntry.getVersionStamp() == null ? "null"
                : regionEntry.getVersionStamp().asVersionTag(),
            returnTombstones, value);
      }
      return value;
    } finally {
      if (diskRegion != null) {
        diskRegion.removeClearCountReference();
      }
    }
  }

  /**
   * @param disableCopyOnRead if true then do not make a copy on read
   * @param preferCachedDeserializable true if the preferred result form is CachedDeserializable
   * @param retainResult if true then the result may be a retained off-heap reference
   * @return the value found, which can be
   *         <ul>
   *         <li>null if the value was removed from the region entry
   *         <li>Token.INVALID if the value of the region entry is invalid
   *         <li>Token.LOCAL_INVALID if the value of the region entry is local invalid
   *         </ul>
   */
  @Retained
  Object getDeserialized(RegionEntry regionEntry, boolean updateStats, boolean disableCopyOnRead,
      boolean preferCachedDeserializable, boolean retainResult) {
    assert !retainResult || preferCachedDeserializable;
    boolean disabledLRUCallback = entries.disableLruUpdateCallback();
    try {
      @Retained
      Object value;
      try {
        if (retainResult) {
          value = regionEntry.getValueRetain(this);
        } else {
          value = regionEntry.getValue(this);
        }
      } catch (DiskAccessException dae) {
        handleDiskAccessException(dae);
        throw dae;
      }

      // skip updating the stats if the value is null
      if (value == null) {
        return null;
      }
      if (value instanceof CachedDeserializable) {
        if (!preferCachedDeserializable) {
          if (isCopyOnRead()) {
            if (disableCopyOnRead) {
              value = ((CachedDeserializable) value).getDeserializedForReading();
            } else {
              value = ((CachedDeserializable) value).getDeserializedWritableCopy(this, regionEntry);
            }
          } else {
            value = ((CachedDeserializable) value).getDeserializedValue(this, regionEntry);
          }
        }
      } else if (!disableCopyOnRead) {
        value = conditionalCopy(value);
      }

      if (updateStats) {
        updateStatsForGet(regionEntry, value != null && !Token.isInvalid(value));
      }
      return value;
    } catch (IllegalArgumentException i) {
      throw new IllegalArgumentException(String.format("%s",
          "Error while deserializing value for key=" + regionEntry.getKey()), i);
    } finally {
      if (disabledLRUCallback) {
        entries.enableLruUpdateCallback();
        entries.lruUpdateCallback();
      }
    }
  }

  @Override
  public Object get(Object key, Object aCallbackArgument, boolean generateCallbacks,
      EntryEventImpl clientEvent) throws TimeoutException, CacheLoaderException {
    Object result =
        get(key, aCallbackArgument, generateCallbacks, false, false, null, clientEvent, false);
    if (Token.isInvalid(result)) {
      result = null;
    }
    return result;
  }

  /**
   * @see BucketRegion#getSerialized(KeyInfo, boolean, boolean, ClientProxyMembershipID,
   *      EntryEventImpl, boolean)
   */
  public Object get(Object key, Object aCallbackArgument, boolean generateCallbacks,
      boolean disableCopyOnRead, boolean preferCD, ClientProxyMembershipID requestingClient,
      EntryEventImpl clientEvent, boolean returnTombstones)
      throws TimeoutException, CacheLoaderException {
    return get(key, aCallbackArgument, generateCallbacks, disableCopyOnRead, preferCD,
        requestingClient, clientEvent, returnTombstones, false, false);
  }

  /**
   * The result of this operation may be an off-heap reference that the caller must release
   */
  @Retained
  public Object getRetained(Object key, Object aCallbackArgument, boolean generateCallbacks,
      boolean disableCopyOnRead, ClientProxyMembershipID requestingClient,
      EntryEventImpl clientEvent, boolean returnTombstones)
      throws TimeoutException, CacheLoaderException {
    return getRetained(key, aCallbackArgument, generateCallbacks, disableCopyOnRead,
        requestingClient, clientEvent, returnTombstones, false);
  }

  /**
   * The result of this operation may be an off-heap reference that the caller must release.
   *
   * @param opScopeIsLocal if true then just check local storage for a value; if false then try to
   *        find the value if it is not local
   */
  @Retained
  private Object getRetained(Object key, Object aCallbackArgument, boolean generateCallbacks,
      boolean disableCopyOnRead, ClientProxyMembershipID requestingClient,
      EntryEventImpl clientEvent, boolean returnTombstones, boolean opScopeIsLocal)
      throws TimeoutException, CacheLoaderException {
    return get(key, aCallbackArgument, generateCallbacks, disableCopyOnRead, true, requestingClient,
        clientEvent, returnTombstones, opScopeIsLocal, false);
  }

  /**
   * @param opScopeIsLocal if true then just check local storage for a value; if false then try to
   *        find the value if it is not local
   * @param retainResult if true then the result may be a retained off-heap reference.
   */
  Object get(Object key, Object aCallbackArgument, boolean generateCallbacks,
      boolean disableCopyOnRead, boolean preferCD, ClientProxyMembershipID requestingClient,
      EntryEventImpl clientEvent, boolean returnTombstones, boolean opScopeIsLocal,
      boolean retainResult) throws TimeoutException, CacheLoaderException {
    assert !retainResult || preferCD;
    validateKey(key);
    checkReadiness();
    checkForNoAccess();
    discoverJTA();
    long start = startGet();
    boolean isMiss = true;
    try {
      KeyInfo keyInfo = getKeyInfo(key, aCallbackArgument);
      Object value = getDataView().getDeserializedValue(keyInfo, this, true, disableCopyOnRead,
          preferCD, clientEvent, returnTombstones, retainResult, true);
      final boolean isCreate = value == null;
      isMiss = value == null || Token.isInvalid(value)
          || !returnTombstones && value == Token.TOMBSTONE;
      // Note: if the value was Token.DESTROYED then getDeserialized returns null
      if (isMiss) {
        // raise the precedence of opScopeIsLocal if scope is local and there is no loader,
        // then don't go further to try and get value
        if (!opScopeIsLocal
            && (getScope().isDistributed() || hasServerProxy() || basicGetLoader() != null)) {
          // serialize search/load threads if not in txn
          value = getDataView().findObject(keyInfo, this, isCreate, generateCallbacks, value,
              disableCopyOnRead, preferCD, requestingClient, clientEvent, returnTombstones);
          if (!returnTombstones && value == Token.TOMBSTONE) {
            value = null;
          }
        } else {
          // local scope with no loader, still might need to update stats
          if (isCreate) {
            recordMiss(null, key);
          }
          value = null;
        }
      }
      return value;
    } finally {
      endGet(start, isMiss);
    }
  }

  protected long startGet() {
    return getCachePerfStats().startGet();
  }

  protected void endGet(long start, boolean isMiss) {
    getCachePerfStats().endGet(start, isMiss);
  }

  /**
   * Update region and potentially entry stats for the miss case
   *
   * @param re optional region entry, fetched if null
   * @param key the key used to fetch the region entry
   */
  public void recordMiss(final RegionEntry re, Object key) {
    if (!statisticsEnabled) {
      return;
    }
    final RegionEntry e;
    if (re == null && !isTX()) {
      e = basicGetEntry(key);
    } else {
      e = re;
    }
    updateStatsForGet(e, false);
  }

  /**
   * @param isCreate true if call found no entry; false if updating an existing entry
   * @param localValue the value retrieved from the region for this object.
   * @param disableCopyOnRead if true then do not make a copy
   * @param preferCD true if the preferred result form is CachedDeserializable
   * @param clientEvent the client event, if any
   * @param returnTombstones whether to return tombstones
   */
  @Retained
  Object nonTxnFindObject(KeyInfo keyInfo, boolean isCreate, boolean generateCallbacks,
      Object localValue, boolean disableCopyOnRead, boolean preferCD,
      ClientProxyMembershipID requestingClient, EntryEventImpl clientEvent,
      boolean returnTombstones) throws TimeoutException, CacheLoaderException {
    @Retained
    Object result;
    if (isProxy()) {
      result =
          getObject(keyInfo, isCreate, generateCallbacks, localValue, disableCopyOnRead, preferCD,
              requestingClient, clientEvent, returnTombstones);
    } else {
      result = optimizedGetObject(keyInfo, isCreate, generateCallbacks, localValue,
          disableCopyOnRead, preferCD,
          requestingClient, clientEvent, returnTombstones);
    }
    return result;
  }


  private Object getObject(KeyInfo keyInfo, boolean isCreate, boolean generateCallbacks,
      Object localValue, boolean disableCopyOnRead, boolean preferCD,
      ClientProxyMembershipID requestingClient, EntryEventImpl clientEvent,
      boolean returnTombstones) {
    Object result;
    boolean partitioned = getDataPolicy().withPartitioning();
    if (!partitioned) {
      localValue = getDeserializedValue(null, keyInfo, isCreate, disableCopyOnRead, preferCD,
          clientEvent, false, false);

      // stats have now been updated
      if (localValue != null && !Token.isInvalid(localValue)) {
        result = localValue;
        return result;
      }
      isCreate = localValue == null;
      result = findObjectInSystem(keyInfo, isCreate, null, generateCallbacks, localValue,
          disableCopyOnRead, preferCD, requestingClient, clientEvent, returnTombstones);

    } else {
      // For PRs we don't want to deserialize the value and we can't use findObjectInSystem
      // because it can invoke code that is transactional.
      result =
          getSharedDataView().findObject(keyInfo, this, isCreate, generateCallbacks, localValue,
              disableCopyOnRead, preferCD, requestingClient, clientEvent, returnTombstones);
    }

    if (result == null && localValue != null) {
      if (localValue != Token.TOMBSTONE || returnTombstones) {
        result = localValue;
      }
    }
    // findObjectInSystem does not call conditionalCopy
    if (!disableCopyOnRead) {
      result = conditionalCopy(result);
    }
    return result;
  }

  /**
   * optimized to only allow one thread to do a search/load, other threads wait on a future
   */
  private Object optimizedGetObject(KeyInfo keyInfo, boolean isCreate, boolean generateCallbacks,
      Object localValue, boolean disableCopyOnRead, boolean preferCD,
      ClientProxyMembershipID requestingClient, EntryEventImpl clientEvent,
      boolean returnTombstones) {
    Object result = null;
    FutureResult thisFuture = new FutureResult(stopper);
    Future otherFuture = (Future) getFutures.putIfAbsent(keyInfo.getKey(), thisFuture);
    // only one thread can get their future into the map for this key at a time
    if (otherFuture != null) {
      try {
        Object[] valueAndVersion = (Object[]) otherFuture.get();
        if (valueAndVersion != null) {
          result = valueAndVersion[0];
          if (clientEvent != null) {
            clientEvent.setVersionTag((VersionTag) valueAndVersion[1]);
          }
          if (!preferCD && result instanceof CachedDeserializable) {
            CachedDeserializable cd = (CachedDeserializable) result;
            if (!disableCopyOnRead && (isCopyOnRead() || isProxy())) {
              result = cd.getDeserializedWritableCopy(null, null);
            } else {
              result = cd.getDeserializedForReading();
            }

          } else if (!disableCopyOnRead) {
            result = conditionalCopy(result);
          }
          // what was a miss is now a hit
          if (isCreate) {
            RegionEntry regionEntry = basicGetEntry(keyInfo.getKey());
            updateStatsForGet(regionEntry, true);
          }
          return result;
        }
      } catch (InterruptedException ignore) {
        Thread.currentThread().interrupt();
        // TODO check a CancelCriterion here?
        return null;
      } catch (ExecutionException e) {
        // unexpected since there is no background thread
        // NOTE: this was creating InternalGemFireError and initCause with itself
        throw new InternalGemFireError(
            "unexpected exception", e);
      }
    }
    try {
      result =
          getObject(keyInfo, isCreate, generateCallbacks, localValue, disableCopyOnRead, preferCD,
              requestingClient, clientEvent, returnTombstones);

    } finally {
      if (otherFuture == null) {
        if (result != null) {
          VersionTag tag = clientEvent == null ? null : clientEvent.getVersionTag();
          thisFuture.set(new Object[] {result, tag});
        } else {
          thisFuture.set(null);
        }
        getFutures.remove(keyInfo.getKey());
      }
    }

    return result;
  }


  /**
   * Returns true if get should give a copy; false if a reference.
   *
   * @since GemFire 4.0
   */
  @Override
  public boolean isCopyOnRead() {
    return compressor == null && cache.isCopyOnRead()
        && !isUsedForPartitionedRegionAdmin && !isUsedForMetaRegion && !getOffHeap()
        && !isSecret();
  }

  /**
   * Makes a copy, if copy-on-get is enabled, of the specified object.
   *
   * @since GemFire 4.0
   */
  Object conditionalCopy(Object o) {
    if (isCopyOnRead() && !Token.isInvalid(o)) {
      return CopyHelper.copy(o);
    }
    return o;
  }

  private final String fullPath;

  @Override
  public String getFullPath() {
    return fullPath;
  }

  @Override
  public Region getParentRegion() {
    return parentRegion;
  }

  @Override
  public Region getSubregion(String path) {
    checkReadiness();
    return getSubregion(path, false);
  }

  @Override
  public void invalidateRegion(Object aCallbackArgument) throws TimeoutException {
    getDataView().checkSupportsRegionInvalidate();
    checkReadiness();
    checkForLimitedOrNoAccess();
    RegionEventImpl event = new RegionEventImpl(this, Operation.REGION_INVALIDATE,
        aCallbackArgument, false, getMyId(), generateEventID());

    basicInvalidateRegion(event);
  }

  @Override
  public Object put(Object key, Object value, Object aCallbackArgument)
      throws TimeoutException, CacheWriterException {
    long startPut = getStatisticsClock().getTime();
    @Released
    EntryEventImpl event = newUpdateEntryEvent(key, value, aCallbackArgument);
    try {
      return validatedPut(event, startPut);
    } finally {
      event.release();
    }
  }

  Object validatedPut(EntryEventImpl event, long startPut)
      throws TimeoutException, CacheWriterException {

    if (event.getEventId() == null && generateEventID()) {
      event.setNewEventId(cache.getDistributedSystem());
    }
    Object oldValue = null;
    if (basicPut(event, false, // ifNew
        false, // ifOld
        null, // expectedOldValue
        false // requireOldValue
    )) {
      if (!event.isOldValueOffHeap()) {
        // don't copy it to heap just to return from put.
        // TODO: come up with a better way to do this.
        oldValue = event.getOldValue();
      }
      if (!getDataView().isDeferredStats()) {
        getCachePerfStats().endPut(startPut, false);
      }
    }
    return handleNotAvailable(oldValue);
  }

  @Retained
  EntryEventImpl newUpdateEntryEvent(Object key, Object value, Object aCallbackArgument) {

    validateArguments(key, value, aCallbackArgument);
    if (value == null) {
      throw new NullPointerException(
          "value must not be null");
    }
    checkReadiness();
    checkForLimitedOrNoAccess();
    discoverJTA();

    // This used to call the constructor which took the old value. It
    // was modified to call the other EntryEventImpl constructor so that
    // an id will be generated by default. Null was passed in anyway.
    // generate EventID
    @Retained
    final EntryEventImpl event =
        entryEventFactory.create(this, Operation.UPDATE, key, value,
            aCallbackArgument, false, getMyId());
    boolean eventReturned = false;
    try {
      extractDeltaIntoEvent(value, event);
      eventReturned = true;
      return event;
    } finally {
      if (!eventReturned) {
        event.release();
      }
    }
  }

  private void extractDeltaIntoEvent(Object value, EntryEventImpl event) {
    // 1. Check for DS-level delta property.
    // 2. Default value for operation type is UPDATE, so no need to check that here.
    // 3. Check if it has server region proxy.
    // We do not have a handle to event in PutOpImpl to check if we have
    // delta bytes calculated already. So no need to calculate it here.
    // 4. Check if value is instanceof org.apache.geode.Delta
    // 5. Check if Region in PR with redundantCopies > 0. Set extractDelta.
    // 6. Check if Region has peers. Set extractDelta.
    // 7. Check if it has any delta proxies attached to it. Set extractDelta.
    // 8. If extractDelta is set, check if it has delta.
    // 9. If delta is found, extract it and set it into the event.
    // 10. If any exception is caught while invoking the delta callbacks, throw it back.
    // 11. Wrap any checked exception in InternalGemFireException before throwing it.
    try {
      // How costly is this if check?
      if (getSystem().getConfig().getDeltaPropagation() && value instanceof Delta) {
        boolean extractDelta = false;
        if (!hasServerProxy()) {
          if (this instanceof PartitionedRegion) {
            if (((PartitionedRegion) this).getRedundantCopies() > 0) {
              extractDelta = true;
            } else {
              InternalDistributedMember ids = (InternalDistributedMember) PartitionRegionHelper
                  .getPrimaryMemberForKey(this, event.getKey());
              if (ids != null) {
                extractDelta = !getSystem().getMemberId().equals(ids.getId())
                    || hasAdjunctRecipientsNeedingDelta(event);
              } else {
                extractDelta = true;
              }
            }
          } else if (this instanceof DistributedRegion
              && !((DistributedRegion) this).scope.isDistributedNoAck()
              && !((CacheDistributionAdvisee) this).getCacheDistributionAdvisor().adviseCacheOp()
                  .isEmpty()) {
            extractDelta = true;
          }
          if (!extractDelta && ClientHealthMonitor.getInstance() != null) {
            extractDelta = ClientHealthMonitor.getInstance().hasDeltaClients();
          }
        } else if (getSystem().isDeltaEnabledOnServer()) {
          // This is a client region
          extractDelta = true;
        }
        if (extractDelta && ((Delta) value).hasDelta()) {
          try (HeapDataOutputStream hdos = new HeapDataOutputStream(KnownVersion.CURRENT)) {
            long start = DistributionStats.getStatTime();
            try {
              ((Delta) value).toDelta(hdos);
            } catch (RuntimeException re) {
              throw re;
            } catch (Exception e) {
              throw new DeltaSerializationException("Caught exception while sending delta", e);
            }
            event.setDeltaBytes(hdos.toByteArray());
            getCachePerfStats().endDeltaPrepared(start);
          }
        }
      }
    } catch (RuntimeException re) {
      throw re;
    } catch (Exception e) {
      throw new InternalGemFireException(e);
    }
  }

  private boolean hasAdjunctRecipientsNeedingDelta(EntryEventImpl event) {
    PartitionedRegion partitionedRegion = (PartitionedRegion) this;
    BucketRegion bucketRegion;

    int bId = event.getKeyInfo().getBucketId();
    try {
      bucketRegion = partitionedRegion.dataStore.getInitializedBucketForId(event.getKey(), bId);
    } catch (ForceReattemptException ignore) {
      return true;
    }
    Set<InternalDistributedMember> recipients =
        bucketRegion.getCacheDistributionAdvisor().adviseUpdate(event);
    Set<InternalDistributedMember> twoMessages =
        bucketRegion.getBucketAdvisor().adviseRequiresTwoMessages();
    CacheDistributionAdvisor cda = partitionedRegion.getCacheDistributionAdvisor();
    FilterRoutingInfo filterRouting = cda.adviseFilterRouting(event, recipients);
    Set<InternalDistributedMember> adjunctRecipients =
        bucketRegion.getAdjunctReceivers(event, recipients, twoMessages, filterRouting);
    Set cacheServerMembers = cda.adviseCacheServers();
    return !Collections.disjoint(adjunctRecipients, cacheServerMembers);
  }

  @Override
  public Region.Entry getEntry(Object key) {
    validateKey(key);
    checkReadiness();
    checkForNoAccess();
    discoverJTA();
    return getDataView().getEntry(getKeyInfo(key), this, false);
  }

  /**
   * internally we often need to get an entry whether it is a tombstone or not
   */
  @Override
  public Region.Entry getEntry(Object key, boolean allowTombstones) {
    return getDataView().getEntry(getKeyInfo(key), this, allowTombstones);
  }

  /**
   * Just like getEntry but also updates the stats that get would have depending on a flag. Also
   * skips discovering JTA
   *
   * @return the entry if it exists; otherwise null.
   */
  public Entry accessEntry(Object key, boolean updateStats) {
    validateKey(key);
    checkReadiness();
    checkForNoAccess();
    if (updateStats) {
      return getDataView().accessEntry(getKeyInfo(key), this);
    }
    return getDataView().getEntry(getKeyInfo(key), this, false);
  }

  /**
   * a fast estimate of total number of entries locally in the region
   */
  long getEstimatedLocalSize() {
    if (!isDestroyed) {
      long size;
      // if region has not been initialized yet, then get the estimate from
      // disk region's recovery map if available
      RegionMap regionMap;
      if (!initialized && diskRegion != null
          && (regionMap = diskRegion.getRecoveredEntryMap()) != null
          && (size = regionMap.size()) > 0) {
        return size;
      }
      if ((regionMap = getRegionMap()) != null) {
        return regionMap.size();
      }
    }
    return 0;
  }

  /**
   * @param access true if caller wants last accessed time updated
   * @param allowTombstones whether an entry with a TOMBSTONE value can be returned
   */
  Region.Entry nonTXGetEntry(KeyInfo keyInfo, boolean access, boolean allowTombstones) {
    final Object key = keyInfo.getKey();
    RegionEntry re = entries.getEntry(key);
    boolean miss = re == null || re.isDestroyedOrRemoved();
    if (access) {
      updateStatsForGet(re, !miss);
    }
    if (re == null) {
      return null;
    }
    if (re.isTombstone()) {
      if (!allowTombstones) {
        return null;
      } // else return an entry (client GII / putAll results)
    } else if (miss) {
      return null;
    }

    return new NonTXEntry(this, re);
  }

  boolean isClosed() {
    return cache.isClosed();
  }

  /**
   * Returns true if this region is or has been closed or destroyed. Note that unlike
   * {@link #isDestroyed()} this method will not return true if the cache is closing but has not yet
   * started closing this region.
   */
  @Override
  public boolean isThisRegionBeingClosedOrDestroyed() {
    return isDestroyed;
  }

  /**
   * returns true if this region has been destroyed
   */
  @Override
  public boolean isDestroyed() {
    if (isClosed()) {
      return true;
    }

    boolean isTraceEnabled = logger.isTraceEnabled();

    if (isDestroyed) {
      if (isTraceEnabled) {
        logger.trace("isDestroyed: true, this.isDestroyed: {}", getFullPath());
      }
      return true;
    }

    if (isTraceEnabled) {
      logger.trace("isDestroyed: false : {}", getFullPath());
    }
    return false;
  }

  /**
   * a variant of subregions() that does not perform a readiness check
   */
  @Override
  public Set basicSubregions(boolean recursive) {
    return new SubregionsSet(recursive);
  }

  @Override
  public Set subregions(boolean recursive) {
    checkReadiness();
    return new SubregionsSet(recursive);
  }

  @Override
  public Set entrySet(boolean recursive) {
    checkReadiness();
    checkForNoAccess();
    if (!restoreSetOperationTransactionBehavior) {
      discoverJTA();
    }
    return basicEntries(recursive);
  }

  /**
   * Returns set of entries without performing validation checks.
   */
  public Set basicEntries(boolean recursive) {
    return new EntriesSet(this, recursive, IteratorType.ENTRIES, false);
  }

  /**
   * Flavor of keys that will not do repeatable read
   *
   * @since GemFire 5.5
   */
  @VisibleForTesting
  public Set testHookKeys() {
    checkReadiness();
    checkForNoAccess();
    return new EntriesSet(this, false, IteratorType.KEYS, false /* allowTombstones */);
  }

  public Set keys() {
    checkReadiness();
    checkForNoAccess();
    if (!restoreSetOperationTransactionBehavior) {
      discoverJTA();
    }
    return new EntriesSet(this, false, IteratorType.KEYS, false);
  }

  /**
   * return a set of the keys in this region
   *
   * @param allowTombstones whether destroyed entries should be included
   * @return the keys
   */
  public Set keySet(boolean allowTombstones) {
    checkReadiness();
    checkForNoAccess();
    return new EntriesSet(this, false, IteratorType.KEYS, allowTombstones);
  }

  @Override
  public Collection values() {
    checkReadiness();
    checkForNoAccess();
    if (!restoreSetOperationTransactionBehavior) {
      discoverJTA();
    }
    return new EntriesSet(this, false, IteratorType.VALUES, false);
  }

  @Override
  public Object getUserAttribute() {
    return regionUserAttribute;
  }

  @Override
  public void setUserAttribute(Object value) {
    checkReadiness();
    regionUserAttribute = value;
  }

  @Override
  public boolean containsKey(Object key) {
    checkReadiness();
    checkForNoAccess();
    return getDataView().containsKey(getKeyInfo(key), this);
  }

  @Override
  public boolean containsTombstone(Object key) {
    checkReadiness();
    checkForNoAccess();
    if (!getConcurrencyChecksEnabled()) {
      return false;
    }
    try {
      Entry entry = getDataView().getEntry(getKeyInfo(key), this, true);
      return entry != null && entry.getValue() == Token.TOMBSTONE;
    } catch (EntryDestroyedException ignore) {
      return true;
    }
  }

  boolean nonTXContainsKey(KeyInfo keyInfo) {
    boolean contains = getRegionMap().containsKey(keyInfo.getKey());
    if (contains && imageState.isClient()) {
      // concurrent RI causes containsKey for destroyed entry to return true
      RegionEntry regionEntry = entries.getEntry(keyInfo.getKey());
      if (regionEntry == null || regionEntry.isDestroyedOrRemoved()) {
        contains = false;
      }
    }
    return contains;
  }

  @Override
  public boolean containsValueForKey(Object key) {
    discoverJTA();
    return getDataView().containsValueForKey(getKeyInfo(key), this);
  }

  boolean nonTXContainsValueForKey(KeyInfo keyInfo) {
    checkReadiness();
    checkForNoAccess();
    if (diskRegion != null) {
      diskRegion.setClearCountReference();
    }
    try {
      RegionEntry entry = entries.getEntry(keyInfo.getKey());
      boolean result = entry != null;
      if (result) {
        ReferenceCountHelper.skipRefCountTracking();
        // no need to decompress since we only want to know if we have an existing value
        Object val = entry.getTransformedValue();
        if (val instanceof StoredObject) {
          OffHeapHelper.release(val);
          ReferenceCountHelper.unskipRefCountTracking();
          return true;
        }
        ReferenceCountHelper.unskipRefCountTracking();
        // No need to to check CachedDeserializable because INVALID and LOCAL_INVALID will never be
        // faulted out of mem If val is NOT_AVAILABLE that means we have a valid value on disk.
        result = !Token.isInvalidOrRemoved(val);
      }
      return result;
    } finally {
      if (diskRegion != null) {
        diskRegion.removeClearCountReference();
      }
    }
  }

  @Override
  public RegionAttributes getAttributes() {
    // allow attribute access on closed regions
    return this;
  }

  @Override
  public String getName() {
    return regionName;
  }

  /**
   * Convenience method to get region name for logging/exception messages. if this region is an
   * instanceof bucket region, it returns the bucket region name
   *
   * @return name of the region or the owning partitioned region
   */
  @Override
  public String getDisplayName() {
    if (isUsedForPartitionedRegionBucket()) {
      return getPartitionedRegion().getName();
    }
    return regionName;
  }

  /**
   * Returns the number of entries in this region. Note that because of the concurrency properties
   * of the {@link RegionMap}, the number of entries is only an approximate. That is, other threads
   * may change the number of entries in this region while this method is being invoked.
   *
   * @see RegionMap#size
   */
  public int entryCount() {
    return getDataView().entryCount(this);
  }

  int entryCount(Set<Integer> buckets) {
    return entryCount(buckets, false);
  }

  int entryCount(Set<Integer> buckets, boolean estimate) {
    assert buckets == null : "unexpected buckets " + buckets + " for region " + this;

    return getDataView().entryCount(this);
  }

  /**
   * @return size after considering imageState
   */
  @Override
  public int getRegionSize() {
    synchronized (getSizeGuard()) {
      int result = getRegionMap().size();
      // if this is a client with no tombstones then we subtract the number
      // of entries being affected by register-interest refresh
      if (imageState.isClient() && !getConcurrencyChecksEnabled()) {
        return result - imageState.getDestroyedEntriesCount();
      }
      return result - tombstoneCount.get();
    }
  }

  /**
   * Returns the {@code DiskRegion} that this region uses to access data on disk.
   *
   * @return {@code null} if disk regions are not being used
   * @since GemFire 3.2
   */
  @Override
  public DiskRegion getDiskRegion() {
    return diskRegion;
  }

  @Override
  public DiskRegionView getDiskRegionView() {
    return getDiskRegion();
  }

  /**
   * Lets the customer do an explicit evict of a value to disk and removes the value from memory.
   */
  public void evictValue(Object key) {
    if (getDiskRegion() != null) {
      entries.evictValue(key);
    }
  }

  private boolean isOverflowEnabled() {
    EvictionAttributes ea = getAttributes().getEvictionAttributes();
    return ea != null && ea.getAction().isOverflowToDisk();
  }

  @Override
  public void writeToDisk() {
    if (diskRegion == null) {
      DataPolicy dp = getDataPolicy();
      if (dp.isEmpty()) {
        throw new IllegalStateException(
            String.format("Cannot write a region with data-policy %s to disk.",
                dp));
      }
      if (!dp.withPersistence() && !isOverflowEnabled()) {
        throw new IllegalStateException(
            "Cannot write a region that is not configured to access disks.");
      }
    } else {
      diskRegion.asynchForceFlush();
    }
  }

  /**
   * Used by tests to force everything out to disk.
   */
  public void forceFlush() {
    if (diskRegion != null) {
      diskRegion.flushForTesting();
    }
  }

  /**
   * This implementation only checks readiness and scope
   */
  @Override
  public Lock getRegionDistributedLock() throws IllegalStateException {
    checkReadiness();
    checkForLimitedOrNoAccess();
    Scope theScope = getAttributes().getScope();
    Assert.assertTrue(theScope == Scope.LOCAL);
    throw new IllegalStateException(
        "Only supported for GLOBAL scope, not LOCAL");
  }

  /**
   * This implementation only checks readiness and scope
   */
  @Override
  public Lock getDistributedLock(Object key) throws IllegalStateException {
    checkReadiness();
    checkForLimitedOrNoAccess();
    Scope theScope = getAttributes().getScope();
    Assert.assertTrue(theScope == Scope.LOCAL);
    throw new IllegalStateException(
        "Only supported for GLOBAL scope, not LOCAL");
  }

  @Override
  public void invalidate(Object key, Object aCallbackArgument)
      throws TimeoutException, EntryNotFoundException {
    checkReadiness();
    checkForLimitedOrNoAccess();
    validatedInvalidate(key, aCallbackArgument);
  }

  /**
   * Destroys entry without performing validations. Call this after validating key, callback arg,
   * and runtime state.
   */
  void validatedInvalidate(Object key, Object aCallbackArgument)
      throws TimeoutException, EntryNotFoundException {
    @Released
    EntryEventImpl event = entryEventFactory.create(this, Operation.INVALIDATE, key, null,
        aCallbackArgument, false, getMyId());
    try {
      if (generateEventID()) {
        event.setNewEventId(cache.getDistributedSystem());
      }
      basicInvalidate(event);
    } finally {
      event.release();
    }
  }

  @Override
  public void localDestroy(Object key, Object aCallbackArgument) throws EntryNotFoundException {
    validateKey(key);
    checkReadiness();
    checkForNoAccess();
    @Released
    EntryEventImpl event = entryEventFactory.create(this, Operation.LOCAL_DESTROY, key, null,
        aCallbackArgument, false, getMyId());
    if (generateEventID()) {
      event.setNewEventId(cache.getDistributedSystem());
    }
    try {
      basicDestroy(event, false, null); // expectedOldValue
    } catch (CacheWriterException e) {
      // cache writer not called
      throw new Error(
          "Cache Writer should not have been called for localDestroy",
          e);
    } catch (TimeoutException e) {
      // no distributed lock
      throw new Error(
          "No distributed lock should have been attempted for localDestroy",
          e);
    } finally {
      event.release();
    }
  }

  @Override
  public void localDestroyRegion(Object aCallbackArgument) {
    getDataView().checkSupportsRegionDestroy();
    RegionEventImpl event = new RegionEventImpl(this, Operation.REGION_LOCAL_DESTROY,
        aCallbackArgument, false, getMyId(), generateEventID()/* generate EventID */);
    try {
      basicDestroyRegion(event, false);
    } catch (CacheWriterException e) {
      // not possible with local operation, CacheWriter not called
      throw new Error(
          "CacheWriterException should not be thrown in localDestroyRegion",
          e);
    } catch (TimeoutException e) {
      // not possible with local operation, no distributed locks possible
      throw new Error(
          "TimeoutException should not be thrown in localDestroyRegion",
          e);
    }
  }

  @Override
  public void close() {
    RegionEventImpl event = new RegionEventImpl(this, Operation.REGION_CLOSE, null, false,
        getMyId(), generateEventID());
    try {
      // NOTE: the 422dynamicRegions branch added the callbackEvents argument
      // to basicDestroyRegion and inhibited events on region.close. This
      // clashed with the new SystemMemberCacheListener functionality in
      // 5.0, causing unit tests to fail
      basicDestroyRegion(event, false, true, true);
    } catch (CacheWriterException e) {
      // not possible with local operation, CacheWriter not called
      throw new Error(
          "CacheWriterException should not be thrown in localDestroyRegion",
          e);
    } catch (TimeoutException e) {
      // not possible with local operation, no distributed locks possible
      throw new Error(
          "TimeoutException should not be thrown in localDestroyRegion",
          e);
    }
  }

  @Override
  public void localInvalidate(Object key, Object aCallbackArgument) throws EntryNotFoundException {
    validateKey(key);
    checkReadiness();
    checkForNoAccess();

    @Released
    EntryEventImpl event = entryEventFactory.create(this, Operation.LOCAL_INVALIDATE, key,
        null, aCallbackArgument, false, getMyId());
    try {
      if (generateEventID()) {
        event.setNewEventId(cache.getDistributedSystem());
      }
      event.setLocalInvalid(true);
      basicInvalidate(event);
    } finally {
      event.release();
    }
  }

  @Override
  public void localInvalidateRegion(Object aCallbackArgument) {
    getDataView().checkSupportsRegionInvalidate();
    checkReadiness();
    checkForNoAccess();
    RegionEventImpl event = new RegionEventImpl(this, Operation.REGION_LOCAL_INVALIDATE,
        aCallbackArgument, false, getMyId());
    basicInvalidateRegion(event);
  }

  /**
   * Do any extra initialization required. Region is already visible in parent's subregion map. This
   * method releases the initialization Latches, so subclasses should call this super method last
   * after performing additional initialization.
   *
   * @param imageTarget ignored, used by subclass for get initial image
   * @see DistributedRegion#initialize(InputStream, InternalDistributedMember,
   *      InternalRegionArguments)
   */
  @Override
  public void initialize(InputStream snapshotInputStream, InternalDistributedMember imageTarget,
      InternalRegionArguments internalRegionArgs)
      throws TimeoutException, IOException, ClassNotFoundException {
    if (!isInternalRegion()) {
      // Subclasses may have already called this method, but this is
      // acceptable because addResourceListener won't add it twice
      if (!isDestroyed) {
        cache.getInternalResourceManager().addResourceListener(ResourceType.MEMORY, this);
      }
    }

    // if not local, then recovery happens in InitialImageOperation
    if (scope.isLocal()) {
      createOQLIndexes(internalRegionArgs);
      if (diskRegion != null) {
        try {
          diskRegion.initializeOwner(this);
          diskRegion.finishInitializeOwner(this, GIIStatus.NO_GII);
          // This block was added so that early recovery could figure out that
          // this data needs to be recovered from disk. Local regions used to
          // not bother assigning a memberId but that is what the early
          // recovery
          // code uses to figure out that a region needs to be recovered.
          PersistentMemberID oldId = diskRegion.getMyInitializingID();
          if (oldId == null) {
            oldId = diskRegion.getMyPersistentID();
          }
          if (oldId == null) {
            PersistentMemberID newId = diskRegion.generatePersistentID();
            diskRegion.setInitializing(newId);
            diskRegion.setInitialized();
          }
        } catch (DiskAccessException dae) {
          releaseAfterRegionCreateEventLatch();
          handleDiskAccessException(dae, true);
          throw dae;
        }
      }
    }

    // make sure latches are released if they haven't been by now already
    releaseBeforeGetInitialImageLatch();
    if (snapshotInputStream != null && scope.isLocal()) {
      try {
        loadSnapshotDuringInitialization(snapshotInputStream);
      } catch (DiskAccessException dae) {
        releaseAfterRegionCreateEventLatch();
        handleDiskAccessException(dae);
        throw dae;
      }
    }

    releaseAfterGetInitialImageLatch();

    if (logger.isDebugEnabled()) {
      logger.debug("Calling addExpiryTasks for {}", this);
    }
    // these calls can throw RegionDestroyedException if this region is
    // destroyed
    // at this point
    try {
      addIdleExpiryTask();
      addTTLExpiryTask();
      if (isEntryExpiryPossible()) {
        rescheduleEntryExpiryTasks();
      }
      initialized();
    } catch (RegionDestroyedException ignore) {
      // whether it is this region or a parent region that is destroyed,
      // then so must we be
      Assert.assertTrue(isDestroyed());
      // just proceed, a destroyed region will be returned to caller
    }
  }

  void createOQLIndexes(InternalRegionArguments internalRegionArgs) {
    createOQLIndexes(internalRegionArgs, false);
  }

  void createOQLIndexes(InternalRegionArguments internalRegionArgs, boolean recoverFromDisk) {
    if (internalRegionArgs == null || internalRegionArgs.getIndexes() == null
        || internalRegionArgs.getIndexes().isEmpty()) {
      return;
    }
    if (logger.isDebugEnabled()) {
      logger.debug("LocalRegion.createOQLIndexes on region {}", getFullPath());
    }
    long start = getCachePerfStats().startIndexInitialization();
    List oqlIndexes = internalRegionArgs.getIndexes();

    if (indexManager == null) {
      indexManager = IndexUtils.getIndexManager(cache, this, true);
    }
    DiskRegion dr = getDiskRegion();
    boolean isOverflowToDisk = false;
    if (dr != null) {
      isOverflowToDisk = dr.isOverflowEnabled();
      if (recoverFromDisk && !isOverflowToDisk) {
        // For disk regions, index creation should wait for async value creation to complete before
        // it starts its iteration
        // In case of disk overflow regions the waitForAsyncRecovery is done in populateOQLIndexes
        // method via getBestIterator()
        dr.waitForAsyncRecovery();
      }
    }
    Set<Index> indexes = new HashSet<>();
    Set<Index> prIndexes = new HashSet<>();
    // Release the initialization latch for index creation.
    final InitializationLevel initLevel = setThreadInitLevelRequirement(ANY_INIT);
    try {
      for (Object o : oqlIndexes) {
        IndexCreationData icd = (IndexCreationData) o;
        try {
          if (icd.getPartitionedIndex() != null) {
            ExecutionContext externalContext = new ExecutionContext(null, cache);
            if (internalRegionArgs.getPartitionedRegion() != null) {
              externalContext.setBucketRegion(internalRegionArgs.getPartitionedRegion(),
                  (BucketRegion) this);
            }
            if (logger.isDebugEnabled()) {
              logger.debug("IndexManager Index creation process for {}", icd.getIndexName());
            }

            // load entries during initialization only for non overflow regions
            indexes.add(indexManager.createIndex(icd.getIndexName(), icd.getIndexType(),
                icd.getIndexExpression(), icd.getIndexFromClause(), icd.getIndexImportString(),
                externalContext, icd.getPartitionedIndex(), !isOverflowToDisk));
            prIndexes.add(icd.getPartitionedIndex());
          } else {
            if (logger.isDebugEnabled()) {
              logger.debug("QueryService Index creation process for {}" + icd.getIndexName());
            }
            DefaultQueryService qs = (DefaultQueryService) getGemFireCache().getLocalQueryService();
            String fromClause =
                icd.getIndexType() == IndexType.FUNCTIONAL || icd.getIndexType() == IndexType.HASH
                    ? icd.getIndexFromClause() : getFullPath();
            // load entries during initialization only for non overflow regions
            indexes.add(
                qs.createIndex(icd.getIndexName(), icd.getIndexType(), icd.getIndexExpression(),
                    fromClause, icd.getIndexImportString(), !isOverflowToDisk));
          }

        } catch (Exception ex) {
          logger.info("Failed to create index {} on region {} with exception: {}",
              icd.getIndexName(), getFullPath(), ex);

        }
      }
    } finally {
      // Reset the initialization lock.
      setThreadInitLevelRequirement(initLevel);
    }
    // Load data into OQL indexes in case of disk recovery and disk overflow
    if (isOverflowToDisk) {
      if (recoverFromDisk) {
        populateOQLIndexes(indexes);
      } else {
        // Empty indexes are created for overflow regions but not populated at this stage
        // since this is not recovery.
        // Setting the populate flag to true so that the indexes can apply updates.
        indexManager.setPopulateFlagForIndexes(indexes);
      }
      // the pr index populate flags were not being set
      // we should revisit and clean up the index creation code paths
      indexManager.setPopulateFlagForIndexes(prIndexes);
    }
    getCachePerfStats().endIndexInitialization(start);
  }

  /**
   * Populate the indexes with region entries
   */
  private void populateOQLIndexes(Set<Index> indexes) {
    logger.info("Loading data into the indexes");
    try {
      indexManager.populateIndexes(indexes);
    } catch (MultiIndexCreationException ex) {
      logger.info("Failed to update index on region {}: {}", getFullPath(), ex.getMessage());
    }
  }

  /**
   * The region is now fully initialized, as far as LocalRegion is concerned
   */
  void initialized() {
    // does nothing in LocalRegion at this time
  }

  void releaseLatches() {
    releaseBeforeGetInitialImageLatch();
    releaseAfterGetInitialImageLatch();
    releaseAfterRegionCreateEventLatch();
  }

  void releaseBeforeGetInitialImageLatch() {
    if (logger.isDebugEnabled()) {
      logger.debug("Releasing Initialization Latch (before initial image) for {}", getFullPath());
    }
    releaseLatch(getInitializationLatchBeforeGetInitialImage());
  }

  void releaseAfterGetInitialImageLatch() {
    if (logger.isDebugEnabled()) {
      logger.debug("Releasing Initialization Latch (after initial image) for {}", getFullPath());
    }
    releaseLatch(getInitializationLatchAfterGetInitialImage());
  }

  /**
   * Called after we have delivered our REGION_CREATE event.
   *
   * @since GemFire 5.0
   */
  private void releaseAfterRegionCreateEventLatch() {
    releaseLatch(afterRegionCreateEventLatch);
  }

  /**
   * Used to cause cache listener events to wait until the after region create event is delivered.
   *
   * @since GemFire 5.0
   */
  private void waitForRegionCreateEvent() {
    StoppableCountDownLatch latch = afterRegionCreateEventLatch;
    if (latch != null && latch.getCount() == 0) {
      return;
    }
    waitOnInitialization(latch);
  }

  private static void releaseLatch(StoppableCountDownLatch latch) {
    if (latch == null) {
      return;
    }
    latch.countDown();
  }

  /**
   * Removes entries and recursively destroys subregions.
   *
   * @param eventSet collects the events for all destroyed regions if null, then we're closing so
   *        don't send events to callbacks or destroy the disk region
   */
  private void recursiveDestroyRegion(Set eventSet, RegionEventImpl regionEvent, boolean cacheWrite)
      throws CacheWriterException, TimeoutException {
    final boolean isClose = regionEvent.getOperation().isClose();
    // do the cacheWriter beforeRegionDestroy first
    if (eventSet != null && cacheWrite) {
      try {
        cacheWriteBeforeRegionDestroy(regionEvent);
      } catch (CancelException e) {
        if (!cache.forcedDisconnect()) {
          logger.warn("recursiveDestroyRegion: problem in cacheWriteBeforeRegionDestroy", e);
        }
      }
    }

    getEventTracker().stop();
    if (logger.isTraceEnabled(LogMarker.RVV_VERBOSE) && getVersionVector() != null) {
      logger.trace(LogMarker.RVV_VERBOSE, "version vector for {} is {}", getName(),
          getVersionVector().fullToString());
    }
    cancelTTLExpiryTask();
    cancelIdleExpiryTask();
    cancelAllEntryExpiryTasks();
    if (!isInternalRegion()) {
      getCachePerfStats().incRegions(-1);
    }
    cache.getInternalResourceManager(false).removeResourceListener(this);
    if (getMembershipAttributes().hasRequiredRoles()) {
      if (!isInternalRegion()) {
        getCachePerfStats().incReliableRegions(-1);
      }
    }

    // Note we need to do this even if we don't have a listener
    // because of the SystemMemberCacheEventProcessor. Once we have
    // a way to check for existence of SystemMemberCacheEventProcessor listeners
    // then the add only needs to be done if hasListener || hasAdminListener
    if (eventSet != null) {
      eventSet.add(regionEvent);
    }

    try {
      // call recursiveDestroyRegion on each subregion and remove it
      // from this subregion map
      Collection values = subregions.values();
      for (Iterator itr = values.iterator(); itr.hasNext();) {
        // element is a LocalRegion
        Object element = itr.next();
        LocalRegion region;
        try {
          setThreadInitLevelRequirement(BEFORE_INITIAL_IMAGE);
          try {
            // converts to a LocalRegion
            region = toRegion(element);
          } finally {
            setThreadInitLevelRequirement(AFTER_INITIAL_IMAGE);
          }
        } catch (CancelException ignore) {
          // ignore, keep going through the motions though
          region = (LocalRegion) element;
        } catch (RegionDestroyedException ignore) {
          // SharedRegionData was destroyed
          continue;
        }

        // if the region is destroyed, then it is a race condition with
        // failed initialization removing it from the parent subregion map
        if (region.isDestroyed) {
          continue;
        }
        // BEGIN operating on subregion of this region (rgn)
        if (eventSet != null) {
          regionEvent = (RegionEventImpl) regionEvent.clone();
          regionEvent.region = region;
        }

        try {
          region.recursiveDestroyRegion(eventSet, regionEvent, cacheWrite);
          if (!region.isInternalRegion()) {
            InternalDistributedSystem system = region.cache.getInternalDistributedSystem();
            system.handleResourceEvent(ResourceEvent.REGION_REMOVE, region);
          }
        } catch (CancelException e) {
          if (!cache.forcedDisconnect()) {
            logger.warn(String.format(
                "recursiveDestroyRegion: recursion failed due to cache closure. region, %s",
                region.getFullPath()),
                e);
          }
        }
        // remove from this subregion map;
        itr.remove();
        // END operating on subregion of this region
      }

      try {
        if (indexManager != null) {
          try {
            if (this instanceof BucketRegion) {
              indexManager.removeBucketIndexes(getPartitionedRegion());
            }
            indexManager.destroy();
          } catch (QueryException e) {
            throw new IndexMaintenanceException(e);
          }
        }
      } catch (CancelException e) {
        if (!cache.forcedDisconnect()) {
          logger.warn(String.format(
              "basicDestroyRegion: index removal failed due to cache closure. region, %s",
              getFullPath()),
              e);
        }
      }
    } finally {
      // mark this region as destroyed.
      if (regionEvent.isReinitializing()) {
        reinitialized_old = true;
      }
      cache.setRegionByPath(getFullPath(), null);

      getEventTracker().stop();

      if (diskRegion != null) {
        diskRegion.prepareForClose(this);
      }

      isDestroyed = true;
      // after isDestroyed is set to true call removeResourceListener
      cache.getInternalResourceManager(false).removeResourceListener(this);
      closeEntries();
      if (logger.isDebugEnabled()) {
        logger.debug("recursiveDestroyRegion: Region Destroyed: {}", getFullPath());
      }

      // if eventSet is null then we need to close the listener as well
      // otherwise, the listener will be closed after the destroy event
      try {
        postDestroyRegion(!isClose, regionEvent);
      } catch (CancelException e) {
        logger.warn(String.format(
            "recursiveDestroyRegion: postDestroyRegion failed due to cache closure. region, %s",
            getFullPath()),
            e);
      }

      // Destroy cqs created against this Region in a server cache.
      if (getServerProxy() == null) {
        closeCqs();
      }

      detachPool();

      if (eventSet != null) {
        closeCallbacksExceptListener();
      } else {
        closeAllCallbacks();
      }
      if (getConcurrencyChecksEnabled() && getDataPolicy().withReplication()
          && !cache.isClosed()) {
        cache.getTombstoneService().unscheduleTombstones(this);
      }
      if (hasOwnStats) {
        cachePerfStats.close();
      }
    }
  }

  public void closeEntries() {
    entries.close(null);
  }

  public Set<VersionSource> clearEntries(RegionVersionVector rvv) {
    return entries.clear(rvv, null);
  }

  @Override
  public void checkReadiness() {
    checkRegionDestroyed(true);
  }

  /**
   * This method should be called when the caller cannot locate an entry and that condition is
   * unexpected. This will first double check the cache and region state before throwing an
   * EntryNotFoundException. EntryNotFoundException should be a last resort exception.
   *
   * @param entryKey the missing entry's key.
   */
  @Override
  public void checkEntryNotFound(Object entryKey) {
    checkReadiness();
    // Localized string for partitioned region is generic enough for general use
    throw new EntryNotFoundException(
        String.format("Entry not found for key %s", entryKey));
  }

  /**
   * Search for the value in a server (if one exists), then try a loader.
   *
   * If we find a value, we put it in the cache.
   *
   * @param preferCD return the CacheDeserializable, if that's what the value is.
   * @param requestingClient the client making the request, if any
   * @param clientEvent the client's event, if any. If not null, we set the version tag
   * @return the deserialized value
   */
  Object findObjectInSystem(KeyInfo keyInfo, boolean isCreate, TXStateInterface tx,
      boolean generateCallbacks, Object localValue, boolean disableCopyOnRead, boolean preferCD,
      ClientProxyMembershipID requestingClient, EntryEventImpl clientEvent,
      boolean returnTombstones) throws CacheLoaderException, TimeoutException {

    final Object key = keyInfo.getKey();
    final Object aCallbackArgument = keyInfo.getCallbackArg();
    Object value = null;
    boolean fromServer = false;
    VersionTagHolder holder = null;

    /*
     * First lets try the server
     */
    ServerRegionProxy mySRP = getServerProxy();
    if (mySRP != null) {
      holder = new VersionTagHolder();
      value = mySRP.get(key, aCallbackArgument, holder);
      fromServer = value != null;
    }

    /*
     * If we didn't get anything from the server, try the loader
     */
    if (!fromServer || value == Token.TOMBSTONE) {
      // copy into local var to prevent race condition
      CacheLoader loader = basicGetLoader();
      if (loader != null) {
        fromServer = false;
        CachePerfStats stats = getCachePerfStats();
        long statStart = stats.startLoad();
        try {
          value = callCacheLoader(loader, key, aCallbackArgument, preferCD);
        } finally {
          stats.endLoad(statStart);
        }
      }
    }

    // don't allow tombstones into a client cache if it doesn't
    // have concurrency checks enabled
    if (fromServer && value == Token.TOMBSTONE && !getConcurrencyChecksEnabled()) {
      value = null;
    }

    /*
     * If we got a value back, let's put it in the cache.
     */
    RegionEntry re = null;
    if (value != null && !isMemoryThresholdReachedForLoad()) {

      long startPut = getStatisticsClock().getTime();
      validateKey(key);
      Operation op;
      if (isCreate) {
        op = Operation.LOCAL_LOAD_CREATE;
      } else {
        op = Operation.LOCAL_LOAD_UPDATE;
      }

      @Released
      EntryEventImpl event =
          entryEventFactory.create(this, op, key, value, aCallbackArgument, false,
              getMyId(), generateCallbacks);
      try {

        // do not put an invalid entry into the cache if there's
        // already one there with the same version
        if (fromServer) {
          if (alreadyInvalid(key, event)) {
            return null;
          }
          event.setFromServer(fromServer);
          event.setVersionTag(holder.getVersionTag());
          if (clientEvent != null) {
            clientEvent.setVersionTag(holder.getVersionTag());
          }
        }

        // set the event id so that we can propagate the value to the server
        if (!fromServer) {
          event.setNewEventId(cache.getDistributedSystem());
        }
        try {
          try {
            re = basicPutEntry(event, 0L);
            if (!fromServer && clientEvent != null) {
              clientEvent.setVersionTag(event.getVersionTag());
              clientEvent.isConcurrencyConflict(event.isConcurrencyConflict());
            }
            if (fromServer && event.getRawNewValue() == Token.TOMBSTONE) {
              // tombstones are destroyed entries
              return null;
            }
          } catch (ConcurrentCacheModificationException ignore) {
            // this means the value attempted to overwrite a newer modification and was rejected
            if (logger.isDebugEnabled()) {
              logger.debug("caught concurrent modification attempt when applying {}", event);
            }
            notifyBridgeClients(event);
          }
          if (!getDataView().isDeferredStats()) {
            getCachePerfStats().endPut(startPut, event.isOriginRemote());
          }
        } catch (CacheWriterException cwe) {
          if (logger.isDebugEnabled()) {
            logger.debug("findObjectInSystem: writer exception putting entry {}", event, cwe);
          }
        }
      } finally {
        event.release();
      }
    }
    if (isCreate) {
      recordMiss(re, key);
    }
    return value;
  }

  Object callCacheLoader(CacheLoader loader, final Object key,
      final Object aCallbackArgument, boolean preferCD) {
    LoaderHelper loaderHelper = loaderHelperFactory.createLoaderHelper(key, aCallbackArgument,
        false /* netSearchAllowed */, true /* netloadAllowed */, null /* searcher */);
    Object result = loader.load(loaderHelper);
    result = getCache().convertPdxInstanceIfNeeded(result, preferCD);
    return result;
  }

  boolean isMemoryThresholdReachedForLoad() {
    return isMemoryThresholdReached();
  }

  /**
   * Returns true if the cache already has this key as an invalid entry with a version >= the one in
   * the given event. This is used in cache-miss processing to avoid overwriting the entry when it
   * is not necessary, so that we avoid invoking cache listeners.
   *
   * @return whether the entry is already invalid
   */
  private boolean alreadyInvalid(Object key, EntryEventImpl event) {
    @Unretained(ENTRY_EVENT_NEW_VALUE)
    Object newValue = event.getRawNewValue();
    if (newValue == null || Token.isInvalid(newValue)) {
      RegionEntry entry = entries.getEntry(key);
      if (entry != null) {
        synchronized (entry) {
          if (entry.isInvalid()) {
            VersionStamp stamp = entry.getVersionStamp();
            if (stamp == null || event.getVersionTag() == null) {
              return true;
            }
            if (stamp.getEntryVersion() >= event.getVersionTag().getEntryVersion()) {
              return true;
            }
          }
        }
      }
    }
    return false;
  }

  /**
   * @return true if cacheWrite was performed
   * @see DistributedRegion#cacheWriteBeforeDestroy(EntryEventImpl, Object)
   */
  @Override
  public boolean cacheWriteBeforeDestroy(EntryEventImpl event, Object expectedOldValue)
      throws CacheWriterException, EntryNotFoundException, TimeoutException {
    boolean result = false;
    // copy into local var to prevent race condition
    CacheWriter writer = basicGetWriter();
    if (writer != null && event.getOperation() != Operation.REMOVE
        && !event.inhibitAllNotifications()) {
      final long start = getCachePerfStats().startCacheWriterCall();
      event.setReadOldValueFromDisk(true);
      try {
        writer.beforeDestroy(event);
      } finally {
        event.setReadOldValueFromDisk(false);
        getCachePerfStats().endCacheWriterCall(start);
      }
      result = true;
    }
    serverDestroy(event, expectedOldValue);
    return result;
  }

  /**
   * @return true if this was a client region; false if not
   */
  @Override
  public boolean bridgeWriteBeforeDestroy(EntryEventImpl event, Object expectedOldValue)
      throws CacheWriterException, EntryNotFoundException, TimeoutException {
    if (hasServerProxy()) {
      serverDestroy(event, expectedOldValue);
      return true;
    }
    return false;
  }

  /**
   * @since GemFire 5.7
   */
  void serverRegionDestroy(RegionEventImpl regionEvent) {
    if (regionEvent.getOperation().isDistributed()) {
      ServerRegionProxy mySRP = getServerProxy();
      if (mySRP != null) {
        EventID eventId = regionEvent.getEventId();
        Object callbackArg = regionEvent.getRawCallbackArgument();
        mySRP.destroyRegion(eventId, callbackArg);
      }
    }
  }

  /**
   * @since GemFire 5.7
   */
  private void serverRegionClear(RegionEventImpl regionEvent) {
    if (regionEvent.getOperation().isDistributed()) {
      ServerRegionProxy mySRP = getServerProxy();
      if (mySRP != null) {
        EventID eventId = regionEvent.getEventId();
        Object callbackArg = regionEvent.getRawCallbackArgument();
        mySRP.clear(eventId, callbackArg);
      }
    }
  }

  /**
   * @since GemFire 5.7
   */
  void serverInvalidate(EntryEventImpl event) {
    if (event.getOperation().isDistributed() && !event.isOriginRemote()) {
      ServerRegionProxy mySRP = getServerProxy();
      if (mySRP != null) {
        mySRP.invalidate(event);
      }
    }
  }

  /**
   * @since GemFire 5.7
   */
  void serverPut(EntryEventImpl event, boolean requireOldValue, Object expectedOldValue) {
    if (event.getOperation().isDistributed() && !event.isFromServer()) {
      ServerRegionProxy mySRP = getServerProxy();
      if (mySRP != null) {
        if (event.isBulkOpInProgress()) {
          // this is a put all, ignore this!
          return;
        }
        Operation op = event.getOperation();
        // TODO: is the newEntry flag needed?
        Object key = event.getKey();
        Object value = event.getRawNewValue();

        // serverPut is called by cacheWriteBeforePut so the new value will not yet be off-heap
        Object callbackArg = event.getRawCallbackArgument();
        boolean isCreate = event.isCreate();
        Object result = mySRP.put(key, value, event.getDeltaBytes(), event, op, requireOldValue,
            expectedOldValue, callbackArg, isCreate);

        // serverProxy returns null when cache is closing
        getCancelCriterion().checkCancelInProgress(null);
        // if concurrent map operations failed we don't want the region map
        // to apply the operation and need to throw an exception
        if (op.guaranteesOldValue()) {
          if (op != Operation.REPLACE || requireOldValue) {
            event.setConcurrentMapOldValue(result);
          }
          if (op == Operation.PUT_IF_ABSENT) {
            checkPutIfAbsentResult(event, value, result);
          } else if (op == Operation.REPLACE) {
            if (requireOldValue && result == null) {
              throw new EntryNotFoundException("entry not found for replace");
            }
            if (!requireOldValue && result != null && !((Boolean) result)) {
              // customers don't see this exception
              throw new EntryNotFoundException("entry found with wrong value");
            }
          }
        }
      }
    }
  }

  @VisibleForTesting
  void checkPutIfAbsentResult(EntryEventImpl event, Object value, Object result) {
    if (result != null) {
      throw new EntryNotFoundException("entry existed for putIfAbsent");
    }
  }

  /**
   * Destroy an entry on the server given its event.
   *
   * @since GemFire 5.7
   */
  void serverDestroy(EntryEventImpl event, Object expectedOldValue) {
    if (event.getOperation().isDistributed()) {
      ServerRegionProxy mySRP = getServerProxy();
      if (mySRP != null) {
        // send to server
        Object key = event.getKey();
        Object callbackArg = event.getRawCallbackArgument();
        Object result =
            mySRP.destroy(key, expectedOldValue, event.getOperation(), event, callbackArg);
        if (result instanceof EntryNotFoundException) {
          throw (EntryNotFoundException) result;
        }
      }
    }
  }

  /**
   * @return true if cacheWrite was performed
   * @see DistributedRegion#cacheWriteBeforeRegionDestroy(RegionEventImpl)
   */
  boolean cacheWriteBeforeRegionDestroy(RegionEventImpl event)
      throws CacheWriterException, TimeoutException {
    boolean result = false;
    // copy into local var to prevent race condition
    CacheWriter writer = basicGetWriter();
    if (writer != null) {
      final long start = getCachePerfStats().startCacheWriterCall();
      try {
        writer.beforeRegionDestroy(event);
      } finally {
        getCachePerfStats().endCacheWriterCall(start);
      }
      result = true;
    }
    serverRegionDestroy(event);
    return result;
  }

  private void cacheWriteBeforeRegionClear(RegionEventImpl event)
      throws CacheWriterException, TimeoutException {
    // copy into local var to prevent race condition
    CacheWriter writer = basicGetWriter();
    if (writer != null) {
      final long start = getCachePerfStats().startCacheWriterCall();
      try {
        writer.beforeRegionClear(event);
      } finally {
        getCachePerfStats().endCacheWriterCall(start);
      }
    }
    serverRegionClear(event);
  }

  @Override
  public void cacheWriteBeforePut(EntryEventImpl event, Set netWriteRecipients,
      CacheWriter localWriter, boolean requireOldValue, Object expectedOldValue)
      throws CacheWriterException, TimeoutException {
    Assert.assertTrue(netWriteRecipients == null);
    Operation operation = event.getOperation();
    boolean isPutIfAbsentOrReplace =
        operation == Operation.PUT_IF_ABSENT || operation == Operation.REPLACE;
    if (!isPutIfAbsentOrReplace && localWriter != null && !event.inhibitAllNotifications()) {
      final long start = getCachePerfStats().startCacheWriterCall();
      final boolean newEntry = event.getOperation().isCreate();
      event.setReadOldValueFromDisk(true);
      try {
        if (!newEntry) {
          localWriter.beforeUpdate(event);
        } else {
          localWriter.beforeCreate(event);
        }
      } finally {
        event.setReadOldValueFromDisk(false);
        getCachePerfStats().endCacheWriterCall(start);
      }
    }
    serverPut(event, requireOldValue, expectedOldValue);
  }

  void validateArguments(Object key, Object value, Object aCallbackArgument) {
    validateKey(key);
    validateValue(value);
  }

  void validateKey(Object key) {
    if (key == null) {
      throw new NullPointerException(
          "key cannot be null");
    }

    // check validity of key against keyConstraint
    if (keyConstraint != null) {
      if (!keyConstraint.isInstance(key)) {
        throw new ClassCastException(
            String.format("key ( %s ) does not satisfy keyConstraint ( %s )",
                key.getClass().getName(), keyConstraint.getName()));
      }
    }

    // We don't need to check that the key is Serializable. Instead,
    // we let the lower-level (data) serialization mechanism take care
    // of this for us.
  }

  /**
   * @since GemFire 5.0.2
   */
  private final boolean doExpensiveValidations =
      Boolean.getBoolean(GeodeGlossary.GEMFIRE_PREFIX + "DO_EXPENSIVE_VALIDATIONS");

  /**
   * the number of tombstone entries in the RegionMap
   */
  private final AtomicInteger tombstoneCount = new AtomicInteger();

  /**
   * a boolean for issuing a client/server configuration mismatch message
   */
  private boolean concurrencyMessageIssued;

  /**
   * Starting in 3.5, we don't check to see if the value is {@code Serializable}. We instead rely on
   * the actual serialization (which happens in-thread with the put) to tell us if there are any
   * problems.
   */
  private void validateValue(Object value) {
    // check validity of value against valueConstraint
    if (valueConstraint != null) {
      if (value != null) {
        if (value instanceof CachedDeserializable) {
          if (doExpensiveValidations) {
            value = ((CachedDeserializable) value).getDeserializedValue(null, null);
          } else {
            return;
          }
        }
        if (!valueConstraint.isInstance(value)) {
          String valueClassName = value.getClass().getName();
          // check for a REST object, which has a @type field denoting its class
          if (value instanceof PdxInstance) {
            PdxInstance pdx = (PdxInstance) value;
            if (pdx.getClassName().equals(JSONFormatter.JSON_CLASSNAME)) {
              Object type = pdx.getField("@type");
              if (type instanceof String) {
                valueClassName = (String) type;
              } else {
                return;
              }
            }
            if (valueClassName.equals(valueConstraint.getName())) {
              return;
            }
          }
          throw new ClassCastException(
              String.format("value ( %s ) does not satisfy valueConstraint ( %s )",
                  valueClassName, valueConstraint.getName()));
        }
      }
    }
  }

  @Override
  public CachePerfStats getCachePerfStats() {
    // return this.cache.getCachePerfStats();
    return cachePerfStats;
  }

  @Override
  public CachePerfStats getRegionPerfStats() {
    return cachePerfStats;
  }

  /**
   * regions track the number of tombstones their map holds for size calculations
   */
  public void incTombstoneCount(int delta) {
    tombstoneCount.addAndGet(delta);
    cachePerfStats.incTombstoneCount(delta);

    // don't include the tombstones in any of our entry count stats
    cachePerfStats.incEntryCount(-delta);
  }

  @Override
  public int getTombstoneCount() {
    return tombstoneCount.get();
  }

  @Override
  public void scheduleTombstone(RegionEntry entry, VersionTag destroyedVersion) {
    scheduleTombstone(entry, destroyedVersion, false);
  }

  @Override
  public void scheduleTombstone(RegionEntry entry, VersionTag destroyedVersion,
      boolean reschedule) {
    if (destroyedVersion == null) {
      throw new NullPointerException("destroyed version tag cannot be null");
    }

    if (!reschedule) {
      incTombstoneCount(1);
    }

    if (logger.isTraceEnabled(LogMarker.TOMBSTONE_COUNT_VERBOSE)) {
      logger.trace(LogMarker.TOMBSTONE_COUNT_VERBOSE,
          "{} tombstone for {} version={} count is {} entryMap size is {}",
          reschedule ? "rescheduling" : "scheduling", entry.getKey(),
          entry.getVersionStamp().asVersionTag(), tombstoneCount.get(),
          entries.size()/* , new Exception("stack trace") */);
    }
    getGemFireCache().getTombstoneService().scheduleTombstone(this, entry, destroyedVersion);
  }

  @Override
  public void rescheduleTombstone(RegionEntry entry, VersionTag version) {
    scheduleTombstone(entry, version, true);
  }

  @Override
  public void unscheduleTombstone(RegionEntry entry) {
    unscheduleTombstone(entry, true);
  }

  private void unscheduleTombstone(RegionEntry entry, boolean validate) {
    incTombstoneCount(-1);
    if (logger.isTraceEnabled(LogMarker.TOMBSTONE_VERBOSE)) {
      logger.trace(LogMarker.TOMBSTONE_VERBOSE,
          "unscheduling tombstone for {} count is {} entryMap size is {}", entry.getKey(),
          tombstoneCount.get(), entries.size()/* , new Exception("stack trace") */);
    }
    if (logger.isTraceEnabled(LogMarker.TOMBSTONE_COUNT_VERBOSE) && validate) {
      if (entries instanceof AbstractRegionMap) {
        ((AbstractRegionMap) entries).verifyTombstoneCount(tombstoneCount);
      }
    }
    // we don't have to remove the entry from the sweeper since the version has
    // changed. It would be costly to iterate over the tombstone list for
    // every tombstone exhumed while holding the entry's lock
    // this.cache.getTombstoneService().unscheduleTombstone(entry);
  }

  /**
   * remove any tombstones from the given member that are <= the given version
   *
   * @param eventID event identifier for the GC operation
   * @param clientRouting routing info (if null a routing is computed)
   */
  public void expireTombstones(Map<VersionSource, Long> regionGCVersions, EventID eventID,
      FilterInfo clientRouting) {
    if (!getConcurrencyChecksEnabled()) {
      return;
    }
    Set<Object> keys = null;
    if (!versionVector.containsTombstoneGCVersions(regionGCVersions)) {
      keys = cache.getTombstoneService().gcTombstones(this, regionGCVersions,
          needsTombstoneGCKeysForClients(eventID, clientRouting));
      if (keys == null) {
        // deltaGII prevented tombstone GC
        return;
      }
    }
    if (eventID != null) {
      // old members might not send an eventID
      notifyClientsOfTombstoneGC(regionGCVersions, keys, eventID, clientRouting);
    }
  }

  public void expireTombstoneKeys(Set<Object> tombstoneKeys) {
    if (getConcurrencyChecksEnabled()) {
      cache.getTombstoneService().gcTombstoneKeys(this, tombstoneKeys);
    }
  }

  boolean needsTombstoneGCKeysForClients(EventID eventID, FilterInfo clientRouting) {
    return false;
  }

  /**
   * pass tombstone garbage-collection info to clients
   *
   * @param eventID the ID of the event
   * @param routing routing info (routing is computed if this is null)
   */
  void notifyClientsOfTombstoneGC(Map<VersionSource, Long> regionGCVersions,
      Set<Object> keysRemoved, EventID eventID, FilterInfo routing) {
    if (CacheClientNotifier.singletonHasClientProxies()) {
      // Only route the event to clients interested in the partitioned region.
      // We do this by constructing a region-level event and then use it to
      // have the filter profile ferret out all of the clients that have interest
      // in this region
      FilterProfile fp = getFilterProfile();
      if (fp != null || routing != null) {
        RegionEventImpl regionEvent =
            new RegionEventImpl(this, Operation.REGION_DESTROY, null, true, getMyId());
        regionEvent.setEventID(eventID);
        if (routing == null) {
          routing = fp.getLocalFilterRouting(regionEvent);
        }
        regionEvent.setLocalFilterInfo(routing);
        ClientUpdateMessage clientMessage =
            ClientTombstoneMessage.gc(this, regionGCVersions, eventID);
        CacheClientNotifier.notifyClients(regionEvent, clientMessage);
      }
    }
  }

  /**
   * local regions do not perform versioning
   */
  boolean shouldGenerateVersionTag(RegionEntry entry, EntryEventImpl event) {
    if (getDataPolicy().withPersistence()) {
      return true;
    }
    return getConcurrencyChecksEnabled()
        && (entry.getVersionStamp().hasValidVersion() || getDataPolicy().withReplication());
  }

  void enableConcurrencyChecks() {
    setConcurrencyChecksEnabled(true);
    if (getDataPolicy().withStorage()) {
      RegionEntryFactory versionedEntryFactory = entries.getEntryFactory().makeVersioned();
      Assert.assertTrue(entries.isEmpty(),
          "RegionMap should be empty but was of size:" + entries.size());
      entries.setEntryFactory(versionedEntryFactory);
    }
  }

  /**
   * validate attributes of subregion being created, sent to parent
   *
   * @throws IllegalArgumentException if attrs is null
   * @throws IllegalStateException if attributes are invalid
   */
  private void validateSubregionAttributes(RegionAttributes attrs) {
    if (attrs == null) {
      throw new IllegalArgumentException(
          "region attributes must not be null");
    }
    if (scope == Scope.LOCAL && attrs.getScope() != Scope.LOCAL) {
      throw new IllegalStateException(
          "A region with Scope.LOCAL can only have subregions with Scope.LOCAL");
    }
  }

  /**
   * Returns the value of the entry with the given key as it is stored in the VM. This means that if
   * the value is invalid, the invalid token will be returned. If the value is a
   * {@link CachedDeserializable}received from another VM, that object will be returned. If the
   * value does not reside in the VM because it has been overflowed to disk, {@code null} will be
   * returned. This method is intended for testing.testing purposes only.
   *
   * @throws EntryNotFoundException No entry with {@code key} exists
   * @see RegionMap#getEntry
   * @since GemFire 3.2
   */
  @Override
  public Object getValueInVM(Object key) throws EntryNotFoundException {
    return basicGetValueInVM(key, true);
  }

  /**
   * @param rememberRead true if read should be remembered in a transaction
   * @since GemFire 5.5
   */
  private Object basicGetValueInVM(Object key, boolean rememberRead) throws EntryNotFoundException {
    return getDataView().getValueInVM(getKeyInfo(key), this, rememberRead);
  }

  @Retained
  Object nonTXbasicGetValueInVM(KeyInfo keyInfo) {
    RegionEntry regionEntry = entries.getEntry(keyInfo.getKey());
    if (regionEntry == null) {
      checkEntryNotFound(keyInfo.getKey());
    }
    // OFFHEAP returned to callers
    // The warning for regionEntry possibly being null is incorrect, as checkEntryNotFound() always
    // throws, making the following line unreachable if regionEntry is null
    Object value = regionEntry.getValueInVM(this); // lgtm [java/dereferenced-value-may-be-null]
    if (Token.isRemoved(value)) {
      checkEntryNotFound(keyInfo.getKey());
    }
    if (value == Token.NOT_AVAILABLE) {
      return null;
    }
    return value;
  }

  /**
   * This is a test hook method used to find out what keys the current tx has read or written.
   *
   * @return an unmodifiable set of keys that have been read or written by the transaction on this
   *         thread.
   * @throws IllegalStateException if not tx in progress
   * @since GemFire 5.5
   */
  @VisibleForTesting
  public Set testHookTXKeys() {
    if (!isTX()) {
      throw new IllegalStateException(
          "tx not in progress");
    }
    TXStateProxyImpl tx = (TXStateProxyImpl) getTXState();
    if (!tx.isRealDealLocal()) {
      return Collections.emptySet();
    }
    TXRegionState txr = txReadRegion();
    if (txr == null) {
      return Collections.emptySet();
    }
    return txr.getEntryKeys();
  }

  /**
   * Returns the value of the entry with the given key as it is stored on disk. While the value may
   * be read from disk, it is <b>not</b> stored into the entry in the VM. This method is intended
   * for testing purposes only.
   *
   * @throws EntryNotFoundException No entry with {@code key} exists
   * @throws IllegalStateException If this region does not write to disk
   * @see RegionEntry#getValueOnDisk
   * @since GemFire 3.2
   */
  @Override
  public Object getValueOnDisk(Object key) throws EntryNotFoundException {
    // Ok for this to ignore tx state
    RegionEntry re = entries.getEntry(key);
    if (re == null) {
      throw new EntryNotFoundException(key.toString());
    }
    return re.getValueOnDisk(this);
  }

  /**
   * Gets the value from VM, if present, otherwise from disk without fault in.
   */
  @Override
  public Object getValueInVMOrDiskWithoutFaultIn(Object key) throws EntryNotFoundException {
    RegionEntry re = entries.getEntry(key);
    if (re == null) {
      throw new EntryNotFoundException(key.toString());
    }
    return re.getValueInVMOrDiskWithoutFaultIn(this);
  }

  /**
   * Returns the value of the entry with the given key as it is stored present in the buffer or
   * disk. While the value may be read from disk or buffer, it is <b>not</b> stored into the entry
   * in the VM. This is different from getValueonDisk in that it checks for a value both in async
   * buffers ( subject to async mode enabled) as well as Disk
   *
   * @throws EntryNotFoundException No entry with {@code key} exists
   * @throws IllegalStateException If this region does not write to disk
   * @see RegionEntry#getValueOnDisk
   * @since GemFire 5.1
   */
  @Override
  public Object getValueOnDiskOrBuffer(Object key) throws EntryNotFoundException {
    // Ok for this to ignore tx state
    RegionEntry re = entries.getEntry(key);
    if (re == null) {
      throw new EntryNotFoundException(key.toString());
    }
    return re.getValueOnDiskOrBuffer(this);
  }

  /**
   * Does a get that attempts to not fault values in from disk or make the entry the most recent in
   * the LRU.
   *
   * @param adamant fault in and affect LRU as a last resort
   * @param allowTombstone also return Token.TOMBSTONE if the entry is deleted
   * @param serializedFormOkay if the serialized form can be returned
   */
  Object getNoLRU(Object key, boolean adamant, boolean allowTombstone, boolean serializedFormOkay) {
    Object value = null;
    try {
      value = getValueInVM(key); // OFFHEAP deserialize
      if (value == null) {
        // must be on disk
        // fault it in w/o putting it back in the region
        value = getValueOnDiskOrBuffer(key);
        if (value == null) {
          // try memory one more time in case it was already faulted back in
          value = getValueInVM(key); // OFFHEAP deserialize
          if (value == null) {
            if (adamant) {
              value = get(key);
            }
          } else {
            if (!serializedFormOkay && value instanceof CachedDeserializable) {
              value =
                  ((CachedDeserializable) value).getDeserializedValue(this, getRegionEntry(key));
            }
          }
        }
      } else {
        if (!serializedFormOkay && value instanceof CachedDeserializable) {
          value = ((CachedDeserializable) value).getDeserializedValue(this, getRegionEntry(key));
        }
      }
    } catch (EntryNotFoundException ignore) {
      // just return null;
    }
    if (value == Token.TOMBSTONE && !allowTombstone) {
      value = null;
    }
    return value;
  }

  /**
   * Bump this number any time an incompatible change is made to the snapshot format.
   */
  private static final byte SNAPSHOT_VERSION = 1;

  private static final byte SNAPSHOT_VALUE_OBJ = 23;

  private static final byte SNAPSHOT_VALUE_INVALID = 24;

  private static final byte SNAPSHOT_VALUE_LOCAL_INVALID = 25;

  @Override
  public void saveSnapshot(OutputStream outputStream) throws IOException {
    if (isProxy()) {
      throw new UnsupportedOperationException(
          String.format("Regions with DataPolicy %s do not support saveSnapshot.",
              getDataPolicy()));
    }
    checkForNoAccess();
    try (DataOutputStream out = new DataOutputStream(outputStream)) {
      out.writeByte(SNAPSHOT_VERSION);
      for (Object entryObject : entrySet(false)) {
        Entry entry = (Entry) entryObject;
        try {
          Object key = entry.getKey();
          Object value = entry.getValue();
          if (value == Token.TOMBSTONE) {
            continue;
          }
          DataSerializer.writeObject(key, out);
          if (value == null) {
            NonTXEntry lre = (NonTXEntry) entry;
            RegionEntry re = lre.getRegionEntry();
            // OFFHEAP: incrc, copy info heap cd for serialization, decrc
            value = re.getValue(this);
            if (value == Token.INVALID) {
              out.writeByte(SNAPSHOT_VALUE_INVALID);
            } else if (value == Token.LOCAL_INVALID) {
              out.writeByte(SNAPSHOT_VALUE_LOCAL_INVALID);
            } else {
              out.writeByte(SNAPSHOT_VALUE_OBJ);
              DataSerializer.writeObject(value, out);
            }
          } else {
            out.writeByte(SNAPSHOT_VALUE_OBJ);
            DataSerializer.writeObject(value, out);
          }
        } catch (EntryDestroyedException ignore) {
          // continue to next entry
        }
      }
      // write NULL terminator
      DataSerializer.writeObject(null, out);
    }
  }

  @Override
  public void loadSnapshot(InputStream inputStream)
      throws CacheWriterException, TimeoutException, ClassNotFoundException, IOException {
    if (isProxy()) {
      throw new UnsupportedOperationException(
          String.format("Regions with DataPolicy %s do not support loadSnapshot.",
              getDataPolicy()));
    }
    if (inputStream == null) {
      throw new NullPointerException(
          "InputStream must not be null.");
    }
    checkReadiness();
    checkForLimitedOrNoAccess();
    RegionEventImpl event = new RegionEventImpl(this, Operation.REGION_LOAD_SNAPSHOT, null, false,
        getMyId(), generateEventID()/* generate EventID */);
    reinitialize(inputStream, event);
  }

  @Override
  public void registerInterest(Object key) {
    registerInterest(key, false);
  }

  @Override
  public void registerInterest(Object key, boolean isDurable) {
    registerInterest(key, isDurable, true);
  }

  @Override
  public void registerInterest(Object key, boolean isDurable, boolean receiveValues) {
    registerInterest(key, InterestResultPolicy.DEFAULT, isDurable, receiveValues);
  }

  public void startRegisterInterest() {
    getImageState().writeLockRI();
    try {
      cache.registerInterestStarted();
      riCnt++;
    } finally {
      getImageState().writeUnlockRI();
    }
  }

  public void finishRegisterInterest() {
    if (Boolean.getBoolean(GeodeGlossary.GEMFIRE_PREFIX + "testing.slow-interest-recovery")) {
      if (logger.isDebugEnabled()) {
        logger.debug("slowing interest recovery...");
      }
      try {
        Thread.sleep(20000);
      } catch (InterruptedException ignore) {
        Thread.currentThread().interrupt();
        return;
      }
      if (logger.isDebugEnabled()) {
        logger.debug("done slowing interest recovery");
      }
    }

    boolean gotLock = false;
    try {
      getImageState().writeLockRI();
      gotLock = true;
      riCnt--;
      Assert.assertTrue(riCnt >= 0, "register interest count can not be < 0 ");
      if (riCnt == 0) {
        // remove any destroyed entries from the region and clear the hashset
        destroyEntriesAndClearDestroyedKeysSet();
      }
    } finally {
      cache.registerInterestCompleted();
      if (gotLock) {
        getImageState().writeUnlockRI();
      }
    }
  }

  // TODO: this is distressingly similar to code in the client.internal package
  private void processSingleInterest(Object key, int interestType,
      InterestResultPolicy interestResultPolicy, boolean isDurable,
      boolean receiveUpdatesAsInvalidates) {
    final ServerRegionProxy proxy = getServerProxy();
    if (proxy == null) {
      throw new UnsupportedOperationException(
          "Interest registration requires a Pool");
    }
    if (isDurable && !proxy.getPool().isDurableClient()) {
      throw new IllegalStateException(
          "Durable flag only applicable for durable clients.");
    }
    if (!proxy.getPool().getSubscriptionEnabled()) {
      String msg = "Interest registration requires a pool whose queue is enabled.";
      throw new SubscriptionNotEnabledException(msg);
    }

    if (getAttributes().getDataPolicy().withReplication()
        && !getAttributes().getScope().isLocal()) {
      throw new UnsupportedOperationException(
          "Interest registration not supported on replicated regions");
    }

    if (key == null) {
      throw new IllegalArgumentException(
          "interest key must not be null");
    }

    // Sequence of events, on a single entry:
    // 1. Client puts value (a).
    // 2. Server updates with value (b). Client never gets the update,
    // because it isn't interested in that key.
    // 3. Client registers interest.
    // At this point, there is an entry in the local cache, but it is
    // inconsistent with the server.
    //
    // Because of this, we must _always_ destroy and refetch affected values
    // during registerInterest.

    startRegisterInterest();
    try {
      clearKeysOfInterest(key, interestType, interestResultPolicy);
      // Checking for the Dunit test(testRegisterInterest_Destroy_Concurrent) flag
      if (PoolImpl.BEFORE_REGISTER_CALLBACK_FLAG) {
        ClientServerObserver bo = ClientServerObserverHolder.getInstance();
        bo.beforeInterestRegistration();
      } // Test Code Ends

      final byte regionDataPolicy = getAttributes().getDataPolicy().ordinal;
      List serverKeys;

      switch (interestType) {
        case InterestType.FILTER_CLASS:
          serverKeys = proxy.registerInterest(key, interestType, interestResultPolicy, isDurable,
              receiveUpdatesAsInvalidates, regionDataPolicy);
          break;

        case InterestType.KEY:
          if (key instanceof String && key.equals("ALL_KEYS")) {
            logger.warn(
                "Usage of registerInterest('ALL_KEYS') has been deprecated.  Please use registerInterestForAllKeys()");
            serverKeys = proxy.registerInterest(".*", InterestType.REGULAR_EXPRESSION,
                interestResultPolicy, isDurable, receiveUpdatesAsInvalidates, regionDataPolicy);
          } else {
            if (key instanceof List) {
              logger.warn(
                  "Usage of registerInterest(List) has been deprecated. Please use registerInterestForKeys(Iterable)");
              serverKeys = proxy.registerInterestList((List) key, interestResultPolicy, isDurable,
                  receiveUpdatesAsInvalidates, regionDataPolicy);
            } else {
              serverKeys = proxy.registerInterest(key, InterestType.KEY, interestResultPolicy,
                  isDurable, receiveUpdatesAsInvalidates, regionDataPolicy);
            }
          }
          break;

        case InterestType.OQL_QUERY:
          serverKeys = proxy.registerInterest(key, InterestType.OQL_QUERY, interestResultPolicy,
              isDurable, receiveUpdatesAsInvalidates, regionDataPolicy);
          break;

        case InterestType.REGULAR_EXPRESSION: {
          String regex = (String) key;
          // compile regex throws java.util.regex.PatternSyntaxException if invalid
          // we do this before sending to the server because it's more efficient
          // and the client is not receiving exception messages properly
          Pattern.compile(regex);
          serverKeys = proxy.registerInterest(regex, InterestType.REGULAR_EXPRESSION,
              interestResultPolicy, isDurable, receiveUpdatesAsInvalidates, regionDataPolicy);
          break;

        }
        default:
          throw new InternalGemFireError(
              "unknown interest type");
      }

      boolean finishedRefresh = false;
      try {
        refreshEntriesFromServerKeys(null, serverKeys, interestResultPolicy);
        finishedRefresh = true;
      } finally {
        if (!finishedRefresh) {
          // unregister before throwing the exception caused by the refresh
          switch (interestType) {
            case InterestType.FILTER_CLASS:
              proxy.unregisterInterest(key, interestType, false, false);
              break;

            case InterestType.KEY:
              if (key instanceof String && key.equals("ALL_KEYS")) {
                proxy.unregisterInterest(".*", InterestType.REGULAR_EXPRESSION, false, false);
              } else if (key instanceof List) {
                proxy.unregisterInterestList((List) key, false, false);
              } else {
                proxy.unregisterInterest(key, InterestType.KEY, false, false);
              }
              break;

            case InterestType.OQL_QUERY:
              proxy.unregisterInterest(key, InterestType.OQL_QUERY, false, false);
              break;

            case InterestType.REGULAR_EXPRESSION: {
              proxy.unregisterInterest(key, InterestType.REGULAR_EXPRESSION, false, false);
              break;

            }
            default:
              throw new InternalGemFireError(
                  "unknown interest type");
          }
        }
      }
    } finally {
      finishRegisterInterest();
    }
  }

  @Override
  public void registerInterest(Object key, InterestResultPolicy policy) {
    registerInterest(key, policy, false);
  }

  @Override
  public void registerInterest(Object key, InterestResultPolicy policy, boolean isDurable) {
    registerInterest(key, policy, isDurable, true);
  }

  @Override
  public void registerInterest(Object key, InterestResultPolicy policy, boolean isDurable,
      boolean receiveValues) {
    processSingleInterest(key, InterestType.KEY, policy, isDurable, !receiveValues);
  }

  @Override
  public void registerInterestRegex(String regex) {
    registerInterestRegex(regex, false);
  }

  @Override
  public void registerInterestRegex(String regex, boolean isDurable) {
    registerInterestRegex(regex, InterestResultPolicy.DEFAULT, isDurable, true);
  }

  @Override
  public void registerInterestRegex(String regex, boolean isDurable, boolean receiveValues) {
    registerInterestRegex(regex, InterestResultPolicy.DEFAULT, isDurable, receiveValues);
  }

  @Override
  public void registerInterestRegex(String regex, InterestResultPolicy policy) {
    registerInterestRegex(regex, policy, false);
  }

  @Override
  public void registerInterestRegex(String regex, InterestResultPolicy policy, boolean isDurable) {
    registerInterestRegex(regex, policy, isDurable, true);
  }

  @Override
  public void registerInterestRegex(String regex, InterestResultPolicy policy, boolean isDurable,
      boolean receiveValues) {
    processSingleInterest(regex, InterestType.REGULAR_EXPRESSION, policy, isDurable,
        !receiveValues);
  }

  @Override
  public void unregisterInterest(Object key) {
    ServerRegionProxy proxy = getServerProxy();
    if (proxy != null) {
      // Keep support for "ALL_KEYS" in 4.2.x
      if (key instanceof String && key.equals("ALL_KEYS")) {
        proxy.unregisterInterest(".*", InterestType.REGULAR_EXPRESSION, false, false);
      } else if (key instanceof List) {
        proxy.unregisterInterestList((List) key, false, false);
      } else {
        proxy.unregisterInterest(key, InterestType.KEY, false, false);
      }
    } else {
      throw new UnsupportedOperationException(
          "Interest unregistration requires a pool.");
    }
  }

  @Override
  public void unregisterInterestRegex(String regex) {
    ServerRegionProxy proxy = getServerProxy();
    if (proxy != null) {
      proxy.unregisterInterest(regex, InterestType.REGULAR_EXPRESSION, false, false);
    } else {
      throw new UnsupportedOperationException(
          "Interest unregistration requires a pool.");
    }
  }

  @Override
  public List getInterestList() {
    ServerRegionProxy proxy = getServerProxy();
    if (proxy != null) {
      return proxy.getInterestList(InterestType.KEY);
    }
    throw new UnsupportedOperationException(
        "Interest unregistration requires a pool.");
  }

  /**
   * finds the keys in this region using the given interestType and argument. Currently only
   * InterestType.REGULAR_EXPRESSION and InterestType.KEY are supported
   *
   * @param interestType an InterestType value
   * @param interestArg the associated argument (regex string, key or key list, etc)
   * @param allowTombstones whether to return destroyed entries
   * @return a set of the keys matching the given criterion
   */
  public Set getKeysWithInterest(int interestType, Object interestArg, boolean allowTombstones) {
    Set ret;
    if (interestType == InterestType.REGULAR_EXPRESSION) {
      if (interestArg == null || ".*".equals(interestArg)) {
        ret = new HashSet(keySet(allowTombstones));
      } else {
        ret = new HashSet();
        // Handle the regex pattern
        if (!(interestArg instanceof String)) {
          throw new IllegalArgumentException(
              "regular expression argument was not a String");
        }

        Pattern keyPattern = Pattern.compile((String) interestArg);
        for (Object entryKey : keySet(allowTombstones)) {
          if (!(entryKey instanceof String)) {
            // key is not a String, cannot apply regex to this entry
            continue;
          }
          if (!keyPattern.matcher((String) entryKey).matches()) {
            // key does not match the regex, this entry should not be returned.
            continue;
          }
          ret.add(entryKey);
        }
      }

    } else if (interestType == InterestType.KEY) {
      if (interestArg instanceof List) {
        ret = new HashSet(); // TODO optimize initial size
        List keyList = (List) interestArg;
        for (Object entryKey : keyList) {
          if (containsKey(entryKey) || allowTombstones && containsTombstone(entryKey)) {
            ret.add(entryKey);
          }
        }
      } else {
        ret = new HashSet();
        if (containsKey(interestArg)
            || allowTombstones && containsTombstone(interestArg)) {
          ret.add(interestArg);
        }
      }

    } else if (interestType == InterestType.FILTER_CLASS) {
      throw new UnsupportedOperationException(
          "InterestType.FILTER_CLASS not yet supported");

    } else if (interestType == InterestType.OQL_QUERY) {
      throw new UnsupportedOperationException(
          "InterestType.OQL_QUERY not yet supported");

    } else {
      throw new IllegalArgumentException(String.format("Unsupported interest type: %s",
          interestType));
    }
    return ret;
  }

  @Override
  public List<String> getInterestListRegex() {
    ServerRegionProxy proxy = getServerProxy();
    if (proxy != null) {
      return proxy.getInterestList(InterestType.REGULAR_EXPRESSION);
    }
    throw new UnsupportedOperationException(
        "Interest list retrieval requires a pool.");
  }

  @Override
  public Set keySetOnServer() {
    ServerRegionProxy proxy = getServerProxy();
    if (proxy != null) {
      return proxy.keySet();
    }
    throw new UnsupportedOperationException(
        "Server keySet requires a pool.");
  }

  @Override
  public boolean containsKeyOnServer(Object key) {
    checkReadiness();
    checkForNoAccess();
    ServerRegionProxy proxy = getServerProxy();
    if (proxy != null) {
      return proxy.containsKey(key);
    }
    throw new UnsupportedOperationException(
        "Server keySet requires a pool.");
  }

  @Override
  public int sizeOnServer() {
    ServerRegionProxy proxy = getServerProxy();
    if (proxy != null) {
      return proxy.size();
    }
    throw new UnsupportedOperationException(
        "sizeOnServer requires a pool.");
  }

  @Override
  public boolean isEmptyOnServer() {
    ServerRegionProxy proxy = getServerProxy();
    if (proxy != null) {
      return proxy.size() == 0;
    }
    throw new UnsupportedOperationException(
        "isEmptyOnServer requires a pool.");
  }

  /**
   * WARNING: this method is overridden in subclasses.
   */
  void localDestroyNoCallbacks(Object key) {
    if (logger.isDebugEnabled()) {
      logger.debug("localDestroyNoCallbacks key={}", key);
    }
    checkReadiness();
    validateKey(key);
    @Released
    EntryEventImpl event = entryEventFactory.create(this, Operation.LOCAL_DESTROY, key, false,
        getMyId(), false, true);
    try {
      basicDestroy(event, false, null); // expectedOldValue
    } catch (CacheWriterException e) {
      // cache writer not called
      throw new Error(
          "Cache Writer should not have been called for localDestroy",
          e);
    } catch (TimeoutException e) {
      // no distributed lock
      throw new Error(
          "No distributed lock should have been attempted for localDestroy",
          e);
    } catch (EntryNotFoundException ignore) {
      // not a problem
    } finally {
      event.release();
    }
  }

  /**
   * Do localDestroy on a list of keys, if they exist
   *
   * @param keys the list of arrays of keys to invalidate
   * @see #registerInterest(Object)
   */
  private void clearViaList(List keys) {
    for (Object entryObject : entrySet(false)) {
      Entry entry = (Entry) entryObject;
      try {
        Object entryKey = entry.getKey();
        boolean match = false;
        for (Object key : keys) {
          if (entryKey.equals(key)) {
            match = true;
            break;
          }
        } // for
        if (!match) {
          continue;
        }
        localDestroyNoCallbacks(entryKey);
      } catch (EntryDestroyedException ignore) {
        // ignore
      }
    }
  }

  /**
   * do a localDestroy on all matching keys
   *
   * @param key the regular expression to match on
   * @see #registerInterestRegex(String)
   */
  private void clearViaRegEx(String key) {
    // TODO: if (key.equals(".*)) then cmnClearRegionNoCallbacks
    Pattern keyPattern = Pattern.compile(key);
    for (Object o : entrySet(false)) {
      Entry entry = (Entry) o;
      try {
        Object entryKey = entry.getKey();
        if (!(entryKey instanceof String)) {
          continue;
        }
        if (!keyPattern.matcher((String) entryKey).matches()) {
          // key does not match the regex, this entry should not be returned.
          continue;
        }
        localDestroyNoCallbacks(entryKey);
      } catch (EntryDestroyedException ignore) {
        // ignore
      }
    }
  }

  /**
   * do a localDestroy on all matching keys
   *
   * @param key the regular expression to match on
   */
  private void clearViaFilterClass(String key) {
    InterestFilter filter;
    try {
      Class filterClass = ClassLoadUtil.classFromName(key);
      filter = (InterestFilter) filterClass.newInstance();
    } catch (ClassNotFoundException e) {
      throw new RuntimeException(
          String.format("Class %s not found in classpath.", key), e);
    } catch (Exception e) {
      throw new RuntimeException(
          String.format("Class %s could not be instantiated.", key), e);
    }

    for (Object entryObject : entrySet(false)) {
      Entry entry = (Entry) entryObject;
      try {
        Object entryKey = entry.getKey();
        if (!(entryKey instanceof String)) {
          continue;
        }
        InterestEvent e = new InterestEvent(entryKey, entry.getValue(), true);
        if (!filter.notifyOnRegister(e)) {
          // the filter does not want to know about this entry, so skip it.
          continue;
        }
        localDestroyNoCallbacks(entryKey);
      } catch (EntryDestroyedException ignore) {
        // ignore
      }
    }
  }

  /**
   * Do a localDestroy of all matching keys
   */
  private void clearViaQuery(String query) {
    throw new InternalGemFireError("not yet supported");
  }

  /**
   * Refresh local entries based on server's list of keys
   */
  public void refreshEntriesFromServerKeys(Connection con, List serverKeys,
      InterestResultPolicy interestResultPolicy) {
    if (serverKeys == null) {
      return;
    }
    ServerRegionProxy proxy = getServerProxy();
    if (logger.isDebugEnabled()) {
      logKeys(serverKeys, interestResultPolicy);
    }

    if (interestResultPolicy == InterestResultPolicy.NONE) {
      return; // done
    }

    if (logger.isDebugEnabled()) {
      logger.debug("refreshEntries region={}", getFullPath());
    }
    for (Object serverKey : serverKeys) {
      ArrayList keysList = (ArrayList) serverKey;
      // The chunk can contain null data if there are no entries on the server
      // corresponding to the requested keys
      if (keysList == null) {
        continue;
      }
      if (EntryLogger.isEnabled()) {
        if (con != null) {
          Endpoint endpoint = con.getEndpoint();
          if (endpoint != null) {
            EntryLogger.setSource(endpoint.getMemberId(), "RIGII");
          }
        }
      }
      try {
        List list = new ArrayList(keysList);
        if (interestResultPolicy != InterestResultPolicy.KEYS_VALUES) {
          for (Object currentKey : keysList) {
            // Don't apply riResponse if the entry was destroyed when
            // ri is in progress
            if (currentKey == null || getImageState().hasDestroyedEntry(currentKey)) {
              list.remove(currentKey);
            }
          }
        }
        if (interestResultPolicy == InterestResultPolicy.KEYS) {
          // Attempt to create an invalid in without overwriting
          if (!isProxy()) {
            for (Object currentKey : list) {
              entries.initialImagePut(currentKey, 0, Token.LOCAL_INVALID, false, false, null,
                  null, false);
            }
          }
          // Size statistics don't take key into account, so we don't
          // need to modify the region's size.
        } else if (!list.isEmpty()) {
          Assert.assertTrue(interestResultPolicy == InterestResultPolicy.KEYS_VALUES);

          VersionedObjectList values = (VersionedObjectList) list.get(0);

          if (logger.isDebugEnabled()) {
            logger.debug("processing interest response: {}", values.size());
          }
          VersionedObjectList.Iterator listIt = values.iterator();
          while (listIt.hasNext()) {
            VersionedObjectList.Entry entry = listIt.next();
            Object currentKey = entry.getKey();
            if (currentKey == null || getImageState().hasDestroyedEntry(currentKey)) {
              continue;
            }
            Object val = entry.getObject();
            boolean isBytes = entry.isBytes();
            boolean isKeyOnServer = !entry.isKeyNotOnServer();
            boolean isTombstone = getConcurrencyChecksEnabled() && entry.isKeyNotOnServer()
                && entry.getVersionTag() != null;
            final VersionTag tag = entry.getVersionTag();
            if (val instanceof Throwable) {
              logger.warn(String.format(
                  "Caught the following exception for key %s while performing a remote getAll",
                  currentKey),
                  (Throwable) val);
              localDestroyNoCallbacks(currentKey);
              continue;
            }
            if (logger.isDebugEnabled()) {
              logger.debug("refreshEntries key={} value={} version={}", currentKey, entry, tag);
            }
            if (tag == null) { // no version checks
              localDestroyNoCallbacks(currentKey);
            }

            if (val instanceof byte[] && !isBytes) {
              val = CachedDeserializableFactory.create((byte[]) val, getCache());
            }

            if (isTombstone) {
              assert val == null : "server returned a value for a destroyed entry";
              val = Token.TOMBSTONE;
            }

            if (val != null || isTombstone) {
              // Sneakily drop in the value into our local cache,
              // but don't overwrite
              if (!isProxy()) {
                entries.initialImagePut(currentKey, 0, val, false, false, tag, null, false);
              }
            } else {
              RegionEntry regionEntry = entries.getEntry(currentKey);
              if (!isProxy() && isKeyOnServer) {
                entries.initialImagePut(currentKey, 0, Token.LOCAL_INVALID, false, false, tag,
                    null, false);
              } else {
                if (regionEntry != null) {
                  synchronized (regionEntry) {
                    if (regionEntry.isDestroyedOrRemovedButNotTombstone()) {
                      entries.removeEntry(currentKey, regionEntry, false);
                    }
                  }
                }
              }
              // In this case, if we didn't overwrite, we don't have a local
              // value, so no size change needs to be recorded.
            }
          }
        }
      } catch (DiskAccessException dae) {
        handleDiskAccessException(dae);
        throw dae;
      } finally {
        EntryLogger.clearSource();
      }
    } // for
  }

  private void logKeys(List serverKeys, InterestResultPolicy pol) {
    int totalKeys = 0;
    StringBuffer buffer = new StringBuffer();
    for (final Object serverKey : serverKeys) {
      List keysList = (List) serverKey;
      // The chunk can contain null data if there are no entries on the server
      // corresponding to the requested keys
      // TODO: is this still possible?
      if (keysList == null) {
        continue;
      }
      int numThisChunk = keysList.size();
      totalKeys += numThisChunk;
      for (Object key : keysList) {
        if (key != null) {
          if (key instanceof VersionedObjectList) {
            Set keys = ((VersionedObjectList) key).keySet();
            for (Object k : keys) {
              buffer.append("  ").append(k).append(getLineSeparator());
            }
          } else {
            buffer.append("  ").append(key).append(getLineSeparator());
          }
        }
      }
    } // for
    if (logger.isDebugEnabled()) {
      logger.debug("{} refreshEntriesFromServerKeys count={} policy={}{}{}", this, totalKeys, pol,
          getLineSeparator(), buffer);
    }
  }

  /**
   * Remove values in local cache before registering interest
   *
   * TODO: interestResultPolicy is never used
   *
   * @param key the interest key
   * @param interestType the interest type from {@link InterestType}
   * @param interestResultPolicy the policy from {@link InterestResultPolicy}
   */
  public void clearKeysOfInterest(Object key, int interestType,
      InterestResultPolicy interestResultPolicy) {
    switch (interestType) {
      case InterestType.FILTER_CLASS:
        clearViaFilterClass((String) key);
        break;
      case InterestType.KEY:
        if (key instanceof String && key.equals("ALL_KEYS")) {
          clearViaRegEx(".*");
        } else if (key instanceof List) {
          clearViaList((List) key);
        } else {
          localDestroyNoCallbacks(key);
        }
        break;
      case InterestType.OQL_QUERY:
        clearViaQuery((String) key);
        break;
      case InterestType.REGULAR_EXPRESSION:
        clearViaRegEx((String) key);
        break;
      default:
        throw new InternalGemFireError(
            "unknown interest type");
    }
  }

  /**
   * Destroys and recreates this region. If this is triggered by loadSnapshot inputStream will be
   * supplied. If this is triggered by LossAction of reinitialize then inputStream will be null, and
   * the region will go through regular GetInitialImage if it is a mirrored replicate.
   * <p>
   * Acquires and releases the DestroyLock.
   *
   * @since GemFire 5.0
   */
  void reinitialize(InputStream inputStream, RegionEventImpl event)
      throws TimeoutException, IOException, ClassNotFoundException {
    acquireDestroyLock();
    try {
      reinitialize_destroy(event);
      recreate(inputStream, null);
    } finally {
      releaseDestroyLock();
    }
  }

  /**
   * must be holding destroy lock
   */
  void reinitializeFromImageTarget(InternalDistributedMember imageTarget)
      throws TimeoutException, IOException, ClassNotFoundException {
    Assert.assertTrue(imageTarget != null);
    recreate(null, imageTarget);
  }

  /**
   * Returns true if this region was reinitialized, e.g. a snapshot was loaded, and this is the
   * recreated region
   */
  boolean reinitialized_new() {
    return reinitialized_new;
  }

  /**
   * must be holding destroy lock
   */
  void reinitialize_destroy(RegionEventImpl event) throws CacheWriterException, TimeoutException {
    final boolean cacheWrite = !event.originRemote;
    // register this region as reinitializing
    cache.regionReinitializing(getFullPath());
    basicDestroyRegion(event, cacheWrite, false/* lock */, true);
  }

  /**
   * must be holding destroy lock
   */
  private void recreate(InputStream inputStream, InternalDistributedMember imageTarget)
      throws TimeoutException, IOException, ClassNotFoundException {
    String thePath = getFullPath();
    Region newRegion = null;
    // recreate new region with snapshot data

    try {
      LocalRegion parent = parentRegion;
      // If specified diskDir in DEFAULT diskstore, we should not use null
      // as diskstore name any more
      if (diskStoreImpl != null
          && diskStoreImpl.getName().equals(DiskStoreFactory.DEFAULT_DISK_STORE_NAME)
          && diskStoreName == null && !useDefaultDiskStore()) {
        diskStoreName = diskStoreImpl.getName();
      }
      RegionAttributes attrs = this;
      boolean getDestroyLock = false;
      InternalRegionArguments internalRegionArguments = new InternalRegionArguments()
          .setDestroyLockFlag(getDestroyLock).setSnapshotInputStream(inputStream)
          .setImageTarget(imageTarget).setRecreateFlag(true);
      if (this instanceof BucketRegion) {
        BucketRegion me = (BucketRegion) this;
        internalRegionArguments.setPartitionedRegionBucketRedundancy(me.getRedundancyLevel());
      }

      if (parent == null) {
        newRegion = cache.createVMRegion(regionName, attrs, internalRegionArguments);
      } else {
        newRegion = parent.createSubregion(regionName, attrs, internalRegionArguments);
      }

      // note that createVMRegion and createSubregion now call regionReinitialized
    } catch (RegionExistsException e) {
      // shouldn't happen since we're holding the destroy lock
      throw new InternalGemFireError(
          "Got RegionExistsException in reinitialize when holding destroy lock",
          e);
    } finally {
      if (newRegion == null) {
        // failed to create region
        cache.unregisterReinitializingRegion(thePath);
      }
    }
  }

  void loadSnapshotDuringInitialization(InputStream inputStream)
      throws IOException, ClassNotFoundException {
    try (DataInputStream in = new DataInputStream(inputStream)) {
      RegionMap map = getRegionMap();
      byte snapshotVersion = in.readByte();
      if (snapshotVersion != SNAPSHOT_VERSION) {
        throw new IllegalArgumentException(
            String.format("Unsupported snapshot version %s. Only version %s is supported.",
                new Object[] {snapshotVersion, SNAPSHOT_VERSION}));
      }
      for (;;) {
        Object key = DataSerializer.readObject(in);
        if (key == null) {
          break;
        }
        byte aByte = in.readByte();
        Object value;

        if (aByte == SNAPSHOT_VALUE_OBJ) {
          value = DataSerializer.readObject(in);
        } else if (aByte == SNAPSHOT_VALUE_INVALID || aByte == SNAPSHOT_VALUE_LOCAL_INVALID) {
          // Even though it was a distributed invalidate when the snapshot was created I think it is
          // correct to turn it into a local invalidate when we load the snapshot since we don't do
          // a distributed invalidate operation when loading.
          value = Token.LOCAL_INVALID;
        } else {
          throw new IllegalArgumentException(
              String.format(
                  "Unexpected snapshot code %s. This snapshot was probably written by an earlier, incompatible, release.",
                  aByte));
        }

        // If versioning is enabled, we will give the entry a "fake" version.
        VersionTag tag = null;
        if (getConcurrencyChecksEnabled()) {
          tag = VersionTag.create(getVersionMember());
        }
        map.initialImagePut(key, cacheTimeMillis(), value, false, false, tag, null, false);
      }
    }
    reinitialized_new = true;
  }

  /**
   * Blocks until initialization is complete.
   *
   * @param destroyedRegionOk true if it is okay to return a region that isDestroyed
   * @see DestroyRegionOperation
   */
  @Override
  public Region getSubregion(String path, boolean destroyedRegionOk) {
    if (destroyedRegionOk) {
      checkCacheClosed();
    } else if (isDestroyed()) {
      // Assume if the owner of the subregion is destroyed, so are all of its
      // subregions
      return null;
    }

    if (path == null) {
      throw new IllegalArgumentException(
          "path should not be null");
    }
    if (path.isEmpty()) {
      waitOnInitialization(); // some internal methods rely on this
      return this;
    }
    if (path.charAt(0) == Region.SEPARATOR_CHAR) {
      throw new IllegalArgumentException(
          "path should not start with a slash");
    }

    // initialize the current region as this one
    LocalRegion region = this;

    // initialize the rest of the name to be regionName
    String name = path;

    // last: are we on the last part of the path?
    boolean last;
    do {
      // if the rest of the name is empty, then we're done, return current region
      if (name.isEmpty()) {
        // return region
        break;
      }

      // the index of the next separator
      int separatorIndex = name.indexOf(Region.SEPARATOR_CHAR);

      // this is the last part if no separator
      last = separatorIndex < 0;

      // try to get next region
      String next = last ? name : name.substring(0, separatorIndex);
      region = region.basicGetSubregion(next);
      if (region == null) {
        // not found
        return null;
      }
      if (region.isDestroyed() && !destroyedRegionOk) {
        return null;
      }

      if (!last) {
        // if found but still more to do, get next rest of path
        name = name.substring(separatorIndex + 1);
      }
    } while (!last);

    region.waitOnInitialization();

    // if region has just been destroyed return null unless specified not to
    if (region.isDestroyed()) {
      if (!destroyedRegionOk) {
        return null;
      }
      return region;
    }

    return region;
  }

  /**
   * Called by a thread that is doing region initialization. Causes the initialization Latch to be
   * bypassed by this thread.
   */
  public static InitializationLevel setThreadInitLevelRequirement(InitializationLevel level) {
    final InitializationLevel oldLevel = getThreadInitLevelRequirement();
    if (level != oldLevel) {
      initializationThread.set(level);
    }
    return oldLevel;
  }

  /**
   * Return the access level this thread has for regions with respect to how initialized they need
   * to be before this thread can have a reference to it. AFTER_INITIAL_IMAGE: Must be fully
   * initialized (the default) BEFORE_INITIAL_IMAGE: Must have had first latch opened ANY_INIT:
   * Thread uses region as soon as possible
   */
  static InitializationLevel getThreadInitLevelRequirement() {
    return initializationThread.get();
  }

  @Override
  public boolean checkForInitialization() {
    if (initialized) {
      return true;
    }
    switch (getThreadInitLevelRequirement()) {
      case AFTER_INITIAL_IMAGE:
        return checkForInitialization(getInitializationLatchAfterGetInitialImage());
      case BEFORE_INITIAL_IMAGE:
        return checkForInitialization(getInitializationLatchBeforeGetInitialImage());
      case ANY_INIT:
        return true;
      default:
        throw new InternalGemFireError(
            "Unexpected getThreadInitLevelRequirement");
    }
  }

  private boolean checkForInitialization(StoppableCountDownLatch latch) {
    return latch.getCount() == 0;
  }

  /**
   * wait on the initialization Latch based on thread requirements
   */
  @Override
  public void waitOnInitialization() {
    if (initialized) {
      return;
    }
    switch (getThreadInitLevelRequirement()) {
      case AFTER_INITIAL_IMAGE:
        waitOnInitialization(getInitializationLatchAfterGetInitialImage());
        break;
      case BEFORE_INITIAL_IMAGE:
        waitOnInitialization(getInitializationLatchBeforeGetInitialImage());
        break;
      case ANY_INIT:
        return;
      default:
        throw new InternalGemFireError(
            "Unexpected getThreadInitLevelRequirement");
    }
  }

  @Override
  public void waitOnInitialization(StoppableCountDownLatch latch) {
    if (latch == null) {
      return; // latch resource has been freed
    }
    while (true) {
      cache.getCancelCriterion().checkCancelInProgress(null);
      boolean interrupted = Thread.interrupted();
      try {
        latch.await();
        break;
      } catch (InterruptedException e) {
        interrupted = true;
        cache.getCancelCriterion().checkCancelInProgress(e);
        // continue waiting
      } finally {
        if (interrupted) {
          // set interrupted flag if was interrupted
          Thread.currentThread().interrupt();
        }
      }
    } // while
  }

  /**
   * Wait until data is ready in this region
   */
  public void waitForData() {
    if (initialized) {
      return;
    }
    waitOnInitialization(getInitializationLatchAfterGetInitialImage());
  }

  /**
   * return null if not found
   */
  @Override
  public RegionEntry basicGetEntry(Object key) {
    // ok to ignore tx state; all callers are non-transactional
    RegionEntry regionEntry = entries.getEntry(key);
    if (regionEntry != null && regionEntry.isRemoved()) {
      regionEntry = null;
    }
    return regionEntry;
  }

  /**
   * Return true if invalidation occurred; false if it did not, for example if it was already
   * invalidated
   *
   * @see DistributedRegion#basicInvalidate(EntryEventImpl)
   */
  public void basicInvalidate(EntryEventImpl event) throws EntryNotFoundException {
    basicInvalidate(event, isInitialized());
  }

  /**
   * Used by disk regions when recovering data from backup. Currently this "put" is done at a very
   * low level to keep it from generating events or pushing updates to others.
   */
  @Override
  public DiskEntry initializeRecoveredEntry(Object key, DiskEntry.RecoveredEntry re) {
    Assert.assertTrue(diskRegion != null);
    // region operation so it is ok to ignore tx state
    RegionEntry regionEntry = entries.initRecoveredEntry(key, re);
    if (regionEntry == null) {
      throw new InternalGemFireError(
          String.format("Entry already existed: %s", key));
    }
    return (DiskEntry) regionEntry;
  }

  /**
   * Used by disk regions when recovering data from backup and initializedRecoveredEntry has already
   * been called for the given key. Currently this "put" is done at a very low level to keep it from
   * generating events or pushing updates to others.
   */
  @Override
  public DiskEntry updateRecoveredEntry(Object key, DiskEntry.RecoveredEntry re) {
    Assert.assertTrue(diskRegion != null);
    // region operation so it is ok to ignore tx state
    RegionEntry regionEntry = entries.updateRecoveredEntry(key, re);
    return (DiskEntry) regionEntry;
  }

  @Override
  public void copyRecoveredEntries(RegionMap rm) {
    entries.copyRecoveredEntries(rm);
  }

  @Override
  public void recordRecoveredGCVersion(VersionSource member, long gcVersion) {
    // TODO - RVV - I'm not sure about this recordGCVersion method. It seems like it's not doing the
    // right thing if the current member is the member we just recovered. We need to update the RVV
    // in memory
    versionVector.recordGCVersion(member, gcVersion);

    // We also need to update the RVV that represents what we have persisted on disk
    DiskRegion region = getDiskRegion();
    if (region != null) {
      region.recordRecoveredGCVersion(member, gcVersion);
    }
  }

  @Override
  public void recordRecoveredVersionHolder(VersionSource member, RegionVersionHolder versionHolder,
      boolean latestOplog) {
    if (getConcurrencyChecksEnabled()) {
      // We need to update the RVV in memory
      versionVector.initRecoveredVersion(member, versionHolder, latestOplog);
      DiskRegion region = getDiskRegion();
      // We also need to update the RVV that represents what we have persisted on disk
      if (region != null) {
        region.recordRecoveredVersionHolder(member, versionHolder, latestOplog);
      }
    }
  }

  @Override
  public void recordRecoveredVersionTag(VersionTag tag) {
    if (getConcurrencyChecksEnabled()) {
      versionVector.recordVersion(tag.getMemberID(), tag.getRegionVersion());
      DiskRegion region = getDiskRegion();
      // We also need to update the RVV that represents what we have persisted on disk
      if (region != null) {
        region.recordRecoveredVersionTag(tag);
      }
    }
  }

  @Override
  public void setRVVTrusted(boolean rvvTrusted) {
    if (getConcurrencyChecksEnabled()) {
      DiskRegion region = getDiskRegion();
      // Update whether or not the RVV we have recovered is trusted (accurately represents what we
      // have on disk).
      if (region != null) {
        region.setRVVTrusted(rvvTrusted);
      }
    }
  }

  /**
   * Get the best iterator for the region entries.
   */
  public Iterator<RegionEntry> getBestIterator(boolean includeValues) {
    if (this instanceof DistributedRegion) {
      return getBestIterator(includeValues);
    }

    return entries.regionEntries().iterator();
  }

  /**
   * Fix up our RVV by iterating over the entries in the region and making sure they are applied to
   * the RVV.
   *
   * If we failed to do a GII, we may have applied the RVV from a remote member. That RVV may not
   * have seen some of the events in our local RVV. Those entries were supposed to be replaced with
   * the results of the GII. However, if we failed the GII, those entries may still be in the cache,
   * but are no longer reflected in the local RVV. This method iterates over those keys and makes
   * sure their versions are applied to the local RVV.
   *
   * TODO - this method should probably rebuild the RVV from scratch, instead of starting with the
   * existing RVV. By starting with the existing RVV, we may claim to have entries that we actually
   * don't have. Unfortunately, we can't really rebuild the RVV from scratch because we will end up
   * with huge exception lists.
   *
   * However, if we are in the state of recovering from disk with an untrusted RVV, we must be newer
   * than any other surviving members. So they shouldn't have any entries in their cache that match
   * entries that we failed to receive through the GII but are reflected in our current RVV. So it
   * should be safe to start with the current RVV.
   */
  void repairRVV() {
    RegionVersionVector rvv = getVersionVector();

    if (rvv == null) {
      // No need to do anything.
      return;
    }

    Iterator<RegionEntry> it = getBestIterator(false);
    VersionSource<?> myId = getVersionMember();

    // Iterate over the all of the entries
    while (it.hasNext()) {
      RegionEntry mapEntry = it.next();
      VersionStamp<?> stamp = mapEntry.getVersionStamp();
      VersionSource<?> id = stamp.getMemberID();
      if (id == null) {
        id = myId;
      }

      // Make sure the version is applied to the regions RVV
      rvv.recordVersion(id, stamp.getRegionVersion());
    }
  }

  /**
   * Return true if invalidation occurred; false if it did not, for example if it was already
   * invalidated
   */
  private void basicInvalidate(final EntryEventImpl event, boolean invokeCallbacks)
      throws EntryNotFoundException {
    final boolean forceNewEntryInClientCache = serverRegionProxy != null
        && getConcurrencyChecksEnabled();
    basicInvalidate(event, invokeCallbacks, forceNewEntryInClientCache);
  }

  /**
   * basicInvalidate is overridden in HARegion to abort expiry of Events which have key as Long , if
   * it is not able to destroy from availableIDs
   *
   * @param forceNewEntry true if we are a mirror and still in the initialization phase. Called from
   *        InvalidateOperation.InvalidateMessage
   */
  void basicInvalidate(final EntryEventImpl event, boolean invokeCallbacks,
      final boolean forceNewEntry) throws EntryNotFoundException {
    if (!event.isOriginRemote() && !event.isDistributed() && getScope().isDistributed()
        && getDataPolicy().withReplication() && invokeCallbacks) {
      // catches case where being called by (distributed) invalidateRegion
      throw new IllegalStateException(
          "Cannot do a local invalidate on a replicated region");
    }

    if (hasSeenEvent(event)) {
      if (logger.isTraceEnabled(LogMarker.DM_VERBOSE)) {
        logger.trace(LogMarker.DM_VERBOSE,
            "LR.basicInvalidate: this cache has already seen this event {}", event);
      }
      if (getConcurrencyChecksEnabled() && event.getVersionTag() != null
          && !event.getVersionTag().isRecorded()) {
        getVersionVector().recordVersion((InternalDistributedMember) event.getDistributedMember(),
            event.getVersionTag());
      }
      return;
    }

    discoverJTA();
    getDataView().invalidateExistingEntry(event, invokeCallbacks, forceNewEntry);
  }

  void basicInvalidatePart2(RegionEntry regionEntry, EntryEventImpl event,
      boolean conflictWithClear, boolean invokeCallbacks) {
    updateStatsForInvalidate();

    if (invokeCallbacks) {
      try {
        regionEntry.dispatchListenerEvents(event);
      } catch (InterruptedException ignore) {
        Thread.currentThread().interrupt();
        stopper.checkCancelInProgress(null);
      }
    } else {
      event.callbacksInvoked(true);
    }
  }

  /**
   * Update stats
   */
  private void updateStatsForInvalidate() {
    getCachePerfStats().incInvalidates();
  }

  void basicInvalidatePart3(RegionEntry re, EntryEventImpl event, boolean invokeCallbacks) {
    // No op. overridden by sub classes.
    // Dispatching listener events moved to basic*Part2.
  }

  /**
   * invoke callbacks for an invalidation
   */
  @Override
  public void invokeInvalidateCallbacks(final EnumListenerEvent eventType,
      final EntryEventImpl event, final boolean callDispatchListenerEvent) {
    // Notify bridge clients (if this is a CacheServer)
    event.setEventType(eventType);
    notifyBridgeClients(event);
    if (callDispatchListenerEvent) {
      dispatchListenerEvent(eventType, event);
    }
  }

  /**
   * @param key the key of the entry to invalidate
   * @param newValue the new value of the entry
   * @param didDestroy true if tx destroyed this entry at some point
   * @param event filled in if operation performed
   * @param txEntryState for passing up versionTag - only on near side
   * @param versionTag tag generated by txCoordinator - only on far side
   * @param tailKey tail (shadow) key generated by txCoordinator for WAN - only on farside
   */
  @Override
  public void txApplyInvalidate(Object key, Object newValue, boolean didDestroy,
      TransactionId transactionId, TXRmtEvent event, boolean localOp, EventID eventId,
      Object aCallbackArgument, List<EntryEventImpl> pendingCallbacks,
      FilterRoutingInfo filterRoutingInfo, ClientProxyMembershipID bridgeContext,
      TXEntryState txEntryState, VersionTag versionTag, long tailKey) {

    entries.txApplyInvalidate(key, newValue, didDestroy, transactionId, event, localOp,
        eventId, aCallbackArgument, pendingCallbacks, filterRoutingInfo, bridgeContext,
        txEntryState, versionTag, tailKey);
  }

  /**
   * Called by lower levels, while still holding the write sync lock, and the low level has
   * completed its part of the basic destroy
   */
  void txApplyInvalidatePart2(RegionEntry regionEntry, Object key, boolean didDestroy,
      boolean didInvalidate) {
    if (testCallable != null) {
      testCallable.call(this, Operation.INVALIDATE, regionEntry);
    }
    if (didInvalidate) {
      updateStatsForInvalidate();
      // clearing index of the old value performed in AbstractRegionMap
    }
    if (didDestroy) {
      entryUserAttributes.remove(key);
    }
  }

  /**
   * Called by AbstractRegionMap txApplyPut when it was told a destroy was also done
   * by the transaction.
   */
  @Override
  public void txApplyPutHandleDidDestroy(Object key) {
    entryUserAttributes.remove(key);
  }

  /**
   * Allows null as new value to accommodate create with a null value. Assumes all key, value, and
   * callback validations have been performed.
   *
   * @param event the event object for this operation, with the exception that the oldValue
   *        parameter is not yet filled in. The oldValue will be filled in by this operation.
   * @param ifNew true if this operation must not overwrite an existing key
   * @param ifOld true if this operation must not create a new key
   * @param expectedOldValue only succeed if old value is equal to this value. If null, then doesn't
   *        matter what old value is. If INVALID token, must be INVALID.
   * @param requireOldValue true if the oldValue should be set in event even if ifNew and entry
   *        exists
   * @return false if ifNew is true and there is an existing key or if ifOld is true and
   *         expectedOldValue does not match the current value in the cache. Otherwise return true.
   */
  @Override
  public boolean basicPut(EntryEventImpl event, boolean ifNew, boolean ifOld,
      Object expectedOldValue, boolean requireOldValue)
      throws TimeoutException, CacheWriterException {
    return getDataView().putEntry(event, ifNew, ifOld, expectedOldValue, requireOldValue, 0L,
        false);
  }

  /**
   * @param putOp describes the operation that did the put
   * @param key the key of the entry to put
   * @param newValue the new value of the entry
   * @param didDestroy true if tx destroyed this entry at some point
   * @param event filled in if operation performed
   * @param aCallbackArgument argument passed in by user
   * @param txEntryState for passing up versionTag - only on near side
   * @param versionTag tag generated by txCoordinator - only on far side
   * @param tailKey tail (shadow) key generated by txCoordinator for WAN - only on farside
   */
  @Override
  public void txApplyPut(Operation putOp, Object key, Object newValue, boolean didDestroy,
      TransactionId transactionId, TXRmtEvent event, EventID eventId, Object aCallbackArgument,
      List<EntryEventImpl> pendingCallbacks, FilterRoutingInfo filterRoutingInfo,
      ClientProxyMembershipID bridgeContext, TXEntryState txEntryState, VersionTag versionTag,
      long tailKey) {
    long startPut = getStatisticsClock().getTime();
    entries.txApplyPut(putOp, key, newValue, didDestroy, transactionId, event, eventId,
        aCallbackArgument, pendingCallbacks, filterRoutingInfo, bridgeContext, txEntryState,
        versionTag, tailKey);
    updateStatsForPut(startPut);
    // make sure we throw an exception if we skip the TX put because
    // the region is cleared (due to a destroy)
    checkReadiness();
  }

  /**
   * update stats
   */
  private void updateStatsForPut(long startPut) {
    getCachePerfStats().endPut(startPut, false);
  }

  @Override
  public void txApplyPutPart2(RegionEntry regionEntry, Object key, long lastModified,
      boolean isCreate, boolean didDestroy, boolean clearConflict) {
    if (testCallable != null) {
      Operation op = isCreate ? Operation.CREATE : Operation.UPDATE;
      testCallable.call(this, op, regionEntry);
    }
    if (isCreate) {
      updateStatsForCreate();
    }
    if (!isProxy() && !clearConflict) {
      if (indexManager != null) {
        try {
          indexManager.updateIndexes(regionEntry,
              isCreate ? IndexManager.ADD_ENTRY : IndexManager.UPDATE_ENTRY,
              isCreate ? IndexProtocol.OTHER_OP : IndexProtocol.AFTER_UPDATE_OP);
        } catch (QueryException e) {
          throw new IndexMaintenanceException(e);
        }
      }
    }
    if (didDestroy) {
      entryUserAttributes.remove(key);
    }
    if (statisticsEnabled && !clearConflict) {
      addExpiryTaskIfAbsent(regionEntry);
    }
    setLastModifiedTime(lastModified);
  }

  public boolean basicBridgeCreate(final Object key, final byte[] value, boolean isObject,
      Object callbackArg, final ClientProxyMembershipID client, boolean fromClient,
      EntryEventImpl clientEvent, boolean throwEntryExists)
      throws TimeoutException, EntryExistsException, CacheWriterException {
    EventID eventId = clientEvent.getEventId();
    Object theCallbackArg = callbackArg;

    long startPut = getStatisticsClock().getTime();

    @Released
    final EntryEventImpl event =
        entryEventFactory.create(this, Operation.CREATE, key, value,
            theCallbackArg, false, client.getDistributedMember(),
            true, eventId);

    try {
      event.setContext(client);

      // if this is a replayed operation or WAN event we may already have a version tag
      event.setVersionTag(clientEvent.getVersionTag());
      // carry over the possibleDuplicate flag from clientEvent
      event.setPossibleDuplicate(clientEvent.isPossibleDuplicate());

      // Only make create with null a local invalidate for
      // normal regions. Otherwise, it will become a distributed invalidate.
      if (getDataPolicy() == DataPolicy.NORMAL) {
        event.setLocalInvalid(true);
      }

      // Set the new value to the input byte[] if it isn't null
      if (value != null) {
        // If the byte[] represents an object, then store it serialized
        // in a CachedDeserializable; otherwise store it directly as a byte[]
        if (isObject) {
          // The value represents an object
          event.setSerializedNewValue(value);
        } else {
          // The value does not represent an object
          event.setNewValue(value);
        }
      }

      // cannot overwrite an existing key
      boolean ifNew = true;
      // can create a new key
      boolean ifOld = false;
      // use now
      long lastModified = 0L;
      // not okay to overwrite the DESTROYED token
      boolean overwriteDestroyed = false;

      boolean success = basicUpdate(event, ifNew, ifOld, lastModified, overwriteDestroyed);
      clientEvent.isConcurrencyConflict(event.isConcurrencyConflict());

      if (success) {
        clientEvent.setVersionTag(event.getVersionTag());
        getCachePerfStats().endPut(startPut, event.isOriginRemote());
      } else {
        stopper.checkCancelInProgress(null);
        if (throwEntryExists) {
          throw new EntryExistsException("" + key, event.getOldValue());
        }
      }
      return success;
    } finally {
      event.release();
    }
  }

  public boolean basicBridgePut(Object key, Object value, byte[] deltaBytes, boolean isObject,
      Object callbackArg, ClientProxyMembershipID memberId, boolean fromClient,
      EntryEventImpl clientEvent) throws TimeoutException, CacheWriterException {

    EventID eventID = clientEvent.getEventId();
    Object theCallbackArg = callbackArg;
    long startPut = getStatisticsClock().getTime();

    @Released
    final EntryEventImpl event = entryEventFactory.create(this, Operation.UPDATE, key,
        null, theCallbackArg, false,
        memberId.getDistributedMember(), true, eventID);

    try {
      event.setContext(memberId);
      event.setDeltaBytes(deltaBytes);

      // if this is a replayed operation we may already have a version tag
      event.setVersionTag(clientEvent.getVersionTag());
      // carry over the possibleDuplicate flag from clientEvent
      event.setPossibleDuplicate(clientEvent.isPossibleDuplicate());

      // Set the new value to the input byte[]. If the byte[] represents an object, then store it
      // serialized in a CachedDeserializable; otherwise store it directly as a byte[].
      if (isObject && value instanceof byte[]) {
        event.setSerializedNewValue((byte[]) value);
      } else {
        event.setNewValue(value);
      }

      boolean success = false;

      try {
        boolean ifNew = false; // can overwrite an existing key
        boolean ifOld = false; // can create a new key
        long lastModified = 0L; // use now
        boolean overwriteDestroyed = false; // not okay to overwrite the DESTROYED token
        success = basicUpdate(event, ifNew, ifOld, lastModified, overwriteDestroyed);

      } catch (ConcurrentCacheModificationException ignore) {
        // thrown by WAN conflicts
        event.isConcurrencyConflict(true);
      }

      clientEvent.isConcurrencyConflict(event.isConcurrencyConflict());

      if (success) {
        clientEvent.setVersionTag(event.getVersionTag());
        getCachePerfStats().endPut(startPut, event.isOriginRemote());
      } else {
        stopper.checkCancelInProgress(null);
      }

      return success;
    } finally {
      event.release();
    }
  }

  /**
   * issue a config message if the server and client have different concurrency checking
   * expectations
   */
  private void concurrencyConfigurationCheck(VersionTag tag) {
    if (!concurrencyMessageIssued && tag == null && getConcurrencyChecksEnabled()) {
      concurrencyMessageIssued = true;
      logger.info("Server has concurrencyChecksEnabled {} but client has {} for region {}",
          new Object[] {!getConcurrencyChecksEnabled(), getConcurrencyChecksEnabled(),
              this});
    }
  }

  /**
   * Perform an update in a bridge client. See CacheClientUpdater.handleUpdate() The op is from the
   * cache server and should not be distributed back to it.
   */
  public void basicBridgeClientUpdate(DistributedMember serverId, Object key, Object value,
      byte[] deltaBytes, boolean isObject, Object callbackArgument, boolean isCreate,
      boolean processedMarker, EntryEventImpl event, EventID eventID)
      throws TimeoutException, CacheWriterException {

    if (isCacheContentProxy()) {
      return;
    }

    concurrencyConfigurationCheck(event.getVersionTag());
    long startPut = getStatisticsClock().getTime();

    // Generate EventID as it is possible that client is a cache server
    // in hierarchical cache
    if (generateEventID() && !cache.getCacheServers().isEmpty()) {
      event.setNewEventId(cache.getDistributedSystem());
    } else {
      event.setEventId(eventID);
    }
    event.setDeltaBytes(deltaBytes);

    // Set the new value to the input byte[] if it isn't null
    if (value != null) {
      // If the byte[] represents an object, then store it
      // serialized in a CachedDeserializable; otherwise store it directly
      // as a byte[].
      if (isObject && value instanceof byte[]) {
        // The value represents an object
        event.setSerializedNewValue((byte[]) value);
      } else {
        // The value does not represent an object
        event.setNewValue(value);
      }
    }

    // If the marker has been processed, process this put event normally;
    // otherwise, this event occurred in the past and has been stored for a
    // durable client. In this case, just invoke the put callbacks.
    if (processedMarker) {
      boolean ifNew = false; // can overwrite an existing key
      boolean ifOld = false; // can create a new key
      long lastModified = 0L; // use now
      boolean overwriteDestroyed = true; // okay to overwrite the DESTROYED token
      if (basicUpdate(event, ifNew, ifOld, lastModified, overwriteDestroyed)) {
        getCachePerfStats().endPut(startPut, event.isOriginRemote());
      }
    } else {
      if (isInitialized()) {
        invokePutCallbacks(
            isCreate ? EnumListenerEvent.AFTER_CREATE : EnumListenerEvent.AFTER_UPDATE, event, true,
            true);
      }
    }
  }

  /**
   * Perform an invalidate in a bridge client. The op is from the cache server and should not be
   * distributed back to it.
   */
  public void basicBridgeClientInvalidate(DistributedMember serverId, Object key,
      Object callbackArgument, boolean processedMarker, EventID eventID, VersionTag versionTag)
      throws EntryNotFoundException {

    if (!isCacheContentProxy()) {
      concurrencyConfigurationCheck(versionTag);

      // Create an event and put the entry
      @Released
      EntryEventImpl event =
          entryEventFactory.create(this, Operation.INVALIDATE, key, null,
              callbackArgument, true, serverId);
      try {

        event.setVersionTag(versionTag);
        event.setFromServer(true);
        if (generateEventID() && !cache.getCacheServers().isEmpty()) {
          event.setNewEventId(cache.getDistributedSystem());
        } else {
          event.setEventId(eventID);
        }

        // If the marker has been processed, process this invalidate event
        // normally; otherwise, this event occurred in the past and has been
        // stored for a durable client. In this case, just invoke the invalidate
        // callbacks.
        if (processedMarker) {
          // changed to force new entry creation for consistency
          final boolean forceNewEntry = getConcurrencyChecksEnabled();
          basicInvalidate(event, true, forceNewEntry);
          if (event.isConcurrencyConflict()) {
            // we must throw this for the CacheClientUpdater
            throw new ConcurrentCacheModificationException();
          }
        } else {
          if (isInitialized()) {
            invokeInvalidateCallbacks(EnumListenerEvent.AFTER_INVALIDATE, event, true);
          }
        }
      } finally {
        event.release();
      }
    }
  }

  /**
   * Perform a destroy in a bridge client. The op is from the cache server and should not be
   * distributed back to it.
   */
  public void basicBridgeClientDestroy(DistributedMember serverId, Object key,
      Object callbackArgument, boolean processedMarker, EventID eventID, VersionTag versionTag)
      throws EntryNotFoundException {

    if (!isCacheContentProxy()) {
      concurrencyConfigurationCheck(versionTag);

      // Create an event and destroy the entry
      @Released
      EntryEventImpl event =
          entryEventFactory.create(this, Operation.DESTROY, key, null,
              callbackArgument, true, serverId);
      try {
        event.setFromServer(true);
        event.setVersionTag(versionTag);

        if (generateEventID() && !cache.getCacheServers().isEmpty()) {
          event.setNewEventId(cache.getDistributedSystem());
        } else {
          event.setEventId(eventID);
        }

        // If the marker has been processed, process this destroy event normally;
        // otherwise, this event occurred in the past and has been stored for a
        // durable client. In this case, just invoke the destroy callbacks.
        if (logger.isDebugEnabled()) {
          logger.debug("basicBridgeClientDestroy(processedMarker={})", processedMarker);
        }

        if (processedMarker) {
          basicDestroy(event, false, null);
          if (event.isConcurrencyConflict()) {
            // we must throw an exception for CacheClientUpdater
            throw new ConcurrentCacheModificationException();
          }
        } else {
          if (isInitialized()) {
            invokeDestroyCallbacks(EnumListenerEvent.AFTER_DESTROY, event, true, true);
          }
        }
      } finally {
        event.release();
      }
    }
  }

  /**
   * Clear the region from a server request.
   *
   * @param callbackArgument The callback argument. This is currently null since
   *        {@link Map#clear} supports no parameters.
   * @param processedMarker Whether the marker has been processed (for durable clients)
   */
  public void basicBridgeClientClear(Object callbackArgument, boolean processedMarker) {
    checkReadiness();
    checkForNoAccess();
    RegionEventImpl event = new RegionEventImpl(this, Operation.REGION_LOCAL_CLEAR,
        callbackArgument, true, getMyId(), generateEventID()/* generate EventID */);
    // If the marker has been processed, process this clear event normally;
    // otherwise, this event occurred in the past and has been stored for a
    // durable client. In this case, just invoke the clear callbacks.
    if (processedMarker) {
      basicLocalClear(event);
    } else {
      if (isInitialized()) {
        dispatchListenerEvent(EnumListenerEvent.AFTER_REGION_CLEAR, event);
      }
    }
  }

  public void basicBridgeDestroy(Object key, Object callbackArg, ClientProxyMembershipID memberId,
      boolean fromClient, EntryEventImpl clientEvent)
      throws TimeoutException, EntryNotFoundException, CacheWriterException {

    // Create an event and put the entry
    @Released
    final EntryEventImpl event =
        entryEventFactory.create(this, Operation.DESTROY, key, null,
            callbackArg, false, memberId.getDistributedMember(), true, clientEvent.getEventId());

    try {
      event.setContext(memberId);
      // if this is a replayed or WAN operation we may already have a version tag
      event.setVersionTag(clientEvent.getVersionTag());
      event.setPossibleDuplicate(clientEvent.isPossibleDuplicate());
      try {
        basicDestroy(event, true, null);
      } catch (ConcurrentCacheModificationException ignore) {
        // thrown by WAN conflicts
        event.isConcurrencyConflict(true);
      } finally {
        clientEvent.setVersionTag(event.getVersionTag());
        clientEvent.isConcurrencyConflict(event.isConcurrencyConflict());
        clientEvent.setIsRedestroyedEntry(event.getIsRedestroyedEntry());
      }
    } finally {
      event.release();
    }
  }

  // TODO: fromClient is always true
  public void basicBridgeInvalidate(Object key, Object callbackArg,
      ClientProxyMembershipID memberId, boolean fromClient, EntryEventImpl clientEvent)
      throws TimeoutException, EntryNotFoundException, CacheWriterException {

    // Create an event and put the entry
    @Released
    final EntryEventImpl event =
        entryEventFactory.create(this, Operation.INVALIDATE, key, null,
            callbackArg, false, memberId.getDistributedMember(), true, clientEvent.getEventId());

    try {
      event.setContext(memberId);

      // if this is a replayed operation we may already have a version tag
      event.setVersionTag(clientEvent.getVersionTag());
      event.setPossibleDuplicate(clientEvent.isPossibleDuplicate());

      try {
        basicInvalidate(event);
      } finally {
        clientEvent.setVersionTag(event.getVersionTag());
        clientEvent.isConcurrencyConflict(event.isConcurrencyConflict());
      }
    } finally {
      event.release();
    }
  }

  // TODO: fromClient is always false and never used
  // TODO: callbackArg is never used
  public void basicBridgeUpdateVersionStamp(Object key, Object callbackArg,
      ClientProxyMembershipID memberId, boolean fromClient, EntryEventImpl clientEvent) {

    // Create an event and update version stamp of the entry
    @Released
    EntryEventImpl event = entryEventFactory.create(this, Operation.UPDATE_VERSION_STAMP, key, null,
        null, false, memberId.getDistributedMember(), false, clientEvent.getEventId());

    event.setContext(memberId);

    // if this is a replayed operation we may already have a version tag
    event.setVersionTag(clientEvent.getVersionTag());
    event.setPossibleDuplicate(clientEvent.isPossibleDuplicate());

    try {
      basicUpdateEntryVersion(event);
    } finally {
      clientEvent.setVersionTag(event.getVersionTag());
      clientEvent.isConcurrencyConflict(event.isConcurrencyConflict());
      event.release();
    }
  }

  void basicUpdateEntryVersion(EntryEventImpl event) throws EntryNotFoundException {
    if (hasSeenEvent(event)) {
      if (logger.isTraceEnabled(LogMarker.DM_VERBOSE)) {
        logger.trace(LogMarker.DM_VERBOSE,
            "LR.basicDestroy: this cache has already seen this event {}", event);
      }
      if (getConcurrencyChecksEnabled() && event.getVersionTag() != null
          && !event.getVersionTag().isRecorded()) {
        getVersionVector().recordVersion((InternalDistributedMember) event.getDistributedMember(),
            event.getVersionTag());
      }
      return;
    }

    getDataView().updateEntryVersion(event);
  }

  boolean basicUpdate(final EntryEventImpl event, final boolean ifNew, final boolean ifOld,
      final long lastModified, final boolean overwriteDestroyed)
      throws TimeoutException, CacheWriterException {
    return this.basicUpdate(event, ifNew, ifOld, lastModified, overwriteDestroyed, true, false);
  }

  /**
   * Allows null as new value to accommodate create with a null value.
   *
   * @param event the event object for this operation, with the exception that the oldValue
   *        parameter is not yet filled in. The oldValue will be filled in by this operation.
   * @param ifNew true if this operation must not overwrite an existing key
   * @param ifOld true if this operation must not create a new entry
   * @param lastModified the lastModified time to set with the value; if 0L, then the lastModified
   *        time will be set to now.
   * @param overwriteDestroyed true if okay to overwrite the DESTROYED token: when this is true has
   *        the following effect: even when ifNew is true will write over DESTROYED token when
   *        overwriteDestroyed is false and ifNew or ifOld is true then if the put doesn't occur
   *        because there is a DESTROYED token present then the entry flag blockedDestroyed is set.
   * @param invokeCallbacks true if this operation should notify bridge clients and gateway senders
   *        in the event of a ConcurrentCacheModificationException being thrown during the update
   * @param throwConcurrentModificationException true if this operation should be allowed to throw
   *        any ConcurrentCacheModificationException that occurs during the update. If false, any
   *        ConcurrentCacheModificationExceptions that are thrown will be suppressed
   * @return false if ifNew is true and there is an existing key, or ifOld is true and there is no
   *         existing entry; otherwise return true.
   */
  boolean basicUpdate(final EntryEventImpl event, final boolean ifNew, final boolean ifOld,
      final long lastModified, final boolean overwriteDestroyed, final boolean invokeCallbacks,
      final boolean throwConcurrentModificationException)
      throws TimeoutException, CacheWriterException {

    // check validity of key against keyConstraint
    if (keyConstraint != null) {
      if (!keyConstraint.isInstance(event.getKey())) {
        throw new ClassCastException(
            String.format("key ( %s ) does not satisfy keyConstraint ( %s )",
                event.getKey().getClass().getName(), keyConstraint.getName()));
      }
    }

    validateValue(event.basicGetNewValue());

    return getDataView().putEntry(event, ifNew, ifOld, null, false, lastModified,
        overwriteDestroyed, invokeCallbacks, throwConcurrentModificationException);
  }

  public boolean virtualPut(final EntryEventImpl event, final boolean ifNew, final boolean ifOld,
      Object expectedOldValue, boolean requireOldValue, final long lastModified,
      final boolean overwriteDestroyed) throws TimeoutException, CacheWriterException {
    return this.virtualPut(event, ifNew, ifOld, expectedOldValue, requireOldValue, lastModified,
        overwriteDestroyed, true, false);
  }

  /**
   * Subclasses should reimplement if needed
   */
  @Override
  public boolean virtualPut(final EntryEventImpl event, final boolean ifNew, final boolean ifOld,
      Object expectedOldValue, boolean requireOldValue, final long lastModified,
      final boolean overwriteDestroyed, boolean invokeCallbacks,
      boolean throwsConcurrentModification)
      throws TimeoutException, CacheWriterException {

    if (!MemoryThresholds.isLowMemoryExceptionDisabled()) {
      checkIfAboveThreshold(event);
    }

    Operation originalOp = event.getOperation();
    RegionEntry oldEntry;

    try {
      oldEntry = entries.basicPut(event, lastModified, ifNew, ifOld, expectedOldValue,
          requireOldValue, overwriteDestroyed);
    } catch (ConcurrentCacheModificationException concCacheModException) {
      // this can happen in a client cache when another thread managed to slip in its version info
      // to the region entry before this thread got around to doing so
      if (logger.isDebugEnabled()) {
        logger.debug("caught concurrent modification attempt when applying {}", event);
      }
      if (invokeCallbacks) {
        notifyBridgeClients(event);
        notifyGatewaySender(event.getOperation().isUpdate() ? EnumListenerEvent.AFTER_UPDATE
            : EnumListenerEvent.AFTER_CREATE, event);
      }
      if (throwsConcurrentModification) {
        throw concCacheModException;
      } else {
        return false;
      }

    }

    // for EMPTY clients, see if a concurrent map operation had an entry on the server
    ServerRegionProxy mySRP = getServerProxy();

    if (mySRP != null && getDataPolicy() == DataPolicy.EMPTY) {
      if (originalOp == Operation.PUT_IF_ABSENT) {
        return !event.hasOldValue();
      }
      if (originalOp == Operation.REPLACE && !requireOldValue) {
        // LocalRegion.serverPut throws an EntryNotFoundException if the operation failed
        return true;
      }
    }
    return oldEntry != null;
  }

  /**
   * check to see if a LowMemoryException should be thrown for this event
   */
  @Override
  public void checkIfAboveThreshold(final EntryEventImpl entryEvent) throws LowMemoryException {
    if (entryEvent == null) {
      checkIfAboveThreshold("UNKNOWN");
      return;
    }
    // Threshold check is performed elsewhere for putAll when there is a server proxy
    boolean alreadyCheckedThreshold = hasServerProxy() && entryEvent.getOperation().isPutAll();
    if (!alreadyCheckedThreshold && !entryEvent.isOriginRemote()) {
      checkIfAboveThreshold(entryEvent.getKey());
    }
  }

  /**
   * Checks to see if the event should be rejected because of sick state either due to exceeding
   * local critical threshold or a remote member exceeding critical threshold
   *
   * @param key the key for the operation
   * @throws LowMemoryException if the target member for this operation is sick
   */
  private void checkIfAboveThreshold(final Object key) throws LowMemoryException {
    MemoryThresholdInfo info = getAtomicThresholdInfo();
    if (info.isMemoryThresholdReached()) {
      Set<DistributedMember> membersThatReachedThreshold = info.getMembersThatReachedThreshold();
      // trigger a background eviction since we're above the the critical threshold
      InternalResourceManager.getInternalResourceManager(cache).getHeapMonitor()
          .updateStateAndSendEvent();
      throw new LowMemoryException(
          String.format(
              "Region: %s cannot process operation on key: %s because member %s is running low on memory",
              getFullPath(), key, membersThatReachedThreshold),
          membersThatReachedThreshold);
    }
  }

  @Override
  public MemoryThresholdInfo getAtomicThresholdInfo() {
    if (!isMemoryThresholdReached()) {
      return MemoryThresholdInfo.getNotReached();
    }
    return new MemoryThresholdInfo(isMemoryThresholdReached(),
        Collections.singleton(cache.getMyId()));
  }

  @Override
  public Map<Object, Object> getEntryUserAttributes() {
    return entryUserAttributes;
  }

  /**
   * Allows null as new value to accommodate create with a null value.
   *
   * @param event the event object for this operation, with the exception that the oldValue
   *        parameter is not yet filled in. The oldValue will be filled in by this operation.
   * @param lastModified the lastModified time to set with the value; if 0L then the lastModified
   *        time will be set to now.
   * @return null if put not done; otherwise the put entry
   */
  RegionEntry basicPutEntry(final EntryEventImpl event, final long lastModified)
      throws TimeoutException, CacheWriterException {

    discoverJTA();
    TXStateInterface tx = getTXState();

    // Note we are doing a load or netsearch result so it seems like we should set ifNew to true.
    // The entry should not yet exist. However since the non-tx code sets ifNew to false this code
    // will also.
    final boolean ifNew = false;

    if (isTX()) {
      tx.txPutEntry(event, ifNew, false, false, null);
      return null;
    }
    if (DistTXState.internalBeforeNonTXBasicPut != null) {
      DistTXState.internalBeforeNonTXBasicPut.run();
    }

    return getRegionMap().basicPut(event, lastModified, ifNew, false, null, false, false);
  }

  @Override
  public long basicPutPart2(EntryEventImpl event, RegionEntry entry, boolean isInitialized,
      long lastModified, boolean clearConflict) {

    final boolean isNewKey = event.getOperation().isCreate();

    // Invoke callbacks only if we are not creating a tombstone
    final boolean invokeCallbacks = event.basicGetNewValue() != Token.TOMBSTONE;

    if (isNewKey) {
      updateStatsForCreate();
    }

    final boolean lruRecentUse = event.isNetSearch() || event.isLoad();

    // the event may have a version timestamp that we need to use, so get the
    // event time to store in the entry
    long lastModifiedTime = event.getEventTime(lastModified);
    updateStatsForPut(entry, lastModifiedTime, lruRecentUse);

    if (!isProxy()) {
      if (!clearConflict && indexManager != null) {
        try {
          if (!entry.isInvalid()) {
            indexManager.updateIndexes(entry,
                isNewKey ? IndexManager.ADD_ENTRY : IndexManager.UPDATE_ENTRY,
                isNewKey ? IndexProtocol.OTHER_OP : IndexProtocol.AFTER_UPDATE_OP);
          }
        } catch (QueryException e) {
          throw new IndexMaintenanceException(e);
        } finally {
          IndexManager.setIndexBufferTime(lastModifiedTime, cacheTimeMillis());
        }
      }
    }

    if (invokeCallbacks) {
      boolean doCallback = false;
      if (isInitialized) {
        // skip wan notification during import newwan moves notification to here
        // from invokePutCallbacks
        if (event.isGenerateCallbacks()) {
          doCallback = true;
        }
      } else if (isUsedForPartitionedRegionBucket) {
        // invokePutCallbacks in BucketRegion will be more discriminating
        doCallback = true;
      }

      if (doCallback) {
        if (event.isBulkOpInProgress() && isUsedForPartitionedRegionBucket) {
          if (logger.isDebugEnabled()) {
            logger.debug(
                "For bulk operation on bucket region, not to notify gateway sender earlier.");
          }
        } else {
          notifyGatewaySender(event.getOperation().isUpdate() ? EnumListenerEvent.AFTER_UPDATE
              : EnumListenerEvent.AFTER_CREATE, event);
        }

        // Notify listeners
        if (!event.isBulkOpInProgress()) {
          try {
            entry.dispatchListenerEvents(event);
          } catch (InterruptedException ignore) {
            Thread.currentThread().interrupt();
            stopper.checkCancelInProgress(null);
          }
        }
      }
    }
    return lastModifiedTime;
  }

  /**
   * To lower latency, PRs generate the local filter routing in DistributedCacheOperation after
   * message distribution and before waiting for responses.
   *
   * Warning: Even if you comment out bucket condition in following method, getLocalRoutingInfo()
   * does NOT process CQs for bucket regions internally. See
   * {@link FilterProfile#getFilterRoutingInfoPart2(FilterRoutingInfo, CacheEvent)} .
   */
  void generateLocalFilterRouting(InternalCacheEvent event) {
    boolean isEntryEvent = event.getOperation().isEntry();
    EntryEventImpl entryEvent = isEntryEvent ? (EntryEventImpl) event : null;

    FilterProfile filterProfile = getFilterProfile();
    FilterInfo routing = event.getLocalFilterInfo();

    if (filterProfile != null && isGenerateLocalFilterRoutingNeeded(event)) {
      boolean lockForCQ = false;
      Object regionEntryObject = null;

      if (isEntryEvent && entryEvent.getRegionEntry() != null) {
        // we should either have the lock on the region entry
        // or the event was elided and CQ processing won't be done on it
        regionEntryObject = entryEvent.getRegionEntry();
        if (!entryEvent.isConcurrencyConflict()) {
          Assert.assertTrue(regionEntryObject != null);
          lockForCQ = true;
        }
      }
      if (isEntryEvent) {
        if (logger.isDebugEnabled()) {
          logger.debug("getting local client routing.");
        }
      }
      if (lockForCQ) {
        synchronized (regionEntryObject) {
          routing = filterProfile.getLocalFilterRouting(event);
        }
      } else {
        routing = filterProfile.getLocalFilterRouting(event);
      }
      event.setLocalFilterInfo(routing);
    }

    // do not send CQ events to clients out of order
    if (routing != null && event.getOperation().isEntry()
        && ((EntryEventImpl) event).isConcurrencyConflict()) {
      if (logger.isDebugEnabled()) {
        logger.debug("clearing CQ routing for event that's in conflict");
      }
      routing.clearCQRouting();
    }
  }

  boolean isGenerateLocalFilterRoutingNeeded(InternalCacheEvent event) {
    FilterRoutingInfo.FilterInfo filterInfo = event.getLocalFilterInfo();
    if (filterInfo == null) {
      return true;
    }
    if (!event.isTransactional()) {
      return false;
    }
    return filterInfo.isChangeAppliedToCache();
  }

  /**
   * This notifies all WAN sites about updated timestamp on local site.
   */
  @Override
  public void notifyTimestampsToGateways(EntryEventImpl event) {
    // Create updateTimeStampEvent from event.
    VersionTagHolder updateTimeStampEvent = new VersionTagHolder(event.getVersionTag());
    updateTimeStampEvent.setOperation(Operation.UPDATE_VERSION_STAMP);
    updateTimeStampEvent.setKeyInfo(event.getKeyInfo());
    updateTimeStampEvent.setGenerateCallbacks(false);
    updateTimeStampEvent.distributedMember = event.getDistributedMember();
    updateTimeStampEvent.setNewEventId(getSystem());

    if (event.getRegion() instanceof BucketRegion) {
      BucketRegion bucketRegion = (BucketRegion) event.getRegion();
      PartitionedRegion partitionedRegion = bucketRegion.getPartitionedRegion();
      updateTimeStampEvent.setRegion(partitionedRegion);

      // increment the tailKey for the event
      if (partitionedRegion.isParallelWanEnabled()) {
        bucketRegion.handleWANEvent(updateTimeStampEvent);
      }

      if (partitionedRegion.isInitialized()) {
        partitionedRegion.notifyGatewaySender(EnumListenerEvent.TIMESTAMP_UPDATE,
            updateTimeStampEvent);
      }
    } else {
      updateTimeStampEvent.setRegion(event.getRegion());
      notifyGatewaySender(EnumListenerEvent.TIMESTAMP_UPDATE, updateTimeStampEvent);
    }
  }

  /**
   * Update CachePerfStats
   */
  private void updateStatsForCreate() {
    getCachePerfStats().incCreates();
  }

  @Override
  public void basicPutPart3(EntryEventImpl event, RegionEntry entry, boolean isInitialized,
      long lastModified, boolean invokeCallbacks, boolean ifNew, boolean ifOld,
      Object expectedOldValue, boolean requireOldValue) {
    if (invokeCallbacks) {
      if (event.isBulkOpInProgress()) {
        event.getPutAllOperation().addEntry(event);
      }
    }
  }

  @Override
  public void invokePutCallbacks(final EnumListenerEvent eventType, final EntryEventImpl event,
      final boolean callDispatchListenerEvent, boolean notifyGateways) {

    // disallow callbacks on import
    if (!event.isGenerateCallbacks()) {
      return;
    }

    // Notify bridge clients (if this is a BridgeServer)
    Operation op = event.getOperation();

    // The spec for ConcurrentMap support requires that operations be mapped
    // to non-CM counterparts
    if (op == Operation.PUT_IF_ABSENT) {
      event.setOperation(Operation.CREATE);
    } else if (op == Operation.REPLACE) {
      event.setOperation(Operation.UPDATE);
    }

    event.setEventType(eventType);
    notifyBridgeClients(event);

    if (notifyGateways) {
      notifyGatewaySender(eventType, event);
    }
    if (callDispatchListenerEvent) {
      dispatchListenerEvent(eventType, event);
    }
  }

  /**
   * retrieve a deep copy of the Region's event state. This is used for getInitialImage. The result
   * is installed in the receiver of the image.
   */
  public Map<? extends DataSerializable, ? extends DataSerializable> getEventState() {
    return getEventTracker().getState();
  }

  /**
   * Record the event state encapsulated in the given Map.
   * <p>
   * This is intended for state transfer during GII.
   *
   * @param provider the member that provided this state
   * @param state a Map obtained from getEventState()
   */
  void recordEventState(InternalDistributedMember provider, Map state) {
    getEventTracker().recordState(provider, state);
  }

  /**
   * generate version tag if it does not exist and set it into the event.
   */
  @Override
  public void generateAndSetVersionTag(InternalCacheEvent event, RegionEntry entry) {
    if (entry != null && event.getOperation().isEntry()) {
      EntryEventImpl entryEvent = (EntryEventImpl) event;
      if (!entryEvent.isOriginRemote() && shouldGenerateVersionTag(entry, entryEvent)) {
        boolean eventHasDelta = getSystem().getConfig().getDeltaPropagation()
            && !scope.isDistributedNoAck() && entryEvent.getDeltaBytes() != null;
        VersionTag v = entry.generateVersionTag(null, eventHasDelta, this, entryEvent);
        if (logger.isDebugEnabled() && v != null) {
          logger.debug("generated version tag {} for {}", v, entryEvent.getKey());
        }
      }
    }
  }

  /**
   * record the event's sequenceId in Region's event state to prevent replay.
   */
  @Override
  public void recordEvent(InternalCacheEvent event) {
    getEventTracker().recordEvent(event);
  }

  /**
   * has the Region's event state seen this event?
   *
   * @return true if the Region's event state has seen the event
   */
  @Override
  public boolean hasSeenEvent(EntryEventImpl event) {
    return getEventTracker().hasSeenEvent(event);
  }

  /**
   * tries to find the version tag for a event
   *
   * @return the version tag, if known. Null if not
   */
  @Override
  public VersionTag findVersionTagForEvent(EventID eventId) {
    return getEventTracker().findVersionTagForSequence(eventId);
  }

  /**
   * tries to find the version tag for a replayed client event
   *
   * @return the version tag, if known. Null if not
   */
  public VersionTag findVersionTagForClientBulkOp(EventID eventId) {
    return getEventTracker().findVersionTagForBulkOp(eventId);
  }

  /**
   * has the Region's event state seen this event? Most checks should use the method that takes an
   * Event, not an ID, but with transactions we do not have an event at the time the check needs to
   * be made. Consequently, this method may cause events to be recorded that would otherwise be
   * ignored.
   *
   * @param eventID the identifier of the event
   * @return true if the Region's event state has seen the event
   */
  @Override
  public boolean hasSeenEvent(EventID eventID) {
    return getEventTracker().hasSeenEvent(eventID);
  }

  /**
   * A routine to provide synchronization running based on <memberShipID, threadID> of the
   * requesting client for the region's event state
   *
   * @param task - a Runnable to wrap the processing of the bulk op
   * @param eventId - the base event ID of the bulk op
   * @since GemFire 5.7
   */
  @Override
  public void syncBulkOp(Runnable task, EventID eventId) {
    getEventTracker().syncBulkOp(task, eventId, isTX());
  }

  public void recordBulkOpStart(ThreadIdentifier membershipID, EventID eventID) {
    if (!isTX()) {
      getEventTracker().recordBulkOpStart(eventID, membershipID);
    }
  }

  protected void notifyBridgeClients(CacheEvent event) {
    int numBS = getCache().getCacheServers().size();

    // In case of localOperations no need to notify clients.
    if (event.getOperation().isLocal() || numBS == 0) {
      return;
    }
    // Return if the inhibit all notifications flag is set
    if (event instanceof EntryEventImpl) {
      if (((EntryEventImpl) event).inhibitAllNotifications()) {
        if (logger.isDebugEnabled()) {
          logger.debug("Notification inhibited for key {}", event);
        }
        return;
      }
    }

    if (shouldNotifyBridgeClients()) {
      if (logger.isDebugEnabled()) {
        logger.debug("{}: notifying {} cache servers of event: {}", getName(), numBS,
            event);
      }

      Operation op = event.getOperation();
      if (event.getOperation().isEntry()) {
        EntryEventImpl e = (EntryEventImpl) event;
        if (e.getEventType() == null) {
          if (op.isCreate()) {
            e.setEventType(EnumListenerEvent.AFTER_CREATE);
          } else if (op.isUpdate()) {
            e.setEventType(EnumListenerEvent.AFTER_UPDATE);
          } else if (op.isDestroy()) {
            e.setEventType(EnumListenerEvent.AFTER_DESTROY);
          } else if (op.isInvalidate()) {
            e.setEventType(EnumListenerEvent.AFTER_INVALIDATE);
          } else {
            throw new IllegalStateException("event is missing client notification eventType: " + e);
          }
        }
      }

      InternalCacheEvent ice = (InternalCacheEvent) event;
      if (!isUsedForPartitionedRegionBucket()) {
        generateLocalFilterRouting(ice);
      }

      CacheClientNotifier.notifyClients((InternalCacheEvent) event);
    }
  }

  /**
   * Returns true if this region notifies any serial gateway senders including internal async event
   * queues.
   */
  public boolean notifiesSerialGatewaySender() {
    if (isPdxTypesRegion()) {
      return false;
    }
    Set<String> allGatewaySenderIds = getAllGatewaySenderIds();
    if (!allGatewaySenderIds.isEmpty()) {
      for (GatewaySender sender : getCache().getAllGatewaySenders()) {
        if (allGatewaySenderIds.contains(sender.getId())) {
          if (!sender.isParallel()) {
            return true;
          }
        }
      }
    }
    return false;
  }

  protected void notifyGatewaySender(EnumListenerEvent operation, EntryEventImpl event) {
    notifyGatewaySender(operation, event, false);
  }

  protected void notifyGatewaySender(EnumListenerEvent operation, EntryEventImpl event,
      boolean isLastEventInTransaction) {
    if (isPdxTypesRegion()) {
      return;
    }

    // Return if the inhibit all notifications flag is set
    if (event.inhibitAllNotifications()) {
      if (logger.isDebugEnabled()) {
        logger.debug("Notification inhibited for key {}", event);
      }
      return;
    }

    checkSameSenderIdsAvailableOnAllNodes();
    Set<String> allGatewaySenderIds;
    if (event.getOperation() == Operation.UPDATE_VERSION_STAMP) {
      allGatewaySenderIds = getGatewaySenderIds();
    } else {
      allGatewaySenderIds = getAllGatewaySenderIds();
    }

    List<Integer> allRemoteDSIds = getRemoteDsIds(allGatewaySenderIds);
    if (allRemoteDSIds != null) {
      for (GatewaySender sender : getCache().getAllGatewaySenders()) {
        if (allGatewaySenderIds.contains(sender.getId())) {
          // TODO: This is a BUG. Why return and not continue?
          if (!getDataPolicy().withStorage() && sender.isParallel()) {
            return;
          }
          if (logger.isDebugEnabled()) {
            logger.debug("Notifying the GatewaySender : {}", sender.getId());
          }
          ((AbstractGatewaySender) sender).distribute(operation, event, allRemoteDSIds,
              isLastEventInTransaction);
        }
      }
    }
  }

  void checkSameSenderIdsAvailableOnAllNodes() {
    // do nothing
  }

  /**
   * @param cacheWrite if true, then we're just cleaning up the local cache and calling listeners,
   * @see DistributedRegion#basicDestroyRegion(RegionEventImpl, boolean, boolean, boolean)
   */
  void basicDestroyRegion(RegionEventImpl event, boolean cacheWrite)
      throws CacheWriterException, TimeoutException {
    basicDestroyRegion(event, cacheWrite, true, true);
  }

  void basicDestroyRegion(RegionEventImpl event, boolean cacheWrite, boolean lock,
      boolean callbackEvents) throws CacheWriterException, TimeoutException {
    preDestroyChecks();

    final TXStateProxy tx = cache.getTXMgr().pauseTransaction();
    try {
      boolean acquiredLock = false;
      if (lock) {
        try {
          acquireDestroyLock();
          acquiredLock = true;
        } catch (CancelException ignore) {
          if (logger.isDebugEnabled()) {
            logger.debug(
                "basicDestroyRegion: acquireDestroyLock failed due to cache closure, region = {}",
                getFullPath());
          }
        }
      }

      try {
        // maintain destroy lock and TXStateInterface
        // I moved checkRegionDestroyed up out of the following
        // try block because it does not seem correct to deliver
        // a destroy event to the clients of the region was already
        // destroyed on the server.
        checkRegionDestroyed(false);
        boolean cancelledByCacheWriterException = false;
        HashSet eventSet = null;

        try { // ensure that destroy events are dispatched
          if (this instanceof PartitionedRegion
              && !((PartitionedRegion) this).getParallelGatewaySenderIds().isEmpty()) {
            ((PartitionedRegion) this).destroyParallelGatewaySenderRegion(event.getOperation(),
                cacheWrite, lock, callbackEvents);
          }

          if (parentRegion != null) {
            // "Bubble up" the cache statistics to parent if this regions are more recent
            parentRegion.updateStats();
          }

          try {
            eventSet = callbackEvents ? new HashSet() : null;
            destroyedSubregionSerialNumbers = collectSubregionSerialNumbers();
            recursiveDestroyRegion(eventSet, event, cacheWrite);
          } catch (CancelException e) {
            // This should be properly caught and ignored; if we see this there is
            // a serious problem.
            if (!cache.forcedDisconnect()) {
              logger.warn(String.format(
                  "recursiveDestroyRegion: recursion failed due to cache closure. region, %s",
                  getFullPath()),
                  e);
            }
          } catch (CacheWriterException cwe) {
            cancelledByCacheWriterException = true;
            throw cwe;
          }

          // at this point all subregions are destroyed and this region has been marked as destroyed
          // and postDestroyRegion has been called for each region. The only detail left is
          // unhooking this region from the parent subregion map, and sending listener events
          Assert.assertTrue(isDestroyed);

          // Added for M&M : At this point we can safely call ResourceEvent to remove the region
          // artifacts From Management Layer
          if (!isInternalRegion()) {
            InternalDistributedSystem system = cache.getInternalDistributedSystem();
            system.handleResourceEvent(ResourceEvent.REGION_REMOVE, this);
          }

          try {
            LocalRegion parent = parentRegion;
            if (parent == null) {
              cache.removeRoot(this);
            } else {
              parent.subregions.remove(regionName, this);
            }
          } catch (CancelException e) {
            if (!cache.forcedDisconnect()) {
              logger.warn(String.format(
                  "basicDestroyRegion: parent removal failed due to cache closure. region, %s",
                  getFullPath()),
                  e);
            }
          }

        } finally {
          // ensure that destroy events are dispatched
          if (!cancelledByCacheWriterException) {
            // We only need to notify bridgeClients of the top level region destroy
            // which it will take and do a localRegionDestroy.
            // So we pass it event and NOT eventSet
            event.setEventType(EnumListenerEvent.AFTER_REGION_DESTROY);
            notifyBridgeClients(event);
          }

          // call sendPendingRegionDestroyEvents even if cancelledByCacheWriterException
          // since some of the destroys happened.
          if (eventSet != null && callbackEvents) {
            try {
              sendPendingRegionDestroyEvents(eventSet);
            } catch (CancelException ignore) {
              // ignore, we're mute.
            }
          }
        }

      } finally {
        if (acquiredLock) {
          try {
            releaseDestroyLock();
          } catch (CancelException ignore) {
            // ignore
          }
        }
      }

    } finally {
      cache.getTXMgr().unpauseTransaction(tx);
    }
  }

  void preDestroyChecks() {
    // do nothing
  }

  void distributeDestroyRegion(RegionEventImpl event, boolean notifyOfRegionDeparture) {
    // do nothing
  }

  public static final float DEFAULT_HEAPLRU_EVICTION_HEAP_PERCENTAGE = 80.0f;

  /**
   * Called after this region has been completely created
   *
   * @see DistributedRegion#postDestroyRegion(boolean, RegionEventImpl)
   * @since GemFire 5.0
   */
  @Override
  public void postCreateRegion() {
    if (getEvictionAttributes().getAlgorithm().isLRUHeap()) {
      final LogWriter logWriter = cache.getLogger();
      float evictionPercentage = DEFAULT_HEAPLRU_EVICTION_HEAP_PERCENTAGE;

      // This is new to 6.5. If a heap lru region is created
      // we make sure that the eviction percentage is enabled.
      InternalResourceManager rm = cache.getInternalResourceManager();
      if (!getOffHeap()) {
        if (!rm.getHeapMonitor().hasEvictionThreshold()) {
          float criticalPercentage = rm.getCriticalHeapPercentage();
          if (criticalPercentage > 0.0f) {
            if (criticalPercentage >= 10.f) {
              evictionPercentage = criticalPercentage - 5.0f;
            } else {
              evictionPercentage = criticalPercentage;
            }
          }
          rm.setEvictionHeapPercentage(evictionPercentage);
          if (logWriter.fineEnabled()) {
            logWriter
                .fine("Enabled heap eviction at " + evictionPercentage + " percent for LRU region");
          }
        }

      } else {
        if (!rm.getOffHeapMonitor().hasEvictionThreshold()) {
          float criticalPercentage = rm.getCriticalOffHeapPercentage();
          if (criticalPercentage > 0.0f) {
            if (criticalPercentage >= 10.f) {
              evictionPercentage = criticalPercentage - 5.0f;
            } else {
              evictionPercentage = criticalPercentage;
            }
          }
          rm.setEvictionOffHeapPercentage(evictionPercentage);
          if (logWriter.fineEnabled()) {
            logWriter.fine(
                "Enabled off-heap eviction at " + evictionPercentage + " percent for LRU region");
          }
        }
      }
    }

    if (!isInternalRegion()) {
      getCachePerfStats().incRegions(1);
      if (getMembershipAttributes().hasRequiredRoles()) {
        getCachePerfStats().incReliableRegions(1);
      }
    }

    if (hasListener()) {
      RegionEventImpl event =
          new RegionEventImpl(this, Operation.REGION_CREATE, null, false, getMyId());
      dispatchListenerEvent(EnumListenerEvent.AFTER_REGION_CREATE, event);
    }
    releaseAfterRegionCreateEventLatch();
    SystemMemberCacheEventProcessor.send(getCache(), this, Operation.REGION_CREATE);
    initializingRegion.remove();
  }

  /**
   * This method is invoked after isDestroyed has been set to true
   */
  void postDestroyRegion(boolean destroyDiskRegion, RegionEventImpl event) {
    if (diskRegion != null) {
      if (destroyDiskRegion) {
        diskRegion.endDestroy(this);
      } else {
        diskRegion.close(this);
      }
    }
    if (versionVector != null) {
      try {
        cache.getDistributionManager().removeMembershipListener(versionVector);
      } catch (CancelException ignore) {
        // ignore: cache close will remove the membership listener
      }
    }
  }

  /**
   * @param cacheWrite true if cacheWrite should be performed or false if cacheWrite should not be
   *        performed
   * @see DistributedRegion#basicDestroy(EntryEventImpl, boolean, Object)
   */
  @Override
  public void basicDestroy(final EntryEventImpl event, final boolean cacheWrite,
      Object expectedOldValue)
      throws EntryNotFoundException, CacheWriterException, TimeoutException {

    if (!event.isOriginRemote()) {
      checkIfReplicatedAndLocalDestroy(event);
    }

    if (hasSeenEvent(event)) {
      assert getJTAEnlistedTX() == null;
      if (logger.isTraceEnabled(LogMarker.DM_VERBOSE)) {
        logger.trace(LogMarker.DM_VERBOSE,
            "LR.basicDestroy: this cache has already seen this event {}", event);
      }
      if (getConcurrencyChecksEnabled() && event.getVersionTag() != null
          && !event.getVersionTag().isRecorded()) {
        getVersionVector().recordVersion((InternalDistributedMember) event.getDistributedMember(),
            event.getVersionTag());
      }
      // When client retried and returned with hasSeenEvent for both LR and DR,
      // the server should still
      // notifyGatewayHubs even the event could be duplicated in gateway queues1
      notifyGatewaySender(EnumListenerEvent.AFTER_DESTROY, event);
      return;
    }

    discoverJTA();
    getDataView().destroyExistingEntry(event, cacheWrite, expectedOldValue);
  }

  final boolean restoreSetOperationTransactionBehavior =
      SystemPropertyHelper.restoreSetOperationTransactionBehavior();

  /**
   * Do the expensive work of discovering an existing JTA transaction Only needs to be called at
   * Region.Entry entry points e.g. Region.put, Region.invalidate, etc.
   *
   * @since GemFire tx
   */
  void discoverJTA() {
    if (!isSecret() && !isUsedForPartitionedRegionAdmin() && !isUsedForMetaRegion()) {
      // prevent internal regions from participating in a TX
      getJTAEnlistedTX();
    }
  }

  private boolean isTransactionPaused() {
    TXManagerImpl txMgr = (TXManagerImpl) getCache().getCacheTransactionManager();
    return txMgr.isTransactionPaused();
  }

  private boolean isJTAPaused() {
    TXManagerImpl txMgr = (TXManagerImpl) getCache().getCacheTransactionManager();
    return txMgr.isJTAPaused();
  }

  /**
   * @return true if a transaction is in process
   * @since GemFire tx
   */
  boolean isTX() {
    return getTXState() != null;
  }

  /**
   * @param expectedOldValue if this is non-null, only destroy if key exists and old value is equal
   *        to expectedOldValue
   * @return true if a the destroy was done; false if it was not needed
   */
  @Override
  public boolean mapDestroy(final EntryEventImpl event, final boolean cacheWrite,
      final boolean isEviction, Object expectedOldValue)
      throws CacheWriterException, EntryNotFoundException, TimeoutException {
    final boolean inGII = lockGII();
    try {
      // make sure unlockGII is called
      return mapDestroy(event, cacheWrite, isEviction, expectedOldValue, inGII, false);
    } finally {
      if (inGII) {
        unlockGII();
      }
    }
  }

  private boolean mapDestroy(final EntryEventImpl event, final boolean cacheWrite,
      final boolean isEviction, Object expectedOldValue, boolean needTokensForGII,
      boolean removeRecoveredEntry) {

    // When register interest is in progress ,
    // We should not remove the key from the
    // region and instead replace the value
    // in the map with a DESTROYED token
    final boolean inRI = !needTokensForGII && !event.isFromRILocalDestroy() && lockRIReadLock();

    // at this point riCnt is guaranteed to be correct and we know for sure
    // whether a RI is in progress and that riCnt will not change during this
    // destroy operation
    try {
      final boolean needRIDestroyToken = inRI && riCnt > 0;
      final boolean inTokenMode = needTokensForGII || needRIDestroyToken;

      // the following will call basicDestroyPart2 at the correct moment
      return entries.destroy(event, inTokenMode, needRIDestroyToken, cacheWrite, isEviction,
          expectedOldValue, removeRecoveredEntry);

    } catch (ConcurrentCacheModificationException ignore) {
      // this can happen in a client/server cache when another thread
      // managed to slip in its version info to the region entry before this
      // thread got around to doing so
      if (logger.isDebugEnabled()) {
        logger.debug("caught concurrent modification attempt when applying {}", event);
      }
      // Notify clients only if its NOT a gateway event.
      if (event.getVersionTag() != null && !event.getVersionTag().isGatewayTag()) {
        notifyBridgeClients(event);
        notifyGatewaySender(EnumListenerEvent.AFTER_DESTROY, event);
      }
      return true; // event was elided

    } catch (DiskAccessException dae) {
      handleDiskAccessException(dae);
      throw dae;

    } finally {
      if (inRI) {
        unlockRIReadLock();
      }
    }
  }

  /**
   * Return true if dae was caused by a RegionDestroyedException.
   */
  static boolean causedByRDE(DiskAccessException diskAccessException) {
    boolean result = false;
    if (diskAccessException != null) {
      Throwable cause = diskAccessException.getCause();
      while (cause != null) {
        if (cause instanceof RegionDestroyedException) {
          result = true;
          break;
        }
        cause = cause.getCause();
      }
    }
    return result;
  }

  @Override
  public void handleDiskAccessException(DiskAccessException dae) {
    handleDiskAccessException(dae, false);
  }

  /**
   * @param dae DiskAccessException encountered by the thread
   * @param duringInitialization indicates that this exception occurred during region
   *        initialization. Instead of closing the cache here, we rely on the region initialization
   *        to clean things up.
   * @see DistributedRegion#initialize(InputStream, InternalDistributedMember,
   *      InternalRegionArguments)
   * @see LocalRegion#initialize(InputStream, InternalDistributedMember, InternalRegionArguments)
   * @see InitialImageOperation#processChunk
   */
  void handleDiskAccessException(DiskAccessException dae, boolean duringInitialization) {

    if (duringInitialization && !(dae instanceof ConflictingPersistentDataException)) {
      return;
    }

    if (causedByRDE(dae)) {
      return;
    }

    // log the error
    String msg =
        String.format(
            "A DiskAccessException has occurred while writing to the disk for region %s. The cache will be closed.",
            fullPath);
    logger.error(msg, dae);

    // forward the error to the disk store
    getDiskStore().handleDiskAccessException(dae);
  }

  void expireDestroy(final EntryEventImpl event, final boolean cacheWrite) {
    basicDestroy(event, cacheWrite, null);
  }

  void expireInvalidate(final EntryEventImpl event) {
    basicInvalidate(event);
  }

  /**
   * Creates an event for EVICT_DESTROY operations. It is intended that this method be overridden to
   * allow for special handling of Partitioned Regions.
   *
   * @param key - the key that this event is related to
   * @return an event for EVICT_DESTROY
   */
  @Retained
  EntryEventImpl generateEvictDestroyEvent(final Object key) {
    @Retained
    EntryEventImpl event = entryEventFactory.create(this, Operation.EVICT_DESTROY, key,
        null, null, false, getMyId());

    if (generateEventID()) {
      event.setNewEventId(cache.getDistributedSystem());
    }
    return event;
  }

  /**
   * @return true if the evict destroy was done; false if it was not needed
   */
  boolean evictDestroy(EvictableEntry entry) {
    checkReadiness();

    @Released
    final EntryEventImpl event = generateEvictDestroyEvent(entry.getKey());

    try {
      return mapDestroy(event, false, // cacheWrite
          true, // isEviction
          null); // expectedOldValue
    } catch (CacheWriterException error) {
      throw new Error(
          "Cache Writer should not have been called for evictDestroy",
          error);
    } catch (TimeoutException anotherError) {
      throw new Error(
          "No distributed lock should have been attempted for evictDestroy",
          anotherError);
    } catch (EntryNotFoundException yetAnotherError) {
      throw new Error(
          "EntryNotFoundException should be masked for evictDestroy",
          yetAnotherError);
    } finally {
      event.release();
    }
  }

  /**
   * Called by lower levels {@link AbstractRegionMap} while holding the entry synchronization
   * <bold>and</bold> while the entry remains in the map. Once the entry is removed from the map,
   * then other operations synchronize on a new entry, allow for ordering problems between
   * {@link #create(Object, Object, Object)} and {@link #destroy(Object, Object)} operations.
   *
   * @param entry the Region entry being destroyed
   * @param event the event describing the destroy operation
   * @since GemFire 5.1
   */
  @Override
  public void basicDestroyBeforeRemoval(RegionEntry entry, EntryEventImpl event) {
    // do nothing
  }

  /**
   * Called by lower levels, while still holding the write sync lock, and the low level has
   * completed its part of the basic destroy
   */
  @Override
  public void basicDestroyPart2(RegionEntry re, EntryEventImpl event, boolean inTokenMode,
      boolean conflictWithClear, boolean duringRI, boolean invokeCallbacks) {
    if (!(this instanceof HARegion)) {
      if (logger.isTraceEnabled()) {
        logger.trace("basicDestroyPart2(inTokenMode={},conflictWithClear={},duringRI={}) event={}",
            inTokenMode, conflictWithClear, duringRI, event);
      }
    }
    VersionTag v = event.getVersionTag();

    /*
     * destroys that are not part of the cleaning out of keys prior to a register-interest are
     * marked with Tombstones instead of Destroyed tokens so that they are not reaped after the RI
     * completes. RI does not create Tombstones because it would flood the TombstoneService with
     * unnecessary work.
     */
    if (inTokenMode && !(getConcurrencyChecksEnabled() || event.isFromRILocalDestroy())) {
      if (re.isDestroyed()) {
        getImageState().addDestroyedEntry(event.getKey());
        if (!(this instanceof HARegion)) {
          if (logger.isTraceEnabled()) {
            logger.trace("basicDestroy: {}--> Token.DESTROYED", event.getKey());
          }
        }
      }
    } else {
      if (getConcurrencyChecksEnabled() && !(this instanceof HARegion)) {
        if (logger.isDebugEnabled()) {
          logger.debug("basicDestroyPart2: {}, version={}", event.getKey(), v);
        }
      }
    }

    /*
     * this is too late to do index maintenance with a CompactRangeIndex because we need to have the
     * old value still intact. At this point the old value has already be replaced with a destroyed
     * token.
     */

    if (event.isBulkOpInProgress() && isUsedForPartitionedRegionBucket) {
      if (logger.isDebugEnabled()) {
        logger.debug("For bulk operation on bucket region, not to notify gateway sender earlier.");
      }
    } else {
      notifyGatewaySender(EnumListenerEvent.AFTER_DESTROY, event);
    }

    // invoke callbacks if initialized and told to do so, or if this is a bucket in a partitioned
    // region
    if (invokeCallbacks && !event.isBulkOpInProgress()) {
      if (isInitialized() && (!inTokenMode || duringRI) || isUsedForPartitionedRegionBucket) {
        try {
          re.dispatchListenerEvents(event);
        } catch (InterruptedException ignore) {
          Thread.currentThread().interrupt();
          stopper.checkCancelInProgress(null);
        }
      } else {
        event.callbacksInvoked(true);
      }
    }
  }

  /**
   * distribution and callback notification are done in part2 inside entry lock for maintaining the
   * order of events.
   */
  @Override
  public void basicDestroyPart3(RegionEntry re, EntryEventImpl event, boolean inTokenMode,
      boolean duringRI, boolean invokeCallbacks, Object expectedOldValue) {

    if (invokeCallbacks) {
      if (event.isBulkOpInProgress()) {
        event.getRemoveAllOperation().addEntry(event);
      }
    }
    if (!inTokenMode || duringRI) {
      updateStatsForDestroy();
    }
    entryUserAttributes.remove(event.getKey());
  }

  /**
   * Update stats
   */
  private void updateStatsForDestroy() {
    getCachePerfStats().incDestroys();
  }

  void txClearRegion() {
    TXStateInterface tx = getJTAEnlistedTX();
    if (tx != null) {
      tx.rmRegion(this);
    }
  }

  @Override
  public void invokeDestroyCallbacks(final EnumListenerEvent eventType, final EntryEventImpl event,
      final boolean callDispatchListenerEvent, boolean notifyGateways) {

    // The spec for ConcurrentMap support requires that operations be mapped
    // to non-CM counterparts
    if (event.getOperation() == Operation.REMOVE) {
      event.setOperation(Operation.DESTROY);
    }
    event.setEventType(eventType);
    notifyBridgeClients(event);
    if (notifyGateways) {
      notifyGatewaySender(eventType, event);
    }
    if (callDispatchListenerEvent && !event.getIsRedestroyedEntry()) {
      dispatchListenerEvent(eventType, event);
    }
  }

  @Override
  public void invokeTXCallbacks(final EnumListenerEvent eventType, final EntryEventImpl event,
      final boolean callDispatchListenerEvent) {
    invokeTXCallbacks(eventType, event, callDispatchListenerEvent, false);
  }

  @Override
  public void invokeTXCallbacks(final EnumListenerEvent eventType, final EntryEventImpl event,
      final boolean callDispatchListenerEvent,
      final boolean isLastEventInTransaction) {

    // The spec for ConcurrentMap support requires that operations be mapped
    // to non-CM counterparts

    Operation operation = event.getOperation();

    if (logger.isDebugEnabled()) {
      logger.debug("invokeTXCallbacks for event {}", event);
    }

    if (operation == Operation.REMOVE) {
      event.setOperation(Operation.DESTROY);
    } else if (operation == Operation.PUT_IF_ABSENT) {
      event.setOperation(Operation.CREATE);
    } else if (operation == Operation.REPLACE) {
      event.setOperation(Operation.UPDATE);
    }
    event.setEventType(eventType);
    notifyBridgeClients(event);
    notifyGatewaySender(eventType, event, isLastEventInTransaction);
    if (callDispatchListenerEvent) {
      if (event.getInvokePRCallbacks() || !(event.getRegion() instanceof PartitionedRegion)
          && !event.getRegion().isUsedForPartitionedRegionBucket()) {
        dispatchListenerEvent(eventType, event);
      }
    }
  }

  /**
   * @param key the key of the entry to destroy
   * @param rmtOrigin true if transaction being applied had a remote origin
   * @param event filled in if operation performed
   * @param needTokensForGII true if caller has determined we are in destroy token mode and will
   *        keep us in that mode while this call is executing.
   * @param isOriginRemote whether the event originated in a peer or in this vm
   * @param txEntryState for passing up versionTag - only on near side
   * @param versionTag tag generated by txCoordinator - only on far side
   * @param tailKey tail (shadow) key generated by txCoordinator for WAN - only on farside
   */
  @Override
  public void txApplyDestroy(Object key, TransactionId rmtOrigin, TXRmtEvent event,
      boolean needTokensForGII, Operation op, EventID eventId, Object aCallbackArgument,
      List<EntryEventImpl> pendingCallbacks, FilterRoutingInfo filterRoutingInfo,
      ClientProxyMembershipID bridgeContext, boolean isOriginRemote, TXEntryState txEntryState,
      VersionTag versionTag, long tailKey) {

    final boolean inRI = !needTokensForGII && lockRIReadLock();
    final boolean needRIDestroyToken = inRI && riCnt > 0;

    try {
      final boolean inTokenMode = isInTokenModeNeeded(needTokensForGII, needRIDestroyToken);
      entries.txApplyDestroy(key, rmtOrigin, event, inTokenMode, needRIDestroyToken, op,
          eventId, aCallbackArgument, pendingCallbacks, filterRoutingInfo, bridgeContext,
          isOriginRemote, txEntryState, versionTag, tailKey);
    } finally {
      if (inRI) {
        unlockRIReadLock();
      }
    }
  }

  boolean isInTokenModeNeeded(boolean needTokensForGII, boolean needRIDestroyToken) {
    return !getConcurrencyChecksEnabled() && (needTokensForGII || needRIDestroyToken);
  }

  /**
   * Called by lower levels, while still holding the write sync lock, and the low level has
   * completed its part of the basic destroy
   */
  void txApplyDestroyPart2(RegionEntry re, Object key, boolean inTokenMode, boolean clearConflict,
      boolean alreadyDestroyedOrRemoved) {
    if (testCallable != null) {
      testCallable.call(this, Operation.DESTROY, re);
    }
    if (inTokenMode) {
      getImageState().addDestroyedEntry(key);
    } else if (!alreadyDestroyedOrRemoved) {
      updateStatsForDestroy();
    }
    entryUserAttributes.remove(key);
  }

  void basicInvalidateRegion(RegionEventImpl event) {
    final TXStateProxy tx = cache.getTXMgr().pauseTransaction();
    try {
      setRegionInvalid(true);
      getImageState().setRegionInvalidated(true);
      invalidateAllEntries(event);

      Set allSubregions = subregions(true);
      for (Object allSubregion : allSubregions) {
        LocalRegion region = (LocalRegion) allSubregion;
        region.setRegionInvalid(true);
        try {
          region.getImageState().setRegionInvalidated(true);
          region.invalidateAllEntries(event);

          if (!region.isInitialized()) {
            continue; // don't invoke callbacks if not initialized yet
          }

          if (region.hasListener()) {
            RegionEventImpl event2 = (RegionEventImpl) event.clone();
            event2.region = region;
            region.dispatchListenerEvent(EnumListenerEvent.AFTER_REGION_INVALIDATE, event2);
          }
        } catch (RegionDestroyedException ignore) {
          // ignore subregions that have been destroyed
        }
      }

      if (!isInitialized()) {
        return;
      }

      event.setEventType(EnumListenerEvent.AFTER_REGION_INVALIDATE);
      notifyBridgeClients(event);

      boolean hasListener = hasListener();
      if (logger.isDebugEnabled()) {
        logger.debug("basicInvalidateRegion: hasListener = {}", hasListener);
      }
      if (hasListener) {
        dispatchListenerEvent(EnumListenerEvent.AFTER_REGION_INVALIDATE, event);
      }

    } finally {
      cache.getTXMgr().unpauseTransaction(tx);
    }
  }

  /**
   * Determines whether the receiver is unexpired with regard to the given timeToLive and idleTime
   * attributes, which may different from this entry's actual attributes. Used for validation of
   * objects during netSearch(), which must validate remote entries against local timeout
   * attributes.
   */
  boolean isExpiredWithRegardTo(Object key, int ttl, int idleTime) {
    if (!getAttributes().getStatisticsEnabled()) {
      return false;
    }

    long expTime;
    try {
      expTime = new NetSearchExpirationCalculator(this, key, ttl, idleTime).getExpirationTime();
    } catch (EntryNotFoundException ignore) {
      return true;
    }

    return expTime != 0 && expTime <= cacheTimeMillis();
  }

  @Override
  public void dispatchListenerEvent(EnumListenerEvent op, InternalCacheEvent event) {
    // Return if the inhibit all notifications flag is set
    boolean isEntryEvent = event instanceof EntryEventImpl;
    if (isEntryEvent) {
      if (((EntryEventImpl) event).inhibitAllNotifications()) {
        if (logger.isDebugEnabled()) {
          logger.debug("Notification inhibited for key {}", event);
        }
        return;
      }
    }

    if (shouldDispatchListenerEvent()) {
      if (logger.isTraceEnabled()) {
        logger.trace("dispatchListenerEvent event={}", event);
      }

      final long start = getCachePerfStats().startCacheListenerCall();

      boolean isOriginRemote = false;
      boolean isOriginRemoteSetOnEvent = false;

      try {
        if (isEntryEvent) {
          if (((EntryEventImpl) event).isSingleHop()) {
            isOriginRemote = event.isOriginRemote();
            ((EntryEventImpl) event).setOriginRemote(true);
            isOriginRemoteSetOnEvent = true;
          }
          RegionEntry regionEntry = ((EntryEventImpl) event).getRegionEntry();
          if (regionEntry != null) {
            ((EntryEventImpl) event).getRegionEntry().setCacheListenerInvocationInProgress(true);
          }
        }

        if (cache.getEventThreadPool() == null) {
          dispatchEvent(this, event, op);
        } else {
          final EventDispatcher eventDispatcher = new EventDispatcher(event, op);
          try {
            cache.getEventThreadPool().execute(eventDispatcher);
          } catch (RejectedExecutionException ignore) {
            eventDispatcher.release();
            dispatchEvent(this, event, op);
          }
        }

      } finally {
        getCachePerfStats().endCacheListenerCall(start);
        if (isOriginRemoteSetOnEvent) {
          ((EntryEventImpl) event).setOriginRemote(isOriginRemote);
        }
        if (isEntryEvent) {
          RegionEntry regionEntry = ((EntryEventImpl) event).getRegionEntry();
          if (regionEntry != null) {
            regionEntry.setCacheListenerInvocationInProgress(false);
          }
        }
      }
    }
  }

  /**
   * @return true if initialization is complete
   */
  @Override
  public boolean isInitialized() {
    if (initialized) {
      return true;
    }

    StoppableCountDownLatch latch = getInitializationLatchAfterGetInitialImage();
    if (latch == null) {
      return true;
    }

    long count = latch.getCount();
    if (count == 0) {
      initialized = true;
      return true;
    }

    return false;
  }

  /**
   * @return true if event state has been transferred to this region from another cache
   */
  boolean isEventTrackerInitialized() {
    return getEventTracker().isInitialized();
  }

  public void acquireDestroyLock() {
    LocalRegion root = getRoot();
    boolean acquired = false;
    do {
      cache.getCancelCriterion().checkCancelInProgress(null);
      boolean interrupted = Thread.interrupted();
      try {
        root.destroyLock.acquire();
        acquired = true;
      } catch (InterruptedException ie) {
        interrupted = true;
        cache.getCancelCriterion().checkCancelInProgress(ie);
      } finally {
        if (interrupted) {
          Thread.currentThread().interrupt();
        }
      }
    } while (!acquired);
    if (logger.isDebugEnabled()) {
      logger.debug("Acquired Destroy Lock: {}", root);
    }
  }

  public void releaseDestroyLock() {
    LocalRegion root = getRoot();
    if (logger.isDebugEnabled()) {
      logger.debug("Releasing Destroy Lock: {}", root.getName());
    }
    root.destroyLock.release();
  }

  /**
   * Cleans up any resources that may have been allocated for this region during its initialization.
   */
  @Override
  public void cleanupFailedInitialization() {
    isDestroyed = true;

    // after isDestroyed is set to true call removeResourceListener
    cache.getInternalResourceManager(false).removeResourceListener(this);

    closeEntries();

    destroyedSubregionSerialNumbers = collectSubregionSerialNumbers();

    try {
      getEventTracker().stop();

      if (diskRegion != null) {
        try {
          diskRegion.cleanupFailedInitialization(this);
        } catch (IllegalStateException ignore) {
          // just ignore this exception since whoever called us is going
          // to report the exception that caused initialization to fail.
        }
      }

      // Clean up region in RegionListeners
      cache.invokeCleanupFailedInitialization(this);
    } finally {
      // make sure any waiters on initializing Latch are released
      releaseLatches();
    }
  }

  LocalRegion getRoot() {
    LocalRegion region = this;
    while (region.parentRegion != null) {
      region = region.parentRegion;
    }
    return region;
  }

  private void initializationFailed(LocalRegion subregion) {
    synchronized (subregionsLock) {
      subregions.remove(subregion.getName());
    }
    subregion.cleanupFailedInitialization();
  }

  /**
   * PRECONDITIONS: Synchronized on updateMonitor for this key in order to guarantee write-through
   * to map entry, and key must be in map
   *
   * @param lastModified time, may be 0 in which case uses now instead
   * @return the actual lastModifiedTime used.
   */
  @Override
  public long updateStatsForPut(RegionEntry entry, long lastModified, boolean lruRecentUse) {
    long lastAccessed = cacheTimeMillis();
    if (lruRecentUse) {
      entry.setRecentlyUsed(this);
    }
    if (lastModified == 0L) {
      lastModified = lastAccessed;
    }

    entry.updateStatsForPut(lastModified, lastAccessed);

    if (statisticsEnabled && !isProxy()) {
      // do not reschedule if there is already a task in the queue.
      // this prevents bloat in the TimerTask since cancelled tasks
      // do not actually get removed from the TimerQueue.
      // When the already existing task gets fired it checks to see
      // if it is premature and if so reschedules a task at that time.
      addExpiryTaskIfAbsent(entry);
    }

    // propagate to region
    setLastModifiedTime(lastModified);
    return lastModified;
  }

  /**
   * Returns a region in the subregion map first, then looks in the reinitializing region registry.
   *
   * @return the region or null if not found, may be destroyed
   */
  private LocalRegion basicGetSubregion(String name) {
    LocalRegion region = toRegion(subregions.get(name));

    // don't wait for reinitialization if the init_level for this thread is
    // ANY_INIT: We don't want CreateRegion messages to wait on a future
    // because it would cause a deadlock. If the region is ready for a
    // CreateRegion message, it would have been in the subregions map.

    if (region == null && getThreadInitLevelRequirement() != ANY_INIT) {
      String thePath = getFullPath() + Region.SEPARATOR + name;
      if (logger.isDebugEnabled()) {
        logger.debug("Trying reinitializing region, fullPath={}", thePath);
      }
      region = (LocalRegion) cache.getReinitializingRegion(thePath);
      if (logger.isDebugEnabled()) {
        logger.debug("Reinitialized region is {}", region);
      }
    }

    return region;
  }

  /**
   * Make a LocalRegion from an element in the subregion map Sent to parent region.
   *
   * @return This method may return null or a destroyed region if the region was just destroyed
   */
  private LocalRegion toRegion(Object element) {
    LocalRegion region = (LocalRegion) element;
    if (region != null) {
      // do not return until done initializing (unless this is an initializing thread)
      region.waitOnInitialization();
    }
    return region;
  }

  /**
   * Update the API statistics appropriately for returning this value from get.
   *
   * @param regionEntry the entry whose value was accessed
   */
  void updateStatsForGet(final RegionEntry regionEntry, final boolean hit) {
    if (!statisticsEnabled) {
      return;
    }

    final long now = cacheTimeMillis();
    if (regionEntry != null) {
      regionEntry.updateStatsForGet(hit, now);
      if (isEntryIdleExpiryPossible()) {
        addExpiryTaskIfAbsent(regionEntry);
      }
    }

    // update region stats
    setLastAccessedTime(now, hit);
  }

  private void sendPendingRegionDestroyEvents(Set regionEvents) {
    for (Object regionEvent : regionEvents) {
      RegionEventImpl regionEventImpl = (RegionEventImpl) regionEvent;
      regionEventImpl.region.dispatchListenerEvent(EnumListenerEvent.AFTER_REGION_DESTROY,
          regionEventImpl);
      if (!cache.forcedDisconnect()) {
        SystemMemberCacheEventProcessor.send(getCache(), regionEventImpl.getRegion(),
            regionEventImpl.getOperation());
      }
    }
  }

  /**
   * The listener is not closed until after the afterRegionDestroy event
   */
  void closeCallbacksExceptListener() {
    closeCacheCallback(getCacheLoader());
    closeCacheCallback(getCacheWriter());
    EvictionController evictionController = getEvictionController();
    if (evictionController != null) {
      evictionController.close();
    }
  }

  /**
   * This is only done when the cache is closed.
   */
  private void closeAllCallbacks() {
    closeCallbacksExceptListener();
    CacheListener[] listeners = fetchCacheListenersField();
    if (listeners != null) {
      for (final CacheListener listener : listeners) {
        closeCacheCallback(listener);
      }
    }
  }

  /**
   * Release the client connection pool if we have one
   *
   * @since GemFire 5.7
   */
  private void detachPool() {
    ServerRegionProxy serverRegionProxy = getServerProxy();
    if (serverRegionProxy != null) {
      InternalCache internalCache = getCache();
      String poolName = getPoolName();
      PoolImpl pool = (PoolImpl) PoolManager.find(getPoolName());
      if (poolName != null && pool != null) {
        serverRegionProxy
            .detach(internalCache.keepDurableSubscriptionsAlive() || pool.getKeepAlive());
      } else {
        serverRegionProxy.detach(internalCache.keepDurableSubscriptionsAlive());
      }
    }
  }

  /**
   * Closes the cqs created based on this region (Cache Client/writer/loader).
   */
  private void closeCqs() {
    CqService cqService = getCache().getCqService();
    if (cqService != null) {
      try {
        cqService.closeCqs(getFullPath());
      } catch (VirtualMachineError err) {
        SystemFailure.initiateFailure(err);
        // If this ever returns, rethrow the error. We're poisoned
        // now, so don't let this thread continue.
        throw err;
      } catch (Throwable t) {
        // Whenever you catch Error or Throwable, you must also
        // catch VirtualMachineError (see above). However, there is
        // _still_ a possibility that you are dealing with a cascading
        // error condition, so you also need to check to see if the JVM
        // is still usable:
        SystemFailure.checkFailure();
        logger.warn("Exception occurred while closing CQs on region destroy.",
            t);
      }
    }
  }

  /**
   * Called when the cache is closed. Behaves just like a Region.close except the operation is
   * CACHE_CLOSE
   */
  @Override
  public void handleCacheClose(Operation operation) {
    RegionEventImpl event =
        new RegionEventImpl(this, operation, null, false, getMyId(), generateEventID());
    if (!isDestroyed) { // don't destroy if already destroyed
      try {
        basicDestroyRegion(event, false, true, true);
      } catch (CancelException ignore) {
        // If the region was destroyed we see this because the cache is closing.
        // Since we are trying to close the cache don't get upset if
        // a region was destroyed out from under us
        if (logger.isDebugEnabled()) {
          logger.debug("handleCacheClose: Encountered cache closure while closing region {}",
              getFullPath());
        }
      } catch (RegionDestroyedException ignore) {
        // Since we are trying to close the cache don't get upset if
        // a region was destroyed out from under us
      } catch (CacheWriterException e) {
        // not possible with local operation, CacheWriter not called
        throw new Error("CacheWriterException should not be thrown here", e);
      } catch (TimeoutException e) {
        // not possible with local operation, no distributed locks possible
        InternalDistributedSystem ids = getCache().getInternalDistributedSystem();
        if (!ids.isDisconnecting()) {
          throw new InternalGemFireError(
              "TimeoutException should not be thrown here",
              e);
        }
      }
    }
  }

  private void checkCacheClosed() {
    if (cache.isClosed()) {
      throw cache.getCacheClosedException(null, null);
    }
  }

  private void checkRegionDestroyed(boolean checkCancel) {
    if (checkCancel) {
      cache.getCancelCriterion().checkCancelInProgress(null);
    }

    if (isDestroyed) {
      RegionDestroyedException regionDestroyedException;
      if (reinitialized_old) {
        regionDestroyedException = new RegionReinitializedException(toString(), getFullPath());
      } else if (cache.isCacheAtShutdownAll()) {
        throw cache.getCacheClosedException("Cache is being closed by ShutdownAll");
      } else {
        regionDestroyedException = new RegionDestroyedException(toString(), getFullPath());
      }

      // Race condition could cause the cache to be destroyed after the
      // cache close check above, so we need to re-check before throwing.
      if (checkCancel) {
        cache.getCancelCriterion().checkCancelInProgress(null);
      }

      throw regionDestroyedException;
    }

    if (isDestroyedForParallelWAN) {
      throw new RegionDestroyedException(
          "Region is being destroyed. Waiting for parallel queue to drain.",
          getFullPath());
    }
  }

  /**
   * For each region entry in this region call the callback
   *
   * @since GemFire prPersistSprint2
   */
  @Override
  public void foreachRegionEntry(RegionEntryCallback callback) {
    for (RegionEntry regionEntry : entries.regionEntriesInVM()) {
      callback.handleRegionEntry(regionEntry);
    }
  }

  void checkIfReplicatedAndLocalDestroy(EntryEventImpl event) {
    // disallow local invalidation for replicated regions
    if (getScope().isDistributed() && getDataPolicy().withReplication() && !event.isDistributed()
        && !isUsedForSerialGatewaySenderQueue()) {
      throw new IllegalStateException(
          "Not allowed to do a local destroy on a replicated region");
    }
  }

  /**
   * Return the number of subregions, including this region. Used for recursive size calculation in
   * SubregionsSet.size
   */
  private int allSubregionsSize() {
    int size = 1; /* 1 for this region */
    for (Object regionObject : subregions.values()) {
      LocalRegion region = (LocalRegion) regionObject;
      if (region != null && region.isInitialized() && !region.isDestroyed()) {
        size += region.allSubregionsSize();
      }
    }
    return size;
  }

  /**
   * Return the number of entries including in subregions. Used for recursive size calculation in
   * EntriesSet.size. This does not include tombstone entries stored in the region.
   */
  int allEntriesSize() {
    int size = entryCount();
    for (Object regionObject : subregions.values()) {
      LocalRegion region = toRegion(regionObject);
      if (region != null && !region.isDestroyed()) {
        size += region.allEntriesSize();
      }
    }
    return size;
  }

  /**
   * @param rgnEvent the RegionEvent for region invalidation
   */
  void invalidateAllEntries(RegionEvent rgnEvent) {
    Operation operation = Operation.LOCAL_INVALIDATE;
    if (rgnEvent.getOperation().isDistributed()) {
      operation = Operation.INVALIDATE;
    }

    // if this is a local invalidation, then set local invalid flag on event
    // so LOCAL_INVALID tokens is used (even though each individual entry
    // invalidation is not distributed).

    // region operation so it is ok to ignore tx state
    for (Object keyObject : keySet()) {
      try {

        // EventID will not be generated by this constructor
        @Released
        EntryEventImpl event = entryEventFactory.create(this, operation, keyObject, null, null,
            rgnEvent.isOriginRemote(), rgnEvent.getDistributedMember());

        try {
          event.setLocalInvalid(!rgnEvent.getOperation().isDistributed());
          basicInvalidate(event, false);
        } finally {
          event.release();
        }

      } catch (EntryNotFoundException ignore) {
        // ignore
      }
    }
  }

  boolean hasListener() {
    CacheListener[] listeners = fetchCacheListenersField();
    return listeners != null && listeners.length > 0;
  }

  private final DiskStoreImpl diskStoreImpl;

  @Override
  public DiskStoreImpl getDiskStore() {
    return diskStoreImpl;
  }

  /**
   * Return true if all disk attributes are defaults. DWA.isSynchronous can be true or false.
   */
  private boolean useDefaultDiskStore() {
    assert getDiskStoreName() == null;
    if (!Arrays.equals(getDiskDirs(), DefaultDiskDirs.getDefaultDiskDirs())) {
      return false;
    }
    if (!Arrays.equals(getDiskDirSizes(), DiskStoreFactory.DEFAULT_DISK_DIR_SIZES)) {
      return false;
    }

    DiskWriteAttributesFactory attributesFactory = new DiskWriteAttributesFactory();
    attributesFactory.setSynchronous(false);
    if (attributesFactory.create().equals(getDiskWriteAttributes())) {
      return true;
    }
    attributesFactory.setSynchronous(true);

    return attributesFactory.create().equals(getDiskWriteAttributes());
  }

  /**
   * Returns true if this region's config indicates that it will use a disk store.
   */
  boolean usesDiskStore(RegionAttributes regionAttributes) {
    return !isProxy() && (getAttributes().getDataPolicy().withPersistence() || isOverflowEnabled());
  }

  DiskStoreImpl findDiskStore(RegionAttributes regionAttributes,
      InternalRegionArguments internalRegionArgs) {
    // validate that persistent type registry is persistent
    if (getAttributes().getDataPolicy().withPersistence()) {
      getCache().getPdxRegistry().creatingPersistentRegion();
    }

    if (usesDiskStore(regionAttributes)) {
      if (getDiskStoreName() != null) {
        DiskStoreImpl diskStore =
            (DiskStoreImpl) getGemFireCache().findDiskStore(getDiskStoreName());
        if (diskStore == null) {
          throw new IllegalStateException(String.format("Disk store %s not found",
              getDiskStoreName()));
        }
        return diskStore;

      }
      if (useDefaultDiskStore()) {
        return getGemFireCache().getOrCreateDefaultDiskStore();

      }
      // backwards compat mode
      DiskStoreFactory diskStoreFactory = getGemFireCache().createDiskStoreFactory();
      diskStoreFactory.setDiskDirsAndSizes(getDiskDirs(), getDiskDirSizes());
      DiskWriteAttributes dwa = getDiskWriteAttributes();
      diskStoreFactory.setAutoCompact(dwa.isRollOplogs());
      diskStoreFactory.setMaxOplogSize(dwa.getMaxOplogSize());
      diskStoreFactory.setTimeInterval(dwa.getTimeInterval());

      if (dwa.getBytesThreshold() > 0) {
        diskStoreFactory.setQueueSize(1);
      } else {
        diskStoreFactory.setQueueSize(0);
      }

      DiskStoreFactoryImpl diskStoreFactoryImpl = (DiskStoreFactoryImpl) diskStoreFactory;
      return diskStoreFactoryImpl.createOwnedByRegion(getFullPath().replace(
          Region.SEPARATOR_CHAR, '_'),
          this instanceof PartitionedRegion, internalRegionArgs);
    }

    return null;
  }

  /**
   * Creates a new {@code DiskRegion} for this region. We assume that the attributes and the name of
   * the region have been set.
   *
   * @return {@code null} is a disk region is not desired
   * @since GemFire 3.2
   */
  DiskRegion createDiskRegion(InternalRegionArguments internalRegionArgs)
      throws DiskAccessException {

    if (internalRegionArgs.getDiskRegion() != null) {
      DiskRegion region = internalRegionArgs.getDiskRegion();
      region.createDataStorage();
      return region;
    }

    if (diskStoreImpl == null) {
      return null;
    }

    DiskRegionStats stats;

    if (this instanceof BucketRegion) {
      stats = internalRegionArgs.getPartitionedRegion().getDiskRegionStats();
    } else {
      stats = new DiskRegionStats(getCache().getDistributedSystem(), getFullPath());
    }

    EnumSet<DiskRegionFlag> diskFlags = EnumSet.noneOf(DiskRegionFlag.class);

    // Add flag if this region has versioning enabled
    if (getAttributes().getConcurrencyChecksEnabled()) {
      diskFlags.add(DiskRegionFlag.IS_WITH_VERSIONING);
    }

    // TODO: fix NO_PARTITITON typo
    return DiskRegion.create(diskStoreImpl, getFullPath(), false,
        getDataPolicy().withPersistence(), isOverflowEnabled(), isDiskSynchronous(), stats,
        getCancelCriterion(), this, getAttributes(), diskFlags, "NO_PARTITITON", -1,
        getCompressor(), getOffHeap());
  }

  /**
   * Returns the object sizer on this region or null if it has no sizer.
   *
   * @since GemFire 6.1.2.9
   */
  @Override
  public ObjectSizer getObjectSizer() {
    ObjectSizer result = null;
    EvictionAttributes ea = getEvictionAttributes();
    if (ea != null) {
      result = ea.getObjectSizer();
    }
    return result;
  }

  /**
   * Add the Region TTL expiry task to the scheduler
   */
  void addTTLExpiryTask() {
    synchronized (regionExpiryLock) {
      RegionTTLExpiryTask task = regionTTLExpiryTask;
      if (task != null) {
        task.cancel();
      }

      if (regionTimeToLive > 0) {
        regionTTLExpiryTask = (RegionTTLExpiryTask) cache.getExpirationScheduler()
            .addExpiryTask(new RegionTTLExpiryTask(this));
        if (regionTTLExpiryTask != null) {
          if (logger.isDebugEnabled()) {
            logger.debug("Initialized Region TTL Expiry Task {}", regionTTLExpiryTask);
          }
        }

      } else {
        regionTTLExpiryTask = null;
      }
    }
  }

  void addTTLExpiryTask(RegionTTLExpiryTask callingTask) {
    synchronized (regionExpiryLock) {
      if (regionTTLExpiryTask != null && regionTTLExpiryTask != callingTask) {
        return;
      }
      if (regionTimeToLive <= 0) {
        regionTTLExpiryTask = null;
        return;
      }

      RegionTTLExpiryTask task = new RegionTTLExpiryTask(this);
      if (logger.isDebugEnabled()) {
        logger.debug("Scheduling Region TTL Expiry Task {} which replaces {}", task,
            regionTTLExpiryTask);
      }
      regionTTLExpiryTask =
          (RegionTTLExpiryTask) cache.getExpirationScheduler().addExpiryTask(task);
    }
  }

  /**
   * Add the Region Idle expiry task to the scheduler
   */
  void addIdleExpiryTask() {
    synchronized (regionExpiryLock) {
      RegionIdleExpiryTask task = regionIdleExpiryTask;
      if (task != null) {
        task.cancel();
      }

      if (regionIdleTimeout > 0) {
        regionIdleExpiryTask = (RegionIdleExpiryTask) cache.getExpirationScheduler()
            .addExpiryTask(new RegionIdleExpiryTask(this));
        if (regionIdleExpiryTask != null) {
          if (logger.isDebugEnabled()) {
            logger.debug("Initialized Region Idle Expiry Task {}", regionIdleExpiryTask);
          }
        }

      } else {
        regionIdleExpiryTask = null;
      }
    }
  }

  void addIdleExpiryTask(RegionIdleExpiryTask callingTask) {
    synchronized (regionExpiryLock) {
      if (regionIdleExpiryTask != null && regionIdleExpiryTask != callingTask) {
        return;
      }
      if (regionIdleTimeout <= 0) {
        regionIdleExpiryTask = null;
        return;
      }

      RegionIdleExpiryTask task = new RegionIdleExpiryTask(this);
      if (logger.isDebugEnabled()) {
        logger.debug("Scheduling Region Idle Expiry Task {} which replaces {}", task,
            regionIdleExpiryTask);
      }
      regionIdleExpiryTask =
          (RegionIdleExpiryTask) cache.getExpirationScheduler().addExpiryTask(task);
    }
  }

  boolean isEntryIdleExpiryPossible() {
    return entryIdleTimeout > 0 || customEntryIdleTimeout != null;
  }

  private void cancelTTLExpiryTask() {
    RegionTTLExpiryTask task;
    synchronized (regionExpiryLock) {
      task = regionTTLExpiryTask;
      if (task != null) {
        regionTTLExpiryTask = null;
      }
    }
    if (task != null) {
      task.cancel();
    }
  }

  private void cancelIdleExpiryTask() {
    RegionIdleExpiryTask task;
    synchronized (regionExpiryLock) {
      task = regionIdleExpiryTask;
      if (task != null) {
        regionIdleExpiryTask = null;
      }
    }
    if (task != null) {
      task.cancel();
    }
  }

  @Override
  void regionTimeToLiveChanged(ExpirationAttributes oldTimeToLive) {
    addTTLExpiryTask();
  }

  @Override
  void regionIdleTimeoutChanged(ExpirationAttributes oldIdleTimeout) {
    addIdleExpiryTask();
  }

  @Override
  void timeToLiveChanged(ExpirationAttributes oldTimeToLive) {
    int oldTimeout = oldTimeToLive.getTimeout();
    if (customEntryTimeToLive != null) {
      rescheduleEntryExpiryTasks();
    }
    if (entryTimeToLive > 0 && (oldTimeout == 0 || entryTimeToLive < oldTimeout)) {
      rescheduleEntryExpiryTasks();
    }
    // else it's safe to let them get rescheduled lazily, as the old expiration time will cause the
    // tasks to fire sooner than the new ones.
  }

  @Override
  void idleTimeoutChanged(ExpirationAttributes oldIdleTimeout) {
    int oldTimeout = oldIdleTimeout.getTimeout();
    if (customEntryIdleTimeout != null) {
      rescheduleEntryExpiryTasks();
    }
    if (entryIdleTimeout > 0 && (oldTimeout == 0 || entryIdleTimeout < oldTimeout)) {
      rescheduleEntryExpiryTasks();
    }
    // else it's safe to let them get rescheduled lazily, as the old expiration time will cause the
    // tasks to fire sooner than the new ones.
  }

  void rescheduleEntryExpiryTasks() {
    if (isProxy()) {
      return;
    }
    if (!isInitialized()) {
      // don't schedule expiration until region is initialized
      return;
    }
    if (!isEntryExpiryPossible()) {
      return;
    }
    // OK to ignore transaction since Expiry only done non-tran
    Iterator<RegionEntry> it = entries.regionEntries().iterator();
    if (it.hasNext()) {
      ExpiryTask.doWithNowSet(this, () -> {
        while (it.hasNext()) {
          addExpiryTask(it.next());
        }
      });
    }
  }

  @Override
  public void addExpiryTaskIfAbsent(RegionEntry entry) {
    addExpiryTask(entry, true);
  }

  void addExpiryTask(RegionEntry re) {
    addExpiryTask(re, false);
  }

  /**
   * If custom expiration returns non-null expiration attributes then create a CustomEntryExpiryTask
   * for this region and the given entry and return it. Otherwise if the region is configured for
   * expiration then create an EntryExpiryTask for this region and the given entry and return it.
   * Null is returned if the expiration attributes indicate that expiration is disabled.
   */
  private EntryExpiryTask createExpiryTask(RegionEntry regionEntry) {
    if (regionEntry == null || regionEntry.isDestroyedOrRemoved()) {
      return null;
    }
    if (customEntryIdleTimeout != null || customEntryTimeToLive != null) {
      ExpiryRegionEntry expiryRegionEntry = new ExpiryRegionEntry(this, regionEntry);
      ExpirationAttributes ttlAttributes = null;
      final RegionAttributes<?, ?> regionAttributes = getAttributes();

      final CustomExpiry<?, ?> customTTL = regionAttributes.getCustomEntryTimeToLive();
      if (customTTL != null) {
        try {
          ttlAttributes = customTTL.getExpiry(expiryRegionEntry);
          if (ttlAttributes != null) {
            checkEntryTimeoutAction("timeToLive", ttlAttributes.getAction());
          }
        } catch (RegionDestroyedException ignore) {
          // Ignore
        } catch (EntryNotFoundException | EntryDestroyedException ignore) {
          // Ignore
        } catch (Exception e) {
          logger.fatal(String.format("Error calculating expiration %s", e.getMessage()),
              e);
        }
      }
      if (ttlAttributes == null) {
        ttlAttributes = regionAttributes.getEntryTimeToLive();
      }

      CustomExpiry<?, ?> customIdle = regionAttributes.getCustomEntryIdleTimeout();
      ExpirationAttributes idleAttributes = null;
      if (customIdle != null) {
        try {
          idleAttributes = customIdle.getExpiry(expiryRegionEntry);
          if (idleAttributes != null) {
            checkEntryTimeoutAction("idleTimeout", idleAttributes.getAction());
          }
        } catch (RegionDestroyedException ignore) {
          // Ignore
        } catch (EntryNotFoundException | EntryDestroyedException ignore) {
          // Ignore
        } catch (Exception e) {
          logger.fatal(String.format("Error calculating expiration %s", e.getMessage()),
              e);
        }
      }
      if (idleAttributes == null) {
        idleAttributes = regionAttributes.getEntryIdleTimeout();
      }

      final boolean ttlDisabled = ttlAttributes == null || ttlAttributes.getTimeout() == 0;
      final boolean idleDisabled = idleAttributes == null || idleAttributes.getTimeout() == 0;

      if (ttlDisabled && idleDisabled) {
        return null;
      }
      if ((ttlDisabled || ttlAttributes.equals(regionAttributes.getEntryTimeToLive()))
          && (idleDisabled || idleAttributes.equals(regionAttributes.getEntryIdleTimeout()))) {
        // no need for custom since we can just use the region's expiration attributes.
        return new EntryExpiryTask(this, regionEntry);
      }
      return new CustomEntryExpiryTask(this, regionEntry, ttlAttributes, idleAttributes);

    }
    if (isEntryExpiryPossible()) {
      return new EntryExpiryTask(this, regionEntry);
    }
    return null;
  }

  @Override
  public EntryExpiryTask getEntryExpiryTask(Object key) {
    RegionEntry re = getRegionEntry(key);
    if (re == null) {
      throw new EntryNotFoundException("Entry for key " + key + " does not exist.");
    }
    return entryExpiryTasks.get(re);
  }

  /**
   * Used by unit tests to get access to the RegionIdleExpiryTask of this region. Returns null if no
   * task exists.
   */
  @Override
  public RegionIdleExpiryTask getRegionIdleExpiryTask() {
    return regionIdleExpiryTask;
  }

  /**
   * Used by unit tests to get access to the RegionTTLExpiryTask of this region. Returns null if no
   * task exists.
   */
  @Override
  public RegionTTLExpiryTask getRegionTTLExpiryTask() {
    return regionTTLExpiryTask;
  }

  private void addExpiryTask(RegionEntry regionEntry, boolean ifAbsent) {
    if (isProxy()) {
      return;
    }
    if (!isInitialized()) {
      // don't schedule expiration until region is initialized
      return;
    }
    if (isEntryExpiryPossible()) {
      EntryExpiryTask newTask = null;
      EntryExpiryTask oldTask;
      if (ifAbsent) {
        oldTask = entryExpiryTasks.get(regionEntry);
        if (oldTask != null) {
          boolean keepOldTask = true;
          if (customEntryIdleTimeout != null || customEntryTimeToLive != null) {
            newTask = createExpiryTask(regionEntry);
            if (newTask == null) {
              return;
            }
            // see if the new tasks expiration would be earlier than the scheduled task.
            long newTaskTime = newTask.getExpirationTime();
            try {
              if (newTaskTime != 0 && newTaskTime < oldTask.getExpirationTime()) {
                // it is so get rid of the old task and schedule the new one.
                keepOldTask = false;
              }
            } catch (EntryNotFoundException ignore) {
              keepOldTask = false;
            }
          }
          if (keepOldTask) {
            // if an oldTask is present leave it be
            if (logger.isTraceEnabled()) {
              logger.trace("Expiry Task not added because one already present. Key={}",
                  regionEntry.getKey());
            }
            return;
          }
        }
      }
      if (newTask == null) {
        newTask = createExpiryTask(regionEntry);
        if (newTask == null) {
          return;
        }
      }
      oldTask = entryExpiryTasks.put(regionEntry, newTask);
      ExpirationScheduler scheduler = cache.getExpirationScheduler();
      if (oldTask != null) {
        if (oldTask.cancel()) {
          scheduler.incCancels();
        }
      }
      if (!scheduler.addEntryExpiryTask(newTask)) {
        entryExpiryTasks.remove(regionEntry);
      } else {
        if (ExpiryTask.expiryTaskListener != null) {
          ExpiryTask.expiryTaskListener.afterSchedule(newTask);
        }
      }
    } else {
      if (logger.isTraceEnabled()) {
        logger.trace("addExpiryTask(key) ignored");
      }
    }
  }

  @Override
  public void cancelExpiryTask(RegionEntry regionEntry) {
    cancelExpiryTask(regionEntry, null);
  }

  void cancelExpiryTask(RegionEntry regionEntry, ExpiryTask expiryTask) {
    if (expiryTask != null) {
      entryExpiryTasks.remove(regionEntry, expiryTask);
      if (expiryTask.cancel()) {
        cache.getExpirationScheduler().incCancels();
      }
    } else {
      EntryExpiryTask oldTask = entryExpiryTasks.remove(regionEntry);
      if (oldTask != null) {
        if (oldTask.cancel()) {
          cache.getExpirationScheduler().incCancels();
        }
      }
    }
  }

  private void cancelAllEntryExpiryTasks() {
    // This method gets called during LocalRegion construction
    // in which case the final entryExpiryTasks field can still be null
    if (entryExpiryTasks.isEmpty()) {
      return;
    }
    boolean doPurge = false;
    Iterator<EntryExpiryTask> iterator = entryExpiryTasks.values().iterator();
    while (iterator.hasNext()) {
      EntryExpiryTask task = iterator.next();
      iterator.remove();
      // no need to call incCancels since we will call forcePurge
      task.cancel();
      doPurge = true;
    }
    if (doPurge) {
      // do a force to not leave any refs to this region
      cache.getExpirationScheduler().forcePurge();
    }
  }

  /**
   * get the ImageState for this region
   */
  @Override
  public ImageState getImageState() {
    return imageState;
  }

  /**
   * Callers of this method should always follow the call with: if (lockGII()) { try { } finally {
   * unlockGII(); } }
   *
   * @return true if lock obtained and unlock needs to be called
   */
  @Override
  public boolean lockGII() {
    ImageState imageState = getImageState();
    if (imageState.isReplicate() && !isInitialized()) {
      imageState.lockGII();
      // recheck initialized while holding lock
      if (isInitialized()) {
        // we didn't need to lock after all so clear and return false
        imageState.unlockGII();
      } else {
        return true;
      }
    }
    return false;
  }

  @Override
  public void unlockGII() {
    ImageState imageState = getImageState();
    assert imageState.isReplicate();
    imageState.unlockGII();
  }

  /**
   * Callers of this method should always follow the call with: if (lockRIReadLock()) { try { }
   * finally { unlockRIReadLock(); } }
   *
   * @return true if lock obtained and unlock needs to be called
   */
  private boolean lockRIReadLock() {
    if (getImageState().isClient()) {
      getImageState().readLockRI();
      return true;
    }
    return false;
  }

  private void unlockRIReadLock() {
    assert getImageState().isClient();
    getImageState().readUnlockRI();
  }

  /**
   * doesn't throw RegionDestroyedException, used by CacheDistributionAdvisor
   */
  LocalRegion basicGetParentRegion() {
    return parentRegion;
  }

  @Override
  public Object basicGetEntryUserAttribute(Object entryKey) {
    return entryUserAttributes.get(entryKey);
  }

  @VisibleForTesting
  public TXStateProxy getTXState() {
    if (supportsTX) {
      return TXManagerImpl.getCurrentTXState();
    }
    return null;
  }

  @Override
  public TXId getTXId() {
    final TXStateInterface tx = getTXState();
    if (tx == null) {
      return null;
    }
    return (TXId) tx.getTransactionId();
  }

  private TXRegionState txReadRegion() {
    final TXStateInterface txState = getTXState();
    if (txState != null) {
      return txState.txReadRegion(this);
    }
    return null;
  }

  @Override
  public TXEntryState createReadEntry(TXRegionState txRegionState, KeyInfo keyInfo,
      boolean createIfAbsent) {
    TXEntryState result = null;
    final RegionEntry regionEntry = basicGetTXEntry(keyInfo);
    if (regionEntry != null) {
      boolean needsLRUCleanup = false;
      try {
        synchronized (regionEntry) {
          if (!regionEntry.isRemoved()) {
            Object value = regionEntry.getValueInVM(this);
            if (value == Token.NOT_AVAILABLE || regionEntry.isEvicted()) {
              // Entry value is on disk
              // Handle the case where we fault in a evicted disk entry
              needsLRUCleanup = txLRUStart();
              // Fault in the value from disk
              value = regionEntry.getValue(this);
            }

            /*
             * The tx will need the raw value for identity comparison. Please see
             * TXEntryState#checkForConflict(LocalRegion,Object)
             */
            Object id = regionEntry.getTransformedValue();

            result = txRegionState.createReadEntry(this, keyInfo.getKey(), regionEntry, id, value);
          }
        }
      } catch (DiskAccessException dae) {
        handleDiskAccessException(dae);
        needsLRUCleanup = false;
        throw dae;
      } finally {
        if (needsLRUCleanup) {
          // do this after releasing sync
          txLRUEnd();
        }
      }
    }
    if (result == null && createIfAbsent) {
      result = txRegionState.createReadEntry(this, keyInfo.getKey(), null, null, null);
    }
    return result;
  }

  private TXStateInterface getJTAEnlistedTX() {
    if (ignoreJTA) {
      return null;
    }
    TXStateInterface txState = getTXState();
    if (txState != null) {
      return txState;
    }
    try {
      if (!ignoreJTA && cache.getJTATransactionManager() != null) {

        Transaction jtaTransaction = cache.getJTATransactionManager().getTransaction();
        if (jtaTransaction == null
            || jtaTransaction.getStatus() == Status.STATUS_NO_TRANSACTION) {
          return null;
        }
        if (isTransactionPaused() || isJTAPaused()) {
          // Do not bootstrap JTA again, if the transaction has been paused.
          return null;
        }
        txState = cache.getTXMgr().beginJTA();
        jtaTransaction.registerSynchronization(txState);
        return txState;
      }
      return null;
    } catch (SystemException se) {
      // this can be thrown when the system is shutting down
      stopper.checkCancelInProgress(se);
      jtaEnlistmentFailureCleanup(txState, se);
      return null;
    } catch (RollbackException | IllegalStateException re) {
      jtaEnlistmentFailureCleanup(txState, re);
      return null;
    }
  }

  private void jtaEnlistmentFailureCleanup(TXStateInterface txState, Exception reason) {
    if (cache == null) {
      return;
    }

    cache.getTXMgr().setTXState(null);
    if (txState != null) {
      txState.rollback();
    }

    String jtaTransName = null;
    try {
      jtaTransName = cache.getJTATransactionManager().getTransaction().toString();
    } catch (VirtualMachineError err) {
      SystemFailure.initiateFailure(err);
      // If this ever returns, rethrow the error. We're poisoned
      // now, so don't let this thread continue.
      throw err;
    } catch (Throwable ignore) {
      // Whenever you catch Error or Throwable, you must also
      // catch VirtualMachineError (see above). However, there is
      // _still_ a possibility that you are dealing with a cascading
      // error condition, so you also need to check to see if the JVM
      // is still usable:
      SystemFailure.checkFailure();
    }

    throw new FailedSynchronizationException(
        String.format("Failed enlistment with transaction %s",
            jtaTransName),
        reason);
  }

  @Override
  public boolean txLRUStart() {
    return entries.disableLruUpdateCallback();
  }

  @Override
  public void txLRUEnd() {
    entries.enableLruUpdateCallback();
    try {
      entries.lruUpdateCallback();
    } catch (DiskAccessException dae) {
      handleDiskAccessException(dae);
      throw dae;
    }
  }

  @Override
  public void txDecRefCount(RegionEntry regionEntry) {
    entries.decTxRefCount(regionEntry);
  }

  /**
   * Does not throw RegionDestroyedException even if destroyed
   */
  List debugGetSubregionNames() {
    List names = new ArrayList(subregions.keySet());
    return names;
  }

  @Override
  public void incRecentlyUsed() {
    // nothing
    entries.incRecentlyUsed();
  }

  private static void dispatchEvent(LocalRegion region, InternalCacheEvent event,
      EnumListenerEvent operation) {

    CacheListener[] listeners = region.fetchCacheListenersField();
    if (event.getOperation().isCreate()) {
      if (logger.isDebugEnabled()) {
        logger.debug("invoking listeners: {}", Arrays.toString(listeners));
      }
    }
    if (listeners == null || listeners.length == 0) {
      return;
    }
    if (operation != EnumListenerEvent.AFTER_REGION_CREATE) {
      try {
        region.waitForRegionCreateEvent();
      } catch (CancelException ignore) {
        // ignore and keep going
        if (logger.isTraceEnabled()) {
          logger.trace("Dispatching events after cache closure for region {}",
              region.getFullPath());
        }
      }
    }

    if (!event.isGenerateCallbacks()) {
      return;
    }

    for (CacheListener listener : listeners) {
      if (listener != null) {
        try {
          operation.dispatchEvent(event, listener);
        } catch (CancelException ignore) {
          // ignore
        } catch (VirtualMachineError err) {
          SystemFailure.initiateFailure(err);
          // If this ever returns, rethrow the error. We're poisoned
          // now, so don't let this thread continue.
          throw err;
        } catch (Throwable t) {
          // Whenever you catch Error or Throwable, you must also
          // catch VirtualMachineError (see above). However, there is
          // _still_ a possibility that you are dealing with a cascading
          // error condition, so you also need to check to see if the JVM
          // is still usable:
          SystemFailure.checkFailure();
          logger.error("Exception occurred in CacheListener", t);
        }
      }
    }
  }

  /**
   * For internal use only.
   */
  @Override
  public RegionMap getRegionMap() {
    // OK to ignore tx state
    return entries;
  }

  /**
   * (description copied from entryCount() Returns the number of entries in this region. Note that
   * because of the concurrency properties of the {@link RegionMap}, the number of entries is only
   * an approximate. That is, other threads may change the number of entries in this region while
   * this method is being invoked.
   *
   * @see LocalRegion#entryCount()
   */
  @Override
  public int size() {
    checkReadiness();
    checkForNoAccess();
    discoverJTA();
    boolean isClient = imageState.isClient();
    if (isClient) {
      lockRIReadLock();
    }
    try {
      return entryCount();
    } finally {
      if (isClient) {
        unlockRIReadLock();
      }
    }
  }

  @Override
  public int getLocalSize() {
    return getRegionMap().size() - tombstoneCount.get();
  }

  /**
   * returns an estimate of the number of entries in this region. This method should be preferred
   * over size() for hdfs regions where an accurate size is not needed. This method is not supported
   * on a client
   *
   * @return the estimated size of this region
   */
  int sizeEstimate() {
    boolean isClient = imageState.isClient();
    if (isClient) {
      throw new UnsupportedOperationException("Method not supported on a client");
    }
    return entryCount(null, true);
  }

  /**
   * This method returns true if Region is Empty.
   */
  @Override
  public boolean isEmpty() {
    // checkForNoAccess(); // size does this check
    return size() <= 0;
  }

  /**
   * Returns true if the value is present in the Map
   */
  @Override
  public boolean containsValue(final Object value) {
    if (value == null) {
      throw new NullPointerException(
          "Value for containsValue(value) cannot be null");
    }
    checkReadiness();
    checkForNoAccess();
    boolean result = false;
    for (Object entry : new EntriesSet(this, false, IteratorType.VALUES, false)) {
      if (entry != null) {
        if (value.equals(entry)) {
          result = true;
          break;
        }
      }
    }
    return result;
  }

  /**
   * Returns a set of the entries present in the Map. This set is Not Modifiable. If changes are
   * made to this set, they will be not reflected in the map
   */
  @Override
  public Set entrySet() {
    // entries(false) takes care of open transactions
    return entrySet(false);
  }

  /**
   * Returns a set of the keys present in the Map. This set is Not Modifiable. If changes are made
   * to this set, they will be not reflected in the map
   */
  @Override
  public Set keySet() {
    // keys() takes care of open transactions
    return keys();
  }

  /**
   * removes the object from the Map and returns the object removed. The object is returned only if
   * present in the localMap. If the value is present in another Node, null is returned
   */
  @Override
  public Object remove(Object key) {
    // no validations needed here since destroy does it for us
    Object value = null;
    try {
      value = destroy(key);
    } catch (EntryNotFoundException ignore) {
      // No need to log this exception; caller can test for null;
    }
    return value;
  }

  // TODO: fromClient is always true
  public void basicBridgeDestroyRegion(Object callbackArg, final ClientProxyMembershipID client,
      boolean fromClient, EventID eventId)
      throws TimeoutException, EntryExistsException, CacheWriterException {

    RegionEventImpl event = new ClientRegionEventImpl(this, Operation.REGION_DESTROY, callbackArg,
        false, client.getDistributedMember(), client, eventId);

    basicDestroyRegion(event, true);
  }

  public void basicBridgeClear(Object callbackArg, final ClientProxyMembershipID client,
      boolean fromClient, EventID eventId)
      throws TimeoutException, EntryExistsException, CacheWriterException {

    RegionEventImpl event = new ClientRegionEventImpl(this, Operation.REGION_CLEAR, callbackArg,
        false, client.getDistributedMember(), client, eventId);

    basicClear(event, true);
  }

  @Override
  void basicClear(RegionEventImpl regionEvent) {
    getDataView().checkSupportsRegionClear();
    basicClear(regionEvent, true);
  }

  void basicClear(RegionEventImpl regionEvent, boolean cacheWrite) {
    cmnClearRegion(regionEvent, cacheWrite, true);
  }

  // TODO: what does cmn refer to?
  void cmnClearRegion(RegionEventImpl regionEvent, boolean cacheWrite, boolean useRVV) {
    RegionVersionVector rvv = null;
    if (useRVV && getDataPolicy().withReplication() && getConcurrencyChecksEnabled()) {
      rvv = versionVector.getCloneForTransmission();
    }
    clearRegionLocally(regionEvent, cacheWrite, rvv);
  }

  /**
   * Common code used by both clear and localClear. On the lines of destroyRegion, this method will
   * be invoked for clearing the local cache.The cmnClearRegion will be overridden in the derived
   * class DistributedRegion too. For clear operation , no CacheWriter will be invoked . It will
   * only have afterClear callback. Also like destroyRegion & invalidateRegion , the clear operation
   * will not take distributedLock. The clear operation will also clear the local transactional
   * entries. The clear operation will have immediate committed state.
   */
  void clearRegionLocally(RegionEventImpl regionEvent, boolean cacheWrite,
      RegionVersionVector vector) {
    final boolean isRvvDebugEnabled = logger.isTraceEnabled(LogMarker.RVV_VERBOSE);

    RegionVersionVector rvv = vector;
    if (serverRegionProxy != null) {
      // clients and local regions do not maintain a full RVV. can't use it with clear()
      rvv = null;
    }
    if (rvv != null && getDataPolicy().withStorage()) {
      if (isRvvDebugEnabled) {
        logger.trace(LogMarker.RVV_VERBOSE,
            "waiting for my version vector to dominate{}mine={}{} other={}", getLineSeparator(),
            getLineSeparator(), versionVector.fullToString(), rvv);
      }
      boolean result = versionVector.waitToDominate(rvv, this);
      if (!result) {
        if (isRvvDebugEnabled) {
          logger.trace(LogMarker.RVV_VERBOSE, "incrementing clearTimeouts for {} rvv={}", getName(),
              versionVector.fullToString());
        }
        getCachePerfStats().incClearTimeouts();
      }
    }

    // If the initial image operation is still in progress then we need will have to do the clear
    // operation at the end of the GII.For this we try to acquire the lock of GII the boolean
    // returned is true that means lock was obtained which also means that GII is still in progress.
    boolean isGIIinProgress = lockGII();
    if (isGIIinProgress) {
      // Set a flag which will indicate that the Clear was invoked.
      // Also we should try & abort the GII
      try {
        getImageState().setClearRegionFlag(true /* Clear region */, rvv);
      } finally {
        unlockGII();
      }
    }

    if (cacheWrite && !isGIIinProgress) {
      cacheWriteBeforeRegionClear(regionEvent);
    }

    RegionVersionVector myVector = getVersionVector();
    if (myVector != null) {
      if (isRvvDebugEnabled) {
        logger.trace(LogMarker.RVV_VERBOSE, "processing version information for {}", regionEvent);
      }
      if (!regionEvent.isOriginRemote() && !regionEvent.getOperation().isLocal()) {
        // generate a new version for the operation
        VersionTag tag = VersionTag.create(getVersionMember());
        tag.setVersionTimeStamp(cacheTimeMillis());
        tag.setRegionVersion(myVector.getNextVersionWhileLocked());
        if (isRvvDebugEnabled) {
          logger.trace(LogMarker.RVV_VERBOSE, "generated version tag for clear: {}", tag);
        }
        regionEvent.setVersionTag(tag);
      } else {
        VersionTag tag = regionEvent.getVersionTag();
        if (tag != null) {
          if (isRvvDebugEnabled) {
            logger.trace(LogMarker.RVV_VERBOSE, "recording version tag for clear: {}", tag);
          }
          // clear() events always have the ID in the tag
          myVector.recordVersion(tag.getMemberID(), tag);
        }
      }
    }

    // Clear the expiration task for all the entries. It is possible that
    // after clearing it some new entries may get added before issuing clear
    // on the map , but that should be OK, as the expiration thread will
    // silently move ahead if the entry to be expired no longer existed
    cancelAllEntryExpiryTasks();
    entryUserAttributes.clear();

    // if all current content has been removed then the version vector
    // does not need to retain any exceptions and the GC versions can
    // be set to the current vector versions
    if (rvv == null && myVector != null) {
      myVector.removeOldVersions();
    }

    /*
     * First we need to clear the TX state for the current region for the thread. The operation will
     * not take global lock similar to regionInvalidator regionDestroy behaviour.
     */

    // clear the disk region if present
    if (diskRegion != null) {
      // persist current rvv and rvvgc which contained version for clear() itself
      if (getDataPolicy().withPersistence()) {
        // null means not to change dr.rvvTrust
        if (isRvvDebugEnabled) {
          logger.trace(LogMarker.RVV_VERBOSE, "Clear: Saved current rvv: {}",
              diskRegion.getRegionVersionVector());
        }
        diskRegion.writeRVV(this, null);
        diskRegion.writeRVVGC(this);
      }

      // clear the entries in disk
      diskRegion.clear(this, rvv);
    }
    // this will be done in diskRegion.clear if it is not null else it has to be
    // done here
    else {
      // Now remove the tx entries for this region
      txClearRegion();
      // Now clear the map of committed entries
      Set<VersionSource> remainingIDs = clearEntries(rvv);
      if (!getDataPolicy().withPersistence()) {
        // persistent regions do not reap IDs
        if (myVector != null) {
          myVector.removeOldMembers(remainingIDs);
        }
      }
    }

    if (!isProxy()) {
      // Now we need to recreate all the indexes.
      // If the indexManager is null we don't have to worry
      // for any other thread creating index at that instant
      // because the region has already been cleared
      // of entries.

      // TODO made indexManager variable is made volatile. Is it necessary?
      if (indexManager != null) {
        try {
          indexManager.rerunIndexCreationQuery();
        } catch (QueryException qe) {
          // Create an anonymous inner class of CacheRuntimeException so
          // that a RuntimeException is thrown
          // TODO: never throw an anonymous class (and outer-class is not serializable)
          throw new CacheRuntimeException(
              "Exception occurred while re creating index data on cleared region.",
              qe) {
            private static final long serialVersionUID = 0L;
          };
        }
      }
    }

    if (ISSUE_CALLBACKS_TO_CACHE_OBSERVER) {
      CacheObserverHolder.getInstance().afterRegionClear(regionEvent);
    }

    if (isGIIinProgress) {
      return;
    }
    regionEvent.setEventType(EnumListenerEvent.AFTER_REGION_CLEAR);

    // Issue a callback to afterClear if the region is initialized
    boolean hasListener = hasListener();
    if (hasListener) {
      dispatchListenerEvent(EnumListenerEvent.AFTER_REGION_CLEAR, regionEvent);
    }
  }

  @Override
  void basicLocalClear(RegionEventImpl rEvent) {
    getDataView().checkSupportsRegionClear();
    cmnClearRegion(rEvent, false/* cacheWrite */, false/* useRVV */);
  }

  public void handleInterestEvent(InterestRegistrationEvent event) {
    throw new UnsupportedOperationException(
        "Region interest registration is only supported for PartitionedRegions");
  }

  // TODO: refactor basicGetAll
  @Override
  Map basicGetAll(Collection keys, Object callback) {
    final boolean isDebugEnabled = logger.isDebugEnabled();
    final boolean isTraceEnabled = logger.isTraceEnabled();

    if (isDebugEnabled) {
      logger.debug("Processing getAll request for: {}", keys);
    }
    discoverJTA();
    Map allResults = new HashMap();
    if (hasServerProxy()) {
      // Some of our implementation expects a list of keys so make sure it is a list
      List keysList;
      if (keys instanceof List) {
        keysList = (List) keys;
      } else {
        keysList = new ArrayList(keys);
      }

      // Gather any local values
      // We only need to do this if this region has local storage
      if (getTXState() == null && hasStorage()) {
        if (keysList == keys) {
          // Create a copy of the collection of keys
          // to keep the original collection intact
          keysList = new ArrayList(keys);
        }
        for (Iterator iterator = keysList.iterator(); iterator.hasNext();) {
          Object value;
          Object key = iterator.next();
          Region.Entry entry = accessEntry(key, true);

          try {
            if (entry != null && (value = entry.getValue()) != null) {
              allResults.put(key, value);
              iterator.remove();
            }
          } catch (EntryDestroyedException ignored) {
            // The entry might have been removed locally between first and second fetch.
            // If that's the case, don't remove the key and try to retrieve the value from server.
          }
        }

        if (isDebugEnabled) {
          logger.debug("Added local results for getAll request: {}", allResults);
        }
      }

      // Send the rest of the keys to the server (if necessary)
      if (!keysList.isEmpty()) {
        VersionedObjectList remoteResults = getServerProxy().getAll(keysList, callback);
        if (isDebugEnabled) {
          logger.debug("remote getAll results are {}", remoteResults);
        }

        // Add remote results to local cache and all results if successful
        for (VersionedObjectList.Iterator it = remoteResults.iterator(); it.hasNext();) {
          VersionedObjectList.Entry entry = it.next();
          Object key = entry.getKey();
          boolean notOnServer = entry.isKeyNotOnServer();
          // in 8.0 we added transfer of tombstones with RI/getAll results
          boolean createTombstone = false;
          if (notOnServer) {
            createTombstone = entry.getVersionTag() != null && getConcurrencyChecksEnabled();
            allResults.put(key, null);
            if (isDebugEnabled) {
              logger.debug("Added remote result for missing key: {}", key);
            }
            if (!createTombstone) {
              continue;
            }
          }

          Object value;
          if (createTombstone) {
            // the value is null in this case, so use TOKEN_TOMBSTONE
            value = Token.TOMBSTONE;
          } else {
            value = entry.getObject();
          }

          if (value instanceof Throwable) {
            continue;
          }

          // The following basicPutEntry needs to be done
          // even if we do not have storage so that the
          // correct events will be delivered to any callbacks we have.
          long startPut = getStatisticsClock().getTime();
          validateKey(key);

          @Released
          EntryEventImpl event = entryEventFactory.create(this, Operation.LOCAL_LOAD_CREATE, key,
              value, callback, false, getMyId(), true);

          try {
            event.setFromServer(true);
            event.setVersionTag(entry.getVersionTag());

            if (!alreadyInvalid(key, event)) {
              // don't update if it's already here & invalid
              TXStateProxy txState = cache.getTXMgr().pauseTransaction();
              try {
                basicPutEntry(event, 0L);
              } catch (ConcurrentCacheModificationException e) {
                if (isDebugEnabled) {
                  logger.debug(
                      "getAll result for {} not stored in cache due to concurrent modification",
                      key, e);
                }
              } finally {
                cache.getTXMgr().unpauseTransaction(txState);
              }
              getCachePerfStats().endPut(startPut, event.isOriginRemote());
            }

            if (!createTombstone) {
              allResults.put(key, value);
              if (isTraceEnabled) {
                logger.trace("Added remote result for getAll request: {}, {}", key, value);
              }
            }
          } finally {
            event.release();
          }
        }
      }

    } else {
      // This implementation for a P2P VM is a stop-gap to provide the
      // functionality. It needs to be rewritten more efficiently.
      for (Object key : keys) {
        try {
          allResults.put(key, get(key, callback));
        } catch (Exception e) {
          logger.warn(String.format("The following exception occurred attempting to get key=%s",
              key),
              e);
        }
      }
    }
    return allResults;
  }

  /**
   * Return false if it will never store entry ekys and values locally; otherwise return true.
   */
  boolean hasStorage() {
    return getDataPolicy().withStorage();
  }

  private void verifyPutAllMap(Map map) {
    Collection theEntries = map.entrySet();
    for (Object theEntry : theEntries) {
      Map.Entry mapEntry = (Map.Entry) theEntry;
      Object key = mapEntry.getKey();
      if (mapEntry.getValue() == null || key == null) {
        throw new NullPointerException("Any key or value in putAll should not be null");
      }
      if (!MemoryThresholds.isLowMemoryExceptionDisabled()) {
        checkIfAboveThreshold(key);
      }
      // Threshold check should not be performed again
    }
  }

  private void verifyRemoveAllKeys(Collection<Object> keys) {
    for (Object key : keys) {
      if (key == null) {
        throw new NullPointerException("Any key in removeAll must not be null");
      }
    }
  }

  /**
   * Called on a cache server when it has a received a putAll command from a client.
   *
   * @param map a map of key->value for the entries we are putting
   * @param retryVersions a map of key->version tag. If any of the entries are the result of a
   *        retried client event, we need to make sure we send the original version tag along with
   *        the event.
   * @param callbackArg callback argument from client
   */
  public VersionedObjectList basicBridgePutAll(Map map, Map<Object, VersionTag> retryVersions,
      ClientProxyMembershipID memberId, EventID eventId, boolean skipCallbacks, Object callbackArg)
      throws TimeoutException, CacheWriterException {

    long startPut = getStatisticsClock().getTime();

    @Released
    final EntryEventImpl event =
        entryEventFactory.create(this, Operation.PUTALL_CREATE, null,
            null, callbackArg, false,
            memberId.getDistributedMember(), !skipCallbacks, eventId);

    try {
      event.setContext(memberId);
      DistributedPutAllOperation putAllOp = new DistributedPutAllOperation(event, map.size(), true);
      try {
        VersionedObjectList result = basicPutAll(map, putAllOp, retryVersions);
        getCachePerfStats().endPutAll(startPut);
        return result;
      } finally {
        putAllOp.freeOffHeapResources();
      }
    } finally {
      event.release();
    }
  }

  /**
   * Called on a cache server when it has a received a removeAll command from a client.
   *
   * @param keys a collection of the keys we are putting
   * @param retryVersions a collection of version tags. If the client is retrying a key then that
   *        keys slot will be non-null in this collection. Note that keys and retryVersions are
   *        parallel lists.
   * @param callbackArg callback argument from client
   */
  public VersionedObjectList basicBridgeRemoveAll(List<Object> keys,
      ArrayList<VersionTag> retryVersions, ClientProxyMembershipID memberId, EventID eventId,
      Object callbackArg) throws TimeoutException, CacheWriterException {

    long startOp = getStatisticsClock().getTime();

    @Released
    final EntryEventImpl event =
        entryEventFactory.create(this, Operation.REMOVEALL_DESTROY, null,
            null, callbackArg, false,
            memberId.getDistributedMember(), true, eventId);

    try {
      event.setContext(memberId);
      DistributedRemoveAllOperation removeAllOp =
          new DistributedRemoveAllOperation(event, keys.size(), true);
      try {
        VersionedObjectList result = basicRemoveAll(keys, removeAllOp, retryVersions);
        getCachePerfStats().endRemoveAll(startOp);
        return result;
      } finally {
        removeAllOp.freeOffHeapResources();
      }
    } finally {
      event.release();
    }
  }

  // TODO: return value is never used
  public VersionedObjectList basicImportPutAll(Map map, boolean skipCallbacks) {
    long startPut = getStatisticsClock().getTime();

    @Released
    EntryEventImpl event = entryEventFactory.create(this, Operation.PUTALL_CREATE, null, null, null,
        true, getMyId(), !skipCallbacks);

    try {
      DistributedPutAllOperation putAllOp =
          new DistributedPutAllOperation(event, map.size(), false);
      try {
        VersionedObjectList result = basicPutAll(map, putAllOp, null);
        getCachePerfStats().endPutAll(startPut);
        return result;
      } finally {
        putAllOp.freeOffHeapResources();
      }
    } finally {
      event.release();
    }
  }

  @Override
  public void putAll(Map map, Object aCallbackArgument) {
    long startPut = getStatisticsClock().getTime();
    final DistributedPutAllOperation putAllOp = newPutAllOperation(map, aCallbackArgument);
    if (putAllOp != null) {
      try {
        basicPutAll(map, putAllOp, null);
      } finally {
        putAllOp.getBaseEvent().release();
        putAllOp.freeOffHeapResources();
      }
    }

    getCachePerfStats().endPutAll(startPut);
  }

  @Override
  public void putAll(Map map) {
    putAll(map, null);
  }

  @Override
  public void removeAll(Collection keys) {
    removeAll(keys, null);
  }

  @Override
  public void removeAll(Collection keys, Object aCallbackArgument) {
    long startOp = getStatisticsClock().getTime();
    DistributedRemoveAllOperation operation = newRemoveAllOperation(keys, aCallbackArgument);
    if (operation != null) {
      try {
        basicRemoveAll(keys, operation, null);
      } finally {
        operation.getBaseEvent().release();
        operation.freeOffHeapResources();
      }
    }
    getCachePerfStats().endRemoveAll(startOp);
  }

  /**
   * Returns true if a one-hop (RemoteOperationMessage) should be used when applying the change to
   * the system.
   */
  boolean requiresOneHopForMissingEntry(EntryEventImpl event) {
    return false;
  }

  // TODO: refactor basicPutAll
  VersionedObjectList basicPutAll(final Map<?, ?> map,
      final DistributedPutAllOperation putAllOp, final Map<Object, VersionTag> retryVersions) {

    final boolean isDebugEnabled = logger.isDebugEnabled();
    final EntryEventImpl event = putAllOp.getBaseEvent();
    EventID eventId = event.getEventId();
    if (eventId == null && generateEventID()) {
      // We need to "reserve" the eventIds for the entries in map here
      event.reserveNewEventId(cache.getDistributedSystem(), map.size());
      eventId = event.getEventId();
    }

    verifyPutAllMap(map);
    VersionedObjectList proxyResult = null;
    boolean partialResult = false;
    RuntimeException runtimeException = null;
    if (hasServerProxy()) {
      // send message to cache server
      if (isTX()) {
        TXStateProxyImpl txState = (TXStateProxyImpl) cache.getTxManager().getTXState();
        txState.getRealDeal(null, this);
      }
      try {
        proxyResult = getServerProxy().putAll(
            uncheckedCast(map),
            eventId,
            !event.isGenerateCallbacks(),
            event.getCallbackArgument());
        if (isDebugEnabled) {
          logger.debug("PutAll received response from server: {}", proxyResult);
        }
      } catch (PutAllPartialResultException e) {
        // adjust the map to only add succeeded entries, then apply the adjustedMap
        proxyResult = e.getSucceededKeysAndVersions();
        partialResult = true;
        if (isDebugEnabled) {
          logger.debug(
              "putAll in client encountered a PutAllPartialResultException:{}{}. Adjusted keys are: {}",
              e.getMessage(), getLineSeparator(), proxyResult.getKeys());
        }
        Throwable txException = e.getFailure();
        while (txException != null) {
          if (txException instanceof TransactionException) {
            runtimeException = (RuntimeException) txException;
            break;
          }
          txException = txException.getCause();
        }
        if (runtimeException == null) {
          // for cache close
          runtimeException = getCancelCriterion().generateCancelledException(e.getFailure());
          if (runtimeException == null) {
            runtimeException = new ServerOperationException(
                String.format("Region %s putAll at server applied partial keys due to exception.",
                    getFullPath()),
                e.getFailure());
          }
        }
      }
    }

    final VersionedObjectList succeeded =
        new VersionedObjectList(map.size(), true, getConcurrencyChecksEnabled());

    // if this is a transactional putAll, we will not have version information as it is only
    // generated at commit
    // so treat transactional putAll as if the server is not versioned
    final boolean serverIsVersioned = proxyResult != null && proxyResult.regionIsVersioned()
        && !isTX() && getDataPolicy() != DataPolicy.EMPTY;
    if (!serverIsVersioned && !partialResult) {
      // we don't need server information if it isn't versioned or if the region is empty
      proxyResult = null;
    }

    lockRVVForBulkOp();
    try {
      try {
        int size = proxyResult == null ? map.size() : proxyResult.size();

        if (isDebugEnabled) {
          logger.debug("size of put result is {} maps is {} proxyResult is {}", size, map,
              proxyResult);
        }

        final PutAllPartialResult partialKeys = new PutAllPartialResult(size);
        final Iterator iterator;
        final boolean isVersionedResults;
        if (proxyResult != null) {
          iterator = proxyResult.iterator();
          isVersionedResults = true;
        } else {
          iterator = map.entrySet().iterator();
          isVersionedResults = false;
        }

        // TODO: refactor this mess
        Runnable task = () -> {
          int offset = 0;
          VersionTagHolder tagHolder = new VersionTagHolder();
          while (iterator.hasNext()) {
            stopper.checkCancelInProgress(null);
            Map.Entry mapEntry = (Map.Entry) iterator.next();
            Object key = mapEntry.getKey();
            tagHolder.setVersionTag(null);
            final Object value;
            boolean overwritten = false;
            VersionTag versionTag = null;
            if (isVersionedResults) {
              versionTag = ((VersionedObjectList.Entry) mapEntry).getVersionTag();
              value = map.get(key);
              if (isDebugEnabled) {
                logger.debug("putAll key {} -> {} version={}", key, value, versionTag);
              }
              if (versionTag == null && serverIsVersioned && getConcurrencyChecksEnabled()
                  && getDataPolicy().withStorage()) {
                // server was unable to determine the version for this operation.
                // I'm not sure this can still happen as described below on a pr.
                // But it can happen on the server if NORMAL or PRELOADED.
                // This can happen in a PR with redundancy if there is a bucket
                // failure or migration during the operation. We destroy the
                // entry since we don't know what its state should be (but the server should)
                if (isDebugEnabled) {
                  logger.debug("server returned no version information for {}", key);
                }
                localDestroyNoCallbacks(key);
                // to be consistent we need to fetch the current entry
                get(key, event.getCallbackArgument(), false, null);
                overwritten = true;
              }
            } else {
              value = mapEntry.getValue();
              if (isDebugEnabled) {
                logger.debug("putAll {} -> {}", key, value);
              }
            }
            try {
              if (serverIsVersioned) {
                if (isDebugEnabled) {
                  logger.debug("associating version tag with {} version={}", key, versionTag);
                }
                // If we have received a version tag from a server, add it to the event
                tagHolder.setVersionTag(versionTag);
                tagHolder.setFromServer(true);
              } else if (retryVersions != null && retryVersions.containsKey(key)) {
                // If this is a retried event, and we have a version tag for the retry,
                // add it to the event.
                tagHolder.setVersionTag(retryVersions.get(key));
              }

              if (!overwritten) {
                basicEntryPutAll(key, value, putAllOp, offset, tagHolder);
              }
              // now we must check again since the cache may have closed during
              // distribution (causing this process to not receive and queue the
              // event for clients
              stopper.checkCancelInProgress(null);
              succeeded.addKeyAndVersion(key, tagHolder.getVersionTag());
            } catch (Exception ex) {
              if (isDebugEnabled) {
                logger.debug("PutAll operation encountered exception for key {}", key, ex);
              }
              partialKeys.saveFailedKey(key, ex);
            }
            offset++;
          }
        };

        syncBulkOp(task, eventId);
        if (partialKeys.hasFailure()) {
          // Now succeeded contains an order key list, may be missing the version tags.
          // Save reference of succeeded into partialKeys. The succeeded may be modified by
          // postPutAll() to fill in the version tags.
          partialKeys.setSucceededKeysAndVersions(succeeded);
          logger
              .info("Region {} putAll: {}",
                  new Object[] {getFullPath(), partialKeys});
          if (isDebugEnabled) {
            logger.debug(partialKeys.detailString());
          }
          if (runtimeException == null) {
            // if received exception from server first, ignore local exception
            if (putAllOp.isBridgeOperation()) {
              if (partialKeys.getFailure() instanceof CancelException) {
                runtimeException = (RuntimeException) partialKeys.getFailure();
              } else if (partialKeys.getFailure() instanceof LowMemoryException) {
                throw partialKeys.getFailure();
              } else {
                runtimeException = new PutAllPartialResultException(partialKeys);
                if (isDebugEnabled) {
                  logger.debug("basicPutAll:" + partialKeys.detailString());
                }
              }
            } else {
              throw partialKeys.getFailure();
            }
          }
        }
      } catch (LowMemoryException lme) {
        throw lme;
      } catch (RuntimeException ex) {
        runtimeException = ex;
      } catch (Exception ex) {
        runtimeException = new RuntimeException(ex);
      } finally {
        putAllOp.getBaseEvent().release();
        putAllOp.freeOffHeapResources();
      }
      getDataView().postPutAll(putAllOp, succeeded, this);
    } finally {
      unlockRVVForBulkOp();
    }
    if (runtimeException != null) {
      throw runtimeException;
    }
    return succeeded;
  }

  @Override
  public VersionedObjectList basicRemoveAll(final Collection<Object> keys,
      final DistributedRemoveAllOperation removeAllOp, final List<VersionTag> retryVersions) {

    final boolean isDebugEnabled = logger.isDebugEnabled();
    final boolean isTraceEnabled = logger.isTraceEnabled();

    final EntryEventImpl event = removeAllOp.getBaseEvent();
    EventID eventId = event.getEventId();
    if (eventId == null && generateEventID()) {
      // We need to "reserve" the eventIds for the entries in map here
      event.reserveNewEventId(cache.getDistributedSystem(), keys.size());
      eventId = event.getEventId();
    }

    verifyRemoveAllKeys(keys);
    VersionedObjectList proxyResult = null;
    boolean partialResult = false;
    RuntimeException runtimeException = null;

    if (hasServerProxy()) {
      // send message to cache server
      if (isTX()) {
        TXStateProxyImpl txState = (TXStateProxyImpl) cache.getTxManager().getTXState();
        txState.getRealDeal(null, this);
      }
      try {
        proxyResult = getServerProxy().removeAll(keys, eventId, event.getCallbackArgument());
        if (isDebugEnabled) {
          logger.debug("removeAll received response from server: {}", proxyResult);
        }
      } catch (PutAllPartialResultException e) {
        // adjust the map to only add succeeded entries, then apply the adjustedMap
        proxyResult = e.getSucceededKeysAndVersions();
        partialResult = true;
        if (isDebugEnabled) {
          logger.debug(
              "removeAll in client encountered a BulkOpPartialResultException: {}{}. Adjusted keys are: {}",
              e.getMessage(), getLineSeparator(), proxyResult.getKeys());
        }
        Throwable txException = e.getFailure();
        while (txException != null) {
          if (txException instanceof TransactionException) {
            runtimeException = (RuntimeException) txException;
            break;
          }
          txException = txException.getCause();
        }
        if (runtimeException == null) {
          runtimeException = getCancelCriterion().generateCancelledException(e.getFailure());
          if (runtimeException == null) {
            runtimeException = new ServerOperationException(
                String.format(
                    "Region %s removeAll at server applied partial keys due to exception.",
                    getFullPath()),
                e.getFailure());
          }
        }
      }
    }

    final VersionedObjectList succeeded =
        new VersionedObjectList(keys.size(), true, getConcurrencyChecksEnabled());

    // If this is a transactional removeAll, we will not have version information as it is only
    // generated at commit
    // so treat transactional removeAll as if the server is not versioned.
    // If we have no storage then act as if the server is not versioned.
    final boolean serverIsVersioned = proxyResult != null && proxyResult.regionIsVersioned()
        && !isTX() && getDataPolicy().withStorage();
    if (!serverIsVersioned && !partialResult) {
      // since the server is not versioned and we do not have a partial result
      // get rid of the proxyResult info returned by the server.
      proxyResult = null;
    }

    lockRVVForBulkOp();
    try {
      try {
        int size = proxyResult == null ? keys.size() : proxyResult.size();

        if (isInternalRegion()) {
          if (isTraceEnabled) {
            logger.trace("size of removeAll result is {} keys are {} proxyResult is {}", size, keys,
                proxyResult);
          } else {
            if (isTraceEnabled) {
              logger.trace("size of removeAll result is {} keys are {} proxyResult is {}", size,
                  keys, proxyResult);
            }
          }
        } else {
          if (isTraceEnabled) {
            logger.trace("size of removeAll result is {} keys are {} proxyResult is {}", size, keys,
                proxyResult);
          }
        }

        final PutAllPartialResult partialKeys = new PutAllPartialResult(size);
        final Iterator iterator;
        final boolean isVersionedResults;
        if (proxyResult != null) {
          iterator = proxyResult.iterator();
          isVersionedResults = true;
        } else {
          iterator = keys.iterator();
          isVersionedResults = false;
        }

        // TODO: refactor this mess
        Runnable task = () -> {
          int offset = 0;
          VersionTagHolder tagHolder = new VersionTagHolder();
          while (iterator.hasNext()) {
            stopper.checkCancelInProgress(null);
            tagHolder.setVersionTag(null);
            Object key;
            VersionTag versionTag = null;
            if (isVersionedResults) {
              Map.Entry mapEntry = (Map.Entry) iterator.next();
              key = mapEntry.getKey();
              versionTag = ((VersionedObjectList.Entry) mapEntry).getVersionTag();
              if (isDebugEnabled) {
                logger.debug("removeAll key {} version={}", key, versionTag);
              }
              if (versionTag == null) {
                if (isDebugEnabled) {
                  logger.debug(
                      "removeAll found invalid version tag, which means the entry is not found at server for key={}.",
                      key);
                }
                succeeded.addKeyAndVersion(key, null);
                continue;
              }
              // No need for special handling here in removeAll.
              // We can just remove this key from the client with versionTag set to null.
            } else {
              key = iterator.next();
              if (isTraceEnabled) {
                logger.trace("removeAll {}", key);
              }
            }

            try {
              if (serverIsVersioned) {
                if (isDebugEnabled) {
                  logger.debug("associating version tag with {} version={}", key, versionTag);
                }
                // If we have received a version tag from a server, add it to the event
                tagHolder.setVersionTag(versionTag);
                tagHolder.setFromServer(true);
              } else if (retryVersions != null) {
                VersionTag versionTag1 = retryVersions.get(offset);
                if (versionTag1 != null) {
                  // If this is a retried event, and we have a version tag for the retry,
                  // add it to the event.
                  tagHolder.setVersionTag(versionTag1);
                }
              }

              basicEntryRemoveAll(key, removeAllOp, offset, tagHolder);
              // now we must check again since the cache may have closed during
              // distribution causing this process to not receive and queue the
              // event for clients
              stopper.checkCancelInProgress(null);
              succeeded.addKeyAndVersion(key, tagHolder.getVersionTag());
            } catch (Exception ex) {
              partialKeys.saveFailedKey(key, ex);
            }
            offset++;
          }
        };

        syncBulkOp(task, eventId);
        if (partialKeys.hasFailure()) {
          // Now succeeded contains an order key list, may be missing the version tags.
          // Save reference of succeeded into partialKeys. The succeeded may be modified by
          // postRemoveAll() to fill in the version tags.
          partialKeys.setSucceededKeysAndVersions(succeeded);
          logger.info("Region {} removeAll: {}",
              new Object[] {getFullPath(), partialKeys});
          if (isDebugEnabled) {
            logger.debug(partialKeys.detailString());
          }
          if (runtimeException == null) {
            // if received exception from server first, ignore local exception
            if (removeAllOp.isBridgeOperation()) {
              if (partialKeys.getFailure() instanceof CancelException) {
                runtimeException = (RuntimeException) partialKeys.getFailure();
              } else if (partialKeys.getFailure() instanceof LowMemoryException) {
                throw partialKeys.getFailure();
              } else {
                runtimeException = new PutAllPartialResultException(partialKeys);
                if (isDebugEnabled) {
                  logger.debug("basicRemoveAll: {}", partialKeys.detailString());
                }
              }
            } else {
              throw partialKeys.getFailure();
            }
          }
        }
      } catch (LowMemoryException lme) {
        throw lme;
      } catch (RuntimeException ex) {
        runtimeException = ex;
      } catch (Exception ex) {
        runtimeException = new RuntimeException(ex);
      } finally {
        removeAllOp.getBaseEvent().release();
        removeAllOp.freeOffHeapResources();
      }
      getDataView().postRemoveAll(removeAllOp, succeeded, this);
    } finally {
      unlockRVVForBulkOp();
    }
    if (runtimeException != null) {
      throw runtimeException;
    }
    return succeeded;
  }

  /**
   * putAll can be partially applied when a clear() occurs, leaving the cache in an
   * inconsistent state. Set the RVV to "cache op in progress" so clear() will block until the
   * putAll completes. This won't work for non-replicate regions though since they uses one-hop
   * during basicPutPart2 to get a valid version tag.
   */
  public void lockRVVForBulkOp() {
    ARMLockTestHook testHook = getRegionMap().getARMLockTestHook();
    if (testHook != null) {
      testHook.beforeBulkLock(this);
    }

    if (versionVector != null && getDataPolicy().withReplication()) {
      versionVector.lockForCacheModification(this);
    }

    if (testHook != null) {
      testHook.afterBulkLock(this);
    }
  }

  public void unlockRVVForBulkOp() {
    ARMLockTestHook testHook = getRegionMap().getARMLockTestHook();
    if (testHook != null) {
      testHook.beforeBulkRelease(this);
    }

    if (versionVector != null && getDataPolicy().withReplication()) {
      versionVector.releaseCacheModificationLock(this);
    }

    if (testHook != null) {
      testHook.afterBulkRelease(this);
    }
  }

  @VisibleForTesting
  public DistributedPutAllOperation newPutAllOperation(Map<?, ?> map, Object callbackArg) {
    if (map == null) {
      throw new NullPointerException(
          "map cannot be null");
    }
    if (map.isEmpty()) {
      return null;
    }

    checkReadiness();
    checkForLimitedOrNoAccess();
    discoverJTA();

    // Create a dummy event for the PutAll operation. Always create a
    // PutAll operation, even if there is no distribution, so that individual
    // events can be tracked and handed off to callbacks in postPutAll
    // No need for release since disallowOffHeapValues called.
    final EntryEventImpl event = entryEventFactory.create(this, Operation.PUTALL_CREATE, null, null,
        callbackArg, true, getMyId());

    event.disallowOffHeapValues();
    return new DistributedPutAllOperation(event, map.size(), false);
  }

  private DistributedRemoveAllOperation newRemoveAllOperation(Collection<?> keys,
      Object callbackArg) {
    if (keys == null) {
      throw new NullPointerException("The keys Collection passed to removeAll was null.");
    }
    if (keys.isEmpty()) {
      return null;
    }

    checkReadiness();
    checkForLimitedOrNoAccess();
    discoverJTA();

    // Create a dummy event for the removeAll operation. Always create a
    // removeAll operation, even if there is no distribution, so that individual
    // events can be tracked and handed off to callbacks in postRemoveAll
    // No need for release since disallowOffHeapValues called.
    final EntryEventImpl event = entryEventFactory.create(this, Operation.REMOVEALL_DESTROY, null,
        null, callbackArg, false, getMyId());
    event.disallowOffHeapValues();
    return new DistributedRemoveAllOperation(event, keys.size(), false);
  }

  /**
   * This performs the putAll operation for a specific key and value
   *
   * @param key the cache key
   * @param value the cache value
   * @param putallOp the DistributedPutAllOperation associated with the event
   * @param tagHolder holder for version tag
   * @throws TimeoutException if the operation times out
   * @throws CacheWriterException if a cache writer objects to the update
   */
  private void basicEntryPutAll(Object key, Object value, DistributedPutAllOperation putallOp,
      int offset, EntryEventImpl tagHolder) throws TimeoutException, CacheWriterException {

    assert putallOp != null;

    checkReadiness();
    if (value == null) {
      throw new NullPointerException(
          "Value cannot be null");
    }

    validateArguments(key, value, null);

    // event is marked as a PUTALL_CREATE but if the entry exists it
    // will be changed to a PUTALL_UPDATE later on.

    @Released
    EntryEventImpl event =
        entryEventFactory.createPutAllEvent(putallOp, this, Operation.PUTALL_CREATE, key, value);

    try {
      if (tagHolder != null) {
        event.setVersionTag(tagHolder.getVersionTag());
        event.setFromServer(tagHolder.isFromServer());
      }
      if (generateEventID()) {
        event.setEventId(new EventID(putallOp.getBaseEvent().getEventId(), offset));
      }

      // TODO: could be called once for the entire putAll instead of calling it for every key
      discoverJTA();

      /*
       * If this is tx, do putEntry, unless it is a local region?
       */
      performPutAllEntry(event);
      if (tagHolder != null) {
        tagHolder.setVersionTag(event.getVersionTag());
        tagHolder.isConcurrencyConflict(event.isConcurrencyConflict());
      }
    } finally {
      event.release();
    }
  }

  private void basicEntryRemoveAll(Object key, DistributedRemoveAllOperation op, int offset,
      EntryEventImpl tagHolder) throws TimeoutException, CacheWriterException {

    assert op != null;

    checkReadiness();
    validateKey(key);

    @Released
    EntryEventImpl event = entryEventFactory.createRemoveAllEvent(op, this, key);

    try {
      if (tagHolder != null) {
        event.setVersionTag(tagHolder.getVersionTag());
        event.setFromServer(tagHolder.isFromServer());
      }
      if (generateEventID()) {
        event.setEventId(new EventID(op.getBaseEvent().getEventId(), offset));
      }

      // TODO: could be called once for the entire removeAll instead of calling it for every key
      discoverJTA();

      /*
       * If this is tx, do destroyEntry, unless it is a local region?
       */
      try {
        performRemoveAllEntry(event);
      } catch (EntryNotFoundException ignore) {
        if (event.getVersionTag() == null) {
          if (logger.isDebugEnabled()) {
            logger.debug("RemoveAll encountered EntryNotFoundException: event={}", event);
          }
        }
      }
      if (tagHolder != null) {
        tagHolder.setVersionTag(event.getVersionTag());
        tagHolder.isConcurrencyConflict(event.isConcurrencyConflict());
      }
    } finally {
      event.release();
    }
  }

  void performPutAllEntry(EntryEventImpl event) {
    getDataView().putEntry(event, false, false, null, false, 0L, false);
  }

  void performRemoveAllEntry(EntryEventImpl event) {
    basicDestroy(event, true, null);
  }

  @Override
  public void postPutAllFireEvents(DistributedPutAllOperation putAllOp,
      VersionedObjectList successfulPuts) {

    if (!getDataPolicy().withStorage() && getConcurrencyChecksEnabled()
        && putAllOp.getBaseEvent().isBridgeEvent()) {
      // if there is no local storage we need to transfer version information
      // to the successfulPuts list for transmission back to the client
      successfulPuts.clear();
      putAllOp.fillVersionedObjectList(successfulPuts);
    }

    Set successfulKeys = new HashSet(successfulPuts.size());
    for (Object key : successfulPuts.getKeys()) {
      successfulKeys.add(key);
    }

    for (Iterator it = putAllOp.eventIterator(); it.hasNext();) {
      @Unretained
      EntryEventImpl event = (EntryEventImpl) it.next();

      if (successfulKeys.contains(event.getKey())) {
        EnumListenerEvent op = event.getOperation().isCreate() ? EnumListenerEvent.AFTER_CREATE
            : EnumListenerEvent.AFTER_UPDATE;
        invokePutCallbacks(op, event, !event.callbacksInvoked() && !event.isPossibleDuplicate(),
            isUsedForPartitionedRegionBucket
        /*
         * If this is replicated region, use "false". We must notify gateways inside RegionEntry
         * lock, NOT here, to preserve the order of events sent by gateways for same key. If this is
         * bucket region, use "true", because the event order is guaranteed
         */);
      }
    }
  }

  @Override
  public void postRemoveAllFireEvents(DistributedRemoveAllOperation removeAllOp,
      VersionedObjectList successfulOps) {

    if (!getDataPolicy().withStorage() && getConcurrencyChecksEnabled()
        && removeAllOp.getBaseEvent().isBridgeEvent()) {
      // if there is no local storage we need to transfer version information
      // to the successfulOps list for transmission back to the client
      successfulOps.clear();
      removeAllOp.fillVersionedObjectList(successfulOps);
    }

    Set successfulKeys = new HashSet(successfulOps.size());
    for (Object key : successfulOps.getKeys()) {
      successfulKeys.add(key);
    }

    for (Iterator it = removeAllOp.eventIterator(); it.hasNext();) {
      @Unretained
      EntryEventImpl event = (EntryEventImpl) it.next();

      if (successfulKeys.contains(event.getKey())) {
        invokeDestroyCallbacks(EnumListenerEvent.AFTER_DESTROY, event,
            !event.callbacksInvoked() && !event.isPossibleDuplicate(),
            isUsedForPartitionedRegionBucket
        /*
         * If this is replicated region, use "false". We must notify gateways inside RegionEntry
         * lock, NOT here, to preserve the order of events sent by gateways for same key. If this is
         * bucket region, use "true", because the event order is guaranteed
         */);
      }
    }
  }

  @Override
  public long postPutAllSend(DistributedPutAllOperation putAllOp,
      VersionedObjectList successfulPuts) {
    /* No-op for local region of course */
    return -1;
  }

  @Override
  public long postRemoveAllSend(DistributedRemoveAllOperation op,
      VersionedObjectList successfulOps) {
    /* No-op for local region of course */
    return -1;
  }

  /**
   * DistributedRegion overrides isCurrentlyLockGrantor
   *
   * @see DistributedRegion#isCurrentlyLockGrantor()
   */
  @Override
  boolean isCurrentlyLockGrantor() {
    return false;
  }

  /**
   * Handle a local region destroy or a region close that was done on this region in a remote vm.
   * Currently the only thing needed is to have the advisor
   *
   * @param sender the id of the member that did the remote operation
   * @param topSerial the remote serialNumber for the top region (maybe root)
   * @param subregionSerialNumbers map of remote subregions to serialNumbers
   * @param regionDestroyed true if the region was destroyed on the remote host (as opposed to
   *        closed)
   * @since GemFire 5.0
   */
  void handleRemoteLocalRegionDestroyOrClose(InternalDistributedMember sender, int topSerial,
      Map subregionSerialNumbers, boolean regionDestroyed) {

    // go through initialization latches
    final InitializationLevel oldLevel = setThreadInitLevelRequirement(ANY_INIT);
    try {
      basicHandleRemoteLocalRegionDestroyOrClose(sender, topSerial, subregionSerialNumbers, false,
          regionDestroyed);
    } finally {
      setThreadInitLevelRequirement(oldLevel);
    }
  }

  /**
   * Does the core work for handleRemoteLocalRegionDestroyOrClose.
   *
   * @param sender the id of the member that did the remote operation
   * @param topSerial the remote serialNumber for the top region (maybe root)
   * @param subregionSerialNumbers remote map of subregions to serialNumbers
   * @since GemFire 5.0
   */
  private void basicHandleRemoteLocalRegionDestroyOrClose(InternalDistributedMember sender,
      int topSerial, Map subregionSerialNumbers, boolean subregion, boolean regionDestroyed) {

    // use topSerial unless this region is in subregionSerialNumbers map
    int serialForThisRegion = topSerial;

    if (subregion) {
      // OPTIMIZE: we don't know if this rgn is a subregion or the top region
      Integer serialNumber = (Integer) subregionSerialNumbers.get(getFullPath());
      if (serialNumber == null) {
        // sender didn't have this subregion
        return;
      }
      // non-null means this is a subregion under the destroyed region
      serialForThisRegion = serialNumber;
    }

    // remove sender's serialForThisRegion from the advisor
    removeSenderFromAdvisor(sender, serialForThisRegion, regionDestroyed);

    // process subregions...
    for (Object regionObject : subregions.values()) {
      LocalRegion region = toRegion(regionObject);
      if (region != null && !region.isDestroyed()) {
        // recursively call basicHandleRemoteLocalRegionDestroyOrClose for subregions
        region.basicHandleRemoteLocalRegionDestroyOrClose(sender, topSerial, subregionSerialNumbers,
            true, regionDestroyed);
      }
    }
  }

  /**
   * Remove the specified sender from this regions advisor.
   *
   * @since GemFire 5.0
   */
  void removeSenderFromAdvisor(InternalDistributedMember sender, int serial,
      boolean regionDestroyed) {
    // nothing needs to be done here since LocalRegion does not have an advisor.
  }

  @Override
  public boolean isUsedForPartitionedRegionAdmin() {
    return isUsedForPartitionedRegionAdmin;
  }

  public boolean shouldSyncForCrashedMember(InternalDistributedMember id) {
    return getConcurrencyChecksEnabled() && getDataPolicy().withReplication()
        && !isUsedForPartitionedRegionAdmin && !isUsedForMetaRegion
        && !isUsedForSerialGatewaySenderQueue;
  }

  /**
   * forces the diskRegion to switch the oplog
   *
   * @since GemFire 5.1
   */
  @Override
  public void forceRolling() throws DiskAccessException {
    if (diskRegion != null) {
      diskRegion.forceRolling();
    }
  }

  /**
   * filterProfile holds CQ and registerInterest information for clients having this region
   */
  FilterProfile filterProfile;

  /**
   * @return int array containing the IDs of the oplogs which will potentially get rolled else null
   *         if no oplogs were available at the time of signal or region is not having disk
   *         persistence. Pls note that the actual number of oplogs rolled may be more than what is
   *         indicated
   * @since GemFire prPersistSprint1
   */
  @Override
  boolean forceCompaction() {
    DiskRegion region = getDiskRegion();
    if (region != null) {
      if (region.isCompactionPossible()) {
        return region.forceCompaction();
      }
      throw new IllegalStateException(
          "To call notifyToCompact you must configure the region with <disk-write-attributes allow-force-compaction=true/>");
    }
    return false;
  }

  @Override
  public File[] getDiskDirs() {
    if (getDiskStore() != null) {
      return getDiskStore().getDiskDirs();
    }
    return diskDirs;
  }

  @Override
  public int[] getDiskDirSizes() {
    if (getDiskStore() != null) {
      return getDiskStore().getDiskDirSizes();
    }
    return diskSizes;
  }

  /**
   * @return Returns the isUsedForPartitionedRegionBucket.
   */
  @Override
  public boolean isUsedForPartitionedRegionBucket() {
    return isUsedForPartitionedRegionBucket;
  }

  protected boolean isUsedForSerialGatewaySenderQueue() {
    return isUsedForSerialGatewaySenderQueue;
  }

  protected boolean isUsedForParallelGatewaySenderQueue() {
    return isUsedForParallelGatewaySenderQueue;
  }

  public void removeCacheServiceProfile(String profileID) {
    cacheServiceProfileUpdateLock.lock();
    try {
      cacheServiceProfiles.remove(profileID);
    } finally {
      cacheServiceProfileUpdateLock.unlock();
    }

  }

  public AbstractGatewaySender getSerialGatewaySender() {
    return serialGatewaySender;
  }

  boolean isParallelWanEnabled() {
    Set<String> regionGatewaySenderIds = getAllGatewaySenderIds();
    if (regionGatewaySenderIds.isEmpty()) {
      return false;
    }
    Set<GatewaySender> cacheGatewaySenders = getCache().getAllGatewaySenders();
    for (GatewaySender sender : cacheGatewaySenders) {
      if (regionGatewaySenderIds.contains(sender.getId()) && sender.isParallel()) {
        return true;
      }
    }
    return false;
  }

  /**
   * A convenience method to get the PartitionedRegion for a Bucket
   *
   * @return If this is an instance of {@link BucketRegion}, returns the {@link PartitionedRegion}
   *         otherwise throws an IllegalArgumentException
   */
  @Override
  public PartitionedRegion getPartitionedRegion() {
    if (!isUsedForPartitionedRegionBucket) {
      throw new IllegalArgumentException();
    }
    return ((Bucket) this).getPartitionedRegion();
  }

  /**
   * @return Returns the isUsedForMetaRegion.
   */
  @Override
  public boolean isUsedForMetaRegion() {
    return isUsedForMetaRegion;
  }

  @Override
  public boolean isMetaRegionWithTransactions() {
    return isMetaRegionWithTransactions;
  }

  /**
   * @return true if this is not a user visible region
   */
  @Override
  public boolean isInternalRegion() {
    return isSecret() || isUsedForMetaRegion() || isUsedForPartitionedRegionAdmin()
        || isUsedForPartitionedRegionBucket();
  }

  Map<String, CacheServiceProfile> getCacheServiceProfiles() {
    return cacheServiceProfiles.getSnapshot();
  }

  @Override
  public void addCacheServiceProfile(CacheServiceProfile profile) {
    cacheServiceProfileUpdateLock.lock();
    try {
      cacheServiceProfiles.put(profile.getId(), profile);
    } finally {
      cacheServiceProfileUpdateLock.unlock();
    }
  }

  @Override
  public LoaderHelper createLoaderHelper(Object key, Object callbackArgument,
      boolean netSearchAllowed, boolean netLoadAllowed, SearchLoadAndWriteProcessor searcher) {
    return new LoaderHelperImpl(this, key, callbackArgument, netSearchAllowed, netLoadAllowed,
        searcher);
  }

  /**
   * visitor over the CacheProfiles to check if the region has a CacheLoader
   */
  @Immutable
  private static final DistributionAdvisor.ProfileVisitor<Void> netLoaderVisitor =
      (advisor, profile, profileIndex, numProfiles, aggregate) -> {
        assert profile instanceof CacheProfile;
        final CacheProfile prof = (CacheProfile) profile;

        // if region in cache is not yet initialized, exclude
        if (prof.regionInitialized) {
          // cut the visit short if we find a CacheLoader
          return !prof.hasCacheLoader;
        }
        // continue the visit
        return true;
      };

  /**
   * Return true if some other member of the distributed system, not including self, has a
   * CacheLoader defined on the region.
   */
  boolean hasNetLoader(CacheDistributionAdvisor distAdvisor) {
    return !distAdvisor.accept(netLoaderVisitor, null);
  }

  /**
   * Used to indicate that this region is used for internal purposes
   */
  @Override
  public boolean isSecret() {
    return false;
  }

  /**
   * whether concurrency checks should be disabled for this region
   */
  @Override
  protected boolean supportsConcurrencyChecks() {
    return !isSecret() || getDataPolicy().withPersistence();
  }

  /**
   * Used to prevent notification of bridge clients, typically used for internal "meta" regions and
   * if the cache doesn't have any cache servers
   *
   * @return true only if it's cache has cache servers and this is nt a meta region
   */
  @Override
  public boolean shouldNotifyBridgeClients() {
    return !cache.getCacheServers().isEmpty() && !isUsedForPartitionedRegionAdmin
        && !isUsedForPartitionedRegionBucket && !isUsedForMetaRegion;
  }

  /**
   * Check if the region has has a Listener or not
   *
   * @return true only if this region has a Listener
   */
  @Override
  public boolean shouldDispatchListenerEvent() {
    return hasListener();
  }

  /**
   * Called by ccn when a client goes away
   *
   * @since GemFire 5.7
   */
  @Override
  public void cleanupForClient(CacheClientNotifier clientNotifier, ClientProxyMembershipID client) {
    if (cache.isClosed() || isDestroyed) {
      return;
    }

    filterProfile.cleanupForClient(clientNotifier, client);

    for (Object regionObject : new SubregionsSet(false)) {
      LocalRegion region = (LocalRegion) regionObject;
      region.cleanupForClient(clientNotifier, client);
    }
  }

  /**
   * Returns the CQ/interest profile for this region
   */
  @Override
  public FilterProfile getFilterProfile() {
    return filterProfile;
  }

  /**
   * Returns a map of subregions that were destroyed when this region was destroyed. Map contains
   * subregion full paths to SerialNumbers. Return is defined as HashMap because
   * DestroyRegionOperation will provide the map to DataSerializer.writeHashMap which requires
   * HashMap. Returns {@link #destroyedSubregionSerialNumbers}.
   *
   * @return HashMap of subregions to SerialNumbers
   * @throws IllegalStateException if this region has not been destroyed
   */
  HashMap getDestroyedSubregionSerialNumbers() {
    if (!isDestroyed) {
      throw new IllegalStateException(
          String.format(
              "Region %s must be destroyed before calling getDestroyedSubregionSerialNumbers",
              getFullPath()));
    }
    return destroyedSubregionSerialNumbers;
  }

  /**
   * Returns a map of subregion full paths to SerialNumbers. Caller must have acquired the
   * destroyLock if a stable view is desired. Key is String, value is Integer.
   *
   * @return HashMap of subregions to SerialNumbers
   */
  private HashMap collectSubregionSerialNumbers() {
    HashMap map = new HashMap();
    addSubregionSerialNumbers(map);
    return map;
  }

  /**
   * Iterates over all subregions to put the full path and serial number into the provided map.
   *
   * @param map the map to put the full path and serial number into for each subregion
   */
  private void addSubregionSerialNumbers(Map map) {
    // iterate over all subregions to gather serialNumbers and recurse
    for (Object entryObject : subregions.entrySet()) {
      Map.Entry entry = (Map.Entry) entryObject;
      LocalRegion subregion = (LocalRegion) entry.getValue();
      map.put(subregion.getFullPath(), subregion.getSerialNumber());

      // recursively call down into each subregion tree
      subregion.addSubregionSerialNumbers(map);
    }
  }

  @Override
  public SelectResults query(String predicate) throws FunctionDomainException,
      TypeMismatchException, NameResolutionException, QueryInvocationTargetException {

    if (predicate == null) {
      throw new IllegalArgumentException(
          "The input query predicate is null. A null predicate is not allowed.");
    }
    predicate = predicate.trim();
    SelectResults results;
    if (hasServerProxy()) {

      // Trim whitespace
      String queryString = constructRegionQueryString(predicate.trim());

      try {
        results = getServerProxy().query(queryString, null);
      } catch (Exception e) {
        Throwable cause = e.getCause();
        if (cause == null) {
          cause = e;
        }
        throw new QueryInvocationTargetException(e.getMessage(), cause);
      }
    } else {
      // TODO: params size is always zero so this whole block is wasted
      Object[] params = new Object[0];
      QueryService qs = getGemFireCache().getLocalQueryService();
      String queryStr = constructRegionQueryString(predicate.trim());
      DefaultQuery query = (DefaultQuery) qs.newQuery(queryStr);
      if (query.getRegionsInQuery(params).size() != 1) {
        throw new QueryInvalidException(
            "Prevent multiple region query from being executed through region.query()");
      }
      results = (SelectResults) query.execute(params);
    }
    return results;
  }

  private String constructRegionQueryString(final String predicate) throws QueryInvalidException {
    // send it as is to the server
    boolean matches = false;
    for (Pattern queryPattern : QUERY_PATTERNS) {
      if (queryPattern.matcher(predicate).matches()) {
        if (!predicate.contains(getName())) {
          throw new QueryInvalidException(
              "Should not execute region.query with a different region in the from clause: "
                  + getName() + " was not present in:" + predicate);
        }
        matches = true;
        break;
      }
    }
    final String queryString;// Compare the query patterns to the 'predicate'. If one matches,
    if (matches) {
      queryString = predicate;
    } else {
      queryString = "select * from " + getFullPath() + " this where " + predicate;
    }
    return queryString;
  }

  /**
   * Execute the provided named function in all locations that contain the given keys. So function
   * can be executed on just one fabric node, executed in parallel on a subset of nodes in parallel
   * across all the nodes.
   *
   * @since GemFire 5.8Beta
   */
  public ResultCollector executeFunction(final DistributedRegionFunctionExecutor execution,
      final Function function, final Object args, final ResultCollector rc, final Set filter,
      final ServerToClientFunctionResultSender sender) {

    if (function.optimizeForWrite()
        && !MemoryThresholds.isLowMemoryExceptionDisabled()) {
      MemoryThresholdInfo info = getAtomicThresholdInfo();
      if (info.isMemoryThresholdReached()) {
        Set<DistributedMember> members = info.getMembersThatReachedThreshold();
        throw new LowMemoryException(
            String.format(
                "Function: %s cannot be executed because the members %s are running low on memory",
                function.getId(), members),
            members);
      }
    }
    final LocalResultCollector<?, ?> resultCollector =
        execution.getLocalResultCollector(function, rc);
    final DistributionManager dm = getDistributionManager();
    execution.setExecutionNodes(Collections.singleton(getMyId()));

    final DistributedRegionFunctionResultSender resultSender =
        new DistributedRegionFunctionResultSender(dm, resultCollector, function, sender);
    final RegionFunctionContextImpl context = new RegionFunctionContextImpl(cache, function.getId(),
        this, args, filter, null, null, resultSender, execution.isReExecute());
    execution.executeFunctionOnLocalNode(function, context, resultSender, dm, isTX());
    return resultCollector;
  }

  @Override
  public void onEvent(MemoryEvent event) {
    if (logger.isDebugEnabled()) {
      logger.debug("Region:{} received a Memory event.{}", this, event);
    }
    setMemoryThresholdFlag(event);
  }

  void setMemoryThresholdFlag(MemoryEvent event) {
    assert getScope().isLocal();
    if (event.isLocal()) {
      if (event.getState().isCritical() && !event.getPreviousState().isCritical()
          && (event.getType() == ResourceType.HEAP_MEMORY
              || event.getType() == ResourceType.OFFHEAP_MEMORY && getOffHeap())) {
        // start rejecting operations
        setMemoryThresholdReached(true);
      } else if (!event.getState().isCritical() && event.getPreviousState().isCritical()
          && (event.getType() == ResourceType.HEAP_MEMORY
              || event.getType() == ResourceType.OFFHEAP_MEMORY && getOffHeap())) {
        setMemoryThresholdReached(false);
      }
    }
  }

  void updateSizeOnClearRegion(int sizeBeforeClear) {
    // Only needed by BucketRegion
  }

  /**
   * Calculate and return the size of a value for updating the bucket size. Zero is always returned
   * for non-bucket regions.
   */
  @Override
  public int calculateValueSize(Object value) {
    // Only needed by BucketRegion
    return 0;
  }

  @Override
  public int calculateRegionEntryValueSize(RegionEntry regionEntry) {
    // Only needed by BucketRegion
    return 0;
  }

  @Override
  public void updateSizeOnPut(Object key, int oldSize, int newSize) {
    // Only needed by BucketRegion
  }

  @Override
  public void updateSizeOnCreate(Object key, int newSize) {
    // Only needed by BucketRegion
  }

  @Override
  public void updateSizeOnRemove(Object key, int oldSize) {
    // Only needed by BucketRegion
  }

  // TODO: return value is never used
  @Override
  public int updateSizeOnEvict(Object key, int oldSize) {
    // Only needed by BucketRegion
    return 0;
  }

  @Override
  public void updateSizeOnFaultIn(Object key, int newSize, int bytesOnDisk) {
    // Only needed by BucketRegion
  }

  @Override
  public void initializeStats(long numEntriesInVM, long numOverflowOnDisk,
      long numOverflowBytesOnDisk) {
    getDiskRegion().getStats().incNumEntriesInVM(numEntriesInVM);
    getDiskRegion().getStats().incNumOverflowOnDisk(numOverflowOnDisk);
  }

  /**
   * This method is meant to be overridden by DistributedRegion and PartitionedRegions to cleanup
   * CRITICAL state
   */
  public void removeCriticalMember(DistributedMember member) {
    // should not be called for LocalRegion
    Assert.assertTrue(false);
  }

  /**
   * Initialize the set of remote members whose memory state is critical. This is called when
   * registering using
   * {@link InternalResourceManager#addResourceListener(ResourceType, ResourceListener)}. It should
   * only be called once and very early in this region's lifetime.
   *
   * @param localMemoryIsCritical true if the local memory is in a critical state
   * @param criticalMembers set of members whose memory is in a critical state
   * @see ResourceManager#setCriticalHeapPercentage(float) and
   *      ResourceManager#setCriticalOffHeapPercentage(float)
   * @since GemFire 6.0
   */
  void initialCriticalMembers(boolean localMemoryIsCritical,
      Set<InternalDistributedMember> criticalMembers) {
    assert getScope().isLocal();
    if (localMemoryIsCritical) {
      setMemoryThresholdReached(true);
    }
  }

  @Override
  public void destroyRecoveredEntry(Object key) {
    @Released
    EntryEventImpl event = entryEventFactory.create(this, Operation.LOCAL_DESTROY, key, null, null,
        false, getMyId(), false);
    try {
      event.inhibitCacheListenerNotification(true);
      mapDestroy(event, true, false, null, false, true);
    } finally {
      event.release();
    }
  }

  @Override
  public boolean lruLimitExceeded() {
    return entries.lruLimitExceeded(getDiskRegionView());
  }

  @Override
  public DiskEntry getDiskEntry(Object key) {
    // should return tombstone as an valid entry
    RegionEntry regionEntry = entries.getEntry(key);
    if (regionEntry != null && regionEntry.isRemoved() && !regionEntry.isTombstone()) {
      regionEntry = null;
    }
    return (DiskEntry) regionEntry;
  }

  /**
   * Fetch the Region which stores the given key The resulting Region will be used for a read
   * operation e.g. Region.get
   *
   * @param entryKey key to evaluate to determine the returned region
   * @return region that stores the key
   */
  @Override
  public LocalRegion getDataRegionForRead(KeyInfo entryKey) {
    return this;
  }

  /**
   * Fetch the Region which stores the given key. The resulting Region will be used for a write
   * operation e.g. Region.put
   *
   * @param entryKey key to evaluate to determine the returned region
   * @return region that stores the key
   */
  @Override
  public LocalRegion getDataRegionForWrite(KeyInfo entryKey) {
    return this;
  }

  /**
   * @return a set of keys, intended for use by the various Region set operations such as
   *         {@link EntriesSet}
   */
  Set getRegionKeysForIteration() {
    return getRegionMap().keySet();
  }

  public InternalDataView getSharedDataView() {
    return sharedDataView;
  }

  /**
   * Used to bootstrap txState.
   *
   * @return localMember for local and distributedRegions, member with primary bucket for
   *         partitionedRegions
   */
  @Override
  public DistributedMember getOwnerForKey(KeyInfo key) {
    return getMyId();
  }

  /**
   * @return the wrapped {@link KeyInfo}
   */
  @Override
  public KeyInfo getKeyInfo(Object key) {
    return new KeyInfo(key, null, null);
  }

  public KeyInfo getKeyInfo(Object key, Object callbackArg) {
    return getKeyInfo(key, null, callbackArg);
  }

  @Override
  public KeyInfo getKeyInfo(Object key, Object value, Object callbackArg) {
    return new KeyInfo(key, null, callbackArg);
  }

  /**
   * @see #basicGetEntry(Object)
   */
  RegionEntry basicGetTXEntry(KeyInfo keyInfo) {
    return basicGetEntry(keyInfo.getKey());
  }

  @Override
  public void senderCreated() {
    distributeUpdatedProfileOnSenderCreation();
  }

  void distributeUpdatedProfileOnSenderCreation() {
    // No op
  }

  /**
   * test hook - dump the backing map for this region
   */
  @VisibleForTesting
  public void dumpBackingMap() {
    synchronized (entries) {
      if (entries instanceof AbstractRegionMap) {
        ((AbstractRegionMap) entries).verifyTombstoneCount(tombstoneCount);
      }
      logger.debug("Dumping region of size {} tombstones: {}: {}", size(), getTombstoneCount(),
          toString());
      if (entries instanceof AbstractRegionMap) {
        ((AbstractRegionMap) entries).dumpMap();
      }
    }
  }

  private void checkIfConcurrentMapOpsAllowed() {
    // This check allows NORMAL with local scope
    if (serverRegionProxy == null
        && (getDataPolicy() == DataPolicy.NORMAL && scope.isDistributed()
            || getDataPolicy() == DataPolicy.EMPTY)) {
      // the functional spec says these data policies do not support concurrent map operations
      throw new UnsupportedOperationException();
    }
  }

  boolean canStoreDataLocally() {
    return getDataPolicy().withStorage();
  }

  /**
   * If the specified key is not already associated with a value, associate it with the given value.
   * This is equivalent to
   *
   * <pre>
   * if (!region.containsKey(key))
   *   return region.put(key, value);
   * else
   *   return region.get(key);
   * </pre>
   *
   * Except that the action is performed atomically.
   *
   * <i>Note that if this method returns null then there is no way to determine definitely whether
   * this operation succeeded and modified the region, or if the entry is in an invalidated state
   * and no modification occurred.</i>
   *
   * If this method does not modify the region then no listeners or other callbacks are executed. If
   * a modification does occur, then the behavior with respect to callbacks is the same as
   * {@link Region#create(Object, Object)}.
   *
   * @param key key with which the specified value is to be associated.
   * @param value the value for the new entry, which may be null meaning the new entry starts as if
   *        it had been locally invalidated.
   * @return previous value associated with specified key, or <tt>null</tt> if there was no mapping
   *         for key. A <tt>null</tt> return can also indicate that the entry in the region was
   *         previously in an invalidated state.
   * @throws ClassCastException if key does not satisfy the keyConstraint
   * @throws IllegalArgumentException if the key or value is not serializable and this is a
   *         distributed region
   * @throws TimeoutException if timed out getting distributed lock for {@code Scope.GLOBAL}
   * @throws NullPointerException if key is <tt>null</tt>
   * @throws PartitionedRegionStorageException if the operation could not be completed.
   */
  public Object putIfAbsent(Object key, Object value, Object callbackArgument) {
    long startPut = getStatisticsClock().getTime();

    checkIfConcurrentMapOpsAllowed();
    validateArguments(key, value, callbackArgument);

    // TODO ConcurrentMap.putIfAbsent() treats null as an invalidation operation
    // BUT we need to return the old value, which Invalidate isn't currently doing

    checkReadiness();
    checkForLimitedOrNoAccess();
    discoverJTA();

    // This used to call the constructor which took the old value. It
    // was modified to call the other EntryEventImpl constructor so that
    // an id will be generated by default. Null was passed in anyway.
    // generate EventID

    @Released
    EntryEventImpl event = entryEventFactory.create(this, Operation.PUT_IF_ABSENT, key, value,
        callbackArgument, false, getMyId());

    try {
      if (generateEventID()) {
        event.setNewEventId(cache.getDistributedSystem());
      }
      final Object oldValue = null;
      final boolean ifNew = true;
      final boolean ifOld = false;
      final boolean requireOldValue = true;
      if (!basicPut(event, ifNew, ifOld, oldValue, requireOldValue)) {
        return event.getOldValue();
      }
      if (!getDataView().isDeferredStats()) {
        getCachePerfStats().endPut(startPut, false);
      }
      return null;
    } catch (EntryNotFoundException ignore) {
      return event.getOldValue();
    } finally {
      event.release();
    }
  }

  @Override
  public Object putIfAbsent(Object key, Object value) {
    return putIfAbsent(key, value, null);
  }

  @Override
  public boolean remove(Object key, Object value) {
    return remove(key, value, null);
  }

  /**
   * Same as {@link #remove(Object, Object)} except a callback argument is supplied to be passed on
   * to <tt>CacheListener</tt>s and/or <tt>CacheWriter</tt>s.
   */
  public boolean remove(Object key, Object value, Object callbackArg) {
    checkIfConcurrentMapOpsAllowed();
    validateKey(key);
    checkReadiness();
    checkForLimitedOrNoAccess();

    if (value == null) {
      value = Token.INVALID;
    }

    @Released
    EntryEventImpl event =
        entryEventFactory.create(this, Operation.REMOVE, key, null, callbackArg, false, getMyId());

    try {
      if (generateEventID() && event.getEventId() == null) {
        event.setNewEventId(cache.getDistributedSystem());
      }
      discoverJTA();
      getDataView().destroyExistingEntry(event, true, value);

    } catch (EntryNotFoundException ignore) {
      return false;
    } catch (RegionDestroyedException rde) {
      if (!rde.getRegionFullPath().equals(getFullPath())) {
        // Handle when a bucket is destroyed
        throw new RegionDestroyedException(toString(), getFullPath(), rde);
      }
      throw rde;
    } finally {
      event.release();
    }
    return true;
  }

  @Override
  public boolean replace(Object key, Object oldValue, Object newValue) {
    return replace(key, oldValue, newValue, null);
  }

  /**
   * Same as {@link #replace(Object, Object, Object)} except a callback argument is supplied to be
   * passed on to <tt>CacheListener</tt>s and/or <tt>CacheWriter</tt>s.
   */
  private boolean replace(Object key, Object expectedOldValue, Object newValue,
      Object callbackArg) {
    checkIfConcurrentMapOpsAllowed();
    if (newValue == null) {
      throw new NullPointerException();
    }

    long startPut = getStatisticsClock().getTime();
    validateArguments(key, newValue, callbackArg);
    checkReadiness();
    checkForLimitedOrNoAccess();

    @Released
    EntryEventImpl event = entryEventFactory.create(this, Operation.REPLACE, key, newValue,
        callbackArg, false, getMyId());

    try {
      if (generateEventID()) {
        event.setNewEventId(cache.getDistributedSystem());
      }

      discoverJTA();

      // In general, expectedOldValue null is used when there is no particular
      // old value expected (it can be anything). Here, however, if null
      // is passed as expectedOldValue, then it specifically means that the
      // oldValue must actually be null (i.e. INVALID). So here we
      // change an expectedOldValue of null to the invalid token
      if (expectedOldValue == null) {
        expectedOldValue = Token.INVALID;
      }

      if (!basicPut(event, false, true, expectedOldValue, false)) {
        return false;
      }
      if (!getDataView().isDeferredStats()) {
        getCachePerfStats().endPut(startPut, false);
      }
      return true;

    } catch (EntryNotFoundException ignore) {
      // put failed on server
      return false;
    } finally {
      event.release();
    }
  }

  @Override
  public Object replace(Object key, Object value) {
    return replaceWithCallbackArgument(key, value, null);
  }

  /**
   * Same as {@link #replace(Object, Object)} except a callback argument is supplied to be passed on
   * to <tt>CacheListener</tt>s and/or <tt>CacheWriter</tt>s.
   * <p>
   * TODO: callbackArg is always null but this method is for callbacks??
   */
  private Object replaceWithCallbackArgument(Object key, Object value, Object callbackArg) {
    long startPut = getStatisticsClock().getTime();

    checkIfConcurrentMapOpsAllowed();

    if (value == null) {
      throw new NullPointerException();
    }

    validateArguments(key, value, callbackArg);
    checkReadiness();
    checkForLimitedOrNoAccess();

    @Released
    EntryEventImpl event =
        entryEventFactory.create(this, Operation.REPLACE, key, value, callbackArg, false,
            getMyId());

    try {
      if (generateEventID()) {
        event.setNewEventId(cache.getDistributedSystem());
      }

      discoverJTA();

      if (!basicPut(event, false, true, null, true)) {
        return null;
      }
      if (!getDataView().isDeferredStats()) {
        getCachePerfStats().endPut(startPut, false);
      }
      return event.getOldValue(); // may be null if was invalid

    } catch (EntryNotFoundException ignore) {
      // put failed on server
      return null;
    } finally {
      event.release();
    }
  }

  // TODO: fromClient is always null
  public Object basicBridgePutIfAbsent(final Object key, Object value, boolean isObject,
      Object callbackArg, final ClientProxyMembershipID client, boolean fromClient,
      EntryEventImpl clientEvent)
      throws TimeoutException, EntryExistsException, CacheWriterException {

    EventID eventId = clientEvent.getEventId();
    long startPut = getStatisticsClock().getTime();

    @Released
    final EntryEventImpl event =
        entryEventFactory.create(this, Operation.PUT_IF_ABSENT, key, null,
            callbackArg, false, client.getDistributedMember(), true, eventId);

    try {
      event.setContext(client);

      // if this is a replayed operation we may already have a version tag
      event.setVersionTag(clientEvent.getVersionTag());
      event.setPossibleDuplicate(clientEvent.isPossibleDuplicate());

      // Set the new value to the input byte[] if it isn't null
      if (value != null) {
        // If the byte[] represents an object, then store it serialized
        // in a CachedDeserializable; otherwise store it directly as a byte[]
        if (isObject) {
          // The value represents an object
          event.setSerializedNewValue((byte[]) value);
        } else {
          // The value does not represent an object
          event.setNewValue(value);
        }
      }

      validateArguments(key, event.basicGetNewValue(), callbackArg);

      // cannot overwrite an existing key
      boolean ifNew = true;
      // can create a new key
      boolean ifOld = false;
      // need the old value if the create fails
      boolean requireOldValue = true;

      boolean basicPut = basicPut(event, ifNew, ifOld, null, requireOldValue);

      getCachePerfStats().endPut(startPut, false);
      stopper.checkCancelInProgress(null);

      Object oldValue = event.getRawOldValueAsHeapObject();
      if (oldValue == Token.NOT_AVAILABLE) {
        oldValue = AbstractRegion.handleNotAvailable(oldValue);
      }

      if (basicPut) {
        clientEvent.setVersionTag(event.getVersionTag());
        clientEvent.isConcurrencyConflict(event.isConcurrencyConflict());
      } else {
        if (oldValue == null) {
          // putIfAbsent on server can return null if the
          // operation was not performed (oldValue in cache was null).
          // We return the INVALID token instead of null to distinguish
          // this case from successful operation
          return Token.INVALID;
        }
      }
      return oldValue;
    } finally {
      event.release();
    }
  }

  @Override
  public KnownVersion[] getSerializationVersions() {
    return null;
  }

  // TODO: fromClient is always true
  public boolean basicBridgeReplace(final Object key, Object expectedOldValue, Object value,
      boolean isObject, Object callbackArg, final ClientProxyMembershipID client,
      boolean fromClient, EntryEventImpl clientEvent)
      throws TimeoutException, EntryExistsException, CacheWriterException {

    EventID eventId = clientEvent.getEventId();
    long startPut = getStatisticsClock().getTime();

    @Released
    final EntryEventImpl event =
        entryEventFactory.create(this, Operation.REPLACE, key, null,
            callbackArg, false, client.getDistributedMember(), true, eventId);

    try {
      event.setContext(client);

      // if this is a replayed operation we may already have a version tag
      event.setVersionTag(clientEvent.getVersionTag());
      event.setPossibleDuplicate(clientEvent.isPossibleDuplicate());

      // Set the new value to the input byte[] if it isn't null
      if (value != null) {
        // If the byte[] represents an object, then store it serialized
        // in a CachedDeserializable; otherwise store it directly as a byte[]
        if (isObject) {
          // The value represents an object
          event.setSerializedNewValue((byte[]) value);
        } else {
          // The value does not represent an object
          event.setNewValue(value);
        }
      }

      validateArguments(key, event.basicGetNewValue(), callbackArg);

      // can overwrite an existing key
      boolean ifNew = false;
      // cannot create a new key
      boolean ifOld = true;
      boolean requireOldValue = false;

      boolean success = basicPut(event, ifNew, ifOld, expectedOldValue, requireOldValue);

      clientEvent.isConcurrencyConflict(event.isConcurrencyConflict());
      if (success) {
        clientEvent.setVersionTag(event.getVersionTag());
      }

      getCachePerfStats().endPut(startPut, false);
      stopper.checkCancelInProgress(null);

      return success;
    } finally {
      event.release();
    }
  }

  // TODO: fromClient is always true
  public Object basicBridgeReplace(final Object key, Object value, boolean isObject,
      Object callbackArg, final ClientProxyMembershipID client, boolean fromClient,
      EntryEventImpl clientEvent)
      throws TimeoutException, EntryExistsException, CacheWriterException {

    EventID eventId = clientEvent.getEventId();
    long startPut = getStatisticsClock().getTime();

    @Released
    final EntryEventImpl event =
        entryEventFactory.create(this, Operation.REPLACE, key, null,
            callbackArg, false, client.getDistributedMember(), true, eventId);

    try {
      event.setContext(client);

      // if this is a replayed operation we may already have a version tag
      event.setVersionTag(clientEvent.getVersionTag());
      event.setPossibleDuplicate(clientEvent.isPossibleDuplicate());

      // Set the new value to the input byte[] if it isn't null
      if (value != null) {
        // If the byte[] represents an object, then store it serialized
        // in a CachedDeserializable; otherwise store it directly as a byte[]
        if (isObject) {
          // The value represents an object
          event.setSerializedNewValue((byte[]) value);
        } else {
          // The value does not represent an object
          event.setNewValue(value);
        }
      }

      validateArguments(key, event.basicGetNewValue(), callbackArg);

      // can overwrite an existing key
      boolean ifNew = false;
      // cannot create a new key
      boolean ifOld = true;
      boolean requireOldValue = true;

      boolean succeeded = basicPut(event, ifNew, ifOld, null, requireOldValue);

      getCachePerfStats().endPut(startPut, false);
      stopper.checkCancelInProgress(null);

      clientEvent.isConcurrencyConflict(event.isConcurrencyConflict());
      if (succeeded) {
        clientEvent.setVersionTag(event.getVersionTag());
        Object oldValue = event.getRawOldValueAsHeapObject();
        if (oldValue == Token.NOT_AVAILABLE) {
          oldValue = AbstractRegion.handleNotAvailable(oldValue);
        }
        if (oldValue == null) {
          oldValue = Token.INVALID;
        }
        return oldValue;
      }
      return null;
    } finally {
      event.release();
    }
  }

  // TODO: fromClient is always true
  public void basicBridgeRemove(Object key, Object expectedOldValue, Object callbackArg,
      ClientProxyMembershipID memberId, boolean fromClient, EntryEventImpl clientEvent)
      throws TimeoutException, EntryNotFoundException, CacheWriterException {

    // Create an event and put the entry
    @Released
    final EntryEventImpl event =
        entryEventFactory.create(this, Operation.REMOVE, key, null,
            callbackArg, false, memberId.getDistributedMember(), true, clientEvent.getEventId());

    try {
      event.setContext(memberId);
      event.setVersionTag(clientEvent.getVersionTag());
      event.setPossibleDuplicate(clientEvent.isPossibleDuplicate());
      // we rely on exceptions to tell us that the operation didn't take
      // place. AbstractRegionMap performs the checks and throws the exception
      try {
        basicDestroy(event, true, expectedOldValue);
      } finally {
        clientEvent.setVersionTag(event.getVersionTag());
        clientEvent.setIsRedestroyedEntry(event.getIsRedestroyedEntry());
      }
    } finally {
      event.release();
    }
  }

  @Override
  public long getVersionForMember(VersionSource member) {
    throw new IllegalStateException("Operation only implemented for disk region");
  }

  /**
   * Return an IndexMap that is persisted to the disk store used by this region.
   *
   * This IndexMap should be used as the backing map for any regions that are using the Soplog
   * persistence.
   *
   * Calling this method may create a branch new index map on disk, or it may recover an index map
   * that was previously persisted, depending on whether the index previously existed.
   *
   * TODO: none of the parameters are ever used
   *
   * @param indexName the name of the index
   * @param indexedExpression the index expression
   * @param fromClause the from clause.
   * @return The index map.
   * @throws IllegalStateException if this region is not using soplog persistence
   * @throws IllegalStateException if this index was previously persisted with a different
   *         expression or from clause.
   */
  public IndexMap getIndexMap(String indexName, String indexedExpression, String fromClause) {
    return new IndexMapImpl();
  }

  @Override
  public void setInUseByTransaction(boolean value) {
    synchronized (regionExpiryLock) {
      if (value) {
        txRefCount++;
      } else {
        txRefCount--;
        assert txRefCount >= 0;
        if (txRefCount == 0) {
          if (regionTTLExpiryTask == null && regionTimeToLive > 0) {
            addTTLExpiryTask();
          }
          if (regionIdleExpiryTask == null && regionIdleTimeout > 0) {
            addIdleExpiryTask();
          }
        }
      }
    }
  }

  /**
   * Return true if the region expiry task should be rescheduled
   */
  boolean expireRegion(RegionExpiryTask regionExpiryTask, boolean distributed, boolean destroy) {
    synchronized (regionExpiryLock) {
      if (regionExpiryTask instanceof RegionTTLExpiryTask) {
        if (regionExpiryTask != regionTTLExpiryTask) {
          // We must be an old task so defer to the currently scheduled one
          return false;
        }
        regionTTLExpiryTask = null;
      } else {
        if (regionExpiryTask != regionIdleExpiryTask) {
          // We must be an old task so defer to the currently scheduled one
          return false;
        }
        regionIdleExpiryTask = null;
      }
      if (txRefCount > 0) {
        return false;
      }
    }
    // release the sync before doing the operation to prevent deadlock
    Operation op = destroy
        ? distributed ? Operation.REGION_EXPIRE_DESTROY : Operation.REGION_EXPIRE_LOCAL_DESTROY
        : distributed ? Operation.REGION_EXPIRE_INVALIDATE
            : Operation.REGION_EXPIRE_LOCAL_INVALIDATE;
    RegionEventImpl event =
        new RegionEventImpl(this, op, null, false, getMyId(), generateEventID());
    if (destroy) {
      basicDestroyRegion(event, distributed);
    } else {
      basicInvalidateRegion(event);
    }
    return true;
  }

  @VisibleForTesting
  public int testHookGetValuesInVM() {
    int result = 0;
    for (RegionEntry re : getRegionMap().regionEntries()) {
      if (re.getValueAsToken() == Token.NOT_A_TOKEN) {
        result++;
      }
    }
    return result;
  }

  @VisibleForTesting
  public int testHookGetValuesOnDisk() {
    int result = 0;
    for (RegionEntry re : getRegionMap().regionEntries()) {
      if (re.getValueAsToken() == null) {
        result++;
      }
    }
    return result;
  }

  /**
   * Send a message to all other members that can have this same region entry and return the latest
   * last access time.
   */
  long getLatestLastAccessTimeFromOthers(Object key) {
    // local regions have no other members so return 0.
    return 0L;
  }

  /**
   * Returns the number of LRU evictions done by this region.
   */
  @Override
  public long getTotalEvictions() {
    return entries.getEvictions();
  }

  void incBucketEvictions() {
    // nothing needed by default
    // override this method on BucketRegion
  }

  @Override
  public long getEvictionCounter() {
    long result = 0L;
    EvictionController evictionController = getEvictionController();
    if (evictionController != null) {
      EvictionCounters es = evictionController.getCounters();
      if (es != null) {
        result = es.getCounter();
      }
    }
    return result;
  }

  @VisibleForTesting
  public long getEvictionLimit() {
    long result = 0L;
    EvictionController evictionController = getEvictionController();
    if (evictionController != null) {
      EvictionCounters es = evictionController.getCounters();
      if (es != null) {
        result = es.getLimit();
      }
    }
    return result;
  }

  @VisibleForTesting
  public long getEvictionDestroys() {
    long result = 0;
    EvictionController evictionController = getEvictionController();
    if (evictionController != null) {
      EvictionCounters es = evictionController.getCounters();
      if (es != null) {
        result = es.getDestroys();
      }
    }
    return result;
  }

  @Override
  public EvictionController getEvictionController() {
    return getRegionMap().getEvictionController();
  }

  @Override
  public void setEvictionMaximum(int maximum) {
    EvictionController evictionController = getEvictionController();
    if (evictionController != null) {
      evictionController.setLimit(maximum);
    }
  }

  @Override
  public Statistics getEvictionStatistics() {
    Statistics result = null;
    EvictionController evictionController = getEvictionController();
    if (evictionController != null) {
      EvictionCounters es = evictionController.getCounters();
      if (es != null) {
        result = es.getStatistics();
      }
    }
    return result;
  }

  @Override
  public EvictionController getExistingController(InternalRegionArguments internalArgs) {
    return null;
  }

  @Override
  public String getNameForStats() {
    return getFullPath();
  }

  @Override
  public Lock getClientMetaDataLock() {
    return clientMetaDataLock;
  }

  @VisibleForTesting
  public boolean isMemoryThresholdReached() {
    return memoryThresholdReached.get();
  }

  void setMemoryThresholdReached(boolean reached) {
    memoryThresholdReached.set(reached);
  }

  boolean isStatisticsEnabled() {
    return statisticsEnabled;
  }

  public enum IteratorType {
    KEYS, VALUES, ENTRIES
  }

  @Override
  public boolean isRegionCreateNotified() {
    return false;
  }

  @Override
  public void setRegionCreateNotified(boolean notified) {
    // do nothing
  }

  /**
   * Used by {@link #foreachRegionEntry}.
   *
   * @since GemFire prPersistSprint2
   */
  @FunctionalInterface
  public interface RegionEntryCallback {
    void handleRegionEntry(RegionEntry regionEntry);
  }

  /**
   * Internal interface used to simulate failures when performing entry operations
   *
   * @since GemFire 5.7
   */
  @FunctionalInterface
  @VisibleForTesting
  public interface TestCallable {
    void call(LocalRegion r, Operation op, RegionEntry re);
  }

  @FunctionalInterface
  @VisibleForTesting
  interface RegionMapConstructor {
    RegionMap create(LocalRegion owner, RegionMap.Attributes attrs,
        InternalRegionArguments internalRegionArgs);
  }

  @FunctionalInterface
  @VisibleForTesting
  interface ServerRegionProxyConstructor {
    ServerRegionProxy create(Region region);
  }

  private static class DefaultServerRegionProxyConstructor implements ServerRegionProxyConstructor {
    @Override
    public ServerRegionProxy create(Region region) {
      return new ServerRegionProxy(region);
    }
  }

  /**
   * Set view of subregions
   */
  private class SubregionsSet extends AbstractSet {
    private final boolean recursive;

    SubregionsSet(boolean recursive) {
      this.recursive = recursive;
    }

    @Override
    public Iterator iterator() {
      // iterates breadth-first (if recursive)
      return new Iterator() {
        private Iterator currentIterator = subregions.values().iterator();

        /** FIFO queue of iterators */
        private List queue;

        private Object nextElement;

        @Override
        public void remove() {
          throw new UnsupportedOperationException(
              "This iterator does not support modification");
        }

        @Override
        public boolean hasNext() {
          if (nextElement != null) {
            return true;
          }
          Object element = next(true);
          if (element != null) {
            nextElement = element;
            return true;
          }
          return false;
        }

        private boolean doHasNext() {
          return currentIterator != null && currentIterator.hasNext();
        }

        @Override
        public Object next() {
          return next(false);
        }

        /**
         * @param nullOK if true, return null instead of throwing NoSuchElementException
         * @return the next element
         */
        private Object next(boolean nullOK) {
          if (nextElement != null) {
            Object next = nextElement;
            nextElement = null;
            return next;
          }

          LocalRegion region;
          do {
            region = null;
            if (!doHasNext()) {
              if (queue == null || queue.isEmpty()) {
                if (nullOK) {
                  return null;
                }
                throw new NoSuchElementException();
              }
              currentIterator = (Iterator) queue.remove(0);
              continue;
            }
            region = (LocalRegion) currentIterator.next();
          } while (region == null || !region.isInitialized() || region.isDestroyed());

          if (recursive) {
            Iterator nextIterator = region.subregions.values().iterator();
            if (nextIterator.hasNext()) {
              if (queue == null) {
                queue = new ArrayList();
              }
              queue.add(nextIterator);
            }
          }
          if (!doHasNext()) {
            if (queue == null || queue.isEmpty()) {
              currentIterator = null;
            } else {
              currentIterator = (Iterator) queue.remove(0);
            }
          }
          return region;
        }
      };
    }

    @Override
    public int size() {
      if (recursive) {
        return allSubregionsSize() - 1 /* don't count this region */;
      }
      return subregions.size();
    }

    @Override
    public Object[] toArray() {
      List temp = new ArrayList(size());
      // do NOT use addAll or this results in stack overflow - must use iterator()
      for (Object o : this) {
        temp.add(o);
      }
      return temp.toArray();
    }

    @Override
    public Object[] toArray(Object[] array) {
      List temp = new ArrayList(size());
      // do NOT use addAll or this results in stack overflow - must use iterator()
      for (Object o : this) {
        temp.add(o);
      }
      return temp.toArray(array);
    }
  }

  /**
   * There seem to be cases where a region can be created and yet the distributed system is not yet
   * in place...
   */
  private class Stopper extends CancelCriterion {

    @Override
    public String cancelInProgress() {
      // This grossness is necessary because there are instances where the
      // region can exist without having a cache (XML creation)
      checkFailure();
      Cache cache = getCache();
      if (cache == null) {
        return "The cache is not available";
      }
      return cache.getCancelCriterion().cancelInProgress();
    }

    @Override
    public RuntimeException generateCancelledException(Throwable e) {
      // This grossness is necessary because there are instances where the
      // region can exist without having a cache (XML creation)
      checkFailure();
      Cache cache = getCache();
      if (cache == null) {
        return new CacheClosedException("No cache", e);
      }
      return cache.getCancelCriterion().generateCancelledException(e);
    }
  }

  private class EventDispatcher implements Runnable {
    /**
     * released by the release method
     */
    @Retained
    private final InternalCacheEvent event;

    private final EnumListenerEvent op;

    EventDispatcher(InternalCacheEvent event, EnumListenerEvent op) {
      if (offHeap && event instanceof EntryEventImpl) {
        // Make a copy that has its own off-heap refcount
        event = new EntryEventImpl((EntryEventImpl) event);
      }
      this.event = event;
      this.op = op;
    }

    @Override
    public void run() {
      try {
        dispatchEvent(LocalRegion.this, event, op);
      } finally {
        release();
      }
    }

    void release() {
      if (offHeap && event instanceof EntryEventImpl) {
        ((Releasable) event).release();
      }
    }
  }
}
