View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.master.balancer;
19  
20  import static org.junit.Assert.assertEquals;
21  import static org.junit.Assert.assertNotNull;
22  import static org.junit.Assert.assertNull;
23  import static org.junit.Assert.assertTrue;
24  import static org.mockito.Mockito.mock;
25  import static org.mockito.Mockito.when;
26  
27  import java.util.ArrayList;
28  import java.util.Arrays;
29  import java.util.HashMap;
30  import java.util.Iterator;
31  import java.util.List;
32  import java.util.Map;
33  import java.util.Map.Entry;
34  import java.util.Queue;
35  import java.util.TreeMap;
36  
37  import org.apache.commons.logging.Log;
38  import org.apache.commons.logging.LogFactory;
39  import org.apache.hadoop.conf.Configuration;
40  import org.apache.hadoop.hbase.ClusterStatus;
41  import org.apache.hadoop.hbase.HBaseConfiguration;
42  import org.apache.hadoop.hbase.HRegionInfo;
43  import org.apache.hadoop.hbase.RegionLoad;
44  import org.apache.hadoop.hbase.ServerLoad;
45  import org.apache.hadoop.hbase.ServerName;
46  import org.apache.hadoop.hbase.client.RegionReplicaUtil;
47  import org.apache.hadoop.hbase.master.MockNoopMasterServices;
48  import org.apache.hadoop.hbase.master.RackManager;
49  import org.apache.hadoop.hbase.master.RegionPlan;
50  import org.apache.hadoop.hbase.master.balancer.BaseLoadBalancer.Cluster;
51  import org.apache.hadoop.hbase.testclassification.FlakeyTests;
52  import org.apache.hadoop.hbase.testclassification.MediumTests;
53  import org.apache.hadoop.hbase.util.Bytes;
54  import org.junit.Ignore;
55  import org.junit.Test;
56  import org.junit.experimental.categories.Category;
57  
58  @Category({FlakeyTests.class, MediumTests.class})
59  public class TestStochasticLoadBalancer extends BalancerTestBase {
60    public static final String REGION_KEY = "testRegion";
61    private static final Log LOG = LogFactory.getLog(TestStochasticLoadBalancer.class);
62  
63    @Test
64    public void testKeepRegionLoad() throws Exception {
65  
66      ServerName sn = ServerName.valueOf("test:8080", 100);
67      int numClusterStatusToAdd = 20000;
68      for (int i = 0; i < numClusterStatusToAdd; i++) {
69        ServerLoad sl = mock(ServerLoad.class);
70  
71        RegionLoad rl = mock(RegionLoad.class);
72        when(rl.getStores()).thenReturn(i);
73  
74        Map<byte[], RegionLoad> regionLoadMap =
75            new TreeMap<byte[], RegionLoad>(Bytes.BYTES_COMPARATOR);
76        regionLoadMap.put(Bytes.toBytes(REGION_KEY), rl);
77        when(sl.getRegionsLoad()).thenReturn(regionLoadMap);
78  
79        ClusterStatus clusterStatus = mock(ClusterStatus.class);
80        when(clusterStatus.getServers()).thenReturn(Arrays.asList(sn));
81        when(clusterStatus.getLoad(sn)).thenReturn(sl);
82  
83        loadBalancer.setClusterStatus(clusterStatus);
84      }
85  
86      String regionNameAsString = HRegionInfo.getRegionNameAsString(Bytes.toBytes(REGION_KEY));
87      assertTrue(loadBalancer.loads.get(regionNameAsString) != null);
88      assertTrue(loadBalancer.loads.get(regionNameAsString).size() == 15);
89  
90      Queue<RegionLoad> loads = loadBalancer.loads.get(regionNameAsString);
91      int i = 0;
92      while(loads.size() > 0) {
93        RegionLoad rl = loads.remove();
94        assertEquals(i + (numClusterStatusToAdd - 15), rl.getStores());
95        i ++;
96      }
97    }
98  
99    /**
100    * Test the load balancing algorithm.
101    *
102    * Invariant is that all servers should be hosting either floor(average) or
103    * ceiling(average)
104    *
105    * @throws Exception
106    */
107   @Test
108   public void testBalanceCluster() throws Exception {
109 
110     for (int[] mockCluster : clusterStateMocks) {
111       Map<ServerName, List<HRegionInfo>> servers = mockClusterServers(mockCluster);
112       List<ServerAndLoad> list = convertToList(servers);
113       LOG.info("Mock Cluster : " + printMock(list) + " " + printStats(list));
114       List<RegionPlan> plans = loadBalancer.balanceCluster(servers);
115       List<ServerAndLoad> balancedCluster = reconcile(list, plans, servers);
116       LOG.info("Mock Balance : " + printMock(balancedCluster));
117       assertClusterAsBalanced(balancedCluster);
118       List<RegionPlan> secondPlans =  loadBalancer.balanceCluster(servers);
119       assertNull(secondPlans);
120       for (Map.Entry<ServerName, List<HRegionInfo>> entry : servers.entrySet()) {
121         returnRegions(entry.getValue());
122         returnServer(entry.getKey());
123       }
124     }
125   }
126 
127   @Test
128   public void testLocalityCost() throws Exception {
129     Configuration conf = HBaseConfiguration.create();
130     MockNoopMasterServices master = new MockNoopMasterServices();
131     StochasticLoadBalancer.CostFunction
132         costFunction = new StochasticLoadBalancer.LocalityCostFunction(conf, master);
133 
134     for (int[][] clusterRegionLocations : clusterRegionLocationMocks) {
135       MockCluster cluster = new MockCluster(clusterRegionLocations);
136       costFunction.init(cluster);
137       double cost = costFunction.cost();
138 
139       assertEquals(0.5f, cost, 0.001);
140     }
141   }
142 
143   @Test
144   public void testMoveCost() throws Exception {
145     Configuration conf = HBaseConfiguration.create();
146     StochasticLoadBalancer.CostFunction
147         costFunction = new StochasticLoadBalancer.MoveCostFunction(conf);
148     for (int[] mockCluster : clusterStateMocks) {
149       BaseLoadBalancer.Cluster cluster = mockCluster(mockCluster);
150       costFunction.init(cluster);
151       double cost = costFunction.cost();
152       assertEquals(0.0f, cost, 0.001);
153 
154       // cluster region number is smaller than maxMoves=600
155       cluster.setNumRegions(200);
156       cluster.setNumMovedRegions(10);
157       cost = costFunction.cost();
158       assertEquals(0.05f, cost, 0.001);
159       cluster.setNumMovedRegions(100);
160       cost = costFunction.cost();
161       assertEquals(0.5f, cost, 0.001);
162       cluster.setNumMovedRegions(200);
163       cost = costFunction.cost();
164       assertEquals(1.0f, cost, 0.001);
165 
166 
167       // cluster region number is bigger than maxMoves=2500
168       cluster.setNumRegions(10000);
169       cluster.setNumMovedRegions(250);
170       cost = costFunction.cost();
171       assertEquals(0.1f, cost, 0.001);
172       cluster.setNumMovedRegions(1250);
173       cost = costFunction.cost();
174       assertEquals(0.5f, cost, 0.001);
175       cluster.setNumMovedRegions(2500);
176       cost = costFunction.cost();
177       assertEquals(1.0f, cost, 0.01);
178     }
179   }
180 
181   @Test
182   public void testSkewCost() {
183     Configuration conf = HBaseConfiguration.create();
184     StochasticLoadBalancer.CostFunction
185         costFunction = new StochasticLoadBalancer.RegionCountSkewCostFunction(conf);
186     for (int[] mockCluster : clusterStateMocks) {
187       costFunction.init(mockCluster(mockCluster));
188       double cost = costFunction.cost();
189       assertTrue(cost >= 0);
190       assertTrue(cost <= 1.01);
191     }
192 
193     costFunction.init(mockCluster(new int[]{0, 0, 0, 0, 1}));
194     assertEquals(0,costFunction.cost(), 0.01);
195     costFunction.init(mockCluster(new int[]{0, 0, 0, 1, 1}));
196     assertEquals(0, costFunction.cost(), 0.01);
197     costFunction.init(mockCluster(new int[]{0, 0, 1, 1, 1}));
198     assertEquals(0, costFunction.cost(), 0.01);
199     costFunction.init(mockCluster(new int[]{0, 1, 1, 1, 1}));
200     assertEquals(0, costFunction.cost(), 0.01);
201     costFunction.init(mockCluster(new int[]{1, 1, 1, 1, 1}));
202     assertEquals(0, costFunction.cost(), 0.01);
203     costFunction.init(mockCluster(new int[]{10000, 0, 0, 0, 0}));
204     assertEquals(1, costFunction.cost(), 0.01);
205   }
206 
207   @Test
208   public void testCostAfterUndoAction() {
209     final int runs = 10;
210     loadBalancer.setConf(conf);
211     for (int[] mockCluster : clusterStateMocks) {
212       BaseLoadBalancer.Cluster cluster = mockCluster(mockCluster);
213       loadBalancer.initCosts(cluster);
214       for (int i = 0; i != runs; ++i) {
215         final double expectedCost = loadBalancer.computeCost(cluster, Double.MAX_VALUE);
216         Cluster.Action action = loadBalancer.nextAction(cluster);
217         cluster.doAction(action);
218         loadBalancer.updateCostsWithAction(cluster, action);
219         Cluster.Action undoAction = action.undoAction();
220         cluster.doAction(undoAction);
221         loadBalancer.updateCostsWithAction(cluster, undoAction);
222         final double actualCost = loadBalancer.computeCost(cluster, Double.MAX_VALUE);
223         assertEquals(expectedCost, actualCost, 0);
224       }
225     }
226   }
227 
228   @Test
229   public void testTableSkewCost() {
230     Configuration conf = HBaseConfiguration.create();
231     StochasticLoadBalancer.CostFunction
232         costFunction = new StochasticLoadBalancer.TableSkewCostFunction(conf);
233     for (int[] mockCluster : clusterStateMocks) {
234       BaseLoadBalancer.Cluster cluster = mockCluster(mockCluster);
235       costFunction.init(cluster);
236       double cost = costFunction.cost();
237       assertTrue(cost >= 0);
238       assertTrue(cost <= 1.01);
239     }
240   }
241 
242   @Test
243   public void testCostFromArray() {
244     Configuration conf = HBaseConfiguration.create();
245     StochasticLoadBalancer.CostFromRegionLoadFunction
246         costFunction = new StochasticLoadBalancer.MemstoreSizeCostFunction(conf);
247     costFunction.init(mockCluster(new int[]{0, 0, 0, 0, 1}));
248 
249     double[] statOne = new double[100];
250     for (int i =0; i < 100; i++) {
251       statOne[i] = 10;
252     }
253     assertEquals(0, costFunction.costFromArray(statOne), 0.01);
254 
255     double[] statTwo= new double[101];
256     for (int i =0; i < 100; i++) {
257       statTwo[i] = 0;
258     }
259     statTwo[100] = 100;
260     assertEquals(1, costFunction.costFromArray(statTwo), 0.01);
261 
262     double[] statThree = new double[200];
263     for (int i =0; i < 100; i++) {
264       statThree[i] = (0);
265       statThree[i+100] = 100;
266     }
267     assertEquals(0.5, costFunction.costFromArray(statThree), 0.01);
268   }
269 
270   @Test(timeout =  60000)
271   public void testLosingRs() throws Exception {
272     int numNodes = 3;
273     int numRegions = 20;
274     int numRegionsPerServer = 3; //all servers except one
275     int replication = 1;
276     int numTables = 2;
277 
278     Map<ServerName, List<HRegionInfo>> serverMap =
279         createServerMap(numNodes, numRegions, numRegionsPerServer, replication, numTables);
280     List<ServerAndLoad> list = convertToList(serverMap);
281 
282 
283     List<RegionPlan> plans = loadBalancer.balanceCluster(serverMap);
284     assertNotNull(plans);
285 
286     // Apply the plan to the mock cluster.
287     List<ServerAndLoad> balancedCluster = reconcile(list, plans, serverMap);
288 
289     assertClusterAsBalanced(balancedCluster);
290 
291     ServerName sn = serverMap.keySet().toArray(new ServerName[serverMap.size()])[0];
292 
293     ServerName deadSn = ServerName.valueOf(sn.getHostname(), sn.getPort(), sn.getStartcode() - 100);
294 
295     serverMap.put(deadSn, new ArrayList<HRegionInfo>(0));
296 
297     plans = loadBalancer.balanceCluster(serverMap);
298     assertNull(plans);
299   }
300 
301   @Test
302   public void testReplicaCost() {
303     Configuration conf = HBaseConfiguration.create();
304     StochasticLoadBalancer.CostFunction
305         costFunction = new StochasticLoadBalancer.RegionReplicaHostCostFunction(conf);
306     for (int[] mockCluster : clusterStateMocks) {
307       BaseLoadBalancer.Cluster cluster = mockCluster(mockCluster);
308       costFunction.init(cluster);
309       double cost = costFunction.cost();
310       assertTrue(cost >= 0);
311       assertTrue(cost <= 1.01);
312     }
313   }
314 
315   @Test
316   public void testReplicaCostForReplicas() {
317     Configuration conf = HBaseConfiguration.create();
318     StochasticLoadBalancer.CostFunction
319         costFunction = new StochasticLoadBalancer.RegionReplicaHostCostFunction(conf);
320 
321     int [] servers = new int[] {3,3,3,3,3};
322     TreeMap<ServerName, List<HRegionInfo>> clusterState = mockClusterServers(servers);
323 
324     BaseLoadBalancer.Cluster cluster;
325 
326     cluster = new BaseLoadBalancer.Cluster(clusterState, null, null, null);
327     costFunction.init(cluster);
328     double costWithoutReplicas = costFunction.cost();
329     assertEquals(0, costWithoutReplicas, 0);
330 
331     // replicate the region from first server to the last server
332     HRegionInfo replica1 = RegionReplicaUtil.getRegionInfoForReplica(
333       clusterState.firstEntry().getValue().get(0),1);
334     clusterState.lastEntry().getValue().add(replica1);
335 
336     cluster = new BaseLoadBalancer.Cluster(clusterState, null, null, null);
337     costFunction.init(cluster);
338     double costWith1ReplicaDifferentServer = costFunction.cost();
339 
340     assertEquals(0, costWith1ReplicaDifferentServer, 0);
341 
342     // add a third replica to the last server
343     HRegionInfo replica2 = RegionReplicaUtil.getRegionInfoForReplica(replica1, 2);
344     clusterState.lastEntry().getValue().add(replica2);
345 
346     cluster = new BaseLoadBalancer.Cluster(clusterState, null, null, null);
347     costFunction.init(cluster);
348     double costWith1ReplicaSameServer = costFunction.cost();
349 
350     assertTrue(costWith1ReplicaDifferentServer < costWith1ReplicaSameServer);
351 
352     // test with replication = 4 for following:
353 
354     HRegionInfo replica3;
355     Iterator<Entry<ServerName, List<HRegionInfo>>> it;
356     Entry<ServerName, List<HRegionInfo>> entry;
357 
358     clusterState = mockClusterServers(servers);
359     it = clusterState.entrySet().iterator();
360     entry = it.next(); //first server
361     HRegionInfo hri = entry.getValue().get(0);
362     replica1 = RegionReplicaUtil.getRegionInfoForReplica(hri, 1);
363     replica2 = RegionReplicaUtil.getRegionInfoForReplica(hri, 2);
364     replica3 = RegionReplicaUtil.getRegionInfoForReplica(hri, 3);
365     entry.getValue().add(replica1);
366     entry.getValue().add(replica2);
367     it.next().getValue().add(replica3); //2nd server
368 
369     cluster = new BaseLoadBalancer.Cluster(clusterState, null, null, null);
370     costFunction.init(cluster);
371     double costWith3ReplicasSameServer = costFunction.cost();
372 
373     clusterState = mockClusterServers(servers);
374     hri = clusterState.firstEntry().getValue().get(0);
375     replica1 = RegionReplicaUtil.getRegionInfoForReplica(hri, 1);
376     replica2 = RegionReplicaUtil.getRegionInfoForReplica(hri, 2);
377     replica3 = RegionReplicaUtil.getRegionInfoForReplica(hri, 3);
378 
379     clusterState.firstEntry().getValue().add(replica1);
380     clusterState.lastEntry().getValue().add(replica2);
381     clusterState.lastEntry().getValue().add(replica3);
382 
383     cluster = new BaseLoadBalancer.Cluster(clusterState, null, null, null);
384     costFunction.init(cluster);
385     double costWith2ReplicasOnTwoServers = costFunction.cost();
386 
387     assertTrue(costWith2ReplicasOnTwoServers < costWith3ReplicasSameServer);
388   }
389 
390   @Test
391   public void testNeedsBalanceForColocatedReplicas() {
392     // check for the case where there are two hosts and with one rack, and where
393     // both the replicas are hosted on the same server
394     List<HRegionInfo> regions = randomRegions(1);
395     ServerName s1 = ServerName.valueOf("host1", 1000, 11111);
396     ServerName s2 = ServerName.valueOf("host11", 1000, 11111);
397     Map<ServerName, List<HRegionInfo>> map = new HashMap<ServerName, List<HRegionInfo>>();
398     map.put(s1, regions);
399     regions.add(RegionReplicaUtil.getRegionInfoForReplica(regions.get(0), 1));
400     // until the step above s1 holds two replicas of a region
401     regions = randomRegions(1);
402     map.put(s2, regions);
403     assertTrue(loadBalancer.needsBalance(new Cluster(map, null, null, null)));
404     // check for the case where there are two hosts on the same rack and there are two racks
405     // and both the replicas are on the same rack
406     map.clear();
407     regions = randomRegions(1);
408     List<HRegionInfo> regionsOnS2 = new ArrayList<HRegionInfo>(1);
409     regionsOnS2.add(RegionReplicaUtil.getRegionInfoForReplica(regions.get(0), 1));
410     map.put(s1, regions);
411     map.put(s2, regionsOnS2);
412     // add another server so that the cluster has some host on another rack
413     map.put(ServerName.valueOf("host2", 1000, 11111), randomRegions(1));
414     assertTrue(loadBalancer.needsBalance(new Cluster(map, null, null,
415         new ForTestRackManagerOne())));
416   }
417 
418   @Test (timeout = 60000)
419   public void testSmallCluster() {
420     int numNodes = 10;
421     int numRegions = 1000;
422     int numRegionsPerServer = 40; //all servers except one
423     int replication = 1;
424     int numTables = 10;
425     testWithCluster(numNodes, numRegions, numRegionsPerServer, replication, numTables, true, true);
426   }
427 
428   @Test (timeout = 60000)
429   public void testSmallCluster2() {
430     int numNodes = 20;
431     int numRegions = 2000;
432     int numRegionsPerServer = 40; //all servers except one
433     int replication = 1;
434     int numTables = 10;
435     testWithCluster(numNodes, numRegions, numRegionsPerServer, replication, numTables, true, true);
436   }
437 
438   @Test (timeout = 60000)
439   public void testSmallCluster3() {
440     int numNodes = 20;
441     int numRegions = 2000;
442     int numRegionsPerServer = 1; // all servers except one
443     int replication = 1;
444     int numTables = 10;
445     /* fails because of max moves */
446     testWithCluster(numNodes, numRegions, numRegionsPerServer, replication, numTables, false, false);
447   }
448 
449   @Test (timeout = 800000)
450   public void testMidCluster() {
451     int numNodes = 100;
452     int numRegions = 10000;
453     int numRegionsPerServer = 60; // all servers except one
454     int replication = 1;
455     int numTables = 40;
456     testWithCluster(numNodes, numRegions, numRegionsPerServer, replication, numTables, true, true);
457   }
458 
459   @Test (timeout = 800000)
460   public void testMidCluster2() {
461     int numNodes = 200;
462     int numRegions = 100000;
463     int numRegionsPerServer = 40; // all servers except one
464     int replication = 1;
465     int numTables = 400;
466     testWithCluster(numNodes,
467         numRegions,
468         numRegionsPerServer,
469         replication,
470         numTables,
471         false, /* num large num regions means may not always get to best balance with one run */
472         false);
473   }
474 
475 
476   @Test (timeout = 800000)
477   public void testMidCluster3() {
478     int numNodes = 100;
479     int numRegions = 2000;
480     int numRegionsPerServer = 9; // all servers except one
481     int replication = 1;
482     int numTables = 110;
483     testWithCluster(numNodes, numRegions, numRegionsPerServer, replication, numTables, true, true);
484     // TODO(eclark): Make sure that the tables are well distributed.
485   }
486 
487   @Test
488   public void testLargeCluster() {
489     int numNodes = 1000;
490     int numRegions = 100000; //100 regions per RS
491     int numRegionsPerServer = 80; //all servers except one
492     int numTables = 100;
493     int replication = 1;
494     testWithCluster(numNodes, numRegions, numRegionsPerServer, replication, numTables, true, true);
495   }
496 
497   @Test (timeout = 800000)
498   public void testRegionReplicasOnSmallCluster() {
499     int numNodes = 10;
500     int numRegions = 1000;
501     int replication = 3; // 3 replicas per region
502     int numRegionsPerServer = 80; //all regions are mostly balanced
503     int numTables = 10;
504     testWithCluster(numNodes, numRegions, numRegionsPerServer, replication, numTables, true, true);
505   }
506 
507   @Ignore @Test (timeout = 800000) // Test is flakey. TODO: Fix!
508   public void testRegionReplicationOnMidClusterSameHosts() {
509     conf.setLong(StochasticLoadBalancer.MAX_STEPS_KEY, 2000000L);
510     conf.setLong("hbase.master.balancer.stochastic.maxRunningTime", 90 * 1000); // 90 sec
511     conf.setFloat("hbase.master.balancer.stochastic.maxMovePercent", 1.0f);
512     loadBalancer.setConf(conf);
513     int numHosts = 100;
514     int numRegions = 100 * 100;
515     int replication = 3; // 3 replicas per region
516     int numRegionsPerServer = 5;
517     int numTables = 10;
518     Map<ServerName, List<HRegionInfo>> serverMap =
519         createServerMap(numHosts, numRegions, numRegionsPerServer, replication, numTables);
520     int numNodesPerHost = 4;
521 
522     // create a new map with 4 RS per host.
523     Map<ServerName, List<HRegionInfo>> newServerMap = new TreeMap<ServerName, List<HRegionInfo>>(serverMap);
524     for (Map.Entry<ServerName, List<HRegionInfo>> entry : serverMap.entrySet()) {
525       for (int i=1; i < numNodesPerHost; i++) {
526         ServerName s1 = entry.getKey();
527         ServerName s2 = ServerName.valueOf(s1.getHostname(), s1.getPort() + i, 1); // create an RS for the same host
528         newServerMap.put(s2, new ArrayList<HRegionInfo>());
529       }
530     }
531 
532     testWithCluster(newServerMap, null, true, true);
533   }
534 
535   private static class ForTestRackManager extends RackManager {
536     int numRacks;
537     public ForTestRackManager(int numRacks) {
538       this.numRacks = numRacks;
539     }
540     @Override
541     public String getRack(ServerName server) {
542       return "rack_" + (server.hashCode() % numRacks);
543     }
544   }
545 
546   private static class ForTestRackManagerOne extends RackManager {
547   @Override
548     public String getRack(ServerName server) {
549       return server.getHostname().endsWith("1") ? "rack1" : "rack2";
550     }
551   }
552 
553   @Test (timeout = 800000)
554   public void testRegionReplicationOnMidClusterWithRacks() {
555     conf.setLong(StochasticLoadBalancer.MAX_STEPS_KEY, 10000000L);
556     conf.setFloat("hbase.master.balancer.stochastic.maxMovePercent", 1.0f);
557     conf.setLong("hbase.master.balancer.stochastic.maxRunningTime", 120 * 1000); // 120 sec
558     loadBalancer.setConf(conf);
559     int numNodes = 30;
560     int numRegions = numNodes * 30;
561     int replication = 3; // 3 replicas per region
562     int numRegionsPerServer = 28;
563     int numTables = 10;
564     int numRacks = 4; // all replicas should be on a different rack
565     Map<ServerName, List<HRegionInfo>> serverMap =
566         createServerMap(numNodes, numRegions, numRegionsPerServer, replication, numTables);
567     RackManager rm = new ForTestRackManager(numRacks);
568 
569     testWithCluster(serverMap, rm, false, true);
570   }
571 
572 }