public static FetchKeysResponse send(InternalDistributedMember recipient, PartitionedRegion r,
      Integer bucketId, boolean allowTombstones) throws ForceReattemptException {
    Assert.assertTrue(recipient != null, "FetchKeysMessage NULL recipient");
    TXManagerImpl txManager = r.getCache().getTxManager();
    boolean resetTxState = isTransactionInternalSuspendNeeded(txManager);
    TXStateProxy txStateProxy = null;
    if (resetTxState) {
      txStateProxy = txManager.pauseTransaction();
    }

    try {
      FetchKeysMessage tmp = new FetchKeysMessage();

      FetchKeysResponse p =
          (FetchKeysResponse) tmp.createReplyProcessor(r, Collections.singleton(recipient));
      FetchKeysMessage m = new FetchKeysMessage(recipient, r.getPRId(), p, bucketId,
          InterestType.REGULAR_EXPRESSION, ".*", allowTombstones);
      m.setTransactionDistributed(txManager.isDistributed());

      Set<InternalDistributedMember> failures = r.getDistributionManager().putOutgoing(m);
      if (failures != null && failures.size() > 0) {
        throw new ForceReattemptException(
            String.format("Failed sending < %s >", m));
      }
      return p;
    } finally {
      if (resetTxState) {
        txManager.unpauseTransaction(txStateProxy);
      }
    }
  }
Sends a PartitionedRegion message to fetch keys for a bucketId

@param recipient the member that the fetch keys message is sent to
@param r the PartitionedRegion that contains the bucket
@param bucketId the identity of the bucket that contains the keys to be returned
@param allowTombstones whether to include destroyed entries in the result
@return the processor used to read the returned keys
@throws ForceReattemptException if the peer is no longer available
geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/FetchKeysMessage.java