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