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