diff --git a/src/java/org/apache/cassandra/service/StorageService.java b/src/java/org/apache/cassandra/service/StorageService.java index b4c8343558..fb4d60a200 100644 --- a/src/java/org/apache/cassandra/service/StorageService.java +++ b/src/java/org/apache/cassandra/service/StorageService.java @@ -3518,14 +3518,21 @@ public class StorageService extends NotificationBroadcasterSupport implements IE long totalRowCountEstimate = cfs.estimatedKeysForRange(range); // splitCount should be much smaller than number of key samples, to avoid huge sampling error - int minSamplesPerSplit = 4; - int maxSplitCount = keys.size() / minSamplesPerSplit + 1; - int splitCount = Math.max(1, Math.min(maxSplitCount, (int)(totalRowCountEstimate / keysPerSplit))); + int splitCount = calculateSplitCount(keysPerSplit, totalRowCountEstimate, keys.size()); List tokens = keysToTokens(range, keys); return getSplits(tokens, splitCount, cfs); } + static int calculateSplitCount(int keysPerSplit, long totalRowCountEstimate, int numberOfKeys) + { + int minSamplesPerSplit = 4; + long maxSplitCount = numberOfKeys / minSamplesPerSplit + 1; + long splitCount = totalRowCountEstimate / keysPerSplit; + int splitCountWithLimit = (int) Math.min(maxSplitCount, splitCount); + return Math.max(1, splitCountWithLimit); + } + private List, Long>> getSplits(List tokens, int splitCount, ColumnFamilyStore cfs) { double step = (double) (tokens.size() - 1) / splitCount; diff --git a/test/unit/org/apache/cassandra/service/StorageServiceTest.java b/test/unit/org/apache/cassandra/service/StorageServiceTest.java index 8742cdac23..318c7c582b 100644 --- a/test/unit/org/apache/cassandra/service/StorageServiceTest.java +++ b/test/unit/org/apache/cassandra/service/StorageServiceTest.java @@ -295,4 +295,46 @@ public class StorageServiceTest extends TestBaseImpl assertEquals("Cannot specify tokens without keyspace.", ex.getMessage()); } } + + @Test + public void calculateSplitCount_SmallRowCount_NotLimited() + { + int result = StorageService.calculateSplitCount(2, 8, 40); + assertEquals(4, result); + } + + @Test + public void calculateSplitCount_ZeroRowCount_ReturnsMinimumOfOne() + { + int result = StorageService.calculateSplitCount(1, 0, 40); + assertEquals(1, result); + } + + @Test + public void calculateSplitCount_ForLargeRowCount_LimitsResult() + { + int result = StorageService.calculateSplitCount(2, 100, 40); + assertEquals(11, result); + } + + @Test + public void calculateSplitCount_ForMaxIntegerRowCount_LimitsResult() + { + int result = StorageService.calculateSplitCount(1, Integer.MAX_VALUE, 4); + assertEquals(2, result); + } + + @Test + public void calculateSplitCount_ForOverflowingRowCount_LimitsResult() + { + int result = StorageService.calculateSplitCount(1, Integer.MAX_VALUE + 1L, 4); + assertEquals(2, result); + } + + @Test + public void calculateSplitCount_ForMaxLongRowCount_LimitsResult() + { + int result = StorageService.calculateSplitCount(1, Long.MAX_VALUE, 4); + assertEquals(2, result); + } }