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