public static SplitOutcome TrySplitRange(PartitionKeyHashRange partitionKeyHashRange, int rangeCount, out PartitionKeyHashRanges splitRanges) { if (rangeCount < 1) { splitRanges = default; return(SplitOutcome.NumRangesNeedsToBeGreaterThanZero); } UInt128 actualEnd = partitionKeyHashRange.EndExclusive.HasValue ? partitionKeyHashRange.EndExclusive.Value.Value : UInt128.MaxValue; UInt128 actualStart = partitionKeyHashRange.StartInclusive.HasValue ? partitionKeyHashRange.StartInclusive.Value.Value : UInt128.MinValue; UInt128 rangeLength = actualEnd - actualStart; if (rangeLength < rangeCount) { splitRanges = default; return(SplitOutcome.RangeNotWideEnough); } if (rangeCount == 1) { // Just return the range as is: splitRanges = PartitionKeyHashRanges.Create(new PartitionKeyHashRange[] { partitionKeyHashRange }); return(SplitOutcome.Success); } List <PartitionKeyHashRange> childRanges = new List <PartitionKeyHashRange>(); UInt128 childRangeLength = rangeLength / rangeCount; // First range should start at the user supplied range (since the input might have an open range and we don't want to return 0) { PartitionKeyHash?start = partitionKeyHashRange.StartInclusive; PartitionKeyHash end = new PartitionKeyHash(actualStart + childRangeLength); childRanges.Add(new PartitionKeyHashRange(start, end)); } for (int i = 1; i < rangeCount - 1; i++) { PartitionKeyHash start = new PartitionKeyHash(actualStart + (childRangeLength * i)); PartitionKeyHash end = new PartitionKeyHash(start.Value + childRangeLength); childRanges.Add(new PartitionKeyHashRange(start, end)); } // Last range will have remaining EPKs, since the range might not be divisible. { PartitionKeyHash start = new PartitionKeyHash(actualStart + (childRangeLength * (rangeCount - 1))); PartitionKeyHash?end = partitionKeyHashRange.EndExclusive; childRanges.Add(new PartitionKeyHashRange(start, end)); } splitRanges = PartitionKeyHashRanges.Create(childRanges); return(SplitOutcome.Success); }
public static PartitionKeyHashRanges SplitRange(PartitionKeyHashRange partitionKeyHashRange, int rangeCount) { SplitOutcome splitOutcome = PartitionKeyHashRangeSplitterAndMerger.TrySplitRange( partitionKeyHashRange, rangeCount, out PartitionKeyHashRanges splitRanges); return(splitOutcome switch { SplitOutcome.Success => splitRanges, SplitOutcome.NumRangesNeedsToBeGreaterThanZero => throw new ArgumentOutOfRangeException($"{nameof(rangeCount)} must be a positive integer"), SplitOutcome.RangeNotWideEnough => throw new ArgumentOutOfRangeException($"{nameof(partitionKeyHashRange)} is not wide enough to split into {rangeCount} ranges."), _ => throw new ArgumentOutOfRangeException($"Unknown {nameof(SplitOutcome)}: {splitOutcome}."), });