/*
 * 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.util.stream.Collectors.toSet;
import static org.apache.geode.internal.lang.SystemUtils.getLineSeparator;

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.Comparator;
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.locks.Lock;

import org.apache.logging.log4j.Logger;

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.LockServiceDestroyedException;
import org.apache.geode.distributed.internal.ClusterDistributionManager;
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.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.gms.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.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.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.tier.sockets.command.Get70;
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.concurrent.ConcurrentHashSet;
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.serialization.Version;
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;

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

  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(DistributionConfig.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) {
    this.shutDownAllStatus = newStatus;
  }

  private final PartitionedRegion colocatedWithRegion;

  private ColocationLogger missingColocatedRegionLogger;

  private List<BucketRegion> sortedBuckets;

  private ScheduledExecutorService bucketSorter;

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

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

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

  private final Object indexLock = new Object();

  private final Set<ColocationListener> colocationListeners = new ConcurrentHashSet<>();

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

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

  ScheduledExecutorService getBucketSorter() {
    return bucketSorter;
  }

  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 {
      this.prStats.endDestroy(startTime);
    }
  }

  public PartitionListener[] getPartitionListeners() {
    return this.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 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() {
      this.cleared = true;
      super.clear();
    }

    public synchronized String dump() {
      StringBuilder sb = new StringBuilder("prIdToPR Map@");
      sb.append(System.identityHashCode(prIdToPR)).append(':').append(getLineSeparator());
      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(getLineSeparator());
        }
      }
      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 =
      DistributionConfig.GEMFIRE_PREFIX + "partitionedRegionRetryTimeout";

  private final PartitionRegionConfigValidator validator;

  final List<FixedPartitionAttributesImpl> fixedPAttrs;

  private byte fixedPASet;

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

  private final PartitionListener[] partitionListeners;

  private boolean isShadowPR = false;

  private AbstractGatewaySender parallelGatewaySender = null;

  private final PartitionedRegionRedundancyTracker redundancyTracker;

  /**
   * 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) {
    super(regionName, regionAttributes, parentRegion, cache, internalRegionArgs,
        new PartitionedRegionDataView(), statisticsClock);

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

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

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

    // Warning: potential early escape of instance
    this.distAdvisor = RegionAdvisor.createRegionAdvisor(this);
    senderIdMonitor = createSenderIdMonitor();
    // Warning: potential early escape of instance
    this.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;
    this.redundantCopies = regionAttributes.getPartitionAttributes().getRedundantCopies();
    this.redundancyTracker = new PartitionedRegionRedundancyTracker(this.totalNumberOfBuckets,
        this.redundantCopies, this.prStats, getFullPath());
    this.prStats.setConfiguredRedundantCopies(
        regionAttributes.getPartitionAttributes().getRedundantCopies());
    this.prStats.setLocalMaxMemory(
        regionAttributes.getPartitionAttributes().getLocalMaxMemory() * 1024L * 1024);

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

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

    this.haveCacheLoader = regionAttributes.getCacheLoader() != null;

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

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

    this.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.
      this.fixedPAttrs = colocatedWithRegion.getFixedPartitionAttributesImpl();
      this.fixedPASet = colocatedWithRegion.fixedPASet;
    } else {
      this.fixedPAttrs = this.partitionAttributes.getFixedPartitionAttributes();
      this.fixedPASet = 0;
    }

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


    /*
     * 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() {
    this.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 =
              ((profile instanceof CacheProfile) ? (CacheProfile) profile : null);
          Set<String> onlineMembers = new HashSet<String>();

          TransformUtils.transform(
              PartitionedRegion.this.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[] {PartitionedRegion.this.getName(),
                      TransformUtils.persistentMemberIdToLogEntryTransformer
                          .transform(cacheProfile.persistentID),
                      onlineMembers});
        }
      }
    });
  }

  public boolean isShadowPR() {
    return isShadowPR;
  }

  public AbstractGatewaySender getParallelGatewaySender() {
    return parallelGatewaySender;
  }

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

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

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

  private void createAndValidatePersistentConfig() {
    DiskStoreImpl diskStore = this.getDiskStore();
    if (this.getDataPolicy().withPersistence() && !this.getConcurrencyChecksEnabled()
        && supportsConcurrencyChecks()) {
      logger.info(
          "Turning on concurrency checks for region: {} since it has been configured to persist data to disk.",
          this.getFullPath());
      this.setConcurrencyChecksEnabled(true);
    }
    if (diskStore != null && this.getDataPolicy().withPersistence()) {
      String colocatedWith = colocatedWithRegion == null ? "" : colocatedWithRegion.getFullPath();
      PRPersistentConfig config = diskStore.getPersistentPRConfig(this.getFullPath());
      if (config != null) {
        if (config.getTotalNumBuckets() != this.getTotalNumberOfBuckets()) {
          Object[] prms = new Object[] {this.getFullPath(), this.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[] {this.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.",
                  this.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(this.getTotalNumberOfBuckets(), colocatedWith);
        diskStore.addPersistentPR(this.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(this.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 (this.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 = this.localMaxMemory > 0;
    if (storesData) {
      initializeDataStore(this.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(this.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 (!this.isDataStore() && supportsConcurrencyChecks()) {
        this.setConcurrencyChecksEnabled(!this.getConcurrencyChecksEnabled());
        new CreateRegionProcessor(this).initializeRegion();
      } else {
        throw e;
      }
    }

    if (!this.isDestroyed && !this.isLocallyDestroyed) {
      // Register at this point so that other members are known
      this.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 (this.isAllEvents()) {
      StateFlushOperation sfo = new StateFlushOperation(getDistributionManager());
      try {
        sfo.flush(this.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 (this.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) {
        this.redundancyProvider.scheduleCreateMissingBuckets();
        this.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 (int i = 0; i < listeners.length; i++) {
        if (listeners[i] instanceof RegionMembershipListener) {
          RegionMembershipListener rml = (RegionMembershipListener) listeners[i];
          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 = this.getPartitionListeners();
    if (partitionListeners != null && partitionListeners.length != 0) {
      for (int i = 0; i < partitionListeners.length; i++) {
        PartitionListener listener = partitionListeners[i];
        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());

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

    if (logger.isDebugEnabled()) {
      logger.debug("PartitionRegion#initialize: finished with {}", this);
    }
    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 (!this.requiresNotification && !(this.isClosed || this.isLocallyDestroyed)) {
      // tell others of the change in status
      this.requiresNotification = true;
      new UpdateAttributesProcessor(this).distribute(false);
    }
  }

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

  @Override
  public void addGatewaySenderId(String gatewaySenderId) {
    super.addGatewaySenderId(gatewaySenderId);
    new UpdateAttributesProcessor(this).distribute();
    ((PartitionedRegion) this).distributeUpdatedProfileOnSenderCreation();
    GatewaySender sender = getCache().getGatewaySender(gatewaySenderId);
    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);
    new UpdateAttributesProcessor(this).distribute();
    ((PartitionedRegion) this).distributeUpdatedProfileOnSenderCreation();
    GatewaySender sender = getCache()
        .getGatewaySender(AsyncEventQueueImpl.getSenderIdFromAsyncEventQueueId(asyncEventQueueId));
    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, this.distAdvisor);
  }

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

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

  /**
   * Initializes the PartitionedRegion - create the Global regions for storing the
   * PartitiotnedRegion configs.
   */
  private void initializePartitionedRegion() {
    this.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(PartitionedRegion.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) {

    this.dataStore =
        PartitionedRegionDataStore.createDataStore(cache, this, ra.getPartitionAttributes(),
            getStatisticsClock());
  }

  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 (this.fixedPAttrs != null) {
        this.node.setPRType(Node.FIXED_PR_DATASTORE);
      } else {
        this.node.setPRType(Node.ACCESSOR_DATASTORE);
      }
      this.node.setPersistence(getAttributes().getDataPolicy() == DataPolicy.PERSISTENT_PARTITION);
      this.node.setLoaderAndWriter(getAttributes().getCacheLoader(),
          getAttributes().getCacheWriter());
    } else {
      if (this.fixedPAttrs != null) {
        this.node.setPRType(Node.FIXED_PR_ACCESSOR);
      } else {
        this.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();
        this.partitionedRegionId = generatePRId(getSystem());
        prConfig = new PartitionRegionConfig(this.partitionedRegionId, this.getFullPath(),
            prAttribs, this.getScope(), getAttributes().getEvictionAttributes(),
            getAttributes().getRegionIdleTimeout(), getAttributes().getRegionTimeToLive(),
            getAttributes().getEntryIdleTimeout(), getAttributes().getEntryTimeToLive(),
            this.getAllGatewaySenderIds());
        logger.info("Partitioned Region {} is born with prId={} ident:{}",
            new Object[] {getFullPath(), this.partitionedRegionId, getRegionIdentifier()});

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

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

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

      prConfig.addNode(this.node);
      if (this.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; }
       */
      this.cleanPRRegistration = true;
    } catch (LockServiceDestroyedException lsde) {
      if (logger.isDebugEnabled()) {
        logger.debug("registerPartitionedRegion: unable to obtain lock for {}", this);
      }
      cleanupFailedInitialization();
      throw new PartitionedRegionException(
          "Can not create PartitionedRegion (failed to acquire RegionLock).",
          lsde);
    } catch (IllegalStateException ill) {
      cleanupFailedInitialization();
      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(this.partitionedRegionId)) {
            prIdToPR.put(this.partitionedRegionId, PRIdMap.FAILED_REGISTRATION, false);
            logger.info("FAILED_REGISTRATION prId={} named {}",
                new Object[] {this.partitionedRegionId, this.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(this.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 : this.prRoot.values()) {
        if (config.getGatewaySenderIds().contains(dispatcherId)) {
          if (this.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.",
                    this.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.",
                this.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 this.requiresNotification;
  }

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

  void setRecoveredFromDisk() {
    this.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",
              new Object[] {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 {
      this.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));
    }
    int bucketIdInt = 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(this.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 = (this.localMaxMemory > 0) && retryNode.equals(getMyId());
        if (loc) {
          ret = this.dataStore.getEntryLocally(bucketId, key, access, allowTombstones);
        } else {
          ret = getEntryRemotely(retryNode, bucketIdInt, 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(bucketIdInt, (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(bucketIdInt);
        if (lastNode.equals(retryNode)) {
          if (retryTime == null) {
            retryTime = new RetryTimeKeeper(this.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(bucketIdInt, retryNode);
        retryNode = getOrCreateNodeForBucketRead(bucketIdInt);
      }

      // 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) {
        this.prStats.incContainsKeyValueOpsRetried();
      }
      this.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();
    this.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);
    this.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 long getLastModifiedTime() {
    if (!this.canStoreDataLocally()) {
      return 0;
    }
    Set<BucketRegion> buckets = this.dataStore.getAllLocalBucketRegions();
    long lastModifiedTime =
        buckets.stream().map(x -> x.getLastModifiedTime()).reduce(0L, (a, b) -> a > b ? a : b);
    return lastModifiedTime;
  }

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

  @Override
  public long getMissCount() {
    if (!this.canStoreDataLocally()) {
      return 0;
    }
    Set<BucketRegion> buckets = this.dataStore.getAllLocalBucketRegions();
    return buckets.stream().map(x -> x.getMissCount()).reduce(0L, (a, b) -> a + b);
  }

  @Override
  public long getHitCount() {
    if (!this.canStoreDataLocally()) {
      return 0;
    }
    Set<BucketRegion> buckets = this.dataStore.getAllLocalBucketRegions();
    return buckets.stream().map(x -> x.getHitCount()).reduce(0L, (a, b) -> a + b);
  }

  @Override
  public void resetCounts() {
    if (!this.canStoreDataLocally()) {
      return;
    }
    Set<BucketRegion> buckets = this.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<Integer>();

    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 (this.dataStore != null) {
        localIter = buckets.iterator();
      } else {
        localIter = Collections.emptySet().iterator();
      }
      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(
          this.getValueConstraint() == null ? Object.class : this.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(this.getSystem(),
        this, query, executionContext, parameters, results, allBuckets);
    for (;;) {
      this.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) throws TimeoutException, CacheWriterException {
    final long startTime = prStats.getTime();
    boolean result = false;
    final DistributedPutAllOperation putAllOp_save = event.setPutAllOperation(null);

    if (event.getEventId() == null) {
      event.setNewEventId(this.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)
          this.checkReadiness();
          if (this.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) {
          this.prStats.endCreate(startTime);
        } else {
          this.prStats.endPut(startTime);
        }
      }
    }
    if (!result) {
      checkReadiness();
      if (!ifNew && !ifOld && !this.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 (this.fixedPAttrs != null || this.fixedPASet == 1) {
      // We are sure that its a FixedFPA
      return true;
    }
    // We know that it's a normal PR
    if (this.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.
    this.fixedPASet = hasRemoteFPAttrs();
    return this.fixedPASet == 1;
  }

  private byte hasRemoteFPAttrs() {
    List<FixedPartitionAttributesImpl> fpaList =
        this.getRegionAdvisor().adviseAllFixedPartitionAttributes();
    Set<InternalDistributedMember> remoteDataStores = this.getRegionAdvisor().adviseDataStore();
    if (!fpaList.isEmpty() || (this.fixedPAttrs != null && !this.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<Object, VersionTag>(successfulPuts.size());
    successfulPuts.clearVersions();
    Iterator itor = prMsgMap.entrySet().iterator();
    while (itor.hasNext()) {
      Map.Entry mapEntry = (Map.Entry) itor.next();
      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 (!this.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");
        }
      }
    }
    this.prStats.endPutAll(startTime);
    if (!keyToVersionMap.isEmpty()) {
      for (Iterator it = successfulPuts.getKeys().iterator(); it.hasNext();) {
        successfulPuts.addVersion(keyToVersionMap.get(it.next()));
      }
      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<Object, VersionTag>(successfulOps.size());
    successfulOps.clearVersions();
    Iterator<Map.Entry<Integer, RemoveAllPRMessage>> itor = prMsgMap.entrySet().iterator();
    while (itor.hasNext()) {
      Map.Entry<Integer, RemoveAllPRMessage> mapEntry = itor.next();
      Integer bucketId = (Integer) 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 (!this.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));
        }
      }
    }
    this.prStats.endRemoveAll(startTime);
    if (!keyToVersionMap.isEmpty()) {
      for (Iterator it = successfulOps.getKeys().iterator(); it.hasNext();) {
        successfulOps.addVersion(keyToVersionMap.get(it.next()));
      }
      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:
            this.cache.getCancelCriterion().checkCancelInProgress(null);
            // Second time (first failure). Calculate timeout and keep going.
            timeOut = System.currentTimeMillis() + this.retryTimeout;
            break;
          default:
            this.cache.getCancelCriterion().checkCancelInProgress(null);
            // test for timeout
            long timeLeft = timeOut - System.currentTimeMillis();
            if (timeLeft < 0) {
              PRHARedundancyProvider.timedOut(this, null, null, "update an entry",
                  this.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(this.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(this.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",
                  this.retryTimeout);
              // NOTREACHED
            }
            retryTime.waitToRetryNode();
          }
          event.setPossibleDuplicate(true);
          if (prMsg != null) {
            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(this.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) {
          this.prStats.incPutAllMsgsRetried();
        }
        this.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:
            this.cache.getCancelCriterion().checkCancelInProgress(null);
            // Second time (first failure). Calculate timeout and keep going.
            timeOut = System.currentTimeMillis() + this.retryTimeout;
            break;
          default:
            this.cache.getCancelCriterion().checkCancelInProgress(null);
            // test for timeout
            long timeLeft = timeOut - System.currentTimeMillis();
            if (timeLeft < 0) {
              PRHARedundancyProvider.timedOut(this, null, null, "update an entry",
                  this.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(this.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(this.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",
                  this.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(this.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) {
          this.prStats.incRemoveAllMsgsRetried();
        }
        this.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 = (this.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, this.getDistributionManager().getDistributionManagerId(), 0L);
      versions = prMsg.getVersions();
    } else {
      PutAllPRMessage.PutAllResponse response =
          (PutAllPRMessage.PutAllResponse) prMsg.send(currentTarget, this);
      PutAllPRMessage.PutAllResult pr = null;
      if (response != null) {
        this.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 = (this.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,
          this.getDistributionManager().getDistributionManagerId(), true);
      versions = prMsg.getVersions();
    } else {
      RemoveAllPRMessage.RemoveAllResponse response =
          (RemoveAllPRMessage.RemoveAllResponse) prMsg.send(currentTarget, this);
      RemoveAllPRMessage.RemoveAllResult pr = null;
      if (response != null) {
        this.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:
          this.cache.getCancelCriterion().checkCancelInProgress(null);
          // Second time (first failure). Calculate timeout and keep going.
          timeOut = System.currentTimeMillis() + this.retryTimeout;
          break;
        default:
          this.cache.getCancelCriterion().checkCancelInProgress(null);
          // test for timeout
          long timeLeft = timeOut - System.currentTimeMillis();
          if (timeLeft < 0) {
            PRHARedundancyProvider.timedOut(this, null, null, "update an entry", this.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(this.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 = (this.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 = this.prStats.startPutLocal();
          try {
            final BucketRegion br =
                this.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 = this.dataStore.createLocally(br, event, ifNew, ifOld, requireOldValue,
                  lastModified);
            } else {
              result = this.dataStore.putLocally(br, event, ifNew, ifOld, expectedOldValue,
                  requireOldValue, lastModified);
            }
          } finally {
            this.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 = this.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 {
            this.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, this.getMyId(), currentTarget, getPRId(), BUCKET_ID_SEPARATOR, bucketId, prce);
          logger.debug("putInBucket: count={}", count);
        }
        checkReadiness();
        InternalDistributedMember lastTarget = currentTarget;
        if (retryTime == null) {
          retryTime = new RetryTimeKeeper(this.retryTimeout);
        }
        currentTarget = getNodeForBucketWrite(bucketId, retryTime);
        if (lastTarget.equals(currentTarget)) {
          if (retryTime.overMaximum()) {
            PRHARedundancyProvider.timedOut(this, null, null, "update an entry", this.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(this.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) {
          this.prStats.incCreateOpsRetried();
        } else {
          this.prStats.incPutOpsRetried();
        }
      }
      if (event.getOperation().isCreate()) {
        this.prStats.incCreateRetries();
      } else {
        this.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)
      this.checkReadiness();
      if (this.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) < this.minimumWriteRedundancy) {
      this.cache.getCancelCriterion().checkCancelInProgress(null);

      // First check to see if there is any storage assigned TODO: redundant check to while
      // condition
      if (!getRegionAdvisor().isStorageAssignedForBucket(bucketId, this.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(this.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 ]",
                new Object[] {bucketStringForLogs(bucketId),
                    localSnoozer.getRetryTime(), red, this.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)
      this.checkReadiness();
      if (this.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 (!this.haveCacheLoader) {
      targetNode = getNodeForBucketRead(bucketId);
    } else {
      targetNode = getNodeForBucketWrite(bucketId, null /* retryTimeKeeper */);
    }
    if (targetNode == null) {
      this.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) {
      this.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 (this.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",
                new Object[] {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 = this.redundancyProvider.createBucketAtomically(bucketId, size, false,
          partitionName);
    } else {
      ret = this.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 {
      this.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();
    HashMap<Integer, HashSet> bucketToKeysMap = FunctionExecutionNodePruner.groupByBucket(this,
        routingKeys, primaryMembersNeeded, false, isBucketSetAsFilter);
    HashMap<InternalDistributedMember, HashSet> memberToKeysMap =
        new HashMap<InternalDistributedMember, HashSet>();
    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 =
                this.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(this.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",
              this.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(PartitionedRegion.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(), PartitionedRegion.this,
              execution.getArgumentsForMember(getMyId().getId()),
              localKeys, ColocationHelper
                  .constructAndGetAllColocatedLocalDataSet(PartitionedRegion.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<InternalDistributedMember, FunctionRemoteContext>();
      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());
        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(), this.getPRId(),
              localResultCollector, function, resultSender);
      return resultReceiver.getPartitionedDataFrom(recipMap, this, execution);
    }
    return localResultCollector;
  }

  /**
   * 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 = this.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(this.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",
                this.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, PartitionedRegion.this, 0, localRC,
              execution.getServerResultSender(), true, false, execution.isForwardExceptions(),
              function, buckets);
      final FunctionContext context =
          new RegionFunctionContextImpl(cache, function.getId(), PartitionedRegion.this,
              execution.getArgumentsForMember(localVm.getId()), routingKeys, ColocationHelper
                  .constructAndGetAllColocatedLocalDataSet(PartitionedRegion.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 = this.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 =
                this.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(this.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",
              this.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<InternalDistributedMember, FunctionRemoteContext>();
    for (InternalDistributedMember recip : dest) {
      FunctionRemoteContext context = new FunctionRemoteContext(function,
          execution.getArgumentsForMember(recip.getId()), null, memberToBuckets.get(recip),
          execution.isReExecute(), execution.isFnSerializationReqd());
      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 && this.dataStore != null) {
      final RegionFunctionContextImpl prContext =
          new RegionFunctionContextImpl(cache, function.getId(), PartitionedRegion.this,
              execution.getArgumentsForMember(getMyId().getId()), null, ColocationHelper
                  .constructAndGetAllColocatedLocalDataSet(PartitionedRegion.this, localBucketSet),
              localBucketSet, resultSender, execution.isReExecute());
      execution.executeFunctionOnLocalNode(function, prContext, resultSender, dm, isTX());
    }
    PartitionedRegionFunctionResultWaiter resultReceiver =
        new PartitionedRegionFunctionResultWaiter(getSystem(), this.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<Integer>();
    Iterator<Integer> itr = this.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(this.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",
              this.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<InternalDistributedMember, FunctionRemoteContext>();
    for (InternalDistributedMember recip : memberToBuckets.keySet()) {
      FunctionRemoteContext context = new FunctionRemoteContext(function,
          execution.getArgumentsForMember(recip.getId()), null, memberToBuckets.get(recip),
          execution.isReExecute(), execution.isFnSerializationReqd());
      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 && this.dataStore != null) {
      final RegionFunctionContextImpl prContext =
          new RegionFunctionContextImpl(cache, function.getId(), PartitionedRegion.this,
              execution.getArgumentsForMember(getMyId().getId()), null, ColocationHelper
                  .constructAndGetAllColocatedLocalDataSet(PartitionedRegion.this, localBucketSet),
              localBucketSet, resultSender, execution.isReExecute());
      execution.executeFunctionOnLocalPRNode(function, prContext, resultSender, dm, isTX());
    }
    PartitionedRegionFunctionResultWaiter resultReceiver =
        new PartitionedRegionFunctionResultWaiter(getSystem(), this.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(this.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 = this.localMaxMemory > 0 && retryNode.equals(getMyId());

      try {
        if (isLocal) {
          obj = this.dataStore.getLocally(bucketId, key, aCallbackArgument, disableCopyOnRead,
              preferCD, requestingClient, clientEvent, returnTombstones, false);
        } else {
          if (this.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, (InternalDistributedMember) 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(this.retryTimeout);
            }
            if (retryTime.overMaximum()) {
              break;
            }
            if (isDebugEnabled) {
              logger.debug("waiting to retry node {}", retryNode);
            }
            retryTime.waitToRetryNode();
          }
        } else {
          // with transaction
          if (prce instanceof BucketNotFoundException) {
            throw new TransactionDataRebalancedException(
                "Transactional data moved, due to rebalancing.",
                prce);
          }
          Throwable cause = prce.getCause();
          if (cause instanceof PrimaryBucketException) {
            throw (PrimaryBucketException) cause;
          } else if (cause instanceof TransactionDataRebalancedException) {
            throw (TransactionDataRebalancedException) cause;
          } else if (cause instanceof RegionDestroyedException) {
            throw new TransactionDataRebalancedException(
                "Transactional data moved, due to rebalancing.",
                cause);
          } else {
            // Make transaction fail so client could retry
            // instead of returning null if ForceReattemptException is thrown.
            // Should not see it currently, added to be protected against future changes.
            throw new TransactionException("Failed to get key: " + key, 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) {
        this.prStats.incGetOpsRetried();
      }
      this.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;
  }

  /**
   * 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 = this.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 ? this.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<BucketDump>();
    HashSet<InternalDistributedMember> collected = new HashSet<InternalDistributedMember>();
    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 = (InternalDistributedMember) ownersI.next();
      // Remove it from our list
      collected.add(owner);

      // If it is ourself, answer directly
      if (owner.equals(getMyId())) {
        BucketRegion br = this.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<Object, VersionTag>();

        for (Iterator<Map.Entry> it = br.entrySet().iterator(); it.hasNext();) {
          NonTXEntry entry = (NonTXEntry) it.next();
          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) {
    int buck = bucketNum;
    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(this.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 = this.dataStore.getKeysLocally(buck, allowTombstones);
        } else {
          FetchKeysResponse r = FetchKeysMessage.send(nod, this, buck, 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(this.retryTimeout);
        }
        InternalDistributedMember oldNode = nod;
        nod = getNodeForBucketRead(buck);
        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",
                    new Object[] {getBucketName(buck), 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> bucketKeys, VersionedObjectList values,
      ServerConnection servConn) throws IOException {
    int retryAttempts = calcRetry();
    RetryTimeKeeper retryTime = null;
    HashMap<Integer, HashSet> failures = new HashMap<Integer, HashSet>(bucketKeys);
    HashMap<InternalDistributedMember, HashMap<Integer, HashSet>> nodeToBuckets =
        new HashMap<InternalDistributedMember, HashMap<Integer, HashSet>>();

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

      // Handle old nodes for Rolling Upgrade support
      Set<Integer> failedSet = handleOldNodes(nodeToBuckets, values, servConn);
      // Add failed buckets to nodeToBuckets map so that these will be tried on
      // remote nodes.
      if (!failedSet.isEmpty()) {
        for (Integer bId : failedSet) {
          failures.put(bId, bucketKeys.get(bId));
        }
        updateNodeToBucketMap(nodeToBuckets, failures);
        failures.clear();
      }

      fetchRemoteEntries(nodeToBuckets, failures, values, servConn);
      if (!failures.isEmpty()) {
        if (retryTime == null) {
          retryTime = new RetryTimeKeeper(this.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<Integer, HashSet>();
        map.put(id, bucketKeys.get(id));
        nodeToBuckets.put(node, map);
      }
    }
  }

  /**
   * @return set of bucket-ids that could not be read from.
   */
  private Set<Integer> handleOldNodes(HashMap nodeToBuckets, VersionedObjectList values,
      ServerConnection servConn) throws IOException {
    Set<Integer> failures = new HashSet<Integer>();
    HashMap oldFellas = filterOldMembers(nodeToBuckets);
    for (Iterator it = oldFellas.entrySet().iterator(); it.hasNext();) {
      Map.Entry e = (Map.Entry) it.next();
      InternalDistributedMember member = (InternalDistributedMember) e.getKey();
      Object bucketInfo = e.getValue();

      HashMap<Integer, HashSet> bucketKeys = null;
      Set<Integer> buckets = null;

      if (bucketInfo instanceof Set) {
        buckets = (Set<Integer>) bucketInfo;
      } else {
        bucketKeys = (HashMap<Integer, HashSet>) bucketInfo;
        buckets = bucketKeys.keySet();
      }

      for (Integer bucket : buckets) {
        Set keys = null;
        if (bucketKeys == null) {
          try {
            FetchKeysResponse fkr = FetchKeysMessage.send(member, this, bucket, true);
            keys = fkr.waitForKeys();
          } catch (ForceReattemptException ignore) {
            failures.add(bucket);
          }
        } else {
          keys = bucketKeys.get(bucket);
        }

        // TODO (ashetkar) Use single Get70 instance for all?
        for (Object key : keys) {
          Get70 command = (Get70) Get70.getCommand();
          Get70.Entry ge = command.getValueAndIsObject(this, key, null, servConn);

          if (ge.keyNotPresent) {
            values.addObjectPartForAbsentKey(key, ge.value, ge.versionTag);
          } else {
            values.addObjectPart(key, ge.value, ge.isObject, ge.versionTag);
          }

          if (values.size() == BaseCommand.MAXIMUM_CHUNK_SIZE) {
            BaseCommand.sendNewRegisterInterestResponseChunk(this, "keyList", values, false,
                servConn);
            values.clear();
          }
        }
      }
    }
    return failures;
  }

  /**
   * @param nodeToBuckets A map with InternalDistributedSystem as key and either HashSet or
   *        HashMap<Integer, HashSet> as value.
   * @return Map of <old members, set/map of bucket ids they host>.
   */
  private HashMap filterOldMembers(HashMap nodeToBuckets) {
    ClusterDistributionManager dm = (ClusterDistributionManager) getDistributionManager();
    HashMap oldGuys = new HashMap();

    Set<InternalDistributedMember> oldMembers =
        new HashSet<InternalDistributedMember>(nodeToBuckets.keySet());
    dm.removeMembersWithSameOrNewerVersion(oldMembers, Version.CURRENT);
    Iterator<InternalDistributedMember> oldies = oldMembers.iterator();
    while (oldies.hasNext()) {
      InternalDistributedMember old = oldies.next();
      if (nodeToBuckets.containsKey(old)) {
        oldGuys.put(old, nodeToBuckets.remove(old));
      } else {
        oldies.remove();
      }
    }

    return oldGuys;
  }

  /**
   * 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<Integer>(getRegionAdvisor().getBucketSet());
    HashMap<InternalDistributedMember, HashSet<Integer>> nodeToBuckets =
        new HashMap<InternalDistributedMember, HashSet<Integer>>();

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

      // Handle old nodes for Rolling Upgrade support
      Set<Integer> ret = handleOldNodes(nodeToBuckets, values, servConn);
      if (!ret.isEmpty()) {
        failures.addAll(ret);
        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(this.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<Integer>();
        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 = this.dataStore.handleRemoteGetKeys(id, InterestType.REGULAR_EXPRESSION, regex, true);
      } else {
        keys = this.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<Integer, HashSet>();

    for (Iterator<Map.Entry<InternalDistributedMember, HashMap<Integer, HashSet>>> itr =
        nodeToBuckets.entrySet().iterator(); itr.hasNext();) {
      Map.Entry<InternalDistributedMember, HashMap<Integer, HashSet>> entry = itr.next();
      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 {
          if (entry.getKey().getVersionObject().compareTo(Version.GFE_80) < 0) {
            failures.putAll(nodeToBuckets.get(entry.getKey()));
            continue;
          }
          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<Integer>();

    for (Iterator<Map.Entry<InternalDistributedMember, HashSet<Integer>>> itr =
        nodeToBuckets.entrySet().iterator(); itr.hasNext();) {
      Map.Entry<InternalDistributedMember, HashSet<Integer>> entry = itr.next();
      HashSet<Integer> buckets = new HashSet<Integer>(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 {
          if (entry.getKey().getVersionObject().compareTo(Version.GFE_80) < 0) {
            failures.addAll(nodeToBuckets.get(entry.getKey()));
            continue;
          }
          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 (this.isDataStore()) {
      result.add(getDistributionManager().getId());
    }
    return result;
  }

  /**
   * Test Method: Get the number of entries in the local data store.
   */
  public long getLocalSizeForTest() {
    if (this.dataStore == null) {
      return 0L;
    }
    long ret = 0L;
    Integer i;
    for (Iterator si = this.dataStore.getSizeLocally().values().iterator(); si.hasNext();) {
      i = (Integer) si.next();
      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);
    this.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(), this.getPRId(), rc, function,
            resultSender);

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

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

    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 this.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 this.distAdvisor;
  }

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

  public RegionAdvisor getRegionAdvisor() {
    return this.distAdvisor;
  }

  /** Returns the distribution profile; lazily creates one if needed */
  @Override
  public Profile getProfile() {
    return this.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 = ((this.cache.getCacheServers().size() > 0) ? true : false);
    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 (this.dataStore != null) {
      profile.numBuckets = this.dataStore.getBucketsManaged();
    }

    profile.requiresNotification = this.requiresNotification;
    profile.localMaxMemory = getLocalMaxMemory();
    profile.fixedPAttrs = this.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) {
      this.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) {
    this.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 (Iterator it = prIdToPR.values().iterator(); it.hasNext();) {
        Object o = it.next();
        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 this.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 this.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(this.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 {
      this.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
          this.cache.getCancelCriterion().checkCancelInProgress(null);
          timeOut = System.currentTimeMillis() + this.retryTimeout;
          break;
        default:
          this.cache.getCancelCriterion().checkCancelInProgress(null);
          // test for timeout
          long timeLeft = timeOut - System.currentTimeMillis();
          if (timeLeft < 0) {
            PRHARedundancyProvider.timedOut(this, null, null, "destroy an entry",
                this.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(this.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 = (this.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);
          this.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(this.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(this.retryTimeout);
        }
        currentTarget = getOrCreateNodeForBucketWrite(bucketId, retryTime);
      }

      // If we get here, the attempt failed.
      if (count == 1) {
        this.prStats.incDestroyOpsRetried();
      }
      this.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 (this.isDataStore() && !getMyId().equals(targetNode)) {
      Set<ServerBucketProfile> profiles = this.getRegionAdvisor().getClientBucketProfiles(bucketId);

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

            if (isProfileFromSameGroup(profile)) {
              if (this.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)");
              }
              this.setNetworkHopType((byte) NETWORK_HOP_TO_SAME_GROUP);
            } else {
              if (this.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)");
              }
              this.setNetworkHopType((byte) NETWORK_HOP_TO_DIFFERENT_GROUP);
            }
            this.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) {
      this.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 this.localMaxMemory;
  }

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

  @Override
  public VersionTag findVersionTagForEvent(EventID eventId) {
    if (this.dataStore != null) {
      Set<Map.Entry<Integer, BucketRegion>> bucketMap = this.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<ThreadIdentifier, VersionTag>();
    if (this.dataStore != null) {
      Set<Map.Entry<Integer, BucketRegion>> bucketMap = this.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.
    this.redundancyProvider.waitForPersistentBucketRecovery();
    this.cache.removePartitionedRegion(this);
    this.cache.getInternalResourceManager(false).removeResourceListener(this);
    this.redundancyProvider.shutdown(); // see bug 41094
    int serials[] = getRegionAdvisor().getBucketSerials();
    RegionEventImpl event = new RegionEventImpl(this, Operation.REGION_CLOSE, null, false,
        getMyId(), generateEventID()/* generate EventID */);
    try {
      sendDestroyRegionMessage(event, serials);
    } catch (Exception ex) {
      logger.warn(
          "PartitionedRegion#cleanupFailedInitialization(): Failed to clean the PartionRegion data store",
          ex);
    }
    if (null != this.dataStore) {
      try {
        this.dataStore.cleanUp(true, false);
      } catch (Exception ex) {
        logger.warn(
            "PartitionedRegion#cleanupFailedInitialization(): Failed to clean the PartionRegion data store",
            ex);
      }
    }

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

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

  /**
   * 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 (!this.isClosed && !this.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(this.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 {
      this.prStats.endInvalidate(startTime);
    }
    return;
  }

  @Override
  void basicUpdateEntryVersion(EntryEventImpl event) throws EntryNotFoundException {

    try {
      if (event.getEventId() == null) {
        event.setNewEventId(this.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(this.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 = (this.localMaxMemory > 0) && retryNode.equals(getMyId());
      try {
        if (isLocal) {
          event.setInvokePRCallbacks(true);
          this.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(this.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) {
        this.prStats.incInvalidateOpsRetried();
      }
      this.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) {
      this.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 (this.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) {
      this.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() {
        this.key.setKey(super.next());
        this.key.setBucketId(this.currentBucketId);

        Object entry =
            view.getEntryForIterator(this.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(this.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<Integer>();
    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) {
        PartitionedRegion.this.checkReadiness();
        this.bucketSet = bucketSet;
        this.allowTombstones = allowTombstones;
        this.bucketSetI = createBucketSetI();
        this.currentBucketI = getNextBucketIter(false /* no throw */);
      }

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

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

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

      protected Iterator getNextBucketIter(boolean canThrow) {
        try {
          this.currentBucketId = this.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, this.currentBucketId, this.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.emptySet().iterator();
          }
        }
      }

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

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

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

    protected final Set<Integer> bucketSet;

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

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

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

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

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

    @Override
    public Object[] toArray(Object[] array) {
      List temp = new ArrayList(this.size());
      for (Iterator iter = this.iterator(); iter.hasNext();) {
        temp.add(iter.next());
      }
      if (array == null) {
        return temp.toArray();
      } else {
        return temp.toArray(array);
      }
    }

    @Override
    public Iterator iterator() {
      checkTX();
      return new KeysSetIterator(this.bucketSet, this.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;
          }
          this.key.setKey(super.next());
          this.key.setBucketId(this.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 (!this.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(this.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 (this.getDataStore() != null) {
      ValuesSet vSet = new ValuesSet(this.getDataStore().getAllLocalPrimaryBucketIds());
      Iterator itr = vSet.iterator();
      while (itr.hasNext()) {
        Object v = itr.next();
        if (v.equals(value)) {
          return true;
        }
      }
    }

    ResultCollector rc = null;
    try {
      rc = FunctionService.onRegion(this).setArguments((Serializable) 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 {
      this.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(this.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 = this.dataStore.containsValueForKeyLocally(bucketIdInt, key);
          } else {
            ret = this.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(this.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) {
        this.prStats.incContainsKeyValueOpsRetried();
      }
      this.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);
    this.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 {
      this.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);
    this.prStats.incPartitionMessagesSent();
    return r.waitForContainsResult();
  }

  /**
   * Get the VSD statistics type
   *
   * @return the statistics instance specific to this Partitioned Region
   */
  public PartitionedRegionStats getPrStats() {
    return this.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 (this.isDataStore()) {
        return entryCount(this.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 (this.dataStore != null) {
        List<Integer> list = new ArrayList<Integer>(buckets);
        bucketSizes = this.dataStore.getSizeLocallyForBuckets(list);
      }
    } else {
      if (this.dataStore != null) {
        bucketSizes = this.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 = this.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);
    this.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) {
      this.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 this.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 (!this.lockOwned) {
          cache.getCancelCriterion().checkCancelInProgress(null);
          this.lockOwned =
              this.lockService.lock(this.lockName, waitInterval, -1, false, false, !enableAlerts);
          if (!this.lockOwned && ackSAThreshold > 0 && enableAlerts) {
            long elapsed = System.currentTimeMillis() - startTime;
            if (elapsed > ackWaitThreshold && enableAlerts) {
              if (!suspected) {
                suspected = true;
                severeAlertIssued = false;
                waitInterval = ackSAThreshold;
                DLockRemoteToken remoteToken = this.lockService.queryLock(this.lockName);
                lockHolder = remoteToken.getLessee();
                if (lockHolder != null) {
                  dm.getMembershipManager().suspectMember((InternalDistributedMember) lockHolder,
                      "Has not released a partitioned region lock in over "
                          + ackWaitThreshold / 1000 + " sec");
                }
              } else if (elapsed > ackSAThreshold && enableAlerts) {
                DLockRemoteToken remoteToken = this.lockService.queryLock(this.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 = this.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();
          this.lockOwned = this.lockService.lock(key, waitInterval, -1, true, false);
          if (this.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 = this.lockService.queryLock(key);
                lockHolder = remoteToken.getLessee();
                if (lockHolder != null) {
                  dm.getMembershipManager().suspectMember((InternalDistributedMember) lockHolder,
                      "Has not released a global region entry lock in over "
                          + ackWaitThreshold / 1000 + " sec");
                }
              } else if (elapsed > ackSAThreshold) {
                DLockRemoteToken remoteToken = this.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 = this.lockService.queryLock(this.lockName);
        return remoteToken.getLessee();
      } catch (LockServiceDestroyedException e) {
        cache.getCancelCriterion().checkCancelInProgress(null);
        throw e;
      }
    }

    public void unlock() {
      if (this.lockOwned) {
        try {
          this.lockService.unlock(this.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", this.lockService, e);
          }
        } finally {
          this.lockOwned = false;
        }
      }
    }

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

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

      DLockService ls1 = lockService;
      DLockService ls2 = other.lockService;
      if (ls1 == null || ls2 == null) {
        if (ls1 != ls2)
          return false;
      }
      return ls1.equals(ls2);
    }

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

    @Override
    public String toString() {
      return "BucketLock@" + System.identityHashCode(this) + "lockName=" + this.lockName
          + " lockService=" + this.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(PartitionedRegion.this.getRegionIdentifier() + "-RecoveryLock", getCache(), false);
    }

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

  @Override
  public String toString() {
    return new StringBuffer().append("Partitioned Region ").append("@")
        .append(Integer.toHexString(hashCode())).append(" [").append("path='").append(getFullPath())
        .append("'; dataPolicy=").append(this.getDataPolicy()).append("; prId=")
        .append(this.partitionedRegionId).append("; isDestroyed=").append(this.isDestroyed)
        .append("; isClosed=").append(this.isClosed).append("; retryTimeout=")
        .append(this.retryTimeout).append("; serialNumber=").append(getSerialNumber())

        .append("; partition attributes=").append(getPartitionAttributes().toString())
        .append("; on VM ").append(getMyId()).append("]").toString();
  }

  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 this.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 this.redundancyProvider;
  }

  /**
   * This method checks if region is closed.
   */
  public void checkClosed() {
    if (this.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 (!this.haveCacheLoader) {
      this.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) {
      this.isClosed = true;
    }
    final RegionLock rl = getRegionLock();
    try {
      rl.lock();
      logger.info("Partitioned Region {} with prId={} closing.",
          new Object[] {getFullPath(), getPRId()});
      if (!checkIfAlreadyDestroyedOrOldReference()) {
        PartitionedRegionHelper.removeGlobalMetadataForFailedNode(getNode(),
            this.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 (this.dataStore != null) {
        this.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()});
  }

  public void checkForColocatedChildren() {
    List<PartitionedRegion> listOfChildRegions = ColocationHelper.getColocatedChildRegions(this);
    if (listOfChildRegions.size() != 0) {
      List<String> childRegionList = new ArrayList<String>();
      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",
            this.getFullPath(), childRegionList));
      }
    }
  }

  @Override
  public void destroyRegion(Object aCallbackArgument)
      throws CacheWriterException, TimeoutException {
    this.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() {
    if (missingColocatedRegionLogger != null) {
      missingColocatedRegionLogger.stopLogger();
    }
    missingColocatedRegionLogger = null;
  }

  public void addMissingColocatedRegionLogger(String childName) {
    if (missingColocatedRegionLogger == null) {
      missingColocatedRegionLogger = new ColocationLogger(this);
    }
    missingColocatedRegionLogger.addMissingChildRegion(childName);
  }

  public void addMissingColocatedRegionLogger(PartitionedRegion childRegion) {
    if (missingColocatedRegionLogger == null) {
      missingColocatedRegionLogger = new ColocationLogger(this);
    }
    missingColocatedRegionLogger.addMissingChildRegions(childRegion);
  }

  public List<String> getMissingColocatedChildren() {
    ColocationLogger regionLogger = missingColocatedRegionLogger;
    if (regionLogger != null) {
      return regionLogger.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: {}",
          this.getParallelGatewaySenderIds());
    }

    boolean keepWaiting = true;

    while (true) {
      List<String> pausedSenders = new ArrayList<String>();
      List<ConcurrentParallelGatewaySenderQueue> parallelQueues =
          new ArrayList<ConcurrentParallelGatewaySenderQueue>();
      isDestroyedForParallelWAN = true;
      int countOfQueueRegionsToBeDestroyed = 0;
      for (String senderId : this.getParallelGatewaySenderIds()) {
        AbstractGatewaySender sender =
            (AbstractGatewaySender) this.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(this.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, this.getName());
        } else {
          exception =
              String.format(
                  "GatewaySenders %s are paused. Resume them before destroying region %s.",
                  pausedSenders, this.getName());
        }
        isDestroyedForParallelWAN = false;
        throw new GatewaySenderException(exception);
      }

      if (countOfQueueRegionsToBeDestroyed == 0) {
        break;
      }

      for (ConcurrentParallelGatewaySenderQueue parallelQueue : parallelQueues) {
        PartitionedRegion parallelQueueRegion = parallelQueue.getRegion(this.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(this.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 = this.getColocatedWith();
    List<PartitionedRegion> listOfChildRegions = ColocationHelper.getColocatedChildRegions(this);

    List<String> childRegionsWithoutSendersList = new ArrayList<String>();
    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(this.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(this.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
        Iterator itr = prConfig.getNodes().iterator();
        while (itr.hasNext()) {
          InternalDistributedMember idm = ((Node) itr.next()).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 (this.isLocallyDestroyed) {
        return false;
      }
      this.locallyDestroyingThread = Thread.currentThread();
      this.isLocallyDestroyed = true;
    }
    if (logger.isDebugEnabled()) {
      logger.debug("destroyPartitionedRegionLocally: Starting destroy for PR = {}", this);
    }
    try {
      synchronized (prIdToPR) {
        prIdToPR.remove(getPRId());
      }
      this.redundancyProvider.shutdown(); // see bug 41094
      if (this.dataStore != null) {
        this.dataStore.cleanUp(false, removeFromDisk);
      }
    } finally {
      this.getRegionAdvisor().close();
      getPrStats().close();
      this.cache.getInternalResourceManager(false).removeResourceListener(this);
      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(this.isDestroyed || this.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.
    this.redundancyProvider.waitForPersistentBucketRecovery();
    // fix #39196 OOME caused by leak in GemFireCache.partitionedRegions
    this.cache.removePartitionedRegion(this);
    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);
            }
          }

          // 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
        this.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(),
        this.cache.getInternalDistributedSystem().getDistributedMember(), null, op.isClose());
  }

  /**
   * 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(this.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() != this.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 (this.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 ? this.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 (this.dataStore != null) {
      this.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 (this.dataStore != null) {
      this.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(this.getRegionAdvisor().adviseAllPRNodes(), this, bucketId, false);
      response.waitForRepliesUninterruptibly();
      this.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() {
    StringBuilder sb = new StringBuilder(getPRRoot().getFullPath());
    sb.append("Dumping allPartitionedRegions for ");
    sb.append(this);
    sb.append("\n");
    sb.append(getPRRoot().get(getRegionIdentifier()));
    logger.debug(sb.toString());
  }

  /**
   * A test method to get the list of all the bucket ids for the partitioned region in the data
   * Store.
   */
  public List getLocalBucketsListTestOnly() {
    List localBucketList = null;
    if (this.dataStore != null) {
      localBucketList = this.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 getLocalPrimaryBucketsListTestOnly() {
    List localPrimaryList = null;
    if (this.dataStore != null) {
      localPrimaryList = this.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) {
      this.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() {
      this.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;
      }
      this.totalTimeInRetry += delta;
    }

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

    public long getRetryTime() {
      return this.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()) {
      this.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(int 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;
      int lbucket = bucket;
      final RetryTimeKeeper retryTime = new RetryTimeKeeper(Integer.MAX_VALUE);
      InternalDistributedMember bucketNode = getOrCreateNodeForBucketRead(lbucket);
      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 = this.dataStore.handleRemoteGetKeys(lbucket, interestType, interestArg,
                  allowTombstones);
            } else {
              FetchKeysResponse r = FetchKeysMessage.sendInterestQuery(bucketNode, this, lbucket,
                  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(lbucket);
          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 this.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 : this.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) {
    Iterator iter = this.indexes.values().iterator();
    while (iter.hasNext()) {
      Object ind = iter.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 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 (this.indexes.isEmpty()) {
      return Collections.emptyList();
    }

    ArrayList idxs = new ArrayList();
    Iterator it = this.indexes.values().iterator();
    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) {
        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 (this.indexManager == null) {
      this.indexManager = IndexUtils.getIndexManager(cache, this, true);
    }

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

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

    // This will return either the Index FutureTask or Index itself, based
    // on whether the index creation is in process or completed.
    Object ind = this.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) {
          this.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>();
            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,
                  PartitionedRegion.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.
              this.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 = this.indexes.get(indexTask);
        if (ind != null && !(ind instanceof Index)) {
          this.indexes.remove(indexTask);
        }
      }

      if (interrupted) {
        Thread.currentThread().interrupt();
      }
    }
    if (logger.isDebugEnabled()) {
      logger.debug(
          "Completed creating index with Index Name :{} On PartitionedRegion {}, Remote Request: {}",
          indexName, this.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<Index>();
    }

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

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

  private boolean createEmptyIndexes(HashSet<IndexCreationData> indexDefinitions,
      boolean remotelyOriginated, Set<Index> indexes, HashMap<String, Exception> exceptionsMap) {
    boolean throwException = false;
    for (IndexCreationData icd : indexDefinitions) {
      try {
        Index ind = this.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 (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<Index>();
      for (Index ind : indexSet) {
        PartitionedIndex prIndex = (PartitionedIndex) ind;
        if (!prIndex.isPopulateInProgress()) {
          prIndex.setPopulateInProgress(true);
          unpopulatedIndexes.add(prIndex);
        }
      }
      return unpopulatedIndexes;
    }
  }

  private boolean populateEmptyIndexes(Set<Index> indexes,
      HashMap<String, Exception> exceptionsMap) {
    boolean throwException = false;
    if (getDataStore() != null && indexes.size() > 0) {
      Set localBuckets = getDataStore().getAllLocalBuckets();
      Iterator it = localBuckets.iterator();
      while (it.hasNext()) {
        Map.Entry entry = (Map.Entry) it.next();
        Region bucket = (Region) entry.getValue();

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

  private Set<Index> getBucketIndexesForPRIndexes(Region bucket, Set<Index> indexes) {
    Set<Index> bucketIndexes = new HashSet<Index>();
    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 (!this.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 (this.indexes.isEmpty()) {
      return;
    }

    Iterator it = this.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 (!this.hasPartitionedIndex || this.indexes.isEmpty()) {
      if (logger.isDebugEnabled()) {
        logger.debug("This partitioned regions does not have any index : {}", this);
      }
      return numBuckets;
    }

    this.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());
          }
        }
      }
      this.indexManager.removeIndexes();
      return numBuckets;

    } // outer try block
    finally {
      this.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 = this.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 = this.indexManager.getIndex(ind.getName());
    if (index1 != null) {
      this.indexManager.removeIndex(index1);
    }

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

    this.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 = this.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) this.indexes.get(indexName), true);
    }
    return numBuckets;
  }

  @Override
  public Object getValueInVM(Object key) throws EntryNotFoundException {
    if (this.dataStore == null) {
      throw new EntryNotFoundException(key.toString());
    }
    final int bucketId = PartitionedRegionHelper.getHashKey(this, null, key, null, null);
    return this.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 (this.dataStore == null) {
      throw new EntryNotFoundException(key.toString());
    }
    return this.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 (this.dataStore == null) {
      throw new EntryNotFoundException(key.toString());
    }
    return this.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 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 remoteInfos = null;
    for (int i = 0; i < 3; i++) {
      rte = null;
      DumpB2NResponse response =
          DumpB2NRegion.send(getRegionAdvisor().adviseDataStore(), this, bucketId, true);
      try {
        remoteInfos = new LinkedList(response.waitForPrimaryInfos());
      } catch (TimeoutException e) {
        rte = e;
        logger.info("DumpB2NRegion failed to get PR {}, bucket id {}'s info due to {}, retrying...",
            this.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(this.initializationLatchAfterBucketIntialization);
  }

  private void releaseAfterBucketMetadataSetupLatch() {
    this.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 this.retryTimeout;
  }

  public long getBirthTime() {
    return birthTime;
  }

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

  public String getColocatedWith() {
    return this.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 (PartitionedRegion.this.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 (PartitionedRegion.this.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 = this.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 (this.dataStore != null) {
      // Handle the interest event in the local data store
      this.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 (this.getDataStore() != null) { // not for accessors
      for (Object o : this.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 (this.getDataStore() != null) { // not for accessors
      for (Object o : this.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);
    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
    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
    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
    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 this.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);
      this.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);
    }
    List<BucketRegion> bucketList = new ArrayList<>(this.sortedBuckets);
    return bucketList;
  }

  class BucketSorterRunnable implements Runnable {
    @Override
    public void run() {
      try {
        List<BucketRegion> bucketList = new ArrayList<BucketRegion>();
        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, new Comparator<BucketRegion>() {
            @Override
            public int compare(BucketRegion buk1, BucketRegion 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(
              "Transactional data moved, due to rebalancing.",
              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.assertTrue(br != null, "Could not create storage for Entry");
      if (keyInfo.isCheckPrimary()) {
        br.checkForPrimary();
      }
    } catch (PrimaryBucketException pbe) {
      throw new TransactionDataRebalancedException(
          "Transactional data moved, due to rebalancing.",
          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));
    }
    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;
      this.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) {
      // TODO: equals should always check the class of other
      if (other == null) {
        return false;
      }
      IndexTask otherIndexTask = (IndexTask) other;
      if (this.indexName.equals(otherIndexTask.indexName)) {
        return true;
      }
      return false;
    }

    @Override
    public int hashCode() {
      return this.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<FixedPartitionAttributesImpl>();
    if (this.fixedPAttrs != null) {
      for (FixedPartitionAttributesImpl fpa : this.fixedPAttrs) {
        if (fpa.isPrimary()) {
          primaryFixedPAttrs.add(fpa);
        }
      }
    }
    return primaryFixedPAttrs;
  }

  public List<FixedPartitionAttributesImpl> getSecondaryFixedPartitionAttributes_TestsOnly() {
    List<FixedPartitionAttributesImpl> secondaryFixedPAttrs =
        new LinkedList<FixedPartitionAttributesImpl>();
    if (this.fixedPAttrs != null) {
      for (FixedPartitionAttributesImpl fpa : this.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 (this.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) {
      this.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 (this.dataStore == null)
      return null;
    Integer bucketId = PartitionedRegionHelper.getHashKey(this, null, key, null, null);
    return this.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 (this.dataStore == null) {
      return null;
    }
    final Integer bucketId = PartitionedRegionHelper.getHashKey(this, null, key, value, null);
    return this.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 (this.dataStore == null) { // this is an accessor
      return -1;
    }
    try {
      return this.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 (this.dataStore == null) {
      return false;
    }
    return this.dataStore.hasSeenEvent(ev);
  }

  public void enableConflation(boolean conflation) {
    this.enableConflation = conflation;
  }

  public boolean isConflationEnabled() {
    return this.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(this.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 = (this.localMaxMemory > 0) && retryNode.equals(getMyId());
      try {
        if (isLocal) {
          this.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(this.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) {
      this.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 this.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<Integer>(allBuckets);
    while (allBucketsClone.size() != 0) {
      logger.debug(
          "Need to wait until partitionedRegionQueue <<{}>> is loaded with all the buckets",
          this.getName());
      Iterator<Integer> itr = allBucketsClone.iterator();
      while (itr.hasNext()) {
        InternalDistributedMember node = this.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 this.getLocalMaxMemory() != 0;
  }

  @Override
  public EntryExpiryTask getEntryExpiryTask(Object key) {
    BucketRegion br = this.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;
  }
}
