private boolean isKeyInNonColocatedBucket(KeyInfo keyInfo) {
    Map<Region<?, ?>, TXRegionStub> regionStubs = state.getRegionStubs();
    Collection<PartitionedRegion> colcatedRegions = ColocationHelper
        .getAllColocationRegions(region).values();
    // get all colocated region buckets touched in the transaction
    for (PartitionedRegion colcatedRegion : colcatedRegions) {
      PartitionedTXRegionStub regionStub =
          (PartitionedTXRegionStub) regionStubs.get(colcatedRegion);
      if (regionStub != null) {
        buckets.putAll(regionStub.getBuckets());
      }
    }
    return keyInfo != null && !buckets.isEmpty() && !buckets.containsKey(keyInfo.getBucketId());
  }
tracks bucketIds of transactional operations so as to distinguish between
TransactionDataNotColocated and TransactionDataRebalanced exceptions. Map rather than set, as a
HashSet is backed by a HashMap. (avoids one "new" call).
geode-core/src/main/java/org/apache/geode/internal/cache/tx/PartitionedTXRegionStub.java