/*
 * 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.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.log4j.LogMarker;
import org.apache.geode.internal.offheap.OffHeapHelper;
import org.apache.geode.internal.offheap.ReferenceCountHelper;
import org.apache.geode.internal.offheap.Releasable;
import org.apache.geode.internal.offheap.StoredObject;
import org.apache.geode.internal.offheap.annotations.Released;
import org.apache.geode.internal.offheap.annotations.Retained;
import org.apache.geode.internal.offheap.annotations.Unretained;
import org.apache.geode.internal.sequencelog.EntryLogger;
import org.apache.geode.internal.serialization.Version;
import org.apache.geode.internal.statistics.StatisticsClock;
import org.apache.geode.internal.util.concurrent.CopyOnWriteHashMap;
import org.apache.geode.internal.util.concurrent.FutureResult;
import org.apache.geode.internal.util.concurrent.StoppableCountDownLatch;
import org.apache.geode.logging.internal.log4j.api.LogService;
import org.apache.geode.pdx.JSONFormatter;
import org.apache.geode.pdx.PdxInstance;

/**
 * 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,
      StatisticsClock statisticsClock) throws DiskAccessException {
    this(regionName, attrs, parentRegion, cache, internalRegionArgs, new LocalRegionDataView(),
        statisticsClock);
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    versionVector = createRegionVersionVector();
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  private final InternalDataView sharedDataView;

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

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

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

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

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

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

    dispatchListenerEvent(EnumListenerEvent.AFTER_REGION_LIVE, event);
  }

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

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

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

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

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

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

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

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

        validateSubregionAttributes(regionAttributes);

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

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

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

            Assert.assertTrue(previousValue == null);

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

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

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

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

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

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

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

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

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

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

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

    cache.invokeRegionAfter(newRegion);
    return newRegion;
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

    return result;
  }


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

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

  private final String fullPath;

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

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

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

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

    basicInvalidateRegion(event);
  }

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

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

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

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

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

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

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

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

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

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

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

  boolean isMemoryThresholdReachedForLoad() {
    return isMemoryThresholdReached();
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  /**
   * pass tombstone garbage-collection info to clients
   *
   * @param eventID the ID of the event
   * @param routing routing info (routing is computed if this is null)
   */
  void notifyClientsOfTombstoneGC(Map<VersionSource, Long> regionGCVersions,
      Set<Object> keysRemoved, EventID eventID, FilterInfo routing) {
    if (CacheClientNotifier.singletonHasClientProxies()) {
      // Only route the event to clients interested in the partitioned region.
      // We do this by constructing a region-level event and then use it to
      // have the filter profile ferret out all of the clients that have interest
      // in this region
      FilterProfile fp = getFilterProfile();
      if (fp != null || routing != null) {
        RegionEventImpl regionEvent =
            new RegionEventImpl(this, Operation.REGION_DESTROY, null, true, getMyId());
        regionEvent.setEventID(eventID);
        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 = getStatisticsClock().getTime();
    entries.txApplyPut(putOp, key, newValue, didDestroy, transactionId, event, eventId,
        aCallbackArgument, pendingCallbacks, filterRoutingInfo, bridgeContext, txEntryState,
        versionTag, tailKey);
    updateStatsForPut(startPut);
    // make sure we throw an exception if we skip the TX put because
    // the region is cleared (due to a destroy)
    checkReadiness();
  }

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

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

  public boolean basicBridgeCreate(final Object key, final byte[] value, boolean isObject,
      Object callbackArg, final ClientProxyMembershipID client, boolean fromClient,
      EntryEventImpl clientEvent, boolean throwEntryExists)
      throws TimeoutException, EntryExistsException, CacheWriterException {

    EventID eventId = clientEvent.getEventId();
    Object theCallbackArg = callbackArg;

    long startPut = getStatisticsClock().getTime();

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

    try {
      event.setContext(client);

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

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

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

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

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

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

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

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

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

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

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

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

      boolean success = false;

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

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

      clientEvent.isConcurrencyConflict(event.isConcurrencyConflict());

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

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

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

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

    if (isCacheContentProxy()) {
      return;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    try {
      event.setContext(memberId);

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

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

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

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

    event.setContext(memberId);

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

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

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

    getDataView().updateEntryVersion(event);
  }

  /**
   * 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(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 = getStatisticsClock().getTime();
          validateKey(key);

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

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

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

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

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

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

  private void verifyPutAllMap(Map map) {
    Collection theEntries = map.entrySet();
    for (Object theEntry : theEntries) {
      Map.Entry mapEntry = (Map.Entry) theEntry;
      Object key = mapEntry.getKey();
      if (mapEntry.getValue() == null || key == null) {
        throw new NullPointerException("Any key or value in putAll should not be null");
      }
      if (!MemoryThresholds.isLowMemoryExceptionDisabled()) {
        checkIfAboveThreshold(key);
      }
      // Threshold check should not be performed again
    }
  }

  private void verifyRemoveAllKeys(Collection<Object> keys) {
    for (Object key : keys) {
      if (key == null) {
        throw new NullPointerException("Any key in removeAll must not be null");
      }
    }
  }

  /**
   * Called on a cache server when it has a received a putAll command from a client.
   *
   * @param map a map of key->value for the entries we are putting
   * @param retryVersions a map of key->version tag. If any of the entries are the result of a
   *        retried client event, we need to make sure we send the original version tag along with
   *        the event.
   * @param callbackArg callback argument from client
   */
  public VersionedObjectList basicBridgePutAll(Map map, Map<Object, VersionTag> retryVersions,
      ClientProxyMembershipID memberId, EventID eventId, boolean skipCallbacks, Object callbackArg)
      throws TimeoutException, CacheWriterException {

    long startPut = getStatisticsClock().getTime();

    @Released
    final EntryEventImpl event =
        entryEventFactory.create(this, Operation.PUTALL_CREATE, null,
            null, callbackArg, false,
            memberId.getDistributedMember(), !skipCallbacks, eventId);

    try {
      event.setContext(memberId);
      DistributedPutAllOperation putAllOp = new DistributedPutAllOperation(event, map.size(), true);
      try {
        VersionedObjectList result = basicPutAll(map, putAllOp, retryVersions);
        getCachePerfStats().endPutAll(startPut);
        return result;
      } finally {
        putAllOp.freeOffHeapResources();
      }
    } finally {
      event.release();
    }
  }

  /**
   * Called on a cache server when it has a received a removeAll command from a client.
   *
   * @param keys a collection of the keys we are putting
   * @param retryVersions a collection of version tags. If the client is retrying a key then that
   *        keys slot will be non-null in this collection. Note that keys and retryVersions are
   *        parallel lists.
   * @param callbackArg callback argument from client
   */
  public VersionedObjectList basicBridgeRemoveAll(List<Object> keys,
      ArrayList<VersionTag> retryVersions, ClientProxyMembershipID memberId, EventID eventId,
      Object callbackArg) throws TimeoutException, CacheWriterException {

    long startOp = getStatisticsClock().getTime();

    @Released
    final EntryEventImpl event =
        entryEventFactory.create(this, Operation.REMOVEALL_DESTROY, null,
            null, callbackArg, false,
            memberId.getDistributedMember(), true, eventId);

    try {
      event.setContext(memberId);
      DistributedRemoveAllOperation removeAllOp =
          new DistributedRemoveAllOperation(event, keys.size(), true);
      try {
        VersionedObjectList result = basicRemoveAll(keys, removeAllOp, retryVersions);
        getCachePerfStats().endRemoveAll(startOp);
        return result;
      } finally {
        removeAllOp.freeOffHeapResources();
      }
    } finally {
      event.release();
    }
  }

  // TODO: return value is never used
  public VersionedObjectList basicImportPutAll(Map map, boolean skipCallbacks) {
    long startPut = getStatisticsClock().getTime();

    @Released
    EntryEventImpl event = entryEventFactory.create(this, Operation.PUTALL_CREATE, null, null, null,
        true, getMyId(), !skipCallbacks);

    try {
      DistributedPutAllOperation putAllOp =
          new DistributedPutAllOperation(event, map.size(), false);
      try {
        VersionedObjectList result = basicPutAll(map, putAllOp, null);
        getCachePerfStats().endPutAll(startPut);
        return result;
      } finally {
        putAllOp.freeOffHeapResources();
      }
    } finally {
      event.release();
    }
  }

  @Override
  public void putAll(Map map, Object aCallbackArgument) {
    long startPut = getStatisticsClock().getTime();
    final DistributedPutAllOperation putAllOp = newPutAllOperation(map, aCallbackArgument);
    if (putAllOp != null) {
      try {
        basicPutAll(map, putAllOp, null);
      } finally {
        putAllOp.getBaseEvent().release();
        putAllOp.freeOffHeapResources();
      }
    }

    getCachePerfStats().endPutAll(startPut);
  }

  @Override
  public void putAll(Map map) {
    putAll(map, null);
  }

  @Override
  public void removeAll(Collection keys) {
    removeAll(keys, null);
  }

  @Override
  public void removeAll(Collection keys, Object aCallbackArgument) {
    long startOp = getStatisticsClock().getTime();
    DistributedRemoveAllOperation operation = newRemoveAllOperation(keys, aCallbackArgument);
    if (operation != null) {
      try {
        basicRemoveAll(keys, operation, null);
      } finally {
        operation.getBaseEvent().release();
        operation.freeOffHeapResources();
      }
    }
    getCachePerfStats().endRemoveAll(startOp);
  }

  /**
   * Returns true if a one-hop (RemoteOperationMessage) should be used when applying the change to
   * the system.
   */
  boolean requiresOneHopForMissingEntry(EntryEventImpl event) {
    return false;
  }

  // TODO: refactor basicPutAll
  VersionedObjectList basicPutAll(final Map<?, ?> map,
      final DistributedPutAllOperation putAllOp, final Map<Object, VersionTag> retryVersions) {

    final boolean isDebugEnabled = logger.isDebugEnabled();
    final EntryEventImpl event = putAllOp.getBaseEvent();
    EventID eventId = event.getEventId();
    if (eventId == null && generateEventID()) {
      // We need to "reserve" the eventIds for the entries in map here
      event.reserveNewEventId(cache.getDistributedSystem(), map.size());
      eventId = event.getEventId();
    }

    verifyPutAllMap(map);
    VersionedObjectList proxyResult = null;
    boolean partialResult = false;
    RuntimeException runtimeException = null;
    if (hasServerProxy()) {
      // send message to cache server
      if (isTX()) {
        TXStateProxyImpl txState = (TXStateProxyImpl) cache.getTxManager().getTXState();
        txState.getRealDeal(null, this);
      }
      try {
        proxyResult = getServerProxy().putAll(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 = getStatisticsClock().getTime();

    checkIfConcurrentMapOpsAllowed();
    validateArguments(key, value, callbackArgument);

    // TODO ConcurrentMap.putIfAbsent() treats null as an invalidation operation
    // BUT we need to return the old value, which Invalidate isn't currently doing

    checkReadiness();
    checkForLimitedOrNoAccess();
    discoverJTA();

    // This used to call the constructor which took the old value. It
    // was modified to call the other EntryEventImpl constructor so that
    // an id will be generated by default. Null was passed in anyway.
    // generate EventID

    @Released
    EntryEventImpl event = entryEventFactory.create(this, Operation.PUT_IF_ABSENT, key, value,
        callbackArgument, false, getMyId());

    try {
      if (generateEventID()) {
        event.setNewEventId(cache.getDistributedSystem());
      }
      final Object oldValue = null;
      final boolean ifNew = true;
      final boolean ifOld = false;
      final boolean requireOldValue = true;
      if (!basicPut(event, ifNew, ifOld, oldValue, requireOldValue)) {
        return event.getOldValue();
      }
      if (!getDataView().isDeferredStats()) {
        getCachePerfStats().endPut(startPut, false);
      }
      return null;
    } catch (EntryNotFoundException ignore) {
      return event.getOldValue();
    } finally {
      event.release();
    }
  }

  @Override
  public Object putIfAbsent(Object key, Object value) {
    return putIfAbsent(key, value, null);
  }

  @Override
  public boolean remove(Object key, Object value) {
    return remove(key, value, null);
  }

  /**
   * Same as {@link #remove(Object, Object)} except a callback argument is supplied to be passed on
   * to <tt>CacheListener</tt>s and/or <tt>CacheWriter</tt>s.
   */
  public boolean remove(Object key, Object value, Object callbackArg) {
    checkIfConcurrentMapOpsAllowed();
    validateKey(key);
    checkReadiness();
    checkForLimitedOrNoAccess();

    if (value == null) {
      value = Token.INVALID;
    }

    @Released
    EntryEventImpl event =
        entryEventFactory.create(this, Operation.REMOVE, key, null, callbackArg, false, getMyId());

    try {
      if (generateEventID() && event.getEventId() == null) {
        event.setNewEventId(cache.getDistributedSystem());
      }
      discoverJTA();
      getDataView().destroyExistingEntry(event, true, value);

    } catch (EntryNotFoundException ignore) {
      return false;
    } catch (RegionDestroyedException rde) {
      if (!rde.getRegionFullPath().equals(getFullPath())) {
        // Handle when a bucket is destroyed
        throw new RegionDestroyedException(toString(), getFullPath(), rde);
      }
      throw rde;
    } finally {
      event.release();
    }
    return true;
  }

  @Override
  public boolean replace(Object key, Object oldValue, Object newValue) {
    return replace(key, oldValue, newValue, null);
  }

  /**
   * Same as {@link #replace(Object, Object, Object)} except a callback argument is supplied to be
   * passed on to <tt>CacheListener</tt>s and/or <tt>CacheWriter</tt>s.
   */
  private boolean replace(Object key, Object expectedOldValue, Object newValue,
      Object callbackArg) {
    checkIfConcurrentMapOpsAllowed();
    if (newValue == null) {
      throw new NullPointerException();
    }

    long startPut = getStatisticsClock().getTime();
    validateArguments(key, newValue, callbackArg);
    checkReadiness();
    checkForLimitedOrNoAccess();

    @Released
    EntryEventImpl event = entryEventFactory.create(this, Operation.REPLACE, key, newValue,
        callbackArg, false, getMyId());

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

      discoverJTA();

      // In general, expectedOldValue null is used when there is no particular
      // old value expected (it can be anything). Here, however, if null
      // is passed as expectedOldValue, then it specifically means that the
      // oldValue must actually be null (i.e. INVALID). So here we
      // change an expectedOldValue of null to the invalid token
      if (expectedOldValue == null) {
        expectedOldValue = Token.INVALID;
      }

      if (!basicPut(event, false, true, expectedOldValue, false)) {
        return false;
      }
      if (!getDataView().isDeferredStats()) {
        getCachePerfStats().endPut(startPut, false);
      }
      return true;

    } catch (EntryNotFoundException ignore) {
      // put failed on server
      return false;
    } finally {
      event.release();
    }
  }

  @Override
  public Object replace(Object key, Object value) {
    return replaceWithCallbackArgument(key, value, null);
  }

  /**
   * Same as {@link #replace(Object, Object)} except a callback argument is supplied to be passed on
   * to <tt>CacheListener</tt>s and/or <tt>CacheWriter</tt>s.
   * <p>
   * TODO: callbackArg is always null but this method is for callbacks??
   */
  private Object replaceWithCallbackArgument(Object key, Object value, Object callbackArg) {
    long startPut = getStatisticsClock().getTime();

    checkIfConcurrentMapOpsAllowed();

    if (value == null) {
      throw new NullPointerException();
    }

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

    @Released
    EntryEventImpl event =
        entryEventFactory.create(this, Operation.REPLACE, key, value, callbackArg, false,
            getMyId());

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

      discoverJTA();

      if (!basicPut(event, false, true, null, true)) {
        return null;
      }
      if (!getDataView().isDeferredStats()) {
        getCachePerfStats().endPut(startPut, false);
      }
      return event.getOldValue(); // may be null if was invalid

    } catch (EntryNotFoundException ignore) {
      // put failed on server
      return null;
    } finally {
      event.release();
    }
  }

  // TODO: fromClient is always null
  public Object basicBridgePutIfAbsent(final Object key, Object value, boolean isObject,
      Object callbackArg, final ClientProxyMembershipID client, boolean fromClient,
      EntryEventImpl clientEvent)
      throws TimeoutException, EntryExistsException, CacheWriterException {

    EventID eventId = clientEvent.getEventId();
    long startPut = getStatisticsClock().getTime();

    @Released
    final EntryEventImpl event =
        entryEventFactory.create(this, Operation.PUT_IF_ABSENT, key, null,
            callbackArg, false, client.getDistributedMember(), true, eventId);

    try {
      event.setContext(client);

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

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

      validateArguments(key, event.basicGetNewValue(), callbackArg);

      // cannot overwrite an existing key
      boolean ifNew = true;
      // can create a new key
      boolean ifOld = false;
      // need the old value if the create fails
      boolean requireOldValue = true;

      boolean basicPut = basicPut(event, ifNew, ifOld, null, requireOldValue);

      getCachePerfStats().endPut(startPut, false);
      stopper.checkCancelInProgress(null);

      Object oldValue = event.getRawOldValueAsHeapObject();
      if (oldValue == Token.NOT_AVAILABLE) {
        oldValue = AbstractRegion.handleNotAvailable(oldValue);
      }

      if (basicPut) {
        clientEvent.setVersionTag(event.getVersionTag());
        clientEvent.isConcurrencyConflict(event.isConcurrencyConflict());
      } else {
        if (oldValue == null) {
          // putIfAbsent on server can return null if the
          // operation was not performed (oldValue in cache was null).
          // We return the INVALID token instead of null to distinguish
          // this case from successful operation
          return Token.INVALID;
        }
      }
      return oldValue;
    } finally {
      event.release();
    }
  }

  @Override
  public 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 = getStatisticsClock().getTime();

    @Released
    final EntryEventImpl event =
        entryEventFactory.create(this, Operation.REPLACE, key, null,
            callbackArg, false, client.getDistributedMember(), true, eventId);

    try {
      event.setContext(client);

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

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

      validateArguments(key, event.basicGetNewValue(), callbackArg);

      // can overwrite an existing key
      boolean ifNew = false;
      // cannot create a new key
      boolean ifOld = true;
      boolean requireOldValue = false;

      boolean success = basicPut(event, ifNew, ifOld, expectedOldValue, requireOldValue);

      clientEvent.isConcurrencyConflict(event.isConcurrencyConflict());
      if (success) {
        clientEvent.setVersionTag(event.getVersionTag());
      }

      getCachePerfStats().endPut(startPut, false);
      stopper.checkCancelInProgress(null);

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

  // TODO: fromClient is always true
  public Object basicBridgeReplace(final Object key, Object value, boolean isObject,
      Object callbackArg, final ClientProxyMembershipID client, boolean fromClient,
      EntryEventImpl clientEvent)
      throws TimeoutException, EntryExistsException, CacheWriterException {

    EventID eventId = clientEvent.getEventId();
    long startPut = getStatisticsClock().getTime();

    @Released
    final EntryEventImpl event =
        entryEventFactory.create(this, Operation.REPLACE, key, null,
            callbackArg, false, client.getDistributedMember(), true, eventId);

    try {
      event.setContext(client);

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

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

      validateArguments(key, event.basicGetNewValue(), callbackArg);

      // can overwrite an existing key
      boolean ifNew = false;
      // cannot create a new key
      boolean ifOld = true;
      boolean requireOldValue = true;

      boolean succeeded = basicPut(event, ifNew, ifOld, null, requireOldValue);

      getCachePerfStats().endPut(startPut, false);
      stopper.checkCancelInProgress(null);

      clientEvent.isConcurrencyConflict(event.isConcurrencyConflict());
      if (succeeded) {
        clientEvent.setVersionTag(event.getVersionTag());
        Object oldValue = event.getRawOldValueAsHeapObject();
        if (oldValue == Token.NOT_AVAILABLE) {
          oldValue = AbstractRegion.handleNotAvailable(oldValue);
        }
        if (oldValue == null) {
          oldValue = Token.INVALID;
        }
        return oldValue;
      }
      return null;
    } finally {
      event.release();
    }
  }

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

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

    try {
      event.setContext(memberId);
      event.setVersionTag(clientEvent.getVersionTag());
      event.setPossibleDuplicate(clientEvent.isPossibleDuplicate());
      // we rely on exceptions to tell us that the operation didn't take
      // place. AbstractRegionMap performs the checks and throws the exception
      try {
        basicDestroy(event, true, expectedOldValue);
      } finally {
        clientEvent.setVersionTag(event.getVersionTag());
        clientEvent.setIsRedestroyedEntry(event.getIsRedestroyedEntry());
      }
    } finally {
      event.release();
    }
  }

  @Override
  public long getVersionForMember(VersionSource member) {
    throw new IllegalStateException("Operation only implemented for disk region");
  }

  /**
   * Return an IndexMap that is persisted to the disk store used by this region.
   *
   * This IndexMap should be used as the backing map for any regions that are using the Soplog
   * persistence.
   *
   * Calling this method may create a branch new index map on disk, or it may recover an index map
   * that was previously persisted, depending on whether the index previously existed.
   *
   * TODO: none of the parameters are ever used
   *
   * @param indexName the name of the index
   * @param indexedExpression the index expression
   * @param fromClause the from clause.
   * @return The index map.
   * @throws IllegalStateException if this region is not using soplog persistence
   * @throws IllegalStateException if this index was previously persisted with a different
   *         expression or from clause.
   */
  public IndexMap getIndexMap(String indexName, String indexedExpression, String fromClause) {
    return new IndexMapImpl();
  }

  @Override
  public void setInUseByTransaction(boolean value) {
    synchronized (regionExpiryLock) {
      if (value) {
        txRefCount++;
      } else {
        txRefCount--;
        assert txRefCount >= 0;
        if (txRefCount == 0) {
          if (regionTTLExpiryTask == null && regionTimeToLive > 0) {
            addTTLExpiryTask();
          }
          if (regionIdleExpiryTask == null && regionIdleTimeout > 0) {
            addIdleExpiryTask();
          }
        }
      }
    }
  }

  /**
   * Return true if the region expiry task should be rescheduled
   */
  boolean expireRegion(RegionExpiryTask regionExpiryTask, boolean distributed, boolean destroy) {
    synchronized (regionExpiryLock) {
      if (regionExpiryTask instanceof RegionTTLExpiryTask) {
        if (regionExpiryTask != regionTTLExpiryTask) {
          // We must be an old task so defer to the currently scheduled one
          return false;
        }
        regionTTLExpiryTask = null;
      } else {
        if (regionExpiryTask != regionIdleExpiryTask) {
          // We must be an old task so defer to the currently scheduled one
          return false;
        }
        regionIdleExpiryTask = null;
      }
      if (txRefCount > 0) {
        return false;
      }
    }
    // release the sync before doing the operation to prevent deadlock
    Operation op = destroy
        ? distributed ? Operation.REGION_EXPIRE_DESTROY : Operation.REGION_EXPIRE_LOCAL_DESTROY
        : distributed ? Operation.REGION_EXPIRE_INVALIDATE
            : Operation.REGION_EXPIRE_LOCAL_INVALIDATE;
    RegionEventImpl event =
        new RegionEventImpl(this, op, null, false, getMyId(), generateEventID());
    if (destroy) {
      basicDestroyRegion(event, distributed);
    } else {
      basicInvalidateRegion(event);
    }
    return true;
  }

  @VisibleForTesting
  public int testHookGetValuesInVM() {
    int result = 0;
    for (RegionEntry re : getRegionMap().regionEntries()) {
      if (re.getValueAsToken() == Token.NOT_A_TOKEN) {
        result++;
      }
    }
    return result;
  }

  @VisibleForTesting
  public int testHookGetValuesOnDisk() {
    int result = 0;
    for (RegionEntry re : getRegionMap().regionEntries()) {
      if (re.getValueAsToken() == null) {
        result++;
      }
    }
    return result;
  }

  /**
   * Send a message to all other members that can have this same region entry and return the latest
   * last access time.
   */
  long getLatestLastAccessTimeFromOthers(Object key) {
    // local regions have no other members so return 0.
    return 0L;
  }

  /**
   * Returns the number of LRU evictions done by this region.
   */
  @Override
  public long getTotalEvictions() {
    return entries.getEvictions();
  }

  void incBucketEvictions() {
    // nothing needed by default
    // override this method on BucketRegion
  }

  @Override
  public long getEvictionCounter() {
    long result = 0L;
    EvictionController evictionController = getEvictionController();
    if (evictionController != null) {
      EvictionCounters es = evictionController.getCounters();
      if (es != null) {
        result = es.getCounter();
      }
    }
    return result;
  }

  @VisibleForTesting
  public long getEvictionLimit() {
    long result = 0L;
    EvictionController evictionController = getEvictionController();
    if (evictionController != null) {
      EvictionCounters es = evictionController.getCounters();
      if (es != null) {
        result = es.getLimit();
      }
    }
    return result;
  }

  @VisibleForTesting
  public long getEvictionDestroys() {
    long result = 0;
    EvictionController evictionController = getEvictionController();
    if (evictionController != null) {
      EvictionCounters es = evictionController.getCounters();
      if (es != null) {
        result = es.getDestroys();
      }
    }
    return result;
  }

  @Override
  public EvictionController getEvictionController() {
    return getRegionMap().getEvictionController();
  }

  @Override
  public void setEvictionMaximum(int maximum) {
    EvictionController evictionController = getEvictionController();
    if (evictionController != null) {
      evictionController.setLimit(maximum);
    }
  }

  @Override
  public Statistics getEvictionStatistics() {
    Statistics result = null;
    EvictionController evictionController = getEvictionController();
    if (evictionController != null) {
      EvictionCounters es = evictionController.getCounters();
      if (es != null) {
        result = es.getStatistics();
      }
    }
    return result;
  }

  @Override
  public EvictionController getExistingController(InternalRegionArguments internalArgs) {
    return null;
  }

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

  @Override
  public Lock getClientMetaDataLock() {
    return clientMetaDataLock;
  }

  @VisibleForTesting
  public boolean isMemoryThresholdReached() {
    return memoryThresholdReached.get();
  }

  void setMemoryThresholdReached(boolean reached) {
    memoryThresholdReached.set(reached);
  }

  boolean isStatisticsEnabled() {
    return statisticsEnabled;
  }

  public enum IteratorType {
    KEYS, VALUES, ENTRIES
  }

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