001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.master.normalizer; 019 020import static java.lang.String.format; 021import static org.apache.hadoop.hbase.master.normalizer.SimpleRegionNormalizer.DEFAULT_MERGE_MIN_REGION_AGE_DAYS; 022import static org.apache.hadoop.hbase.master.normalizer.SimpleRegionNormalizer.MERGE_ENABLED_KEY; 023import static org.apache.hadoop.hbase.master.normalizer.SimpleRegionNormalizer.MERGE_MIN_REGION_AGE_DAYS_KEY; 024import static org.apache.hadoop.hbase.master.normalizer.SimpleRegionNormalizer.MERGE_MIN_REGION_SIZE_MB_KEY; 025import static org.apache.hadoop.hbase.master.normalizer.SimpleRegionNormalizer.MIN_REGION_COUNT_KEY; 026import static org.apache.hadoop.hbase.master.normalizer.SimpleRegionNormalizer.SPLIT_ENABLED_KEY; 027import static org.hamcrest.MatcherAssert.assertThat; 028import static org.hamcrest.Matchers.contains; 029import static org.hamcrest.Matchers.empty; 030import static org.hamcrest.Matchers.everyItem; 031import static org.hamcrest.Matchers.greaterThanOrEqualTo; 032import static org.hamcrest.Matchers.instanceOf; 033import static org.hamcrest.Matchers.iterableWithSize; 034import static org.hamcrest.Matchers.not; 035import static org.junit.Assert.assertEquals; 036import static org.junit.Assert.assertFalse; 037import static org.junit.Assert.assertTrue; 038import static org.mockito.ArgumentMatchers.any; 039import static org.mockito.Mockito.RETURNS_DEEP_STUBS; 040import static org.mockito.Mockito.when; 041import java.time.Instant; 042import java.time.Period; 043import java.util.ArrayList; 044import java.util.Collections; 045import java.util.HashMap; 046import java.util.List; 047import java.util.Map; 048import org.apache.hadoop.conf.Configuration; 049import org.apache.hadoop.hbase.HBaseClassTestRule; 050import org.apache.hadoop.hbase.HBaseConfiguration; 051import org.apache.hadoop.hbase.RegionMetrics; 052import org.apache.hadoop.hbase.ServerName; 053import org.apache.hadoop.hbase.Size; 054import org.apache.hadoop.hbase.TableName; 055import org.apache.hadoop.hbase.client.RegionInfo; 056import org.apache.hadoop.hbase.client.RegionInfoBuilder; 057import org.apache.hadoop.hbase.master.MasterServices; 058import org.apache.hadoop.hbase.master.RegionState; 059import org.apache.hadoop.hbase.testclassification.MasterTests; 060import org.apache.hadoop.hbase.testclassification.SmallTests; 061import org.apache.hadoop.hbase.util.Bytes; 062import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 063import org.junit.Before; 064import org.junit.ClassRule; 065import org.junit.Rule; 066import org.junit.Test; 067import org.junit.experimental.categories.Category; 068import org.junit.rules.TestName; 069import org.mockito.Mockito; 070 071/** 072 * Tests logic of {@link SimpleRegionNormalizer}. 073 */ 074@Category({MasterTests.class, SmallTests.class}) 075public class TestSimpleRegionNormalizer { 076 077 @ClassRule 078 public static final HBaseClassTestRule CLASS_RULE = 079 HBaseClassTestRule.forClass(TestSimpleRegionNormalizer.class); 080 081 private Configuration conf; 082 private SimpleRegionNormalizer normalizer; 083 private MasterServices masterServices; 084 085 @Rule 086 public TestName name = new TestName(); 087 088 @Before 089 public void before() { 090 conf = HBaseConfiguration.create(); 091 } 092 093 @Test 094 public void testNoNormalizationForMetaTable() { 095 TableName testTable = TableName.META_TABLE_NAME; 096 List<RegionInfo> RegionInfo = new ArrayList<>(); 097 Map<byte[], Integer> regionSizes = new HashMap<>(); 098 099 setupMocksForNormalizer(regionSizes, RegionInfo); 100 List<NormalizationPlan> plans = normalizer.computePlansForTable(testTable); 101 assertThat(plans, empty()); 102 } 103 104 @Test 105 public void testNoNormalizationIfTooFewRegions() { 106 final TableName tableName = TableName.valueOf(name.getMethodName()); 107 final List<RegionInfo> regionInfos = createRegionInfos(tableName, 2); 108 final Map<byte[], Integer> regionSizes = createRegionSizesMap(regionInfos, 10, 15); 109 setupMocksForNormalizer(regionSizes, regionInfos); 110 111 List<NormalizationPlan> plans = normalizer.computePlansForTable(tableName); 112 assertThat(plans, empty()); 113 } 114 115 @Test 116 public void testNoNormalizationOnNormalizedCluster() { 117 final TableName tableName = TableName.valueOf(name.getMethodName()); 118 final List<RegionInfo> regionInfos = createRegionInfos(tableName, 4); 119 final Map<byte[], Integer> regionSizes = createRegionSizesMap(regionInfos, 10, 15, 8, 10); 120 setupMocksForNormalizer(regionSizes, regionInfos); 121 122 List<NormalizationPlan> plans = normalizer.computePlansForTable(tableName); 123 assertThat(plans, empty()); 124 } 125 126 private void noNormalizationOnTransitioningRegions(final RegionState.State state) { 127 final TableName tableName = TableName.valueOf(name.getMethodName()); 128 final List<RegionInfo> regionInfos = createRegionInfos(tableName, 3); 129 final Map<byte[], Integer> regionSizes = createRegionSizesMap(regionInfos, 10, 1, 100); 130 131 setupMocksForNormalizer(regionSizes, regionInfos); 132 when(masterServices.getAssignmentManager().getRegionStates() 133 .getRegionState(any(RegionInfo.class))) 134 .thenReturn(RegionState.createForTesting(null, state)); 135 assertThat(normalizer.getMinRegionCount(), greaterThanOrEqualTo(regionInfos.size())); 136 137 List<NormalizationPlan> plans = normalizer.computePlansForTable(tableName); 138 assertThat(format("Unexpected plans for RegionState %s", state), plans, empty()); 139 } 140 141 @Test 142 public void testNoNormalizationOnMergingNewRegions() { 143 noNormalizationOnTransitioningRegions(RegionState.State.MERGING_NEW); 144 } 145 146 @Test 147 public void testNoNormalizationOnMergingRegions() { 148 noNormalizationOnTransitioningRegions(RegionState.State.MERGING); 149 } 150 151 @Test 152 public void testNoNormalizationOnMergedRegions() { 153 noNormalizationOnTransitioningRegions(RegionState.State.MERGED); 154 } 155 156 @Test 157 public void testNoNormalizationOnSplittingNewRegions() { 158 noNormalizationOnTransitioningRegions(RegionState.State.SPLITTING_NEW); 159 } 160 161 @Test 162 public void testNoNormalizationOnSplittingRegions() { 163 noNormalizationOnTransitioningRegions(RegionState.State.SPLITTING); 164 } 165 166 @Test 167 public void testNoNormalizationOnSplitRegions() { 168 noNormalizationOnTransitioningRegions(RegionState.State.SPLIT); 169 } 170 171 @Test 172 public void testMergeOfSmallRegions() { 173 final TableName tableName = TableName.valueOf(name.getMethodName()); 174 final List<RegionInfo> regionInfos = createRegionInfos(tableName, 5); 175 final Map<byte[], Integer> regionSizes = 176 createRegionSizesMap(regionInfos, 15, 5, 5, 15, 16); 177 setupMocksForNormalizer(regionSizes, regionInfos); 178 179 List<NormalizationPlan> plans = normalizer.computePlansForTable(tableName); 180 assertThat(plans.get(0), instanceOf(MergeNormalizationPlan.class)); 181 MergeNormalizationPlan plan = (MergeNormalizationPlan) plans.get(0); 182 assertEquals(regionInfos.get(1), plan.getFirstRegion()); 183 assertEquals(regionInfos.get(2), plan.getSecondRegion()); 184 } 185 186 // Test for situation illustrated in HBASE-14867 187 @Test 188 public void testMergeOfSecondSmallestRegions() { 189 final TableName tableName = TableName.valueOf(name.getMethodName()); 190 final List<RegionInfo> regionInfos = createRegionInfos(tableName, 6); 191 final Map<byte[], Integer> regionSizes = 192 createRegionSizesMap(regionInfos, 1, 10000, 10000, 10000, 2700, 2700); 193 setupMocksForNormalizer(regionSizes, regionInfos); 194 195 List<NormalizationPlan> plans = normalizer.computePlansForTable(tableName); 196 assertThat(plans.get(0), instanceOf(MergeNormalizationPlan.class)); 197 MergeNormalizationPlan plan = (MergeNormalizationPlan) plans.get(0); 198 assertEquals(regionInfos.get(4), plan.getFirstRegion()); 199 assertEquals(regionInfos.get(5), plan.getSecondRegion()); 200 } 201 202 @Test 203 public void testMergeOfSmallNonAdjacentRegions() { 204 final TableName tableName = TableName.valueOf(name.getMethodName()); 205 final List<RegionInfo> regionInfos = createRegionInfos(tableName, 5); 206 final Map<byte[], Integer> regionSizes = 207 createRegionSizesMap(regionInfos, 15, 5, 16, 15, 5); 208 setupMocksForNormalizer(regionSizes, regionInfos); 209 210 List<NormalizationPlan> plans = normalizer.computePlansForTable(tableName); 211 assertThat(plans, empty()); 212 } 213 214 @Test 215 public void testSplitOfLargeRegion() { 216 final TableName tableName = TableName.valueOf(name.getMethodName()); 217 final List<RegionInfo> regionInfos = createRegionInfos(tableName, 4); 218 final Map<byte[], Integer> regionSizes = 219 createRegionSizesMap(regionInfos, 8, 6, 10, 30); 220 setupMocksForNormalizer(regionSizes, regionInfos); 221 222 List<NormalizationPlan> plans = normalizer.computePlansForTable(tableName); 223 assertThat(plans.get(0), instanceOf(SplitNormalizationPlan.class)); 224 SplitNormalizationPlan plan = (SplitNormalizationPlan) plans.get(0); 225 assertEquals(regionInfos.get(3), plan.getRegionInfo()); 226 } 227 228 @Test 229 public void testSplitWithTargetRegionCount() throws Exception { 230 final TableName tableName = TableName.valueOf(name.getMethodName()); 231 final List<RegionInfo> regionInfos = createRegionInfos(tableName, 6); 232 final Map<byte[], Integer> regionSizes = 233 createRegionSizesMap(regionInfos, 20, 40, 60, 80, 100, 120); 234 setupMocksForNormalizer(regionSizes, regionInfos); 235 236 // test when target region size is 20 237 when(masterServices.getTableDescriptors().get(any()).getNormalizerTargetRegionSize()) 238 .thenReturn(20L); 239 List<NormalizationPlan> plans = normalizer.computePlansForTable(tableName); 240 assertThat(plans, iterableWithSize(4)); 241 assertThat(plans, everyItem(instanceOf(SplitNormalizationPlan.class))); 242 243 // test when target region size is 200 244 when(masterServices.getTableDescriptors().get(any()).getNormalizerTargetRegionSize()) 245 .thenReturn(200L); 246 plans = normalizer.computePlansForTable(tableName); 247 assertThat(plans, iterableWithSize(2)); 248 assertTrue(plans.get(0) instanceof MergeNormalizationPlan); 249 MergeNormalizationPlan plan = (MergeNormalizationPlan) plans.get(0); 250 assertEquals(regionInfos.get(0), plan.getFirstRegion()); 251 assertEquals(regionInfos.get(1), plan.getSecondRegion()); 252 } 253 254 @Test 255 public void testSplitWithTargetRegionSize() throws Exception { 256 final TableName tableName = TableName.valueOf(name.getMethodName()); 257 final List<RegionInfo> regionInfos = createRegionInfos(tableName, 4); 258 final Map<byte[], Integer> regionSizes = createRegionSizesMap(regionInfos, 20, 40, 60, 80); 259 setupMocksForNormalizer(regionSizes, regionInfos); 260 261 // test when target region count is 8 262 when(masterServices.getTableDescriptors().get(any()).getNormalizerTargetRegionCount()) 263 .thenReturn(8); 264 List<NormalizationPlan> plans = normalizer.computePlansForTable(tableName); 265 assertThat(plans, iterableWithSize(2)); 266 assertThat(plans, everyItem(instanceOf(SplitNormalizationPlan.class))); 267 268 // test when target region count is 3 269 when(masterServices.getTableDescriptors().get(any()).getNormalizerTargetRegionCount()) 270 .thenReturn(3); 271 plans = normalizer.computePlansForTable(tableName); 272 assertThat(plans, contains(instanceOf(MergeNormalizationPlan.class))); 273 MergeNormalizationPlan plan = (MergeNormalizationPlan) plans.get(0); 274 assertEquals(regionInfos.get(0), plan.getFirstRegion()); 275 assertEquals(regionInfos.get(1), plan.getSecondRegion()); 276 } 277 278 @Test 279 public void testHonorsSplitEnabled() { 280 conf.setBoolean(SPLIT_ENABLED_KEY, true); 281 final TableName tableName = TableName.valueOf(name.getMethodName()); 282 final List<RegionInfo> regionInfos = createRegionInfos(tableName, 5); 283 final Map<byte[], Integer> regionSizes = 284 createRegionSizesMap(regionInfos, 5, 5, 20, 5, 5); 285 setupMocksForNormalizer(regionSizes, regionInfos); 286 assertThat( 287 normalizer.computePlansForTable(tableName), 288 contains(instanceOf(SplitNormalizationPlan.class))); 289 290 conf.setBoolean(SPLIT_ENABLED_KEY, false); 291 setupMocksForNormalizer(regionSizes, regionInfos); 292 assertThat(normalizer.computePlansForTable(tableName), empty()); 293 } 294 295 @Test 296 public void testHonorsMergeEnabled() { 297 conf.setBoolean(MERGE_ENABLED_KEY, true); 298 final TableName tableName = TableName.valueOf(name.getMethodName()); 299 final List<RegionInfo> regionInfos = createRegionInfos(tableName, 5); 300 final Map<byte[], Integer> regionSizes = 301 createRegionSizesMap(regionInfos, 20, 5, 5, 20, 20); 302 setupMocksForNormalizer(regionSizes, regionInfos); 303 assertThat( 304 normalizer.computePlansForTable(tableName), 305 contains(instanceOf(MergeNormalizationPlan.class))); 306 307 conf.setBoolean(MERGE_ENABLED_KEY, false); 308 setupMocksForNormalizer(regionSizes, regionInfos); 309 assertThat(normalizer.computePlansForTable(tableName), empty()); 310 } 311 312 @Test 313 public void testHonorsMinimumRegionCount() { 314 conf.setInt(MIN_REGION_COUNT_KEY, 1); 315 final TableName tableName = TableName.valueOf(name.getMethodName()); 316 final List<RegionInfo> regionInfos = createRegionInfos(tableName, 3); 317 // create a table topology that results in both a merge plan and a split plan. Assert that the 318 // merge is only created when the when the number of table regions is above the region count 319 // threshold, and that the split plan is create in both cases. 320 final Map<byte[], Integer> regionSizes = createRegionSizesMap(regionInfos, 1, 1, 10); 321 setupMocksForNormalizer(regionSizes, regionInfos); 322 323 List<NormalizationPlan> plans = normalizer.computePlansForTable(tableName); 324 assertThat(plans, contains( 325 instanceOf(SplitNormalizationPlan.class), 326 instanceOf(MergeNormalizationPlan.class))); 327 SplitNormalizationPlan splitPlan = (SplitNormalizationPlan) plans.get(0); 328 assertEquals(regionInfos.get(2), splitPlan.getRegionInfo()); 329 MergeNormalizationPlan mergePlan = (MergeNormalizationPlan) plans.get(1); 330 assertEquals(regionInfos.get(0), mergePlan.getFirstRegion()); 331 assertEquals(regionInfos.get(1), mergePlan.getSecondRegion()); 332 333 // have to call setupMocks again because we don't have dynamic config update on normalizer. 334 conf.setInt(MIN_REGION_COUNT_KEY, 4); 335 setupMocksForNormalizer(regionSizes, regionInfos); 336 plans = normalizer.computePlansForTable(tableName); 337 assertThat(plans, contains(instanceOf(SplitNormalizationPlan.class))); 338 splitPlan = (SplitNormalizationPlan) plans.get(0); 339 assertEquals(regionInfos.get(2), splitPlan.getRegionInfo()); 340 } 341 342 @Test 343 public void testHonorsMergeMinRegionAge() { 344 conf.setInt(MERGE_MIN_REGION_AGE_DAYS_KEY, 7); 345 final TableName tableName = TableName.valueOf(name.getMethodName()); 346 final List<RegionInfo> regionInfos = createRegionInfos(tableName, 4); 347 final Map<byte[], Integer> regionSizes = 348 createRegionSizesMap(regionInfos, 1, 1, 10, 10); 349 setupMocksForNormalizer(regionSizes, regionInfos); 350 assertEquals(Period.ofDays(7), normalizer.getMergeMinRegionAge()); 351 assertThat( 352 normalizer.computePlansForTable(tableName), 353 everyItem(not(instanceOf(MergeNormalizationPlan.class)))); 354 355 // have to call setupMocks again because we don't have dynamic config update on normalizer. 356 conf.unset(MERGE_MIN_REGION_AGE_DAYS_KEY); 357 setupMocksForNormalizer(regionSizes, regionInfos); 358 assertEquals( 359 Period.ofDays(DEFAULT_MERGE_MIN_REGION_AGE_DAYS), normalizer.getMergeMinRegionAge()); 360 final List<NormalizationPlan> plans = normalizer.computePlansForTable(tableName); 361 assertThat(plans, not(empty())); 362 assertThat(plans, everyItem(instanceOf(MergeNormalizationPlan.class))); 363 } 364 365 @Test 366 public void testHonorsMergeMinRegionSize() { 367 conf.setBoolean(SPLIT_ENABLED_KEY, false); 368 final TableName tableName = TableName.valueOf(name.getMethodName()); 369 final List<RegionInfo> regionInfos = createRegionInfos(tableName, 5); 370 final Map<byte[], Integer> regionSizes = createRegionSizesMap(regionInfos, 1, 2, 0, 10, 10); 371 setupMocksForNormalizer(regionSizes, regionInfos); 372 373 assertFalse(normalizer.isSplitEnabled()); 374 assertEquals(1, normalizer.getMergeMinRegionSizeMb()); 375 final List<NormalizationPlan> plans = normalizer.computePlansForTable(tableName); 376 assertThat(plans, everyItem(instanceOf(MergeNormalizationPlan.class))); 377 assertThat(plans, iterableWithSize(1)); 378 final MergeNormalizationPlan plan = (MergeNormalizationPlan) plans.get(0); 379 assertEquals(regionInfos.get(0), plan.getFirstRegion()); 380 assertEquals(regionInfos.get(1), plan.getSecondRegion()); 381 382 conf.setInt(MERGE_MIN_REGION_SIZE_MB_KEY, 3); 383 setupMocksForNormalizer(regionSizes, regionInfos); 384 assertEquals(3, normalizer.getMergeMinRegionSizeMb()); 385 assertThat(normalizer.computePlansForTable(tableName), empty()); 386 } 387 388 // This test is to make sure that normalizer is only going to merge adjacent regions. 389 @Test 390 public void testNormalizerCannotMergeNonAdjacentRegions() { 391 final TableName tableName = TableName.valueOf(name.getMethodName()); 392 // create 5 regions with sizes to trigger merge of small regions. region ranges are: 393 // [, "aa"), ["aa", "aa1"), ["aa1", "aa1!"), ["aa1!", "aa2"), ["aa2", ) 394 // Region ["aa", "aa1") and ["aa1!", "aa2") are not adjacent, they are not supposed to 395 // merged. 396 final byte[][] keys = { 397 null, 398 Bytes.toBytes("aa"), 399 Bytes.toBytes("aa1!"), 400 Bytes.toBytes("aa1"), 401 Bytes.toBytes("aa2"), 402 null, 403 }; 404 final List<RegionInfo> regionInfos = createRegionInfos(tableName, keys); 405 final Map<byte[], Integer> regionSizes = createRegionSizesMap(regionInfos, 3, 1, 1, 3, 5); 406 setupMocksForNormalizer(regionSizes, regionInfos); 407 408 // Compute the plan, no merge plan returned as they are not adjacent. 409 List<NormalizationPlan> plans = normalizer.computePlansForTable(tableName); 410 assertThat(plans, empty()); 411 } 412 413 @SuppressWarnings("MockitoCast") 414 private void setupMocksForNormalizer(Map<byte[], Integer> regionSizes, 415 List<RegionInfo> regionInfoList) { 416 masterServices = Mockito.mock(MasterServices.class, RETURNS_DEEP_STUBS); 417 418 // for simplicity all regions are assumed to be on one server; doesn't matter to us 419 ServerName sn = ServerName.valueOf("localhost", 0, 0L); 420 when(masterServices.getAssignmentManager().getRegionStates() 421 .getRegionsOfTable(any())).thenReturn(regionInfoList); 422 when(masterServices.getAssignmentManager().getRegionStates() 423 .getRegionServerOfRegion(any())).thenReturn(sn); 424 when(masterServices.getAssignmentManager().getRegionStates() 425 .getRegionState(any(RegionInfo.class))).thenReturn( 426 RegionState.createForTesting(null, RegionState.State.OPEN)); 427 428 for (Map.Entry<byte[], Integer> region : regionSizes.entrySet()) { 429 RegionMetrics regionLoad = Mockito.mock(RegionMetrics.class); 430 when(regionLoad.getRegionName()).thenReturn(region.getKey()); 431 when(regionLoad.getStoreFileSize()) 432 .thenReturn(new Size(region.getValue(), Size.Unit.MEGABYTE)); 433 434 // this is possibly broken with jdk9, unclear if false positive or not 435 // suppress it for now, fix it when we get to running tests on 9 436 // see: http://errorprone.info/bugpattern/MockitoCast 437 when((Object) masterServices.getServerManager().getLoad(sn) 438 .getRegionMetrics().get(region.getKey())).thenReturn(regionLoad); 439 } 440 441 when(masterServices.isSplitOrMergeEnabled(any())).thenReturn(true); 442 443 normalizer = new SimpleRegionNormalizer(); 444 normalizer.setConf(conf); 445 normalizer.setMasterServices(masterServices); 446 } 447 448 /** 449 * Create a list of {@link RegionInfo}s that represent a region chain of the specified length. 450 */ 451 private static List<RegionInfo> createRegionInfos(final TableName tableName, final int length) { 452 if (length < 1) { 453 throw new IllegalStateException("length must be greater than or equal to 1."); 454 } 455 456 final byte[] startKey = Bytes.toBytes("aaaaa"); 457 final byte[] endKey = Bytes.toBytes("zzzzz"); 458 if (length == 1) { 459 return Collections.singletonList(createRegionInfo(tableName, startKey, endKey)); 460 } 461 462 final byte[][] splitKeys = Bytes.split(startKey, endKey, length - 1); 463 final List<RegionInfo> ret = new ArrayList<>(length); 464 for (int i = 0; i < splitKeys.length - 1; i++) { 465 ret.add(createRegionInfo(tableName, splitKeys[i], splitKeys[i+1])); 466 } 467 return ret; 468 } 469 470 private static RegionInfo createRegionInfo(final TableName tableName, final byte[] startKey, 471 final byte[] endKey) { 472 return RegionInfoBuilder.newBuilder(tableName) 473 .setStartKey(startKey) 474 .setEndKey(endKey) 475 .setRegionId(generateRegionId()) 476 .build(); 477 } 478 479 private static long generateRegionId() { 480 return Instant.ofEpochMilli(EnvironmentEdgeManager.currentTime()) 481 .minus(Period.ofDays(DEFAULT_MERGE_MIN_REGION_AGE_DAYS + 1)) 482 .toEpochMilli(); 483 } 484 485 private static List<RegionInfo> createRegionInfos(final TableName tableName, 486 final byte[][] splitKeys) { 487 final List<RegionInfo> ret = new ArrayList<>(splitKeys.length); 488 for (int i = 0; i < splitKeys.length - 1; i++) { 489 ret.add(createRegionInfo(tableName, splitKeys[i], splitKeys[i+1])); 490 } 491 return ret; 492 } 493 494 private static Map<byte[], Integer> createRegionSizesMap(final List<RegionInfo> regionInfos, 495 int... sizes) { 496 if (regionInfos.size() != sizes.length) { 497 throw new IllegalStateException("Parameter lengths must match."); 498 } 499 500 final Map<byte[], Integer> ret = new HashMap<>(regionInfos.size()); 501 for (int i = 0; i < regionInfos.size(); i++) { 502 ret.put(regionInfos.get(i).getRegionName(), sizes[i]); 503 } 504 return ret; 505 } 506}