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.balancer; 019 020import static org.apache.hadoop.hbase.ServerName.NON_STARTCODE; 021import static org.junit.Assert.assertEquals; 022import static org.junit.Assert.assertFalse; 023import static org.junit.Assert.assertNotNull; 024import static org.junit.Assert.assertNull; 025import static org.junit.Assert.assertTrue; 026 027import java.io.IOException; 028import java.util.EnumSet; 029import java.util.List; 030import java.util.Map; 031import java.util.Map.Entry; 032import java.util.Set; 033import java.util.stream.Collectors; 034import org.apache.hadoop.conf.Configuration; 035import org.apache.hadoop.hbase.ClusterMetrics.Option; 036import org.apache.hadoop.hbase.HBaseClassTestRule; 037import org.apache.hadoop.hbase.HBaseTestingUtility; 038import org.apache.hadoop.hbase.HColumnDescriptor; 039import org.apache.hadoop.hbase.HConstants; 040import org.apache.hadoop.hbase.HTableDescriptor; 041import org.apache.hadoop.hbase.MiniHBaseCluster; 042import org.apache.hadoop.hbase.ServerName; 043import org.apache.hadoop.hbase.TableName; 044import org.apache.hadoop.hbase.Waiter; 045import org.apache.hadoop.hbase.client.Admin; 046import org.apache.hadoop.hbase.client.RegionInfo; 047import org.apache.hadoop.hbase.favored.FavoredNodeAssignmentHelper; 048import org.apache.hadoop.hbase.favored.FavoredNodesManager; 049import org.apache.hadoop.hbase.favored.FavoredNodesPlan; 050import org.apache.hadoop.hbase.master.HMaster; 051import org.apache.hadoop.hbase.master.LoadBalancer; 052import org.apache.hadoop.hbase.master.ServerManager; 053import org.apache.hadoop.hbase.master.assignment.RegionStateNode; 054import org.apache.hadoop.hbase.master.assignment.RegionStates; 055import org.apache.hadoop.hbase.regionserver.HRegion; 056import org.apache.hadoop.hbase.testclassification.MediumTests; 057import org.apache.hadoop.hbase.util.Bytes; 058import org.apache.hadoop.hbase.util.JVMClusterUtil; 059import org.junit.After; 060import org.junit.Before; 061import org.junit.BeforeClass; 062import org.junit.ClassRule; 063import org.junit.Ignore; 064import org.junit.Test; 065import org.junit.experimental.categories.Category; 066import org.slf4j.Logger; 067import org.slf4j.LoggerFactory; 068 069import org.apache.hbase.thirdparty.com.google.common.collect.Lists; 070import org.apache.hbase.thirdparty.com.google.common.collect.Maps; 071import org.apache.hbase.thirdparty.com.google.common.collect.Sets; 072 073@Ignore // Disabled 074@Category(MediumTests.class) 075public class TestFavoredStochasticLoadBalancer extends BalancerTestBase { 076 077 @ClassRule 078 public static final HBaseClassTestRule CLASS_RULE = 079 HBaseClassTestRule.forClass(TestFavoredStochasticLoadBalancer.class); 080 081 private static final Logger LOG = 082 LoggerFactory.getLogger(TestFavoredStochasticLoadBalancer.class); 083 084 private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); 085 private static final int SLAVES = 8; 086 private static final int REGION_NUM = SLAVES * 3; 087 088 private Admin admin; 089 private HMaster master; 090 private MiniHBaseCluster cluster; 091 092 @BeforeClass 093 public static void setupBeforeClass() throws Exception { 094 Configuration conf = TEST_UTIL.getConfiguration(); 095 // Enable the favored nodes based load balancer 096 conf.setClass(HConstants.HBASE_MASTER_LOADBALANCER_CLASS, 097 LoadOnlyFavoredStochasticBalancer.class, LoadBalancer.class); 098 } 099 100 @Before 101 public void startCluster() throws Exception { 102 TEST_UTIL.startMiniCluster(SLAVES); 103 TEST_UTIL.getDFSCluster().waitClusterUp(); 104 cluster = TEST_UTIL.getMiniHBaseCluster(); 105 master = TEST_UTIL.getMiniHBaseCluster().getMaster(); 106 admin = TEST_UTIL.getAdmin(); 107 admin.setBalancerRunning(false, true); 108 } 109 110 @After 111 public void stopCluster() throws Exception { 112 TEST_UTIL.cleanupTestDir(); 113 TEST_UTIL.shutdownMiniCluster(); 114 } 115 116 @Test 117 public void testBasicBalance() throws Exception { 118 119 TableName tableName = TableName.valueOf("testBasicBalance"); 120 HTableDescriptor desc = new HTableDescriptor(tableName); 121 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY)); 122 admin.createTable(desc, Bytes.toBytes("aaa"), Bytes.toBytes("zzz"), REGION_NUM); 123 TEST_UTIL.waitTableAvailable(tableName); 124 TEST_UTIL.loadTable(admin.getConnection().getTable(tableName), HConstants.CATALOG_FAMILY); 125 admin.flush(tableName); 126 compactTable(tableName); 127 128 JVMClusterUtil.RegionServerThread rs1 = cluster.startRegionServerAndWait(10000); 129 JVMClusterUtil.RegionServerThread rs2 = cluster.startRegionServerAndWait(10000); 130 131 // Now try to run balance, and verify no regions are moved to the 2 region servers recently 132 // started. 133 admin.setBalancerRunning(true, true); 134 assertTrue("Balancer did not run", admin.balancer()); 135 TEST_UTIL.waitUntilNoRegionsInTransition(120000); 136 137 List<RegionInfo> hris = admin.getRegions(rs1.getRegionServer().getServerName()); 138 for (RegionInfo hri : hris) { 139 assertFalse("New RS contains regions belonging to table: " + tableName, 140 hri.getTable().equals(tableName)); 141 } 142 hris = admin.getRegions(rs2.getRegionServer().getServerName()); 143 for (RegionInfo hri : hris) { 144 assertFalse("New RS contains regions belonging to table: " + tableName, 145 hri.getTable().equals(tableName)); 146 } 147 } 148 149 @Test 150 public void testRoundRobinAssignment() throws Exception { 151 152 TableName tableName = TableName.valueOf("testRoundRobinAssignment"); 153 HTableDescriptor desc = new HTableDescriptor(tableName); 154 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY)); 155 admin.createTable(desc, Bytes.toBytes("aaa"), Bytes.toBytes("zzz"), REGION_NUM); 156 TEST_UTIL.waitTableAvailable(tableName); 157 TEST_UTIL.loadTable(admin.getConnection().getTable(tableName), HConstants.CATALOG_FAMILY); 158 admin.flush(tableName); 159 160 LoadBalancer balancer = master.getLoadBalancer(); 161 List<RegionInfo> regions = admin.getRegions(tableName); 162 regions.addAll(admin.getTableRegions(TableName.META_TABLE_NAME)); 163 regions.addAll(admin.getTableRegions(TableName.NAMESPACE_TABLE_NAME)); 164 List<ServerName> servers = Lists.newArrayList( 165 admin.getClusterMetrics(EnumSet.of(Option.LIVE_SERVERS)).getLiveServerMetrics().keySet()); 166 Map<ServerName, List<RegionInfo>> map = balancer.roundRobinAssignment(regions, servers); 167 for (List<RegionInfo> regionInfos : map.values()) { 168 regions.removeAll(regionInfos); 169 } 170 assertEquals("No region should be missed by balancer", 0, regions.size()); 171 } 172 173 174 @Test 175 public void testBasicRegionPlacementAndReplicaLoad() throws Exception { 176 177 String tableName = "testBasicRegionPlacement"; 178 HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(tableName)); 179 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY)); 180 admin.createTable(desc, Bytes.toBytes("aaa"), Bytes.toBytes("zzz"), REGION_NUM); 181 TEST_UTIL.waitTableAvailable(desc.getTableName()); 182 183 FavoredNodesManager fnm = master.getFavoredNodesManager(); 184 List<RegionInfo> regionsOfTable = admin.getRegions(TableName.valueOf(tableName)); 185 for (RegionInfo rInfo : regionsOfTable) { 186 Set<ServerName> favNodes = Sets.newHashSet(fnm.getFavoredNodes(rInfo)); 187 assertNotNull(favNodes); 188 assertEquals(FavoredNodeAssignmentHelper.FAVORED_NODES_NUM, favNodes.size()); 189 } 190 191 Map<ServerName, List<Integer>> replicaLoadMap = fnm.getReplicaLoad( 192 Lists.newArrayList(admin.getClusterMetrics(EnumSet.of(Option.LIVE_SERVERS)) 193 .getLiveServerMetrics().keySet())); 194 assertTrue("Not all replica load collected.", 195 admin.getClusterMetrics(EnumSet.of(Option.LIVE_SERVERS)) 196 .getLiveServerMetrics().size() == replicaLoadMap.size()); 197 for (Entry<ServerName, List<Integer>> entry : replicaLoadMap.entrySet()) { 198 assertTrue(entry.getValue().size() == FavoredNodeAssignmentHelper.FAVORED_NODES_NUM); 199 assertTrue(entry.getValue().get(0) >= 0); 200 assertTrue(entry.getValue().get(1) >= 0); 201 assertTrue(entry.getValue().get(2) >= 0); 202 } 203 204 admin.disableTable(TableName.valueOf(tableName)); 205 admin.deleteTable(TableName.valueOf(tableName)); 206 replicaLoadMap = fnm.getReplicaLoad(Lists.newArrayList( 207 admin.getClusterMetrics(EnumSet.of(Option.LIVE_SERVERS)).getLiveServerMetrics().keySet())); 208 assertTrue("replica load found " + replicaLoadMap.size() + " instead of 0.", 209 replicaLoadMap.size() == admin 210 .getClusterMetrics(EnumSet.of(Option.LIVE_SERVERS)).getLiveServerMetrics() 211 .size()); 212 } 213 214 @Test 215 public void testRandomAssignmentWithNoFavNodes() throws Exception { 216 217 final String tableName = "testRandomAssignmentWithNoFavNodes"; 218 HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(tableName)); 219 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY)); 220 admin.createTable(desc); 221 TEST_UTIL.waitTableAvailable(desc.getTableName()); 222 223 RegionInfo hri = admin.getTableRegions(TableName.valueOf(tableName)).get(0); 224 225 FavoredNodesManager fnm = master.getFavoredNodesManager(); 226 fnm.deleteFavoredNodesForRegions(Lists.newArrayList(hri)); 227 assertNull("Favored nodes not found null after delete", fnm.getFavoredNodes(hri)); 228 229 LoadBalancer balancer = master.getLoadBalancer(); 230 ServerName destination = balancer.randomAssignment(hri, Lists.newArrayList(admin 231 .getClusterMetrics(EnumSet.of(Option.LIVE_SERVERS)).getLiveServerMetrics() 232 .keySet().stream().collect(Collectors.toList()))); 233 assertNotNull(destination); 234 List<ServerName> favoredNodes = fnm.getFavoredNodes(hri); 235 assertNotNull(favoredNodes); 236 boolean containsFN = false; 237 for (ServerName sn : favoredNodes) { 238 if (ServerName.isSameAddress(destination, sn)) { 239 containsFN = true; 240 } 241 } 242 assertTrue("Destination server does not belong to favored nodes.", containsFN); 243 } 244 245 @Test 246 public void testBalancerWithoutFavoredNodes() throws Exception { 247 248 TableName tableName = TableName.valueOf("testBalancerWithoutFavoredNodes"); 249 HTableDescriptor desc = new HTableDescriptor(tableName); 250 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY)); 251 admin.createTable(desc, Bytes.toBytes("aaa"), Bytes.toBytes("zzz"), REGION_NUM); 252 TEST_UTIL.waitTableAvailable(tableName); 253 254 final RegionInfo region = admin.getTableRegions(tableName).get(0); 255 LOG.info("Region thats supposed to be in transition: " + region); 256 FavoredNodesManager fnm = master.getFavoredNodesManager(); 257 List<ServerName> currentFN = fnm.getFavoredNodes(region); 258 assertNotNull(currentFN); 259 260 fnm.deleteFavoredNodesForRegions(Lists.newArrayList(region)); 261 262 RegionStates regionStates = master.getAssignmentManager().getRegionStates(); 263 admin.setBalancerRunning(true, true); 264 265 // Balancer should unassign the region 266 assertTrue("Balancer did not run", admin.balancer()); 267 TEST_UTIL.waitUntilNoRegionsInTransition(); 268 269 admin.assign(region.getEncodedNameAsBytes()); 270 TEST_UTIL.waitUntilNoRegionsInTransition(60000); 271 272 currentFN = fnm.getFavoredNodes(region); 273 assertNotNull(currentFN); 274 assertEquals("Expected number of FN not present", 275 FavoredNodeAssignmentHelper.FAVORED_NODES_NUM, currentFN.size()); 276 277 assertTrue("Balancer did not run", admin.balancer()); 278 TEST_UTIL.waitUntilNoRegionsInTransition(60000); 279 280 checkFavoredNodeAssignments(tableName, fnm, regionStates); 281 } 282 283 @Ignore @Test 284 public void testMisplacedRegions() throws Exception { 285 286 TableName tableName = TableName.valueOf("testMisplacedRegions"); 287 HTableDescriptor desc = new HTableDescriptor(tableName); 288 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY)); 289 admin.createTable(desc, Bytes.toBytes("aaa"), Bytes.toBytes("zzz"), REGION_NUM); 290 TEST_UTIL.waitTableAvailable(tableName); 291 292 final RegionInfo misplacedRegion = admin.getTableRegions(tableName).get(0); 293 FavoredNodesManager fnm = master.getFavoredNodesManager(); 294 List<ServerName> currentFN = fnm.getFavoredNodes(misplacedRegion); 295 assertNotNull(currentFN); 296 297 List<ServerName> serversForNewFN = Lists.newArrayList(); 298 for (ServerName sn : admin.getClusterMetrics(EnumSet.of(Option.LIVE_SERVERS)) 299 .getLiveServerMetrics().keySet()) { 300 serversForNewFN.add(ServerName.valueOf(sn.getHostname(), sn.getPort(), NON_STARTCODE)); 301 } 302 for (ServerName sn : currentFN) { 303 serversForNewFN.remove(sn); 304 } 305 FavoredNodeAssignmentHelper helper = new FavoredNodeAssignmentHelper(serversForNewFN, conf); 306 helper.initialize(); 307 List<ServerName> newFavoredNodes = helper.generateFavoredNodes(misplacedRegion); 308 assertNotNull(newFavoredNodes); 309 assertEquals(FavoredNodeAssignmentHelper.FAVORED_NODES_NUM, newFavoredNodes.size()); 310 Map<RegionInfo, List<ServerName>> regionFNMap = Maps.newHashMap(); 311 regionFNMap.put(misplacedRegion, newFavoredNodes); 312 fnm.updateFavoredNodes(regionFNMap); 313 314 final RegionStates regionStates = master.getAssignmentManager().getRegionStates(); 315 final ServerName current = regionStates.getRegionServerOfRegion(misplacedRegion); 316 assertNull("Misplaced region is still hosted on favored node, not expected.", 317 FavoredNodesPlan.getFavoredServerPosition(fnm.getFavoredNodes(misplacedRegion), current)); 318 admin.setBalancerRunning(true, true); 319 assertTrue("Balancer did not run", admin.balancer()); 320 TEST_UTIL.waitFor(120000, 30000, new Waiter.Predicate<Exception>() { 321 @Override 322 public boolean evaluate() throws Exception { 323 ServerName host = regionStates.getRegionServerOfRegion(misplacedRegion); 324 return !ServerName.isSameAddress(host, current); 325 } 326 }); 327 checkFavoredNodeAssignments(tableName, fnm, regionStates); 328 } 329 330 @Test 331 public void test2FavoredNodesDead() throws Exception { 332 333 TableName tableName = TableName.valueOf("testAllFavoredNodesDead"); 334 HTableDescriptor desc = new HTableDescriptor(tableName); 335 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY)); 336 admin.createTable(desc, Bytes.toBytes("aaa"), Bytes.toBytes("zzz"), REGION_NUM); 337 TEST_UTIL.waitTableAvailable(tableName); 338 339 final RegionInfo region = admin.getTableRegions(tableName).get(0); 340 LOG.info("Region that's supposed to be in transition: " + region); 341 FavoredNodesManager fnm = master.getFavoredNodesManager(); 342 List<ServerName> currentFN = fnm.getFavoredNodes(region); 343 assertNotNull(currentFN); 344 345 List<ServerName> serversToStop = Lists.newArrayList(currentFN); 346 serversToStop.remove(currentFN.get(0)); 347 348 // Lets kill 2 FN for the region. All regions should still be assigned 349 stopServersAndWaitUntilProcessed(serversToStop); 350 351 TEST_UTIL.waitUntilNoRegionsInTransition(); 352 final RegionStates regionStates = master.getAssignmentManager().getRegionStates(); 353 TEST_UTIL.waitFor(10000, new Waiter.Predicate<Exception>() { 354 @Override 355 public boolean evaluate() throws Exception { 356 return regionStates.getRegionState(region).isOpened(); 357 } 358 }); 359 360 assertEquals("Not all regions are online", REGION_NUM, admin.getTableRegions(tableName).size()); 361 admin.setBalancerRunning(true, true); 362 assertTrue("Balancer did not run", admin.balancer()); 363 TEST_UTIL.waitUntilNoRegionsInTransition(60000); 364 365 checkFavoredNodeAssignments(tableName, fnm, regionStates); 366 } 367 368 @Ignore @Test 369 public void testAllFavoredNodesDead() throws Exception { 370 371 TableName tableName = TableName.valueOf("testAllFavoredNodesDead"); 372 HTableDescriptor desc = new HTableDescriptor(tableName); 373 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY)); 374 admin.createTable(desc, Bytes.toBytes("aaa"), Bytes.toBytes("zzz"), REGION_NUM); 375 TEST_UTIL.waitTableAvailable(tableName); 376 377 final RegionInfo region = admin.getTableRegions(tableName).get(0); 378 LOG.info("Region that's supposed to be in transition: " + region); 379 FavoredNodesManager fnm = master.getFavoredNodesManager(); 380 List<ServerName> currentFN = fnm.getFavoredNodes(region); 381 assertNotNull(currentFN); 382 383 // Lets kill all the RS that are favored nodes for this region. 384 stopServersAndWaitUntilProcessed(currentFN); 385 386 final RegionStates regionStates = master.getAssignmentManager().getRegionStates(); 387 TEST_UTIL.waitFor(10000, new Waiter.Predicate<Exception>() { 388 @Override 389 public boolean evaluate() throws Exception { 390 return regionStates.getRegionState(region).isFailedOpen(); 391 } 392 }); 393 394 assertTrue("Region: " + region + " should be RIT", 395 regionStates.getRegionState(region).isFailedOpen()); 396 397 // Regenerate FN and assign, everything else should be fine 398 List<ServerName> serversForNewFN = Lists.newArrayList(); 399 for (ServerName sn : admin.getClusterMetrics(EnumSet.of(Option.LIVE_SERVERS)) 400 .getLiveServerMetrics().keySet()) { 401 serversForNewFN.add(ServerName.valueOf(sn.getHostname(), sn.getPort(), NON_STARTCODE)); 402 } 403 404 FavoredNodeAssignmentHelper helper = new FavoredNodeAssignmentHelper(serversForNewFN, conf); 405 helper.initialize(); 406 407 for (RegionStateNode regionState: regionStates.getRegionsInTransition()) { 408 RegionInfo regionInfo = regionState.getRegionInfo(); 409 List<ServerName> newFavoredNodes = helper.generateFavoredNodes(regionInfo); 410 assertNotNull(newFavoredNodes); 411 assertEquals(FavoredNodeAssignmentHelper.FAVORED_NODES_NUM, newFavoredNodes.size()); 412 LOG.info("Region: " + regionInfo.getEncodedName() + " FN: " + newFavoredNodes); 413 414 Map<RegionInfo, List<ServerName>> regionFNMap = Maps.newHashMap(); 415 regionFNMap.put(regionInfo, newFavoredNodes); 416 fnm.updateFavoredNodes(regionFNMap); 417 LOG.info("Assigning region: " + regionInfo.getEncodedName()); 418 admin.assign(regionInfo.getEncodedNameAsBytes()); 419 } 420 TEST_UTIL.waitUntilNoRegionsInTransition(60000); 421 assertEquals("Not all regions are online", REGION_NUM, admin.getTableRegions(tableName).size()); 422 423 admin.setBalancerRunning(true, true); 424 assertTrue("Balancer did not run", admin.balancer()); 425 TEST_UTIL.waitUntilNoRegionsInTransition(60000); 426 427 checkFavoredNodeAssignments(tableName, fnm, regionStates); 428 } 429 430 @Ignore @Test 431 public void testAllFavoredNodesDeadMasterRestarted() throws Exception { 432 433 TableName tableName = TableName.valueOf("testAllFavoredNodesDeadMasterRestarted"); 434 HTableDescriptor desc = new HTableDescriptor(tableName); 435 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY)); 436 admin.createTable(desc, Bytes.toBytes("aaa"), Bytes.toBytes("zzz"), REGION_NUM); 437 TEST_UTIL.waitTableAvailable(tableName); 438 439 final RegionInfo region = admin.getTableRegions(tableName).get(0); 440 LOG.info("Region that's supposed to be in transition: " + region); 441 FavoredNodesManager fnm = master.getFavoredNodesManager(); 442 List<ServerName> currentFN = fnm.getFavoredNodes(region); 443 assertNotNull(currentFN); 444 445 // Lets kill all the RS that are favored nodes for this region. 446 stopServersAndWaitUntilProcessed(currentFN); 447 448 final RegionStates regionStatesBeforeMaster = 449 master.getAssignmentManager().getRegionStates(); 450 TEST_UTIL.waitFor(10000, new Waiter.Predicate<Exception>() { 451 @Override 452 public boolean evaluate() throws Exception { 453 return regionStatesBeforeMaster.getRegionState(region).isFailedOpen(); 454 } 455 }); 456 457 assertTrue("Region: " + region + " should be RIT", 458 regionStatesBeforeMaster.getRegionState(region).isFailedOpen()); 459 460 List<RegionInfo> rit = Lists.newArrayList(); 461 for (RegionStateNode regionState: regionStatesBeforeMaster.getRegionsInTransition()) { 462 RegionInfo regionInfo = regionState.getRegionInfo(); 463 LOG.debug("Region in transition after stopping FN's: " + regionInfo); 464 rit.add(regionInfo); 465 assertTrue("Region: " + regionInfo + " should be RIT", 466 regionStatesBeforeMaster.getRegionState(regionInfo).isFailedOpen()); 467 assertEquals("Region: " + regionInfo + " does not belong to table: " + tableName, 468 tableName, regionInfo.getTable()); 469 } 470 471 Configuration conf = cluster.getConf(); 472 conf.setInt(ServerManager.WAIT_ON_REGIONSERVERS_MINTOSTART, 473 SLAVES - FavoredNodeAssignmentHelper.FAVORED_NODES_NUM); 474 475 cluster.stopMaster(master.getServerName()); 476 cluster.waitForMasterToStop(master.getServerName(), 60000); 477 478 cluster.startMaster(); 479 cluster.waitForActiveAndReadyMaster(); 480 master = cluster.getMaster(); 481 fnm = master.getFavoredNodesManager(); 482 483 RegionStates regionStates = master.getAssignmentManager().getRegionStates(); 484 assertTrue("Region: " + region + " should be RIT", 485 regionStates.getRegionState(region).isFailedOpen()); 486 487 for (RegionInfo regionInfo : rit) { 488 assertTrue("Region: " + regionInfo + " should be RIT", 489 regionStates.getRegionState(regionInfo).isFailedOpen()); 490 } 491 492 // Regenerate FN and assign, everything else should be fine 493 List<ServerName> serversForNewFN = Lists.newArrayList(); 494 for (ServerName sn : admin.getClusterMetrics(EnumSet.of(Option.LIVE_SERVERS)) 495 .getLiveServerMetrics().keySet()) { 496 serversForNewFN.add(ServerName.valueOf(sn.getHostname(), sn.getPort(), NON_STARTCODE)); 497 } 498 499 FavoredNodeAssignmentHelper helper = new FavoredNodeAssignmentHelper(serversForNewFN, conf); 500 helper.initialize(); 501 502 for (RegionInfo regionInfo : rit) { 503 List<ServerName> newFavoredNodes = helper.generateFavoredNodes(regionInfo); 504 assertNotNull(newFavoredNodes); 505 assertEquals(FavoredNodeAssignmentHelper.FAVORED_NODES_NUM, newFavoredNodes.size()); 506 LOG.info("Region: " + regionInfo.getEncodedName() + " FN: " + newFavoredNodes); 507 508 Map<RegionInfo, List<ServerName>> regionFNMap = Maps.newHashMap(); 509 regionFNMap.put(regionInfo, newFavoredNodes); 510 fnm.updateFavoredNodes(regionFNMap); 511 LOG.info("Assigning region: " + regionInfo.getEncodedName()); 512 admin.assign(regionInfo.getEncodedNameAsBytes()); 513 } 514 TEST_UTIL.waitUntilNoRegionsInTransition(60000); 515 assertEquals("Not all regions are online", REGION_NUM, admin.getTableRegions(tableName).size()); 516 517 admin.setBalancerRunning(true, true); 518 assertTrue("Balancer did not run", admin.balancer()); 519 TEST_UTIL.waitUntilNoRegionsInTransition(60000); 520 521 checkFavoredNodeAssignments(tableName, fnm, regionStates); 522 } 523 524 private void checkFavoredNodeAssignments(TableName tableName, FavoredNodesManager fnm, 525 RegionStates regionStates) throws IOException { 526 for (RegionInfo hri : admin.getTableRegions(tableName)) { 527 ServerName host = regionStates.getRegionServerOfRegion(hri); 528 assertNotNull("Region: " + hri.getEncodedName() + " not on FN, current: " + host 529 + " FN list: " + fnm.getFavoredNodes(hri), 530 FavoredNodesPlan.getFavoredServerPosition(fnm.getFavoredNodes(hri), host)); 531 } 532 } 533 534 private void stopServersAndWaitUntilProcessed(List<ServerName> currentFN) throws Exception { 535 for (ServerName sn : currentFN) { 536 for (JVMClusterUtil.RegionServerThread rst : cluster.getLiveRegionServerThreads()) { 537 if (ServerName.isSameAddress(sn, rst.getRegionServer().getServerName())) { 538 LOG.info("Shutting down server: " + sn); 539 cluster.stopRegionServer(rst.getRegionServer().getServerName()); 540 cluster.waitForRegionServerToStop(rst.getRegionServer().getServerName(), 60000); 541 } 542 } 543 } 544 545 // Wait until dead servers are processed. 546 TEST_UTIL.waitFor(60000, new Waiter.Predicate<Exception>() { 547 @Override 548 public boolean evaluate() throws Exception { 549 return !master.getServerManager().areDeadServersInProgress(); 550 } 551 }); 552 553 assertEquals("Not all servers killed", 554 SLAVES - currentFN.size(), cluster.getLiveRegionServerThreads().size()); 555 } 556 557 private void compactTable(TableName tableName) throws IOException { 558 for(JVMClusterUtil.RegionServerThread t : cluster.getRegionServerThreads()) { 559 for(HRegion region : t.getRegionServer().getRegions(tableName)) { 560 region.compact(true); 561 } 562 } 563 } 564}