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; 019 020import static org.junit.Assert.assertEquals; 021import static org.junit.Assert.assertNotNull; 022import static org.junit.Assert.assertNull; 023import static org.junit.Assert.assertTrue; 024import static org.junit.Assert.fail; 025 026import java.io.IOException; 027import java.net.InetSocketAddress; 028import java.util.ArrayList; 029import java.util.Arrays; 030import java.util.Collection; 031import java.util.HashMap; 032import java.util.List; 033import java.util.Map; 034import java.util.Random; 035import java.util.concurrent.ThreadLocalRandom; 036import java.util.concurrent.atomic.AtomicInteger; 037import org.apache.hadoop.conf.Configuration; 038import org.apache.hadoop.hbase.HBaseClassTestRule; 039import org.apache.hadoop.hbase.HBaseTestingUtility; 040import org.apache.hadoop.hbase.HColumnDescriptor; 041import org.apache.hadoop.hbase.HConstants; 042import org.apache.hadoop.hbase.HRegionLocation; 043import org.apache.hadoop.hbase.HTableDescriptor; 044import org.apache.hadoop.hbase.MetaTableAccessor; 045import org.apache.hadoop.hbase.MiniHBaseCluster; 046import org.apache.hadoop.hbase.NamespaceDescriptor; 047import org.apache.hadoop.hbase.ServerName; 048import org.apache.hadoop.hbase.TableName; 049import org.apache.hadoop.hbase.client.Admin; 050import org.apache.hadoop.hbase.client.Connection; 051import org.apache.hadoop.hbase.client.RegionInfo; 052import org.apache.hadoop.hbase.client.RegionLocator; 053import org.apache.hadoop.hbase.client.Result; 054import org.apache.hadoop.hbase.client.TableDescriptor; 055import org.apache.hadoop.hbase.favored.FavoredNodeAssignmentHelper; 056import org.apache.hadoop.hbase.favored.FavoredNodeLoadBalancer; 057import org.apache.hadoop.hbase.favored.FavoredNodesPlan; 058import org.apache.hadoop.hbase.favored.FavoredNodesPlan.Position; 059import org.apache.hadoop.hbase.regionserver.HRegion; 060import org.apache.hadoop.hbase.regionserver.HRegionServer; 061import org.apache.hadoop.hbase.regionserver.Region; 062import org.apache.hadoop.hbase.testclassification.MasterTests; 063import org.apache.hadoop.hbase.testclassification.MediumTests; 064import org.apache.hadoop.hbase.util.Bytes; 065import org.apache.hadoop.hbase.util.Pair; 066import org.apache.zookeeper.KeeperException; 067import org.junit.AfterClass; 068import org.junit.BeforeClass; 069import org.junit.ClassRule; 070import org.junit.Ignore; 071import org.junit.Test; 072import org.junit.experimental.categories.Category; 073import org.slf4j.Logger; 074import org.slf4j.LoggerFactory; 075 076@Category({ MasterTests.class, MediumTests.class }) 077public class TestRegionPlacement { 078 079 @ClassRule 080 public static final HBaseClassTestRule CLASS_RULE = 081 HBaseClassTestRule.forClass(TestRegionPlacement.class); 082 083 private static final Logger LOG = LoggerFactory.getLogger(TestRegionPlacement.class); 084 private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); 085 private final static int SLAVES = 10; 086 private static Connection CONNECTION; 087 private static Admin admin; 088 private static RegionPlacementMaintainer rp; 089 private static Position[] positions = Position.values(); 090 private int lastRegionOnPrimaryRSCount = 0; 091 private int REGION_NUM = 10; 092 private Map<RegionInfo, ServerName[]> favoredNodesAssignmentPlan = new HashMap<>(); 093 094 @BeforeClass 095 public static void setupBeforeClass() throws Exception { 096 Configuration conf = TEST_UTIL.getConfiguration(); 097 // Enable the favored nodes based load balancer 098 conf.setClass(HConstants.HBASE_MASTER_LOADBALANCER_CLASS, FavoredNodeLoadBalancer.class, 099 LoadBalancer.class); 100 conf.setBoolean("hbase.tests.use.shortcircuit.reads", false); 101 TEST_UTIL.startMiniCluster(SLAVES); 102 CONNECTION = TEST_UTIL.getConnection(); 103 admin = CONNECTION.getAdmin(); 104 rp = new RegionPlacementMaintainer(conf); 105 } 106 107 @AfterClass 108 public static void tearDownAfterClass() throws Exception { 109 TEST_UTIL.shutdownMiniCluster(); 110 } 111 112 @Ignore("Test for unfinished feature") 113 @Test 114 public void testRegionPlacement() throws Exception { 115 String tableStr = "testRegionAssignment"; 116 TableName table = TableName.valueOf(tableStr); 117 // Create a table with REGION_NUM regions. 118 createTable(table, REGION_NUM); 119 120 TEST_UTIL.waitTableAvailable(table); 121 122 // Verify all the user regions are assigned to the primary region server 123 // based on the plan 124 verifyRegionOnPrimaryRS(REGION_NUM); 125 126 FavoredNodesPlan currentPlan = rp.getRegionAssignmentSnapshot().getExistingAssignmentPlan(); 127 // Verify all the region server are update with the latest favored nodes 128 verifyRegionServerUpdated(currentPlan); 129 // Test Case 2: To verify whether the region placement tools can 130 // correctly update the new assignment plan to hbase:meta and Region Server. 131 // The new assignment plan is generated by shuffle the existing assignment 132 // plan by switching PRIMARY, SECONDARY and TERTIARY nodes. 133 // Shuffle the plan by switching the secondary region server with 134 // the tertiary. 135 136 // Shuffle the secondary with tertiary favored nodes 137 FavoredNodesPlan shuffledPlan = this.shuffleAssignmentPlan(currentPlan, 138 FavoredNodesPlan.Position.SECONDARY, FavoredNodesPlan.Position.TERTIARY); 139 // Let the region placement update the hbase:meta and Region Servers 140 rp.updateAssignmentPlan(shuffledPlan); 141 142 // Verify the region assignment. There are supposed to no region reassignment 143 // All the regions are still on the primary region server 144 verifyRegionAssignment(shuffledPlan, 0, REGION_NUM); 145 146 // Shuffle the plan by switching the primary with secondary and 147 // verify the region reassignment is consistent with the plan. 148 shuffledPlan = this.shuffleAssignmentPlan(currentPlan, FavoredNodesPlan.Position.PRIMARY, 149 FavoredNodesPlan.Position.SECONDARY); 150 151 // Let the region placement update the hbase:meta and Region Servers 152 rp.updateAssignmentPlan(shuffledPlan); 153 154 verifyRegionAssignment(shuffledPlan, REGION_NUM, REGION_NUM); 155 156 // also verify that the AssignmentVerificationReport has the correct information 157 RegionPlacementMaintainer rp = new RegionPlacementMaintainer(TEST_UTIL.getConfiguration()); 158 // we are interested in only one table (and hence one report) 159 rp.setTargetTableName(new String[] { tableStr }); 160 List<AssignmentVerificationReport> reports = rp.verifyRegionPlacement(false); 161 AssignmentVerificationReport report = reports.get(0); 162 assertTrue(report.getRegionsWithoutValidFavoredNodes().isEmpty()); 163 assertTrue(report.getNonFavoredAssignedRegions().isEmpty()); 164 assertTrue(report.getTotalFavoredAssignments() >= REGION_NUM); 165 assertTrue(report.getNumRegionsOnFavoredNodeByPosition(FavoredNodesPlan.Position.PRIMARY) != 0); 166 assertTrue( 167 report.getNumRegionsOnFavoredNodeByPosition(FavoredNodesPlan.Position.SECONDARY) == 0); 168 assertTrue( 169 report.getNumRegionsOnFavoredNodeByPosition(FavoredNodesPlan.Position.TERTIARY) == 0); 170 assertTrue(report.getUnassignedRegions().isEmpty()); 171 172 // Check when a RS stops, the regions get assigned to their secondary/tertiary 173 killRandomServerAndVerifyAssignment(); 174 175 // also verify that the AssignmentVerificationReport has the correct information 176 reports = rp.verifyRegionPlacement(false); 177 report = reports.get(0); 178 assertTrue(report.getRegionsWithoutValidFavoredNodes().isEmpty()); 179 assertTrue(report.getNonFavoredAssignedRegions().isEmpty()); 180 assertTrue(report.getTotalFavoredAssignments() >= REGION_NUM); 181 assertTrue(report.getNumRegionsOnFavoredNodeByPosition(FavoredNodesPlan.Position.PRIMARY) > 0); 182 assertTrue( 183 "secondary " 184 + report.getNumRegionsOnFavoredNodeByPosition(FavoredNodesPlan.Position.SECONDARY) 185 + " tertiary " 186 + report.getNumRegionsOnFavoredNodeByPosition(FavoredNodesPlan.Position.TERTIARY), 187 (report.getNumRegionsOnFavoredNodeByPosition(FavoredNodesPlan.Position.SECONDARY) > 0 188 || report.getNumRegionsOnFavoredNodeByPosition(FavoredNodesPlan.Position.TERTIARY) > 0)); 189 assertTrue((report.getNumRegionsOnFavoredNodeByPosition(FavoredNodesPlan.Position.PRIMARY) 190 + report.getNumRegionsOnFavoredNodeByPosition(FavoredNodesPlan.Position.SECONDARY) 191 + report.getNumRegionsOnFavoredNodeByPosition(FavoredNodesPlan.Position.TERTIARY)) 192 == REGION_NUM); 193 RegionPlacementMaintainer.printAssignmentPlan(currentPlan); 194 } 195 196 private void killRandomServerAndVerifyAssignment() 197 throws IOException, InterruptedException, KeeperException { 198 ServerName serverToKill = null; 199 int killIndex = 0; 200 Random rand = ThreadLocalRandom.current(); 201 ServerName metaServer = TEST_UTIL.getHBaseCluster().getServerHoldingMeta(); 202 LOG.debug("Server holding meta " + metaServer); 203 boolean isNamespaceServer = false; 204 do { 205 // kill a random non-meta server carrying at least one region 206 killIndex = rand.nextInt(SLAVES); 207 serverToKill = TEST_UTIL.getHBaseCluster().getRegionServer(killIndex).getServerName(); 208 Collection<HRegion> regs = 209 TEST_UTIL.getHBaseCluster().getRegionServer(killIndex).getOnlineRegionsLocalContext(); 210 isNamespaceServer = false; 211 for (HRegion r : regs) { 212 if ( 213 r.getRegionInfo().getTable().getNamespaceAsString() 214 .equals(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR) 215 ) { 216 isNamespaceServer = true; 217 break; 218 } 219 } 220 } while ( 221 ServerName.isSameAddress(metaServer, serverToKill) || isNamespaceServer 222 || TEST_UTIL.getHBaseCluster().getRegionServer(killIndex).getNumberOfOnlineRegions() == 0 223 ); 224 LOG.debug("Stopping RS " + serverToKill); 225 Map<RegionInfo, Pair<ServerName, ServerName>> regionsToVerify = new HashMap<>(); 226 // mark the regions to track 227 for (Map.Entry<RegionInfo, ServerName[]> entry : favoredNodesAssignmentPlan.entrySet()) { 228 ServerName s = entry.getValue()[0]; 229 if (ServerName.isSameAddress(s, serverToKill)) { 230 regionsToVerify.put(entry.getKey(), new Pair<>(entry.getValue()[1], entry.getValue()[2])); 231 LOG.debug("Adding " + entry.getKey() + " with sedcondary/tertiary " + entry.getValue()[1] 232 + " " + entry.getValue()[2]); 233 } 234 } 235 int orig = TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager().getNumRegionsOpened(); 236 TEST_UTIL.getHBaseCluster().stopRegionServer(serverToKill); 237 TEST_UTIL.getHBaseCluster().waitForRegionServerToStop(serverToKill, 60000); 238 int curr = TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager().getNumRegionsOpened(); 239 while (curr - orig < regionsToVerify.size()) { 240 LOG.debug("Waiting for " + regionsToVerify.size() + " to come online " + " Current #regions " 241 + curr + " Original #regions " + orig); 242 Thread.sleep(200); 243 curr = TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager().getNumRegionsOpened(); 244 } 245 // now verify 246 for (Map.Entry<RegionInfo, Pair<ServerName, ServerName>> entry : regionsToVerify.entrySet()) { 247 ServerName newDestination = TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager() 248 .getRegionStates().getRegionServerOfRegion(entry.getKey()); 249 Pair<ServerName, ServerName> secondaryTertiaryServers = entry.getValue(); 250 LOG.debug("New destination for region " + entry.getKey().getEncodedName() + " " 251 + newDestination + ". Secondary/Tertiary are " + secondaryTertiaryServers.getFirst() + "/" 252 + secondaryTertiaryServers.getSecond()); 253 if ( 254 !(ServerName.isSameAddress(newDestination, secondaryTertiaryServers.getFirst()) 255 || ServerName.isSameAddress(newDestination, secondaryTertiaryServers.getSecond())) 256 ) { 257 fail("Region " + entry.getKey() + " not present on any of the expected servers"); 258 } 259 } 260 // start(reinstate) region server since we killed one before 261 TEST_UTIL.getHBaseCluster().startRegionServer(); 262 } 263 264 /** 265 * Used to test the correctness of this class. 266 */ 267 @Ignore("Test for unfinished feature") 268 @Test 269 public void testRandomizedMatrix() { 270 int rows = 100; 271 int cols = 100; 272 float[][] matrix = new float[rows][cols]; 273 Random rand = ThreadLocalRandom.current(); 274 for (int i = 0; i < rows; i++) { 275 for (int j = 0; j < cols; j++) { 276 matrix[i][j] = rand.nextFloat(); 277 } 278 } 279 280 // Test that inverting a transformed matrix gives the original matrix. 281 RegionPlacementMaintainer.RandomizedMatrix rm = 282 new RegionPlacementMaintainer.RandomizedMatrix(rows, cols); 283 float[][] transformed = rm.transform(matrix); 284 float[][] invertedTransformed = rm.invert(transformed); 285 for (int i = 0; i < rows; i++) { 286 for (int j = 0; j < cols; j++) { 287 if (matrix[i][j] != invertedTransformed[i][j]) { 288 throw new RuntimeException(); 289 } 290 } 291 } 292 293 // Test that the indices on a transformed matrix can be inverted to give 294 // the same values on the original matrix. 295 int[] transformedIndices = new int[rows]; 296 for (int i = 0; i < rows; i++) { 297 transformedIndices[i] = rand.nextInt(cols); 298 } 299 int[] invertedTransformedIndices = rm.invertIndices(transformedIndices); 300 float[] transformedValues = new float[rows]; 301 float[] invertedTransformedValues = new float[rows]; 302 for (int i = 0; i < rows; i++) { 303 transformedValues[i] = transformed[i][transformedIndices[i]]; 304 invertedTransformedValues[i] = matrix[i][invertedTransformedIndices[i]]; 305 } 306 Arrays.sort(transformedValues); 307 Arrays.sort(invertedTransformedValues); 308 if (!Arrays.equals(transformedValues, invertedTransformedValues)) { 309 throw new RuntimeException(); 310 } 311 } 312 313 /** 314 * Shuffle the assignment plan by switching two favored node positions. 315 * @param plan The assignment plan 316 * @param p1 The first switch position 317 * @param p2 The second switch position 318 * @return the shuffled assignment plan 319 */ 320 private FavoredNodesPlan shuffleAssignmentPlan(FavoredNodesPlan plan, 321 FavoredNodesPlan.Position p1, FavoredNodesPlan.Position p2) throws IOException { 322 FavoredNodesPlan shuffledPlan = new FavoredNodesPlan(); 323 324 Map<String, RegionInfo> regionToHRegion = 325 rp.getRegionAssignmentSnapshot().getRegionNameToRegionInfoMap(); 326 for (Map.Entry<String, List<ServerName>> entry : plan.getAssignmentMap().entrySet()) { 327 328 // copy the server list from the original plan 329 List<ServerName> shuffledServerList = new ArrayList<>(); 330 shuffledServerList.addAll(entry.getValue()); 331 332 // start to shuffle 333 shuffledServerList.set(p1.ordinal(), entry.getValue().get(p2.ordinal())); 334 shuffledServerList.set(p2.ordinal(), entry.getValue().get(p1.ordinal())); 335 336 // update the plan 337 shuffledPlan.updateFavoredNodesMap(regionToHRegion.get(entry.getKey()), shuffledServerList); 338 } 339 return shuffledPlan; 340 } 341 342 /** 343 * To verify the region assignment status. It will check the assignment plan consistency between 344 * hbase:meta and region servers. Also it will verify weather the number of region movement and 345 * the number regions on the primary region server are expected nnnnn 346 */ 347 private void verifyRegionAssignment(FavoredNodesPlan plan, int regionMovementNum, 348 int numRegionsOnPrimaryRS) throws InterruptedException, IOException { 349 // Verify the assignment plan in hbase:meta is consistent with the expected plan. 350 verifyMETAUpdated(plan); 351 352 // Verify the number of region movement is expected 353 verifyRegionMovementNum(regionMovementNum); 354 355 // Verify the number of regions is assigned to the primary region server 356 // based on the plan is expected 357 verifyRegionOnPrimaryRS(numRegionsOnPrimaryRS); 358 359 // Verify all the online region server are updated with the assignment plan 360 verifyRegionServerUpdated(plan); 361 } 362 363 /** 364 * Verify the meta has updated to the latest assignment plan 365 * @param expectedPlan the region assignment plan 366 * @throws IOException if an IO problem is encountered 367 */ 368 private void verifyMETAUpdated(FavoredNodesPlan expectedPlan) throws IOException { 369 FavoredNodesPlan planFromMETA = rp.getRegionAssignmentSnapshot().getExistingAssignmentPlan(); 370 assertTrue("The assignment plan is NOT consistent with the expected plan ", 371 planFromMETA.equals(expectedPlan)); 372 } 373 374 /** 375 * Verify the number of region movement is expected 376 */ 377 private void verifyRegionMovementNum(int expected) throws InterruptedException, IOException { 378 MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster(); 379 HMaster m = cluster.getMaster(); 380 int lastRegionOpenedCount = m.getAssignmentManager().getNumRegionsOpened(); 381 // get the assignments start to execute 382 m.balance(); 383 384 int retry = 10; 385 long sleep = 3000; 386 int attempt = 0; 387 int currentRegionOpened, regionMovement; 388 do { 389 currentRegionOpened = m.getAssignmentManager().getNumRegionsOpened(); 390 regionMovement = currentRegionOpened - lastRegionOpenedCount; 391 LOG.debug("There are " + regionMovement + "/" + expected + " regions moved after " + attempt 392 + " attempts"); 393 Thread.sleep((++attempt) * sleep); 394 } while (regionMovement != expected && attempt <= retry); 395 396 // update the lastRegionOpenedCount 397 lastRegionOpenedCount = currentRegionOpened; 398 399 assertEquals("There are only " + regionMovement + " instead of " + expected 400 + " region movement for " + attempt + " attempts", expected, regionMovement); 401 } 402 403 /** 404 * Verify the number of user regions is assigned to the primary region server based on the plan is 405 * expected 406 * @param expectedNum the expected number of assigned regions n 407 */ 408 private void verifyRegionOnPrimaryRS(int expectedNum) throws IOException { 409 lastRegionOnPrimaryRSCount = getNumRegionisOnPrimaryRS(); 410 assertEquals( 411 "Only " + expectedNum + " of user regions running " + "on the primary region server", 412 expectedNum, lastRegionOnPrimaryRSCount); 413 } 414 415 /** 416 * Verify all the online region servers has been updated to the latest assignment plan nn 417 */ 418 private void verifyRegionServerUpdated(FavoredNodesPlan plan) throws IOException { 419 // Verify all region servers contain the correct favored nodes information 420 MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster(); 421 for (int i = 0; i < SLAVES; i++) { 422 HRegionServer rs = cluster.getRegionServer(i); 423 for (Region region : rs.getRegions(TableName.valueOf("testRegionAssignment"))) { 424 InetSocketAddress[] favoredSocketAddress = 425 rs.getFavoredNodesForRegion(region.getRegionInfo().getEncodedName()); 426 String regionName = region.getRegionInfo().getRegionNameAsString(); 427 List<ServerName> favoredServerList = plan.getAssignmentMap().get(regionName); 428 429 // All regions are supposed to have favored nodes, 430 // except for hbase:meta and ROOT 431 if (favoredServerList == null) { 432 TableDescriptor desc = region.getTableDescriptor(); 433 // Verify they are ROOT and hbase:meta regions since no favored nodes 434 assertNull(favoredSocketAddress); 435 assertTrue("User region " + region.getTableDescriptor().getTableName() 436 + " should have favored nodes", desc.isMetaRegion()); 437 } else { 438 // For user region, the favored nodes in the region server should be 439 // identical to favored nodes in the assignmentPlan 440 assertTrue(favoredSocketAddress.length == favoredServerList.size()); 441 assertTrue(favoredServerList.size() > 0); 442 for (int j = 0; j < favoredServerList.size(); j++) { 443 InetSocketAddress addrFromRS = favoredSocketAddress[j]; 444 InetSocketAddress addrFromPlan = InetSocketAddress.createUnresolved( 445 favoredServerList.get(j).getHostname(), favoredServerList.get(j).getPort()); 446 447 assertNotNull(addrFromRS); 448 assertNotNull(addrFromPlan); 449 assertTrue( 450 "Region server " + rs.getServerName().getAddress() + " has the " + positions[j] 451 + " for region " + region.getRegionInfo().getRegionNameAsString() + " is " 452 + addrFromRS + " which is inconsistent with the plan " + addrFromPlan, 453 addrFromRS.equals(addrFromPlan)); 454 } 455 } 456 } 457 } 458 } 459 460 /** 461 * Check whether regions are assigned to servers consistent with the explicit hints that are 462 * persisted in the hbase:meta table. Also keep track of the number of the regions are assigned to 463 * the primary region server. 464 * @return the number of regions are assigned to the primary region server n 465 */ 466 private int getNumRegionisOnPrimaryRS() throws IOException { 467 final AtomicInteger regionOnPrimaryNum = new AtomicInteger(0); 468 final AtomicInteger totalRegionNum = new AtomicInteger(0); 469 LOG.info("The start of region placement verification"); 470 MetaTableAccessor.Visitor visitor = new MetaTableAccessor.Visitor() { 471 @Override 472 public boolean visit(Result result) throws IOException { 473 try { 474 @SuppressWarnings("deprecation") 475 RegionInfo info = MetaTableAccessor.getRegionInfo(result); 476 if ( 477 info.getTable().getNamespaceAsString() 478 .equals(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR) 479 ) { 480 return true; 481 } 482 byte[] server = result.getValue(HConstants.CATALOG_FAMILY, HConstants.SERVER_QUALIFIER); 483 byte[] favoredNodes = result.getValue(HConstants.CATALOG_FAMILY, 484 FavoredNodeAssignmentHelper.FAVOREDNODES_QUALIFIER); 485 // Add the favored nodes into assignment plan 486 ServerName[] favoredServerList = 487 FavoredNodeAssignmentHelper.getFavoredNodesList(favoredNodes); 488 favoredNodesAssignmentPlan.put(info, favoredServerList); 489 490 Position[] positions = Position.values(); 491 if (info != null) { 492 totalRegionNum.incrementAndGet(); 493 if (server != null) { 494 ServerName serverName = ServerName.valueOf(Bytes.toString(server), -1); 495 if (favoredNodes != null) { 496 String placement = "[NOT FAVORED NODE]"; 497 for (int i = 0; i < favoredServerList.length; i++) { 498 if (favoredServerList[i].equals(serverName)) { 499 placement = positions[i].toString(); 500 if (i == Position.PRIMARY.ordinal()) { 501 regionOnPrimaryNum.incrementAndGet(); 502 } 503 break; 504 } 505 } 506 LOG.info(info.getRegionNameAsString() + " on " + serverName + " " + placement); 507 } else { 508 LOG.info(info.getRegionNameAsString() + " running on " + serverName 509 + " but there is no favored region server"); 510 } 511 } else { 512 LOG.info(info.getRegionNameAsString() + " not assigned to any server"); 513 } 514 } 515 return true; 516 } catch (RuntimeException e) { 517 LOG.error("Result=" + result); 518 throw e; 519 } 520 } 521 }; 522 MetaTableAccessor.fullScanRegions(CONNECTION, visitor); 523 LOG.info("There are " + regionOnPrimaryNum.intValue() + " out of " + totalRegionNum.intValue() 524 + " regions running on the primary" + " region servers"); 525 return regionOnPrimaryNum.intValue(); 526 } 527 528 /** 529 * Create a table with specified table name and region number. 530 * @param tableName the name of the table to be created 531 * @param regionNum number of regions to create n 532 */ 533 private static void createTable(TableName tableName, int regionNum) throws IOException { 534 int expectedRegions = regionNum; 535 byte[][] splitKeys = new byte[expectedRegions - 1][]; 536 for (int i = 1; i < expectedRegions; i++) { 537 byte splitKey = (byte) i; 538 splitKeys[i - 1] = new byte[] { splitKey, splitKey, splitKey }; 539 } 540 541 HTableDescriptor desc = new HTableDescriptor(tableName); 542 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY)); 543 admin.createTable(desc, splitKeys); 544 545 try (RegionLocator r = CONNECTION.getRegionLocator(tableName)) { 546 List<HRegionLocation> regions = r.getAllRegionLocations(); 547 assertEquals( 548 "Tried to create " + expectedRegions + " regions " + "but only found " + regions.size(), 549 expectedRegions, regions.size()); 550 } 551 } 552}