/*
 * 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 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.DistributionConfig;
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.Version;
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.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.LogService;
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.util.concurrent.CopyOnWriteHashMap;
import org.apache.geode.internal.util.concurrent.FutureResult;
import org.apache.geode.internal.util.concurrent.StoppableCountDownLatch;
import org.apache.geode.pdx.JSONFormatter;
import org.apache.geode.pdx.PdxInstance;

/**
 * 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 final ConcurrentHashMap<RegionEntry, EntryExpiryTask> entryExpiryTasks =
      new ConcurrentHashMap<>();

  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 =
      DistributionConfig.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(SEPARATOR).append(regionName);
    return buf.toString();
  }

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

  protected LocalRegion(String regionName, RegionAttributes attrs, LocalRegion parentRegion,
      InternalCache cache, InternalRegionArguments internalRegionArgs,
      InternalDataView internalDataView) 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()));
  }

  @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)
      throws DiskAccessException {
    super(cache, attrs, regionName, internalRegionArgs, poolFinder);

    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) {
      hasOwnStats = false;
      cachePerfStats = internalRegionArgs.getCachePerfStatsHolder().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
   */
  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);
              } else {
                newRegion = new BucketRegion(subregionName, regionAttributes, this, cache,
                    internalRegionArgs);
              }
            } else if (regionAttributes.getPartitionAttributes() != null) {
              newRegion = new PartitionedRegion(subregionName, regionAttributes, this, cache,
                  internalRegionArgs);
            } else {
              boolean local = regionAttributes.getScope().isLocal();
              newRegion = local
                  ? new LocalRegion(subregionName, regionAttributes, this, cache,
                      internalRegionArgs)
                  : new DistributedRegion(subregionName, regionAttributes, this, cache,
                      internalRegionArgs);
            }
            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 = CachePerfStats.getStatTime();
    @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 = CachePerfStats.getStatTime();
    @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()) {
          HeapDataOutputStream hdos = new HeapDataOutputStream(Version.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 = CachePerfStats.getStatTime();
      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) {
              if (!(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(DistributionConfig.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;
  }

  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);
        FilterInfo clientRouting = routing;
        if (clientRouting == null) {
          clientRouting = fp.getLocalFilterRouting(regionEvent);
        }
        regionEvent.setLocalFilterInfo(clientRouting);
        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 { // KIRK
    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
    Object value = regionEntry.getValueInVM(this);
    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(DistributionConfig.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) == 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(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 = CachePerfStats.getStatTime();
    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 = CachePerfStats.getStatTime();

    @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 = CachePerfStats.getStatTime();

    @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 = CachePerfStats.getStatTime();

    // 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);
  }

  /**
   * 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.
   * @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)
      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);
  }

  /**
   * 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) 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 ignore) {
      // 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);
      }
      notifyBridgeClients(event);
      notifyGatewaySender(event.getOperation().isUpdate() ? EnumListenerEvent.AFTER_UPDATE
          : EnumListenerEvent.AFTER_CREATE, event);
      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 && routing == null) {
      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();
    }
  }

  /**
   * 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) {
    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);
        }
      }
    }
  }

  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) {

    // 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);
    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 = needTokensForGII || needRIDestroyToken;
      entries.txApplyDestroy(key, rmtOrigin, event, inTokenMode, needRIDestroyToken, op,
          eventId, aCallbackArgument, pendingCallbacks, filterRoutingInfo, bridgeContext,
          isOriginRemote, txEntryState, versionTag, tailKey);
    } finally {
      if (inRI) {
        unlockRIReadLock();
      }
    }
  }

  /**
   * 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() + 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('/', '_'),
          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 == null) {
      return;
    }
    if (entryExpiryTasks.isEmpty()) {
      return;
    }
    boolean doPurge = false;
    for (EntryExpiryTask task : entryExpiryTasks.values()) {
      // 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();
    names.addAll(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 key = iterator.next();
          Object value;
          Region.Entry entry = accessEntry(key, true);
          if (entry != null && (value = entry.getValue()) != null) {
            allResults.put(key, value);
            iterator.remove();
          }
        }
        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 = CachePerfStats.getStatTime();
          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 = CachePerfStats.getStatTime();

    @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 = CachePerfStats.getStatTime();

    @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 = CachePerfStats.getStatTime();

    @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 = CachePerfStats.getStatTime();
    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 = CachePerfStats.getStatTime();
    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(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;
  }

  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.
   */
  private 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);
    }
  }

  private 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;
  }

  /**
   * This method determines whether this region should synchronize with peer replicated regions when
   * the given member has crashed.
   *
   * @param id the crashed member
   * @return true if synchronization should be attempted
   */
  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 = CachePerfStats.getStatTime();

    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 = CachePerfStats.getStatTime();
    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 = CachePerfStats.getStatTime();

    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 = CachePerfStats.getStatTime();

    @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 Version[] 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 = CachePerfStats.getStatTime();

    @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 = CachePerfStats.getStatTime();

    @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
  }

  /**
   * 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();
      }
    }
  }
}
