public static RebalanceResults moveData(Region<?, ?> region, DistributedMember source,
      DistributedMember destination, float percentage) {
    PartitionedRegion pr = isPartitionedCheck(region);
    if (pr.isFixedPartitionedRegion()) {
      throw new IllegalStateException("Cannot move data in a fixed partitioned region");
    }
    if (percentage <= 0 || percentage > 100.0) {
      throw new IllegalArgumentException("Percentage must be between 0 and 100");
    }

    PercentageMoveDirector director = new PercentageMoveDirector(source, destination, percentage);
    PartitionedRegionRebalanceOp rebalance =
        new PartitionedRegionRebalanceOp(pr, false, director, true, true);
    Set<PartitionRebalanceInfo> results = rebalance.execute();

    RebalanceResultsImpl rebalanceResults = new RebalanceResultsImpl();
    for (PartitionRebalanceInfo details : results) {
      rebalanceResults.addDetails(details);
    }

    return rebalanceResults;
  }
Moves data from the source member to the destination member, up to the given percentage of data
(measured in bytes). The data will be fully transferred once this method is complete, if the
method does not throw an exception. The percentage is a percentage of the amount of data in
bytes on the source member for this region.
<p>

If this region has colocated regions, the colocated data will also be moved. The total amount
of data in all colocated regions will be taken into consideration when determining what
percentage of data will be moved.
<p>
It may not be possible to move data to the destination member, if the destination member has no
available space, no bucket smaller than the given percentage exists, or if moving data would
violate redundancy constraints. If data cannot be moved, this method will return a
RebalanceResult object with 0 total bucket transfers.
<p>
This method allows direct control of what data to move. To automatically balance buckets, see
{@link ResourceManager#createRebalanceFactory()}

@param region The region in which to move data. Data in regions colocated with this region will
       also be moved.
@param source A member that is currently hosting data. The bucket is moved off of this member.
@param destination A member that that has the partitioned region defined. Data is moved to this
       member.
@param percentage the maximum amount of data to move, as a percentage from 0 to 100.

@throws IllegalStateException if the source or destination are not valid members of the system.
@throws IllegalArgumentException if the percentage is not between 0 to 100.

@return A RebalanceResult object that contains information about what what data was actually
        moved.

@since GemFire 7.1
geode-core/src/main/java/org/apache/geode/cache/partition/PartitionRegionHelper.java