1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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.master.balancer.StochasticLoadBalancer.ServerLocalityCostFunction;
52 import org.apache.hadoop.hbase.testclassification.FlakeyTests;
53 import org.apache.hadoop.hbase.testclassification.MediumTests;
54 import org.apache.hadoop.hbase.util.Bytes;
55 import org.junit.Ignore;
56 import org.junit.Test;
57 import org.junit.experimental.categories.Category;
58
59 @Category({FlakeyTests.class, MediumTests.class})
60 public class TestStochasticLoadBalancer extends BalancerTestBase {
61 public static final String REGION_KEY = "testRegion";
62 private static final Log LOG = LogFactory.getLog(TestStochasticLoadBalancer.class);
63
64
65 private float[] expectedLocalities = {1.0f, 0.0f, 0.50f, 0.25f, 1.0f};
66
67
68
69
70
71
72
73
74 private int[][][] clusterRegionLocationMocks = new int[][][]{
75
76
77 new int[][]{
78 new int[]{2, 1, 1},
79 new int[]{2, 0, 0, 100},
80 new int[]{0, 100, 0, 0},
81 new int[]{0, 100, 0, 0},
82 new int[]{1, 0, 100, 0},
83 },
84
85
86 new int[][]{
87 new int[]{1, 2, 1},
88 new int[]{0, 0, 0, 100},
89 new int[]{1, 100, 0, 0},
90 new int[]{1, 100, 0, 0},
91 new int[]{2, 0, 100, 0},
92 },
93
94
95 new int[][]{
96 new int[]{1, 2, 1},
97 new int[]{0, 25, 0, 50},
98 new int[]{1, 50, 25, 0},
99 new int[]{1, 50, 25, 0},
100 new int[]{2, 0, 50, 25},
101 },
102
103
104 new int[][]{
105 new int[]{1, 2, 1},
106 new int[]{0, 25, 0, 100},
107 new int[]{1, 100, 25, 0},
108 new int[]{1, 100, 25, 0},
109 new int[]{2, 0, 100, 25},
110 },
111
112
113 new int[][]{
114 new int[]{1, 2, 1},
115 new int[]{0, 75, 75, 75},
116 new int[]{1, 75, 75, 75},
117 new int[]{1, 75, 75, 75},
118 new int[]{2, 75, 75, 75},
119 },
120 };
121
122
123 @Test
124 public void testKeepRegionLoad() throws Exception {
125
126 ServerName sn = ServerName.valueOf("test:8080", 100);
127 int numClusterStatusToAdd = 20000;
128 for (int i = 0; i < numClusterStatusToAdd; i++) {
129 ServerLoad sl = mock(ServerLoad.class);
130
131 RegionLoad rl = mock(RegionLoad.class);
132 when(rl.getStores()).thenReturn(i);
133
134 Map<byte[], RegionLoad> regionLoadMap =
135 new TreeMap<byte[], RegionLoad>(Bytes.BYTES_COMPARATOR);
136 regionLoadMap.put(Bytes.toBytes(REGION_KEY), rl);
137 when(sl.getRegionsLoad()).thenReturn(regionLoadMap);
138
139 ClusterStatus clusterStatus = mock(ClusterStatus.class);
140 when(clusterStatus.getServers()).thenReturn(Arrays.asList(sn));
141 when(clusterStatus.getLoad(sn)).thenReturn(sl);
142
143 loadBalancer.setClusterStatus(clusterStatus);
144 }
145 assertTrue(loadBalancer.loads.get(REGION_KEY) != null);
146 assertTrue(loadBalancer.loads.get(REGION_KEY).size() == 15);
147
148 Queue<RegionLoad> loads = loadBalancer.loads.get(REGION_KEY);
149 int i = 0;
150 while(loads.size() > 0) {
151 RegionLoad rl = loads.remove();
152 assertEquals(i + (numClusterStatusToAdd - 15), rl.getStores());
153 i ++;
154 }
155 }
156
157 @Test
158 public void testNeedBalance() {
159 float minCost = conf.getFloat("hbase.master.balancer.stochastic.minCostNeedBalance", 0.05f);
160 conf.setFloat("hbase.master.balancer.stochastic.minCostNeedBalance", 1.0f);
161 loadBalancer.setConf(conf);
162 for (int[] mockCluster : clusterStateMocks) {
163 Map<ServerName, List<HRegionInfo>> servers = mockClusterServers(mockCluster);
164 List<RegionPlan> plans = loadBalancer.balanceCluster(servers);
165 assertNull(plans);
166 }
167
168 conf.setFloat("hbase.master.balancer.stochastic.minCostNeedBalance", minCost);
169 loadBalancer.setConf(conf);
170 }
171
172
173
174
175
176
177
178
179
180 @Test
181 public void testBalanceCluster() throws Exception {
182
183 for (int[] mockCluster : clusterStateMocks) {
184 Map<ServerName, List<HRegionInfo>> servers = mockClusterServers(mockCluster);
185 List<ServerAndLoad> list = convertToList(servers);
186 LOG.info("Mock Cluster : " + printMock(list) + " " + printStats(list));
187 List<RegionPlan> plans = loadBalancer.balanceCluster(servers);
188 List<ServerAndLoad> balancedCluster = reconcile(list, plans, servers);
189 LOG.info("Mock Balance : " + printMock(balancedCluster));
190 assertClusterAsBalanced(balancedCluster);
191 List<RegionPlan> secondPlans = loadBalancer.balanceCluster(servers);
192 assertNull(secondPlans);
193 for (Map.Entry<ServerName, List<HRegionInfo>> entry : servers.entrySet()) {
194 returnRegions(entry.getValue());
195 returnServer(entry.getKey());
196 }
197 }
198 }
199
200 @Test
201 public void testLocalityCost() throws Exception {
202 Configuration conf = HBaseConfiguration.create();
203 MockNoopMasterServices master = new MockNoopMasterServices();
204 StochasticLoadBalancer.CostFunction
205 costFunction = new ServerLocalityCostFunction(conf, master);
206
207 for (int test = 0; test < clusterRegionLocationMocks.length; test++) {
208 int[][] clusterRegionLocations = clusterRegionLocationMocks[test];
209 MockCluster cluster = new MockCluster(clusterRegionLocations);
210 costFunction.init(cluster);
211 double cost = costFunction.cost();
212 double expected = 1 - expectedLocalities[test];
213 assertEquals(expected, cost, 0.001);
214 }
215 }
216
217 @Test
218 public void testMoveCost() throws Exception {
219 Configuration conf = HBaseConfiguration.create();
220 StochasticLoadBalancer.CostFunction
221 costFunction = new StochasticLoadBalancer.MoveCostFunction(conf);
222 for (int[] mockCluster : clusterStateMocks) {
223 BaseLoadBalancer.Cluster cluster = mockCluster(mockCluster);
224 costFunction.init(cluster);
225 double cost = costFunction.cost();
226 assertEquals(0.0f, cost, 0.001);
227
228
229 cluster.setNumRegions(200);
230 cluster.setNumMovedRegions(10);
231 cost = costFunction.cost();
232 assertEquals(0.05f, cost, 0.001);
233 cluster.setNumMovedRegions(100);
234 cost = costFunction.cost();
235 assertEquals(0.5f, cost, 0.001);
236 cluster.setNumMovedRegions(200);
237 cost = costFunction.cost();
238 assertEquals(1.0f, cost, 0.001);
239
240
241
242 cluster.setNumRegions(10000);
243 cluster.setNumMovedRegions(250);
244 cost = costFunction.cost();
245 assertEquals(0.1f, cost, 0.001);
246 cluster.setNumMovedRegions(1250);
247 cost = costFunction.cost();
248 assertEquals(0.5f, cost, 0.001);
249 cluster.setNumMovedRegions(2500);
250 cost = costFunction.cost();
251 assertEquals(1.0f, cost, 0.01);
252 }
253 }
254
255 @Test
256 public void testSkewCost() {
257 Configuration conf = HBaseConfiguration.create();
258 StochasticLoadBalancer.CostFunction
259 costFunction = new StochasticLoadBalancer.RegionCountSkewCostFunction(conf);
260 for (int[] mockCluster : clusterStateMocks) {
261 costFunction.init(mockCluster(mockCluster));
262 double cost = costFunction.cost();
263 assertTrue(cost >= 0);
264 assertTrue(cost <= 1.01);
265 }
266
267 costFunction.init(mockCluster(new int[]{0, 0, 0, 0, 1}));
268 assertEquals(0,costFunction.cost(), 0.01);
269 costFunction.init(mockCluster(new int[]{0, 0, 0, 1, 1}));
270 assertEquals(0, costFunction.cost(), 0.01);
271 costFunction.init(mockCluster(new int[]{0, 0, 1, 1, 1}));
272 assertEquals(0, costFunction.cost(), 0.01);
273 costFunction.init(mockCluster(new int[]{0, 1, 1, 1, 1}));
274 assertEquals(0, costFunction.cost(), 0.01);
275 costFunction.init(mockCluster(new int[]{1, 1, 1, 1, 1}));
276 assertEquals(0, costFunction.cost(), 0.01);
277 costFunction.init(mockCluster(new int[]{10000, 0, 0, 0, 0}));
278 assertEquals(1, costFunction.cost(), 0.01);
279 }
280
281 @Test
282 public void testCostAfterUndoAction() {
283 final int runs = 10;
284 loadBalancer.setConf(conf);
285 for (int[] mockCluster : clusterStateMocks) {
286 BaseLoadBalancer.Cluster cluster = mockCluster(mockCluster);
287 loadBalancer.initCosts(cluster);
288 for (int i = 0; i != runs; ++i) {
289 final double expectedCost = loadBalancer.computeCost(cluster, Double.MAX_VALUE);
290 Cluster.Action action = loadBalancer.nextAction(cluster);
291 cluster.doAction(action);
292 loadBalancer.updateCostsWithAction(cluster, action);
293 Cluster.Action undoAction = action.undoAction();
294 cluster.doAction(undoAction);
295 loadBalancer.updateCostsWithAction(cluster, undoAction);
296 final double actualCost = loadBalancer.computeCost(cluster, Double.MAX_VALUE);
297 assertEquals(expectedCost, actualCost, 0);
298 }
299 }
300 }
301
302 @Test
303 public void testTableSkewCost() {
304 Configuration conf = HBaseConfiguration.create();
305 StochasticLoadBalancer.CostFunction
306 costFunction = new StochasticLoadBalancer.TableSkewCostFunction(conf);
307 for (int[] mockCluster : clusterStateMocks) {
308 BaseLoadBalancer.Cluster cluster = mockCluster(mockCluster);
309 costFunction.init(cluster);
310 double cost = costFunction.cost();
311 assertTrue(cost >= 0);
312 assertTrue(cost <= 1.01);
313 }
314 }
315
316 @Test
317 public void testRegionLoadCost() {
318 List<RegionLoad> regionLoads = new ArrayList<>();
319 for (int i = 1; i < 5; i++) {
320 RegionLoad regionLoad = mock(RegionLoad.class);
321 when(regionLoad.getReadRequestsCount()).thenReturn(new Long(i));
322 when(regionLoad.getStorefileSizeMB()).thenReturn(i);
323 regionLoads.add(regionLoad);
324 }
325
326 Configuration conf = HBaseConfiguration.create();
327 StochasticLoadBalancer.ReadRequestCostFunction readCostFunction =
328 new StochasticLoadBalancer.ReadRequestCostFunction(conf);
329 double rateResult = readCostFunction.getRegionLoadCost(regionLoads);
330
331 assertEquals(1, rateResult, 0.01);
332
333 StochasticLoadBalancer.StoreFileCostFunction storeFileCostFunction =
334 new StochasticLoadBalancer.StoreFileCostFunction(conf);
335 double result = storeFileCostFunction.getRegionLoadCost(regionLoads);
336
337 assertEquals(2.5, result, 0.01);
338 }
339
340 @Test
341 public void testCostFromArray() {
342 Configuration conf = HBaseConfiguration.create();
343 StochasticLoadBalancer.CostFromRegionLoadFunction
344 costFunction = new StochasticLoadBalancer.MemstoreSizeCostFunction(conf);
345 costFunction.init(mockCluster(new int[]{0, 0, 0, 0, 1}));
346
347 double[] statOne = new double[100];
348 for (int i =0; i < 100; i++) {
349 statOne[i] = 10;
350 }
351 assertEquals(0, costFunction.costFromArray(statOne), 0.01);
352
353 double[] statTwo= new double[101];
354 for (int i =0; i < 100; i++) {
355 statTwo[i] = 0;
356 }
357 statTwo[100] = 100;
358 assertEquals(1, costFunction.costFromArray(statTwo), 0.01);
359
360 double[] statThree = new double[200];
361 for (int i =0; i < 100; i++) {
362 statThree[i] = (0);
363 statThree[i+100] = 100;
364 }
365 assertEquals(0.5, costFunction.costFromArray(statThree), 0.01);
366 }
367
368 @Test(timeout = 60000)
369 public void testLosingRs() throws Exception {
370 int numNodes = 3;
371 int numRegions = 20;
372 int numRegionsPerServer = 3;
373 int replication = 1;
374 int numTables = 2;
375
376 Map<ServerName, List<HRegionInfo>> serverMap =
377 createServerMap(numNodes, numRegions, numRegionsPerServer, replication, numTables);
378 List<ServerAndLoad> list = convertToList(serverMap);
379
380
381 List<RegionPlan> plans = loadBalancer.balanceCluster(serverMap);
382 assertNotNull(plans);
383
384
385 List<ServerAndLoad> balancedCluster = reconcile(list, plans, serverMap);
386
387 assertClusterAsBalanced(balancedCluster);
388
389 ServerName sn = serverMap.keySet().toArray(new ServerName[serverMap.size()])[0];
390
391 ServerName deadSn = ServerName.valueOf(sn.getHostname(), sn.getPort(), sn.getStartcode() - 100);
392
393 serverMap.put(deadSn, new ArrayList<HRegionInfo>(0));
394
395 plans = loadBalancer.balanceCluster(serverMap);
396 assertNull(plans);
397 }
398
399 @Test
400 public void testReplicaCost() {
401 Configuration conf = HBaseConfiguration.create();
402 StochasticLoadBalancer.CostFunction
403 costFunction = new StochasticLoadBalancer.RegionReplicaHostCostFunction(conf);
404 for (int[] mockCluster : clusterStateMocks) {
405 BaseLoadBalancer.Cluster cluster = mockCluster(mockCluster);
406 costFunction.init(cluster);
407 double cost = costFunction.cost();
408 assertTrue(cost >= 0);
409 assertTrue(cost <= 1.01);
410 }
411 }
412
413 @Test
414 public void testReplicaCostForReplicas() {
415 Configuration conf = HBaseConfiguration.create();
416 StochasticLoadBalancer.CostFunction
417 costFunction = new StochasticLoadBalancer.RegionReplicaHostCostFunction(conf);
418
419 int [] servers = new int[] {3,3,3,3,3};
420 TreeMap<ServerName, List<HRegionInfo>> clusterState = mockClusterServers(servers);
421
422 BaseLoadBalancer.Cluster cluster;
423
424 cluster = new BaseLoadBalancer.Cluster(clusterState, null, null, null);
425 costFunction.init(cluster);
426 double costWithoutReplicas = costFunction.cost();
427 assertEquals(0, costWithoutReplicas, 0);
428
429
430 HRegionInfo replica1 = RegionReplicaUtil.getRegionInfoForReplica(
431 clusterState.firstEntry().getValue().get(0),1);
432 clusterState.lastEntry().getValue().add(replica1);
433
434 cluster = new BaseLoadBalancer.Cluster(clusterState, null, null, null);
435 costFunction.init(cluster);
436 double costWith1ReplicaDifferentServer = costFunction.cost();
437
438 assertEquals(0, costWith1ReplicaDifferentServer, 0);
439
440
441 HRegionInfo replica2 = RegionReplicaUtil.getRegionInfoForReplica(replica1, 2);
442 clusterState.lastEntry().getValue().add(replica2);
443
444 cluster = new BaseLoadBalancer.Cluster(clusterState, null, null, null);
445 costFunction.init(cluster);
446 double costWith1ReplicaSameServer = costFunction.cost();
447
448 assertTrue(costWith1ReplicaDifferentServer < costWith1ReplicaSameServer);
449
450
451
452 HRegionInfo replica3;
453 Iterator<Entry<ServerName, List<HRegionInfo>>> it;
454 Entry<ServerName, List<HRegionInfo>> entry;
455
456 clusterState = mockClusterServers(servers);
457 it = clusterState.entrySet().iterator();
458 entry = it.next();
459 HRegionInfo hri = entry.getValue().get(0);
460 replica1 = RegionReplicaUtil.getRegionInfoForReplica(hri, 1);
461 replica2 = RegionReplicaUtil.getRegionInfoForReplica(hri, 2);
462 replica3 = RegionReplicaUtil.getRegionInfoForReplica(hri, 3);
463 entry.getValue().add(replica1);
464 entry.getValue().add(replica2);
465 it.next().getValue().add(replica3);
466
467 cluster = new BaseLoadBalancer.Cluster(clusterState, null, null, null);
468 costFunction.init(cluster);
469 double costWith3ReplicasSameServer = costFunction.cost();
470
471 clusterState = mockClusterServers(servers);
472 hri = clusterState.firstEntry().getValue().get(0);
473 replica1 = RegionReplicaUtil.getRegionInfoForReplica(hri, 1);
474 replica2 = RegionReplicaUtil.getRegionInfoForReplica(hri, 2);
475 replica3 = RegionReplicaUtil.getRegionInfoForReplica(hri, 3);
476
477 clusterState.firstEntry().getValue().add(replica1);
478 clusterState.lastEntry().getValue().add(replica2);
479 clusterState.lastEntry().getValue().add(replica3);
480
481 cluster = new BaseLoadBalancer.Cluster(clusterState, null, null, null);
482 costFunction.init(cluster);
483 double costWith2ReplicasOnTwoServers = costFunction.cost();
484
485 assertTrue(costWith2ReplicasOnTwoServers < costWith3ReplicasSameServer);
486 }
487
488 @Test
489 public void testNeedsBalanceForColocatedReplicas() {
490
491
492 List<HRegionInfo> regions = randomRegions(1);
493 ServerName s1 = ServerName.valueOf("host1", 1000, 11111);
494 ServerName s2 = ServerName.valueOf("host11", 1000, 11111);
495 Map<ServerName, List<HRegionInfo>> map = new HashMap<ServerName, List<HRegionInfo>>();
496 map.put(s1, regions);
497 regions.add(RegionReplicaUtil.getRegionInfoForReplica(regions.get(0), 1));
498
499 regions = randomRegions(1);
500 map.put(s2, regions);
501 assertTrue(loadBalancer.needsBalance(new Cluster(map, null, null, null)));
502
503
504 map.clear();
505 regions = randomRegions(1);
506 List<HRegionInfo> regionsOnS2 = new ArrayList<HRegionInfo>(1);
507 regionsOnS2.add(RegionReplicaUtil.getRegionInfoForReplica(regions.get(0), 1));
508 map.put(s1, regions);
509 map.put(s2, regionsOnS2);
510
511 map.put(ServerName.valueOf("host2", 1000, 11111), randomRegions(1));
512 assertTrue(loadBalancer.needsBalance(new Cluster(map, null, null,
513 new ForTestRackManagerOne())));
514 }
515
516 @Test (timeout = 60000)
517 public void testSmallCluster() {
518 int numNodes = 10;
519 int numRegions = 1000;
520 int numRegionsPerServer = 40;
521 int replication = 1;
522 int numTables = 10;
523 testWithCluster(numNodes, numRegions, numRegionsPerServer, replication, numTables, true, true);
524 }
525
526 @Test (timeout = 60000)
527 public void testSmallCluster2() {
528 int numNodes = 20;
529 int numRegions = 2000;
530 int numRegionsPerServer = 40;
531 int replication = 1;
532 int numTables = 10;
533 testWithCluster(numNodes, numRegions, numRegionsPerServer, replication, numTables, true, true);
534 }
535
536 @Test (timeout = 60000)
537 public void testSmallCluster3() {
538 int numNodes = 20;
539 int numRegions = 2000;
540 int numRegionsPerServer = 1;
541 int replication = 1;
542 int numTables = 10;
543
544 testWithCluster(numNodes, numRegions, numRegionsPerServer, replication, numTables, false, false);
545 }
546
547 @Test (timeout = 800000)
548 public void testMidCluster() {
549 int numNodes = 100;
550 int numRegions = 10000;
551 int numRegionsPerServer = 60;
552 int replication = 1;
553 int numTables = 40;
554 testWithCluster(numNodes, numRegions, numRegionsPerServer, replication, numTables, true, true);
555 }
556
557 @Test (timeout = 800000)
558 public void testMidCluster2() {
559 int numNodes = 200;
560 int numRegions = 100000;
561 int numRegionsPerServer = 40;
562 int replication = 1;
563 int numTables = 400;
564 testWithCluster(numNodes,
565 numRegions,
566 numRegionsPerServer,
567 replication,
568 numTables,
569 false,
570 false);
571 }
572
573
574 @Test (timeout = 800000)
575 public void testMidCluster3() {
576 int numNodes = 100;
577 int numRegions = 2000;
578 int numRegionsPerServer = 9;
579 int replication = 1;
580 int numTables = 110;
581 testWithCluster(numNodes, numRegions, numRegionsPerServer, replication, numTables, true, true);
582
583 }
584
585 @Test
586 public void testLargeCluster() {
587 int numNodes = 1000;
588 int numRegions = 100000;
589 int numRegionsPerServer = 80;
590 int numTables = 100;
591 int replication = 1;
592 testWithCluster(numNodes, numRegions, numRegionsPerServer, replication, numTables, true, true);
593 }
594
595 @Test (timeout = 800000)
596 public void testRegionReplicasOnSmallCluster() {
597 int numNodes = 10;
598 int numRegions = 1000;
599 int replication = 3;
600 int numRegionsPerServer = 80;
601 int numTables = 10;
602 testWithCluster(numNodes, numRegions, numRegionsPerServer, replication, numTables, true, true);
603 }
604
605 @Ignore @Test (timeout = 800000)
606 public void testRegionReplicationOnMidClusterSameHosts() {
607 conf.setLong(StochasticLoadBalancer.MAX_STEPS_KEY, 2000000L);
608 conf.setLong("hbase.master.balancer.stochastic.maxRunningTime", 90 * 1000);
609 conf.setFloat("hbase.master.balancer.stochastic.maxMovePercent", 1.0f);
610 loadBalancer.setConf(conf);
611 int numHosts = 100;
612 int numRegions = 100 * 100;
613 int replication = 3;
614 int numRegionsPerServer = 5;
615 int numTables = 10;
616 Map<ServerName, List<HRegionInfo>> serverMap =
617 createServerMap(numHosts, numRegions, numRegionsPerServer, replication, numTables);
618 int numNodesPerHost = 4;
619
620
621 Map<ServerName, List<HRegionInfo>> newServerMap = new TreeMap<ServerName, List<HRegionInfo>>(serverMap);
622 for (Map.Entry<ServerName, List<HRegionInfo>> entry : serverMap.entrySet()) {
623 for (int i=1; i < numNodesPerHost; i++) {
624 ServerName s1 = entry.getKey();
625 ServerName s2 = ServerName.valueOf(s1.getHostname(), s1.getPort() + i, 1);
626 newServerMap.put(s2, new ArrayList<HRegionInfo>());
627 }
628 }
629
630 testWithCluster(newServerMap, null, true, true);
631 }
632
633 private static class ForTestRackManager extends RackManager {
634 int numRacks;
635 public ForTestRackManager(int numRacks) {
636 this.numRacks = numRacks;
637 }
638 @Override
639 public String getRack(ServerName server) {
640 return "rack_" + (server.hashCode() % numRacks);
641 }
642 }
643
644 private static class ForTestRackManagerOne extends RackManager {
645 @Override
646 public String getRack(ServerName server) {
647 return server.getHostname().endsWith("1") ? "rack1" : "rack2";
648 }
649 }
650
651 @Test (timeout = 800000)
652 public void testRegionReplicationOnMidClusterWithRacks() {
653 conf.setLong(StochasticLoadBalancer.MAX_STEPS_KEY, 10000000L);
654 conf.setFloat("hbase.master.balancer.stochastic.maxMovePercent", 1.0f);
655 conf.setLong("hbase.master.balancer.stochastic.maxRunningTime", 120 * 1000);
656 loadBalancer.setConf(conf);
657 int numNodes = 30;
658 int numRegions = numNodes * 30;
659 int replication = 3;
660 int numRegionsPerServer = 28;
661 int numTables = 10;
662 int numRacks = 4;
663 Map<ServerName, List<HRegionInfo>> serverMap =
664 createServerMap(numNodes, numRegions, numRegionsPerServer, replication, numTables);
665 RackManager rm = new ForTestRackManager(numRacks);
666
667 testWithCluster(serverMap, rm, false, true);
668 }
669
670
671 private class MockCluster extends BaseLoadBalancer.Cluster {
672
673 private int[][] localities = null;
674
675 public MockCluster(int[][] regions) {
676
677
678 super(mockClusterServers(regions[0], 1), null, null, null);
679
680 localities = new int[regions.length - 1][];
681 for (int i = 1; i < regions.length; i++) {
682 int regionIndex = i - 1;
683 localities[regionIndex] = new int[regions[i].length - 1];
684 regionIndexToServerIndex[regionIndex] = regions[i][0];
685 for (int j = 1; j < regions[i].length; j++) {
686 int serverIndex = j - 1;
687 localities[regionIndex][serverIndex] = regions[i][j] > 100 ? regions[i][j] % 100 : regions[i][j];
688 }
689 }
690 }
691
692 @Override
693 float getLocalityOfRegion(int region, int server) {
694
695 return localities[region][server] / 100.0f;
696 }
697
698 @Override
699 public int getRegionSizeMB(int region) {
700 return 1;
701 }
702
703 }
704
705 }