final Map<Index, List<RangeLocationPair>> otherSplitInfo = new HashMap<Index, List<RangeLocationPair>>();
do {
// this will get the least value at or above the target range
final BigInteger compareRange = targetRange;
pairToSplit = orderedSplits.ceiling(new IndexRangeLocation(
new RangeLocationPair(
null,
null) {
@Override
protected BigInteger getRangeAtCardinality(
final int cardinality ) {
return compareRange;
}
},
null));
// there are no elements greater than the target, so take the
// largest element and adjust the target
if (pairToSplit == null) {
final IndexRangeLocation highestRange = orderedSplits.pollLast();
List<RangeLocationPair> rangeList = otherSplitInfo.get(highestRange.index);
if (rangeList == null) {
rangeList = new ArrayList<RangeLocationPair>();
otherSplitInfo.put(
highestRange.index,
rangeList);
}
rangeList.add(highestRange.rangeLocationPair);
targetRange = targetRange.subtract(highestRange.rangeLocationPair.getRangeAtCardinality(maxCardinality));
}
}
while ((pairToSplit == null) && !orderedSplits.isEmpty());
if (pairToSplit == null) {
// this should never happen!
LOGGER.error("Unable to identify splits");
// but if it does, just take the first range off of this and
// split it in half if this is left as empty
clearCache();
return splitSingleRange(maxCardinality);
}
// now we just carve the pair to split by the amount we are over
// the target range
final BigInteger currentRange = pairToSplit.rangeLocationPair.getRangeAtCardinality(maxCardinality);
final BigInteger rangeExceeded = currentRange.subtract(targetRange);
if (rangeExceeded.compareTo(BigInteger.ZERO) > 0) {
// remove pair to split from ordered splits and split it to
// attempt to match the target range, adding the appropriate
// sides of the range to this info's ordered splits and the
// other's splits
orderedSplits.remove(pairToSplit);
final BigInteger end = getEnd(
pairToSplit.rangeLocationPair.range,
maxCardinality);
final byte[] splitKey = getKeyFromBigInteger(
end.subtract(rangeExceeded),
maxCardinality);
List<RangeLocationPair> rangeList = otherSplitInfo.get(pairToSplit.index);
if (rangeList == null) {
rangeList = new ArrayList<RangeLocationPair>();
otherSplitInfo.put(
pairToSplit.index,
rangeList);
}
rangeList.add(new RangeLocationPair(
new Range(
pairToSplit.rangeLocationPair.range.getStartKey(),
pairToSplit.rangeLocationPair.range.isStartKeyInclusive(),
new Key(
new Text(
splitKey)),
false),
pairToSplit.rangeLocationPair.location));
orderedSplits.add(new IndexRangeLocation(
new RangeLocationPair(
new Range(
new Key(
new Text(
splitKey)),
true,