View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.master.normalizer;
20  
21  import static org.apache.hadoop.hbase.master.normalizer.SimpleRegionNormalizer.DEFAULT_MERGE_MIN_REGION_AGE_DAYS;
22  import static org.apache.hadoop.hbase.master.normalizer.SimpleRegionNormalizer.MERGE_ENABLED_KEY;
23  import static org.apache.hadoop.hbase.master.normalizer.SimpleRegionNormalizer.MERGE_MIN_REGION_AGE_DAYS_KEY;
24  import static org.apache.hadoop.hbase.master.normalizer.SimpleRegionNormalizer.MERGE_MIN_REGION_SIZE_MB_KEY;
25  import static org.apache.hadoop.hbase.master.normalizer.SimpleRegionNormalizer.MIN_REGION_COUNT_KEY;
26  import static org.apache.hadoop.hbase.master.normalizer.SimpleRegionNormalizer.SPLIT_ENABLED_KEY;
27  import static org.junit.Assert.assertEquals;
28  import static org.junit.Assert.assertFalse;
29  import static org.junit.Assert.assertTrue;
30  import static org.mockito.Matchers.any;
31  import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
32  import static org.mockito.Mockito.when;
33  import com.google.protobuf.RpcController;
34  import com.google.protobuf.ServiceException;
35  import java.sql.Timestamp;
36  import java.util.ArrayList;
37  import java.util.Collections;
38  import java.util.HashMap;
39  import java.util.List;
40  import java.util.Map;
41  import java.util.concurrent.TimeUnit;
42  import org.apache.commons.logging.Log;
43  import org.apache.commons.logging.LogFactory;
44  import org.apache.hadoop.conf.Configuration;
45  import org.apache.hadoop.hbase.HBaseConfiguration;
46  import org.apache.hadoop.hbase.HBaseIOException;
47  import org.apache.hadoop.hbase.HRegionInfo;
48  import org.apache.hadoop.hbase.RegionLoad;
49  import org.apache.hadoop.hbase.ServerName;
50  import org.apache.hadoop.hbase.TableName;
51  import org.apache.hadoop.hbase.master.MasterRpcServices;
52  import org.apache.hadoop.hbase.master.MasterServices;
53  import org.apache.hadoop.hbase.master.RegionState;
54  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsSplitOrMergeEnabledRequest;
55  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsSplitOrMergeEnabledResponse;
56  import org.apache.hadoop.hbase.testclassification.SmallTests;
57  import org.apache.hadoop.hbase.util.Bytes;
58  import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
59  import org.junit.Before;
60  import org.junit.Rule;
61  import org.junit.Test;
62  import org.junit.experimental.categories.Category;
63  import org.junit.rules.TestName;
64  import org.mockito.Mockito;
65  
66  /**
67   * Tests logic of {@link SimpleRegionNormalizer}.
68   */
69  @Category(SmallTests.class)
70  public class TestSimpleRegionNormalizer {
71    private static final Log LOG = LogFactory.getLog(TestSimpleRegionNormalizer.class);
72  
73    private static SimpleRegionNormalizer normalizer;
74    private static Configuration conf;
75  
76    // mocks
77    private static MasterServices masterServices;
78    private static MasterRpcServices masterRpcServices;
79  
80    @Rule
81    public TestName name = new TestName();
82  
83    @Before
84    public void before() {
85      conf = HBaseConfiguration.create();
86    }
87  
88    @Test
89    public void testNoNormalizationForMetaTable() throws HBaseIOException {
90      TableName testTable = TableName.META_TABLE_NAME;
91      List<HRegionInfo> hris = new ArrayList<>();
92      Map<byte[], Integer> regionSizes = new HashMap<>();
93  
94      setupMocksForNormalizer(regionSizes, hris);
95      List<NormalizationPlan> plans = normalizer.computePlansForTable(testTable);
96      assertTrue(plans.isEmpty());
97    }
98  
99    @Test
100   public void testNoNormalizationIfTooFewRegions() throws HBaseIOException {
101     TableName testTable = TableName.valueOf(name.getMethodName());
102     final List<HRegionInfo> regionInfos = createRegionInfos(testTable, 2);
103     Map<byte[], Integer> regionSizes = createRegionSizesMap(regionInfos, 10, 15);
104     setupMocksForNormalizer(regionSizes, regionInfos);
105     List<NormalizationPlan> plans = normalizer.computePlansForTable(testTable);
106 
107     assertTrue(plans.isEmpty());
108   }
109 
110   @Test
111   public void testNoNormalizationOnNormalizedCluster() throws HBaseIOException {
112     TableName testTable = TableName.valueOf(name.getMethodName());
113     List<HRegionInfo> regionInfos = createRegionInfos(testTable, 4);
114     Map<byte[], Integer> regionSizes = createRegionSizesMap(regionInfos, 10, 15, 8, 10);
115 
116     setupMocksForNormalizer(regionSizes, regionInfos);
117     List<NormalizationPlan> plans = normalizer.computePlansForTable(testTable);
118     assertTrue(plans.isEmpty());
119   }
120 
121   @Test
122   public void testMergeOfSmallRegions() throws HBaseIOException {
123     TableName testTable = TableName.valueOf(name.getMethodName());
124     List<HRegionInfo> regionInfos = createRegionInfos(testTable, 5);
125     Map<byte[], Integer> regionSizes = createRegionSizesMap(regionInfos, 15, 5, 5, 15, 16);
126 
127     setupMocksForNormalizer(regionSizes, regionInfos);
128     List<NormalizationPlan> plans = normalizer.computePlansForTable(testTable);
129 
130     NormalizationPlan plan = plans.get(0);
131     assertTrue(plan instanceof MergeNormalizationPlan);
132     assertEquals(regionInfos.get(1), ((MergeNormalizationPlan) plan).getFirstRegion());
133     assertEquals(regionInfos.get(2), ((MergeNormalizationPlan) plan).getSecondRegion());
134   }
135 
136   // Test for situation illustrated in HBASE-14867
137   @Test
138   public void testMergeOfSecondSmallestRegions() throws HBaseIOException {
139     TableName testTable = TableName.valueOf(name.getMethodName());
140     List<HRegionInfo> regionInfos = createRegionInfos(testTable, 6);
141     Map<byte[], Integer> regionSizes =
142         createRegionSizesMap(regionInfos, 1, 10000, 10000, 10000, 2700, 2700);
143 
144     setupMocksForNormalizer(regionSizes, regionInfos);
145     List<NormalizationPlan> plans = normalizer.computePlansForTable(testTable);
146     NormalizationPlan plan = plans.get(0);
147 
148     assertTrue(plan instanceof MergeNormalizationPlan);
149     assertEquals(regionInfos.get(4), ((MergeNormalizationPlan) plan).getFirstRegion());
150     assertEquals(regionInfos.get(5), ((MergeNormalizationPlan) plan).getSecondRegion());
151   }
152 
153   @Test
154   public void testMergeOfSmallNonAdjacentRegions() throws HBaseIOException {
155     TableName testTable = TableName.valueOf(name.getMethodName());
156     List<HRegionInfo> regionInfos = createRegionInfos(testTable, 5);
157     Map<byte[], Integer> regionSizes = createRegionSizesMap(regionInfos, 15, 5, 16, 15, 5);
158 
159     setupMocksForNormalizer(regionSizes, regionInfos);
160     List<NormalizationPlan> plans = normalizer.computePlansForTable(testTable);
161 
162     assertTrue(plans.isEmpty());
163   }
164 
165   @Test
166   public void testSplitOfLargeRegion() throws HBaseIOException {
167     TableName testTable = TableName.valueOf(name.getMethodName());
168     List<HRegionInfo> regionInfos = createRegionInfos(testTable, 4);
169     Map<byte[], Integer> regionSizes = createRegionSizesMap(regionInfos, 8, 6, 10, 30);
170 
171     setupMocksForNormalizer(regionSizes, regionInfos);
172     List<NormalizationPlan> plans = normalizer.computePlansForTable(testTable);
173     NormalizationPlan plan = plans.get(0);
174 
175     assertTrue(plan instanceof SplitNormalizationPlan);
176     assertEquals(regionInfos.get(3), ((SplitNormalizationPlan) plan).getRegionInfo());
177   }
178 
179   @Test
180   public void testSplitWithTargetRegionCount() throws Exception {
181     final TableName tableName = TableName.valueOf(name.getMethodName());
182     List<HRegionInfo> regionInfo = createRegionInfos(tableName, 6);
183     Map<byte[], Integer> regionSizes = createRegionSizesMap(regionInfo, 20, 40, 60, 80, 100, 120);
184     setupMocksForNormalizer(regionSizes, regionInfo);
185 
186     // test when target region size is 20
187     when(
188       masterServices.getTableDescriptors().get((TableName) any()).getNormalizerTargetRegionSize())
189           .thenReturn(20L);
190     List<NormalizationPlan> plans = normalizer.computePlansForTable(tableName);
191     assertEquals(4, plans.size());
192 
193     for (NormalizationPlan plan : plans) {
194       assertTrue(plan instanceof SplitNormalizationPlan);
195     }
196 
197     // test when target region size is 200
198     when(
199       masterServices.getTableDescriptors().get((TableName) any()).getNormalizerTargetRegionSize())
200           .thenReturn(200L);
201     plans = normalizer.computePlansForTable(tableName);
202     assertEquals(2, plans.size());
203     NormalizationPlan plan = plans.get(0);
204     assertTrue(plan instanceof MergeNormalizationPlan);
205     assertEquals(regionInfo.get(0), ((MergeNormalizationPlan) plan).getFirstRegion());
206     assertEquals(regionInfo.get(1), ((MergeNormalizationPlan) plan).getSecondRegion());
207   }
208 
209   @Test
210   public void testSplitWithTargetRegionSize() throws Exception {
211     final TableName tableName = TableName.valueOf(name.getMethodName());
212     final List<HRegionInfo> regionInfos = createRegionInfos(tableName, 4);
213     final Map<byte[], Integer> regionSizes = createRegionSizesMap(regionInfos, 20, 40, 60, 80);
214     setupMocksForNormalizer(regionSizes, regionInfos);
215 
216     // test when target region count is 8
217     when(
218       masterServices.getTableDescriptors().get((TableName) any()).getNormalizerTargetRegionCount())
219           .thenReturn(8);
220     List<NormalizationPlan> plans = normalizer.computePlansForTable(tableName);
221     assertEquals(2, plans.size());
222 
223     for (NormalizationPlan plan : plans) {
224       assertTrue(plan instanceof SplitNormalizationPlan);
225     }
226 
227     // test when target region count is 3
228     when(
229       masterServices.getTableDescriptors().get((TableName) any()).getNormalizerTargetRegionCount())
230           .thenReturn(3);
231     plans = normalizer.computePlansForTable(tableName);
232     assertEquals(1, plans.size());
233     NormalizationPlan plan = plans.get(0);
234     assertTrue(plan instanceof MergeNormalizationPlan);
235     assertEquals(regionInfos.get(0), ((MergeNormalizationPlan) plan).getFirstRegion());
236     assertEquals(regionInfos.get(1), ((MergeNormalizationPlan) plan).getSecondRegion());
237   }
238 
239   @Test
240   public void testHonorsSplitEnabled() throws HBaseIOException {
241     conf.setBoolean(SPLIT_ENABLED_KEY, true);
242     final TableName tableName = TableName.valueOf(name.getMethodName());
243     final List<HRegionInfo> regionInfos = createRegionInfos(tableName, 5);
244     final Map<byte[], Integer> regionSizes = createRegionSizesMap(regionInfos, 5, 5, 20, 5, 5);
245     setupMocksForNormalizer(regionSizes, regionInfos);
246     List<NormalizationPlan> plans = normalizer.computePlansForTable(tableName);
247     boolean present = false;
248     for (NormalizationPlan plan : plans) {
249       if (plan instanceof SplitNormalizationPlan) {
250         present = true;
251         break;
252       }
253     }
254     assertTrue(present);
255     conf.setBoolean(SPLIT_ENABLED_KEY, false);
256     setupMocksForNormalizer(regionSizes, regionInfos);
257     plans = normalizer.computePlansForTable(tableName);
258     assertTrue(plans.isEmpty());
259   }
260 
261   @Test
262   public void testHonorsMergeEnabled() throws HBaseIOException {
263     conf.setBoolean(MERGE_ENABLED_KEY, true);
264     final TableName tableName = TableName.valueOf(name.getMethodName());
265     final List<HRegionInfo> regionInfos = createRegionInfos(tableName, 5);
266     final Map<byte[], Integer> regionSizes = createRegionSizesMap(regionInfos, 20, 5, 5, 20, 20);
267     setupMocksForNormalizer(regionSizes, regionInfos);
268     List<NormalizationPlan> plans = normalizer.computePlansForTable(tableName);
269     boolean present = false;
270     for (NormalizationPlan plan : plans) {
271       if (plan instanceof MergeNormalizationPlan) {
272         present = true;
273         break;
274       }
275     }
276     assertTrue(present);
277     conf.setBoolean(MERGE_ENABLED_KEY, false);
278     setupMocksForNormalizer(regionSizes, regionInfos);
279     plans = normalizer.computePlansForTable(tableName);
280     assertTrue(plans.isEmpty());
281   }
282 
283   @Test
284   public void testHonorsMinimumRegionCount() throws HBaseIOException {
285     conf.setInt(MIN_REGION_COUNT_KEY, 1);
286     final TableName tableName = TableName.valueOf(name.getMethodName());
287     final List<HRegionInfo> regionInfos = createRegionInfos(tableName, 3);
288     // create a table topology that results in both a merge plan and a split plan. Assert that the
289     // merge is only created when the when the number of table regions is above the region count
290     // threshold, and that the split plan is create in both cases.
291     final Map<byte[], Integer> regionSizes = createRegionSizesMap(regionInfos, 1, 1, 10);
292     setupMocksForNormalizer(regionSizes, regionInfos);
293 
294     List<NormalizationPlan> plans = normalizer.computePlansForTable(tableName);
295     boolean splitPlanPresent = false;
296     boolean mergePlanPresent = false;
297     for (NormalizationPlan plan : plans) {
298       if (plan instanceof MergeNormalizationPlan) {
299         mergePlanPresent = true;
300         break;
301       } else if (plan instanceof SplitNormalizationPlan) {
302         splitPlanPresent = true;
303       }
304     }
305     assertTrue(splitPlanPresent && mergePlanPresent);
306     SplitNormalizationPlan splitPlan = (SplitNormalizationPlan) plans.get(0);
307     assertEquals(regionInfos.get(2), splitPlan.getRegionInfo());
308     MergeNormalizationPlan mergePlan = (MergeNormalizationPlan) plans.get(1);
309     assertEquals(regionInfos.get(0), mergePlan.getFirstRegion());
310     assertEquals(regionInfos.get(1), mergePlan.getSecondRegion());
311 
312     // have to call setupMocks again because we don't have dynamic config update on normalizer.
313     conf.setInt(MIN_REGION_COUNT_KEY, 4);
314     setupMocksForNormalizer(regionSizes, regionInfos);
315     plans = normalizer.computePlansForTable(tableName);
316     splitPlanPresent = false;
317     for (NormalizationPlan plan : plans) {
318       if (plan instanceof SplitNormalizationPlan) {
319         splitPlanPresent = true;
320         break;
321       }
322     }
323     assertTrue(splitPlanPresent);
324     splitPlan = (SplitNormalizationPlan) plans.get(0);
325     assertEquals(regionInfos.get(2), splitPlan.getRegionInfo());
326   }
327 
328   @Test
329   public void testHonorsMergeMinRegionAge() throws HBaseIOException {
330     conf.setInt(MERGE_MIN_REGION_AGE_DAYS_KEY, 7);
331     final TableName tableName = TableName.valueOf(name.getMethodName());
332     final List<HRegionInfo> regionInfos = createRegionInfos(tableName, 4);
333     final Map<byte[], Integer> regionSizes = createRegionSizesMap(regionInfos, 1, 1, 10, 10);
334     setupMocksForNormalizer(regionSizes, regionInfos);
335     assertEquals(7, normalizer.getMergeMinRegionAge());
336     final List<NormalizationPlan> plans = normalizer.computePlansForTable(tableName);
337     for (NormalizationPlan plan : plans) {
338       assertFalse(plan instanceof MergeNormalizationPlan);
339     }
340     // have to call setupMocks again because we don't have dynamic config update on normalizer.
341     conf.unset(MERGE_MIN_REGION_AGE_DAYS_KEY);
342     setupMocksForNormalizer(regionSizes, regionInfos);
343     assertEquals(DEFAULT_MERGE_MIN_REGION_AGE_DAYS, normalizer.getMergeMinRegionAge());
344     final List<NormalizationPlan> plans1 = normalizer.computePlansForTable(tableName);
345     assertTrue(!plans1.isEmpty());
346     for (NormalizationPlan plan : plans) {
347       assertTrue(plan instanceof MergeNormalizationPlan);
348     }
349   }
350 
351   @Test
352   public void testHonorsMergeMinRegionSize() throws HBaseIOException {
353     conf.setBoolean(SPLIT_ENABLED_KEY, false);
354     final TableName tableName = TableName.valueOf(name.getMethodName());
355     final List<HRegionInfo> regionInfos = createRegionInfos(tableName, 5);
356     final Map<byte[], Integer> regionSizes = createRegionSizesMap(regionInfos, 1, 2, 0, 10, 10);
357     setupMocksForNormalizer(regionSizes, regionInfos);
358 
359     assertFalse(normalizer.isSplitEnabled());
360     assertEquals(1, normalizer.getMergeMinRegionSizeMb());
361     final List<NormalizationPlan> plans = normalizer.computePlansForTable(tableName);
362     for (NormalizationPlan plan : plans) {
363       assertTrue(plan instanceof MergeNormalizationPlan);
364     }
365     assertEquals(plans.size(), 1);
366     final MergeNormalizationPlan plan = (MergeNormalizationPlan) plans.get(0);
367     assertEquals(regionInfos.get(0), plan.getFirstRegion());
368     assertEquals(regionInfos.get(1), plan.getSecondRegion());
369 
370     conf.setInt(MERGE_MIN_REGION_SIZE_MB_KEY, 3);
371     setupMocksForNormalizer(regionSizes, regionInfos);
372     assertEquals(3, normalizer.getMergeMinRegionSizeMb());
373     assertTrue(normalizer.computePlansForTable(tableName).isEmpty());
374   }
375 
376   // This test is to make sure that normalizer is only going to merge adjacent regions.
377   @Test
378   public void testNormalizerCannotMergeNonAdjacentRegions() throws HBaseIOException {
379     final TableName tableName = TableName.valueOf(name.getMethodName());
380     // create 5 regions with sizes to trigger merge of small regions. region ranges are:
381     // [, "aa"), ["aa", "aa1"), ["aa1", "aa1!"), ["aa1!", "aa2"), ["aa2", )
382     // Region ["aa", "aa1") and ["aa1!", "aa2") are not adjacent, they are not supposed to
383     // merged.
384     final byte[][] keys = { null, Bytes.toBytes("aa"), Bytes.toBytes("aa1!"), Bytes.toBytes("aa1"),
385         Bytes.toBytes("aa2"), null, };
386     final List<HRegionInfo> regionInfos = createRegionInfos(tableName, keys);
387     final Map<byte[], Integer> regionSizes = createRegionSizesMap(regionInfos, 3, 1, 1, 3, 5);
388     setupMocksForNormalizer(regionSizes, regionInfos);
389 
390     // Compute the plan, no merge plan returned as they are not adjacent.
391     List<NormalizationPlan> plans = normalizer.computePlansForTable(tableName);
392     assertTrue(plans.isEmpty());
393   }
394 
395   @SuppressWarnings("MockitoCast")
396   protected void setupMocksForNormalizer(Map<byte[], Integer> regionSizes, List<HRegionInfo> hris) {
397     masterServices = Mockito.mock(MasterServices.class, RETURNS_DEEP_STUBS);
398     masterRpcServices = Mockito.mock(MasterRpcServices.class, RETURNS_DEEP_STUBS);
399 
400     // for simplicity all regions are assumed to be on one server; doesn't matter to us
401     ServerName sn = ServerName.valueOf("localhost", 0, 1L);
402     when(masterServices.getAssignmentManager().getRegionStates()
403         .getRegionsOfTable(any(TableName.class))).thenReturn(hris);
404     when(masterServices.getAssignmentManager().getRegionStates()
405         .getRegionServerOfRegion(any(HRegionInfo.class))).thenReturn(sn);
406     when(masterServices.getAssignmentManager().getRegionStates()
407         .isRegionInState(any(HRegionInfo.class), any(RegionState.State.class))).thenReturn(true);
408 
409     for (Map.Entry<byte[], Integer> region : regionSizes.entrySet()) {
410       RegionLoad regionLoad = Mockito.mock(RegionLoad.class);
411       when(regionLoad.getName()).thenReturn(region.getKey());
412       when(regionLoad.getStorefileSizeMB()).thenReturn(region.getValue());
413 
414       // this is possibly broken with jdk9, unclear if false positive or not
415       // suppress it for now, fix it when we get to running tests on 9
416       // see: http://errorprone.info/bugpattern/MockitoCast
417       when((Object) masterServices.getServerManager().getLoad(sn).getRegionsLoad()
418           .get(region.getKey())).thenReturn(regionLoad);
419     }
420     try {
421       when(masterRpcServices.isSplitOrMergeEnabled(any(RpcController.class),
422         any(IsSplitOrMergeEnabledRequest.class)))
423             .thenReturn(IsSplitOrMergeEnabledResponse.newBuilder().setEnabled(true).build());
424     } catch (ServiceException se) {
425       LOG.debug("error setting isSplitOrMergeEnabled switch", se);
426     }
427 
428     normalizer = new SimpleRegionNormalizer();
429     normalizer.setMasterServices(masterServices);
430     normalizer.setMasterRpcServices(masterRpcServices);
431     normalizer.setConf(conf);
432   }
433 
434   /**
435    * Create a list of {@link HRegionInfo}s that represent a region chain of the specified length.
436    */
437   private static List<HRegionInfo> createRegionInfos(final TableName tableName, final int length) {
438     if (length < 1) {
439       throw new IllegalStateException("length must be greater than or equal to 1.");
440     }
441 
442     final byte[] startKey = Bytes.toBytes("aaaaa");
443     final byte[] endKey = Bytes.toBytes("zzzzz");
444     if (length == 1) {
445       return Collections.singletonList(createRegionInfo(tableName, startKey, endKey));
446     }
447 
448     final byte[][] splitKeys = Bytes.split(startKey, endKey, length - 1);
449     final List<HRegionInfo> ret = new ArrayList<>(length);
450     for (int i = 0; i < splitKeys.length - 1; i++) {
451       ret.add(createRegionInfo(tableName, splitKeys[i], splitKeys[i + 1]));
452     }
453     return ret;
454   }
455 
456   private static HRegionInfo createRegionInfo(final TableName tableName, final byte[] startKey,
457       final byte[] endKey) {
458     return new HRegionInfo(tableName, startKey, endKey, false, generateRegionId());
459   }
460 
461   private static long generateRegionId() {
462     final Timestamp currentTime = new Timestamp(EnvironmentEdgeManager.currentTime());
463     return new Timestamp(
464         currentTime.getTime() - TimeUnit.DAYS.toMillis(DEFAULT_MERGE_MIN_REGION_AGE_DAYS + 1))
465             .getTime();
466   }
467 
468   private static List<HRegionInfo> createRegionInfos(final TableName tableName,
469       final byte[][] splitKeys) {
470     final List<HRegionInfo> ret = new ArrayList<>(splitKeys.length);
471     for (int i = 0; i < splitKeys.length - 1; i++) {
472       ret.add(createRegionInfo(tableName, splitKeys[i], splitKeys[i + 1]));
473     }
474     return ret;
475   }
476 
477   private static Map<byte[], Integer> createRegionSizesMap(final List<HRegionInfo> regionInfos,
478       int... sizes) {
479     if (regionInfos.size() != sizes.length) {
480       throw new IllegalStateException("Parameter lengths must match.");
481     }
482 
483     final Map<byte[], Integer> ret = new HashMap<>(regionInfos.size());
484     for (int i = 0; i < regionInfos.size(); i++) {
485       ret.put(regionInfos.get(i).getRegionName(), sizes[i]);
486     }
487     return ret;
488   }
489 }