/*
 * 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 java.lang.System.lineSeparator;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toSet;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Lock;

import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.NotNull;

import org.apache.geode.CancelException;
import org.apache.geode.InternalGemFireException;
import org.apache.geode.StatisticsFactory;
import org.apache.geode.SystemFailure;
import org.apache.geode.annotations.Immutable;
import org.apache.geode.annotations.VisibleForTesting;
import org.apache.geode.annotations.internal.MakeNotStatic;
import org.apache.geode.annotations.internal.MutableForTesting;
import org.apache.geode.cache.AttributesFactory;
import org.apache.geode.cache.AttributesMutator;
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.CacheStatistics;
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.EntryExistsException;
import org.apache.geode.cache.EntryNotFoundException;
import org.apache.geode.cache.ExpirationAttributes;
import org.apache.geode.cache.InterestPolicy;
import org.apache.geode.cache.InterestRegistrationEvent;
import org.apache.geode.cache.LoaderHelper;
import org.apache.geode.cache.LowMemoryException;
import org.apache.geode.cache.Operation;
import org.apache.geode.cache.PartitionAttributes;
import org.apache.geode.cache.PartitionResolver;
import org.apache.geode.cache.PartitionedRegionDistributionException;
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.RegionMembershipListener;
import org.apache.geode.cache.TimeoutException;
import org.apache.geode.cache.TransactionDataNotColocatedException;
import org.apache.geode.cache.TransactionDataRebalancedException;
import org.apache.geode.cache.TransactionException;
import org.apache.geode.cache.asyncqueue.AsyncEventQueue;
import org.apache.geode.cache.asyncqueue.internal.AsyncEventQueueImpl;
import org.apache.geode.cache.client.internal.ClientMetadataService;
import org.apache.geode.cache.execute.EmptyRegionFunctionException;
import org.apache.geode.cache.execute.Function;
import org.apache.geode.cache.execute.FunctionContext;
import org.apache.geode.cache.execute.FunctionException;
import org.apache.geode.cache.execute.FunctionService;
import org.apache.geode.cache.execute.ResultCollector;
import org.apache.geode.cache.partition.PartitionListener;
import org.apache.geode.cache.partition.PartitionNotAvailableException;
import org.apache.geode.cache.partition.PartitionRegionHelper;
import org.apache.geode.cache.persistence.PartitionOfflineException;
import org.apache.geode.cache.persistence.PersistentID;
import org.apache.geode.cache.query.FunctionDomainException;
import org.apache.geode.cache.query.Index;
import org.apache.geode.cache.query.IndexCreationException;
import org.apache.geode.cache.query.IndexExistsException;
import org.apache.geode.cache.query.IndexInvalidException;
import org.apache.geode.cache.query.IndexNameConflictException;
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.QueryInvocationTargetException;
import org.apache.geode.cache.query.SelectResults;
import org.apache.geode.cache.query.TypeMismatchException;
import org.apache.geode.cache.query.internal.Bag;
import org.apache.geode.cache.query.internal.CompiledSelect;
import org.apache.geode.cache.query.internal.DefaultQuery;
import org.apache.geode.cache.query.internal.ExecutionContext;
import org.apache.geode.cache.query.internal.QCompiler;
import org.apache.geode.cache.query.internal.QueryExecutor;
import org.apache.geode.cache.query.internal.ResultsBag;
import org.apache.geode.cache.query.internal.ResultsCollectionWrapper;
import org.apache.geode.cache.query.internal.ResultsSet;
import org.apache.geode.cache.query.internal.index.AbstractIndex;
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.IndexUtils;
import org.apache.geode.cache.query.internal.index.PartitionedIndex;
import org.apache.geode.cache.query.internal.types.ObjectTypeImpl;
import org.apache.geode.cache.query.types.ObjectType;
import org.apache.geode.cache.wan.GatewaySender;
import org.apache.geode.distributed.DistributedLockService;
import org.apache.geode.distributed.DistributedMember;
import org.apache.geode.distributed.DistributedSystemDisconnectedException;
import org.apache.geode.distributed.LockServiceDestroyedException;
import org.apache.geode.distributed.internal.DistributionAdvisee;
import org.apache.geode.distributed.internal.DistributionAdvisor;
import org.apache.geode.distributed.internal.DistributionAdvisor.Profile;
import org.apache.geode.distributed.internal.DistributionConfig;
import org.apache.geode.distributed.internal.DistributionManager;
import org.apache.geode.distributed.internal.FunctionExecutionPooledExecutor;
import org.apache.geode.distributed.internal.InternalDistributedSystem;
import org.apache.geode.distributed.internal.InternalDistributedSystem.DisconnectListener;
import org.apache.geode.distributed.internal.MembershipListener;
import org.apache.geode.distributed.internal.OperationExecutors;
import org.apache.geode.distributed.internal.ProfileListener;
import org.apache.geode.distributed.internal.ReplyException;
import org.apache.geode.distributed.internal.ReplyProcessor21;
import org.apache.geode.distributed.internal.ResourceEvent;
import org.apache.geode.distributed.internal.locks.DLockRemoteToken;
import org.apache.geode.distributed.internal.locks.DLockService;
import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
import org.apache.geode.distributed.internal.membership.api.MemberDataBuilder;
import org.apache.geode.internal.Assert;
import org.apache.geode.internal.NanoTimer;
import org.apache.geode.internal.cache.BucketAdvisor.ServerBucketProfile;
import org.apache.geode.internal.cache.CacheDistributionAdvisor.CacheProfile;
import org.apache.geode.internal.cache.DestroyPartitionedRegionMessage.DestroyPartitionedRegionResponse;
import org.apache.geode.internal.cache.PutAllPartialResultException.PutAllPartialResult;
import org.apache.geode.internal.cache.control.InternalResourceManager.ResourceType;
import org.apache.geode.internal.cache.control.MemoryEvent;
import org.apache.geode.internal.cache.eviction.EvictionController;
import org.apache.geode.internal.cache.eviction.HeapEvictor;
import org.apache.geode.internal.cache.execute.AbstractExecution;
import org.apache.geode.internal.cache.execute.BucketMovedException;
import org.apache.geode.internal.cache.execute.FunctionExecutionNodePruner;
import org.apache.geode.internal.cache.execute.FunctionRemoteContext;
import org.apache.geode.internal.cache.execute.InternalFunctionInvocationTargetException;
import org.apache.geode.internal.cache.execute.LocalResultCollector;
import org.apache.geode.internal.cache.execute.PartitionedRegionFunctionExecutor;
import org.apache.geode.internal.cache.execute.PartitionedRegionFunctionResultSender;
import org.apache.geode.internal.cache.execute.PartitionedRegionFunctionResultWaiter;
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.ContainsKeyValueMessage;
import org.apache.geode.internal.cache.partitioned.ContainsKeyValueMessage.ContainsKeyValueResponse;
import org.apache.geode.internal.cache.partitioned.DestroyMessage;
import org.apache.geode.internal.cache.partitioned.DestroyMessage.DestroyResponse;
import org.apache.geode.internal.cache.partitioned.DumpAllPRConfigMessage;
import org.apache.geode.internal.cache.partitioned.DumpB2NRegion;
import org.apache.geode.internal.cache.partitioned.DumpB2NRegion.DumpB2NResponse;
import org.apache.geode.internal.cache.partitioned.DumpBucketsMessage;
import org.apache.geode.internal.cache.partitioned.FetchBulkEntriesMessage;
import org.apache.geode.internal.cache.partitioned.FetchBulkEntriesMessage.FetchBulkEntriesResponse;
import org.apache.geode.internal.cache.partitioned.FetchEntriesMessage;
import org.apache.geode.internal.cache.partitioned.FetchEntriesMessage.FetchEntriesResponse;
import org.apache.geode.internal.cache.partitioned.FetchEntryMessage;
import org.apache.geode.internal.cache.partitioned.FetchEntryMessage.FetchEntryResponse;
import org.apache.geode.internal.cache.partitioned.FetchKeysMessage;
import org.apache.geode.internal.cache.partitioned.FetchKeysMessage.FetchKeysResponse;
import org.apache.geode.internal.cache.partitioned.GetMessage;
import org.apache.geode.internal.cache.partitioned.GetMessage.GetResponse;
import org.apache.geode.internal.cache.partitioned.IdentityRequestMessage;
import org.apache.geode.internal.cache.partitioned.IdentityRequestMessage.IdentityResponse;
import org.apache.geode.internal.cache.partitioned.IdentityUpdateMessage;
import org.apache.geode.internal.cache.partitioned.IdentityUpdateMessage.IdentityUpdateResponse;
import org.apache.geode.internal.cache.partitioned.IndexCreationMsg;
import org.apache.geode.internal.cache.partitioned.InterestEventMessage;
import org.apache.geode.internal.cache.partitioned.InterestEventMessage.InterestEventResponse;
import org.apache.geode.internal.cache.partitioned.InvalidateMessage;
import org.apache.geode.internal.cache.partitioned.InvalidateMessage.InvalidateResponse;
import org.apache.geode.internal.cache.partitioned.PREntriesIterator;
import org.apache.geode.internal.cache.partitioned.PRLocallyDestroyedException;
import org.apache.geode.internal.cache.partitioned.PRSanityCheckMessage;
import org.apache.geode.internal.cache.partitioned.PRUpdateEntryVersionMessage;
import org.apache.geode.internal.cache.partitioned.PRUpdateEntryVersionMessage.UpdateEntryVersionResponse;
import org.apache.geode.internal.cache.partitioned.PartitionMessage.PartitionResponse;
import org.apache.geode.internal.cache.partitioned.PartitionedRegionObserver;
import org.apache.geode.internal.cache.partitioned.PartitionedRegionObserverHolder;
import org.apache.geode.internal.cache.partitioned.PutAllPRMessage;
import org.apache.geode.internal.cache.partitioned.PutMessage;
import org.apache.geode.internal.cache.partitioned.PutMessage.PutResult;
import org.apache.geode.internal.cache.partitioned.RegionAdvisor;
import org.apache.geode.internal.cache.partitioned.RegionAdvisor.PartitionProfile;
import org.apache.geode.internal.cache.partitioned.RemoveAllPRMessage;
import org.apache.geode.internal.cache.partitioned.RemoveIndexesMessage;
import org.apache.geode.internal.cache.partitioned.SizeMessage;
import org.apache.geode.internal.cache.partitioned.SizeMessage.SizeResponse;
import org.apache.geode.internal.cache.partitioned.colocation.ColocationLogger;
import org.apache.geode.internal.cache.partitioned.colocation.ColocationLoggerFactory;
import org.apache.geode.internal.cache.persistence.PRPersistentConfig;
import org.apache.geode.internal.cache.tier.InterestType;
import org.apache.geode.internal.cache.tier.sockets.BaseCommand;
import org.apache.geode.internal.cache.tier.sockets.ClientProxyMembershipID;
import org.apache.geode.internal.cache.tier.sockets.ServerConnection;
import org.apache.geode.internal.cache.tier.sockets.VersionedObjectList;
import org.apache.geode.internal.cache.versions.ConcurrentCacheModificationException;
import org.apache.geode.internal.cache.versions.RegionVersionVector;
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.cache.wan.AbstractGatewaySenderEventProcessor;
import org.apache.geode.internal.cache.wan.AsyncEventQueueConfigurationException;
import org.apache.geode.internal.cache.wan.GatewaySenderConfigurationException;
import org.apache.geode.internal.cache.wan.GatewaySenderException;
import org.apache.geode.internal.cache.wan.parallel.ConcurrentParallelGatewaySenderQueue;
import org.apache.geode.internal.cache.wan.parallel.ParallelGatewaySenderQueue;
import org.apache.geode.internal.logging.log4j.LogMarker;
import org.apache.geode.internal.offheap.annotations.Released;
import org.apache.geode.internal.offheap.annotations.Unretained;
import org.apache.geode.internal.sequencelog.RegionLogger;
import org.apache.geode.internal.size.Sizeable;
import org.apache.geode.internal.statistics.StatisticsClock;
import org.apache.geode.internal.util.TransformUtils;
import org.apache.geode.internal.util.concurrent.StoppableCountDownLatch;
import org.apache.geode.logging.internal.executors.LoggingExecutors;
import org.apache.geode.logging.internal.log4j.api.LogService;
import org.apache.geode.util.internal.GeodeGlossary;

/**
 * A Region whose total storage is split into chunks of data (partitions) which are copied up to a
 * configurable level (for high availability) and placed on multiple VMs for improved performance
 * and increased storage capacity.
 */
public class PartitionedRegion extends LocalRegion
    implements CacheDistributionAdvisee, QueryExecutor {

  @Immutable
  public static final Random RANDOM =
      new Random(Long.getLong(GeodeGlossary.GEMFIRE_PREFIX + "PartitionedRegionRandomSeed",
          NanoTimer.getTime()));

  @MakeNotStatic
  private static final AtomicInteger SERIAL_NUMBER_GENERATOR = new AtomicInteger();

  /**
   * getNetworkHopType byte indicating this was the bucket owner for the last operation
   */
  public static final int NETWORK_HOP_NONE = 0;

  /**
   * getNetworkHopType byte indicating this was not the bucket owner and a message had to be sent to
   * a primary in the same server group
   */
  private static final int NETWORK_HOP_TO_SAME_GROUP = 1;

  /**
   * getNetworkHopType byte indicating this was not the bucket owner and a message had to be sent to
   * a primary in a different server group
   */
  public static final int NETWORK_HOP_TO_DIFFERENT_GROUP = 2;
  public static final String DATA_MOVED_BY_REBALANCE =
      "Transactional data moved, due to rebalancing.";

  private final DiskRegionStats diskRegionStats;

  /**
   * Changes scope of replication to secondary bucket to SCOPE.DISTRIBUTED_NO_ACK
   */
  static final boolean DISABLE_SECONDARY_BUCKET_ACK =
      Boolean.getBoolean(GeodeGlossary.GEMFIRE_PREFIX + "disablePartitionedRegionBucketAck");

  /**
   * A debug flag used for testing calculation of starting bucket id
   */
  @MutableForTesting
  public static boolean BEFORE_CALCULATE_STARTING_BUCKET_FLAG = false;

  /**
   * Thread specific random number
   */
  private static final ThreadLocal threadRandom = new ThreadLocal() {
    @Override
    protected Object initialValue() {
      int i = RANDOM.nextInt();
      if (i < 0) {
        i = -1 * i;
      }
      return i;
    }
  };

  /**
   * Global Region for storing PR config ( PRName->PRConfig). This region would be used to resolve
   * PR name conflict.*
   */
  private volatile Region<String, PartitionRegionConfig> prRoot;

  /**
   *
   * PartitionedRegionDataStore class takes care of data storage for the PR. This will contain the
   * bucket Regions to store data entries for PR*
   */
  protected PartitionedRegionDataStore dataStore;

  /**
   * The advisor that hold information about this partitioned region
   */
  private final RegionAdvisor distAdvisor;
  private final SenderIdMonitor senderIdMonitor;

  /** Logging mechanism for debugging */
  private static final Logger logger = LogService.getLogger();

  /** cleanup flags * */
  private boolean cleanPRRegistration = false;

  /** Time to wait for for acquiring distributed lock ownership */
  private static final long VM_OWNERSHIP_WAIT_TIME = PRSystemPropertyGetter.parseLong(
      System.getProperty(PartitionedRegionHelper.VM_OWNERSHIP_WAIT_TIME_PROPERTY),
      PartitionedRegionHelper.VM_OWNERSHIP_WAIT_TIME_DEFAULT);

  /**
   * default redundancy level is 0.
   */
  final int redundantCopies;

  /**
   * The miminum amount of redundancy needed for a write operation
   */
  final int minimumWriteRedundancy;

  /**
   * The miminum amount of redundancy needed for a read operation
   */
  final int minimumReadRedundancy;

  /**
   * Ratio of currently allocated memory to maxMemory that triggers rebalance activity.
   */
  static final float rebalanceThreshold = 0.75f;

  /** The maximum memory allocated for this node in Mb */
  final int localMaxMemory;

  /** The maximum milliseconds for retrying operations */
  private final int retryTimeout;

  /**
   * The statistics for this PR
   */
  public final PartitionedRegionStats prStats;

  // private Random random = new Random(System.currentTimeMillis());

  /** Number of initial buckets */
  private final int totalNumberOfBuckets;

  // private static final boolean throwIfNoNodesLeft = true;

  public static final int DEFAULT_RETRY_ITERATIONS = 3;

  /**
   * Flag to indicate if a cache loader is present
   */
  private volatile boolean haveCacheLoader;

  /**
   * Region identifier used for DLocks (Bucket and Region)
   */
  private final String regionIdentifier;

  /**
   * Maps each PR to a prId. This prId will uniquely identify the PR.
   */
  @MakeNotStatic
  private static final PRIdMap prIdToPR = new PRIdMap();

  /**
   * Flag to indicate whether region is closed
   *
   */
  public volatile boolean isClosed = false;

  /**
   * a flag indicating that the PR is destroyed in this VM
   */
  public volatile boolean isLocallyDestroyed = false;

  /**
   * the thread locally destroying this pr. not volatile, so always check isLocallyDestroyed before
   * checking locallyDestroyingThread
   *
   * Concurrency: {@link #isLocallyDestroyed} is volatile
   */
  Thread locallyDestroyingThread;

  // TODO someone please add a javadoc for this
  private volatile boolean hasPartitionedIndex = false;

  /**
   * regionMembershipListener notification requires this to be plugged into a PR's RegionAdvisor
   */
  private final AdvisorListener advisorListener = new AdvisorListener();

  /*
   * Map containing <IndexTask, FutureTask<IndexTask> or Index>. IndexTask represents an index thats
   * completely created or one thats in create phase. This is done in order to avoid synchronization
   * on the indexes.
   */
  private final ConcurrentMap indexes = new ConcurrentHashMap();

  private volatile boolean recoveredFromDisk;

  public static final int RUNNING_MODE = -1;
  public static final int PRIMARY_BUCKETS_LOCKED = 1;
  public static final int DISK_STORE_FLUSHED = 2;
  public static final int OFFLINE_EQUAL_PERSISTED = 3;

  private volatile int shutDownAllStatus = RUNNING_MODE;

  private final long birthTime = System.currentTimeMillis();

  public void setShutDownAllStatus(int newStatus) {
    shutDownAllStatus = newStatus;
  }

  private final PartitionedRegion colocatedWithRegion;

  private final ColocationLoggerFactory colocationLoggerFactory;

  private final AtomicReference<ColocationLogger> missingColocatedRegionLogger =
      new AtomicReference<>();

  private List<BucketRegion> sortedBuckets;

  private ScheduledExecutorService bucketSorter;

  private final ConcurrentMap<String, Integer[]> partitionsMap = new ConcurrentHashMap<>();

  public ConcurrentMap<String, Integer[]> getPartitionsMap() {
    return partitionsMap;
  }

  /**
   * for wan shadowPR
   */
  private boolean enableConflation;

  private final Object indexLock = new Object();

  private final Set<ColocationListener> colocationListeners = ConcurrentHashMap.newKeySet();

  public void addColocationListener(ColocationListener colocationListener) {
    if (colocationListener != null) {
      colocationListeners.add(colocationListener);
    }
  }

  public void removeColocationListener(ColocationListener colocationListener) {
    colocationListeners.remove(colocationListener);
  }

  ScheduledExecutorService getBucketSorter() {
    return bucketSorter;
  }

  @VisibleForTesting
  public static PRIdMap getPrIdToPR() {
    return prIdToPR;
  }

  /**
   * Byte 0 = no NWHOP Byte 1 = NWHOP to servers in same server-grp Byte 2 = NWHOP tp servers in
   * other server-grp
   */
  private static final ThreadLocal<Byte> networkHopType = new ThreadLocal<Byte>() {
    @Override
    protected Byte initialValue() {
      return (byte) NETWORK_HOP_NONE;
    }
  };

  public void clearNetworkHopData() {
    networkHopType.remove();
    metadataVersion.remove();
  }

  private void setNetworkHopType(Byte value) {
    networkHopType.set(value);
  }

  /**
   * If the last operation in the current thread required a one-hop to another server who held the
   * primary bucket for the operation then this will return something other than NETWORK_HOP_NONE.
   * <p>
   * see NETWORK_HOP_NONE, NETWORK_HOP_TO_SAME_GROUP and NETWORK_HOP_TO_DIFFERENT_GROUP
   */
  public byte getNetworkHopType() {
    return networkHopType.get();
  }

  private static final ThreadLocal<Byte> metadataVersion = new ThreadLocal<Byte>() {
    @Override
    protected Byte initialValue() {
      return ClientMetadataService.INITIAL_VERSION;
    }
  };

  private void setMetadataVersion(Byte value) {
    metadataVersion.set(value);
  }

  public byte getMetadataVersion() {
    return metadataVersion.get();
  }

  /**
   * Returns the EvictionController for this PR. This is needed to find the single instance of
   * EvictionController created early for a PR when it is recovered from disk. This fixes bug 41938
   */
  public EvictionController getPREvictionControllerFromDiskInitialization() {
    EvictionController result = null;
    if (getDiskStore() != null) {
      result = getDiskStore().getExistingPREvictionContoller(this);
    }
    return result;
  }

  @Override
  public boolean remove(Object key, Object value, Object callbackArg) {
    final long startTime = prStats.getTime();
    try {
      return super.remove(key, value, callbackArg);
    } finally {
      prStats.endDestroy(startTime);
    }
  }

  public PartitionListener[] getPartitionListeners() {
    return partitionListeners;
  }

  /**
   * Return canonical representation for a bucket (for logging)
   *
   * @param bucketId the bucket
   * @return a String representing this PR and the bucket
   */
  public String bucketStringForLogs(int bucketId) {
    return getPRId() + BUCKET_ID_SEPARATOR + bucketId;
  }

  /** Separator between PRId and bucketId for creating bucketString */
  public static final String BUCKET_ID_SEPARATOR = ":";

  /**
   * Clear the prIdMap, typically used when disconnecting from the distributed system or clearing
   * the cache
   */
  public static void clearPRIdMap() {
    synchronized (prIdToPR) {
      prIdToPR.clear();
    }
  }

  @Immutable
  private static final DisconnectListener dsPRIdCleanUpListener = new DisconnectListener() {
    @Override
    public String toString() {
      return "Shutdown listener for PartitionedRegion";
    }

    @Override
    public void onDisconnect(InternalDistributedSystem sys) {
      clearPRIdMap();
    }
  };

  PartitionedRegionRedundancyTracker getRedundancyTracker() {
    return redundancyTracker;
  }

  public <T> T computeWithPrimaryLocked(Object key, Callable<T> callable) throws Exception {
    int bucketId = PartitionedRegionHelper.getHashKey(this, null, key, null, null);

    BucketRegion br;
    try {
      br = dataStore.getInitializedBucketForId(key, bucketId);
    } catch (ForceReattemptException e) {
      throw new BucketMovedException(e);
    }

    try {
      br.doLockForPrimary(false);
    } catch (PrimaryBucketException e) {
      throw new PrimaryBucketLockException("retry since primary lock failed: " + e);
    }

    try {
      return callable.call();
    } finally {
      br.doUnlockForPrimary();
    }
  }


  public static class PRIdMap extends HashMap {
    private static final long serialVersionUID = 3667357372967498179L;
    public static final String DESTROYED = "Partitioned Region Destroyed";

    static final String LOCALLY_DESTROYED = "Partitioned Region Is Locally Destroyed";

    static final String FAILED_REGISTRATION = "Partitioned Region's Registration Failed";

    public static final String NO_PATH_FOUND = "NoPathFound";

    private volatile boolean cleared = true;

    @Override
    public Object get(Object key) {
      throw new UnsupportedOperationException(
          "PRIdMap.get not supported - use getRegion instead");
    }

    public Object getRegion(Object key) throws PRLocallyDestroyedException {
      Assert.assertTrue(key instanceof Integer);

      Object o = super.get(key);
      if (o == DESTROYED) {
        throw new RegionDestroyedException(
            String.format("Region for prId= %s is destroyed",
                key),
            NO_PATH_FOUND);
      }
      if (o == LOCALLY_DESTROYED) {
        throw new PRLocallyDestroyedException(
            String.format("Region with prId= %s is locally destroyed on this node",
                key));
      }
      if (o == FAILED_REGISTRATION) {
        throw new PRLocallyDestroyedException(
            String.format("Region with prId= %s failed initialization on this node",
                key));
      }
      return o;
    }

    @Override
    public Object remove(final Object key) {
      return put(key, DESTROYED, true);
    }

    @Override
    public Object put(final Object key, final Object value) {
      return put(key, value, true);
    }

    public Object put(final Object key, final Object value, boolean sendIdentityRequestMessage) {
      if (cleared) {
        cleared = false;
      }

      if (key == null) {
        throw new NullPointerException(
            "null key not allowed for prIdToPR Map");
      }
      if (value == null) {
        throw new NullPointerException(
            "null value not allowed for prIdToPR Map");
      }
      Assert.assertTrue(key instanceof Integer);
      if (sendIdentityRequestMessage) {
        IdentityRequestMessage.setLatestId((Integer) key);
      }
      if ((super.get(key) == DESTROYED) && (value instanceof PartitionedRegion)) {
        throw new PartitionedRegionException(
            String.format("Can NOT reuse old Partitioned Region Id= %s",
                key));
      }
      return super.put(key, value);
    }

    @Override
    public void clear() {
      cleared = true;
      super.clear();
    }

    public synchronized String dump() {
      StringBuilder sb = new StringBuilder("prIdToPR Map@");
      sb.append(System.identityHashCode(prIdToPR)).append(':').append(lineSeparator());
      Map.Entry mapEntry;
      for (Iterator iterator = prIdToPR.entrySet().iterator(); iterator.hasNext();) {
        mapEntry = (Map.Entry) iterator.next();
        sb.append(mapEntry.getKey()).append("=>").append(mapEntry.getValue());
        if (iterator.hasNext()) {
          sb.append(lineSeparator());
        }
      }
      return sb.toString();
    }
  }

  private int partitionedRegionId = -3;

  /** Node description */
  private final Node node;

  /** Helper Object for redundancy Management of PartitionedRegion */
  private final PRHARedundancyProvider redundancyProvider;

  /**
   * flag saying whether this VM needs cache operation notifications from other members
   */
  private boolean requiresNotification;

  /**
   * Latch that signals when the Bucket meta-data is ready to receive updates
   */
  private final StoppableCountDownLatch initializationLatchAfterBucketIntialization;

  public static final String RETRY_TIMEOUT_PROPERTY =
      GeodeGlossary.GEMFIRE_PREFIX + "partitionedRegionRetryTimeout";

  private final PartitionRegionConfigValidator validator;

  final List<FixedPartitionAttributesImpl> fixedPAttrs;

  private byte fixedPASet;

  private final List<PartitionedRegion> colocatedByList =
      new CopyOnWriteArrayList<>();

  private final PartitionListener[] partitionListeners;

  private boolean isShadowPR = false;

  private AbstractGatewaySender parallelGatewaySender = null;

  private final PartitionedRegionRedundancyTracker redundancyTracker;

  private boolean regionCreationNotified;

  public interface RegionAdvisorFactory {
    RegionAdvisor create(PartitionedRegion region);
  }

  /**
   * Constructor for a PartitionedRegion. This has an accessor (Region API) functionality and
   * contains a datastore for actual storage. An accessor can act as a local cache by having a local
   * storage enabled. A PartitionedRegion can be created by a factory method of RegionFactory.java
   * and also by invoking Cache.createRegion(). (Cache.xml etc to be added)
   */
  public PartitionedRegion(String regionName,
      RegionAttributes regionAttributes,
      LocalRegion parentRegion,
      InternalCache cache,
      InternalRegionArguments internalRegionArgs,
      StatisticsClock statisticsClock,
      ColocationLoggerFactory colocationLoggerFactory) {
    this(regionName, regionAttributes, parentRegion, cache, internalRegionArgs, statisticsClock,
        colocationLoggerFactory,
        region -> RegionAdvisor.createRegionAdvisor(region));
  }

  PartitionedRegion(String regionName,
      RegionAttributes regionAttributes,
      LocalRegion parentRegion,
      InternalCache cache,
      InternalRegionArguments internalRegionArgs,
      StatisticsClock statisticsClock,
      ColocationLoggerFactory colocationLoggerFactory,
      RegionAdvisorFactory regionAdvisorFactory) {

    super(regionName, regionAttributes, parentRegion, cache, internalRegionArgs,
        new PartitionedRegionDataView(), statisticsClock);

    this.colocationLoggerFactory = colocationLoggerFactory;
    node = initializeNode();
    prStats = new PartitionedRegionStats(cache.getDistributedSystem(), getFullPath(),
        statisticsClock);
    regionIdentifier = getFullPath().replace(Region.SEPARATOR_CHAR, '#');

    if (logger.isDebugEnabled()) {
      logger.debug("Constructing Partitioned Region {}", regionName);
    }

    // By adding this disconnect listener we ensure that the pridmap is cleaned
    // up upon
    // distributed system disconnect even this (or other) PRs are destroyed
    // (which prevents pridmap cleanup).
    cache.getInternalDistributedSystem().addDisconnectListener(dsPRIdCleanUpListener);

    partitionAttributes = regionAttributes.getPartitionAttributes();
    localMaxMemory = partitionAttributes.getLocalMaxMemory();
    retryTimeout = Integer.getInteger(RETRY_TIMEOUT_PROPERTY,
        PartitionedRegionHelper.DEFAULT_TOTAL_WAIT_RETRY_ITERATION);
    totalNumberOfBuckets = partitionAttributes.getTotalNumBuckets();
    prStats.incTotalNumBuckets(totalNumberOfBuckets);

    // Warning: potential early escape of instance
    distAdvisor = regionAdvisorFactory.create(this);
    senderIdMonitor = createSenderIdMonitor();
    // Warning: potential early escape of instance
    redundancyProvider = new PRHARedundancyProvider(this, cache.getInternalResourceManager());

    // localCacheEnabled = ra.getPartitionAttributes().isLocalCacheEnabled();
    // This is to make sure that local-cache get and put works properly.
    // getScope is overridden to return the correct scope.
    // this.scope = Scope.LOCAL;
    redundantCopies = regionAttributes.getPartitionAttributes().getRedundantCopies();
    redundancyTracker = new PartitionedRegionRedundancyTracker(totalNumberOfBuckets,
        redundantCopies, prStats, getFullPath());
    prStats.setConfiguredRedundantCopies(
        regionAttributes.getPartitionAttributes().getRedundantCopies());
    prStats.setLocalMaxMemory(
        regionAttributes.getPartitionAttributes().getLocalMaxMemory() * 1024L * 1024);

    // No redundancy required for writes
    minimumWriteRedundancy = Integer.getInteger(
        GeodeGlossary.GEMFIRE_PREFIX + "mimimumPartitionedRegionWriteRedundancy", 0);

    // No redundancy required for reads
    minimumReadRedundancy = Integer.getInteger(
        GeodeGlossary.GEMFIRE_PREFIX + "mimimumPartitionedRegionReadRedundancy", 0);

    haveCacheLoader = regionAttributes.getCacheLoader() != null;

    initializationLatchAfterBucketIntialization =
        new StoppableCountDownLatch(getCancelCriterion(), 1);

    validator = new PartitionRegionConfigValidator(this);
    partitionListeners = partitionAttributes.getPartitionListeners();

    colocatedWithRegion = ColocationHelper.getColocatedRegion(this);

    if (colocatedWithRegion != null) {
      colocatedWithRegion.getColocatedByList().add(this);
    }

    if (colocatedWithRegion != null && !internalRegionArgs.isUsedForParallelGatewaySenderQueue()) {
      // In a colocation chain, the child region inherits the fixed partition attributes from parent
      // region.
      fixedPAttrs = colocatedWithRegion.getFixedPartitionAttributesImpl();
      fixedPASet = colocatedWithRegion.fixedPASet;
    } else {
      fixedPAttrs = partitionAttributes.getFixedPartitionAttributes();
      fixedPASet = 0;
    }

    if (logger.isDebugEnabled()) {
      logger.debug("Partitioned Region {} constructed {}", regionName,
          (haveCacheLoader ? "with a cache loader" : ""));
    }
    if (getEvictionAttributes() != null
        && getEvictionAttributes().getAlgorithm().isLRUHeap()) {
      sortedBuckets = new ArrayList<>();
      bucketSorter = LoggingExecutors.newScheduledThreadPool(1, "BucketSorterThread");
    }
    // If eviction is on, Create an instance of PartitionedRegionLRUStatistics
    if ((getEvictionAttributes() != null
        && !getEvictionAttributes().getAlgorithm().isNone()
        && getEvictionAttributes().getAction().isOverflowToDisk())
        || getDataPolicy().withPersistence()) {
      StatisticsFactory sf = getCache().getDistributedSystem();
      diskRegionStats = new DiskRegionStats(sf, getFullPath());
    } else {
      diskRegionStats = null;
    }
    if (internalRegionArgs.isUsedForParallelGatewaySenderQueue()) {
      isShadowPR = true;
      parallelGatewaySender = internalRegionArgs.getParallelGatewaySender();
    }
    regionCreationNotified = false;

    /*
     * Start persistent profile logging if we are a persistent region.
     */
    if (getDataPolicy().withPersistence()) {
      startPersistenceProfileLogging();
    }
  }

  /**
   * Monitors when other members that participate in this persistent region are removed and creates
   * a log entry marking the event.
   */
  private void startPersistenceProfileLogging() {
    distAdvisor.addProfileChangeListener(new ProfileListener() {
      @Override
      public void profileCreated(Profile profile) {}

      @Override
      public void profileUpdated(Profile profile) {}

      @Override
      public void profileRemoved(Profile profile, boolean destroyed) {
        /*
         * Don't bother logging membership activity if our region isn't ready.
         */
        if (isInitialized()) {
          CacheProfile cacheProfile = (CacheProfile) profile;
          Set<String> onlineMembers = new HashSet<>();

          TransformUtils.transform(
              distAdvisor.advisePersistentMembers().values(), onlineMembers,
              TransformUtils.persistentMemberIdToLogEntryTransformer);

          logger
              .info(
                  "The following persistent member has gone offline for region {}:{}.  Remaining participating members for the region include: {}",
                  new Object[] {getName(),
                      TransformUtils.persistentMemberIdToLogEntryTransformer
                          .transform(cacheProfile.persistentID),
                      onlineMembers});
        }
      }
    });
  }

  public boolean isShadowPR() {
    return isShadowPR;
  }

  public AbstractGatewaySender getParallelGatewaySender() {
    return parallelGatewaySender;
  }

  public Set<String> getParallelGatewaySenderIds() {
    Set<String> regionGatewaySenderIds = getAllGatewaySenderIds();
    if (regionGatewaySenderIds.isEmpty()) {
      return Collections.emptySet();
    }
    Set<GatewaySender> cacheGatewaySenders = getCache().getAllGatewaySenders();
    Set<String> parallelGatewaySenderIds = new HashSet<>();
    for (GatewaySender sender : cacheGatewaySenders) {
      if (regionGatewaySenderIds.contains(sender.getId()) && sender.isParallel()) {
        parallelGatewaySenderIds.add(sender.getId());
      }
    }
    return parallelGatewaySenderIds;
  }

  public List<PartitionedRegion> getColocatedByList() {
    return colocatedByList;
  }

  public boolean isColocatedBy() {
    return !colocatedByList.isEmpty();
  }

  private void createAndValidatePersistentConfig() {
    DiskStoreImpl diskStore = getDiskStore();
    if (getDataPolicy().withPersistence() && !getConcurrencyChecksEnabled()
        && supportsConcurrencyChecks()) {
      logger.info(
          "Turning on concurrency checks for region: {} since it has been configured to persist data to disk.",
          getFullPath());
      setConcurrencyChecksEnabled(true);
    }
    if (diskStore != null && getDataPolicy().withPersistence()) {
      String colocatedWith = colocatedWithRegion == null ? "" : colocatedWithRegion.getFullPath();
      PRPersistentConfig config = diskStore.getPersistentPRConfig(getFullPath());
      if (config != null) {
        if (config.getTotalNumBuckets() != getTotalNumberOfBuckets()) {
          Object[] prms = new Object[] {getFullPath(), getTotalNumberOfBuckets(),
              config.getTotalNumBuckets()};
          throw new IllegalStateException(
              String.format(
                  "For partition region %s,total-num-buckets %s should not be changed. Previous configured number is %s.",
                  prms));
        }
        // Make sure we don't change to be colocated with a different region
        // We also can't change from colocated to not colocated without writing
        // a record to disk, so we won't allow that right now either.
        if (!colocatedWith.equals(config.getColocatedWith())) {
          Object[] prms =
              new Object[] {getFullPath(), colocatedWith, config.getColocatedWith()};
          DiskAccessException dae = new DiskAccessException(
              String.format(
                  "A DiskAccessException has occurred while writing to the disk for region %s. The region will be closed.",
                  getFullPath()),
              null, diskStore);
          diskStore.handleDiskAccessException(dae);
          throw new IllegalStateException(
              String.format(
                  "For partition region %s, cannot change colocated-with to \"%s\" because there is persistent data with different colocation. Previous configured value is \"%s\".",
                  prms));
        }
      } else {

        config = new PRPersistentConfig(getTotalNumberOfBuckets(), colocatedWith);
        diskStore.addPersistentPR(getFullPath(), config);
        // Fix for support issue 7870 - the parent region needs to be able
        // to discover that there is a persistent colocated child region. So
        // if this is a child region, persist its config to the parent disk store
        // as well.
        if (colocatedWithRegion != null && colocatedWithRegion.getDiskStore() != null
            && colocatedWithRegion.getDiskStore() != diskStore) {
          colocatedWithRegion.getDiskStore().addPersistentPR(getFullPath(), config);
        }
      }

    }
  }

  /**
   * Initializes the PartitionedRegion meta data, adding this Node and starting the service on this
   * node (if not already started). Made this synchronized for bug 41982
   *
   * @return true if initialize was done; false if not because it was destroyed
   */
  private synchronized boolean initPRInternals(InternalRegionArguments internalRegionArgs) {

    if (isLocallyDestroyed) {
      // don't initialize if we are already destroyed for bug 41982
      return false;
    }
    /* Initialize the PartitionRegion */
    if (cache.isCacheAtShutdownAll()) {
      throw cache.getCacheClosedException("Cache is shutting down");
    }
    validator.validateColocation();

    // Do this after the validation, to avoid creating a persistent config
    // for an invalid PR.
    createAndValidatePersistentConfig();
    initializePartitionedRegion();

    // If localMaxMemory is set to 0, do not initialize Data Store.
    final boolean storesData = localMaxMemory > 0;
    if (storesData) {
      initializeDataStore(getAttributes());
    }

    // register this PartitionedRegion, Create a PartitionRegionConfig and bind
    // it into the allPartitionedRegion system wide Region.
    // IMPORTANT: do this before advising peers that we have this region
    registerPartitionedRegion(storesData);

    getRegionAdvisor().initializeRegionAdvisor(); // must be BEFORE initializeRegion call
    getRegionAdvisor().addMembershipListener(advisorListener); // fix for bug 38719

    // 3rd part of eviction attributes validation, after eviction attributes
    // have potentially been published (by the first VM) but before buckets are created
    validator.validateEvictionAttributesAgainstLocalMaxMemory();
    validator.validateFixedPartitionAttributes();

    // Register with the other Nodes that have this region defined, this
    // allows for an Advisor profile exchange, also notifies the Admin
    // callbacks that this Region is created.
    try {
      new CreateRegionProcessor(this).initializeRegion();
    } catch (IllegalStateException e) {
      // If this is a PARTITION_PROXY then retry region creation
      // after toggling the concurrencyChecksEnabled flag. This is
      // required because for persistent regions, we enforce concurrencyChecks
      if (!isDataStore() && supportsConcurrencyChecks()) {
        setConcurrencyChecksEnabled(!getConcurrencyChecksEnabled());
        new CreateRegionProcessor(this).initializeRegion();
      } else {
        throw e;
      }
    }

    if (!isDestroyed && !isLocallyDestroyed) {
      // Register at this point so that other members are known
      cache.getInternalResourceManager().addResourceListener(ResourceType.MEMORY, this);
    }

    // Create OQL indexes before starting GII.
    createOQLIndexes(internalRegionArgs);

    // if any other services are dependent on notifications from this region,
    // then we need to make sure that in-process ops are distributed before
    // releasing the GII latches
    if (isAllEvents()) {
      StateFlushOperation sfo = new StateFlushOperation(getDistributionManager());
      try {
        sfo.flush(distAdvisor.adviseAllPRNodes(), getDistributionManager().getId(),
            OperationExecutors.HIGH_PRIORITY_EXECUTOR, false);
      } catch (InterruptedException ie) {
        Thread.currentThread().interrupt();
        getCancelCriterion().checkCancelInProgress(ie);
      }
    }

    releaseBeforeGetInitialImageLatch(); // moved to this spot for bug 36671

    // requires prid assignment mthomas 4/3/2007
    getRegionAdvisor().processProfilesQueuedDuringInitialization();

    releaseAfterBucketMetadataSetupLatch();

    try {
      if (storesData) {
        if (redundancyProvider.recoverPersistentBuckets()) {
          // Mark members as recovered from disk recursively, starting
          // with the leader region.
          PartitionedRegion leaderRegion = ColocationHelper.getLeaderRegion(this);
          markRecoveredRecursively(leaderRegion);
        }
      }
    } catch (RegionDestroyedException rde) {
      // Do nothing.
      if (logger.isDebugEnabled()) {
        logger.debug("initPRInternals: failed due to exception", rde);
      }
    }

    releaseAfterGetInitialImageLatch();

    try {
      if (storesData) {
        redundancyProvider.scheduleCreateMissingBuckets();
        redundancyProvider.startRedundancyRecovery();
      }
    } catch (RegionDestroyedException rde) {
      // Do nothing.
      if (logger.isDebugEnabled()) {
        logger.debug("initPRInternals: failed due to exception", rde);
      }
    }

    return true;
  }

  private void markRecoveredRecursively(PartitionedRegion region) {
    region.setRecoveredFromDisk();
    for (PartitionedRegion colocatedRegion : ColocationHelper.getColocatedChildRegions(region)) {
      markRecoveredRecursively(colocatedRegion);
    }
  }

  @Override
  public void postCreateRegion() {
    super.postCreateRegion();
    CacheListener[] listeners = fetchCacheListenersField();
    if (listeners != null && listeners.length > 0) {
      Set others = getRegionAdvisor().adviseGeneric();
      for (final CacheListener listener : listeners) {
        if (listener instanceof RegionMembershipListener) {
          RegionMembershipListener rml = (RegionMembershipListener) listener;
          try {
            DistributedMember[] otherDms = new DistributedMember[others.size()];
            others.toArray(otherDms);
            rml.initialMembers(this, otherDms);
          } 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 RegionMembershipListener",
                t);
          }
        }
      }
    }

    PartitionListener[] partitionListeners = getPartitionListeners();
    if (partitionListeners != null && partitionListeners.length != 0) {
      for (PartitionListener listener : partitionListeners) {
        if (listener != null) {
          listener.afterRegionCreate(this);
        }
      }
    }

    Set<String> allGatewaySenderIds = getAllGatewaySenderIds();
    if (!allGatewaySenderIds.isEmpty()) {
      for (GatewaySender sender : cache.getAllGatewaySenders()) {
        if (sender.isParallel() && allGatewaySenderIds.contains(sender.getId())) {
          /*
           * get the ParallelGatewaySender to create the colocated partitioned region for this
           * region.
           */
          if (sender.isRunning()) {
            AbstractGatewaySender senderImpl = (AbstractGatewaySender) sender;
            ((ConcurrentParallelGatewaySenderQueue) senderImpl.getQueues()
                .toArray(new RegionQueue[1])[0]).addShadowPartitionedRegionForUserPR(this);
          }
        }
      }
    }
  }

  /*
   * Initializes the PartitionedRegion. OVERRIDES
   */
  @Override
  public void initialize(InputStream snapshotInputStream, InternalDistributedMember imageTarget,
      InternalRegionArguments internalRegionArgs) throws TimeoutException, ClassNotFoundException {
    if (logger.isDebugEnabled()) {
      logger.debug("PartitionedRegion#initialize {}", getName());
    }
    RegionLogger.logCreate(getName(), getDistributionManager().getDistributionManagerId());

    requiresNotification = cache.requiresNotificationFromPR(this);
    initPRInternals(internalRegionArgs);

    if (logger.isDebugEnabled()) {
      logger.debug("PartitionRegion#initialize: finished with {}", this);
    }
    cache.addPartitionedRegion(this);

  }

  @Override
  protected RegionVersionVector createRegionVersionVector() {
    return null;
  }

  /**
   * Initializes the Node for this Map.
   */
  private Node initializeNode() {
    return new Node(getDistributionManager().getId(), SERIAL_NUMBER_GENERATOR.getAndIncrement());
  }

  /**
   * receive notification that a cache server or wan gateway has been created that requires
   * notification of cache events from this region
   */
  public void cacheRequiresNotification() {
    if (!requiresNotification && !(isClosed || isLocallyDestroyed)) {
      // tell others of the change in status
      requiresNotification = true;
      new UpdateAttributesProcessor(this).distribute(false);
    }
  }

  @Override
  void distributeUpdatedProfileOnSenderCreation() {
    if (!(isClosed || isLocallyDestroyed)) {
      // tell others of the change in status
      requiresNotification = true;
      new UpdateAttributesProcessor(this).distribute(false);
    }
  }

  @Override
  public void addGatewaySenderId(String gatewaySenderId) {
    super.addGatewaySenderId(gatewaySenderId);
    new UpdateAttributesProcessor(this).distribute();
    GatewaySender sender = getCache().getGatewaySender(gatewaySenderId);
    if (sender != null && !sender.isParallel()) {
      distributeUpdatedProfileOnSenderCreation();
    }
    if (sender != null && sender.isParallel() && sender.isRunning()) {
      AbstractGatewaySender senderImpl = (AbstractGatewaySender) sender;
      ((ConcurrentParallelGatewaySenderQueue) senderImpl.getQueues().toArray(new RegionQueue[1])[0])
          .addShadowPartitionedRegionForUserPR(this);
    }
    updateSenderIdMonitor();
  }

  public void updatePRConfigWithNewSetOfAsynchronousEventDispatchers(
      Set<String> asynchronousEventDispatchers) {
    updatePartitionRegionConfig(prConfig -> {
      prConfig.setGatewaySenderIds(asynchronousEventDispatchers);
    });
  }

  public void updatePRConfigWithNewGatewaySenderAfterAssigningBuckets(String aeqId) {
    PartitionRegionHelper.assignBucketsToPartitions(this);
    updatePartitionRegionConfig(prConfig -> {
      Set<String> newGateWayIds;
      if (prConfig.getGatewaySenderIds() != null) {
        newGateWayIds = new HashSet<>(prConfig.getGatewaySenderIds());
      } else {
        newGateWayIds = new HashSet<>();
      }
      newGateWayIds.add(aeqId);
      prConfig.setGatewaySenderIds(newGateWayIds);
    });
  }

  @Override
  public void removeGatewaySenderId(String gatewaySenderId) {
    super.removeGatewaySenderId(gatewaySenderId);
    new UpdateAttributesProcessor(this).distribute();
    updateSenderIdMonitor();
  }

  @Override
  public void addAsyncEventQueueId(String asyncEventQueueId) {
    addAsyncEventQueueId(asyncEventQueueId, false);
  }

  @Override
  public void addAsyncEventQueueId(String asyncEventQueueId, boolean isInternal) {
    super.addAsyncEventQueueId(asyncEventQueueId, isInternal);
    GatewaySender sender = getCache()
        .getGatewaySender(AsyncEventQueueImpl.getSenderIdFromAsyncEventQueueId(asyncEventQueueId));
    if (sender != null && !sender.isParallel()) {
      distributeUpdatedProfileOnSenderCreation();
    }
    if (sender != null && sender.isParallel() && sender.isRunning()) {
      AbstractGatewaySender senderImpl = (AbstractGatewaySender) sender;
      ((ConcurrentParallelGatewaySenderQueue) senderImpl.getQueues().toArray(new RegionQueue[1])[0])
          .addShadowPartitionedRegionForUserPR(this);
    }
    updateSenderIdMonitor();
  }

  @Override
  public void removeAsyncEventQueueId(String asyncEventQueueId) {
    super.removeAsyncEventQueueId(asyncEventQueueId);
    new UpdateAttributesProcessor(this).distribute();
    updateSenderIdMonitor();
  }

  private SenderIdMonitor createSenderIdMonitor() {
    return SenderIdMonitor.createSenderIdMonitor(this, distAdvisor);
  }

  private void updateSenderIdMonitor() {
    senderIdMonitor.update();
  }

  @Override
  void checkSameSenderIdsAvailableOnAllNodes() {
    senderIdMonitor.checkSenderIds();
  }

  /**
   * Initializes the PartitionedRegion - create the Global regions for storing the
   * PartitiotnedRegion configs.
   */
  private void initializePartitionedRegion() {
    prRoot = PartitionedRegionHelper.getPRRoot(getCache());
  }

  // Used for testing purposes
  Region<String, PartitionRegionConfig> getPRRoot() {
    return prRoot;
  }

  @Override
  public void remoteRegionInitialized(CacheProfile profile) {
    if (isInitialized() && hasListener()) {
      Object callback = DistributedRegion.TEST_HOOK_ADD_PROFILE ? profile : null;
      RegionEventImpl event = new RegionEventImpl(this, Operation.REGION_CREATE,
          callback, true, profile.peerMemberId);
      dispatchListenerEvent(EnumListenerEvent.AFTER_REMOTE_REGION_CREATE, event);
    }
  }

  /**
   * This method initializes the partitionedRegionDataStore for this PR.
   *
   * @param ra Region attributes
   */
  private void initializeDataStore(RegionAttributes ra) {
    setDataStore(
        PartitionedRegionDataStore.createDataStore(cache, this, ra.getPartitionAttributes(),
            getStatisticsClock()));
  }

  void setDataStore(PartitionedRegionDataStore dataStore) {
    this.dataStore = dataStore;
  }

  protected DistributedLockService getPartitionedRegionLockService() {
    return getGemFireCache().getPartitionedRegionLockService();
  }

  /**
   * Register this PartitionedRegion by: 1) Create a PartitionRegionConfig and 2) Bind it into the
   * allPartitionedRegion system wide Region.
   *
   * @param storesData which indicates whether the instance in this cache stores data, effecting the
   *        Nodes PRType
   *
   * @see Node#setPRType(int)
   */
  private void registerPartitionedRegion(boolean storesData) {
    // Register this ParitionedRegion. First check if the ParitionedRegion
    // entry already exists globally.
    PartitionRegionConfig prConfig = null;
    PartitionAttributes prAttribs = getAttributes().getPartitionAttributes();
    if (storesData) {
      if (fixedPAttrs != null) {
        node.setPRType(Node.FIXED_PR_DATASTORE);
      } else {
        node.setPRType(Node.ACCESSOR_DATASTORE);
      }
      node.setPersistence(getAttributes().getDataPolicy() == DataPolicy.PERSISTENT_PARTITION);
      node.setLoaderAndWriter(getAttributes().getCacheLoader(),
          getAttributes().getCacheWriter());
    } else {
      if (fixedPAttrs != null) {
        node.setPRType(Node.FIXED_PR_ACCESSOR);
      } else {
        node.setPRType(Node.ACCESSOR);
      }
    }
    final RegionLock rl = getRegionLock();
    try {
      if (logger.isDebugEnabled()) {
        logger.debug("registerPartitionedRegion: obtaining lock");
      }
      rl.lock();
      checkReadiness();

      prConfig = getPRRoot().get(getRegionIdentifier());

      if (prConfig == null) {
        validateParallelAsynchronousEventDispatcherIds();
        partitionedRegionId = generatePRId(getSystem());
        prConfig = new PartitionRegionConfig(partitionedRegionId, getFullPath(),
            prAttribs, getScope(), getAttributes().getEvictionAttributes(),
            getAttributes().getRegionIdleTimeout(), getAttributes().getRegionTimeToLive(),
            getAttributes().getEntryIdleTimeout(), getAttributes().getEntryTimeToLive(),
            getAllGatewaySenderIds());
        logger.info("Partitioned Region {} is born with prId={} ident:{}",
            new Object[] {getFullPath(), partitionedRegionId, getRegionIdentifier()});

        PRSanityCheckMessage.schedule(this);
      } else {
        validator.validatePartitionAttrsFromPRConfig(prConfig);
        if (storesData) {
          validator.validatePersistentMatchBetweenDataStores(prConfig);
          validator.validateCacheLoaderWriterBetweenDataStores(prConfig);
          validator.validateFixedPABetweenDataStores(prConfig);
        }

        partitionedRegionId = prConfig.getPRId();
        logger.info("Partitioned Region {} is created with prId={}",
            new Object[] {getFullPath(), partitionedRegionId});
      }

      synchronized (prIdToPR) {
        prIdToPR.put(partitionedRegionId, this); // last
      }

      prConfig.addNode(node);
      if (getFixedPartitionAttributesImpl() != null) {
        calculateStartingBucketIDs(prConfig);
      }
      updatePRConfig(prConfig, false);
      /*
       * try { if (this.redundantCopies > 0) { if (storesData) {
       * this.dataStore.grabBackupBuckets(false); } } } catch (RegionDestroyedException rde) { if
       * (!this.isClosed) throw rde; }
       */
      cleanPRRegistration = true;
    } catch (LockServiceDestroyedException lsde) {
      if (logger.isDebugEnabled()) {
        logger.debug("registerPartitionedRegion: unable to obtain lock for {}", this);
      }
      PartitionedRegionException pre = null;
      try {
        cleanupFailedInitialization();
      } catch (DistributedSystemDisconnectedException rte) {
        rte.initCause(lsde);
        pre = new PartitionedRegionException(
            "Can not create PartitionedRegion (failed to acquire RegionLock).", rte);
      }
      if (pre == null) {
        pre = new PartitionedRegionException(
            "Can not create PartitionedRegion (failed to acquire RegionLock).", lsde);
      }
      throw pre;
    } catch (IllegalStateException ill) {
      try {
        cleanupFailedInitialization();
      } catch (DistributedSystemDisconnectedException rte) {
        logger.info("IllegalStateException " + ill
            + " will override DistributedSystemDisconnectedException " + rte);
      }
      throw ill;
    } 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();
      String registerErrMsg =
          String.format(
              "An exception was caught while registering PartitionedRegion %s. dumpPRId: %s",
              getFullPath(), prIdToPR.dump());
      try {
        synchronized (prIdToPR) {
          if (prIdToPR.containsKey(partitionedRegionId)) {
            prIdToPR.put(partitionedRegionId, PRIdMap.FAILED_REGISTRATION, false);
            logger.info("FAILED_REGISTRATION prId={} named {}",
                new Object[] {partitionedRegionId, getName()});
          }
        }
      } 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 e) {
        // 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();
        if (logger.isDebugEnabled()) {
          logger.debug("Partitioned Region creation, could not clean up after caught exception", e);
        }
      }
      throw new PartitionedRegionException(registerErrMsg, t);
    } finally {
      try {
        rl.unlock();
        if (logger.isDebugEnabled()) {
          logger.debug("registerPartitionedRegion: released lock");
        }
      } catch (Exception es) {
        if (logger.isDebugEnabled()) {
          logger.debug(es.getMessage(), es);
        }
      }
    }
  }

  public void validateParallelAsynchronousEventDispatcherIds() throws PRLocallyDestroyedException {
    validateParallelAsynchronousEventDispatcherIds(getParallelGatewaySenderIds());
  }

  /**
   * Filters out non parallel GatewaySenders.
   *
   * @param senderIds set of gateway sender IDs.
   * @return set of parallel gateway senders present in the input set.
   */
  public Set<String> filterOutNonParallelGatewaySenders(Set<String> senderIds) {
    Set<String> allParallelSenders = cache.getAllGatewaySenders()
        .parallelStream()
        .filter(GatewaySender::isParallel)
        .map(GatewaySender::getId)
        .collect(toSet());

    Set<String> parallelSenders = new HashSet<>(senderIds);
    parallelSenders.retainAll(allParallelSenders);

    return parallelSenders;
  }

  /**
   * Filters out non parallel AsyncEventQueues.
   *
   * @param queueIds set of async-event-queue IDs.
   * @return set of parallel async-event-queues present in the input set.
   */
  public Set<String> filterOutNonParallelAsyncEventQueues(Set<String> queueIds) {
    Set<String> allParallelQueues = cache.getAsyncEventQueues()
        .parallelStream()
        .filter(AsyncEventQueue::isParallel)
        .map(asyncEventQueue -> AsyncEventQueueImpl
            .getAsyncEventQueueIdFromSenderId(asyncEventQueue.getId()))
        .collect(toSet());

    Set<String> parallelAsyncEventQueues = new HashSet<>(queueIds);
    parallelAsyncEventQueues.retainAll(allParallelQueues);

    return parallelAsyncEventQueues;
  }

  public void validateParallelAsynchronousEventDispatcherIds(
      Set<String> asynchronousEventDispatcherIds) throws PRLocallyDestroyedException {
    for (String dispatcherId : asynchronousEventDispatcherIds) {
      GatewaySender sender = getCache().getGatewaySender(dispatcherId);
      AsyncEventQueue asyncEventQueue = getCache()
          .getAsyncEventQueue(AsyncEventQueueImpl.getAsyncEventQueueIdFromSenderId(dispatcherId));

      // Can't attach a non persistent parallel gateway / async-event-queue to a persistent
      // partitioned region.
      if (getDataPolicy().withPersistence()) {
        if ((sender != null) && (!sender.isPersistenceEnabled())) {
          throw new GatewaySenderConfigurationException(String.format(
              "Non persistent gateway sender %s can not be attached to persistent region %s",
              dispatcherId, getFullPath()));
        } else if ((asyncEventQueue != null) && (!asyncEventQueue.isPersistent())) {
          throw new AsyncEventQueueConfigurationException(String.format(
              "Non persistent asynchronous event queue %s can not be attached to persistent region %s",
              dispatcherId, getFullPath()));
        }
      }

      for (PartitionRegionConfig config : prRoot.values()) {
        if (config.getGatewaySenderIds().contains(dispatcherId)) {
          if (getFullPath().equals(config.getFullPath())) {
            // The sender is already attached to this region
            continue;
          }

          Map<String, PartitionedRegion> colocationMap =
              ColocationHelper.getAllColocationRegions(this);
          if (!colocationMap.isEmpty()) {
            if (colocationMap.containsKey(config.getFullPath())) {
              continue;
            } else {
              int prID = config.getPRId();
              PartitionedRegion colocatedPR = PartitionedRegion.getPRFromId(prID);
              PartitionedRegion leader = ColocationHelper.getLeaderRegion(colocatedPR);

              if (colocationMap.containsValue(leader)) {
                continue;
              } else {
                throw new IllegalStateException(String.format(
                    "Non colocated regions %s, %s cannot have the same parallel %s id %s configured.",
                    getFullPath(), config.getFullPath(),
                    (asyncEventQueue != null ? "async event queue" : "gateway sender"),
                    dispatcherId));
              }
            }
          } else {
            throw new IllegalStateException(String.format(
                "Non colocated regions %s, %s cannot have the same parallel %s id %s configured.",
                getFullPath(), config.getFullPath(),
                (asyncEventQueue != null ? "async event queue" : "gateway sender"), dispatcherId));
          }
        }
      }
    }
  }

  /**
   * @return whether this region requires event notification for all cache content changes from
   *         other nodes
   */
  public boolean getRequiresNotification() {
    return requiresNotification;
  }

  /**
   * Get the Partitioned Region identifier used for DLocks (Bucket and Region)
   */
  public String getRegionIdentifier() {
    return regionIdentifier;
  }

  void setRecoveredFromDisk() {
    recoveredFromDisk = true;
    new UpdateAttributesProcessor(this).distribute(false);
  }

  /**
   * Throw an exception if persistent data recovery from disk is not complete for this region.
   */
  public void checkPROffline() throws PartitionOfflineException {
    if (getDataPolicy().withPersistence() && !recoveredFromDisk) {
      Set<PersistentID> persistIds =
          new HashSet(getRegionAdvisor().advisePersistentMembers().values());
      persistIds.removeAll(getRegionAdvisor().adviseInitializedPersistentMembers().values());
      throw new PartitionOfflineException(persistIds,
          String.format("Partitioned Region %s is offline due to unrecovered persistent data, %s",
              getFullPath(), persistIds));
    }
  }

  /**
   *
   * Set the global PartitionedRegionConfig metadata for this region.
   *
   * This method should *only* be called while holding the partitioned region lock. For code
   * that is mutating the config, use
   * {@link #updatePartitionRegionConfig(PartitionRegionConfigModifier)}
   * instead.
   */
  void updatePRConfig(PartitionRegionConfig prConfig, boolean putOnlyIfUpdated) {
    final PartitionedRegion colocatedRegion = ColocationHelper.getColocatedRegion(this);
    RegionLock colocatedLock = null;
    boolean colocatedLockAcquired = false;
    try {
      boolean colocationComplete = false;
      if (colocatedRegion != null && !prConfig.isColocationComplete()) {
        colocatedLock = colocatedRegion.getRegionLock();
        colocatedLock.lock();
        colocatedLockAcquired = true;
        final PartitionRegionConfig parentConf =
            getPRRoot().get(colocatedRegion.getRegionIdentifier());
        if (parentConf.isColocationComplete() && parentConf.hasSameDataStoreMembers(prConfig)) {
          colocationComplete = true;
          prConfig.setColocationComplete(this);
        }
      }

      if (isDataStore() && !prConfig.isFirstDataStoreCreated()) {
        prConfig.setDatastoreCreated(getEvictionAttributes());
      }
      // N.B.: this put could fail with a CacheClosedException:
      if (!putOnlyIfUpdated || colocationComplete) {
        getPRRoot().put(getRegionIdentifier(), prConfig);
      }
    } finally {
      if (colocatedLockAcquired) {
        colocatedLock.unlock();
      }
    }
  }

  void executeColocationCallbacks() {
    colocationListeners.stream().forEach(ColocationListener::afterColocationCompleted);
  }

  /**
   * @param access true if caller wants last accessed time updated
   * @param allowTombstones - whether a tombstone can be returned
   */
  @Override
  protected Region.Entry<?, ?> nonTXGetEntry(KeyInfo keyInfo, boolean access,
      boolean allowTombstones) {
    final long startTime = prStats.getTime();
    final Object key = keyInfo.getKey();
    try {
      int bucketId = keyInfo.getBucketId();
      if (bucketId == KeyInfo.UNKNOWN_BUCKET) {
        bucketId = PartitionedRegionHelper.getHashKey(this, Operation.GET_ENTRY, key, null, null);
        keyInfo.setBucketId(bucketId);
      }
      InternalDistributedMember targetNode = getOrCreateNodeForBucketRead(bucketId);
      return getEntryInBucket(targetNode, bucketId, key, access, allowTombstones);
    } finally {
      prStats.endGetEntry(startTime);
    }
  }

  protected EntrySnapshot getEntryInBucket(final DistributedMember targetNode, final int bucketId,
      final Object key, boolean access, final boolean allowTombstones) {
    final int retryAttempts = calcRetry();
    if (logger.isTraceEnabled()) {
      logger.trace("getEntryInBucket: " + "Key key={} ({}) from: {} bucketId={}", key,
          key.hashCode(), targetNode, bucketStringForLogs(bucketId));
    }
    EntrySnapshot ret = null;
    int count = 0;
    RetryTimeKeeper retryTime = null;
    InternalDistributedMember retryNode = (InternalDistributedMember) targetNode;
    while (count <= retryAttempts) {
      // Every continuation should check for DM cancellation
      if (retryNode == null) {
        checkReadiness();
        if (retryTime == null) {
          retryTime = new RetryTimeKeeper(retryTimeout);
        }
        if (retryTime.overMaximum()) {
          break;
        }
        retryNode = getOrCreateNodeForBucketRead(bucketId);

        // No storage found for bucket, early out preventing hot loop, bug 36819
        if (retryNode == null) {
          checkShutdown();
          return null;
        }
        continue;
      }
      try {
        final boolean loc = (localMaxMemory > 0) && retryNode.equals(getMyId());
        if (loc) {
          ret = dataStore.getEntryLocally(bucketId, key, access, allowTombstones);
        } else {
          ret = getEntryRemotely(retryNode, bucketId, key, access, allowTombstones);
          // TODO:Suranjan&Yogesh : there should be better way than this one
          String name = Thread.currentThread().getName();
          if (name.startsWith("ServerConnection") && !getMyId().equals(targetNode)) {
            setNetworkHopType(bucketId, (InternalDistributedMember) targetNode);
          }
        }

        return ret;
      } catch (PRLocallyDestroyedException pde) {
        if (logger.isDebugEnabled()) {
          logger.debug("getEntryInBucket: Encountered PRLocallyDestroyedException", pde);
        }
        checkReadiness();
      } catch (EntryNotFoundException ignore) {
        return null;
      } catch (ForceReattemptException prce) {
        prce.checkKey(key);
        if (logger.isDebugEnabled()) {
          logger.debug("getEntryInBucket: retrying, attempts so far: {}", count, prce);
        }
        checkReadiness();
        InternalDistributedMember lastNode = retryNode;
        retryNode = getOrCreateNodeForBucketRead(bucketId);
        if (lastNode.equals(retryNode)) {
          if (retryTime == null) {
            retryTime = new RetryTimeKeeper(retryTimeout);
          }
          if (retryTime.overMaximum()) {
            break;
          }
          retryTime.waitToRetryNode();
        }
      } catch (PrimaryBucketException notPrimary) {
        if (logger.isDebugEnabled()) {
          logger.debug("Bucket {} on Node {} not primary", notPrimary.getLocalizedMessage(),
              retryNode);
        }
        getRegionAdvisor().notPrimary(bucketId, retryNode);
        retryNode = getOrCreateNodeForBucketRead(bucketId);
      }

      // It's possible this is a GemFire thread e.g. ServerConnection
      // which got to this point because of a distributed system shutdown or
      // region closure which uses interrupt to break any sleep() or wait()
      // calls
      // e.g. waitForPrimary
      checkShutdown();

      count++;
      if (count == 1) {
        prStats.incContainsKeyValueOpsRetried();
      }
      prStats.incContainsKeyValueRetries();

    }

    PartitionedRegionDistributionException e = null; // Fix for bug 36014
    if (logger.isDebugEnabled()) {
      e = new PartitionedRegionDistributionException(
          String.format("No VM available for getEntry in %s attempts",
              count));
    }
    logger.warn(String.format("No VM available for getEntry in %s attempts", count), e);
    return null;
  }

  /**
   * Check for region closure, region destruction, cache closure as well as distributed system
   * disconnect. As of 6/21/2007, there were at least four volatile variables reads and one
   * synchonrization performed upon completion of this method.
   */
  private void checkShutdown() {
    checkReadiness();
    cache.getCancelCriterion().checkCancelInProgress(null);
  }

  /**
   * Checks if a key is contained remotely.
   *
   * @param targetNode the node where bucket region for the key exists.
   * @param bucketId the bucket id for the key.
   * @param key the key, whose value needs to be checks
   * @param access true if caller wants last access time updated
   * @param allowTombstones whether tombstones should be returned
   * @throws EntryNotFoundException if the entry doesn't exist
   * @throws ForceReattemptException if the peer is no longer available
   * @return true if the passed key is contained remotely.
   */
  public EntrySnapshot getEntryRemotely(InternalDistributedMember targetNode, Integer bucketId,
      Object key, boolean access, boolean allowTombstones)
      throws EntryNotFoundException, PrimaryBucketException, ForceReattemptException {
    FetchEntryResponse r = FetchEntryMessage.send(targetNode, this, key, access);
    prStats.incPartitionMessagesSent();
    EntrySnapshot entry = r.waitForResponse();
    if (entry != null && entry.getRawValue() == Token.TOMBSTONE) {
      if (!allowTombstones) {
        return null;
      }
    }
    return entry;
  }

  // /////////////////////////////////////////////////////////////////
  // Following methods would throw, operation Not Supported Exception
  // /////////////////////////////////////////////////////////////////

  /**
   * @since GemFire 5.0
   * @throws UnsupportedOperationException OVERRIDES
   */
  @Override
  public void becomeLockGrantor() {
    throw new UnsupportedOperationException();
  }

  /**
   * @since GemFire 5.0
   * @throws UnsupportedOperationException OVERRIDES
   */
  @Override
  public Region createSubregion(String subregionName, RegionAttributes regionAttributes)
      throws RegionExistsException, TimeoutException {
    throw new UnsupportedOperationException();
  }

  /**
   * @since GemFire 5.0
   * @throws UnsupportedOperationException OVERRIDES
   */
  @Override
  public Lock getDistributedLock(Object key) throws IllegalStateException {
    throw new UnsupportedOperationException();
  }

  @Override
  public synchronized long getLastModifiedTime() {
    if (!canStoreDataLocally()) {
      return 0;
    }
    Set<BucketRegion> buckets = dataStore.getAllLocalBucketRegions();
    return buckets.stream().map(AbstractRegion::getLastModifiedTime).reduce(0L,
        (a, b) -> a > b ? a : b);
  }

  @Override
  public synchronized long getLastAccessedTime() {
    if (!canStoreDataLocally()) {
      return 0;
    }
    Set<BucketRegion> buckets = dataStore.getAllLocalBucketRegions();
    return buckets.stream().map(AbstractRegion::getLastAccessedTime).reduce(0L,
        (a, b) -> a > b ? a : b);
  }

  @Override
  public long getMissCount() {
    if (!canStoreDataLocally()) {
      return 0;
    }
    Set<BucketRegion> buckets = dataStore.getAllLocalBucketRegions();
    return buckets.stream().map(AbstractRegion::getMissCount).reduce(0L, Long::sum);
  }

  @Override
  public long getHitCount() {
    if (!canStoreDataLocally()) {
      return 0;
    }
    Set<BucketRegion> buckets = dataStore.getAllLocalBucketRegions();
    return buckets.stream().map(AbstractRegion::getHitCount).reduce(0L, Long::sum);
  }

  @Override
  public void resetCounts() {
    if (!canStoreDataLocally()) {
      return;
    }
    Set<BucketRegion> buckets = dataStore.getAllLocalBucketRegions();
    for (BucketRegion bucket : buckets) {
      bucket.resetCounts();
    }
  }

  /**
   * @since GemFire 5.0
   * @throws UnsupportedOperationException OVERRIDES
   */
  public Region getSubregion() {
    throw new UnsupportedOperationException();
  }

  /**
   * @since GemFire 5.0
   * @throws UnsupportedOperationException OVERRIDES
   */
  @Override
  public Lock getRegionDistributedLock() throws IllegalStateException {

    throw new UnsupportedOperationException();
  }

  /**
   * @since GemFire 5.0
   * @throws UnsupportedOperationException OVERRIDES
   */
  @Override
  public void loadSnapshot(InputStream inputStream)
      throws IOException, ClassNotFoundException, CacheWriterException, TimeoutException {
    throw new UnsupportedOperationException();
  }

  /**
   * Should it destroy entry from local accessor????? OVERRIDES
   */
  @Override
  public void localDestroy(Object key, Object aCallbackArgument) throws EntryNotFoundException {

    throw new UnsupportedOperationException();
  }

  /**
   * @since GemFire 5.0
   * @throws UnsupportedOperationException OVERRIDES
   */
  @Override
  public void localInvalidate(Object key, Object aCallbackArgument) throws EntryNotFoundException {

    throw new UnsupportedOperationException();
  }

  /**
   * @since GemFire 5.0
   * @throws UnsupportedOperationException OVERRIDES
   */
  @Override
  public void localInvalidateRegion(Object aCallbackArgument) {
    getDataView().checkSupportsRegionInvalidate();
    throw new UnsupportedOperationException();
  }

  /**
   * Executes a query on this PartitionedRegion. The restrictions have already been checked. The
   * query is a SELECT expression, and the only region it refers to is this region.
   *
   * @see DefaultQuery#execute()
   *
   * @since GemFire 5.1
   */
  @Override
  public Object executeQuery(final DefaultQuery query,
      final ExecutionContext executionContext,
      final Object[] parameters,
      final Set buckets)
      throws FunctionDomainException, TypeMismatchException, NameResolutionException,
      QueryInvocationTargetException {
    for (;;) {
      try {
        return doExecuteQuery(query, executionContext, parameters, buckets);
      } catch (ForceReattemptException ignore) {
        // fall through and loop
      }
    }
  }

  /**
   * If ForceReattemptException is thrown then the caller must loop and call us again.
   *
   * @throws ForceReattemptException if one of the buckets moved out from under us
   */
  private Object doExecuteQuery(final DefaultQuery query,
      final ExecutionContext executionContext,
      final Object[] parameters,
      final Set buckets)
      throws FunctionDomainException, TypeMismatchException, NameResolutionException,
      QueryInvocationTargetException, ForceReattemptException {
    if (logger.isDebugEnabled()) {
      logger.debug("Executing query :{}", query);
    }

    HashSet<Integer> allBuckets = new HashSet<>();

    if (buckets == null) { // remote buckets
      final Iterator remoteIter = getRegionAdvisor().getBucketSet().iterator();
      try {
        while (remoteIter.hasNext()) {
          allBuckets.add((Integer) remoteIter.next());
        }
      } catch (NoSuchElementException ignore) {
      }
    } else { // local buckets
      Iterator localIter = null;
      if (dataStore != null) {
        localIter = buckets.iterator();
      } else {
        localIter = Collections.emptyIterator();
      }
      try {
        while (localIter.hasNext()) {
          allBuckets.add((Integer) localIter.next());
        }
      } catch (NoSuchElementException ignore) {
      }
    }

    if (allBuckets.size() == 0) {
      if (logger.isDebugEnabled()) {
        logger.debug("No bucket storage allocated. PR has no data yet.");
      }
      ResultsSet resSet = new ResultsSet();
      resSet.setElementType(new ObjectTypeImpl(
          getValueConstraint() == null ? Object.class : getValueConstraint()));
      return resSet;
    }

    CompiledSelect selectExpr = query.getSimpleSelect();
    if (selectExpr == null) {
      throw new IllegalArgumentException(
          "query must be a select expression only");
    }

    // this can return a BAG even if it's a DISTINCT select expression,
    // since the expectation is that the duplicates will be removed at the end
    SelectResults results = selectExpr.getEmptyResultSet(parameters, getCache(), query);

    PartitionedRegionQueryEvaluator prqe = new PartitionedRegionQueryEvaluator(getSystem(),
        this, query, executionContext, parameters, results, allBuckets);
    for (;;) {
      getCancelCriterion().checkCancelInProgress(null);
      boolean interrupted = Thread.interrupted();
      try {
        results = prqe.queryBuckets(null);
        break;
      } catch (InterruptedException ignore) {
        interrupted = true;
      } catch (FunctionDomainException e) {
        throw e;
      } catch (TypeMismatchException e) {
        throw e;
      } catch (NameResolutionException e) {
        throw e;
      } catch (QueryInvocationTargetException e) {
        throw e;
      } catch (QueryException qe) {
        throw new QueryInvocationTargetException(
            String.format("Unexpected query exception occurred during query execution %s",
                qe.getMessage()),
            qe);
      } finally {
        if (interrupted) {
          Thread.currentThread().interrupt();
        }
      }
    } // for

    // Drop Duplicates if this is a DISTINCT query
    boolean allowsDuplicates = results.getCollectionType().allowsDuplicates();
    // No need to apply the limit to the SelectResults.
    // We know that even if we do not apply the limit,
    // the results will satisfy the limit
    // as it has been evaluated in the iteration of List to
    // populate the SelectsResuts
    // So if the results is instance of ResultsBag or is a StructSet or
    // a ResultsSet, if the limit exists, the data set size will
    // be exactly matching the limit
    if (selectExpr.isDistinct()) {
      // don't just convert to a ResultsSet (or StructSet), since
      // the bags can convert themselves to a Set more efficiently
      ObjectType elementType = results.getCollectionType().getElementType();
      if (selectExpr.getOrderByAttrs() != null) {
        // Set limit also, its not applied while building the final result set as order by is
        // involved.
      } else if (allowsDuplicates) {
        results = new ResultsCollectionWrapper(elementType, results.asSet());
      }
      if (selectExpr.isCount() && (results.isEmpty() || selectExpr.isDistinct())) {
        // Constructor with elementType not visible.
        SelectResults resultCount = new ResultsBag(getCachePerfStats());
        resultCount.setElementType(new ObjectTypeImpl(Integer.class));
        ((Bag) resultCount).addAndGetOccurence(results.size());
        return resultCount;
      }
    }
    return results;
  }

  /**
   * @since GemFire 5.0
   * @throws UnsupportedOperationException OVERRIDES
   */
  @Override
  public void saveSnapshot(OutputStream outputStream) throws IOException {
    throw new UnsupportedOperationException();
  }

  /**
   * @since GemFire 5.0
   * @throws UnsupportedOperationException OVERRIDES
   */
  @Override
  public void writeToDisk() {
    throw new UnsupportedOperationException();
  }

  /**
   * @since GemFire 5.0
   * @throws UnsupportedOperationException OVERRIDES
   */
  @Override
  public void clear() {
    throw new UnsupportedOperationException();
  }

  @Override
  void basicClear(RegionEventImpl regionEvent, boolean cacheWrite) {
    throw new UnsupportedOperationException();
  }

  @Override
  void basicLocalClear(RegionEventImpl event) {
    throw new UnsupportedOperationException();
  }

  @Override
  public boolean virtualPut(EntryEventImpl event, boolean ifNew, boolean ifOld,
      Object expectedOldValue, boolean requireOldValue, long lastModified,
      boolean overwriteDestroyed, boolean invokeCallbacks, boolean throwConcurrentModificaiton)
      throws TimeoutException, CacheWriterException {
    final long startTime = prStats.getTime();
    boolean result = false;
    final DistributedPutAllOperation putAllOp_save = event.setPutAllOperation(null);

    if (event.getEventId() == null) {
      event.setNewEventId(cache.getDistributedSystem());
    }
    boolean bucketStorageAssigned = true;
    try {
      final Integer bucketId = event.getKeyInfo().getBucketId();
      assert bucketId != KeyInfo.UNKNOWN_BUCKET;
      // check in bucket2Node region
      InternalDistributedMember targetNode = getNodeForBucketWrite(bucketId, null);
      // force all values to be serialized early to make size computation cheap
      // and to optimize distribution.
      if (logger.isDebugEnabled()) {
        logger.debug("PR.virtualPut putting event={}", event);
      }

      if (targetNode == null) {
        try {
          bucketStorageAssigned = false;
          targetNode = createBucket(bucketId, event.getNewValSizeForPR(), null);
        } catch (PartitionedRegionStorageException e) {
          // try not to throw a PRSE if the cache is closing or this region was
          // destroyed during createBucket() (bug 36574)
          checkReadiness();
          if (cache.isClosed()) {
            throw new RegionDestroyedException(toString(), getFullPath());
          }
          throw e;
        }
      }

      if (event.isBridgeEvent() && bucketStorageAssigned) {
        setNetworkHopType(bucketId, targetNode);
      }
      if (putAllOp_save == null) {
        result = putInBucket(targetNode, bucketId, event, ifNew, ifOld, expectedOldValue,
            requireOldValue, (ifNew ? 0L : lastModified));
        if (logger.isDebugEnabled()) {
          logger.debug("PR.virtualPut event={} ifNew={} ifOld={} result={}", event, ifNew, ifOld,
              result);
        }
      } else {
        checkIfAboveThreshold(event); // fix for 40502
        // putAll: save the bucket id into DPAO, then wait for postPutAll to send msg
        // at this time, DPAO's PutAllEntryData should be empty, we should add entry here with
        // bucket id
        // the message will be packed in postPutAll, include the one to local bucket, because the
        // buckets
        // could be changed at that time
        putAllOp_save.addEntry(event, bucketId);
        if (logger.isDebugEnabled()) {
          logger.debug("PR.virtualPut PutAll added event={} into bucket {}", event, bucketId);
        }
        result = true;
      }
    } catch (RegionDestroyedException rde) {
      if (!rde.getRegionFullPath().equals(getFullPath())) {
        throw new RegionDestroyedException(toString(), getFullPath(), rde);
      }
    } finally {
      if (putAllOp_save == null) {
        // only for normal put
        if (ifNew) {
          prStats.endCreate(startTime);
        } else {
          prStats.endPut(startTime);
        }
      }
    }
    if (!result) {
      checkReadiness();
      if (!ifNew && !ifOld && !getConcurrencyChecksEnabled()) {
        // may fail due to concurrency conflict
        // failed for unknown reason
        // throw new PartitionedRegionStorageException("unable to execute operation");
        logger.warn("PR.virtualPut returning false when ifNew and ifOld are both false",
            new Exception("stack trace"));
      }
    }
    return result;
  }

  @Override
  void performPutAllEntry(EntryEventImpl event) {
    /*
     * force shared data view so that we just do the virtual op, accruing things in the put all
     * operation for later
     */
    getSharedDataView().putEntry(event, false, false, null, false, 0L, false);
  }

  @Override
  void performRemoveAllEntry(EntryEventImpl event) {
    // do not call basicDestroy directly since it causes bug 51715
    // basicDestroy(event, true, null);
    // force shared data view so that we just do the virtual op
    getSharedDataView().destroyExistingEntry(event, true, null);
  }

  @Override
  public void checkIfAboveThreshold(EntryEventImpl entryEvent) throws LowMemoryException {
    getRegionAdvisor().checkIfBucketSick(entryEvent.getKeyInfo().getBucketId(),
        entryEvent.getKey());
  }

  public boolean isFixedPartitionedRegion() {
    if (fixedPAttrs != null || fixedPASet == 1) {
      // We are sure that its a FixedFPA
      return true;
    }
    // We know that it's a normal PR
    if (fixedPASet == 2) {
      return false;
    }
    // Now is the case for accessor with fixedPAttrs null
    // and we don't know if it is a FPR
    // We will find out once and return that value whenever we have check again.
    fixedPASet = hasRemoteFPAttrs();
    return fixedPASet == 1;
  }

  private byte hasRemoteFPAttrs() {
    List<FixedPartitionAttributesImpl> fpaList =
        getRegionAdvisor().adviseAllFixedPartitionAttributes();
    Set<InternalDistributedMember> remoteDataStores = getRegionAdvisor().adviseDataStore();
    if (!fpaList.isEmpty() || (fixedPAttrs != null && !fixedPAttrs.isEmpty())) {
      return 1;
    }
    if (isDataStore() || !remoteDataStores.isEmpty()) {
      return 2;
    }

    // This is an accessor and we need to wait for a datastore to see if there
    // are any fixed PRs.
    return 0;
  }

  @Override
  public void postPutAllFireEvents(DistributedPutAllOperation putAllOp,
      VersionedObjectList successfulPuts) {
    /*
     * No op on pr, will happen in the buckets etc.
     */
  }

  @Override
  public void postRemoveAllFireEvents(DistributedRemoveAllOperation removeAllOp,
      VersionedObjectList successfulOps) {
    /*
     * No op on pr, will happen in the buckets etc.
     */
  }

  /**
   * Create PutAllPRMsgs for each bucket, and send them.
   *
   * @param putAllOp DistributedPutAllOperation object.
   * @param successfulPuts not used in PartitionedRegion.
   */
  @Override
  public long postPutAllSend(DistributedPutAllOperation putAllOp,
      VersionedObjectList successfulPuts) {
    final boolean isDebugEnabled = logger.isDebugEnabled();

    if (cache.isCacheAtShutdownAll()) {
      throw cache.getCacheClosedException("Cache is shutting down");
    }

    final long startTime = prStats.getTime();
    // build all the msgs by bucketid
    HashMap prMsgMap = putAllOp.createPRMessages();
    PutAllPartialResult partialKeys = new PutAllPartialResult(putAllOp.putAllDataSize);

    // clear the successfulPuts list since we're actually doing the puts here
    // and the basicPutAll work was just a way to build the DPAO object
    Map<Object, VersionTag> keyToVersionMap =
        new HashMap<>(successfulPuts.size());
    successfulPuts.clearVersions();
    for (final Object value : prMsgMap.entrySet()) {
      Map.Entry mapEntry = (Map.Entry) value;
      Integer bucketId = (Integer) mapEntry.getKey();
      PutAllPRMessage prMsg = (PutAllPRMessage) mapEntry.getValue();
      checkReadiness();
      long then = 0;
      if (isDebugEnabled) {
        then = System.currentTimeMillis();
      }
      try {
        VersionedObjectList versions = sendMsgByBucket(bucketId, prMsg);
        if (versions.size() > 0) {
          partialKeys.addKeysAndVersions(versions);
          versions.saveVersions(keyToVersionMap);
        } else if (!getConcurrencyChecksEnabled()) { // no keys returned if not versioned
          Set keys = prMsg.getKeys();
          partialKeys.addKeys(keys);
        }
      } catch (PutAllPartialResultException pre) {
        // sendMsgByBucket applied partial keys
        if (isDebugEnabled) {
          logger.debug("PR.postPutAll encountered PutAllPartialResultException, ", pre);
        }
        partialKeys.consolidate(pre.getResult());
      } catch (Exception ex) {
        // If failed at other exception
        if (isDebugEnabled) {
          logger.debug("PR.postPutAll encountered exception at sendMsgByBucket, ", ex);
        }
        @Released
        EntryEventImpl firstEvent = prMsg.getFirstEvent(this);
        try {
          partialKeys.saveFailedKey(firstEvent.getKey(), ex);
        } finally {
          firstEvent.release();
        }
      }
      if (isDebugEnabled) {
        long now = System.currentTimeMillis();
        if ((now - then) >= 10000) {
          logger.debug("PR.sendMsgByBucket took " + (now - then) + " ms");
        }
      }
    }
    prStats.endPutAll(startTime);
    if (!keyToVersionMap.isEmpty()) {
      for (final Object o : successfulPuts.getKeys()) {
        successfulPuts.addVersion(keyToVersionMap.get(o));
      }
      keyToVersionMap.clear();
    }

    if (partialKeys.hasFailure()) {
      logger.info("Region {} putAll: {}",
          new Object[] {getFullPath(), partialKeys});
      if (putAllOp.isBridgeOperation()) {
        if (partialKeys.getFailure() instanceof CancelException) {
          throw (CancelException) partialKeys.getFailure();
        } else {
          throw new PutAllPartialResultException(partialKeys);
        }
      } else {
        if (partialKeys.getFailure() instanceof RuntimeException) {
          throw (RuntimeException) partialKeys.getFailure();
        } else {
          throw new RuntimeException(partialKeys.getFailure());
        }
      }
    }
    return -1;
  }

  @Override
  public long postRemoveAllSend(DistributedRemoveAllOperation op,
      VersionedObjectList successfulOps) {
    final boolean isDebugEnabled = logger.isDebugEnabled();

    if (cache.isCacheAtShutdownAll()) {
      throw cache.getCacheClosedException("Cache is shutting down");
    }

    final long startTime = prStats.getTime();
    // build all the msgs by bucketid
    HashMap<Integer, RemoveAllPRMessage> prMsgMap = op.createPRMessages();
    PutAllPartialResult partialKeys = new PutAllPartialResult(op.removeAllDataSize);

    // clear the successfulOps list since we're actually doing the removes here
    // and the basicRemoveAll work was just a way to build the "op" object
    Map<Object, VersionTag> keyToVersionMap = new HashMap<>(successfulOps.size());
    successfulOps.clearVersions();
    for (final Map.Entry<Integer, RemoveAllPRMessage> mapEntry : prMsgMap.entrySet()) {
      Integer bucketId = mapEntry.getKey();
      RemoveAllPRMessage prMsg = mapEntry.getValue();
      checkReadiness();
      long then = 0;
      if (isDebugEnabled) {
        then = System.currentTimeMillis();
      }
      try {
        VersionedObjectList versions = sendMsgByBucket(bucketId, prMsg);
        if (versions.size() > 0) {
          partialKeys.addKeysAndVersions(versions);
          versions.saveVersions(keyToVersionMap);
        } else if (!getConcurrencyChecksEnabled()) { // no keys returned if not versioned
          Set keys = prMsg.getKeys();
          partialKeys.addKeys(keys);
        }
      } catch (PutAllPartialResultException pre) {
        // sendMsgByBucket applied partial keys
        if (isDebugEnabled) {
          logger.debug("PR.postRemoveAll encountered BulkOpPartialResultException, ", pre);
        }
        partialKeys.consolidate(pre.getResult());
      } catch (Exception ex) {
        // If failed at other exception
        if (isDebugEnabled) {
          logger.debug("PR.postRemoveAll encountered exception at sendMsgByBucket, ", ex);
        }
        @Released
        EntryEventImpl firstEvent = prMsg.getFirstEvent(this);
        try {
          partialKeys.saveFailedKey(firstEvent.getKey(), ex);
        } finally {
          firstEvent.release();
        }
      }
      if (isDebugEnabled) {
        long now = System.currentTimeMillis();
        if ((now - then) >= 10000) {
          logger.debug("PR.sendMsgByBucket took {} ms", (now - then));
        }
      }
    }
    prStats.endRemoveAll(startTime);
    if (!keyToVersionMap.isEmpty()) {
      for (Object o : successfulOps.getKeys()) {
        successfulOps.addVersion(keyToVersionMap.get(o));
      }
      keyToVersionMap.clear();
    }

    if (partialKeys.hasFailure()) {
      logger.info("Region {} putAll: {}",
          new Object[] {getFullPath(), partialKeys});
      if (op.isBridgeOperation()) {
        if (partialKeys.getFailure() instanceof CancelException) {
          throw (CancelException) partialKeys.getFailure();
        } else {
          throw new PutAllPartialResultException(partialKeys);
        }
      } else {
        if (partialKeys.getFailure() instanceof RuntimeException) {
          throw (RuntimeException) partialKeys.getFailure();
        } else {
          throw new RuntimeException(partialKeys.getFailure());
        }
      }
    }
    return -1;
  }

  /*
   * If failed after retries, it will throw PartitionedRegionStorageException, no need for return
   * value
   */
  private VersionedObjectList sendMsgByBucket(final Integer bucketId, PutAllPRMessage prMsg) {
    final boolean isDebugEnabled = logger.isDebugEnabled();

    // retry the put remotely until it finds the right node managing the bucket
    @Released
    EntryEventImpl event = prMsg.getFirstEvent(this);
    try {
      RetryTimeKeeper retryTime = null;
      InternalDistributedMember currentTarget = getNodeForBucketWrite(bucketId, null);
      if (isDebugEnabled) {
        logger.debug("PR.sendMsgByBucket:bucket {}'s currentTarget is {}", bucketId, currentTarget);
      }

      long timeOut = 0;
      int count = 0;
      for (;;) {
        switch (count) {
          case 0:
            // Note we don't check for DM cancellation in common case.
            // First time. Assume success, keep going.
            break;
          case 1:
            cache.getCancelCriterion().checkCancelInProgress(null);
            // Second time (first failure). Calculate timeout and keep going.
            timeOut = System.currentTimeMillis() + retryTimeout;
            break;
          default:
            cache.getCancelCriterion().checkCancelInProgress(null);
            // test for timeout
            long timeLeft = timeOut - System.currentTimeMillis();
            if (timeLeft < 0) {
              PRHARedundancyProvider.timedOut(this, null, null, "update an entry",
                  retryTimeout);
              // NOTREACHED
            }

            // Didn't time out. Sleep a bit and then continue
            boolean interrupted = Thread.interrupted();
            try {
              Thread.sleep(PartitionedRegionHelper.DEFAULT_WAIT_PER_RETRY_ITERATION);
            } catch (InterruptedException ignore) {
              interrupted = true;
            } finally {
              if (interrupted) {
                Thread.currentThread().interrupt();
              }
            }
            break;
        } // switch
        count++;

        if (currentTarget == null) { // pick target
          checkReadiness();
          if (retryTime == null) {
            retryTime = new RetryTimeKeeper(retryTimeout);
          }

          currentTarget = waitForNodeOrCreateBucket(retryTime, event, bucketId);
          if (isDebugEnabled) {
            logger.debug("PR.sendMsgByBucket: event size is {}, new currentTarget is {}",
                getEntrySize(event), currentTarget);
          }

          // It's possible this is a GemFire thread e.g. ServerConnection
          // which got to this point because of a distributed system shutdown or
          // region closure which uses interrupt to break any sleep() or wait() calls
          // e.g. waitForPrimary or waitForBucketRecovery in which case throw exception
          checkShutdown();
          continue;
        } // pick target

        try {
          return tryToSendOnePutAllMessage(prMsg, currentTarget);
        } catch (ForceReattemptException prce) {
          checkReadiness();
          InternalDistributedMember lastTarget = currentTarget;
          if (retryTime == null) {
            retryTime = new RetryTimeKeeper(retryTimeout);
          }
          currentTarget = getNodeForBucketWrite(bucketId, retryTime);
          if (isDebugEnabled) {
            logger.debug("PR.sendMsgByBucket: Old target was {}, Retrying {}", lastTarget,
                currentTarget);
          }
          if (lastTarget.equals(currentTarget)) {
            if (isDebugEnabled) {
              logger.debug("PR.sendMsgByBucket: Retrying at the same node:{} due to {}",
                  currentTarget, prce.getMessage());
            }
            if (retryTime.overMaximum()) {
              PRHARedundancyProvider.timedOut(this, null, null, "update an entry",
                  retryTimeout);
              // NOTREACHED
            }
            retryTime.waitToRetryNode();
          }
          event.setPossibleDuplicate(true);
          prMsg.setPossibleDuplicate(true);
        } catch (PrimaryBucketException notPrimary) {
          if (isDebugEnabled) {
            logger.debug("Bucket {} on Node {} not primnary", notPrimary.getLocalizedMessage(),
                currentTarget);
          }
          getRegionAdvisor().notPrimary(bucketId, currentTarget);
          if (retryTime == null) {
            retryTime = new RetryTimeKeeper(retryTimeout);
          }
          currentTarget = getNodeForBucketWrite(bucketId, retryTime);
        } catch (DataLocationException dle) {
          if (isDebugEnabled) {
            logger.debug("DataLocationException processing putAll", dle);
          }
          throw new TransactionException(dle);
        }

        // It's possible this is a GemFire thread e.g. ServerConnection
        // which got to this point because of a distributed system shutdown or
        // region closure which uses interrupt to break any sleep() or wait()
        // calls
        // e.g. waitForPrimary or waitForBucketRecovery in which case throw
        // exception
        checkShutdown();

        // If we get here, the attempt failed...
        if (count == 1) {
          prStats.incPutAllMsgsRetried();
        }
        prStats.incPutAllRetries();
      } // for
    } finally {
      if (event != null) {
        event.release();
      }
    }
    // NOTREACHED
  }

  /*
   * If failed after retries, it will throw PartitionedRegionStorageException, no need for return
   * value
   */
  private VersionedObjectList sendMsgByBucket(final Integer bucketId, RemoveAllPRMessage prMsg) {
    // retry the put remotely until it finds the right node managing the bucket
    @Released
    EntryEventImpl event = prMsg.getFirstEvent(this);
    try {
      RetryTimeKeeper retryTime = null;
      InternalDistributedMember currentTarget = getNodeForBucketWrite(bucketId, null);
      if (logger.isDebugEnabled()) {
        logger.debug("PR.sendMsgByBucket:bucket {}'s currentTarget is {}", bucketId, currentTarget);
      }

      long timeOut = 0;
      int count = 0;
      for (;;) {
        switch (count) {
          case 0:
            // Note we don't check for DM cancellation in common case.
            // First time. Assume success, keep going.
            break;
          case 1:
            cache.getCancelCriterion().checkCancelInProgress(null);
            // Second time (first failure). Calculate timeout and keep going.
            timeOut = System.currentTimeMillis() + retryTimeout;
            break;
          default:
            cache.getCancelCriterion().checkCancelInProgress(null);
            // test for timeout
            long timeLeft = timeOut - System.currentTimeMillis();
            if (timeLeft < 0) {
              PRHARedundancyProvider.timedOut(this, null, null, "update an entry",
                  retryTimeout);
              // NOTREACHED
            }

            // Didn't time out. Sleep a bit and then continue
            boolean interrupted = Thread.interrupted();
            try {
              Thread.sleep(PartitionedRegionHelper.DEFAULT_WAIT_PER_RETRY_ITERATION);
            } catch (InterruptedException ignore) {
              interrupted = true;
            } finally {
              if (interrupted) {
                Thread.currentThread().interrupt();
              }
            }
            break;
        } // switch
        count++;

        if (currentTarget == null) { // pick target
          checkReadiness();
          if (retryTime == null) {
            retryTime = new RetryTimeKeeper(retryTimeout);
          }

          currentTarget = waitForNodeOrCreateBucket(retryTime, event, bucketId);
          if (logger.isDebugEnabled()) {
            logger.debug("PR.sendMsgByBucket: event size is {}, new currentTarget is {}",
                getEntrySize(event), currentTarget);
          }

          // It's possible this is a GemFire thread e.g. ServerConnection
          // which got to this point because of a distributed system shutdown or
          // region closure which uses interrupt to break any sleep() or wait() calls
          // e.g. waitForPrimary or waitForBucketRecovery in which case throw exception
          checkShutdown();
          continue;
        } // pick target

        try {
          return tryToSendOneRemoveAllMessage(prMsg, currentTarget);
        } catch (ForceReattemptException prce) {
          checkReadiness();
          InternalDistributedMember lastTarget = currentTarget;
          if (retryTime == null) {
            retryTime = new RetryTimeKeeper(retryTimeout);
          }
          currentTarget = getNodeForBucketWrite(bucketId, retryTime);
          if (logger.isTraceEnabled()) {
            logger.trace("PR.sendMsgByBucket: Old target was {}, Retrying {}", lastTarget,
                currentTarget);
          }
          if (lastTarget.equals(currentTarget)) {
            if (logger.isDebugEnabled()) {
              logger.debug("PR.sendMsgByBucket: Retrying at the same node:{} due to {}",
                  currentTarget, prce.getMessage());
            }
            if (retryTime.overMaximum()) {
              PRHARedundancyProvider.timedOut(this, null, null, "update an entry",
                  retryTimeout);
              // NOTREACHED
            }
            retryTime.waitToRetryNode();
          }
          event.setPossibleDuplicate(true);
          if (prMsg != null) {
            prMsg.setPossibleDuplicate(true);
          }
        } catch (PrimaryBucketException notPrimary) {
          if (logger.isDebugEnabled()) {
            logger.debug("Bucket {} on Node {} not primary", notPrimary.getLocalizedMessage(),
                currentTarget);
          }
          getRegionAdvisor().notPrimary(bucketId, currentTarget);
          if (retryTime == null) {
            retryTime = new RetryTimeKeeper(retryTimeout);
          }
          currentTarget = getNodeForBucketWrite(bucketId, retryTime);
        } catch (DataLocationException dle) {
          if (logger.isDebugEnabled()) {
            logger.debug("DataLocationException processing putAll", dle);
          }
          throw new TransactionException(dle);
        }

        // It's possible this is a GemFire thread e.g. ServerConnection
        // which got to this point because of a distributed system shutdown or
        // region closure which uses interrupt to break any sleep() or wait()
        // calls
        // e.g. waitForPrimary or waitForBucketRecovery in which case throw
        // exception
        checkShutdown();

        // If we get here, the attempt failed...
        if (count == 1) {
          prStats.incRemoveAllMsgsRetried();
        }
        prStats.incRemoveAllRetries();
      } // for
      // NOTREACHED
    } finally {
      event.release();
    }
  }

  public VersionedObjectList tryToSendOnePutAllMessage(PutAllPRMessage prMsg,
      InternalDistributedMember currentTarget) throws DataLocationException {
    boolean putResult = false;
    VersionedObjectList versions = null;
    final boolean isLocal = (localMaxMemory > 0) && currentTarget.equals(getMyId());
    if (isLocal) { // local
      // It might throw retry exception when one key failed
      // InternalDS has to be set for each msg
      prMsg.initMessage(this, null, false, null);
      putResult =
          prMsg.doLocalPutAll(this, getDistributionManager().getDistributionManagerId(), 0L);
      versions = prMsg.getVersions();
    } else {
      PutAllPRMessage.PutAllResponse response =
          (PutAllPRMessage.PutAllResponse) prMsg.send(currentTarget, this);
      PutAllPRMessage.PutAllResult pr = null;
      if (response != null) {
        prStats.incPartitionMessagesSent();
        try {
          pr = response.waitForResult();
          putResult = pr.returnValue;
          versions = pr.versions;
        } catch (RegionDestroyedException rde) {
          if (logger.isDebugEnabled()) {
            logger.debug("prMsg.send: caught RegionDestroyedException", rde);
          }
          throw new RegionDestroyedException(toString(), getFullPath());
        } catch (CacheException ce) {
          // Fix for bug 36014
          throw new PartitionedRegionDistributionException(
              "prMsg.send on " + currentTarget + " failed", ce);
        }
      } else {
        putResult = true; // follow the same behavior of putRemotely()
      }
    }

    if (!putResult) {
      // retry exception when msg failed in waitForResult()
      ForceReattemptException fre =
          new ForceReattemptException("false result in PutAllMessage.send - retrying");
      fre.setHash(0);
      throw fre;
    }
    return versions;
  }

  public VersionedObjectList tryToSendOneRemoveAllMessage(RemoveAllPRMessage prMsg,
      InternalDistributedMember currentTarget) throws DataLocationException {
    boolean putResult = false;
    VersionedObjectList versions = null;
    final boolean isLocal = (localMaxMemory > 0) && currentTarget.equals(getMyId());
    if (isLocal) { // local
      // It might throw retry exception when one key failed
      // InternalDS has to be set for each msg
      prMsg.initMessage(this, null, false, null);
      putResult = prMsg.doLocalRemoveAll(this,
          getDistributionManager().getDistributionManagerId(), true);
      versions = prMsg.getVersions();
    } else {
      RemoveAllPRMessage.RemoveAllResponse response =
          (RemoveAllPRMessage.RemoveAllResponse) prMsg.send(currentTarget, this);
      RemoveAllPRMessage.RemoveAllResult pr = null;
      if (response != null) {
        prStats.incPartitionMessagesSent();
        try {
          pr = response.waitForResult();
          putResult = pr.returnValue;
          versions = pr.versions;
        } catch (RegionDestroyedException rde) {
          if (logger.isDebugEnabled()) {
            logger.debug("prMsg.send: caught RegionDestroyedException", rde);
          }
          throw new RegionDestroyedException(toString(), getFullPath());
        } catch (CacheException ce) {
          // Fix for bug 36014
          throw new PartitionedRegionDistributionException(
              "prMsg.send on " + currentTarget + " failed", ce);
        }
      } else {
        putResult = true; // follow the same behavior of putRemotely()
      }
    }

    if (!putResult) {
      // retry exception when msg failed in waitForResult()
      ForceReattemptException fre =
          new ForceReattemptException("false result in PutAllMessage.send - retrying");
      fre.setHash(0);
      throw fre;
    }
    return versions;
  }

  /**
   * Performs the {@link Operation#UPDATE put} operation in the bucket on the remote VM and invokes
   * "put" callbacks
   *
   * @param targetNode the VM in whose {@link PartitionedRegionDataStore} contains the bucket
   * @param bucketId the identity of the bucket
   * @param event the event that contains the key and value
   * @param lastModified the timestamp that the entry was modified
   * @param ifNew true=can create a new key false=can't create a new key
   * @param ifOld true=can update existing entry false=can't update existing entry
   * @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.
   * @see LocalRegion#virtualPut(EntryEventImpl, boolean, boolean, Object, boolean, long, boolean)
   * @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.
   *
   */
  private boolean putInBucket(final InternalDistributedMember targetNode, final Integer bucketId,
      final EntryEventImpl event, final boolean ifNew, boolean ifOld, Object expectedOldValue,
      boolean requireOldValue, final long lastModified) {
    if (logger.isDebugEnabled()) {
      logger.debug("putInBucket: {} ({}) to {} to bucketId={} retry={} ms", event.getKey(),
          event.getKey().hashCode(), targetNode, bucketStringForLogs(bucketId), retryTimeout);
    }
    // retry the put remotely until it finds the right node managing the bucket

    RetryTimeKeeper retryTime = null;
    boolean result = false;
    InternalDistributedMember currentTarget = targetNode;
    long timeOut = 0;
    int count = 0;
    for (;;) {
      switch (count) {
        case 0:
          // Note we don't check for DM cancellation in common case.
          // First time. Assume success, keep going.
          break;
        case 1:
          cache.getCancelCriterion().checkCancelInProgress(null);
          // Second time (first failure). Calculate timeout and keep going.
          timeOut = System.currentTimeMillis() + retryTimeout;
          break;
        default:
          cache.getCancelCriterion().checkCancelInProgress(null);
          // test for timeout
          long timeLeft = timeOut - System.currentTimeMillis();
          if (timeLeft < 0) {
            PRHARedundancyProvider.timedOut(this, null, null, "update an entry", retryTimeout);
            // NOTREACHED
          }

          // Didn't time out. Sleep a bit and then continue
          boolean interrupted = Thread.interrupted();
          try {
            Thread.sleep(PartitionedRegionHelper.DEFAULT_WAIT_PER_RETRY_ITERATION);
          } catch (InterruptedException ignore) {
            interrupted = true;
          } finally {
            if (interrupted) {
              Thread.currentThread().interrupt();
            }
          }
          break;
      } // switch
      count++;

      if (currentTarget == null) { // pick target
        checkReadiness();
        if (retryTime == null) {
          retryTime = new RetryTimeKeeper(retryTimeout);
        }
        currentTarget = waitForNodeOrCreateBucket(retryTime, event, bucketId);

        // It's possible this is a GemFire thread e.g. ServerConnection
        // which got to this point because of a distributed system shutdown or
        // region closure which uses interrupt to break any sleep() or wait() calls
        // e.g. waitForPrimary or waitForBucketRecovery in which case throw exception
        checkShutdown();
        continue;
      } // pick target

      try {
        final boolean isLocal = (localMaxMemory > 0) && currentTarget.equals(getMyId());
        if (logger.isDebugEnabled()) {
          logger.debug("putInBucket: currentTarget = {}; ifNew = {}; ifOld = {}; isLocal = {}",
              currentTarget, ifNew, ifOld, isLocal);
        }
        checkIfAboveThreshold(event);
        if (isLocal) {
          event.setInvokePRCallbacks(true);
          long start = prStats.startPutLocal();
          try {
            final BucketRegion br =
                dataStore.getInitializedBucketForId(event.getKey(), bucketId);
            // Local updates should insert a serialized (aka CacheDeserializable) object
            // given that most manipulation of values is remote (requiring serialization to send).
            // But... function execution always implies local manipulation of
            // values so keeping locally updated values in Object form should be more efficient.
            if (!FunctionExecutionPooledExecutor.isFunctionExecutionThread()) {
              // TODO: this condition may not help since BucketRegion.virtualPut calls
              // forceSerialized
              br.forceSerialized(event);
            }
            if (ifNew) {
              result = dataStore.createLocally(br, event, ifNew, ifOld, requireOldValue,
                  lastModified);
            } else {
              result = dataStore.putLocally(br, event, ifNew, ifOld, expectedOldValue,
                  requireOldValue, lastModified);
            }
          } finally {
            prStats.endPutLocal(start);
          }
        } // local
        else { // remote
          // no need to perform early serialization (and create an un-necessary byte array)
          // sending the message performs that work.
          long start = prStats.startPutRemote();
          try {
            if (ifNew) {
              result = createRemotely(currentTarget, bucketId, event, requireOldValue);
            } else {
              result = putRemotely(currentTarget, event, ifNew, ifOld, expectedOldValue,
                  requireOldValue);
              if (!requireOldValue) {
                // make sure old value is set to NOT_AVAILABLE token
                event.oldValueNotAvailable();
              }
            }
          } finally {
            prStats.endPutRemote(start);
          }
        } // remote

        if (!result && !ifOld && !ifNew) {
          Assert.assertTrue(!isLocal);
          ForceReattemptException fre = new ForceReattemptException(
              "false result when !ifNew and !ifOld is unacceptable - retrying");
          fre.setHash(event.getKey().hashCode());
          throw fre;
        }

        return result;
      } catch (ConcurrentCacheModificationException e) {
        if (logger.isDebugEnabled()) {
          logger.debug("putInBucket: caught concurrent cache modification exception", e);
        }
        event.isConcurrencyConflict(true);

        if (logger.isTraceEnabled()) {
          logger.trace(
              "ConcurrentCacheModificationException received for putInBucket for bucketId: {}{}{} for event: {}  No reattampt is done, returning from here",
              getPRId(), BUCKET_ID_SEPARATOR, bucketId, event);
        }
        return result;
      } catch (ForceReattemptException prce) {
        prce.checkKey(event.getKey());
        if (logger.isDebugEnabled()) {
          logger.debug(
              "putInBucket: Got ForceReattemptException for {} on VM {} for node {}{}{} for bucket = {}",
              this, getMyId(), currentTarget, getPRId(), BUCKET_ID_SEPARATOR, bucketId, prce);
          logger.debug("putInBucket: count={}", count);
        }
        checkReadiness();
        InternalDistributedMember lastTarget = currentTarget;
        if (retryTime == null) {
          retryTime = new RetryTimeKeeper(retryTimeout);
        }
        currentTarget = getNodeForBucketWrite(bucketId, retryTime);
        if (lastTarget.equals(currentTarget)) {
          if (retryTime.overMaximum()) {
            PRHARedundancyProvider.timedOut(this, null, null, "update an entry", retryTimeout);
            // NOTREACHED
          }
          retryTime.waitToRetryNode();
        }
        event.setPossibleDuplicate(true);
      } catch (PrimaryBucketException notPrimary) {
        if (logger.isDebugEnabled()) {
          logger.debug("Bucket {} on Node {} not primary", notPrimary.getLocalizedMessage(),
              currentTarget);
        }
        getRegionAdvisor().notPrimary(bucketId, currentTarget);
        if (retryTime == null) {
          retryTime = new RetryTimeKeeper(retryTimeout);
        }
        currentTarget = getNodeForBucketWrite(bucketId, retryTime);
      }

      // It's possible this is a GemFire thread e.g. ServerConnection
      // which got to this point because of a distributed system shutdown or
      // region closure which uses interrupt to break any sleep() or wait()
      // calls
      // e.g. waitForPrimary or waitForBucketRecovery in which case throw
      // exception
      checkShutdown();

      // If we get here, the attempt failed...
      if (count == 1) {
        if (ifNew) {
          prStats.incCreateOpsRetried();
        } else {
          prStats.incPutOpsRetried();
        }
      }
      if (event.getOperation().isCreate()) {
        prStats.incCreateRetries();
      } else {
        prStats.incPutRetries();
      }

      if (logger.isDebugEnabled()) {
        logger.debug(
            "putInBucket for bucketId = {} failed (attempt # {} ({} ms left), retrying with node {}",
            bucketStringForLogs(bucketId), count, (timeOut - System.currentTimeMillis()),
            currentTarget);
      }
    } // for

    // NOTREACHED
  }


  /**
   * Find an existing live Node that owns the bucket, or create the bucket and return one of its
   * owners.
   *
   * @param retryTime the RetryTimeKeeper to track retry times
   * @param event the event used to get the entry size in the event a new bucket should be created
   * @param bucketId the identity of the bucket should it be created
   * @return a Node which contains the bucket, potentially null
   */
  private InternalDistributedMember waitForNodeOrCreateBucket(RetryTimeKeeper retryTime,
      EntryEventImpl event, Integer bucketId) {
    InternalDistributedMember newNode;
    if (retryTime.overMaximum()) {
      PRHARedundancyProvider.timedOut(this, null, null, "allocate a bucket",
          retryTime.getRetryTime());
      // NOTREACHED
    }

    retryTime.waitForBucketsRecovery();
    newNode = getNodeForBucketWrite(bucketId, retryTime);
    if (newNode == null) {
      newNode = createBucket(bucketId, getEntrySize(event), retryTime);
    }

    return newNode;
  }

  /**
   * Get the serialized size of an {@code EntryEventImpl}
   *
   * @param eei the entry from whcih to fetch the size
   * @return the size of the serialized entry
   */
  private static int getEntrySize(EntryEventImpl eei) {
    @Unretained
    final Object v = eei.getRawNewValue();
    if (v instanceof CachedDeserializable) {
      return ((Sizeable) v).getSizeInBytes();
    }
    return 0;
  }

  public InternalDistributedMember getOrCreateNodeForBucketWrite(int bucketId,
      final RetryTimeKeeper snoozer) {
    InternalDistributedMember targetNode = getNodeForBucketWrite(bucketId, snoozer);
    if (targetNode != null) {
      return targetNode;
    }

    try {
      return createBucket(bucketId, 0, null);
    } catch (PartitionedRegionStorageException e) {
      // try not to throw a PRSE if the cache is closing or this region was
      // destroyed during createBucket() (bug 36574)
      checkReadiness();
      if (cache.isClosed()) {
        throw new RegionDestroyedException(toString(), getFullPath());
      }
      throw e;
    }
  }

  /**
   * Fetch the primary Node returning if the redundancy for the Node is satisfied
   *
   * @param bucketId the identity of the bucket
   * @param snoozer a RetryTimeKeeper to track how long we may wait until the bucket is ready
   * @return the primary member's id or null if there is no storage
   */
  public InternalDistributedMember getNodeForBucketWrite(int bucketId,
      final RetryTimeKeeper snoozer) {
    final boolean isDebugEnabled = logger.isDebugEnabled();

    RetryTimeKeeper localSnoozer = snoozer;
    // Prevent early access to buckets that are not completely created/formed
    // and
    // prevent writing to a bucket whose redundancy is sub par
    while (minimumWriteRedundancy > 0
        && getRegionAdvisor().getBucketRedundancy(bucketId) < minimumWriteRedundancy) {
      cache.getCancelCriterion().checkCancelInProgress(null);

      // First check to see if there is any storage assigned TODO: redundant check to while
      // condition
      if (!getRegionAdvisor().isStorageAssignedForBucket(bucketId, minimumWriteRedundancy,
          false)) {
        if (isDebugEnabled) {
          logger.debug("No storage assigned for bucket ({}{}{}) writer", getPRId(),
              BUCKET_ID_SEPARATOR, bucketId);
        }
        return null; // No bucket for this key
      }

      if (localSnoozer == null) {
        localSnoozer = new RetryTimeKeeper(retryTimeout);
      }

      if (!localSnoozer.overMaximum()) {
        localSnoozer.waitForBucketsRecovery();
      } else {
        int red = getRegionAdvisor().getBucketRedundancy(bucketId);
        final TimeoutException noTime = new TimeoutException(
            String.format(
                "Attempt to acquire primary node for write on bucket %s timed out in %s ms. Current redundancy [ %s ] does not satisfy minimum [ %s ]",
                bucketStringForLogs(bucketId),
                localSnoozer.getRetryTime(), red, minimumWriteRedundancy));
        checkReadiness();
        throw noTime;
      }
    }
    // Possible race with loss of redundancy at this point.
    // This loop can possibly create a soft hang if no primary is ever selected.
    // This is preferable to returning null since it will prevent obtaining the
    // bucket lock for bucket creation.
    return waitForNoStorageOrPrimary(bucketId, "write");
  }

  /**
   * wait until there is a primary or there is no storage
   *
   * @param bucketId the id of the target bucket
   * @param readOrWrite a string used in log messages
   * @return the primary member's id or null if there is no storage
   */
  private InternalDistributedMember waitForNoStorageOrPrimary(int bucketId, String readOrWrite) {
    boolean isInterrupted = false;
    try {
      for (;;) {
        isInterrupted = Thread.interrupted() || isInterrupted;
        InternalDistributedMember d = getBucketPrimary(bucketId);
        if (d != null) {
          return d; // success!
        } else {
          // go around the loop again
          if (logger.isDebugEnabled()) {
            logger.debug("No primary node found for bucket ({}{}{}) {}", getPRId(),
                BUCKET_ID_SEPARATOR, bucketId, readOrWrite);
          }
        }
        if (!getRegionAdvisor().isStorageAssignedForBucket(bucketId)) {
          if (logger.isDebugEnabled()) {
            logger.debug("No storage while waiting for primary for bucket ({}{}{}) {}", getPRId(),
                BUCKET_ID_SEPARATOR, bucketId, readOrWrite);
          }
          return null; // No bucket for this key
        }
        checkShutdown();
      }
    } finally {
      if (isInterrupted) {
        Thread.currentThread().interrupt();
      }
    }
  }

  /**
   * override the one in LocalRegion since we don't need to do getDeserialized.
   */
  @Override
  public Object get(Object key, Object aCallbackArgument, boolean generateCallbacks,
      boolean disableCopyOnRead, boolean preferCD, ClientProxyMembershipID requestingClient,
      EntryEventImpl clientEvent, boolean returnTombstones)
      throws TimeoutException, CacheLoaderException {
    validateKey(key);
    checkReadiness();
    checkForNoAccess();
    discoverJTA();
    boolean miss = true;
    Object value = getDataView().findObject(getKeyInfo(key, aCallbackArgument), this,
        true/* isCreate */, generateCallbacks, null /* no local value */, disableCopyOnRead,
        preferCD, requestingClient, clientEvent, returnTombstones);
    if (value != null && !Token.isInvalid(value)) {
      miss = false;
    }
    return value;
  }

  @Override
  protected long startGet() {
    return 0;
  }

  @Override
  protected void endGet(long start, boolean isMiss) {
    // get stats are recorded by the BucketRegion
    // so nothing is needed on the PartitionedRegion.
  }

  public InternalDistributedMember getOrCreateNodeForBucketRead(int bucketId) {
    InternalDistributedMember targetNode = getNodeForBucketRead(bucketId);
    if (targetNode != null) {
      return targetNode;
    }
    try {
      return createBucket(bucketId, 0, null);
    } catch (PartitionedRegionStorageException e) {
      // try not to throw a PRSE if the cache is closing or this region was
      // destroyed during createBucket() (bug 36574)
      checkReadiness();
      if (cache.isClosed()) {
        throw new RegionDestroyedException(toString(), getFullPath());
      }
      throw e;
    }
  }

  /**
   * Gets the Node for reading a specific bucketId. This method gives priority to local node to
   * speed up operation and avoid remote calls.
   *
   * @param bucketId identifier for bucket
   *
   * @return the primary member's id or null if there is no storage
   */
  public InternalDistributedMember getNodeForBucketRead(int bucketId) {
    // Wait until there is storage
    InternalDistributedMember primary = waitForNoStorageOrPrimary(bucketId, "read");
    if (primary == null) {
      return null;
    }
    if (isTX()) {
      return getNodeForBucketWrite(bucketId, null);
    }
    return getRegionAdvisor().getPreferredNode(bucketId);
  }

  /**
   * Gets the Node for reading or performing a load from a specific bucketId.
   *
   * @return the member from which to read or load
   * @since GemFire 5.7
   */
  private InternalDistributedMember getNodeForBucketReadOrLoad(int bucketId) {
    InternalDistributedMember targetNode;
    if (!haveCacheLoader) {
      targetNode = getNodeForBucketRead(bucketId);
    } else {
      targetNode = getNodeForBucketWrite(bucketId, null /* retryTimeKeeper */);
    }
    if (targetNode == null) {
      checkShutdown(); // Fix for bug#37207
      targetNode = createBucket(bucketId, 0 /* size */, null /* retryTimeKeeper */);
    }
    return targetNode;
  }

  /**
   * Puts the key/value pair into the remote target that is managing the key's bucket.
   *
   * @param recipient the member to receive the message
   * @param event the event prompting this action
   * @param ifNew the mysterious ifNew parameter
   * @param ifOld the mysterious ifOld parameter
   * @return whether the operation succeeded
   * @throws PrimaryBucketException if the remote bucket was not the primary
   * @throws ForceReattemptException if the peer is no longer available
   */
  public boolean putRemotely(final DistributedMember recipient, final EntryEventImpl event,
      boolean ifNew, boolean ifOld, Object expectedOldValue, boolean requireOldValue)
      throws PrimaryBucketException, ForceReattemptException {
    // boolean forceAck = basicGetWriter() != null
    // || getDistributionAdvisor().adviseNetWrite().size() > 0;
    long eventTime = event.getEventTime(0L);
    PutMessage.PutResponse response = (PutMessage.PutResponse) PutMessage.send(recipient, this,
        event, eventTime, ifNew, ifOld, expectedOldValue, requireOldValue);
    PutResult pr = null;
    if (response != null) {
      prStats.incPartitionMessagesSent();
      try {
        pr = response.waitForResult();
        event.setOperation(pr.op);
        event.setVersionTag(pr.versionTag);
        if (requireOldValue) {
          event.setOldValue(pr.oldValue, true);
        }
        return pr.returnValue;
      } catch (RegionDestroyedException rde) {
        if (logger.isDebugEnabled()) {
          logger.debug("putRemotely: caught RegionDestroyedException", rde);
        }
        throw new RegionDestroyedException(toString(), getFullPath());
      } catch (TransactionException te) {
        throw te;
      } catch (CacheException ce) {
        // Fix for bug 36014
        throw new PartitionedRegionDistributionException(
            String.format("Putting entry on %s failed",
                recipient),
            ce);
      }
    }
    return true;// ???:ezoerner:20080728 why return true if response was null?
  }

  /**
   * Create a bucket for the provided bucket identifier in an atomic fashion.
   *
   * @param bucketId the bucket identifier for the bucket that needs creation
   * @param snoozer tracking object used to determine length of time t for bucket creation
   * @return a selected Node on which to perform bucket operations
   */
  public InternalDistributedMember createBucket(int bucketId, int size,
      final RetryTimeKeeper snoozer) {

    InternalDistributedMember ret = getNodeForBucketWrite(bucketId, snoozer);
    if (ret != null) {
      return ret;
    }
    // In the current co-location scheme, we have to create the bucket for the
    // colocatedWith region, before we create bucket for this region
    final PartitionedRegion colocatedWith = ColocationHelper.getColocatedRegion(this);
    if (colocatedWith != null) {
      colocatedWith.createBucket(bucketId, size, snoozer);
    }

    // THis is for FPR.if the given bucket id is not starting bucket id then
    // create bucket for starting bucket id
    String partitionName = null;
    if (isFixedPartitionedRegion()) {
      FixedPartitionAttributesImpl fpa =
          PartitionedRegionHelper.getFixedPartitionAttributesForBucket(this, bucketId);
      partitionName = fpa.getPartitionName();
      int startBucketId = fpa.getStartingBucketID();
      if (startBucketId == -1) {
        throw new PartitionNotAvailableException(
            String.format(
                "For FixedPartitionedRegion %s, Partition %s is not yet initialized on datastore",
                getName(), partitionName));
      }
      if (startBucketId != bucketId) {
        createBucket(startBucketId, size, snoozer);
      }
    }
    // Potentially no storage assigned, start bucket creation, be careful of race
    // conditions
    final long startTime = prStats.getTime();
    if (isDataStore()) {
      ret = redundancyProvider.createBucketAtomically(bucketId, size, false,
          partitionName);
    } else {
      ret = redundancyProvider.createBucketOnDataStore(bucketId, size, snoozer);
    }
    return ret;
  }

  @Override
  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 {
    Object obj = null;
    final Object key = keyInfo.getKey();
    final Object aCallbackArgument = keyInfo.getCallbackArg();
    final long startTime = prStats.getTime();
    try {
      int bucketId = keyInfo.getBucketId();
      if (bucketId == KeyInfo.UNKNOWN_BUCKET) {
        bucketId = PartitionedRegionHelper.getHashKey(this, isCreate ? Operation.CREATE : null, key,
            null, aCallbackArgument);
        keyInfo.setBucketId(bucketId);
      }
      InternalDistributedMember targetNode = null;
      TXStateProxy txState = getTXState();
      boolean allowRetry;
      if (txState != null) {
        if (txState.isRealDealLocal()) {
          targetNode = getMyId();
        } else {
          targetNode = (InternalDistributedMember) txState.getTarget();
          assert targetNode != null;
        }
        allowRetry = false;
      } else {
        targetNode = getBucketNodeForReadOrWrite(bucketId, clientEvent);
        allowRetry = true;
      }
      if (targetNode == null) {
        if (logger.isDebugEnabled()) {
          logger.debug("No need to create buckets on get(), no CacheLoader configured.");
        }
        return null;
      }

      obj = getFromBucket(targetNode, bucketId, key, aCallbackArgument, disableCopyOnRead, preferCD,
          requestingClient, clientEvent, returnTombstones, allowRetry);
    } finally {
      prStats.endGet(startTime);
    }
    return obj;
  }

  InternalDistributedMember getBucketNodeForReadOrWrite(int bucketId,
      EntryEventImpl clientEvent) {
    InternalDistributedMember targetNode;
    if (clientEvent != null && clientEvent.getOperation() != null
        && clientEvent.getOperation().isGetForRegisterInterest()) {
      targetNode = getNodeForBucketWrite(bucketId, null);
    } else {
      targetNode = getNodeForBucketReadOrLoad(bucketId);
    }
    return targetNode;
  }

  /**
   * 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 6.0
   */
  public ResultCollector executeFunction(final Function function,
      final PartitionedRegionFunctionExecutor execution, ResultCollector rc,
      boolean executeOnBucketSet) {
    if (execution.isPrSingleHop()) {
      if (!executeOnBucketSet) {
        switch (execution.getFilter().size()) {
          case 1:
            if (logger.isDebugEnabled()) {
              logger.debug("Executing Function: (Single Hop) {} on single node.", function.getId());
            }
            return executeOnSingleNode(function, execution, rc, true, false);
          default:
            if (logger.isDebugEnabled()) {
              logger.debug("Executing Function: (Single Hop) {} on multiple nodes.",
                  function.getId());
            }
            return executeOnMultipleNodes(function, execution, rc, true, false);
        }
      } else {
        if (logger.isDebugEnabled()) {
          logger.debug("Executing Function: (Single Hop) {} on a set of buckets nodes.",
              function.getId());
        }
        return executeOnBucketSet(function, execution, rc, execution.getFilter());
      }
    } else {
      switch (execution.getFilter().size()) {
        case 0:
          if (logger.isDebugEnabled()) {
            logger.debug("Executing Function: {} setArguments={} on all buckets.", function.getId(),
                execution.getArguments());
          }
          return executeOnAllBuckets(function, execution, rc, false);
        case 1:
          if (logger.isDebugEnabled()) {
            logger.debug("Executing Function: {} setArguments={} on single node.", function.getId(),
                execution.getArguments());
          }
          return executeOnSingleNode(function, execution, rc, false, executeOnBucketSet);
        default:
          if (logger.isDebugEnabled()) {
            logger.debug("Executing Function: {} setArguments={} on multiple nodes.",
                function.getId(), execution.getArguments());
          }
          return executeOnMultipleNodes(function, execution, rc, false, executeOnBucketSet);
      }
    }
  }

  /**
   * Executes function on multiple nodes
   */
  private ResultCollector executeOnMultipleNodes(final Function function,
      final PartitionedRegionFunctionExecutor execution, ResultCollector rc, boolean isPRSingleHop,
      boolean isBucketSetAsFilter) {
    final Set routingKeys = execution.getFilter();
    final boolean primaryMembersNeeded = function.optimizeForWrite();
    Map<Integer, Set> bucketToKeysMap = FunctionExecutionNodePruner.groupByBucket(this,
        routingKeys, primaryMembersNeeded, false, isBucketSetAsFilter);
    HashMap<InternalDistributedMember, HashSet> memberToKeysMap =
        new HashMap<>();
    HashMap<InternalDistributedMember, int[]> memberToBuckets =
        FunctionExecutionNodePruner.groupByMemberToBuckets(this, bucketToKeysMap.keySet(),
            primaryMembersNeeded);

    if (isPRSingleHop && (memberToBuckets.size() > 1)) {
      // memberToBuckets.remove(getMyId()); // don't remove
      for (InternalDistributedMember targetNode : memberToBuckets.keySet()) {
        if (!targetNode.equals(getMyId())) {
          int[] bucketArray = memberToBuckets.get(targetNode);
          int length = BucketSetHelper.length(bucketArray);
          if (length == 0) {
            continue;
          }
          for (int i = 0; i < length; i++) {
            int bucketId = BucketSetHelper.get(bucketArray, i);
            Set<ServerBucketProfile> profiles =
                getRegionAdvisor().getClientBucketProfiles(bucketId);
            if (profiles != null) {
              for (ServerBucketProfile profile : profiles) {
                if (profile.getDistributedMember().equals(targetNode)) {
                  if (logger.isDebugEnabled()) {
                    logger.debug("FunctionServiceSingleHop: Found multiple nodes.{}", getMyId());
                  }
                  throw new InternalFunctionInvocationTargetException(
                      "Multiple target nodes found for single hop operation");
                }
              }
            }
          }
        }
      }
    }

    while (!execution.getFailedNodes().isEmpty()) {
      Set memberKeySet = memberToBuckets.keySet();
      RetryTimeKeeper retryTime = new RetryTimeKeeper(retryTimeout);
      Iterator iterator = memberKeySet.iterator();

      boolean hasRemovedNode = false;

      while (iterator.hasNext()) {
        if (execution.getFailedNodes().contains(((DistributedMember) iterator.next()).getId())) {
          hasRemovedNode = true;
        }
      }

      if (hasRemovedNode) {
        if (retryTime.overMaximum()) {
          PRHARedundancyProvider.timedOut(this, null, null, "doing function execution",
              retryTimeout);
          // NOTREACHED
        }
        retryTime.waitToRetryNode();
        memberToBuckets = FunctionExecutionNodePruner.groupByMemberToBuckets(this,
            bucketToKeysMap.keySet(), primaryMembersNeeded);

      } else {
        execution.clearFailedNodes();
      }
    }

    for (Map.Entry entry : memberToBuckets.entrySet()) {
      InternalDistributedMember member = (InternalDistributedMember) entry.getKey();
      int[] buckets = (int[]) entry.getValue();
      int length = BucketSetHelper.length(buckets);
      if (length == 0) {
        continue;
      }
      int bucket;
      for (int i = 0; i < length; i++) {
        bucket = BucketSetHelper.get(buckets, i);
        HashSet keys = memberToKeysMap.get(member);
        if (keys == null) {
          keys = new HashSet();
        }
        keys.addAll(bucketToKeysMap.get(bucket));
        memberToKeysMap.put(member, keys);
      }
    }
    // memberToKeysMap.keySet().retainAll(memberToBuckets.keySet());
    if (memberToKeysMap.isEmpty()) {
      throw new FunctionException(String.format("No target node found for KEY, %s",
          routingKeys));
    }
    Set<InternalDistributedMember> dest = memberToKeysMap.keySet();
    execution.validateExecution(function, dest);
    // added for the data aware procedure.
    execution.setExecutionNodes(dest);
    // end

    final HashSet localKeys = memberToKeysMap.remove(getMyId());
    int[] localBucketSet = null;
    boolean remoteOnly = false;
    if (localKeys == null) {
      remoteOnly = true;
    } else {
      localBucketSet = FunctionExecutionNodePruner.getBucketSet(this, localKeys,
          false, isBucketSetAsFilter);

      remoteOnly = false;
    }
    final LocalResultCollector<?, ?> localResultCollector =
        execution.getLocalResultCollector(function, rc);
    final DistributionManager dm = getDistributionManager();
    final PartitionedRegionFunctionResultSender resultSender =
        new PartitionedRegionFunctionResultSender(dm, this, 0L, localResultCollector,
            execution.getServerResultSender(), memberToKeysMap.isEmpty(), remoteOnly,
            execution.isForwardExceptions(), function, localBucketSet);

    if (localKeys != null) {
      final RegionFunctionContextImpl prContext =
          new RegionFunctionContextImpl(cache, function.getId(), this,
              execution.getArgumentsForMember(getMyId().getId()),
              localKeys, ColocationHelper
                  .constructAndGetAllColocatedLocalDataSet(this, localBucketSet),
              localBucketSet, resultSender, execution.isReExecute());
      if (logger.isDebugEnabled()) {
        logger.debug("FunctionService: Executing on local node with keys.{}", localKeys);
      }
      execution.executeFunctionOnLocalPRNode(function, prContext, resultSender, dm, isTX());
    }

    if (!memberToKeysMap.isEmpty()) {
      HashMap<InternalDistributedMember, FunctionRemoteContext> recipMap =
          new HashMap<>();
      for (Map.Entry me : memberToKeysMap.entrySet()) {
        InternalDistributedMember recip = (InternalDistributedMember) me.getKey();
        HashSet memKeys = (HashSet) me.getValue();
        FunctionRemoteContext context = new FunctionRemoteContext(function,
            execution.getArgumentsForMember(recip.getId()), memKeys,
            FunctionExecutionNodePruner.getBucketSet(this, memKeys, false, isBucketSetAsFilter),
            execution.isReExecute(), execution.isFnSerializationReqd(), getPrincipal());
        recipMap.put(recip, context);
      }
      if (logger.isDebugEnabled()) {
        logger.debug("FunctionService: Executing on remote nodes with member to keys map.{}",
            memberToKeysMap);
      }
      PartitionedRegionFunctionResultWaiter resultReceiver =
          new PartitionedRegionFunctionResultWaiter(getSystem(), getPRId(),
              localResultCollector, function, resultSender);
      return resultReceiver.getPartitionedDataFrom(recipMap, this, execution);
    }
    return localResultCollector;
  }

  private Object getPrincipal() {
    return cache.getSecurityService().getPrincipal();
  }

  /**
   * Single key execution on single node
   *
   * @since GemFire 6.0
   */
  private ResultCollector executeOnSingleNode(final Function function,
      final PartitionedRegionFunctionExecutor execution, ResultCollector rc, boolean isPRSingleHop,
      boolean isBucketSetAsFilter) {
    final Set routingKeys = execution.getFilter();
    final Object key = routingKeys.iterator().next();
    final Integer bucketId;
    if (isBucketSetAsFilter) {
      bucketId = (Integer) key;
    } else {
      bucketId =
          PartitionedRegionHelper.getHashKey(this, Operation.FUNCTION_EXECUTION, key, null, null);
    }
    InternalDistributedMember targetNode = null;
    if (function.optimizeForWrite()) {
      targetNode = createBucket(bucketId, 0, null /* retryTimeKeeper */);
      cache.getInternalResourceManager().getHeapMonitor().checkForLowMemory(function, targetNode);
    } else {
      targetNode = getOrCreateNodeForBucketRead(bucketId);
    }
    final DistributedMember localVm = getMyId();
    if (targetNode != null && isPRSingleHop && !localVm.equals(targetNode)) {
      Set<ServerBucketProfile> profiles = getRegionAdvisor().getClientBucketProfiles(bucketId);
      if (profiles != null) {
        for (ServerBucketProfile profile : profiles) {
          if (profile.getDistributedMember().equals(targetNode)) {
            if (logger.isDebugEnabled()) {
              logger.debug("FunctionServiceSingleHop: Found remote node.{}", localVm);
            }
            throw new InternalFunctionInvocationTargetException(
                "Multiple target nodes found for single hop operation");
          }
        }
      }
    }

    if (targetNode == null) {
      throw new FunctionException(
          String.format("No target node found for KEY, %s", key));
    }

    if (logger.isDebugEnabled()) {
      logger.debug("Executing Function: {} setArguments={} on {}", function.getId(),
          execution.getArguments(), targetNode);
    }
    while (!execution.getFailedNodes().isEmpty()) {
      RetryTimeKeeper retryTime = new RetryTimeKeeper(retryTimeout);
      if (execution.getFailedNodes().contains(targetNode.getId())) {
        /*
         * if (retryTime.overMaximum()) { PRHARedundancyProvider.timedOut(this, null, null,
         * "doing function execution", this.retryTimeout); // NOTREACHED }
         */
        // Fix for Bug # 40083
        targetNode = null;
        while (targetNode == null) {
          if (retryTime.overMaximum()) {
            PRHARedundancyProvider.timedOut(this, null, null, "doing function execution",
                retryTimeout);
            // NOTREACHED
          }
          retryTime.waitToRetryNode();
          if (function.optimizeForWrite()) {
            targetNode = getOrCreateNodeForBucketWrite(bucketId, retryTime);
          } else {
            targetNode = getOrCreateNodeForBucketRead(bucketId);
          }
        }
      } else {
        execution.clearFailedNodes();
      }
    }

    final int[] buckets = new int[2];
    buckets[0] = 0;
    BucketSetHelper.add(buckets, bucketId);
    final Set<InternalDistributedMember> singleMember = Collections.singleton(targetNode);
    execution.validateExecution(function, singleMember);
    execution.setExecutionNodes(singleMember);
    LocalResultCollector<?, ?> localRC = execution.getLocalResultCollector(function, rc);
    if (targetNode.equals(localVm)) {
      final DistributionManager dm = getDistributionManager();
      PartitionedRegionFunctionResultSender resultSender =
          new PartitionedRegionFunctionResultSender(dm, this, 0, localRC,
              execution.getServerResultSender(), true, false, execution.isForwardExceptions(),
              function, buckets);
      final FunctionContext context =
          new RegionFunctionContextImpl(cache, function.getId(), this,
              execution.getArgumentsForMember(localVm.getId()), routingKeys, ColocationHelper
                  .constructAndGetAllColocatedLocalDataSet(this, buckets),
              buckets, resultSender, execution.isReExecute());
      execution.executeFunctionOnLocalPRNode(function, context, resultSender, dm, isTX());
      return localRC;
    } else {
      return executeFunctionOnRemoteNode(targetNode, function,
          execution.getArgumentsForMember(targetNode.getId()), routingKeys,
          function.isHA() ? rc : localRC, buckets, execution.getServerResultSender(), execution);
    }
  }

  public ResultCollector executeOnBucketSet(final Function function,
      PartitionedRegionFunctionExecutor execution, ResultCollector rc, Set<Integer> bucketSet) {
    Set<Integer> actualBucketSet = getRegionAdvisor().getBucketSet();
    try {
      bucketSet.retainAll(actualBucketSet);
    } catch (NoSuchElementException ignore) {
      // done
    }
    HashMap<InternalDistributedMember, int[]> memberToBuckets =
        FunctionExecutionNodePruner.groupByMemberToBuckets(this, bucketSet,
            function.optimizeForWrite());

    if (memberToBuckets.isEmpty()) {
      if (logger.isDebugEnabled()) {
        logger.debug(
            "Executing on bucketset : {} executeOnBucketSet Member to buckets map is : {} bucketSet is empty",
            bucketSet, memberToBuckets);
      }
      throw new EmptyRegionFunctionException(
          "Region is empty and the function cannot be executed");
    } else {
      if (logger.isDebugEnabled()) {
        logger.debug("Executing on bucketset : {} executeOnBucketSet Member to buckets map is : {}",
            bucketSet, memberToBuckets);

      }
    }

    if (memberToBuckets.size() > 1) {
      for (InternalDistributedMember targetNode : memberToBuckets.keySet()) {
        if (!targetNode.equals(getMyId())) {
          int[] bucketArray = memberToBuckets.get(targetNode);
          int length = BucketSetHelper.length(bucketArray);
          if (length == 0) {
            continue;
          }
          for (int i = 0; i < length; i++) {
            int bucketId = BucketSetHelper.get(bucketArray, i);
            Set<ServerBucketProfile> profiles =
                getRegionAdvisor().getClientBucketProfiles(bucketId);
            if (profiles != null) {
              for (ServerBucketProfile profile : profiles) {
                if (profile.getDistributedMember().equals(targetNode)) {
                  if (logger.isDebugEnabled()) {
                    logger.debug(
                        "FunctionServiceSingleHop: Found multiple nodes for executing on bucket set.{}",
                        getMyId());
                  }
                  throw new InternalFunctionInvocationTargetException(
                      "Multiple target nodes found for single hop operation");
                }
              }
            }
          }
        }
      }
    }

    execution = (PartitionedRegionFunctionExecutor) execution.withFilter(new HashSet());
    while (!execution.getFailedNodes().isEmpty()) {
      Set memberKeySet = memberToBuckets.keySet();
      RetryTimeKeeper retryTime = new RetryTimeKeeper(retryTimeout);
      Iterator iterator = memberKeySet.iterator();
      boolean hasRemovedNode = false;

      while (iterator.hasNext()) {
        if (execution.getFailedNodes().contains(((DistributedMember) iterator.next()).getId())) {
          hasRemovedNode = true;
        }
      }

      if (hasRemovedNode) {
        if (retryTime.overMaximum()) {
          PRHARedundancyProvider.timedOut(this, null, null, "doing function execution",
              retryTimeout);
          // NOTREACHED
        }
        retryTime.waitToRetryNode();
        memberToBuckets = FunctionExecutionNodePruner.groupByMemberToBuckets(this, bucketSet,
            function.optimizeForWrite());
      } else {
        execution.clearFailedNodes();
      }
    }

    Set<InternalDistributedMember> dest = memberToBuckets.keySet();
    cache.getInternalResourceManager().getHeapMonitor().checkForLowMemory(function,
        Collections.unmodifiableSet(dest));

    boolean isSelf = false;
    execution.setExecutionNodes(dest);
    final int[] localBucketSet = memberToBuckets.remove(getMyId());
    if (BucketSetHelper.length(localBucketSet) > 0) {
      isSelf = true;
    }
    final HashMap<InternalDistributedMember, FunctionRemoteContext> recipMap =
        new HashMap<>();
    for (InternalDistributedMember recip : dest) {
      FunctionRemoteContext context = new FunctionRemoteContext(function,
          execution.getArgumentsForMember(recip.getId()), null, memberToBuckets.get(recip),
          execution.isReExecute(), execution.isFnSerializationReqd(), getPrincipal());
      recipMap.put(recip, context);
    }
    final LocalResultCollector<?, ?> localRC = execution.getLocalResultCollector(function, rc);

    final DistributionManager dm = getDistributionManager();
    final PartitionedRegionFunctionResultSender resultSender =
        new PartitionedRegionFunctionResultSender(dm, this, 0L, localRC,
            execution.getServerResultSender(), recipMap.isEmpty(), !isSelf,
            execution.isForwardExceptions(), function, localBucketSet);

    // execute locally and collect the result
    if (isSelf && dataStore != null) {
      final RegionFunctionContextImpl prContext =
          new RegionFunctionContextImpl(cache, function.getId(), this,
              execution.getArgumentsForMember(getMyId().getId()), null, ColocationHelper
                  .constructAndGetAllColocatedLocalDataSet(this, localBucketSet),
              localBucketSet, resultSender, execution.isReExecute());
      execution.executeFunctionOnLocalNode(function, prContext, resultSender, dm, isTX());
    }
    PartitionedRegionFunctionResultWaiter resultReceiver =
        new PartitionedRegionFunctionResultWaiter(getSystem(), getPRId(), localRC, function,
            resultSender);

    return resultReceiver.getPartitionedDataFrom(recipMap, this, execution);
  }

  /**
   * Executes function on all bucket nodes
   *
   * @since GemFire 6.0
   */
  private ResultCollector executeOnAllBuckets(final Function function,
      final PartitionedRegionFunctionExecutor execution, ResultCollector rc,
      boolean isPRSingleHop) {
    Set<Integer> bucketSet = new HashSet<>();
    Iterator<Integer> itr = getRegionAdvisor().getBucketSet().iterator();
    while (itr.hasNext()) {
      try {
        bucketSet.add(itr.next());
      } catch (NoSuchElementException ignore) {
      }
    }
    HashMap<InternalDistributedMember, int[]> memberToBuckets =
        FunctionExecutionNodePruner.groupByMemberToBuckets(this, bucketSet,
            function.optimizeForWrite());

    if (memberToBuckets.isEmpty()) {
      throw new EmptyRegionFunctionException(
          "Region is empty and the function cannot be executed");
    }

    while (!execution.getFailedNodes().isEmpty()) {
      Set memberKeySet = memberToBuckets.keySet();
      RetryTimeKeeper retryTime = new RetryTimeKeeper(retryTimeout);

      Iterator iterator = memberKeySet.iterator();

      boolean hasRemovedNode = false;

      while (iterator.hasNext()) {
        if (execution.getFailedNodes().contains(((DistributedMember) iterator.next()).getId())) {
          hasRemovedNode = true;
        }
      }

      if (hasRemovedNode) {
        if (retryTime.overMaximum()) {
          PRHARedundancyProvider.timedOut(this, null, null, "doing function execution",
              retryTimeout);
          // NOTREACHED
        }
        retryTime.waitToRetryNode();
        memberToBuckets = FunctionExecutionNodePruner.groupByMemberToBuckets(this, bucketSet,
            function.optimizeForWrite());
      } else {
        execution.clearFailedNodes();
      }
    }

    Set<InternalDistributedMember> dest = memberToBuckets.keySet();
    execution.validateExecution(function, dest);
    execution.setExecutionNodes(dest);

    boolean isSelf = false;
    final int[] localBucketSet = memberToBuckets.remove(getMyId());
    if (BucketSetHelper.length(localBucketSet) > 0) {
      isSelf = true;
    }
    final HashMap<InternalDistributedMember, FunctionRemoteContext> recipMap =
        new HashMap<>();
    for (InternalDistributedMember recip : memberToBuckets.keySet()) {
      FunctionRemoteContext context = new FunctionRemoteContext(function,
          execution.getArgumentsForMember(recip.getId()), null, memberToBuckets.get(recip),
          execution.isReExecute(), execution.isFnSerializationReqd(), getPrincipal());
      recipMap.put(recip, context);
    }
    final LocalResultCollector<?, ?> localResultCollector =
        execution.getLocalResultCollector(function, rc);
    final DistributionManager dm = getDistributionManager();
    final PartitionedRegionFunctionResultSender resultSender =
        new PartitionedRegionFunctionResultSender(dm, this, 0L, localResultCollector,
            execution.getServerResultSender(), recipMap.isEmpty(), !isSelf,
            execution.isForwardExceptions(), function, localBucketSet);

    // execute locally and collect the result
    if (isSelf && dataStore != null) {
      final RegionFunctionContextImpl prContext =
          new RegionFunctionContextImpl(cache, function.getId(), this,
              execution.getArgumentsForMember(getMyId().getId()), null, ColocationHelper
                  .constructAndGetAllColocatedLocalDataSet(this, localBucketSet),
              localBucketSet, resultSender, execution.isReExecute());
      execution.executeFunctionOnLocalPRNode(function, prContext, resultSender, dm, isTX());
    }
    PartitionedRegionFunctionResultWaiter resultReceiver =
        new PartitionedRegionFunctionResultWaiter(getSystem(), getPRId(), localResultCollector,
            function, resultSender);

    return resultReceiver.getPartitionedDataFrom(recipMap, this, execution);
  }

  /**
   * @param requestingClient the client requesting the object, or null if not from a client
   * @param allowRetry if false then do not retry
   */
  private Object getFromBucket(final InternalDistributedMember targetNode, int bucketId,
      final Object key, final Object aCallbackArgument, boolean disableCopyOnRead, boolean preferCD,
      ClientProxyMembershipID requestingClient, EntryEventImpl clientEvent,
      boolean returnTombstones, boolean allowRetry) {
    final boolean isDebugEnabled = logger.isDebugEnabled();

    final int retryAttempts = calcRetry();
    Object obj;
    // retry the get remotely until it finds the right node managing the bucket
    int count = 0;
    RetryTimeKeeper retryTime = null;
    InternalDistributedMember retryNode = targetNode;
    while (count <= retryAttempts) {
      // Every continuation should check for DM cancellation
      if (retryNode == null) {
        checkReadiness();
        if (retryTime == null) {
          retryTime = new RetryTimeKeeper(retryTimeout);
        }
        retryNode = getNodeForBucketReadOrLoad(bucketId);

        // No storage found for bucket, early out preventing hot loop, bug 36819
        if (retryNode == null) {
          checkShutdown();
          return null;
        }
        continue;
      }
      final boolean isLocal = localMaxMemory > 0 && retryNode.equals(getMyId());

      try {
        if (isLocal) {
          obj = dataStore.getLocally(bucketId, key, aCallbackArgument, disableCopyOnRead,
              preferCD, requestingClient, clientEvent, returnTombstones, false);
        } else {
          if (haveCacheLoader) {
            // If the region has a cache loader,
            // the target node is the primary server of the bucket. But, if the
            // value can be found in a local bucket, we should first try there.

            /* MergeGemXDHDFSToGFE -readoing from local bucket was disabled in GemXD */
            if (null != (obj = getFromLocalBucket(bucketId, key, aCallbackArgument,
                disableCopyOnRead, preferCD, requestingClient, clientEvent, returnTombstones))) {
              return obj;
            }
          }

          obj = getRemotely(retryNode, bucketId, key, aCallbackArgument, preferCD, requestingClient,
              clientEvent, returnTombstones);

          // TODO: there should be better way than this one
          String name = Thread.currentThread().getName();
          if (name.startsWith("ServerConnection") && !getMyId().equals(retryNode)) {
            setNetworkHopType(bucketId, retryNode);
          }
        }
        return obj;
      } catch (PRLocallyDestroyedException pde) {
        if (isDebugEnabled) {
          logger.debug("getFromBucket Encountered PRLocallyDestroyedException", pde);
        }
        checkReadiness();
        if (allowRetry) {
          retryNode = getNodeForBucketReadOrLoad(bucketId);
        } else {
          // Only transactions set allowRetry to false,
          // fail the transaction here as region is destroyed.
          Throwable cause = pde.getCause();
          if (cause != null && cause instanceof RegionDestroyedException) {
            throw (RegionDestroyedException) cause;
          } else {
            // Should not see it currently, all current constructors of PRLocallyDestroyedException
            // set the cause to RegionDestroyedException.
            throw new RegionDestroyedException(toString(), getFullPath());
          }
        }
      } catch (ForceReattemptException prce) {
        prce.checkKey(key);
        checkReadiness();

        if (allowRetry) {
          InternalDistributedMember lastNode = retryNode;
          if (isDebugEnabled) {
            logger.debug("getFromBucket: retry attempt: {} of {}", count, retryAttempts, prce);
          }
          retryNode = getNodeForBucketReadOrLoad(bucketId);
          if (lastNode.equals(retryNode)) {
            if (retryTime == null) {
              retryTime = new RetryTimeKeeper(retryTimeout);
            }
            if (retryTime.overMaximum()) {
              break;
            }
            if (isDebugEnabled) {
              logger.debug("waiting to retry node {}", retryNode);
            }
            retryTime.waitToRetryNode();
          }
        } else {
          // with transaction
          handleForceReattemptExceptionWithTransaction(prce);
        }
      } catch (PrimaryBucketException notPrimary) {
        if (allowRetry) {
          if (isDebugEnabled) {
            logger.debug("getFromBucket: {} on Node {} not primary",
                notPrimary.getLocalizedMessage(), retryNode);
          }
          getRegionAdvisor().notPrimary(bucketId, retryNode);
          retryNode = getNodeForBucketReadOrLoad(bucketId);
        } else {
          throw notPrimary;
        }
      }

      // It's possible this is a GemFire thread e.g. ServerConnection
      // which got to this point because of a distributed system shutdown or
      // region closure which uses interrupt to break any sleep() or wait()
      // calls
      // e.g. waitForPrimary
      checkShutdown();

      count++;
      if (count == 1) {
        prStats.incGetOpsRetried();
      }
      prStats.incGetRetries();
      if (isDebugEnabled) {
        logger.debug("getFromBucket: Attempting to resend get to node {} after {} failed attempts",
            retryNode, count);
      }
    } // While

    PartitionedRegionDistributionException e = null; // Fix for bug 36014
    if (logger.isDebugEnabled()) {
      e = new PartitionedRegionDistributionException(
          String.format("No VM available for get in %s attempts",
              count));
    }
    logger.warn(String.format("No VM available for get in %s attempts", count), e);
    return null;
  }

  void handleForceReattemptExceptionWithTransaction(
      ForceReattemptException forceReattemptException) {
    if (forceReattemptException instanceof BucketNotFoundException) {
      throw new TransactionDataRebalancedException(DATA_MOVED_BY_REBALANCE,
          forceReattemptException);
    }
    Throwable cause = forceReattemptException.getCause();
    if (cause instanceof PrimaryBucketException) {
      throw (PrimaryBucketException) cause;
    } else if (cause instanceof TransactionDataRebalancedException) {
      throw (TransactionDataRebalancedException) cause;
    } else if (cause instanceof RegionDestroyedException) {
      throw new TransactionDataRebalancedException(DATA_MOVED_BY_REBALANCE, cause);
    } else {
      throw new TransactionDataRebalancedException(DATA_MOVED_BY_REBALANCE,
          forceReattemptException);
    }
  }

  /**
   * If a bucket is local, try to fetch the value from it
   */
  public Object getFromLocalBucket(int bucketId, final Object key, final Object aCallbackArgument,
      boolean disableCopyOnRead, boolean preferCD, ClientProxyMembershipID requestingClient,
      EntryEventImpl clientEvent, boolean returnTombstones)
      throws ForceReattemptException, PRLocallyDestroyedException {
    Object obj;
    // try reading locally.
    InternalDistributedMember readNode = getNodeForBucketRead(bucketId);
    if (readNode == null) {
      return null; // fixes 51657
    }
    if (readNode.equals(getMyId())
        && null != (obj = dataStore.getLocally(bucketId, key, aCallbackArgument,
            disableCopyOnRead, preferCD, requestingClient, clientEvent, returnTombstones, true))) {
      if (logger.isTraceEnabled()) {
        logger.trace("getFromBucket: Getting key {} ({}) locally - success", key, key.hashCode());
      }
      return obj;
    }
    return null;
  }

  /**
   * This invokes a cache writer before a destroy operation. Although it has the same method
   * signature as the method in LocalRegion, it is invoked in a different code path. LocalRegion
   * invokes this method via its "entries" member, while PartitionedRegion invokes this method in
   * its region operation methods and messages.
   */
  @Override
  boolean cacheWriteBeforeRegionDestroy(RegionEventImpl event)
      throws CacheWriterException, TimeoutException {

    if (event.getOperation().isDistributed()) {
      serverRegionDestroy(event);
      CacheWriter localWriter = basicGetWriter();
      Set netWriteRecipients = localWriter == null ? distAdvisor.adviseNetWrite() : null;

      if (localWriter == null && (netWriteRecipients == null || netWriteRecipients.isEmpty())) {
        return false;
      }

      final long start = getCachePerfStats().startCacheWriterCall();
      try {
        SearchLoadAndWriteProcessor processor = SearchLoadAndWriteProcessor.getProcessor();
        processor.initialize(this, "preDestroyRegion", null);
        processor.doNetWrite(event, netWriteRecipients, localWriter,
            SearchLoadAndWriteProcessor.BEFOREREGIONDESTROY);
        processor.release();
      } finally {
        getCachePerfStats().endCacheWriterCall(start);
      }
      return true;
    }
    return false;
  }

  /**
   * Test Method: Get the DistributedMember identifier for the vm containing a key
   *
   * @param key the key to look for
   * @return The ID of the DistributedMember holding the key, or null if there is no current mapping
   *         for the key
   */
  public DistributedMember getMemberOwning(Object key) {
    int bucketId = PartitionedRegionHelper.getHashKey(this, null, key, null, null);
    return getNodeForBucketRead(bucketId);
  }

  /**
   * Test Method: Investigate the local cache to determine if it contains a the key
   *
   * @param key The key
   * @return true if the key exists
   * @see LocalRegion#containsKey(Object)
   */
  public boolean localCacheContainsKey(Object key) {
    return getRegionMap().containsKey(key);
  }

  /**
   * Test Method: Fetch a value from the local cache
   *
   * @param key The kye
   * @return the value associated with that key
   * @see LocalRegion#get(Object, Object, boolean, EntryEventImpl)
   */
  public Object localCacheGet(Object key) {
    RegionEntry re = getRegionMap().getEntry(key);
    if (re == null || re.isDestroyedOrRemoved()) {
      return null;
    } else {
      return re.getValue(this); // OFFHEAP: spin until we can copy into a heap cd?
    }
  }

  /**
   * Test Method: Fetch the local cache's key set
   *
   * @return A set of keys
   * @see LocalRegion#keys()
   */
  public Set localCacheKeySet() {
    return super.keys();
  }

  /**
   * Test Method: Get all entries for all copies of a bucket
   *
   * This method will not work correctly if membership in the distributed system changes while the
   * result is being calculated.
   *
   * @return a List of HashMaps, each map being a copy of the entries in a bucket
   */
  public List<BucketDump> getAllBucketEntries(final int bucketId) throws ForceReattemptException {
    if (bucketId >= getTotalNumberOfBuckets()) {
      return Collections.emptyList();
    }
    ArrayList<BucketDump> ret = new ArrayList<>();
    HashSet<InternalDistributedMember> collected = new HashSet<>();
    for (;;) {
      // Collect all the candidates by re-examining the advisor...
      Set<InternalDistributedMember> owners = getRegionAdvisor().getBucketOwners(bucketId);
      // Remove ones we've already polled...
      owners.removeAll(collected);

      // Terminate if no more entries
      if (owners.isEmpty()) {
        break;
      }
      // Get first entry
      Iterator<InternalDistributedMember> ownersI = owners.iterator();
      InternalDistributedMember owner = ownersI.next();
      // Remove it from our list
      collected.add(owner);

      // If it is ourself, answer directly
      if (owner.equals(getMyId())) {
        BucketRegion br = dataStore.handleRemoteGetEntries(bucketId);
        Map<Object, Object> m = new HashMap<Object, Object>() {
          // TODO: clean this up -- outer class is not serializable
          private static final long serialVersionUID = 0L;

          @Override
          public String toString() {
            return "Bucket id = " + bucketId + " from local member = "
                + getDistributionManager().getDistributionManagerId() + ": " + super.toString();
          }
        };

        Map<Object, VersionTag> versions = new HashMap<>();

        for (final Map.Entry o : (Iterable<Map.Entry>) br.entrySet()) {
          NonTXEntry entry = (NonTXEntry) o;
          RegionEntry re = entry.getRegionEntry();
          Object value = re.getValue(br); // OFFHEAP: incrc, deserialize, decrc
          VersionStamp versionStamp = re.getVersionStamp();
          VersionTag versionTag = versionStamp != null ? versionStamp.asVersionTag() : null;
          if (versionTag != null) {
            versionTag.replaceNullIDs(br.getVersionMember());
          }
          if (Token.isRemoved(value)) {
            continue;
          } else if (Token.isInvalid(value)) {
            value = null;
          } else if (value instanceof CachedDeserializable) {
            value = ((CachedDeserializable) value).getDeserializedForReading();
          }
          m.put(re.getKey(), value);
          versions.put(re.getKey(), versionTag);
        }
        RegionVersionVector rvv = br.getVersionVector();
        rvv = rvv != null ? rvv.getCloneForTransmission() : null;
        ret.add(new BucketDump(bucketId, owner, rvv, m, versions));
        continue;
      }

      // Send a message
      try {
        final FetchEntriesResponse r;
        r = FetchEntriesMessage.send(owner, this, bucketId);
        ret.add(r.waitForEntries());
      } catch (ForceReattemptException ignore) {
        // node has departed? Ignore.
      }
    } // for

    return ret;
  }

  /**
   * Fetch the keys for the given bucket identifier, if the bucket is local or remote.
   *
   * @return A set of keys from bucketNum or {@link Collections#EMPTY_SET}if no keys can be found.
   */
  public Set getBucketKeys(int bucketNum) {
    return getBucketKeys(bucketNum, false);
  }

  /**
   * Fetch the keys for the given bucket identifier, if the bucket is local or remote. This version
   * of the method allows you to retrieve Tombstone entries as well as undestroyed entries.
   *
   * @param allowTombstones whether to include destroyed entries in the result
   * @return A set of keys from bucketNum or {@link Collections#EMPTY_SET}if no keys can be found.
   */
  public Set getBucketKeys(int bucketNum, boolean allowTombstones) {
    final int retryAttempts = calcRetry();
    Set ret = null;
    int count = 0;
    InternalDistributedMember nod = getOrCreateNodeForBucketRead(bucketNum);
    RetryTimeKeeper snoozer = null;
    while (count <= retryAttempts) {
      // It's possible this is a GemFire thread e.g. ServerConnection
      // which got to this point because of a distributed system shutdown or
      // region closure which uses interrupt to break any sleep() or wait()
      // calls
      // e.g. waitForPrimary or waitForBucketRecovery
      checkShutdown();

      if (nod == null) {
        if (snoozer == null) {
          snoozer = new RetryTimeKeeper(retryTimeout);
        }
        nod = getOrCreateNodeForBucketRead(bucketNum);

        // No storage found for bucket, early out preventing hot loop, bug 36819
        if (nod == null) {
          checkShutdown();
          break;
        }
        count++;
        continue;
      }

      try {
        if (nod.equals(getMyId())) {
          ret = dataStore.getKeysLocally(bucketNum, allowTombstones);
        } else {
          FetchKeysResponse r = FetchKeysMessage.send(nod, this, bucketNum, allowTombstones);
          ret = r.waitForKeys();
        }
        if (ret != null) {
          return ret;
        }
      } catch (PRLocallyDestroyedException ignore) {
        if (logger.isDebugEnabled()) {
          logger.debug("getBucketKeys: Encountered PRLocallyDestroyedException");
        }
        checkReadiness();
      } catch (ForceReattemptException prce) {
        if (logger.isDebugEnabled()) {
          logger.debug("getBucketKeys: attempt:{}", (count + 1), prce);
        }
        checkReadiness();
        if (snoozer == null) {
          snoozer = new RetryTimeKeeper(retryTimeout);
        }
        InternalDistributedMember oldNode = nod;
        nod = getNodeForBucketRead(bucketNum);
        if (nod != null && nod.equals(oldNode)) {
          if (snoozer.overMaximum()) {
            checkReadiness();
            throw new TimeoutException(
                String.format(
                    "Attempt to acquire primary node for read on bucket %s timed out in %s ms",
                    getBucketName(bucketNum), snoozer.getRetryTime()));
          }
          snoozer.waitToRetryNode();
        }

      }
      count++;
    }
    if (logger.isDebugEnabled()) {
      logger.debug("getBucketKeys: no keys found returning empty set");
    }
    return Collections.emptySet();
  }

  /**
   * Fetches entries from local and remote nodes and appends these to register-interest response.
   */
  public void fetchEntries(HashMap<Integer, HashSet<Object>> bucketKeys, VersionedObjectList values,
      ServerConnection servConn) throws IOException {
    int retryAttempts = calcRetry();
    RetryTimeKeeper retryTime = null;
    HashMap<Integer, HashSet> failures = new HashMap<>(bucketKeys);
    HashMap<InternalDistributedMember, HashMap<Integer, HashSet>> nodeToBuckets =
        new HashMap<>();

    while (--retryAttempts >= 0 && !failures.isEmpty()) {
      nodeToBuckets.clear();
      updateNodeToBucketMap(nodeToBuckets, failures);
      failures.clear();

      HashMap<Integer, HashSet> localBuckets = nodeToBuckets.remove(getMyId());
      if (localBuckets != null && !localBuckets.isEmpty()) {
        Set keys = new HashSet();
        for (Integer id : localBuckets.keySet()) {
          keys.addAll(localBuckets.get(id));
        }
        if (!keys.isEmpty()) {
          BaseCommand.appendNewRegisterInterestResponseChunkFromLocal(this, values, "keyList", keys,
              servConn);
        }
      }

      fetchRemoteEntries(nodeToBuckets, failures, values, servConn);
      if (!failures.isEmpty()) {
        if (retryTime == null) {
          retryTime = new RetryTimeKeeper(retryTimeout);
        }
        if (!waitForFetchRemoteEntriesRetry(retryTime)) {
          break;
        }
      }
    }
    if (!failures.isEmpty()) {
      throw new InternalGemFireException("Failed to fetch entries from " + failures.size()
          + " buckets of region " + getName() + " for register interest.");
    }
  }

  void updateNodeToBucketMap(
      HashMap<InternalDistributedMember, HashMap<Integer, HashSet>> nodeToBuckets,
      HashMap<Integer, HashSet> bucketKeys) {
    for (int id : bucketKeys.keySet()) {
      InternalDistributedMember node = getOrCreateNodeForBucketWrite(id, null);
      if (nodeToBuckets.containsKey(node)) {
        nodeToBuckets.get(node).put(id, bucketKeys.get(id));
      } else {
        HashMap<Integer, HashSet> map = new HashMap<>();
        map.put(id, bucketKeys.get(id));
        nodeToBuckets.put(node, map);
      }
    }
  }


  /**
   * Fetches entries from local and remote nodes and appends these to register-interest response.
   */
  public void fetchEntries(String regex, VersionedObjectList values, ServerConnection servConn)
      throws IOException {
    int retryAttempts = calcRetry();
    RetryTimeKeeper retryTime = null;
    HashSet<Integer> failures = new HashSet<>(getRegionAdvisor().getBucketSet());
    HashMap<InternalDistributedMember, HashSet<Integer>> nodeToBuckets =
        new HashMap<>();

    while (--retryAttempts >= 0 && !failures.isEmpty()) {
      nodeToBuckets.clear();
      updateNodeToBucketMap(nodeToBuckets, failures);
      failures.clear();

      HashSet<Integer> localBuckets = nodeToBuckets.remove(getMyId());

      if (localBuckets != null && !localBuckets.isEmpty()) {
        for (Integer id : localBuckets) {
          Set keys = fetchAllLocalKeys(id, failures, regex);
          if (!keys.isEmpty()) {
            BaseCommand.appendNewRegisterInterestResponseChunkFromLocal(this, values,
                regex != null ? regex : "ALL_KEYS", keys, servConn);
          }
        }
      }
      // Add failed buckets to nodeToBuckets map so that these will be tried on
      // remote nodes.
      updateNodeToBucketMap(nodeToBuckets, failures);
      failures.clear();

      localBuckets = nodeToBuckets.remove(getMyId());
      if (localBuckets != null && !localBuckets.isEmpty()) {
        failures.addAll(localBuckets);
        // updateNodeToBucketMap(nodeToBuckets, failures);
        // failures.clear();
      }

      fetchAllRemoteEntries(nodeToBuckets, failures, regex, values, servConn);
      if (!failures.isEmpty()) {
        if (retryTime == null) {
          retryTime = new RetryTimeKeeper(retryTimeout);
        }
        if (!waitForFetchRemoteEntriesRetry(retryTime)) {
          break;
        }
      }
    }
    if (!failures.isEmpty()) {
      throw new InternalGemFireException("Failed to fetch entries from " + failures.size()
          + " buckets of region " + getName() + " for register interest.");
    }
  }

  void updateNodeToBucketMap(
      HashMap<InternalDistributedMember, HashSet<Integer>> nodeToBuckets, Set<Integer> buckets) {
    for (int id : buckets) {
      InternalDistributedMember node = getOrCreateNodeForBucketWrite(id, null);
      if (nodeToBuckets.containsKey(node)) {
        nodeToBuckets.get(node).add(id);
      } else {
        HashSet<Integer> set = new HashSet<>();
        set.add(id);
        nodeToBuckets.put(node, set);
      }
    }
  }

  /**
   * @return boolean False indicates caller should stop re-trying.
   */
  private boolean waitForFetchRemoteEntriesRetry(RetryTimeKeeper retryTime) {
    if (retryTime.overMaximum()) {
      return false;
    }
    retryTime.waitToRetryNode();
    return true;
  }

  public Set fetchAllLocalKeys(Integer id, Set<Integer> failures, String regex) {
    Set result = new HashSet();
    try {
      Set keys = null;
      if (regex != null) {
        keys = dataStore.handleRemoteGetKeys(id, InterestType.REGULAR_EXPRESSION, regex, true);
      } else {
        keys = dataStore.getKeysLocally(id, true);
      }
      result.addAll(keys);
    } catch (ForceReattemptException ignore) {
      failures.add(id);
    } catch (PRLocallyDestroyedException ignore) {
      failures.add(id);
    }
    return result;
  }

  /**
   * Sends FetchBulkEntriesMessage to each of the nodes hosting the buckets, unless the nodes are
   * older than 8.0
   */
  public void fetchRemoteEntries(
      HashMap<InternalDistributedMember, HashMap<Integer, HashSet>> nodeToBuckets,
      HashMap<Integer, HashSet> failures, VersionedObjectList values, ServerConnection servConn)
      throws IOException {
    Set result = null;
    HashMap<Integer, HashSet> oneBucketKeys = new HashMap<>();

    for (Map.Entry<InternalDistributedMember, HashMap<Integer, HashSet>> entry : nodeToBuckets
        .entrySet()) {
      HashMap<Integer, HashSet> bucketKeys = entry.getValue();
      FetchBulkEntriesResponse fber = null;
      result = new HashSet();

      // Fetch one bucket-data at a time to avoid this VM running out of memory.
      // See #50647
      for (Map.Entry<Integer, HashSet> e : bucketKeys.entrySet()) {
        result.clear();
        oneBucketKeys.clear();
        oneBucketKeys.put(e.getKey(), e.getValue());
        try {
          fber =
              FetchBulkEntriesMessage.send(entry.getKey(), this, oneBucketKeys, null, null, true);

          BucketDump[] bds = fber.waitForEntries();
          if (fber.getFailedBucketIds() != null && !fber.getFailedBucketIds().isEmpty()) {
            for (int id : fber.getFailedBucketIds()) {
              failures.put(id, nodeToBuckets.get(entry.getKey()).get(id));
            }
          }
          for (BucketDump bd : bds) {
            result.addAll(bd.getValuesWithVersions().entrySet());
          }

          BaseCommand.appendNewRegisterInterestResponseChunk(this, values, "keyList", result,
              servConn);

        } catch (ForceReattemptException ignore) {
          failures.put(e.getKey(), e.getValue());
        }
      }
    }
  }

  /**
   * Sends FetchBulkEntriesMessage to each of the nodes hosting the buckets, unless the nodes are
   * older than 8.0
   */
  public void fetchAllRemoteEntries(
      HashMap<InternalDistributedMember, HashSet<Integer>> nodeToBuckets, HashSet<Integer> failures,
      String regex, VersionedObjectList values, ServerConnection servConn) throws IOException {
    Set result = null;
    HashSet<Integer> bucketId = new HashSet<>();

    for (Map.Entry<InternalDistributedMember, HashSet<Integer>> entry : nodeToBuckets.entrySet()) {
      HashSet<Integer> buckets = new HashSet<>(entry.getValue()); // Is it needed to copy the
      // set here?
      FetchBulkEntriesResponse fber = null;
      result = new HashSet();

      // Fetch one bucket-data at a time to avoid this VM running out of memory.
      // See #50647
      for (int bucket : buckets) {
        result.clear();
        bucketId.clear();
        bucketId.add(bucket);
        try {
          fber = FetchBulkEntriesMessage.send(entry.getKey(), this, null, bucketId, regex, true);

          BucketDump[] bds = fber.waitForEntries();
          if (fber.getFailedBucketIds() != null) {
            failures.addAll(fber.getFailedBucketIds());
          }
          for (BucketDump bd : bds) {
            result.addAll(bd.getValuesWithVersions().entrySet());
          }
          BaseCommand.appendNewRegisterInterestResponseChunk(this, values,
              regex != null ? regex : "ALL_KEYS", result, servConn);

        } catch (ForceReattemptException ignore) {
          failures.add(bucket);
        }
      }
    }
  }

  /**
   * Test Method: Get all {@link InternalDistributedMember}s known by this instance of the
   * PartitionedRegion. Note: A member is recognized as such when it partiticpates as a "data
   * store".
   *
   * @return a {@code HashSet} of {@link InternalDistributedMember}s or an empty {@code HashSet}
   */
  public Set<InternalDistributedMember> getAllNodes() {
    Set<InternalDistributedMember> result = getRegionAdvisor().adviseDataStore(true);
    if (isDataStore()) {
      result.add(getDistributionManager().getId());
    }
    return result;
  }

  /**
   * Test Method: Get the number of entries in the local data store.
   */
  public long getLocalSizeForTest() {
    if (dataStore == null) {
      return 0L;
    }
    long ret = 0L;
    Integer i;
    for (final Integer integer : dataStore.getSizeLocally().values()) {
      i = integer;
      ret += i;
    }
    return ret;
  }

  /**
   * Gets the remote object with the given key.
   *
   * @param targetNode the Node hosting the key
   * @param bucketId the id of the bucket the key hashed into
   * @param key the key
   * @param requestingClient the client that made this request
   * @param clientEvent client event for carrying version information. Null if not a client
   *        operation
   * @param returnTombstones TODO
   * @return the value
   * @throws PrimaryBucketException if the peer is no longer the primary
   * @throws ForceReattemptException if the peer is no longer available
   */
  public Object getRemotely(InternalDistributedMember targetNode, int bucketId, final Object key,
      final Object aCallbackArgument, boolean preferCD, ClientProxyMembershipID requestingClient,
      EntryEventImpl clientEvent, boolean returnTombstones)
      throws PrimaryBucketException, ForceReattemptException {
    Object value;
    if (logger.isDebugEnabled()) {
      logger.debug("PartitionedRegion#getRemotely: getting value from bucketId={}{}{} for key {}",
          getPRId(), BUCKET_ID_SEPARATOR, bucketId, key);
    }
    GetResponse response = GetMessage.send(targetNode, this, key, aCallbackArgument,
        requestingClient, returnTombstones);
    prStats.incPartitionMessagesSent();
    value = response.waitForResponse(preferCD);
    if (clientEvent != null) {
      clientEvent.setVersionTag(response.getVersionTag());
    }
    if (logger.isDebugEnabled()) {
      logger.debug("getRemotely: got value {} for key {}", value, key);
    }
    return value;
  }

  private ResultCollector executeFunctionOnRemoteNode(InternalDistributedMember targetNode,
      final Function function, final Object object, final Set routingKeys, ResultCollector rc,
      int[] bucketArray, ServerToClientFunctionResultSender sender, AbstractExecution execution) {
    PartitionedRegionFunctionResultSender resultSender =
        new PartitionedRegionFunctionResultSender(null, this, 0, rc, sender, false, true,
            execution.isForwardExceptions(), function, bucketArray);

    PartitionedRegionFunctionResultWaiter resultReceiver =
        new PartitionedRegionFunctionResultWaiter(getSystem(), getPRId(), rc, function,
            resultSender);

    FunctionRemoteContext context = new FunctionRemoteContext(function, object, routingKeys,
        bucketArray, execution.isReExecute(), execution.isFnSerializationReqd(), getPrincipal());

    HashMap<InternalDistributedMember, FunctionRemoteContext> recipMap =
        new HashMap<>();

    recipMap.put(targetNode, context);

    return resultReceiver.getPartitionedDataFrom(recipMap, this, execution);
  }

  /**
   * This method returns Partitioned Region data store associated with this Partitioned Region
   *
   */
  public PartitionedRegionDataStore getDataStore() {
    return dataStore;
  }

  @Override
  boolean canStoreDataLocally() {
    return getDataStore() != null;
  }

  /**
   * Grab the PartitionedRegionID Lock, this MUST be done in a try block since it may throw an
   * exception
   *
   * @return true if the lock was acquired
   */
  private static boolean grabPRIDLock(final DistributedLockService lockService) {
    final boolean isDebugEnabled = logger.isDebugEnabled();

    boolean ownership = false;
    int n = 0;
    while (!ownership) {
      if (isDebugEnabled) {
        logger.debug("grabPRIDLock: Trying to get the dlock in allPartitionedRegions for {}: {}",
            PartitionedRegionHelper.MAX_PARTITIONED_REGION_ID, (n + 1));
      }
      ownership = lockService.lock(PartitionedRegionHelper.MAX_PARTITIONED_REGION_ID,
          VM_OWNERSHIP_WAIT_TIME, -1);
    }
    return ownership;
  }

  private static void releasePRIDLock(final DistributedLockService lockService) {
    try {
      lockService.unlock(PartitionedRegionHelper.MAX_PARTITIONED_REGION_ID);
      if (logger.isDebugEnabled()) {
        logger.debug("releasePRIDLock: Released the dlock in allPartitionedRegions for {}",
            PartitionedRegionHelper.MAX_PARTITIONED_REGION_ID);
      }
    } catch (Exception es) {
      logger.warn(String.format("releasePRIDLock: unlocking %s caught an exception",
          PartitionedRegionHelper.MAX_PARTITIONED_REGION_ID), es);
    }
  }

  /**
   * generates new partitioned region ID globally.
   */
  public int generatePRId(InternalDistributedSystem sys) {
    final DistributedLockService lockService = getPartitionedRegionLockService();
    return _generatePRId(sys, lockService);
  }

  private static int _generatePRId(InternalDistributedSystem sys,
      DistributedLockService lockService) {
    boolean ownership = false;
    int prid = 0;

    try {
      ownership = grabPRIDLock(lockService);
      if (ownership) {
        if (logger.isDebugEnabled()) {
          logger.debug("generatePRId: Got the dlock in allPartitionedRegions for {}",
              PartitionedRegionHelper.MAX_PARTITIONED_REGION_ID);
        }

        Set parMembers = sys.getDistributionManager().getOtherDistributionManagerIds();

        Integer currentPRID;

        IdentityResponse pir = IdentityRequestMessage.send(parMembers, sys);
        currentPRID = pir.waitForId();

        if (currentPRID == null) {
          currentPRID = 0;
        }
        prid = currentPRID + 1;
        currentPRID = prid;

        try {
          IdentityUpdateResponse pr = IdentityUpdateMessage.send(parMembers, sys, currentPRID);
          pr.waitForRepliesUninterruptibly();
        } catch (ReplyException e) {
          if (logger.isDebugEnabled()) {
            logger.debug("generatePRId: Ignoring exception", e);
          }
        }
      }
    } finally {
      if (ownership) {
        releasePRIDLock(lockService);
      }
    }
    return prid;
  }

  @Override
  public DistributionAdvisor getDistributionAdvisor() {
    return distAdvisor;
  }

  @Override
  public CacheDistributionAdvisor getCacheDistributionAdvisor() {
    return distAdvisor;
  }

  public RegionAdvisor getRegionAdvisor() {
    return distAdvisor;
  }

  /** Returns the distribution profile; lazily creates one if needed */
  @Override
  public Profile getProfile() {
    return distAdvisor.createProfile();
  }

  @Override
  public void fillInProfile(Profile p) {
    CacheProfile profile = (CacheProfile) p;
    // set fields on CacheProfile...
    profile.isPartitioned = true;
    profile.isPersistent = getDataPolicy().withPersistence();
    profile.dataPolicy = getDataPolicy();
    profile.hasCacheLoader = basicGetLoader() != null;
    profile.hasCacheWriter = basicGetWriter() != null;
    profile.hasCacheListener = hasListener();
    Assert.assertTrue(getScope().isDistributed());
    profile.scope = getScope();
    profile.setSubscriptionAttributes(getSubscriptionAttributes());
    // fillInProfile MUST set serialNumber
    profile.serialNumber = getSerialNumber();

    // TODO - prpersist - this is a bit of a hack, but we're
    // reusing this boolean to indicate that this member has finished disk recovery.
    profile.regionInitialized = recoveredFromDisk;

    profile.hasCacheServer = (cache.getCacheServers().size() > 0);
    profile.filterProfile = getFilterProfile();
    profile.gatewaySenderIds = getGatewaySenderIds();
    profile.asyncEventQueueIds = getVisibleAsyncEventQueueIds();

    if (getDataPolicy().withPersistence()) {
      profile.persistentID = getDiskStore().generatePersistentID();
    }

    fillInProfile((PartitionProfile) profile);

    for (CacheServiceProfile csp : getCacheServiceProfiles().values()) {
      profile.addCacheServiceProfile(csp);
    }

    profile.isOffHeap = getOffHeap();
  }

  /** set fields that are only in PartitionProfile... */
  public void fillInProfile(PartitionProfile profile) {
    // both isDataStore and numBuckets are not required for sending purposes,
    // but nice to have for toString debugging
    profile.isDataStore = getLocalMaxMemory() > 0;
    if (dataStore != null) {
      profile.numBuckets = dataStore.getBucketsManaged();
    }

    profile.requiresNotification = requiresNotification;
    profile.localMaxMemory = getLocalMaxMemory();
    profile.fixedPAttrs = fixedPAttrs;
    // shutdownAll
    profile.shutDownAllStatus = shutDownAllStatus;
  }

  @Override
  void initialized() {
    // PartitionedRegions do not send out a profile at the end of
    // initialization. It is not currently needed by other members
    // since no GII is done on a PartitionedRegion
  }

  @Override
  protected void cacheListenersChanged(boolean nowHasListener) {
    if (nowHasListener) {
      advisorListener.initRMLWrappers();
    }
    new UpdateAttributesProcessor(this).distribute();
  }

  // propagate the new writer to the data store
  @Override
  protected void cacheWriterChanged(CacheWriter p_oldWriter) {
    super.cacheWriterChanged(p_oldWriter);
    if (p_oldWriter == null ^ basicGetWriter() == null) {
      updatePRNodeInformation();
      new UpdateAttributesProcessor(this).distribute();
    }
  }

  // propagate the new loader to the data store
  @Override
  protected void cacheLoaderChanged(CacheLoader oldLoader) {
    dataStore.cacheLoaderChanged(basicGetLoader(), oldLoader);
    super.cacheLoaderChanged(oldLoader);
    if (oldLoader == null ^ basicGetLoader() == null) {
      updatePRNodeInformation();
      new UpdateAttributesProcessor(this).distribute();
    }
  }

  /**
   * This method returns PartitionedRegion associated with a PartitionedRegion ID from prIdToPR map.
   *
   * @param prid Partitioned Region ID
   */
  public static PartitionedRegion getPRFromId(int prid) throws PRLocallyDestroyedException {
    final Object o;
    synchronized (prIdToPR) {
      o = prIdToPR.getRegion(prid);
    }
    return (PartitionedRegion) o;
  }

  /**
   * Verify that the given prId is correct for the given region name in this vm
   *
   * @param sender the member requesting validation
   * @param prId the ID being used for the pr by the sender
   * @param regionId the regionIdentifier used for prId by the sender
   */
  public static void validatePRID(InternalDistributedMember sender, int prId, String regionId) {
    try {
      PartitionedRegion pr = null;
      synchronized (prIdToPR) {
        // first do a quick probe
        pr = (PartitionedRegion) prIdToPR.getRegion(prId);
      }
      if (pr != null && !pr.isLocallyDestroyed && pr.getRegionIdentifier().equals(regionId)) {
        return;
      }
    } catch (RegionDestroyedException ignore) {
      // ignore and do full pass over prid map
    } catch (PartitionedRegionException ignore) {
      // ditto
    } catch (PRLocallyDestroyedException ignore) {
      // ignore and do full check
    }
    synchronized (prIdToPR) {
      for (Object o : prIdToPR.values()) {
        if (o instanceof String) {
          continue;
        }
        PartitionedRegion pr = (PartitionedRegion) o;
        if (pr.getPRId() == prId) {
          if (!pr.getRegionIdentifier().equals(regionId)) {
            logger.warn("{} is using PRID {} for {} but this process maps that PRID to {}",
                new Object[] {sender.toString(), prId, pr.getRegionIdentifier()});
          }
        } else if (pr.getRegionIdentifier().equals(regionId)) {
          logger.warn("{} is using PRID {} for {} but this process is using PRID {}",
              new Object[] {sender, prId, pr.getRegionIdentifier(), pr.getPRId()});
        }
      }
    }
  }

  public static String dumpPRId() {
    return prIdToPR.dump();
  }

  public String dumpAllPartitionedRegions() {
    StringBuilder sb = new StringBuilder(getPRRoot().getFullPath());
    sb.append("\n");
    Object key = null;
    for (Iterator i = getPRRoot().keySet().iterator(); i.hasNext();) {
      key = i.next();
      sb.append(key).append("=>").append(getPRRoot().get(key));
      if (i.hasNext()) {
        sb.append("\n");
      }
    }
    return sb.toString();
  }

  /**
   * This method returns prId
   *
   */
  public int getPRId() {
    return partitionedRegionId;
  }

  /**
   * Updates local cache with a new value.
   *
   * @param key the key
   * @param value the value
   * @param newVersion the new version of the key
   */
  void updateLocalCache(Object key, Object value, long newVersion) {

  }

  /**
   * This method returns total number of buckets for this PR
   *
   */
  public int getTotalNumberOfBuckets() {

    return totalNumberOfBuckets;
  }

  @Override
  public void basicDestroy(final EntryEventImpl event, final boolean cacheWrite,
      final Object expectedOldValue)
      throws TimeoutException, EntryNotFoundException, CacheWriterException {

    final long startTime = prStats.getTime();
    try {
      if (event.getEventId() == null) {
        event.setNewEventId(cache.getDistributedSystem());
      }
      discoverJTA();
      getDataView().destroyExistingEntry(event, cacheWrite, expectedOldValue);
    } catch (RegionDestroyedException rde) {
      if (!rde.getRegionFullPath().equals(getFullPath())) {
        // Handle when a bucket is destroyed
        throw new RegionDestroyedException(toString(), getFullPath(), rde);
      }
    } finally {
      prStats.endDestroy(startTime);
    }
  }

  /**
   * @param expectedOldValue only succeed if current value is equal to expectedOldValue
   * @throws EntryNotFoundException if entry not found or if expectedOldValue not null and current
   *         value was not equal to expectedOldValue
   */
  public void destroyInBucket(final EntryEventImpl event, Object expectedOldValue)
      throws EntryNotFoundException, CacheWriterException {
    // Get the bucket id for the key
    final Integer bucketId = event.getKeyInfo().getBucketId();
    assert bucketId != KeyInfo.UNKNOWN_BUCKET;
    // check in bucket2Node region
    final InternalDistributedMember targetNode = getOrCreateNodeForBucketWrite(bucketId, null);

    if (logger.isDebugEnabled()) {
      logger.debug("destroyInBucket: key={} ({}) in node {} to bucketId={} retry={} ms",
          event.getKey(), event.getKey().hashCode(), targetNode, bucketStringForLogs(bucketId),
          retryTimeout);
    }

    // retry the put remotely until it finds the right node managing the bucket
    RetryTimeKeeper retryTime = null;
    InternalDistributedMember currentTarget = targetNode;
    long timeOut = 0;
    int count = 0;
    for (;;) {
      switch (count) {
        case 0:
          // Note we don't check for DM cancellation in common case.
          // First time, keep going
          break;
        case 1:
          // First failure
          cache.getCancelCriterion().checkCancelInProgress(null);
          timeOut = System.currentTimeMillis() + retryTimeout;
          break;
        default:
          cache.getCancelCriterion().checkCancelInProgress(null);
          // test for timeout
          long timeLeft = timeOut - System.currentTimeMillis();
          if (timeLeft < 0) {
            PRHARedundancyProvider.timedOut(this, null, null, "destroy an entry",
                retryTimeout);
            // NOTREACHED
          }

          // Didn't time out. Sleep a bit and then continue
          boolean interrupted = Thread.interrupted();
          try {
            Thread.sleep(PartitionedRegionHelper.DEFAULT_WAIT_PER_RETRY_ITERATION);
          } catch (InterruptedException ignore) {
            interrupted = true;
          } finally {
            if (interrupted) {
              Thread.currentThread().interrupt();
            }
          }
          break;
      }
      count++;

      if (currentTarget == null) { // pick target
        checkReadiness();

        if (retryTime == null) {
          retryTime = new RetryTimeKeeper(retryTimeout);
        }
        if (retryTime.overMaximum()) {
          // if (this.getNodeList(bucketId) == null
          // || this.getNodeList(bucketId).size() == 0) {
          // throw new EntryNotFoundException("Entry not found for key "
          // + event.getKey());
          // }
          if (getRegionAdvisor().getBucket(bucketId).getBucketAdvisor()
              .basicGetPrimaryMember() == null) {
            throw new EntryNotFoundException(
                String.format("Entry not found for key %s",
                    event.getKey()));
          }
          TimeoutException e = new TimeoutException(
              String.format("Time out looking for target node for destroy; waited %s ms",
                  retryTime.getRetryTime()));
          if (logger.isDebugEnabled()) {
            logger.debug(e.getMessage(), e);
          }
          checkReadiness();
          throw e;
        }

        currentTarget = getOrCreateNodeForBucketWrite(bucketId, retryTime);

        // No storage found for bucket, early out preventing hot loop, bug 36819
        if (currentTarget == null) {
          checkEntryNotFound(event.getKey());
        }
        continue;
      } // pick target

      final boolean isLocal = (localMaxMemory > 0) && currentTarget.equals(getMyId());
      try {

        DistributedRemoveAllOperation savedOp = event.setRemoveAllOperation(null);
        if (savedOp != null) {
          savedOp.addEntry(event, bucketId);
          return;
        }
        if (isLocal) {
          // doCacheWriteBeforeDestroy(event);
          event.setInvokePRCallbacks(true);
          dataStore.destroyLocally(bucketId, event, expectedOldValue);
        } else {
          if (event.isBridgeEvent()) {
            setNetworkHopType(bucketId, currentTarget);
          }
          destroyRemotely(currentTarget, bucketId, event, expectedOldValue);
        }
        return;

        // NOTREACHED (success)
      } catch (ConcurrentCacheModificationException e) {
        if (logger.isDebugEnabled()) {
          logger.debug("destroyInBucket: caught concurrent cache modification exception", e);
        }
        event.isConcurrencyConflict(true);

        if (logger.isTraceEnabled()) {
          logger.trace(
              "ConcurrentCacheModificationException received for destroyInBucket for bucketId: {}{}{} for event: {} No reattempt is done, returning from here",
              getPRId(), BUCKET_ID_SEPARATOR, bucketId, event);
        }
        return;
      } catch (ForceReattemptException e) {
        e.checkKey(event.getKey());
        // We don't know if the destroy took place or not at this point.
        // Assume that if the next destroy throws EntryDestroyedException, the
        // previous destroy attempt was a success
        checkReadiness();
        InternalDistributedMember lastNode = currentTarget;
        if (retryTime == null) {
          retryTime = new RetryTimeKeeper(retryTimeout);
        }
        currentTarget = getOrCreateNodeForBucketWrite(bucketId, retryTime);
        event.setPossibleDuplicate(true);
        if (lastNode.equals(currentTarget)) {
          if (retryTime.overMaximum()) {
            PRHARedundancyProvider.timedOut(this, null, null, "destroy an entry",
                retryTime.getRetryTime());
          }
          retryTime.waitToRetryNode();
        }
      } catch (PrimaryBucketException notPrimary) {
        if (logger.isDebugEnabled()) {
          logger.debug("destroyInBucket: {} on Node {} not primary",
              notPrimary.getLocalizedMessage(), currentTarget);
        }
        getRegionAdvisor().notPrimary(bucketId, currentTarget);
        if (retryTime == null) {
          retryTime = new RetryTimeKeeper(retryTimeout);
        }
        currentTarget = getOrCreateNodeForBucketWrite(bucketId, retryTime);
      }

      // If we get here, the attempt failed.
      if (count == 1) {
        prStats.incDestroyOpsRetried();
      }
      prStats.incDestroyRetries();

      if (logger.isDebugEnabled()) {
        logger.debug(
            "destroyInBucket: Attempting to resend destroy to node {} after {} failed attempts",
            currentTarget, count);
      }
    } // for
  }

  private void setNetworkHopType(final Integer bucketId,
      final InternalDistributedMember targetNode) {

    if (isDataStore() && !getMyId().equals(targetNode)) {
      Set<ServerBucketProfile> profiles = getRegionAdvisor().getClientBucketProfiles(bucketId);

      if (profiles != null) {
        for (ServerBucketProfile profile : profiles) {
          if (profile.getDistributedMember().equals(targetNode)) {

            if (isProfileFromSameGroup(profile)) {
              if (getNetworkHopType() != NETWORK_HOP_TO_SAME_GROUP
                  && logger.isDebugEnabled()) {
                logger.debug(
                    "one-hop: cache op meta data staleness observed.  Message is in same server group (byte 1)");
              }
              setNetworkHopType((byte) NETWORK_HOP_TO_SAME_GROUP);
            } else {
              if (getNetworkHopType() != NETWORK_HOP_TO_DIFFERENT_GROUP
                  && logger.isDebugEnabled()) {
                logger.debug(
                    "one-hop: cache op meta data staleness observed.  Message is to different server group (byte 2)");
              }
              setNetworkHopType((byte) NETWORK_HOP_TO_DIFFERENT_GROUP);
            }
            setMetadataVersion((byte) profile.getVersion());
            break;
          }
        }
      }
    }
  }

  public boolean isProfileFromSameGroup(ServerBucketProfile profile) {
    Set<String> localServerGroups = getLocalServerGroups();
    if (localServerGroups.isEmpty()) {
      return true;
    }

    Set<BucketServerLocation66> locations = profile.getBucketServerLocations();

    for (BucketServerLocation66 sl : locations) {
      String[] groups = sl.getServerGroups();
      if (groups.length == 0) {
        return true;
      } else {
        for (String s : groups) {
          if (localServerGroups.contains(s)) {
            return true;
          }
        }
      }
    }
    return false;
  }

  public Set<String> getLocalServerGroups() {
    Set<String> localServerGroups = new HashSet();
    InternalCache cache = getCache();
    List servers;

    servers = cache.getCacheServers();

    Collections.addAll(localServerGroups, MemberDataBuilder.parseGroups(null,
        cache.getInternalDistributedSystem().getConfig().getGroups()));

    for (Object object : servers) {
      CacheServerImpl server = (CacheServerImpl) object;
      if (server.isRunning() && (server.getExternalAddress() != null)) {
        Collections.addAll(localServerGroups, server.getGroups());
      }
    }
    return localServerGroups;
  }

  /**
   * Destroy the entry on the remote node.
   *
   * @param recipient the member id of the receiver of the message
   * @param bucketId the idenity of the bucket
   * @param event the event prompting this request
   * @param expectedOldValue if not null, then destroy only if entry exists and current value is
   *        equal to expectedOldValue
   * @throws EntryNotFoundException if entry not found OR if expectedOldValue is non-null and
   *         doesn't equal the current value
   * @throws PrimaryBucketException if the bucket on that node is not the primary copy
   * @throws ForceReattemptException if the peer is no longer available
   */
  public void destroyRemotely(DistributedMember recipient, Integer bucketId, EntryEventImpl event,
      Object expectedOldValue)
      throws EntryNotFoundException, PrimaryBucketException, ForceReattemptException {
    DestroyResponse response = DestroyMessage.send(recipient, this, event, expectedOldValue);
    if (response != null) {
      prStats.incPartitionMessagesSent();
      try {
        response.waitForCacheException();
        event.setVersionTag(response.getVersionTag());
      } catch (EntryNotFoundException enfe) {
        throw enfe;
      } catch (TransactionDataNotColocatedException enfe) {
        throw enfe;
      } catch (TransactionDataRebalancedException e) {
        throw e;
      } catch (CacheException ce) {
        throw new PartitionedRegionException(
            String.format("Destroy of entry on %s failed",
                recipient),
            ce);
      } catch (RegionDestroyedException ignore) {
        throw new RegionDestroyedException(toString(), getFullPath());
      }
    }
  }

  /**
   * This is getter method for local max memory.
   *
   * @return local max memory for this PartitionedRegion
   */
  public int getLocalMaxMemory() {
    return localMaxMemory;
  }

  /**
   * This is getter method for redundancy.
   *
   * @return redundancy for this PartitionedRegion
   */
  public int getRedundantCopies() {
    return redundantCopies;
  }

  @Override
  public VersionTag findVersionTagForEvent(EventID eventId) {
    if (dataStore != null) {
      Set<Map.Entry<Integer, BucketRegion>> bucketMap = dataStore.getAllLocalBuckets();
      for (Map.Entry<Integer, BucketRegion> entry : bucketMap) {
        VersionTag result = entry.getValue().findVersionTagForEvent(eventId);
        if (result != null) {
          return result;
        }
      }
    }
    return null;
  }

  @Override
  public VersionTag findVersionTagForClientBulkOp(EventID eventId) {
    Map<ThreadIdentifier, VersionTag> results = new HashMap<>();
    if (dataStore != null) {
      Set<Map.Entry<Integer, BucketRegion>> bucketMap = dataStore.getAllLocalBuckets();
      for (Map.Entry<Integer, BucketRegion> entry : bucketMap) {
        VersionTag bucketResult = entry.getValue().findVersionTagForClientBulkOp(eventId);
        if (bucketResult != null) {
          return bucketResult;
        }
      }
    }
    return null;
  }

  /*
   * This method cleans the Partioned region structures if the the creation of Partition region
   * fails OVERRIDES
   */
  @Override
  public void cleanupFailedInitialization() {
    super.cleanupFailedInitialization();
    // Fix for 44551 - make sure persistent buckets
    // are done recoverying from disk before sending the
    // destroy region message.
    redundancyProvider.waitForPersistentBucketRecovery();
    cache.removePartitionedRegion(this);
    cache.getInternalResourceManager(false).removeResourceListener(this);
    redundancyProvider.shutdown(); // see bug 41094
    int[] serials = getRegionAdvisor().getBucketSerials();
    RegionEventImpl event = new RegionEventImpl(this, Operation.REGION_CLOSE, null, false,
        getMyId(), generateEventID()/* generate EventID */);
    Exception savedFirstRuntimeException = null;
    try {
      sendDestroyRegionMessage(event, serials);
    } catch (Exception ex) {
      logger.warn(
          "PartitionedRegion#cleanupFailedInitialization(): Failed to clean the PartionRegion data store",
          ex);
      savedFirstRuntimeException = ex;
    }
    if (null != dataStore) {
      try {
        dataStore.cleanUp(true, false);
      } catch (Exception ex) {
        logger.warn(
            "PartitionedRegion#cleanupFailedInitialization(): Failed to clean the PartionRegion data store",
            ex);
        if (savedFirstRuntimeException == null) {
          savedFirstRuntimeException = ex;
        }
      }
    }

    if (cleanPRRegistration) {
      try {
        synchronized (prIdToPR) {
          if (prIdToPR.containsKey(partitionedRegionId)) {
            prIdToPR.put(partitionedRegionId, PRIdMap.FAILED_REGISTRATION, false);
            if (logger.isDebugEnabled()) {
              logger.debug("cleanupFailedInitialization: set failed for prId={} named {}",
                  partitionedRegionId, getName());
            }
          }
        }

        PartitionedRegionHelper.removeGlobalMetadataForFailedNode(node,
            getRegionIdentifier(), getGemFireCache(), true);
      } catch (Exception ex) {
        logger.warn(
            "PartitionedRegion#cleanupFailedInitialization: Failed to clean the PartionRegion allPartitionedRegions",
            ex);
        if (savedFirstRuntimeException == null) {
          savedFirstRuntimeException = ex;
        }
      }
    }
    distAdvisor.close();
    getPrStats().close();
    if (getDiskStore() != null && getDiskStore().getOwnedByRegion()) {
      getDiskStore().close();
    }
    if (logger.isDebugEnabled()) {
      logger.debug("cleanupFailedInitialization: end of {}", getName());
    }
    if (savedFirstRuntimeException != null
        && savedFirstRuntimeException instanceof DistributedSystemDisconnectedException) {
      logger.warn("cleanupFailedInitialization originally failed with {}",
          savedFirstRuntimeException);
      throw (DistributedSystemDisconnectedException) savedFirstRuntimeException;
    }
  }

  /**
   * Called after the cache close has closed all regions. This clean up static pr resources.
   *
   * @since GemFire 5.0
   */
  static void afterRegionsClosedByCacheClose(InternalCache cache) {
    PRQueryProcessor.shutdown();
    clearPRIdMap();
  }

  @Override
  void basicInvalidateRegion(RegionEventImpl event) {
    if (!event.isOriginRemote()) {
      sendInvalidateRegionMessage(event);
    }
    for (BucketRegion br : getDataStore().getAllLocalPrimaryBucketRegions()) {
      if (logger.isDebugEnabled()) {
        logger.debug("Invalidating bucket {}", br);
      }
      br.basicInvalidateRegion(event);
    }
    super.basicInvalidateRegion(event);
  }

  @Override
  void invalidateAllEntries(RegionEvent rgnEvent) {
    // do nothing
  }

  private void sendInvalidateRegionMessage(RegionEventImpl event) {
    final int retryAttempts = calcRetry();
    Throwable thr = null;
    int count = 0;
    while (count <= retryAttempts) {
      try {
        count++;
        Set recipients = getRegionAdvisor().adviseDataStore();
        ReplyProcessor21 response =
            InvalidatePartitionedRegionMessage.send(recipients, this, event);
        response.waitForReplies();
        thr = null;
        break;
      } catch (ReplyException e) {
        thr = e;
        if (!isClosed && !isDestroyed) {
          if (logger.isDebugEnabled()) {
            logger.debug("Invalidating partitioned region caught exception", e);
          }
        }
      } catch (InterruptedException e) {
        thr = e;
        if (!cache.getCancelCriterion().isCancelInProgress()) {
          if (logger.isDebugEnabled()) {
            logger.debug("Invalidating partitioned region caught exception", e);
          }
        }
      }
    }
    if (thr != null) {
      PartitionedRegionDistributionException e = new PartitionedRegionDistributionException(
          String.format("Invalidating partitioned region caught exception %s",
              count));
      if (logger.isDebugEnabled()) {
        logger.debug(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  public void basicInvalidate(EntryEventImpl event) throws EntryNotFoundException {
    final long startTime = prStats.getTime();
    try {
      if (event.getEventId() == null) {
        event.setNewEventId(cache.getDistributedSystem());
      }
      discoverJTA();
      getDataView().invalidateExistingEntry(event, isInitialized(), false);
    } catch (RegionDestroyedException rde) {
      if (!rde.getRegionFullPath().equals(getFullPath())) {
        // Handle when a bucket is destroyed
        throw new RegionDestroyedException(toString(), getFullPath(), rde);
      }
    } finally {
      prStats.endInvalidate(startTime);
    }
    return;
  }

  @Override
  void basicUpdateEntryVersion(EntryEventImpl event) throws EntryNotFoundException {

    try {
      if (event.getEventId() == null) {
        event.setNewEventId(cache.getDistributedSystem());
      }
      getDataView().updateEntryVersion(event);
    } catch (RegionDestroyedException rde) {
      if (!rde.getRegionFullPath().equals(getFullPath())) {
        // Handle when a bucket is destroyed
        throw new RegionDestroyedException(toString(), getFullPath(), rde);
      }
    }
    return;
  }

  /**
   * Invalidate the entry in the bucket identified by the key
   */
  void invalidateInBucket(final EntryEventImpl event) throws EntryNotFoundException {
    final boolean isDebugEnabled = logger.isDebugEnabled();

    final int bucketId = event.getKeyInfo().getBucketId();
    assert bucketId != KeyInfo.UNKNOWN_BUCKET;
    final InternalDistributedMember targetNode = getOrCreateNodeForBucketWrite(bucketId, null);

    final int retryAttempts = calcRetry();
    int count = 0;
    RetryTimeKeeper retryTime = null;
    InternalDistributedMember retryNode = targetNode;
    while (count <= retryAttempts) {
      // It's possible this is a GemFire thread e.g. ServerConnection
      // which got to this point because of a distributed system shutdown or
      // region closure which uses interrupt to break any sleep() or wait()
      // calls
      // e.g. waitForPrimary or waitForBucketRecovery
      checkShutdown();

      if (retryNode == null) {
        checkReadiness();
        if (retryTime == null) {
          retryTime = new RetryTimeKeeper(retryTimeout);
        }
        try {
          retryNode = getOrCreateNodeForBucketWrite(bucketId, retryTime);
        } catch (TimeoutException ignore) {
          if (getRegionAdvisor().isStorageAssignedForBucket(bucketId)) {
            // bucket no longer exists
            throw new EntryNotFoundException(
                String.format("Entry not found for key %s",
                    event.getKey()));
          }
          break; // fall out to failed exception
        }

        if (retryNode == null) {
          checkEntryNotFound(event.getKey());
        }
        continue;
      }
      final boolean isLocal = (localMaxMemory > 0) && retryNode.equals(getMyId());
      try {
        if (isLocal) {
          event.setInvokePRCallbacks(true);
          dataStore.invalidateLocally(bucketId, event);
        } else {
          invalidateRemotely(retryNode, bucketId, event);
        }
        return;
      } catch (ConcurrentCacheModificationException e) {
        if (isDebugEnabled) {
          logger.debug("invalidateInBucket: caught concurrent cache modification exception", e);
        }
        event.isConcurrencyConflict(true);

        if (isDebugEnabled) {
          logger.debug(
              "ConcurrentCacheModificationException received for invalidateInBucket for bucketId: {}{}{} for event: {}  No reattampt is done, returning from here",
              getPRId(), BUCKET_ID_SEPARATOR, bucketId, event);
        }
        return;
      } catch (ForceReattemptException prce) {
        prce.checkKey(event.getKey());
        if (isDebugEnabled) {
          logger.debug("invalidateInBucket: retry attempt:{} of {}", count, retryAttempts, prce);
        }
        checkReadiness();

        InternalDistributedMember lastNode = retryNode;
        retryNode = getOrCreateNodeForBucketWrite(bucketId, retryTime);
        if (lastNode.equals(retryNode)) {
          if (retryTime == null) {
            retryTime = new RetryTimeKeeper(retryTimeout);
          }
          if (retryTime.overMaximum()) {
            break;
          }
          retryTime.waitToRetryNode();
        }
        event.setPossibleDuplicate(true);
      } catch (PrimaryBucketException notPrimary) {
        if (isDebugEnabled) {
          logger.debug("invalidateInBucket {} on Node {} not primary",
              notPrimary.getLocalizedMessage(), retryNode);
        }
        getRegionAdvisor().notPrimary(bucketId, retryNode);
        retryNode = getOrCreateNodeForBucketWrite(bucketId, retryTime);
      }

      count++;
      if (count == 1) {
        prStats.incInvalidateOpsRetried();
      }
      prStats.incInvalidateRetries();
      if (isDebugEnabled) {
        logger.debug(
            "invalidateInBucket: Attempting to resend invalidate to node {} after {} failed attempts",
            retryNode, count);
      }
    } // while

    // No target was found
    PartitionedRegionDistributionException e = new PartitionedRegionDistributionException(
        String.format("No VM available for invalidate in %s attempts.",
            count)); // Fix for bug 36014
    if (!isDebugEnabled) {
      logger.warn("No VM available for invalidate in {} attempts.", count);
    } else {
      logger.warn(e.getMessage(), e);
    }
    throw e;
  }

  /**
   * invalidates the remote object with the given key.
   *
   * @param recipient the member id of the recipient of the operation
   * @param bucketId the id of the bucket the key hashed into
   * @throws EntryNotFoundException if the entry does not exist in this region
   * @throws PrimaryBucketException if the bucket on that node is not the primary copy
   * @throws ForceReattemptException if the peer is no longer available
   */
  public void invalidateRemotely(DistributedMember recipient, Integer bucketId,
      EntryEventImpl event)
      throws EntryNotFoundException, PrimaryBucketException, ForceReattemptException {
    InvalidateResponse response = InvalidateMessage.send(recipient, this, event);
    if (response != null) {
      prStats.incPartitionMessagesSent();
      try {
        response.waitForResult();
        event.setVersionTag(response.versionTag);
        return;
      } catch (EntryNotFoundException ex) {
        throw ex;
      } catch (TransactionDataNotColocatedException ex) {
        throw ex;
      } catch (TransactionDataRebalancedException e) {
        throw e;
      } catch (CacheException ce) {
        throw new PartitionedRegionException(
            String.format("Invalidation of entry on %s failed",
                recipient),
            ce);
      }
    }
  }

  /**
   * Calculate the number of times we attempt to commumnicate with a data store. Beware that this
   * method is called very frequently so it absolutely must perform well.
   *
   * @return the number of times to attempt to communicate with a data store
   */
  private int calcRetry() {
    return (retryTimeout / PartitionedRegionHelper.DEFAULT_WAIT_PER_RETRY_ITERATION) + 1;
  }

  /**
   * Creates the key/value pair into the remote target that is managing the key's bucket.
   *
   * @param recipient member id of the recipient of the operation
   * @param bucketId the id of the bucket that the key hashed to
   * @param event the event prompting this request
   * @throws PrimaryBucketException if the bucket on that node is not the primary copy
   * @throws ForceReattemptException if the peer is no longer available
   */
  private boolean createRemotely(DistributedMember recipient, Integer bucketId,
      EntryEventImpl event, boolean requireOldValue)
      throws PrimaryBucketException, ForceReattemptException {
    boolean ret = false;
    long eventTime = event.getEventTime(0L);
    PutMessage.PutResponse reply = (PutMessage.PutResponse) PutMessage.send(recipient, this, event,
        eventTime, true, false, null, // expectedOldValue
        requireOldValue);
    PutResult pr = null;
    if (reply != null) {
      prStats.incPartitionMessagesSent();
      try {
        pr = reply.waitForResult();
        event.setOperation(pr.op);
        event.setVersionTag(pr.versionTag);
        if (requireOldValue) {
          event.setOldValue(pr.oldValue, true);
        }
        ret = pr.returnValue;
      } catch (EntryExistsException ignore) {
        // This might not be necessary and is here for safety sake
        ret = false;
      } catch (TransactionDataNotColocatedException tdnce) {
        throw tdnce;
      } catch (TransactionDataRebalancedException e) {
        throw e;
      } catch (CacheException ce) {
        throw new PartitionedRegionException(
            String.format("Create of entry on %s failed",
                recipient),
            ce);
      } catch (RegionDestroyedException rde) {
        if (logger.isDebugEnabled()) {
          logger.debug("createRemotely: caught exception", rde);
        }
        throw new RegionDestroyedException(toString(), getFullPath());
      }
    }
    return ret;
  }

  // ////////////////////////////////
  // ////// Set Operations /////////
  // ///////////////////////////////

  /**
   * This method returns set of all the entries of this PartitionedRegion(locally or remotely).
   * Currently, it throws UnsupportedOperationException
   *
   * @param recursive boolean flag to indicate whether subregions should be considered or not.
   * @return set of all the entries of this PartitionedRegion
   *
   *         OVERRIDES
   */
  @Override
  public Set entrySet(boolean recursive) {
    checkReadiness();
    if (!restoreSetOperationTransactionBehavior) {
      discoverJTA();
    }
    return Collections.unmodifiableSet(new PREntriesSet());
  }

  public Set<Region.Entry> entrySet(Set<Integer> bucketIds) {
    return new PREntriesSet(bucketIds);
  }

  /**
   * Set view of entries. This currently extends the keySet iterator and performs individual
   * getEntry() operations using the keys
   *
   * @since GemFire 5.1
   */
  protected class PREntriesSet extends KeysSet {

    boolean allowTombstones;

    private class EntriesSetIterator extends KeysSetIterator {

      /** reusable KeyInfo */
      private final KeyInfo key = new KeyInfo(null, null, null);

      public EntriesSetIterator(Set bucketSet, boolean allowTombstones) {
        super(bucketSet, allowTombstones);
        PREntriesSet.this.allowTombstones = allowTombstones;
      }

      @Override
      public Object next() {
        key.setKey(super.next());
        key.setBucketId(currentBucketId);

        Object entry =
            view.getEntryForIterator(key, PartitionedRegion.this, true, allowTombstones);
        return entry != null ? entry : new DestroyedEntry(key.getKey().toString());
      }
    }

    public PREntriesSet() {
      super();
    }

    public PREntriesSet(Set<Integer> bucketSet) {
      super(bucketSet);
    }

    @Override
    public Iterator iterator() {
      checkTX();
      return new EntriesSetIterator(bucketSet, allowTombstones);
    }
  }

  /**
   * This method returns set of all the keys of this PartitionedRegion(locally or remotely).
   *
   * @return set of all the keys of this PartitionedRegion
   *
   *         OVERRIDES
   */
  @Override
  public Set keys() {
    checkReadiness();
    if (!restoreSetOperationTransactionBehavior) {
      discoverJTA();
    }
    return Collections.unmodifiableSet(new KeysSet());
  }

  @Override
  public Set keySet(boolean allowTombstones) {
    checkReadiness();
    return Collections.unmodifiableSet(new KeysSet(allowTombstones));
  }

  /**
   * Get a keyset of the given buckets
   */
  public Set keySet(Set<Integer> bucketSet) {
    return new KeysSet(bucketSet);
  }

  public Set keysWithoutCreatesForTests() {
    checkReadiness();
    Set<Integer> availableBuckets = new HashSet<>();
    for (int i = 0; i < getTotalNumberOfBuckets(); i++) {
      if (distAdvisor.isStorageAssignedForBucket(i)) {
        availableBuckets.add(i);
      }
    }
    return Collections.unmodifiableSet(new KeysSet(availableBuckets));
  }

  /** Set view of entries */
  protected class KeysSet extends EntriesSet {
    class KeysSetIterator implements PREntriesIterator<Object> {
      final Iterator<Integer> bucketSetI;
      volatile Iterator currentBucketI = null;
      int currentBucketId = -1;
      volatile Object currentKey = null;
      protected final Set<Integer> bucketSet;
      boolean allowTombstones;

      public KeysSetIterator(Set<Integer> bucketSet, boolean allowTombstones) {
        checkReadiness();
        this.bucketSet = bucketSet;
        this.allowTombstones = allowTombstones;
        bucketSetI = createBucketSetI();
        currentBucketI = getNextBucketIter(false /* no throw */);
      }

      protected Iterator<Integer> createBucketSetI() {
        if (bucketSet != null) {
          return bucketSet.iterator();
        }
        return getRegionAdvisor().getBucketSet().iterator();
      }

      @Override
      public boolean hasNext() {
        checkReadiness();
        if (currentBucketI.hasNext()) {
          return true;
        } else {
          while (!currentBucketI.hasNext() && bucketSetI.hasNext()) {
            checkReadiness();
            currentBucketI = getNextBucketIter(false);
          }
          return currentBucketI.hasNext();
        }
      }

      @Override
      public Object next() {
        if (myTX != null) {
          checkTX();
        }
        checkReadiness();
        if (currentBucketI.hasNext()) {
          currentKey = currentBucketI.next();
        } else {
          currentKey = null;
          while (!currentBucketI.hasNext() && bucketSetI.hasNext()) {
            checkReadiness();
            currentBucketI = getNextBucketIter(true);
          }
          // Next line may throw NoSuchElementException... this is expected.
          currentKey = currentBucketI.next();
        }
        return currentKey;
      }

      protected Iterator getNextBucketIter(boolean canThrow) {
        try {
          currentBucketId = bucketSetI.next();
          // TODO: optimize this code by implementing getBucketKeysIterator.
          // Instead of creating a Set to return it can just create an ArrayList
          // and return an iterator on it. This would cut down on garbage and
          // cpu usage.
          return view
              .getBucketKeys(PartitionedRegion.this, currentBucketId, allowTombstones)
              .iterator();
        } catch (NoSuchElementException endOfTheLine) {
          if (canThrow) {
            throw endOfTheLine;
          } else {
            // Logically pass the NoSuchElementException to the caller
            // Can't throw here because it is called in the contructor context
            return Collections.emptyIterator();
          }
        }
      }

      @Override
      public void remove() {
        if (currentKey == null) {
          throw new IllegalStateException();
        }
        try {
          destroy(currentKey);
        } catch (EntryNotFoundException e) {
          if (logger.isDebugEnabled()) {
            logger.debug("Caught exception during KeySetIterator remove", e);
          }
        } finally {
          currentKey = null;
        }
      }

      @Override
      public PartitionedRegion getPartitionedRegion() {
        return PartitionedRegion.this;
      }

      @Override
      public int getBucketId() {
        return currentBucketId;
      }
    }

    protected final Set<Integer> bucketSet;

    public KeysSet() {
      super(PartitionedRegion.this, false, IteratorType.KEYS, false);
      bucketSet = null;
    }

    public KeysSet(boolean allowTombstones) {
      super(PartitionedRegion.this, false, IteratorType.KEYS, allowTombstones);
      bucketSet = null;
    }

    public KeysSet(Set<Integer> bucketSet) {
      super(PartitionedRegion.this, false, IteratorType.KEYS, false);
      this.bucketSet = bucketSet;
    }

    @Override
    public int size() {
      checkTX();
      return entryCount(bucketSet);
    }

    @Override
    public Object[] toArray() {
      return toArray(null);
    }

    @Override
    public Object[] toArray(Object[] array) {
      List temp = new ArrayList(size());
      for (final Object o : this) {
        temp.add(o);
      }
      if (array == null) {
        return temp.toArray();
      } else {
        return temp.toArray(array);
      }
    }

    @Override
    public Iterator iterator() {
      checkTX();
      return new KeysSetIterator(bucketSet, allowTombstones);
    }
  }

  /**
   * This method returns collection of all the values of this PartitionedRegion(locally or
   * remotely).
   *
   * @return collection of all the values of this PartitionedRegion
   */
  @Override
  public Collection values() {
    checkReadiness();
    if (!restoreSetOperationTransactionBehavior) {
      discoverJTA();
    }
    return Collections.unmodifiableSet(new ValuesSet());
  }

  /**
   * Set view of values. This currently extends the keySet iterator and performs individual get()
   * operations using the keys
   *
   * @since GemFire 5.1
   */
  protected class ValuesSet extends KeysSet {

    private class ValuesSetIterator extends KeysSetIterator {

      Object nextValue = null;

      /** reusable KeyInfo */
      private final KeyInfo key = new KeyInfo(null, null, null);

      public ValuesSetIterator(Set bucketSet) {
        super(bucketSet, false);
      }

      @Override
      public boolean hasNext() {
        if (nextValue != null) {
          return true;
        }
        while (nextValue == null) {
          if (!super.hasNext()) {
            return false;
          }
          key.setKey(super.next());
          key.setBucketId(currentBucketId);
          Region.Entry re = (Region.Entry) view.getEntryForIterator(key, PartitionedRegion.this,
              rememberReads, allowTombstones);
          if (re != null) {
            nextValue = re.getValue();
          }
        }
        return true;
      }

      @Override
      public Object next() {
        if (!hasNext()) {
          throw new NoSuchElementException();
        }
        Assert.assertTrue(nextValue != null, "nextValue found to be null");
        Object result = nextValue;
        nextValue = null;
        return result;
      }

      @Override
      public void remove() {
        super.remove();
        nextValue = null;
      }
    }

    public ValuesSet() {
      super();
    }

    public ValuesSet(Set<Integer> bucketSet) {
      super(bucketSet);
    }

    @Override
    public Iterator iterator() {
      checkTX();
      return new ValuesSetIterator(bucketSet);
    }
  }

  /**
   * @since GemFire 6.6
   */
  @Override
  public boolean containsValue(final Object value) {
    if (value == null) {
      throw new NullPointerException(
          "Value for containsValue(value) cannot be null");
    }
    checkReadiness();
    // First check the values is present locally.
    if (getDataStore() != null) {
      ValuesSet vSet = new ValuesSet(getDataStore().getAllLocalPrimaryBucketIds());
      for (final Object v : vSet) {
        if (v.equals(value)) {
          return true;
        }
      }
    }

    ResultCollector rc = null;
    try {
      rc = FunctionService.onRegion(this).setArguments(value)
          .execute(PRContainsValueFunction.class.getName());
      List<Boolean> results = ((List<Boolean>) rc.getResult());
      for (Boolean r : results) {
        if (r) {
          return true;
        }
      }
    } catch (FunctionException fe) {
      checkShutdown();
      logger.warn("PR containsValue warning. Got an exception while executing function",
          fe.getCause());
    }
    return false;
  }

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

  @Override
  boolean nonTXContainsKey(KeyInfo keyInfo) {
    final long startTime = prStats.getTime();
    boolean contains = false;
    try {
      int bucketId = keyInfo.getBucketId();
      if (bucketId == KeyInfo.UNKNOWN_BUCKET) {
        bucketId = PartitionedRegionHelper.getHashKey(this, Operation.CONTAINS_KEY,
            keyInfo.getKey(), keyInfo.getValue(), keyInfo.getCallbackArg());
        keyInfo.setBucketId(bucketId);
      }
      Integer bucketIdInt = bucketId;
      InternalDistributedMember targetNode = getOrCreateNodeForBucketRead(bucketId);
      // targetNode null means that this key is not in the system.
      if (targetNode != null) {
        contains = containsKeyInBucket(targetNode, bucketIdInt, keyInfo.getKey(), false);
      }
    } finally {
      prStats.endContainsKey(startTime);
    }
    return contains;
  }

  boolean containsKeyInBucket(final InternalDistributedMember targetNode, final Integer bucketIdInt,
      final Object key, boolean valueCheck) {
    final int retryAttempts = calcRetry();
    if (logger.isDebugEnabled()) {
      logger.debug("containsKeyInBucket: {}{} ({}) from: {} bucketId={}",
          (valueCheck ? "ValueForKey key=" : "Key key="), key, key.hashCode(), targetNode,
          bucketStringForLogs(bucketIdInt));
    }
    boolean ret;
    int count = 0;
    RetryTimeKeeper retryTime = null;
    InternalDistributedMember retryNode = targetNode;
    while (count <= retryAttempts) {
      // Every continuation should check for DM cancellation
      if (retryNode == null) {
        checkReadiness();
        if (retryTime == null) {
          retryTime = new RetryTimeKeeper(retryTimeout);
        }
        if (retryTime.overMaximum()) {
          break;
        }
        retryNode = getOrCreateNodeForBucketRead(bucketIdInt);
        // No storage found for bucket, early out preventing hot loop, bug 36819
        if (retryNode == null) {
          checkShutdown(); // Prefer closed style exceptions over empty result
          return false;
        }

        continue;
      } // retryNode != null
      try {
        final boolean loc = retryNode.equals(getMyId());
        if (loc) {
          if (valueCheck) {
            ret = dataStore.containsValueForKeyLocally(bucketIdInt, key);
          } else {
            ret = dataStore.containsKeyLocally(bucketIdInt, key);
          }
        } else {
          if (valueCheck) {
            ret = containsValueForKeyRemotely(retryNode, bucketIdInt, key);
          } else {
            ret = containsKeyRemotely(retryNode, bucketIdInt, key);
          }
        }
        return ret;
      } catch (PRLocallyDestroyedException pde) {
        if (logger.isDebugEnabled()) {
          logger.debug("containsKeyInBucket: Encountered PRLocallyDestroyedException", pde);
        }
        checkReadiness();
      } catch (ForceReattemptException prce) {
        prce.checkKey(key);
        if (logger.isDebugEnabled()) {
          logger.debug("containsKeyInBucket: retry attempt:{} of {}", count, retryAttempts, prce);
        }
        checkReadiness();

        InternalDistributedMember lastNode = retryNode;
        retryNode = getOrCreateNodeForBucketRead(bucketIdInt);
        if (lastNode.equals(retryNode)) {
          if (retryTime == null) {
            retryTime = new RetryTimeKeeper(retryTimeout);
          }
          if (retryTime.overMaximum()) {
            break;
          }
          retryTime.waitToRetryNode();
        }
      } catch (PrimaryBucketException notPrimary) {
        if (logger.isDebugEnabled()) {
          logger.debug("containsKeyInBucket {} on Node {} not primary",
              notPrimary.getLocalizedMessage(), retryNode);
        }
        getRegionAdvisor().notPrimary(bucketIdInt, retryNode);
        retryNode = getOrCreateNodeForBucketRead(bucketIdInt);
      } catch (RegionDestroyedException rde) {
        if (!rde.getRegionFullPath().equals(getFullPath())) {
          throw new RegionDestroyedException(toString(), getFullPath(), rde);
        }
      }

      // It's possible this is a GemFire thread e.g. ServerConnection
      // which got to this point because of a distributed system shutdown or
      // region closure which uses interrupt to break any sleep() or wait()
      // calls
      // e.g. waitForPrimary
      checkShutdown();

      count++;
      if (count == 1) {
        prStats.incContainsKeyValueOpsRetried();
      }
      prStats.incContainsKeyValueRetries();

    }

    String msg;
    if (valueCheck) {
      msg =
          "No VM available for contains value for key in %s attempts";
    } else {
      msg = "No VM available for contains key in %s attempts";
    }

    Integer countInteger = count;
    PartitionedRegionDistributionException e = null; // Fix for bug 36014
    if (logger.isDebugEnabled()) {
      e = new PartitionedRegionDistributionException(String.format(msg, countInteger));
    }
    logger.warn(String.format(msg, countInteger), e);
    return false;
  }

  /**
   * Checks if a key is contained remotely.
   *
   * @param targetNode the node where bucket region for the key exists.
   * @param bucketId the bucket id for the key.
   * @param key the key, whose value needs to be checks
   * @return true if the passed key is contained remotely.
   * @throws PrimaryBucketException if the remote bucket was not the primary
   * @throws ForceReattemptException if the peer is no longer available
   */
  public boolean containsKeyRemotely(InternalDistributedMember targetNode, Integer bucketId,
      Object key) throws PrimaryBucketException, ForceReattemptException {
    ContainsKeyValueResponse r =
        ContainsKeyValueMessage.send(targetNode, this, key, bucketId, false);
    prStats.incPartitionMessagesSent();
    return r.waitForContainsResult();
  }

  /**
   * Returns whether there is a valid (non-null) value present for the specified key, locally or
   * remotely. This method is equivalent to:
   *
   * <pre>
   * Entry e = getEntry(key);
   * return e != null &amp;&amp; e.getValue() != null;
   * </pre>
   *
   * This method does not consult localCache, even if enabled.
   *
   * @param key the key to check for a valid value
   * @return true if there is an entry in this region for the specified key and it has a valid value
   *         OVERRIDES
   */
  @Override
  public boolean containsValueForKey(Object key) {
    // checkClosed();
    checkReadiness();
    validateKey(key);
    final long startTime = prStats.getTime();
    boolean containsValueForKey = false;
    try {
      containsValueForKey = getDataView().containsValueForKey(getKeyInfo(key), this);
    } finally {
      prStats.endContainsValueForKey(startTime);
    }
    return containsValueForKey;
  }

  @Override
  boolean nonTXContainsValueForKey(KeyInfo keyInfo) {
    boolean containsValueForKey = false;
    int bucketId = keyInfo.getBucketId();
    if (bucketId == KeyInfo.UNKNOWN_BUCKET) {
      bucketId = PartitionedRegionHelper.getHashKey(this, Operation.CONTAINS_VALUE_FOR_KEY,
          keyInfo.getKey(), keyInfo.getValue(), keyInfo.getCallbackArg());
      keyInfo.setBucketId(bucketId);
    }
    InternalDistributedMember targetNode = getOrCreateNodeForBucketRead(bucketId);
    // targetNode null means that this key is not in the system.
    if (targetNode != null) {
      containsValueForKey = containsKeyInBucket(targetNode, bucketId, keyInfo.getKey(), true);
    }
    return containsValueForKey;
  }

  /**
   * Checks if this instance contains a value for the key remotely.
   *
   * @param targetNode the node where bucket region for the key exists.
   * @param bucketId the bucket id for the key.
   * @param key the key, whose value needs to be checks
   * @return true if there is non-null value for the given key
   * @throws PrimaryBucketException if the remote bucket was not the primary
   * @throws ForceReattemptException if the peer is no longer available
   */
  public boolean containsValueForKeyRemotely(InternalDistributedMember targetNode, Integer bucketId,
      Object key) throws PrimaryBucketException, ForceReattemptException {
    if (logger.isDebugEnabled()) {
      logger.debug("containsValueForKeyRemotely: key={}", key);
    }
    ContainsKeyValueResponse r =
        ContainsKeyValueMessage.send(targetNode, this, key, bucketId, true);
    prStats.incPartitionMessagesSent();
    return r.waitForContainsResult();
  }

  /**
   * Get the VSD statistics type
   *
   * @return the statistics instance specific to this Partitioned Region
   */
  public PartitionedRegionStats getPrStats() {
    return prStats;
  }

  /* non-transactional size calculation */
  @Override
  public int getRegionSize() {
    return entryCount(null);
  }

  @Override
  public int getLocalSize() {
    if (dataStore == null) {
      return 0;
    }

    return dataStore.getLocalBucket2RegionMap().values().stream()
        .mapToInt(BucketRegion::getLocalSize)
        .sum();
  }

  public int entryCount(boolean localOnly) {
    if (localOnly) {
      if (isDataStore()) {
        return entryCount(dataStore.getAllLocalBucketIds());
      } else {
        return 0;
      }
    } else {
      return entryCount(null);
    }
  }

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

  @Override
  public int entryCount(Set<Integer> buckets, boolean estimate) {
    Map<Integer, SizeEntry> bucketSizes = null;
    if (buckets != null) {
      if (dataStore != null) {
        List<Integer> list = new ArrayList<>(buckets);
        bucketSizes = dataStore.getSizeLocallyForBuckets(list);
      }
    } else {
      if (dataStore != null) {
        bucketSizes = dataStore.getSizeForLocalBuckets();
      }
      HashSet recips = (HashSet) getRegionAdvisor().adviseDataStore(true);
      recips.remove(getMyId());
      if (!recips.isEmpty()) {
        Map<Integer, SizeEntry> remoteSizes = getSizeRemotely(recips, false);
        if (logger.isDebugEnabled()) {
          logger.debug("entryCount: {} remoteSizes={}", this, remoteSizes);
        }
        if (bucketSizes != null && !bucketSizes.isEmpty()) {
          for (Map.Entry<Integer, SizeEntry> me : remoteSizes.entrySet()) {
            Integer k = me.getKey();
            if (!bucketSizes.containsKey(k) || !bucketSizes.get(k).isPrimary()) {
              bucketSizes.put(k, me.getValue());
            }
          }
        } else {
          bucketSizes = remoteSizes;
        }
      }
    }

    int size = 0;
    if (bucketSizes != null) {
      for (SizeEntry entry : bucketSizes.values()) {
        size += entry.getSize();
      }
    }
    return size;
  }

  @Override
  long getEstimatedLocalSize() {
    final PartitionedRegionDataStore ds = dataStore;
    if (ds != null) {
      return ds.getEstimatedLocalBucketSize(false);
    } else {
      return 0;
    }
  }

  /**
   * This method gets a PartitionServerSocketConnection to targetNode and sends size request to the
   * node. It returns size of all the buckets "primarily" hosted on that node. Here "primarily"
   * means that for a given bucketID that node comes first in the node list. This selective counting
   * ensures that redundant bucket size is added only once.
   *
   * @return the size of all the buckets hosted on the target node.
   */
  private Map<Integer, SizeEntry> getSizeRemotely(Set targetNodes, boolean estimate) {
    SizeResponse r = SizeMessage.send(targetNodes, this, null, estimate);
    prStats.incPartitionMessagesSent();
    Map retVal = null;
    try {
      retVal = r.waitBucketSizes();
    } catch (CacheException e) {
      checkReadiness();
      throw e;
    }
    return retVal;
  }

  /**
   * Returns the lockname used by Distributed Lock service to clean the
   * {@code allPartitionedRegions}.
   *
   */
  private String getLockNameForBucket2NodeModification(int bucketID) {
    return (getRegionIdentifier() + ":" + bucketID);
  }

  /**
   * A simple container class that holds the lock name and the service that created the lock,
   * typically used for locking buckets, but not restricted to that usage.
   *
   * @since GemFire 5.0
   */
  static class BucketLock {

    protected final DLockService lockService;

    protected final String lockName;

    private boolean lockOwned = false;

    private final InternalCache cache;

    private final boolean enableAlerts;

    protected BucketLock(String lockName, InternalCache cache, boolean enableAlerts) {
      lockService = (DLockService) cache.getPartitionedRegionLockService();
      this.cache = cache;
      this.lockName = lockName;
      this.enableAlerts = enableAlerts;
    }

    /**
     * Locks the given name (provided during construction) uninterruptibly or throws an exception.
     */
    public void lock() {
      try {
        basicLock();
      } catch (LockServiceDestroyedException e) {
        cache.getCancelCriterion().checkCancelInProgress(null);
        throw e;
      }
    }

    /**
     * Attempts to lock the given name (provided during construction) uninterruptibly
     *
     * @return true if the lock was acquired, otherwise false.
     */
    public boolean tryLock() {
      try {
        cache.getCancelCriterion().checkCancelInProgress(null);
        basicTryLock(PartitionedRegionHelper.DEFAULT_WAIT_PER_RETRY_ITERATION);
      } catch (LockServiceDestroyedException e) {
        cache.getCancelCriterion().checkCancelInProgress(null);
        throw e;
      }
      return lockOwned;
    }

    private void basicLock() {
      if (enableAlerts) {
        ReplyProcessor21.forceSevereAlertProcessing();
      }
      try {
        DistributionManager dm = cache.getInternalDistributedSystem().getDistributionManager();

        long ackWaitThreshold = 0;
        long ackSAThreshold = dm.getConfig().getAckSevereAlertThreshold() * 1000L;
        boolean suspected = false;
        boolean severeAlertIssued = false;
        DistributedMember lockHolder = null;

        long waitInterval;
        long startTime;

        if (!enableAlerts) {
          // Make sure we only attempt the lock long enough not to
          // get a 15 second warning from the reply processor.
          ackWaitThreshold = dm.getConfig().getAckWaitThreshold() * 1000L;
          waitInterval = ackWaitThreshold - 1;
          startTime = System.currentTimeMillis();
        } else if (ackSAThreshold > 0) {
          ackWaitThreshold = dm.getConfig().getAckWaitThreshold() * 1000L;
          waitInterval = ackWaitThreshold;
          startTime = System.currentTimeMillis();
        } else {
          waitInterval = PartitionedRegion.VM_OWNERSHIP_WAIT_TIME;
          startTime = 0;
        }

        while (!lockOwned) {
          cache.getCancelCriterion().checkCancelInProgress(null);
          lockOwned =
              lockService.lock(lockName, waitInterval, -1, false, false, !enableAlerts);
          if (!lockOwned && ackSAThreshold > 0 && enableAlerts) {
            long elapsed = System.currentTimeMillis() - startTime;
            if (elapsed > ackWaitThreshold && enableAlerts) {
              if (!suspected) {
                suspected = true;
                severeAlertIssued = false;
                waitInterval = ackSAThreshold;
                DLockRemoteToken remoteToken = lockService.queryLock(lockName);
                lockHolder = remoteToken.getLessee();
                if (lockHolder != null) {
                  dm.getDistribution().suspectMember((InternalDistributedMember) lockHolder,
                      "Has not released a partitioned region lock in over "
                          + ackWaitThreshold / 1000 + " sec");
                }
              } else if (elapsed > ackSAThreshold && enableAlerts) {
                DLockRemoteToken remoteToken = lockService.queryLock(lockName);
                if (lockHolder != null && remoteToken.getLessee() != null
                    && lockHolder.equals(remoteToken.getLessee())) {
                  if (!severeAlertIssued) {
                    severeAlertIssued = true;
                    logger.fatal(
                        "{} seconds have elapsed waiting for the partitioned region lock held by {}",
                        new Object[] {(ackWaitThreshold + ackSAThreshold) / 1000,
                            lockHolder});
                  }
                } else {
                  // either no lock holder now, or the lock holder has changed
                  // since the ackWaitThreshold last elapsed
                  suspected = false;
                  waitInterval = ackWaitThreshold;
                  lockHolder = null;
                }
              }
            }
          }
        }
      } finally {
        if (enableAlerts) {
          ReplyProcessor21.unforceSevereAlertProcessing();
        }
      }
    }

    private void basicTryLock(long time) {
      final Object key = lockName;

      final DistributionManager dm = cache.getInternalDistributedSystem().getDistributionManager();

      long start = System.currentTimeMillis();
      long end;
      long timeoutMS = time;
      if (timeoutMS < 0) {
        timeoutMS = Long.MAX_VALUE;
        end = Long.MAX_VALUE;
      } else {
        end = start + timeoutMS;
      }

      long ackSAThreshold =
          cache.getInternalDistributedSystem().getConfig().getAckSevereAlertThreshold() * 1000L;
      boolean suspected = false;
      boolean severeAlertIssued = false;
      DistributedMember lockHolder = null;

      long waitInterval;
      long ackWaitThreshold;

      if (ackSAThreshold > 0) {
        ackWaitThreshold =
            cache.getInternalDistributedSystem().getConfig().getAckWaitThreshold() * 1000L;
        waitInterval = ackWaitThreshold;
        start = System.currentTimeMillis();
      } else {
        waitInterval = timeoutMS;
        ackWaitThreshold = 0;
        start = 0;
      }

      do {
        try {
          waitInterval = Math.min(end - System.currentTimeMillis(), waitInterval);
          ReplyProcessor21.forceSevereAlertProcessing();
          lockOwned = lockService.lock(key, waitInterval, -1, true, false);
          if (lockOwned) {
            return;
          }
          if (ackSAThreshold > 0) {
            long elapsed = System.currentTimeMillis() - start;
            if (elapsed > ackWaitThreshold) {
              if (!suspected) {
                // start suspect processing on the holder of the lock
                suspected = true;
                severeAlertIssued = false; // in case this is a new lock holder
                waitInterval = ackSAThreshold;
                DLockRemoteToken remoteToken = lockService.queryLock(key);
                lockHolder = remoteToken.getLessee();
                if (lockHolder != null) {
                  dm.getDistribution().suspectMember((InternalDistributedMember) lockHolder,
                      "Has not released a global region entry lock in over "
                          + ackWaitThreshold / 1000 + " sec");
                }
              } else if (elapsed > ackSAThreshold) {
                DLockRemoteToken remoteToken = lockService.queryLock(key);
                if (lockHolder != null && remoteToken.getLessee() != null
                    && lockHolder.equals(remoteToken.getLessee())) {
                  if (!severeAlertIssued) {
                    severeAlertIssued = true;
                    logger.fatal(
                        "{} seconds have elapsed waiting for global region entry lock held by {}",
                        (ackWaitThreshold + ackSAThreshold) / 1000,
                        lockHolder);
                  }
                } else {
                  // the lock holder has changed
                  suspected = false;
                  waitInterval = ackWaitThreshold;
                  lockHolder = null;
                }
              }
            }
          } // ackSAThreshold processing
        } catch (IllegalStateException ex) {
          cache.getCancelCriterion().checkCancelInProgress(null);
          throw ex;
        } finally {
          ReplyProcessor21.unforceSevereAlertProcessing();
        }
      } while (System.currentTimeMillis() < end);
    }

    /**
     * Ask the grantor who has the lock
     *
     * @return the ID of the member holding the lock
     */
    public DistributedMember queryLock() {
      try {
        DLockRemoteToken remoteToken = lockService.queryLock(lockName);
        return remoteToken.getLessee();
      } catch (LockServiceDestroyedException e) {
        cache.getCancelCriterion().checkCancelInProgress(null);
        throw e;
      }
    }

    public void unlock() {
      if (lockOwned) {
        try {
          lockService.unlock(lockName);
        } catch (LockServiceDestroyedException e) {
          // cache was probably closed which destroyed this lock service
          // note: destroyed lock services release all held locks
          cache.getCancelCriterion().checkCancelInProgress(null);
          if (logger.isDebugEnabled()) {
            logger.debug("BucketLock#unlock: Lock service {} was destroyed", lockService, e);
          }
        } finally {
          lockOwned = false;
        }
      }
    }

    @Override
    public boolean equals(Object obj) {
      if (obj == this) {
        return true;
      }
      if (!(obj instanceof BucketLock)) {
        return false;
      }

      BucketLock other = (BucketLock) obj;
      if (!lockName.equals(other.lockName)) {
        return false;
      }

      DLockService ls1 = lockService;
      DLockService ls2 = other.lockService;
      if (ls1 == null || ls2 == null) {
        // If both are null, return true, if only one is null, return false
        return ls1 == ls2;
      }
      return ls1.equals(ls2);
    }

    @Override
    public int hashCode() {
      return lockName.hashCode();
    }

    @Override
    public String toString() {
      return "BucketLock@" + System.identityHashCode(this) + "lockName=" + lockName
          + " lockService=" + lockService;
    }
  } // end class BucketLock

  public BucketLock getBucketLock(int bucketID) {
    String lockName = getLockNameForBucket2NodeModification(bucketID);
    return new BucketLock(lockName, getCache(), false);
  }

  public static class RegionLock extends BucketLock {
    protected RegionLock(String regionIdentifier, InternalCache cache) {
      super(regionIdentifier, cache, true);
    }

    @Override
    public String toString() {
      return "RegionLock@" + System.identityHashCode(this) + "lockName=" + super.lockName
          + " lockService=" + super.lockService;
    }
  }

  public class RecoveryLock extends BucketLock {
    protected RecoveryLock() {
      super(getRegionIdentifier() + "-RecoveryLock", getCache(), false);
    }

    @Override
    public String toString() {
      return "RecoveryLock@" + System.identityHashCode(this) + "lockName=" + super.lockName
          + " lockService=" + super.lockService;
    }
  }

  @Override
  public String toString() {
    return "Partitioned Region " + "@"
        + Integer.toHexString(hashCode()) + " [" + "path='" + getFullPath()
        + "'; dataPolicy=" + getDataPolicy() + "; prId="
        + partitionedRegionId + "; isDestroyed=" + isDestroyed
        + "; isClosed=" + isClosed + "; retryTimeout="
        + retryTimeout + "; serialNumber=" + getSerialNumber()
        + "; partition attributes=" + getPartitionAttributes().toString()
        + "; on VM " + getMyId() + "]";
  }

  public RegionLock getRegionLock() {
    return getRegionLock(getRegionIdentifier(), getGemFireCache());
  }

  public static RegionLock getRegionLock(String regionIdentifier, InternalCache cache) {
    return new RegionLock(regionIdentifier, cache);
  }

  public RecoveryLock getRecoveryLock() {
    return new RecoveryLock();
  }

  public Node getNode() {
    return node;
  }

  @Override
  public LoaderHelper createLoaderHelper(Object key, Object callbackArgument,
      boolean netSearchAllowed, boolean netLoadAllowed, SearchLoadAndWriteProcessor searcher) {
    return new LoaderHelperImpl(this, key, callbackArgument, netSearchAllowed, netLoadAllowed,
        searcher);
  }

  public PRHARedundancyProvider getRedundancyProvider() {
    return redundancyProvider;
  }

  /**
   * This method checks if region is closed.
   */
  public void checkClosed() {
    if (isClosed) {
      throw new RegionDestroyedException(
          String.format("PR %s is locally closed", this),
          getFullPath());
    }
  }

  /**
   * This method checks if region is closed or destroyed.
   */
  public void checkClosedOrDestroyed() {
    checkClosed();
    if (isDestroyed()) {
      throw new RegionDestroyedException(toString(), getFullPath());
    }
  }

  public void setHaveCacheLoader() {
    if (!haveCacheLoader) {
      haveCacheLoader = true;
    }
  }

  /**
   * This method closes the partitioned region locally. It is invoked from the postDestroyRegion
   * method of LocalRegion {@link LocalRegion}, which is overridden in PartitionedRegion This method
   * <br>
   * Updates this prId in prIDMap <br>
   * Cleanups the data store (Removes the bucket mapping from b2n region, locally destroys b2n and
   * destroys the bucket regions. <br>
   * sends destroyPartitionedRegionMessage to other VMs so that they update their RegionAdvisor <br>
   * Sends BackupBucketMessage to other nodes
   *
   * @param event the region event
   */
  private void closePartitionedRegion(RegionEventImpl event) {
    final boolean isClose = event.getOperation().isClose();
    if (isClose) {
      setClosed();
    }
    final RegionLock rl = getRegionLock();
    try {
      rl.lock();
      logger.info("Partitioned Region {} with prId={} closing.",
          new Object[] {getFullPath(), getPRId()});
      if (!checkIfAlreadyDestroyedOrOldReference()) {
        PartitionedRegionHelper.removeGlobalMetadataForFailedNode(getNode(),
            getRegionIdentifier(), getGemFireCache(), false);
      }
      int[] serials = getRegionAdvisor().getBucketSerials();

      if (!event.getOperation().isClose() && getDiskStore() != null && getDataStore() != null) {
        for (BucketRegion bucketRegion : getDataStore().getAllLocalBucketRegions()) {
          bucketRegion.isDestroyingDiskRegion = true;
          bucketRegion.getDiskRegion().beginDestroy(bucketRegion);
        }
      }

      sendDestroyRegionMessage(event, serials); // Notify other members that this VM
      // no longer has the region

      // Must clean up pridToPR map so that messages do not get access to buckets
      // which should be destroyed
      synchronized (prIdToPR) {
        prIdToPR.put(getPRId(), PRIdMap.LOCALLY_DESTROYED, false);
      }

      redundancyProvider.shutdown();

      if (dataStore != null) {
        dataStore.cleanUp(true, !isClose);
      }
    } finally {
      // Make extra sure that the static is cleared in the event
      // a new cache is created
      synchronized (prIdToPR) {
        prIdToPR.put(getPRId(), PRIdMap.LOCALLY_DESTROYED, false);
      }

      rl.unlock();
    }

    logger.info("Partitioned Region {} with prId={} closed.",
        new Object[] {getFullPath(), getPRId()});
  }

  void setClosed() {
    isClosed = true;
  }

  public void checkForColocatedChildren() {
    List<PartitionedRegion> listOfChildRegions = ColocationHelper.getColocatedChildRegions(this);
    if (listOfChildRegions.size() != 0) {
      List<String> childRegionList = new ArrayList<>();
      for (PartitionedRegion childRegion : listOfChildRegions) {
        if (!childRegion.getName().contains(ParallelGatewaySenderQueue.QSTRING)) {
          childRegionList.add(childRegion.getFullPath());
        }
      }
      if (!childRegionList.isEmpty()) {
        throw new IllegalStateException(String.format(
            "The parent region [%s] in colocation chain cannot "
                + "be destroyed, unless all its children [%s] are destroyed",
            getFullPath(), childRegionList));
      }
    }
  }

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

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

  private void stopMissingColocatedRegionLogger() {
    ColocationLogger colocationLogger = missingColocatedRegionLogger.getAndSet(null);
    if (colocationLogger != null) {
      colocationLogger.stop();
    }
  }

  public void addMissingColocatedRegionLogger(String childName) {
    getOrSetMissingColocatedRegionLogger().addMissingChildRegion(childName);
  }

  public void addMissingColocatedRegionLogger(PartitionedRegion childRegion) {
    getOrSetMissingColocatedRegionLogger().addMissingChildRegions(childRegion);
  }

  /**
   * Returns existing ColocationLogger or creates and sets a new instance if one does not yet exist.
   * Spins to ensure that if another thread sets ColocationLogger, we return that one instead of
   * setting another instance. Checks CancelCriterion during spin and either returns an instance or
   * throws NullPointerException. The only way to exist the loop is with an instance or by throwing
   * CancelException if the Cache closes.
   */
  private ColocationLogger getOrSetMissingColocatedRegionLogger() {
    ColocationLogger colocationLogger = missingColocatedRegionLogger.get();
    while (colocationLogger == null) {
      colocationLogger = colocationLoggerFactory.startColocationLogger(this);
      if (!missingColocatedRegionLogger.compareAndSet(null, colocationLogger)) {
        colocationLogger = missingColocatedRegionLogger.get();
      }
      getCancelCriterion().checkCancelInProgress();
    }
    requireNonNull(colocationLogger);
    return colocationLogger;
  }

  public List<String> getMissingColocatedChildren() {
    ColocationLogger colocationLogger = missingColocatedRegionLogger.get();
    if (colocationLogger != null) {
      return colocationLogger.updateAndGetMissingChildRegions();
    }
    return Collections.emptyList();
  }

  public void destroyParallelGatewaySenderRegion(Operation op, boolean cacheWrite, boolean lock,
      boolean callbackEvents) {

    if (logger.isDebugEnabled()) {
      logger.debug("Destroying parallel queue region for senders: {}",
          getParallelGatewaySenderIds());
    }

    boolean keepWaiting = true;

    while (true) {
      List<String> pausedSenders = new ArrayList<>();
      List<ConcurrentParallelGatewaySenderQueue> parallelQueues =
          new ArrayList<>();
      isDestroyedForParallelWAN = true;
      int countOfQueueRegionsToBeDestroyed = 0;
      for (String senderId : getParallelGatewaySenderIds()) {
        AbstractGatewaySender sender =
            (AbstractGatewaySender) cache.getGatewaySender(senderId);
        if (sender == null || sender.getEventProcessor() == null) {
          continue;
        }

        if (cacheWrite) { // in case of destroy operation senders should be
                          // resumed
          if (sender.isPaused()) {
            pausedSenders.add(senderId);
            continue;
          }
        }

        if (pausedSenders.isEmpty()) { // if there are puase sender then only
                                       // check for other pause senders instead
                                       // of creating list of shadowPR
          AbstractGatewaySenderEventProcessor ep = sender.getEventProcessor();
          if (ep == null) {
            continue;
          }
          ConcurrentParallelGatewaySenderQueue parallelQueue =
              (ConcurrentParallelGatewaySenderQueue) ep.getQueue();
          PartitionedRegion parallelQueueRegion = parallelQueue.getRegion(getFullPath());

          // this may be removed in previous iteration
          if (parallelQueueRegion == null || parallelQueueRegion.isDestroyed
              || parallelQueueRegion.isClosed) {
            continue;
          }

          parallelQueues.add(parallelQueue);
          countOfQueueRegionsToBeDestroyed++;
        }
      }

      if (!pausedSenders.isEmpty()) {
        String exception = null;
        if (pausedSenders.size() == 1) {
          exception =
              String.format("GatewaySender %s is paused. Resume it before destroying region %s.",
                  pausedSenders, getName());
        } else {
          exception =
              String.format(
                  "GatewaySenders %s are paused. Resume them before destroying region %s.",
                  pausedSenders, getName());
        }
        isDestroyedForParallelWAN = false;
        throw new GatewaySenderException(exception);
      }

      if (countOfQueueRegionsToBeDestroyed == 0) {
        break;
      }

      for (ConcurrentParallelGatewaySenderQueue parallelQueue : parallelQueues) {
        PartitionedRegion parallelQueueRegion = parallelQueue.getRegion(getFullPath());
        // CacheWrite true == distributedDestoy. So in case of false, dont wait
        // for queue to drain
        // parallelQueueRegion.size() = With DistributedDestroym wait for queue
        // to drain
        // keepWaiting : comes from the MAXIMUM_SHUTDOWN_WAIT_TIME case handled
        if (cacheWrite && parallelQueueRegion.size() != 0 && keepWaiting) {
          continue;
        } else {// In any case, destroy shadow PR locally. distributed destroy of
                // userPR will take care of detsroying shadowPR locally on other
                // nodes.
          RegionEventImpl event = null;
          if (op.isClose()) { // In case of cache close operation, we want SPR's basic destroy to go
                              // through CACHE_CLOSE condition of postDestroyRegion not
                              // closePartitionedRegion code
            event = new RegionEventImpl(parallelQueueRegion, op, null, false, getMyId(),
                generateEventID());
          } else {
            event = new RegionEventImpl(parallelQueueRegion, Operation.REGION_LOCAL_DESTROY, null,
                false, getMyId(), generateEventID());
          }
          parallelQueueRegion.basicDestroyRegion(event, false, lock, callbackEvents);
          parallelQueue.removeShadowPR(getFullPath());
          countOfQueueRegionsToBeDestroyed--;
          continue;
        }
      }

      if (countOfQueueRegionsToBeDestroyed == 0) {
        break;
      }

      if (cacheWrite) {
        if (AbstractGatewaySender.MAXIMUM_SHUTDOWN_WAIT_TIME == -1) {
          keepWaiting = true;
          try {
            Thread.sleep(5000);
          } catch (InterruptedException ignore) {
            // interrupted
          }
        } else {
          try {
            Thread.sleep(AbstractGatewaySender.MAXIMUM_SHUTDOWN_WAIT_TIME * 1000L);
          } catch (InterruptedException ignore) {/* ignore */
            // interrupted
          }
          keepWaiting = false;
        }
      }
    }
  }

  @Override
  public void localDestroyRegion(Object aCallbackArgument) {
    getDataView().checkSupportsRegionDestroy();
    String prName = getColocatedWith();
    List<PartitionedRegion> listOfChildRegions = ColocationHelper.getColocatedChildRegions(this);

    List<String> childRegionsWithoutSendersList = new ArrayList<>();
    if (listOfChildRegions.size() != 0) {
      for (PartitionedRegion childRegion : listOfChildRegions) {
        if (!childRegion.getName().contains(ParallelGatewaySenderQueue.QSTRING)) {
          childRegionsWithoutSendersList.add(childRegion.getFullPath());
        }
      }
    }

    if ((prName != null) || (!childRegionsWithoutSendersList.isEmpty())) {
      throw new UnsupportedOperationException(
          "Any Region in colocation chain cannot be destroyed locally.");
    }

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

  /**
   * This method actually destroys the local accessor and data store. This method is invoked from
   * the postDestroyRegion method of LocalRegion {@link LocalRegion}, which is overridden in
   * PartitionedRegion This method is invoked from postDestroyRegion method. If origin is local:
   * <br>
   * Takes region lock <br>
   * Removes prId from PRIDMap <br>
   * Does data store cleanup (removal of bucket regions) <br>
   * Sends destroyRegionMessage to other nodes <br>
   * Removes it from allPartitionedRegions <br>
   * Destroys bucket2node region
   *
   * @param event the RegionEvent that triggered this operation
   *
   * @see #destroyPartitionedRegionLocally(boolean)
   * @see #destroyPartitionedRegionGlobally(RegionEventImpl)
   * @see #destroyCleanUp(RegionEventImpl, int[])
   * @see DestroyPartitionedRegionMessage
   */
  private void destroyPartitionedRegion(RegionEventImpl event) {
    final RegionLock rl = getRegionLock();
    boolean isLocked = false;

    boolean removeFromDisk = !event.getOperation().isClose();
    try {
      logger.info("Partitioned Region {} with prId={} is being destroyed.",
          new Object[] {getFullPath(), getPRId()});
      if (!event.isOriginRemote()) {
        try {
          rl.lock();
          isLocked = true;
        } catch (CancelException ignore) {
          // ignore
        }
        if (!destroyPartitionedRegionGlobally(event)) {
          if (destroyPartitionedRegionLocally(removeFromDisk)) {
            sendLocalDestroyRegionMessage(event);
          }
        }
      } else {
        PartitionRegionConfig prConfig = null;
        try {
          prConfig = getPRRoot().get(getRegionIdentifier());
        } catch (CancelException ignore) {
          // ignore; metadata not accessible
        }
        if (!checkIfAlreadyDestroyedOrOldReference() && null != prConfig
            && !prConfig.getIsDestroying()) {
          try {
            rl.lock();
            isLocked = true;
          } catch (CancelException ignore) {
            // ignore
          }
          if (!destroyPartitionedRegionGlobally(event)) {
            if (destroyPartitionedRegionLocally(removeFromDisk)) {
              sendLocalDestroyRegionMessage(event);
            }
          }
        } else {
          if (destroyPartitionedRegionLocally(removeFromDisk)) {
            sendLocalDestroyRegionMessage(event);
          }
        }
      }
      logger.info("Partitioned Region {} with prId={} is destroyed.",
          new Object[] {getFullPath(), getPRId()});
    } finally {
      try {
        if (isLocked) {
          rl.unlock();
        }
      } catch (Exception es) {
        logger.info("Caught exception while trying to unlock during Region destruction.",
            es);
      }
    }
  }

  /**
   * This method destroys the PartitionedRegion globally. It sends destroyRegion message to other
   * nodes and handles cleaning up of the data stores and meta-data.
   *
   * @param event the RegionEvent which triggered this global destroy operation
   * @return true if the region was found globally.
   */
  private boolean destroyPartitionedRegionGlobally(RegionEventImpl event) {
    if (checkIfAlreadyDestroyedOrOldReference()) {
      return false;
    }
    PartitionRegionConfig prConfig;
    try {
      prConfig = getPRRoot().get(getRegionIdentifier());
    } catch (CancelException ignore) {
      // global data not accessible, don't try to finish global destroy.
      return false;
    }

    if (prConfig == null || prConfig.getIsDestroying()) {
      return false;
    }
    prConfig.setIsDestroying();
    try {
      getPRRoot().put(getRegionIdentifier(), prConfig);
    } catch (CancelException ignore) {
      // ignore; metadata not accessible
    }
    int[] serials = getRegionAdvisor().getBucketSerials();
    final boolean isClose = event.getOperation().isClose();
    destroyPartitionedRegionLocally(!isClose);
    destroyCleanUp(event, serials);
    return true;
  }

  private void sendLocalDestroyRegionMessage(RegionEventImpl event) {
    int[] serials = getRegionAdvisor().getBucketSerials();
    RegionEventImpl eventForLocalDestroy = (RegionEventImpl) event.clone();
    eventForLocalDestroy.setOperation(Operation.REGION_LOCAL_DESTROY);
    sendDestroyRegionMessage(event, serials);
  }

  /**
   * This method: <br>
   * Sends DestroyRegionMessage to other nodes <br>
   * Removes this PartitionedRegion from allPartitionedRegions <br>
   * Destroys bucket2node region <br>
   *
   * @param event the RegionEvent that triggered the region clean up
   *
   * @see DestroyPartitionedRegionMessage
   */
  private void destroyCleanUp(RegionEventImpl event, int[] serials) {
    String rId = getRegionIdentifier();
    try {
      if (logger.isDebugEnabled()) {
        logger.debug("PartitionedRegion#destroyCleanUp: Destroying region: {}", getFullPath());
      }
      sendDestroyRegionMessage(event, serials);
      try {
        // if this event is global destruction of the region everywhere, remove
        // it from the pr root configuration
        if (null != getPRRoot()) {
          getPRRoot().destroy(rId);
        }
      } catch (EntryNotFoundException ex) {
        if (logger.isDebugEnabled()) {
          logger.debug("PartitionedRegion#destroyCleanup: caught exception", ex);
        }
      } catch (CancelException ignore) {
        // ignore; metadata not accessible
      }
    } finally {
      if (logger.isDebugEnabled()) {
        logger.debug("PartitionedRegion#destroyCleanUp: " + "Destroyed region: {}", getFullPath());
      }
    }
  }

  /**
   * Sends the partitioned region specific destroy region message and waits for any responses. This
   * message is also sent in close/localDestroyRegion operation. When it is sent in Cache
   * close/Region close/localDestroyRegion operations, it results in updating of RegionAdvisor on
   * recipient nodes.
   *
   * @param event the destruction event
   * @param serials the bucket serials hosted locally
   * @see Region#destroyRegion()
   * @see Region#close()
   * @see Region#localDestroyRegion()
   * @see GemFireCacheImpl#close()
   */
  private void sendDestroyRegionMessage(RegionEventImpl event, int[] serials) {
    boolean retry = true;
    while (retry) {
      retry = attemptToSendDestroyRegionMessage(event, serials);
    }
  }

  private boolean attemptToSendDestroyRegionMessage(RegionEventImpl event, int[] serials) {
    if (getPRRoot() == null) {
      if (logger.isDebugEnabled()) {
        logger.debug(
            "Partition region {} failed to initialize. Remove its profile from remote members.",
            this);
      }
      new UpdateAttributesProcessor(this, true).distribute(false);
      return false;
    }
    final HashSet configRecipients = new HashSet(getRegionAdvisor().adviseAllPRNodes());

    // It's possible this instance has not been initialized
    // or hasn't gotten through initialize() far enough to have
    // sent a CreateRegionProcessor message, bug 36048
    try {
      final PartitionRegionConfig prConfig = getPRRoot().get(getRegionIdentifier());

      if (prConfig != null) {
        // Fix for bug#34621 by Tushar
        for (final Node value : prConfig.getNodes()) {
          InternalDistributedMember idm = value.getMemberId();
          if (!idm.equals(getMyId())) {
            configRecipients.add(idm);
          }
        }
      }
    } catch (CancelException ignore) {
      // ignore
    }

    try {
      DestroyPartitionedRegionResponse resp =
          DestroyPartitionedRegionMessage.send(configRecipients, this, event, serials);
      resp.waitForRepliesUninterruptibly();
    } catch (ReplyException e) {
      if (e.getRootCause() instanceof ForceReattemptException) {
        return true;
      }
      logger.warn(
          "PartitionedRegion#sendDestroyRegionMessage: Caught exception during DestroyRegionMessage send and waiting for response",
          e);
    }
    return false;
  }

  /**
   * This method is used to destroy this partitioned region data and its associated store and
   * removal of its PartitionedRegionID from local prIdToPR map. This method is called from
   * destroyPartitionedRegion Method and removes the entry from prIdMap and cleans the data store
   * buckets. It first checks whether this PartitionedRegion is already locally destroyed. If it is,
   * this call returns, else if process with the removal from prIdMap and dataStore cleanup.
   *
   * @return wether local destroy happened
   *
   * @see #destroyPartitionedRegion(RegionEventImpl)
   */
  boolean destroyPartitionedRegionLocally(boolean removeFromDisk) {
    synchronized (this) {
      if (isLocallyDestroyed) {
        return false;
      }
      locallyDestroyingThread = Thread.currentThread();
      isLocallyDestroyed = true;
    }
    if (logger.isDebugEnabled()) {
      logger.debug("destroyPartitionedRegionLocally: Starting destroy for PR = {}", this);
    }
    try {
      synchronized (prIdToPR) {
        prIdToPR.remove(getPRId());
      }
      redundancyProvider.shutdown(); // see bug 41094
      if (dataStore != null) {
        dataStore.cleanUp(false, removeFromDisk);
      }
    } finally {
      getRegionAdvisor().close();
      getPrStats().close();
      cache.getInternalResourceManager(false).removeResourceListener(this);
      locallyDestroyingThread = null;
      if (logger.isDebugEnabled()) {
        logger.debug("destroyPartitionedRegionLocally: Ending destroy for PR = {}", this);
      }
    }
    return true;
  }

  /**
   * This method is invoked from recursiveDestroyRegion method of LocalRegion. This method checks
   * the region type and invokes the relevant method.
   *
   * @param destroyDiskRegion - true if the contents on disk should be destroyed
   * @param event the RegionEvent
   */
  @Override
  protected void postDestroyRegion(boolean destroyDiskRegion, RegionEventImpl event) {
    if (logger.isDebugEnabled()) {
      logger.debug("PartitionedRegion#postDestroyRegion: {}", this);
    }
    Assert.assertTrue(isDestroyed || isClosed);

    // Fixes 44551 - wait for persistent buckets to finish
    // recovering before sending the destroy region message
    // any GII or wait for persistent recovery will be aborted by the destroy
    // flag being set to true, so this shouldn't take long.
    redundancyProvider.waitForPersistentBucketRecovery();
    // fix #39196 OOME caused by leak in GemFireCache.partitionedRegions
    cache.removePartitionedRegion(this);
    cache.getInternalResourceManager(false).removeResourceListener(this);

    final Operation op = event.getOperation();
    stopMissingColocatedRegionLogger();
    if (op.isClose() || Operation.REGION_LOCAL_DESTROY.equals(op)) {
      try {
        if (Operation.CACHE_CLOSE.equals(op) || Operation.FORCED_DISCONNECT.equals(op)) {
          int[] serials = getRegionAdvisor().getBucketSerials();

          try {
            getRegionAdvisor().closeBucketAdvisors();
            // BUGFIX for bug#34672 by Tushar Apshankar. It would update the
            // advisors on other nodes about cache closing of this PartitionedRegion
            sendDestroyRegionMessage(event, serials);

            // Because this code path never cleans up the real buckets, we need
            // to log the fact that those buckets are destroyed here
            if (RegionLogger.isEnabled()) {
              PartitionedRegionDataStore store = getDataStore();
              if (store != null) {
                for (BucketRegion bucket : store.getAllLocalBucketRegions()) {
                  RegionLogger.logDestroy(bucket.getFullPath(), getMyId(), bucket.getPersistentID(),
                      true);
                }
              }
            }
          } catch (CancelException ignore) {
            // Don't throw this; we're just trying to remove the region.
            if (logger.isDebugEnabled()) {
              logger.debug(
                  "postDestroyRegion: failed sending DestroyRegionMessage due to cache closure");
            }
          } finally {
            // Since we are not calling closePartitionedRegion
            // we need to cleanup any diskStore we own here.
            // Why don't we call closePartitionedRegion?
            // Instead of closing it, we need to register it to be closed later
            // Otherwise, when the cache close tries to close all of the bucket regions,
            // they'll fail because their disk store is already closed.
            DiskStoreImpl dsi = getDiskStore();
            if (dsi != null && dsi.getOwnedByRegion()) {
              cache.addDiskStore(dsi);
            }
            closeDataStoreStats();
          }

          // Majority of cache close operations handled by
          // afterRegionsClosedByCacheClose(GemFireCache
          // cache) or GemFireCache.close()
        } else {
          if (logger.isDebugEnabled()) {
            logger.debug("Making closePartitionedRegion call for {} with origin = {} op= {}", this,
                event.isOriginRemote(), op);
          }
          try {
            closePartitionedRegion(event);
          } finally {
            if (Operation.REGION_LOCAL_DESTROY.equals(op)) {
              DiskStoreImpl dsi = getDiskStore();
              if (dsi != null && dsi.getOwnedByRegion()) {
                dsi.destroy();
              }
            }
          }
        }
      } finally {
        // tell other members to recover redundancy for any buckets
        getRegionAdvisor().close();
        getPrStats().close();
      }
    } else if (Operation.REGION_DESTROY.equals(op) || Operation.REGION_EXPIRE_DESTROY.equals(op)) {
      if (logger.isDebugEnabled()) {
        logger.debug(
            "PartitionedRegion#postDestroyRegion: Making destroyPartitionedRegion call for {} with originRemote = {}",
            this, event.isOriginRemote());
      }
      destroyPartitionedRegion(event);
    } else {
      Assert.assertTrue(false, "Unknown op" + op);
    }

    // set client routing information into the event
    // The destroy operation in case of PR is distributed differently
    // hence the FilterRoutingInfo is set here instead of
    // DistributedCacheOperation.distribute().
    if (!isUsedForMetaRegion() && !isUsedForPartitionedRegionAdmin()
        && !isUsedForPartitionedRegionBucket() && !isUsedForParallelGatewaySenderQueue()) {
      FilterRoutingInfo localCqFrInfo = getFilterProfile().getFilterRoutingInfoPart1(event,
          FilterProfile.NO_PROFILES, Collections.emptySet());
      FilterRoutingInfo localCqInterestFrInfo =
          getFilterProfile().getFilterRoutingInfoPart2(localCqFrInfo, event);
      if (localCqInterestFrInfo != null) {
        event.setLocalFilterInfo(localCqInterestFrInfo.getLocalFilterInfo());
      }
    }

    if (destroyDiskRegion) {
      DiskStoreImpl dsi = getDiskStore();
      if (dsi != null && getDataPolicy().withPersistence()) {
        dsi.removePersistentPR(getFullPath());
        // Fix for support issue 7870 - remove this regions
        // config from the parent disk store, if we are removing the region.
        if (colocatedWithRegion != null && colocatedWithRegion.getDiskStore() != null
            && colocatedWithRegion.getDiskStore() != dsi) {
          colocatedWithRegion.getDiskStore().removePersistentPR(getFullPath());

        }
      }
    }
    if (colocatedWithRegion != null) {
      colocatedWithRegion.getColocatedByList().remove(this);
    }

    if (bucketSorter != null) {
      bucketSorter.shutdown();
    }

    RegionLogger.logDestroy(getName(),
        cache.getInternalDistributedSystem().getDistributedMember(), null, op.isClose());
  }

  private void closeDataStoreStats() {
    if (dataStore != null) {
      CachePerfStats dataStoreStats = dataStore.getCachePerfStats();
      if (dataStoreStats != null) {
        dataStoreStats.close();
      }
    }
  }

  /**
   * This method checks whether this PartitionedRegion is eligible for the destruction or not. It
   * first gets the prConfig for this region, and if it NULL, it sends a
   * destroyPartitionedRegionLocally call as a pure precautionary measure. If it is not null, we
   * check if this call is intended for this region only and there is no new PartitionedRegion
   * creation with the same name. This check fixes, bug # 34621.
   *
   * @return true, if it is eligible for the region destroy
   */
  private boolean checkIfAlreadyDestroyedOrOldReference() {
    PartitionRegionConfig prConfig = null;
    try {
      prConfig = getPRRoot().get(getRegionIdentifier());
    } catch (CancelException ignore) {
      // ignore, metadata not accessible
    }
    boolean isAlreadyDestroyedOrOldReference = false;
    if (null == prConfig) {
      isAlreadyDestroyedOrOldReference = true;
    } else {
      // If this reference is a destroyed reference and a new PR is created
      // after destruction of the older one is complete, bail out.
      if (prConfig.getPRId() != partitionedRegionId) {
        isAlreadyDestroyedOrOldReference = true;
      }
    }
    return isAlreadyDestroyedOrOldReference;
  }

  @Override
  public void dispatchListenerEvent(EnumListenerEvent op, InternalCacheEvent event) {
    // don't dispatch the event if the interest policy forbids it
    if (hasListener()) {
      if (event.getOperation().isEntry()) {
        EntryEventImpl ev = (EntryEventImpl) event;
        if (!ev.getInvokePRCallbacks()) {
          if (getSubscriptionAttributes()
              .getInterestPolicy() == InterestPolicy.CACHE_CONTENT) {
            if (logger.isTraceEnabled(LogMarker.DM_BRIDGE_SERVER_VERBOSE)) {
              logger.trace(LogMarker.DM_BRIDGE_SERVER_VERBOSE,
                  "not dispatching PR event in this member as there is no interest in it");
            }
            return;
          }
        }
      }
      super.dispatchListenerEvent(op, event);
    }
  }

  @Override
  void generateLocalFilterRouting(InternalCacheEvent event) {
    if (event.getLocalFilterInfo() == null) {
      super.generateLocalFilterRouting(event);
    }
  }

  /**
   * Invoke the cache writer before a put is performed. Each BucketRegion delegates to the
   * CacheWriter on the PartitionedRegion meaning that CacheWriters on a BucketRegion should only be
   * used for internal purposes.
   *
   * @see BucketRegion#cacheWriteBeforePut(EntryEventImpl, Set, CacheWriter, boolean, Object)
   */
  @Override
  public void cacheWriteBeforePut(EntryEventImpl event, Set netWriteRecipients,
      CacheWriter localWriter, boolean requireOldValue, Object expectedOldValue)
      throws CacheWriterException, TimeoutException {
    final boolean isDebugEnabled = logger.isDebugEnabled();

    // return if notifications are inhibited
    if (event.inhibitAllNotifications()) {
      if (isDebugEnabled) {
        logger.debug("Notification inhibited for key {}", event.getKey());
      }

      return;
    }

    final boolean isNewKey = event.getOperation().isCreate();
    serverPut(event, requireOldValue, expectedOldValue);
    if (localWriter == null && (netWriteRecipients == null || netWriteRecipients.isEmpty())) {
      if (isDebugEnabled) {
        logger.debug(
            "cacheWriteBeforePut: beforePut empty set returned by advisor.adviseNetWrite in netWrite");
      }
      return;
    }

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

    try {
      SearchLoadAndWriteProcessor processor = SearchLoadAndWriteProcessor.getProcessor();
      processor.initialize(this, "preUpdate", null);
      try {
        if (!isNewKey) {
          if (isDebugEnabled) {
            logger.debug("cacheWriteBeforePut: doNetWrite(BEFOREUPDATE)");
          }
          processor.doNetWrite(event, netWriteRecipients, localWriter,
              SearchLoadAndWriteProcessor.BEFOREUPDATE);
        } else {
          if (isDebugEnabled) {
            logger.debug("cacheWriteBeforePut: doNetWrite(BEFORECREATE)");
          }
          // sometimes the op will erroneously be UPDATE
          processor.doNetWrite(event, netWriteRecipients, localWriter,
              SearchLoadAndWriteProcessor.BEFORECREATE);
        }
      } finally {
        processor.release();
      }
    } finally {
      getCachePerfStats().endCacheWriterCall(start);
    }
  }

  /**
   * Invoke the CacheWriter before the detroy operation occurs. Each BucketRegion delegates to the
   * CacheWriter on the PartitionedRegion meaning that CacheWriters on a BucketRegion should only be
   * used for internal purposes.
   *
   * @see BucketRegion#cacheWriteBeforeDestroy(EntryEventImpl, Object)
   */
  @Override
  public boolean cacheWriteBeforeDestroy(EntryEventImpl event, Object expectedOldValue)
      throws CacheWriterException, EntryNotFoundException, TimeoutException {
    // return if notifications are inhibited
    if (event.inhibitAllNotifications()) {
      if (logger.isDebugEnabled()) {
        logger.debug("Notification inhibited for key {}", event.getKey());
      }
      return false;
    }

    if (event.isDistributed()) {
      serverDestroy(event, expectedOldValue);
      CacheWriter localWriter = basicGetWriter();
      Set netWriteRecipients = localWriter == null ? distAdvisor.adviseNetWrite() : null;

      if (localWriter == null && (netWriteRecipients == null || netWriteRecipients.isEmpty())) {
        return false;
      }

      final long start = getCachePerfStats().startCacheWriterCall();
      try {
        event.setOldValueFromRegion();
        SearchLoadAndWriteProcessor processor = SearchLoadAndWriteProcessor.getProcessor();
        processor.initialize(this, event.getKey(), null);
        processor.doNetWrite(event, netWriteRecipients, localWriter,
            SearchLoadAndWriteProcessor.BEFOREDESTROY);
        processor.release();
      } finally {
        getCachePerfStats().endCacheWriterCall(start);
      }
      return true;
    }
    return false;
  }

  /**
   * Send a message to all PartitionedRegion participants, telling each member of the
   * PartitionedRegion with a datastore to dump the contents of the buckets to the system.log and
   * validate that the meta-data for buckets agrees with the data store's perspective
   *
   * @param distribute true will distributed a DumpBucketsMessage to PR nodes
   * @see #validateAllBuckets()
   */
  public void dumpAllBuckets(boolean distribute) throws ReplyException {
    if (logger.isDebugEnabled()) {
      logger.debug("[dumpAllBuckets] distribute={} {}", distribute, this);
    }
    getRegionAdvisor().dumpProfiles("dumpAllBuckets");
    if (distribute) {
      PartitionResponse response = DumpBucketsMessage.send(getRegionAdvisor().adviseAllPRNodes(),
          this, false /* only validate */, false);
      response.waitForRepliesUninterruptibly();
    }
    if (dataStore != null) {
      dataStore.dumpEntries(false /* onlyValidate */);
    }
  }

  @Override
  public void dumpBackingMap() {
    dumpAllBuckets(true);
  }

  /**
   * Send a message to all PartitionedRegion participants, telling each member of the
   * PartitionedRegion with a datastore to validate that the meta-data for buckets agrees with the
   * data store's perspective
   *
   * @see #dumpAllBuckets(boolean)
   */
  public void validateAllBuckets() throws ReplyException {
    PartitionResponse response = DumpBucketsMessage.send(getRegionAdvisor().adviseAllPRNodes(),
        this, true /* only validate */, false);
    response.waitForRepliesUninterruptibly();
    if (dataStore != null) {
      dataStore.dumpEntries(true /* onlyValidate */);
    }
  }

  /**
   * Sends a message to all the {@code PartitionedRegion} participants, telling each member of the
   * PartitionedRegion to dump the nodelist in bucket2node metadata for specified bucketId.
   */
  public void sendDumpB2NRegionForBucket(int bucketId) {
    getRegionAdvisor().dumpProfiles("dumpB2NForBucket");
    try {
      PartitionResponse response =
          DumpB2NRegion.send(getRegionAdvisor().adviseAllPRNodes(), this, bucketId, false);
      response.waitForRepliesUninterruptibly();
      dumpB2NForBucket(bucketId);
    } catch (ReplyException re) {
      if (logger.isDebugEnabled()) {
        logger.debug("sendDumpB2NRegionForBucket got ReplyException", re);
      }
    } catch (CancelException e) {
      if (logger.isDebugEnabled()) {
        logger.debug("sendDumpB2NRegionForBucket got CacheClosedException", e);
      }
    } catch (RegionDestroyedException e) {
      if (logger.isDebugEnabled()) {
        logger.debug("sendDumpB2RegionForBucket got RegionDestroyedException", e);
      }
    }
  }

  /**
   * Logs the b2n nodelist for specified bucketId.
   */
  public void dumpB2NForBucket(int bId) {
    getRegionAdvisor().getBucket(bId).getBucketAdvisor()
        .dumpProfiles("Dumping advisor bucket meta-data for bId=" + bucketStringForLogs(bId)
            + " aka " + getBucketName(bId));
  }

  /**
   * Send a message to all PartitionedRegion participants, telling each member of the
   * PartitionedRegion with a datastore to dump the contents of the allPartitionedRegions for this
   * PartitionedRegion.
   */
  public void sendDumpAllPartitionedRegions() throws ReplyException {
    getRegionAdvisor().dumpProfiles("dumpAllPartitionedRegions");
    PartitionResponse response =
        DumpAllPRConfigMessage.send(getRegionAdvisor().adviseAllPRNodes(), this);
    response.waitForRepliesUninterruptibly();
    dumpSelfEntryFromAllPartitionedRegions();
  }

  /**
   * This method prints the content of the allPartitionedRegion's contents for this
   * PartitionedRegion.
   */
  public void dumpSelfEntryFromAllPartitionedRegions() {
    final String sb = getPRRoot().getFullPath() + "Dumping allPartitionedRegions for "
        + this
        + "\n"
        + getPRRoot().get(getRegionIdentifier());
    logger.debug(sb);
  }

  /**
   * A test method to get the list of all the bucket ids for the partitioned region in the data
   * Store.
   */
  public List<Integer> getLocalBucketsListTestOnly() {
    List<Integer> localBucketList = null;
    if (dataStore != null) {
      localBucketList = dataStore.getLocalBucketsListTestOnly();
    }
    return localBucketList;
  }

  /**
   * A test method to get the list of all the primary bucket ids for the partitioned region in the
   * data Store.
   */
  public List<Integer> getLocalPrimaryBucketsListTestOnly() {
    List<Integer> localPrimaryList = null;
    if (dataStore != null) {
      localPrimaryList = dataStore.getLocalPrimaryBucketsListTestOnly();
    }
    return localPrimaryList;
  }

  /** doesn't throw RegionDestroyedException, used by CacheDistributionAdvisor */
  @Override
  public DistributionAdvisee getParentAdvisee() {
    return (DistributionAdvisee) basicGetParentRegion();
  }

  /**
   * A Simple class used to track retry time for Region operations Does not provide any
   * synchronization or concurrent safety
   */
  public static class RetryTimeKeeper {
    private long totalTimeInRetry;

    private final long maxTimeInRetry;

    public RetryTimeKeeper(int maxTime) {
      maxTimeInRetry = maxTime;
    }

    /**
     * wait for {@link PartitionedRegionHelper#DEFAULT_WAIT_PER_RETRY_ITERATION}, updating the total
     * wait time. Use this method when the same node has been selected for consecutive attempts with
     * an operation.
     */
    public void waitToRetryNode() {
      waitForBucketsRecovery();
    }

    /**
     * Wait for {@link PartitionedRegionHelper#DEFAULT_WAIT_PER_RETRY_ITERATION} time and update the
     * total wait time.
     */
    public void waitForBucketsRecovery() {
      /*
       * Unfortunately, due to interrupts plus the vagaries of thread scheduling, we can't assume
       * that our sleep is for exactly the amount of time that we specify. Thus, we need to measure
       * the before/after times and increment the counter accordingly.
       */
      long start = System.currentTimeMillis();
      boolean interrupted = Thread.interrupted();
      try {
        Thread.sleep(PartitionedRegionHelper.DEFAULT_WAIT_PER_RETRY_ITERATION);
      } catch (InterruptedException ignore) {
        interrupted = true;
      } finally {
        if (interrupted) {
          Thread.currentThread().interrupt();
        }
      }
      long delta = System.currentTimeMillis() - start;
      if (delta < 1) {
        // I don't think this can happen, but I want to guarantee that
        // this thing will eventually time out.
        delta = 1;
      }
      totalTimeInRetry += delta;
    }

    public boolean overMaximum() {
      return totalTimeInRetry > maxTimeInRetry;
    }

    public long getRetryTime() {
      return totalTimeInRetry;
    }
  }

  public String getBucketName(int bucketId) {
    return PartitionedRegionHelper.getBucketName(getFullPath(), bucketId);
  }

  public static final String BUCKET_NAME_SEPARATOR = "_";

  public boolean isDataStore() {
    return localMaxMemory > 0;
  }

  @Override
  void enableConcurrencyChecks() {
    if (supportsConcurrencyChecks()) {
      setConcurrencyChecksEnabled(true);
      assert !isDataStore();
    }
  }

  /**
   * finds all the keys matching the given regular expression (or all keys if regex is ".*")
   *
   * @param regex the regular expression
   * @param allowTombstones whether to include destroyed entries
   * @param collector object that will receive the keys as they arrive
   */
  public void getKeysWithRegEx(String regex, boolean allowTombstones, SetCollector collector)
      throws IOException {
    _getKeysWithInterest(InterestType.REGULAR_EXPRESSION, regex, allowTombstones, collector);
  }

  /**
   * finds all the keys in the given list that are present in the region
   *
   * @param keyList the key list
   * @param allowTombstones whether to return destroyed entries
   * @param collector object that will receive the keys as they arrive
   */
  public void getKeysWithList(List keyList, boolean allowTombstones, SetCollector collector)
      throws IOException {
    _getKeysWithInterest(InterestType.KEY, keyList, allowTombstones, collector);
  }

  /**
   * finds all the keys matching the given interest type and passes them to the given collector
   *
   * @param allowTombstones whether to return destroyed entries
   */
  private void _getKeysWithInterest(final @NotNull InterestType interestType, Object interestArg,
      boolean allowTombstones,
      SetCollector collector) throws IOException {
    // this could be parallelized by building up a list of buckets for each
    // vm and sending out the requests for keys in parallel. That might dump
    // more onto this vm in one swoop than it could handle, though, so we're
    // keeping it simple for now
    int totalBuckets = getTotalNumberOfBuckets();
    int retryAttempts = calcRetry();
    for (int bucket = 0; bucket < totalBuckets; bucket++) {
      Set bucketSet = null;
      final RetryTimeKeeper retryTime = new RetryTimeKeeper(Integer.MAX_VALUE);
      InternalDistributedMember bucketNode = getOrCreateNodeForBucketRead(bucket);
      for (int count = 0; count <= retryAttempts; count++) {
        if (logger.isDebugEnabled()) {
          logger.debug("_getKeysWithInterest bucketId={} attempt={}", bucket, (count + 1));
        }
        try {
          if (bucketNode != null) {
            if (bucketNode.equals(getMyId())) {
              bucketSet = dataStore.handleRemoteGetKeys(bucket, interestType, interestArg,
                  allowTombstones);
            } else {
              FetchKeysResponse r = FetchKeysMessage.sendInterestQuery(bucketNode, this, bucket,
                  interestType, interestArg, allowTombstones);
              bucketSet = r.waitForKeys();
            }
          }
          break;
        } catch (PRLocallyDestroyedException ignore) {
          if (logger.isDebugEnabled()) {
            logger.debug("_getKeysWithInterest: Encountered PRLocallyDestroyedException");
          }
          checkReadiness();
        } catch (ForceReattemptException prce) {
          // no checkKey possible
          if (logger.isDebugEnabled()) {
            logger.debug("_getKeysWithInterest: retry attempt: {}", count, prce);
          }
          checkReadiness();

          InternalDistributedMember lastTarget = bucketNode;
          bucketNode = getOrCreateNodeForBucketRead(bucket);
          if (lastTarget.equals(bucketNode)) {
            if (retryTime.overMaximum()) {
              break;
            }
            retryTime.waitToRetryNode();
          }
        }
      } // for(count)
      if (bucketSet != null) {
        collector.receiveSet(bucketSet);
      }
    } // for(bucket)
  }

  /**
   * EventIDs are generated for PartitionedRegion.
   */
  @Override
  public boolean generateEventID() {
    return true;
  }

  @Override
  public boolean shouldNotifyBridgeClients() {
    return true;
  }

  /**
   * SetCollector is implemented by classes that want to receive chunked results from queries like
   * getKeysWithRegEx. The implementor creates a method, receiveSet, that consumes the chunks.
   *
   * @since GemFire 5.1
   */
  public interface SetCollector {
    void receiveSet(Set theSet) throws IOException;
  }

  /**
   * Returns the index flag
   *
   * @return true if the partitioned region is indexed else false
   */
  public boolean isIndexed() {
    return hasPartitionedIndex;
  }

  /**
   * Returns the map containing all the indexes on this partitioned region.
   *
   * @return Map of all the indexes created.
   */
  public Map getIndex() {
    Hashtable availableIndexes = new Hashtable();
    for (final Object ind : indexes.values()) {
      // Check if the returned value is instance of Index (this means
      // the index is not in create phase, its created successfully).
      if (ind instanceof Index) {
        availableIndexes.put(((Index) ind).getName(), ind);
      }
    }
    return availableIndexes;
  }

  /**
   * Returns the a PartitionedIndex on this partitioned region.
   *
   */
  public PartitionedIndex getIndex(String indexName) {
    for (final Object ind : indexes.values()) {
      // Check if the returned value is instance of Index (this means
      // the index is not in create phase, its created successfully).
      if (ind instanceof PartitionedIndex && ((Index) ind).getName().equals(indexName)) {
        return (PartitionedIndex) ind;
      }
    }
    return null;
  }

  /**
   * Gets a collecion of all the indexes created on this pr.
   *
   * @return collection of all the indexes
   */
  public Collection getIndexes() {
    if (indexes.isEmpty()) {
      return Collections.emptyList();
    }

    ArrayList idxs = new ArrayList();
    for (final Object ind : indexes.values()) {
      // Check if the returned value is instance of Index (this means
      // the index is not in create phase, its created successfully).
      if (ind instanceof Index) {
        idxs.add(ind);
      }
    }
    return idxs;
  }

  /**
   * Creates the actual index on this partitioned regions.
   *
   * @param remotelyOriginated true if the index is created because of a remote index creation call
   * @param indexType the type of index created.
   * @param indexName the name for the index to be created
   * @param indexedExpression expression for index creation.
   * @param fromClause the from clause for index creation
   * @param imports class to be imported for fromClause.
   *
   * @return Index an index created on this region.
   * @throws ForceReattemptException indicating the operation failed to create a remote index
   * @throws IndexCreationException if the index is not created properly
   * @throws IndexNameConflictException if an index exists with this name on this region
   * @throws IndexExistsException if and index already exists with the same properties as the one
   *         created
   */
  public Index createIndex(boolean remotelyOriginated, IndexType indexType, String indexName,
      String indexedExpression, String fromClause, String imports, boolean loadEntries)
      throws ForceReattemptException, IndexCreationException, IndexNameConflictException,
      IndexExistsException {
    return createIndex(remotelyOriginated, indexType, indexName, indexedExpression, fromClause,
        imports, loadEntries, true);
  }

  public Index createIndex(boolean remotelyOriginated, IndexType indexType, String indexName,
      String indexedExpression, String fromClause, String imports, boolean loadEntries,
      boolean sendMessage) throws ForceReattemptException, IndexCreationException,
      IndexNameConflictException, IndexExistsException {
    // Check if its remote request and this vm is an accessor.
    if (remotelyOriginated && dataStore == null) {
      // This check makes sure that for some region this vm cannot create
      // data store where as it should have.
      if (getLocalMaxMemory() != 0) {
        throw new IndexCreationException(
            String.format(
                "Data Store on this vm is null and the local max Memory is not zero, the data policy is %s and the localMaxMemeory is : %s",
                getDataPolicy(), (long) getLocalMaxMemory()));
      }
      // Not have to do anything since the region is just an Accessor and
      // does not store any data.
      logger.info("This is an accessor vm and doesnt contain data");
      return null;
    }

    // Create indexManager.
    if (indexManager == null) {
      indexManager = IndexUtils.getIndexManager(cache, this, true);
    }

    if (logger.isDebugEnabled()) {
      logger.debug(
          "Started creating index with Index Name :{} On PartitionedRegion {}, Indexfrom caluse={}, Remote Request: {}",
          indexName, getFullPath(), fromClause, remotelyOriginated);
    }
    IndexTask indexTask = new IndexTask(remotelyOriginated, indexType, indexName, indexedExpression,
        fromClause, imports, loadEntries);

    FutureTask<Index> indexFutureTask = new FutureTask<>(indexTask);

    // This will return either the Index FutureTask or Index itself, based
    // on whether the index creation is in process or completed.
    Object ind = indexes.putIfAbsent(indexTask, indexFutureTask);

    // Check if its instance of Index, in that the case throw index exists exception.
    if (ind instanceof Index) {
      if (remotelyOriginated) {
        return (Index) ind;
      }

      throw new IndexNameConflictException(
          String.format("Index named ' %s ' already exists.", indexName));
    }

    FutureTask<Index> oldIndexFutureTask = (FutureTask<Index>) ind;
    Index index = null;
    boolean interrupted = false;

    try {
      if (oldIndexFutureTask == null) {
        // Index doesn't exist, create index.
        indexFutureTask.run();
        index = indexFutureTask.get();
        if (index != null) {
          indexes.put(indexTask, index);
          PartitionedIndex prIndex = (PartitionedIndex) index;
          indexManager.addIndex(indexName, index);

          // Locally originated create index request.
          // Send create request to other PR nodes.
          if (!remotelyOriginated && sendMessage) {
            logger.info(
                "Created index locally, sending index creation message to all members, and will be waiting for response {}.",
                prIndex);
            HashSet<IndexCreationData> singleIndexDefinition = new HashSet<>();
            IndexCreationData icd = new IndexCreationData(indexName);
            icd.setIndexData(indexType, fromClause, indexedExpression, imports, loadEntries);
            singleIndexDefinition.add(icd);

            IndexCreationMsg.IndexCreationResponse response = null;
            try {
              response = (IndexCreationMsg.IndexCreationResponse) IndexCreationMsg.send(null,
                  this, singleIndexDefinition);
              if (response != null) {
                IndexCreationMsg.IndexCreationResult result = response.waitForResult();
                Map<String, Integer> indexBucketsMap = result.getIndexBucketsMap();
                if (indexBucketsMap != null && indexBucketsMap.size() > 0) {
                  prIndex.setRemoteBucketesIndexed(indexBucketsMap.values().iterator().next());
                }
              }
            } catch (UnsupportedOperationException ignore) {
              // if remote nodes are of older versions indexes will not be created there, so remove
              // index on this node as well.
              indexes.remove(index);
              indexManager.removeIndex(index);
              throw new IndexCreationException(
                  "Indexes should not be created when there are older versions of gemfire in the cluster.");
            }
          }
        }
      } else {
        // Some other thread is trying to create the same index.
        // Wait for index to be initialized from other thread.
        index = oldIndexFutureTask.get();
        // The Index is successfully created, throw appropriate error message from this thread.

        if (remotelyOriginated) {
          return index;
        }

        throw new IndexNameConflictException(
            String.format("Index named ' %s ' already exists.",
                indexName));
      }
    } catch (InterruptedException ignore) {
      interrupted = true;
    } catch (ExecutionException ee) {
      if (!remotelyOriginated) {
        Throwable cause = ee.getCause();
        if (cause instanceof IndexNameConflictException) {
          throw (IndexNameConflictException) cause;
        } else if (cause instanceof IndexExistsException) {
          throw (IndexExistsException) cause;
        }
        throw new IndexInvalidException(ee);
      }
    } finally {
      // If the index is not successfully created, remove IndexTask from the map.
      if (index == null) {
        ind = indexes.get(indexTask);
        if (ind != null && !(ind instanceof Index)) {
          indexes.remove(indexTask);
        }
      }

      if (interrupted) {
        Thread.currentThread().interrupt();
      }
    }
    if (logger.isDebugEnabled()) {
      logger.debug(
          "Completed creating index with Index Name :{} On PartitionedRegion {}, Remote Request: {}",
          indexName, getFullPath(), remotelyOriginated);
    }
    return index;
  }

  public List<Index> createIndexes(boolean remotelyOriginated,
      HashSet<IndexCreationData> indexDefinitions) throws MultiIndexCreationException,
      CacheException, ForceReattemptException, IndexCreationException {
    if (remotelyOriginated && dataStore == null) {
      // This check makes sure that for some region this vm cannot create
      // data store where as it should have.
      if (getLocalMaxMemory() != 0) {
        throw new IndexCreationException(
            String.format(
                "Data Store on this vm is null and the local max Memory is not zero, the data policy is %s and the localMaxMemeory is : %s",
                getDataPolicy(), (long) getLocalMaxMemory()));
      }
      // Not have to do anything since the region is just an Accessor and
      // does not store any data.
      logger
          .info("This is an accessor vm and doesnt contain data");
      return new ArrayList<>();
    }

    Set<Index> indexes = new HashSet<>();
    boolean throwException = false;
    HashMap<String, Exception> exceptionsMap = new HashMap<>();

    // First step is creating all the defined indexes.
    // Do not send the IndexCreationMsg to remote nodes now.
    throwException |=
        createEmptyIndexes(indexDefinitions, remotelyOriginated, indexes, exceptionsMap);

    // If same indexes are created locally and also being created by a remote index creation msg
    // populate such indexes only once.
    Set<Index> unpopulatedIndexes = null;

    if (indexes.size() > 0) {
      unpopulatedIndexes = getUnpopulatedIndexes(indexes);
    }

    // Second step is iterating over REs and populating all the created indexes
    if (unpopulatedIndexes != null && unpopulatedIndexes.size() > 0) {
      throwException |= populateEmptyIndexes(unpopulatedIndexes, exceptionsMap);
    }

    // Third step is to send the message to remote nodes
    // Locally originated create index request.
    // Send create request to other PR nodes.
    throwException |=
        sendCreateIndexesMessage(remotelyOriginated, indexDefinitions, indexes, exceptionsMap);

    // If exception is throw in any of the above steps
    if (throwException) {
      throw new MultiIndexCreationException(exceptionsMap);
    }

    // set the populate flag for all the created PR indexes
    for (Index ind : indexes) {
      ((AbstractIndex) ind).setPopulated(true);
    }

    return new ArrayList<>(indexes);
  }

  @VisibleForTesting
  boolean createEmptyIndexes(HashSet<IndexCreationData> indexDefinitions,
      boolean remotelyOriginated, Set<Index> indexes, HashMap<String, Exception> exceptionsMap) {
    boolean throwException = false;
    for (IndexCreationData icd : indexDefinitions) {
      try {
        Index ind = createIndex(remotelyOriginated, icd.getIndexType(), icd.getIndexName(),
            icd.getIndexExpression(), icd.getIndexFromClause(), icd.getIndexImportString(), false,
            false);
        // There could be nulls in the set if a node is accessor.
        // The index might have been created by the local node.
        if (ind != null) {
          indexes.add(ind);
        }
      } catch (CancelException cancelException) {
        // Do not add cancel exception to exceptionsMap, re-throw instead.
        throw cancelException;
      } catch (Exception ex) {
        // If an index creation fails, add the exception to the map and
        // continue creating rest of the indexes.The failed indexes will
        // be removed from the IndexManager#indexes map by the createIndex
        // method so that those indexes will not be populated in the next
        // step.
        if (logger.isDebugEnabled()) {
          logger.debug("Creation failed for index: {}, {}", icd.getIndexName(), ex.getMessage(),
              ex);
        }
        exceptionsMap.put(icd.getIndexName(), ex);
        throwException = true;
      }
    }
    return throwException;
  }

  private Set<Index> getUnpopulatedIndexes(Set<Index> indexSet) {
    synchronized (indexLock) {
      HashSet<Index> unpopulatedIndexes = new HashSet<>();
      for (Index ind : indexSet) {
        PartitionedIndex prIndex = (PartitionedIndex) ind;
        if (!prIndex.isPopulateInProgress()) {
          prIndex.setPopulateInProgress(true);
          unpopulatedIndexes.add(prIndex);
        }
      }
      return unpopulatedIndexes;
    }
  }

  @VisibleForTesting
  boolean populateEmptyIndexes(Set<Index> indexes,
      HashMap<String, Exception> exceptionsMap) {
    boolean throwException = false;
    if (getDataStore() != null && indexes.size() > 0) {
      Set localBuckets = getDataStore().getAllLocalBuckets();
      for (final Object localBucket : localBuckets) {
        Map.Entry entry = (Map.Entry) localBucket;
        Region bucket = (Region) entry.getValue();

        if (bucket == null) {
          continue;
        }
        IndexManager bucketIndexManager = IndexUtils.getIndexManager(cache, bucket, true);
        if (bucketIndexManager == null) {
          cache.getCancelCriterion().checkCancelInProgress();
        }
        Set<Index> bucketIndexes = getBucketIndexesForPRIndexes(bucket, indexes);
        try {
          bucketIndexManager.populateIndexes(bucketIndexes);
        } catch (MultiIndexCreationException ex) {
          exceptionsMap.putAll(ex.getExceptionsMap());
          throwException = true;
        }
      }
    }
    return throwException;
  }

  @VisibleForTesting
  Set<Index> getBucketIndexesForPRIndexes(Region bucket, Set<Index> indexes) {
    Set<Index> bucketIndexes = new HashSet<>();
    for (Index ind : indexes) {
      bucketIndexes.addAll(((PartitionedIndex) ind).getBucketIndexes(bucket));
    }
    return bucketIndexes;
  }

  private boolean sendCreateIndexesMessage(boolean remotelyOriginated,
      HashSet<IndexCreationData> indexDefinitions, Set<Index> indexes,
      HashMap<String, Exception> exceptionsMap) throws CacheException, ForceReattemptException {
    boolean throwException = false;
    if (!remotelyOriginated) {
      logger.info(
          "Created index locally, sending index creation message to all members, and will be waiting for response.");
      IndexCreationMsg.IndexCreationResponse response;
      try {
        response = (IndexCreationMsg.IndexCreationResponse) IndexCreationMsg.send(null, this,
            indexDefinitions);

        if (response != null) {
          IndexCreationMsg.IndexCreationResult result = response.waitForResult();
          Map<String, Integer> remoteIndexBucketsMap = result.getIndexBucketsMap();
          // set the number of remote buckets indexed for each pr index
          if (remoteIndexBucketsMap != null) {
            for (Index ind : indexes) {
              if (remoteIndexBucketsMap.containsKey(ind.getName())) {
                ((PartitionedIndex) ind)
                    .setRemoteBucketesIndexed(remoteIndexBucketsMap.get(ind.getName()));
              }
            }
          }
        }
      } catch (UnsupportedOperationException ignore) {
        // if remote nodes are of older versions indexes will not be created
        // there, so remove index on this node as well.
        for (Index ind : indexes) {
          exceptionsMap.put(ind.getName(),
              new IndexCreationException(
                  "Indexes should not be created when there are older versions of gemfire in the cluster."));
          this.indexes.remove(ind);
          indexManager.removeIndex(ind);
        }
        throwException = true;
      }
    }
    return throwException;
  }

  /**
   * Explicitly sends an index creation message to a newly added node to the system on prs.
   *
   * @param idM id on the newly added node.
   */
  public void sendIndexCreationMsg(InternalDistributedMember idM) {
    if (!isIndexed()) {
      return;
    }

    RegionAdvisor advisor = (RegionAdvisor) getCacheDistributionAdvisor();
    final Set<InternalDistributedMember> recipients = advisor.adviseDataStore();
    if (!recipients.contains(idM)) {
      logger.info(
          "Newly added member to the PR is an accessor and will not receive index information : {}",
          idM);
      return;
    }
    // this should add the member to a synchronized set and then sent this member
    // and index creation msg latter after its completed creating the partitioned region.
    IndexCreationMsg.IndexCreationResponse response;
    IndexCreationMsg.IndexCreationResult result;

    if (indexes.isEmpty()) {
      return;
    }

    Iterator it = indexes.values().iterator();
    HashSet<IndexCreationData> indexDefinitions = new HashSet<>();
    Set<PartitionedIndex> indexes = new HashSet<>();
    while (it.hasNext()) {
      Object ind = it.next();
      // Check if the returned value is instance of Index (this means
      // the index is not in create phase, its created successfully).
      if (!(ind instanceof Index)) {
        continue;
      }
      PartitionedIndex prIndex = (PartitionedIndex) ind;
      indexes.add(prIndex);
      IndexCreationData icd = new IndexCreationData(prIndex.getName());
      icd.setIndexData(prIndex.getType(), prIndex.getFromClause(), prIndex.getIndexedExpression(),
          prIndex.getImports(), true);
      indexDefinitions.add(icd);
    }

    response =
        (IndexCreationMsg.IndexCreationResponse) IndexCreationMsg.send(idM, this, indexDefinitions);

    if (logger.isDebugEnabled()) {
      logger.debug("Sending explicitly index creation message to : {}", idM);
    }

    if (response != null) {
      try {
        result = response.waitForResult();
        Map<String, Integer> remoteIndexBucketsMap = result.getIndexBucketsMap();
        // set the number of remote buckets indexed for each pr index
        for (Index ind : indexes) {
          ((PartitionedIndex) ind)
              .setRemoteBucketesIndexed(remoteIndexBucketsMap.get(ind.getName()));
        }
      } catch (ForceReattemptException e) {
        logger.info(String.format("ForceReattempt exception : %s", e));
      }
    }
  }

  /**
   * Removes all the indexes on this partitioned regions instance and send remove index message
   */
  public int removeIndexes(boolean remotelyOriginated)
      throws CacheException, ForceReattemptException {
    int numBuckets = 0;

    if (!hasPartitionedIndex || indexes.isEmpty()) {
      if (logger.isDebugEnabled()) {
        logger.debug("This partitioned regions does not have any index : {}", this);
      }
      return numBuckets;
    }

    hasPartitionedIndex = false;

    logger.info("Removing all the indexes on this paritition region {}",
        this);

    try {
      for (Object bucketEntryObject : dataStore.getAllLocalBuckets()) {
        LocalRegion bucket = null;
        Map.Entry bucketEntry = (Map.Entry) bucketEntryObject;
        bucket = (LocalRegion) bucketEntry.getValue();
        if (bucket != null) {
          bucket.waitForData();
          IndexManager indexMang = IndexUtils.getIndexManager(cache, bucket, false);
          if (indexMang != null) {
            indexMang.removeIndexes();
            numBuckets++;
            if (logger.isDebugEnabled()) {
              logger.debug("Removed all the indexes on bucket {}", bucket);
            }
          }
        }
      } // ends while
      if (logger.isDebugEnabled()) {
        logger.debug("Removed this many indexes on the buckets : {}", numBuckets);
      }
      RemoveIndexesMessage.RemoveIndexesResponse response;

      if (!remotelyOriginated) {
        logger.info("Sending removeIndex message to all the participating prs.");

        response = (RemoveIndexesMessage.RemoveIndexesResponse) RemoveIndexesMessage.send(this,
            null, true);

        if (null != response) {
          response.waitForResults();
          logger.info("Done waiting for index removal");
          if (logger.isDebugEnabled()) {
            logger.debug(
                "Total number of buckets which removed indexes , locally : {} and remotely removed : {} and the total number of remote buckets : {}",
                numBuckets, response.getRemoteRemovedIndexes(), response.getTotalRemoteBuckets());
          }
        }
      }
      indexManager.removeIndexes();
      return numBuckets;

    } // outer try block
    finally {
      indexes.clear();
    }
  }

  /**
   * Removes a particular index on this partitioned regions instance.
   *
   * @param ind Index to be removed.
   *
   */
  public int removeIndex(Index ind, boolean remotelyOriginated)
      throws CacheException, ForceReattemptException {

    int numBuckets = 0;
    IndexTask indexTask = null;
    Object prIndex = null;

    if (ind != null) {
      indexTask = new IndexTask(ind.getName());
      prIndex = indexes.get(indexTask);
    }

    // Check if the returned value is instance of Index (this means the index is
    // not in create phase, its created successfully).
    if (!(prIndex instanceof Index)) {
      logger.info("This index {} is not on this partitoned region :  {}",
          ind, this);
      return numBuckets;
    }

    if (logger.isDebugEnabled()) {
      logger.debug(
          "Remove index called, IndexName: {} Index: {}  Will be removing all the bucket indexes.",
          ind.getName(), ind);
    }

    Index index1 = indexManager.getIndex(ind.getName());
    if (index1 != null) {
      indexManager.removeIndex(index1);
    }

    // After removing from region wait for removing from index manager and
    // marking the index invalid.
    PartitionedIndex index = (PartitionedIndex) prIndex;
    index.acquireIndexWriteLockForRemove();

    indexes.remove(indexTask);

    // For releasing the write lock after removal.
    try {
      synchronized (prIndex) {
        List allBucketIndex = ((PartitionedIndex) prIndex).getBucketIndexes();
        Iterator it = allBucketIndex.iterator();

        if (logger.isDebugEnabled()) {
          logger.debug("Will be removing indexes on : {} buckets", allBucketIndex.size());
        }

        while (it.hasNext()) {
          Index in = (Index) it.next();
          LocalRegion region = ((LocalRegion) in.getRegion());
          region.waitForData();
          IndexManager indMng = region.getIndexManager();
          indMng.removeIndex(in);

          if (logger.isDebugEnabled()) {
            logger.debug("Removed index : {} on bucket {}", in, region);
          }
          numBuckets++;
          ((PartitionedIndex) prIndex).removeFromBucketIndexes(region, in);
        } // while
      }
    } finally {
      ((PartitionedIndex) prIndex).releaseIndexWriteLockForRemove();
    }

    if (!remotelyOriginated) {
      // send remove index message.
      RemoveIndexesMessage.RemoveIndexesResponse response;
      logger.info("Sending removeIndex message to all the participating prs.");
      response =
          (RemoveIndexesMessage.RemoveIndexesResponse) RemoveIndexesMessage.send(this, ind, false);

      if (response != null) {
        response.waitForResults();
        logger.info("Done waiting for index removal");
        if (logger.isDebugEnabled()) {
          logger.debug(
              "Total number of buckets which removed indexs , locally : {} and remotely removed : {} and the total number of remote buckets : {}",
              numBuckets, response.getRemoteRemovedIndexes(), response.getTotalRemoteBuckets());
        }
      }
    }
    return numBuckets;
  }

  /**
   * Gets and removes index by name.
   *
   * @param indexName name of the index to be removed.
   */
  public int removeIndex(String indexName) throws CacheException, ForceReattemptException {
    int numBuckets = 0;
    // remotely originated removeindex
    Object ind = indexes.get(indexName);

    // Check if the returned value is instance of Index (this means the index is
    // not in create phase, its created successfully).
    if (ind instanceof Index) {
      numBuckets = removeIndex((Index) indexes.get(indexName), true);
    }
    return numBuckets;
  }

  @Override
  public Object getValueInVM(Object key) throws EntryNotFoundException {
    if (dataStore == null) {
      throw new EntryNotFoundException(key.toString());
    }
    final int bucketId = PartitionedRegionHelper.getHashKey(this, null, key, null, null);
    return dataStore.getLocalValueInVM(key, bucketId);
  }

  /**
   * This method is intended for testing purposes only.
   */
  @Override
  public Object getValueOnDisk(Object key) throws EntryNotFoundException {
    final int bucketId = PartitionedRegionHelper.getHashKey(this, null, key, null, null);
    if (dataStore == null) {
      throw new EntryNotFoundException(key.toString());
    }
    return dataStore.getLocalValueOnDisk(key, bucketId);
  }

  /**
   * This method is intended for testing purposes only.
   */
  @Override
  public Object getValueOnDiskOrBuffer(Object key) throws EntryNotFoundException {
    final int bucketId = PartitionedRegionHelper.getHashKey(this, null, key, null, null);
    if (dataStore == null) {
      throw new EntryNotFoundException(key.toString());
    }
    return dataStore.getLocalValueOnDiskOrBuffer(key, bucketId);
  }

  /**
   * Test Method: Fetch the given bucket's meta-data from each member hosting buckets
   *
   * @param bucketId the identity of the bucket
   * @return list of arrays, each array element containing a {@link DistributedMember} and a
   *         {@link Boolean} the boolean denotes if the member is hosting the bucket and believes it
   *         is the primary
   * @throws ForceReattemptException if the caller should reattempt this request
   */
  public List<Object[]> getBucketOwnersForValidation(int bucketId) throws ForceReattemptException {
    // bucketid 1 => "vm A", false | "vm B", false | "vm C", true | "vm D", false
    // bucketid 2 => List< Tuple(MemberId mem, Boolean isPrimary) >

    // remotely fetch each VM's bucket meta-data (versus looking at the bucket
    // advisor's data
    RuntimeException rte = null;
    List<Object[]> remoteInfos = new LinkedList<>();
    for (int i = 0; i < 3; i++) {
      rte = null;
      DumpB2NResponse response =
          DumpB2NRegion.send(getRegionAdvisor().adviseDataStore(), this, bucketId, true);
      try {
        remoteInfos.addAll(response.waitForPrimaryInfos());
        break;
      } catch (TimeoutException e) {
        rte = e;
        logger.info("DumpB2NRegion failed to get PR {}, bucket id {}'s info due to {}, retrying...",
            getFullPath(), bucketId, e.getMessage());
      }
    }
    if (rte != null) {
      logger.info("DumpB2NRegion retried 3 times", rte);
      throw rte;
    }

    // Include current VM in the status...
    if (getRegionAdvisor().getBucket(bucketId).isHosting()) {
      if (getRegionAdvisor().isPrimaryForBucket(bucketId)) {
        remoteInfos.add(new Object[] {getSystem().getDM().getId(), Boolean.TRUE, ""});
      } else {
        remoteInfos.add(new Object[] {getSystem().getDM().getId(), Boolean.FALSE, ""});
      }
    }
    return remoteInfos;
  }

  /**
   * Return the primary for the local bucket. Returns null if no primary can be found within
   * {@link DistributionConfig#getMemberTimeout}.
   *
   * @return the primary bucket member
   */
  public InternalDistributedMember getBucketPrimary(int bucketId) {
    return getRegionAdvisor().getPrimaryMemberForBucket(bucketId);
  }

  /**
   * Wait until the bucket meta-data has been built and is ready to receive messages and/or updates
   */
  public void waitOnBucketMetadataInitialization() {
    waitOnInitialization(initializationLatchAfterBucketIntialization);
  }

  private void releaseAfterBucketMetadataSetupLatch() {
    initializationLatchAfterBucketIntialization.countDown();
  }

  @Override
  void releaseLatches() {
    super.releaseLatches();
    releaseAfterBucketMetadataSetupLatch();
  }

  /**
   * get the total retry interval, in milliseconds, for operations concerning this partitioned
   * region
   *
   * @return millisecond retry timeout interval
   */
  public int getRetryTimeout() {
    return retryTimeout;
  }

  public long getBirthTime() {
    return birthTime;
  }

  public PartitionResolver getPartitionResolver() {
    return partitionAttributes.getPartitionResolver();
  }

  public String getColocatedWith() {
    return partitionAttributes.getColocatedWith();
  }

  /**
   * Used to get membership events from our advisor to implement RegionMembershipListener
   * invocations. This is copied almost in whole from DistributedRegion
   *
   * @since GemFire 5.7
   */
  protected class AdvisorListener implements MembershipListener {
    protected synchronized void initRMLWrappers() {
      if (isInitialized() && hasListener()) {
        initPostCreateRegionMembershipListeners(getRegionAdvisor().adviseAllPRNodes());
      }
    }

    @Override
    public synchronized void memberJoined(DistributionManager distributionManager,
        InternalDistributedMember id) {
      // bug #44684 - this notification has been moved to a point AFTER the
      // other member has finished initializing its region

      // required-roles functionality is not implemented for partitioned regions,
      // or it would be done here
    }

    @Override
    public void quorumLost(DistributionManager distributionManager,
        Set<InternalDistributedMember> failures, List<InternalDistributedMember> remaining) {}

    @Override
    public void memberSuspect(DistributionManager distributionManager, InternalDistributedMember id,
        InternalDistributedMember whoSuspected, String reason) {}

    @Override
    public synchronized void memberDeparted(DistributionManager distributionManager,
        InternalDistributedMember id, boolean crashed) {
      if (isInitialized() && hasListener()) {
        RegionEventImpl event =
            new RegionEventImpl(PartitionedRegion.this, Operation.REGION_CLOSE, null, true, id);
        if (crashed) {
          dispatchListenerEvent(EnumListenerEvent.AFTER_REMOTE_REGION_CRASH, event);
        } else {
          // TODO: it would be nice to know if what actual op was done
          // could be close, local destroy, or destroy (or load snap?)
          if (DestroyRegionOperation.isRegionDepartureNotificationOk()) {
            dispatchListenerEvent(EnumListenerEvent.AFTER_REMOTE_REGION_DEPARTURE, event);
          }
        }
      }
      // required-roles functionality is not implemented for partitioned regions,
      // or it would be done here
    }
  }

  @Override
  RegionEntry basicGetTXEntry(KeyInfo keyInfo) {
    int bucketId = keyInfo.getBucketId();
    if (bucketId == KeyInfo.UNKNOWN_BUCKET) {
      bucketId = PartitionedRegionHelper.getHashKey(this, null, keyInfo.getKey(),
          keyInfo.getValue(), keyInfo.getCallbackArg());
      keyInfo.setBucketId(bucketId);
    }
    if (keyInfo.isCheckPrimary()) {
      DistributedMember primary = getRegionAdvisor().getPrimaryMemberForBucket(bucketId);
      if (!primary.equals(getMyId())) {
        throw new PrimaryBucketException(
            "Bucket " + bucketId + " is not primary. Current primary holder is " + primary);
      }
    }
    BucketRegion br = dataStore.getLocalBucketById(bucketId);
    RegionEntry re = br.basicGetEntry(keyInfo.getKey());
    if (re != null && re.isRemoved()) {
      re = null;
    }
    return re;
  }

  @Override
  boolean usesDiskStore(RegionAttributes regionAttributes) {
    if (regionAttributes.getPartitionAttributes().getLocalMaxMemory() <= 0) {
      return false; // see bug 42055
    }
    return super.usesDiskStore(regionAttributes);
  }

  @Override
  DiskStoreImpl findDiskStore(RegionAttributes regionAttributes,
      InternalRegionArguments internalRegionArgs) {
    DiskStoreImpl store = super.findDiskStore(regionAttributes, internalRegionArgs);
    if (store != null && store.getOwnedByRegion()) {
      store.initializeIfNeeded();
    }
    return store;
  }

  @Override
  DiskRegion createDiskRegion(InternalRegionArguments internalRegionArgs)
      throws DiskAccessException {
    if (internalRegionArgs.getDiskRegion() != null) {
      return internalRegionArgs.getDiskRegion();
    } else {
      return null;
    }
  }

  @Override
  public void handleInterestEvent(InterestRegistrationEvent event) {
    if (logger.isDebugEnabled()) {
      logger.debug("PartitionedRegion {} handling {}", getFullPath(), event);
    }
    // Process event in remote data stores by sending message
    Set<InternalDistributedMember> allRemoteStores = getRegionAdvisor().adviseDataStore(true);
    if (logger.isDebugEnabled()) {
      logger.debug("PartitionedRegion {} sending InterestEvent message to:{}", getFullPath(),
          allRemoteStores);
    }
    InterestEventResponse response = null;
    if (!allRemoteStores.isEmpty()) {
      try {
        response = InterestEventMessage.send(allRemoteStores, this, event);
      } catch (ForceReattemptException e) {
        if (logger.isDebugEnabled()) {
          logger.debug("PartitionedRegion {} caught exception", getFullPath(), e);
        }
      }
    }

    // Process event in the local data store if necessary
    if (dataStore != null) {
      // Handle the interest event in the local data store
      dataStore.handleInterestEvent(event);
    }

    // Wait for replies
    if (response != null) {
      try {
        if (logger.isDebugEnabled()) {
          logger.debug("PartitionedRegion {} waiting for response from {}", getFullPath(),
              allRemoteStores);
        }
        response.waitForResponse();
      } catch (ForceReattemptException e) {
        if (logger.isDebugEnabled()) {
          logger.debug("PartitionedRegion {} caught exception", getFullPath(), e);
        }
      }
    }
  }

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

  /**
   * Changes the timeToLive expiration attributes for the partitioned region as a whole
   *
   * @param timeToLive the expiration attributes for the region timeToLive
   * @return the previous value of region timeToLive
   * @throws IllegalArgumentException if timeToLive is null or if the ExpirationAction is
   *         LOCAL_INVALIDATE and the region is {@link DataPolicy#withReplication replicated}
   * @throws IllegalStateException if statistics are disabled for this region.
   */
  @Override
  public ExpirationAttributes setRegionTimeToLive(ExpirationAttributes timeToLive) {
    ExpirationAttributes attr = super.setRegionTimeToLive(timeToLive);
    // Set to Bucket regions as well
    if (getDataStore() != null) { // not for accessors
      for (Object o : getDataStore().getAllLocalBuckets()) {
        Map.Entry entry = (Map.Entry) o;
        Region bucketRegion = (Region) entry.getValue();
        bucketRegion.getAttributesMutator().setRegionTimeToLive(timeToLive);
      }
    }
    return attr;
  }

  /**
   * Changes the idleTimeout expiration attributes for the region as a whole. Resets the
   * {@link CacheStatistics#getLastAccessedTime} for the region.
   *
   * @param idleTimeout the ExpirationAttributes for this region idleTimeout
   * @return the previous value of region idleTimeout
   * @throws IllegalArgumentException if idleTimeout is null or if the ExpirationAction is
   *         LOCAL_INVALIDATE and the region is {@link DataPolicy#withReplication replicated}
   * @throws IllegalStateException if statistics are disabled for this region.
   */
  @Override
  public ExpirationAttributes setRegionIdleTimeout(ExpirationAttributes idleTimeout) {
    ExpirationAttributes attr = super.setRegionIdleTimeout(idleTimeout);
    // Set to Bucket regions as well
    if (getDataStore() != null) { // not for accessors
      for (Object o : getDataStore().getAllLocalBuckets()) {
        Map.Entry entry = (Map.Entry) o;
        Region bucketRegion = (Region) entry.getValue();
        bucketRegion.getAttributesMutator().setRegionIdleTimeout(idleTimeout);
      }
    }
    return attr;
  }

  /**
   * Changes the timeToLive expiration attributes for values in this region.
   *
   * @param timeToLive the timeToLive expiration attributes for entries
   * @return the previous value of entry timeToLive
   * @throws IllegalArgumentException if timeToLive is null or if the ExpirationAction is
   *         LOCAL_DESTROY and the region is {@link DataPolicy#withReplication replicated} or if the
   *         ExpirationAction is LOCAL_INVALIDATE and the region is
   *         {@link DataPolicy#withReplication replicated}
   * @throws IllegalStateException if statistics are disabled for this region.
   */
  @Override
  public ExpirationAttributes setEntryTimeToLive(ExpirationAttributes timeToLive) {
    ExpirationAttributes attr = super.setEntryTimeToLive(timeToLive);

    /*
     * All buckets must be created to make this change, otherwise it is possible for
     * updatePRConfig(...) to make changes that cause bucket creation to live lock
     */
    PartitionRegionHelper.assignBucketsToPartitions(this);
    if (dataStore != null) {
      dataStore.lockBucketCreationAndVisit(
          (bucketId, r) -> r.getAttributesMutator().setEntryTimeToLive(timeToLive));
    }
    updatePartitionRegionConfig(config -> config.setEntryTimeToLive(timeToLive));
    return attr;
  }

  /**
   * Changes the custom timeToLive for values in this region
   *
   * @param custom the new CustomExpiry
   * @return the old CustomExpiry
   */
  @Override
  public CustomExpiry setCustomEntryTimeToLive(CustomExpiry custom) {
    CustomExpiry expiry = super.setCustomEntryTimeToLive(custom);
    // Set to Bucket regions as well
    if (dataStore != null) {
      dataStore.lockBucketCreationAndVisit(
          (bucketId, r) -> r.getAttributesMutator().setCustomEntryTimeToLive(custom));
    }
    return expiry;
  }

  /**
   * Changes the idleTimeout expiration attributes for values in the region.
   *
   * @param idleTimeout the idleTimeout expiration attributes for entries
   * @return the previous value of entry idleTimeout
   * @throws IllegalArgumentException if idleTimeout is null or if the ExpirationAction is
   *         LOCAL_DESTROY and the region is {@link DataPolicy#withReplication replicated} or if the
   *         the ExpirationAction is LOCAL_INVALIDATE and the region is
   *         {@link DataPolicy#withReplication replicated}
   * @see AttributesFactory#setStatisticsEnabled
   * @throws IllegalStateException if statistics are disabled for this region.
   */
  @Override
  public ExpirationAttributes setEntryIdleTimeout(ExpirationAttributes idleTimeout) {
    ExpirationAttributes attr = super.setEntryIdleTimeout(idleTimeout);
    /*
     * All buckets must be created to make this change, otherwise it is possible for
     * updatePRConfig(...) to make changes that cause bucket creation to live lock
     */
    PartitionRegionHelper.assignBucketsToPartitions(this);
    // Set to Bucket regions as well
    if (dataStore != null) {
      dataStore.lockBucketCreationAndVisit(
          (bucketId, r) -> r.getAttributesMutator().setEntryIdleTimeout(idleTimeout));
    }
    updatePartitionRegionConfig(config -> config.setEntryIdleTimeout(idleTimeout));
    return attr;
  }

  /**
   * Changes the CustomExpiry for idleTimeout for values in the region
   *
   * @param custom the new CustomExpiry
   * @return the old CustomExpiry
   */
  @Override
  public CustomExpiry setCustomEntryIdleTimeout(CustomExpiry custom) {
    CustomExpiry expiry = super.setCustomEntryIdleTimeout(custom);
    // Set to Bucket regions as well
    if (dataStore != null) {
      dataStore.lockBucketCreationAndVisit(
          (bucketId, r) -> r.getAttributesMutator().setCustomEntryIdleTimeout(custom));
    }
    return expiry;
  }

  @Override
  void setMemoryThresholdFlag(MemoryEvent event) {
    if (event.getState().isCritical() && !event.getPreviousState().isCritical()
        && (event.getType() == ResourceType.HEAP_MEMORY
            || (event.getType() == ResourceType.OFFHEAP_MEMORY && getOffHeap()))) {
      // update proxy bucket, so that we can reject operations on those buckets.
      getRegionAdvisor().markBucketsOnMember(event.getMember(), true/* sick */);
    } else if (!event.getState().isCritical() && event.getPreviousState().isCritical()
        && (event.getType() == ResourceType.HEAP_MEMORY
            || (event.getType() == ResourceType.OFFHEAP_MEMORY && getOffHeap()))) {
      getRegionAdvisor().markBucketsOnMember(event.getMember(), false/* not sick */);
    }
  }

  @Override
  void initialCriticalMembers(boolean localMemoryIsCritical,
      Set<InternalDistributedMember> criticalMembers) {
    for (InternalDistributedMember idm : criticalMembers) {
      getRegionAdvisor().markBucketsOnMember(idm, true/* sick */);
    }
  }

  public DiskRegionStats getDiskRegionStats() {
    return diskRegionStats;
  }

  @Override
  public void removeCriticalMember(DistributedMember member) {
    if (logger.isDebugEnabled()) {
      logger.debug("PR: removing member {} from critical member list", member);
    }
    getRegionAdvisor().markBucketsOnMember(member, false/* sick */);
  }

  public PartitionedRegion getColocatedWithRegion() {
    return colocatedWithRegion;
  }

  private final AtomicBoolean bucketSorterStarted = new AtomicBoolean(false);

  private final AtomicBoolean bucketSortedOnce = new AtomicBoolean(false);

  public List<BucketRegion> getSortedBuckets() {
    if (!bucketSorterStarted.get()) {
      bucketSorterStarted.set(true);
      bucketSorter.scheduleAtFixedRate(new BucketSorterRunnable(), 0,
          HeapEvictor.BUCKET_SORTING_INTERVAL, TimeUnit.MILLISECONDS);
      if (logger.isDebugEnabled()) {
        logger.debug(
            "Started BucketSorter to sort the buckets according to number of entries in each bucket for every {} milliseconds",
            HeapEvictor.BUCKET_SORTING_INTERVAL);
      }
    }
    if (!bucketSortedOnce.get()) {
      while (bucketSortedOnce.get() == false) {
      }
    }
    return new ArrayList<>(sortedBuckets);
  }

  class BucketSorterRunnable implements Runnable {
    @Override
    public void run() {
      try {
        List<BucketRegion> bucketList = new ArrayList<>();
        Set<BucketRegion> buckets = dataStore.getAllLocalBucketRegions();
        for (BucketRegion br : buckets) {
          if (HeapEvictor.MINIMUM_ENTRIES_PER_BUCKET < br.getSizeForEviction()) {
            bucketList.add(br);
          }
        }
        if (!bucketList.isEmpty()) {
          Collections.sort(bucketList, (buk1, buk2) -> {
            long buk1NumEntries = buk1.getSizeForEviction();
            long buk2NumEntries = buk2.getSizeForEviction();
            if (buk1NumEntries > buk2NumEntries) {
              return -1;
            } else if (buk1NumEntries < buk2NumEntries) {
              return 1;
            }
            return 0;
          });
        }
        sortedBuckets = bucketList;
        if (!bucketSortedOnce.get()) {
          bucketSortedOnce.set(true);
        }
      } catch (Exception e) {
        if (logger.isDebugEnabled()) {
          logger.debug("BucketSorterRunnable : encountered Exception ", e);
        }
      }
    }
  }

  @Override
  public LocalRegion getDataRegionForRead(final KeyInfo keyInfo) {
    final Object entryKey = keyInfo.getKey();
    BucketRegion br;
    try {
      PartitionedRegionDataStore ds = getDataStore();
      if (ds == null) {
        throw new TransactionException(
            "PartitionedRegion Transactions cannot execute on nodes with local max memory zero");
      }
      // TODO provide appropriate Operation and arg
      int bucketId = keyInfo.getBucketId();
      if (bucketId == KeyInfo.UNKNOWN_BUCKET) {
        bucketId = PartitionedRegionHelper.getHashKey(this, null, entryKey, keyInfo.getValue(),
            keyInfo.getCallbackArg());
        keyInfo.setBucketId(bucketId);
      }
      br = ds.getInitializedBucketWithKnownPrimaryForId(null, bucketId);
      if (keyInfo.isCheckPrimary()) {
        try {
          br.checkForPrimary();
        } catch (PrimaryBucketException pbe) {
          throw new TransactionDataRebalancedException(DATA_MOVED_BY_REBALANCE, pbe);
        }
      }
    } catch (RegionDestroyedException ignore) {
      // TODO: why is this purposely not wrapping the original cause?
      throw new TransactionDataNotColocatedException(
          String.format("Key %s is not colocated with transaction",
              entryKey));
    } catch (ForceReattemptException ignore) {
      br = null;
    }
    return br;
  }

  @Override
  public LocalRegion getDataRegionForWrite(KeyInfo keyInfo) {
    BucketRegion br = null;
    final Object entryKey = keyInfo.getKey();
    try {
      final int retryAttempts = calcRetry();
      // TODO provide appropriate Operation and arg
      int bucketId = keyInfo.getBucketId();
      if (bucketId == KeyInfo.UNKNOWN_BUCKET) {
        bucketId = PartitionedRegionHelper.getHashKey(this, null, entryKey, keyInfo.getValue(),
            keyInfo.getCallbackArg());
        keyInfo.setBucketId(bucketId);
      }
      int count = 0;
      while (count <= retryAttempts) {
        try {
          PartitionedRegionDataStore ds = getDataStore();
          if (ds == null) {
            throw new TransactionException(
                "PartitionedRegion Transactions cannot execute on nodes with local max memory zero");
          }
          br = ds.getInitializedBucketWithKnownPrimaryForId(entryKey, bucketId);
          break;
        } catch (ForceReattemptException ignore) {
          // create a new bucket
          InternalDistributedMember member = createBucket(bucketId, 0, null);
          if (!getMyId().equals(member) && keyInfo.isCheckPrimary()) {
            throw new PrimaryBucketException(
                "Bucket " + bucketId + " is not primary. Current primary holder is " + member);
          }
          count++;
        }
      }
      Assert.assertNotNull(br, "Could not create storage for Entry");
      if (keyInfo.isCheckPrimary()) {
        br.checkForPrimary();
      }
    } catch (PrimaryBucketException | RegionDestroyedException exception) {
      throw new TransactionDataRebalancedException(DATA_MOVED_BY_REBALANCE, exception);
    }
    return br;
  }

  @Override
  public DistributedMember getOwnerForKey(KeyInfo key) {
    if (key == null) {
      return super.getOwnerForKey(null);
    }
    // TODO provide appropriate Operation and arg
    int bucketId = key.getBucketId();
    if (bucketId == KeyInfo.UNKNOWN_BUCKET) {
      bucketId = PartitionedRegionHelper.getHashKey(this, null, key.getKey(), key.getValue(),
          key.getCallbackArg());
      key.setBucketId(bucketId);
    }
    return createBucket(bucketId, 0, null);
  }

  @Override
  public KeyInfo getKeyInfo(Object key) {
    return getKeyInfo(key, null);
  }

  @Override
  public KeyInfo getKeyInfo(Object key, Object callbackArg) {
    return getKeyInfo(key, null, callbackArg);
  }

  @Override
  public KeyInfo getKeyInfo(Object key, Object value, Object callbackArg) {
    final int bucketId;
    if (key == null) {
      // key is null for putAll
      bucketId = KeyInfo.UNKNOWN_BUCKET;
    } else {
      bucketId = PartitionedRegionHelper.getHashKey(this, null, key, value, callbackArg);
    }
    return new KeyInfo(key, callbackArg, bucketId);
  }

  public static class SizeEntry implements Serializable {
    private final int size;
    private final boolean isPrimary;

    public SizeEntry(int size, boolean isPrimary) {
      this.size = size;
      this.isPrimary = isPrimary;
    }

    public int getSize() {
      return size;
    }

    public boolean isPrimary() {
      return isPrimary;
    }

    @Override
    public String toString() {
      return "SizeEntry(" + size + ", primary=" + isPrimary + ")";
    }
  }

  /**
   * Index Task used to create the index. This is used along with the FutureTask to take care of,
   * same index creation request from multiple threads. At any time only one thread succeeds and
   * other threads waits for the completion of the index creation. This avoids usage of
   * synchronization which could block any index creation.
   */
  public class IndexTask implements Callable<Index> {

    public String indexName;

    public boolean remotelyOriginated;

    private IndexType indexType;

    private String indexedExpression;

    private String fromClause;

    public String imports;

    public boolean loadEntries;

    IndexTask(boolean remotelyOriginated, IndexType indexType, String indexName,
        String indexedExpression, String fromClaus, String imports, boolean loadEntries) {
      this.indexName = indexName;
      this.remotelyOriginated = remotelyOriginated;
      this.indexType = indexType;
      this.indexName = indexName;
      this.indexedExpression = indexedExpression;
      fromClause = fromClaus;
      // this.p_list = p_list;
      this.imports = imports;
      this.loadEntries = loadEntries;

    }

    IndexTask(String indexName) {
      this.indexName = indexName;
    }

    @Override
    public boolean equals(Object other) {
      if (!(other instanceof IndexTask)) {
        return false;
      }
      IndexTask otherIndexTask = (IndexTask) other;
      return indexName.equals(otherIndexTask.indexName);
    }

    @Override
    public int hashCode() {
      return indexName.hashCode();
    }

    /**
     * This starts creating the index.
     */
    @Override
    public PartitionedIndex call() throws IndexCreationException, IndexNameConflictException,
        IndexExistsException, ForceReattemptException {
      PartitionedIndex prIndex;

      if (dataStore != null) {
        prIndex = createIndexOnPRBuckets();
      } else {
        if (getLocalMaxMemory() != 0) {
          throw new IndexCreationException(
              String.format("Data Store on this vm is null and the local max Memory is not zero %s",
                  (long) getLocalMaxMemory()));
        }
        logger.info("This is an accessor vm and doesnt contain data");

        prIndex = new PartitionedIndex(cache, indexType, indexName, PartitionedRegion.this,
            indexedExpression, fromClause, imports);
      }

      hasPartitionedIndex = true;
      return prIndex;
    }

    /**
     * This creates indexes on PR buckets.
     */
    private PartitionedIndex createIndexOnPRBuckets()
        throws IndexNameConflictException, IndexExistsException, IndexCreationException {

      Set localBuckets = getDataStore().getAllLocalBuckets();
      Iterator it = localBuckets.iterator();
      QCompiler compiler = new QCompiler();
      if (imports != null) {
        compiler.compileImports(imports);
      }

      // imports can be null
      PartitionedIndex parIndex = new PartitionedIndex(cache, indexType, indexName,
          PartitionedRegion.this, indexedExpression, fromClause, imports);

      // In cases where we have no data yet (creation from cache xml), it would leave the populated
      // flag to false Not really an issue as a put will trigger bucket index creation which should
      // set this the flag to true However if the region is empty, we should set this flag to true
      // so it will be reported as used even though there is no data in the region

      if (!it.hasNext()) {
        parIndex.setPopulated(true);
      }
      while (it.hasNext()) {
        Map.Entry entry = (Map.Entry) it.next();
        Region bucket = (Region) entry.getValue();

        if (bucket == null) {
          continue;
        }

        ExecutionContext externalContext = new ExecutionContext(null, cache);
        externalContext.setBucketRegion(PartitionedRegion.this, (BucketRegion) bucket);
        IndexManager indMng = IndexUtils.getIndexManager(cache, bucket, true);
        try {
          Index bucketIndex = indMng.createIndex(indexName, indexType, indexedExpression,
              fromClause, imports, externalContext, parIndex, loadEntries);
          // parIndex.addToBucketIndexes(bucketIndex);
        } catch (IndexNameConflictException ince) {
          if (!remotelyOriginated) {
            throw ince;
          }
        } catch (IndexExistsException iee) {
          if (!remotelyOriginated) {
            throw iee;
          }
        }
      } // End of bucket list
      parIndex.markValid(true);
      return parIndex;
    }
  }

  public List<FixedPartitionAttributesImpl> getFixedPartitionAttributesImpl() {
    return fixedPAttrs;
  }

  public List<FixedPartitionAttributesImpl> getPrimaryFixedPartitionAttributes_TestsOnly() {
    List<FixedPartitionAttributesImpl> primaryFixedPAttrs =
        new LinkedList<>();
    if (fixedPAttrs != null) {
      for (FixedPartitionAttributesImpl fpa : fixedPAttrs) {
        if (fpa.isPrimary()) {
          primaryFixedPAttrs.add(fpa);
        }
      }
    }
    return primaryFixedPAttrs;
  }

  public List<FixedPartitionAttributesImpl> getSecondaryFixedPartitionAttributes_TestsOnly() {
    List<FixedPartitionAttributesImpl> secondaryFixedPAttrs =
        new LinkedList<>();
    if (fixedPAttrs != null) {
      for (FixedPartitionAttributesImpl fpa : fixedPAttrs) {
        if (!fpa.isPrimary()) {
          secondaryFixedPAttrs.add(fpa);
        }
      }
    }
    return secondaryFixedPAttrs;
  }

  /**
   * For the very first member, FPR's first partition has starting bucket id as 0 and other
   * partitions have starting bucket id as the sum of previous partition's starting bucket id and
   * previous partition's num-buckets.
   *
   * For other members, all partitions defined previously with assigned starting bucket ids are
   * fetched from the metadata PartitionRegionConfig. Now for each partition defined for this
   * member, if this partition is already available in the list of the previously defined partitions
   * then starting bucket id is directly assigned from the same previously defined partition.
   *
   * And if the partition on this member is not available in the previously defined partitions then
   * new starting bucket id is calculated as the sum of the largest starting bucket id from
   * previously defined partitions and corresponding num-buckets of the partition.
   *
   * This data of the partitions (FixedPartitionAttributes with starting bucket id for the Fixed
   * Partitioned Region) is stored in metadata for each member.
   */
  private void calculateStartingBucketIDs(PartitionRegionConfig prConfig) {
    if (BEFORE_CALCULATE_STARTING_BUCKET_FLAG) {
      PartitionedRegionObserver pro = PartitionedRegionObserverHolder.getInstance();
      pro.beforeCalculatingStartingBucketId();
    }
    List<FixedPartitionAttributesImpl> fpaList = getFixedPartitionAttributesImpl();

    if (getColocatedWith() == null) {
      Set<FixedPartitionAttributesImpl> elderFPAs = prConfig.getElderFPAs();
      int startingBucketID = 0;
      if (elderFPAs != null && !elderFPAs.isEmpty()) {
        int largestStartBucId = -1;
        for (FixedPartitionAttributesImpl fpa : elderFPAs) {
          if (fpa.getStartingBucketID() > largestStartBucId) {
            largestStartBucId = fpa.getStartingBucketID();
            startingBucketID = largestStartBucId + fpa.getNumBuckets();
          }
        }
      }
      for (FixedPartitionAttributesImpl fpaImpl : fpaList) {
        if (elderFPAs != null && elderFPAs.contains(fpaImpl)) {
          for (FixedPartitionAttributesImpl remotefpa : elderFPAs) {
            if (remotefpa.equals(fpaImpl)) {
              fpaImpl.setStartingBucketID(remotefpa.getStartingBucketID());
            }
          }
        } else {
          fpaImpl.setStartingBucketID(startingBucketID);
          startingBucketID += fpaImpl.getNumBuckets();
        }
      }
    }
    prConfig.addFPAs(fpaList);
    for (FixedPartitionAttributesImpl fxPrAttr : fpaList) {
      partitionsMap.put(fxPrAttr.getPartitionName(),
          new Integer[] {fxPrAttr.getStartingBucketID(), fxPrAttr.getNumBuckets()});
    }
  }

  /**
   * Returns the local BucketRegion given the key. Returns null if no BucketRegion exists.
   *
   * @since GemFire 6.1.2.9
   */
  public BucketRegion getBucketRegion(Object key) {
    if (dataStore == null) {
      return null;
    }
    Integer bucketId = PartitionedRegionHelper.getHashKey(this, null, key, null, null);
    return dataStore.getLocalBucketById(bucketId);
  }

  /**
   * Returns the local BucketRegion given the key and value. Returns null if no BucketRegion exists.
   */
  public BucketRegion getBucketRegion(Object key, Object value) {
    if (dataStore == null) {
      return null;
    }
    final Integer bucketId = PartitionedRegionHelper.getHashKey(this, null, key, value, null);
    return dataStore.getLocalBucketById(bucketId);
  }

  /**
   * Test hook to return the per entry overhead for a bucket region. Returns -1 if no buckets exist
   * in this vm.
   *
   * @since GemFire 6.1.2.9
   */
  public int getPerEntryLRUOverhead() {
    if (dataStore == null) { // this is an accessor
      return -1;
    }
    try {
      return dataStore.getPerEntryLRUOverhead();
    } catch (NoSuchElementException ignore) { // no buckets available
      return -1;
    }
  }

  @Override
  boolean isEntryIdleExpiryPossible() {
    // false always as this is a partitionedRegion,
    // its the BucketRegion that does the expiry
    return false;
  }

  @Override
  public boolean hasSeenEvent(EntryEventImpl ev) {
    // [bruce] PRs don't track events - their buckets do that
    if (dataStore == null) {
      return false;
    }
    return dataStore.hasSeenEvent(ev);
  }

  public void enableConflation(boolean conflation) {
    enableConflation = conflation;
  }

  public boolean isConflationEnabled() {
    return enableConflation;
  }

  @Override
  public CachePerfStats getRegionPerfStats() {
    PartitionedRegionDataStore ds = getDataStore();
    CachePerfStats result = null;
    if (ds != null) {
      // If we don't have a data store (we are an accessor)
      // then we do not have per region stats.
      // This is not good. We should still have stats even for accessors.
      result = ds.getCachePerfStats(); // fixes 46692
    }
    return result;
  }

  public void updateEntryVersionInBucket(EntryEventImpl event) {
    final boolean isDebugEnabled = logger.isDebugEnabled();

    final int bucketId = event.getKeyInfo().getBucketId();
    assert bucketId != KeyInfo.UNKNOWN_BUCKET;
    final InternalDistributedMember targetNode = getOrCreateNodeForBucketWrite(bucketId, null);

    final int retryAttempts = calcRetry();
    int count = 0;
    RetryTimeKeeper retryTime = null;
    InternalDistributedMember retryNode = targetNode;
    while (count <= retryAttempts) {
      // It's possible this is a GemFire thread e.g. ServerConnection
      // which got to this point because of a distributed system shutdown or
      // region closure which uses interrupt to break any sleep() or wait()
      // calls
      // e.g. waitForPrimary or waitForBucketRecovery
      checkShutdown();

      if (retryNode == null) {
        checkReadiness();
        if (retryTime == null) {
          retryTime = new RetryTimeKeeper(retryTimeout);
        }
        try {
          retryNode = getOrCreateNodeForBucketWrite(bucketId, retryTime);
        } catch (TimeoutException ignore) {
          if (getRegionAdvisor().isStorageAssignedForBucket(bucketId)) {
            // bucket no longer exists
            throw new EntryNotFoundException(
                String.format("Entry not found for key %s",
                    event.getKey()));
          }
          break; // fall out to failed exception
        }

        if (retryNode == null) {
          checkEntryNotFound(event.getKey());
        }
        continue;
      }
      final boolean isLocal = (localMaxMemory > 0) && retryNode.equals(getMyId());
      try {
        if (isLocal) {
          dataStore.updateEntryVersionLocally(bucketId, event);
        } else {
          updateEntryVersionRemotely(retryNode, bucketId, event);
        }
        return;
      } catch (ConcurrentCacheModificationException e) {
        if (isDebugEnabled) {
          logger.debug("updateEntryVersionInBucket: caught concurrent cache modification exception",
              e);
        }
        event.isConcurrencyConflict(true);

        if (isDebugEnabled) {
          logger.debug(
              "ConcurrentCacheModificationException received for updateEntryVersionInBucket for bucketId: {}{}{} for event: {}  No reattampt is done, returning from here",
              getPRId(), BUCKET_ID_SEPARATOR, bucketId, event);
        }
        return;
      } catch (ForceReattemptException prce) {
        prce.checkKey(event.getKey());
        if (isDebugEnabled) {
          logger.debug("updateEntryVersionInBucket: retry attempt:{} of {}", count, retryAttempts,
              prce);
        }
        checkReadiness();

        InternalDistributedMember lastNode = retryNode;
        retryNode = getOrCreateNodeForBucketWrite(bucketId, retryTime);
        if (lastNode.equals(retryNode)) {
          if (retryTime == null) {
            retryTime = new RetryTimeKeeper(retryTimeout);
          }
          if (retryTime.overMaximum()) {
            break;
          }
          retryTime.waitToRetryNode();
        }
      } catch (PrimaryBucketException notPrimary) {
        if (isDebugEnabled) {
          logger.debug("updateEntryVersionInBucket {} on Node {} not primary",
              notPrimary.getLocalizedMessage(), retryNode);
        }
        getRegionAdvisor().notPrimary(bucketId, retryNode);
        retryNode = getOrCreateNodeForBucketWrite(bucketId, retryTime);
      }

      count++;

      if (isDebugEnabled) {
        logger.debug(
            "updateEntryVersionInBucket: Attempting to resend update version to node {} after {} failed attempts",
            retryNode, count);
      }
    } // while

    // No target was found
    PartitionedRegionDistributionException e = new PartitionedRegionDistributionException(
        String.format("No VM available for update-version in %s attempts.",
            count)); // Fix for bug 36014
    if (!isDebugEnabled) {
      logger.warn("No VM available for update-version in {} attempts.",
          count);
    } else {
      logger.warn(e.getMessage(), e);
    }
    throw e;
  }

  /**
   * Updates the entry version timestamp of the remote object with the given key.
   *
   * @param recipient the member id of the recipient of the operation
   * @param bucketId the id of the bucket the key hashed into
   * @throws EntryNotFoundException if the entry does not exist in this region
   * @throws PrimaryBucketException if the bucket on that node is not the primary copy
   * @throws ForceReattemptException if the peer is no longer available
   */
  private void updateEntryVersionRemotely(InternalDistributedMember recipient, Integer bucketId,
      EntryEventImpl event)
      throws EntryNotFoundException, PrimaryBucketException, ForceReattemptException {

    UpdateEntryVersionResponse response = PRUpdateEntryVersionMessage.send(recipient, this, event);
    if (response != null) {
      prStats.incPartitionMessagesSent();
      try {
        response.waitForResult();
        return;
      } catch (EntryNotFoundException ex) {
        throw ex;
      } catch (TransactionDataNotColocatedException ex) {
        throw ex;
      } catch (TransactionDataRebalancedException e) {
        throw e;
      } catch (CacheException ce) {
        throw new PartitionedRegionException(
            String.format("Update version of entry on %s failed.",
                recipient),
            ce);
      }
    }
  }

  public void shadowPRWaitForBucketRecovery() {
    assert isShadowPR();
    PartitionedRegion userPR = ColocationHelper.getLeaderRegion(this);
    boolean isAccessor = (userPR.getLocalMaxMemory() == 0);
    if (isAccessor) {
      return; // return from here if accessor node
    }

    // Before going ahead, make sure all the buckets of shadowPR are
    // loaded
    // and primary nodes have been decided.
    // This is required in case of persistent PR and sender.
    Set<Integer> allBuckets = userPR.getDataStore().getAllLocalBucketIds();
    Set<Integer> allBucketsClone = new HashSet<>(allBuckets);
    while (allBucketsClone.size() != 0) {
      logger.debug(
          "Need to wait until partitionedRegionQueue <<{}>> is loaded with all the buckets",
          getName());
      Iterator<Integer> itr = allBucketsClone.iterator();
      while (itr.hasNext()) {
        InternalDistributedMember node = getNodeForBucketWrite(itr.next(), null);
        if (node != null) {
          itr.remove();
        }
      }
      // after the iteration is over, sleep for sometime before trying
      // again
      try {
        Thread.sleep(ParallelGatewaySenderQueue.WAIT_CYCLE_SHADOW_BUCKET_LOAD);
      } catch (InterruptedException e) {
        logger.error(e.getMessage(), e);
      }
    }
  }

  @Override
  void preDestroyChecks() {
    try {
      // if there are colocated children throw an exception
      checkForColocatedChildren();
    } catch (CancelException ignore) {
      // If cache is being closed, ignore and go
      // ahead with the destroy
    }
  }

  @Override
  boolean hasStorage() {
    return getLocalMaxMemory() != 0;
  }

  @Override
  public EntryExpiryTask getEntryExpiryTask(Object key) {
    BucketRegion br = getDataStore().getLocalBucketByKey(key);
    if (br == null) {
      throw new EntryNotFoundException("Bucket for key " + key + " does not exist.");
    }
    return br.getEntryExpiryTask(key);
  }

  void updatePRNodeInformation() {
    updatePartitionRegionConfig(prConfig -> {
      CacheLoader cacheLoader = basicGetLoader();
      CacheWriter cacheWriter = basicGetWriter();
      if (prConfig != null) {

        for (Node node : prConfig.getNodes()) {

          if (node.getMemberId().equals(getMyId())) {
            node.setLoaderAndWriter(cacheLoader, cacheWriter);
          }
        }
      }
    });
  }

  public Logger getLogger() {
    return logger;
  }

  interface PartitionRegionConfigModifier {
    void modify(PartitionRegionConfig prConfig);
  }

  void updatePartitionRegionConfig(
      PartitionRegionConfigModifier partitionRegionConfigModifier) {
    RegionLock rl = getRegionLock();
    rl.lock();
    try {
      if (getPRRoot() == null) {
        if (logger.isDebugEnabled()) {
          logger.debug(PartitionedRegionHelper.PR_ROOT_REGION_NAME + " is null");
        }
        return;
      }
      PartitionRegionConfig prConfig = getPRRoot().get(getRegionIdentifier());
      partitionRegionConfigModifier.modify(prConfig);
      updatePRConfig(prConfig, false);
    } finally {
      rl.unlock();
    }
  }

  @VisibleForTesting
  public SenderIdMonitor getSenderIdMonitor() {
    return senderIdMonitor;
  }

  @Override
  public boolean isRegionCreateNotified() {
    return regionCreationNotified;
  }

  @Override
  public void setRegionCreateNotified(boolean notified) {
    regionCreationNotified = notified;
  }

  void notifyRegionCreated() {
    if (regionCreationNotified) {
      return;
    }
    getSystem().handleResourceEvent(ResourceEvent.REGION_CREATE, this);
    regionCreationNotified = true;
  }

  public boolean areRecoveriesInProgress() {
    return prStats.getRecoveriesInProgress() > 0;
  }
}
