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 java.text.DecimalFormat; 021import java.util.ArrayList; 022import java.util.HashMap; 023import java.util.HashSet; 024import java.util.List; 025import java.util.Map; 026import java.util.Set; 027import org.apache.hadoop.hbase.ServerName; 028import org.apache.hadoop.hbase.TableName; 029import org.apache.hadoop.hbase.client.RegionInfo; 030import org.apache.hadoop.hbase.favored.FavoredNodeAssignmentHelper; 031import org.apache.hadoop.hbase.favored.FavoredNodesPlan; 032import org.apache.yetus.audience.InterfaceAudience; 033import org.slf4j.Logger; 034import org.slf4j.LoggerFactory; 035 036/** 037 * Helper class that is used by RegionPlacementMaintainer to print information for favored nodes 038 */ 039@InterfaceAudience.Private 040public class AssignmentVerificationReport { 041 private static final Logger LOG = 042 LoggerFactory.getLogger(AssignmentVerificationReport.class.getName()); 043 044 private TableName tableName = null; 045 private boolean enforceLocality = false; 046 private boolean isFilledUp = false; 047 048 private int totalRegions = 0; 049 private int totalRegionServers = 0; 050 // for unassigned regions 051 private List<RegionInfo> unAssignedRegionsList = new ArrayList<>(); 052 053 // For regions without valid favored nodes 054 private List<RegionInfo> regionsWithoutValidFavoredNodes = new ArrayList<>(); 055 056 // For regions not running on the favored nodes 057 private List<RegionInfo> nonFavoredAssignedRegionList = new ArrayList<>(); 058 059 // For regions running on the favored nodes 060 private int totalFavoredAssignments = 0; 061 private int[] favoredNodes = new int[FavoredNodeAssignmentHelper.FAVORED_NODES_NUM]; 062 private float[] favoredNodesLocalitySummary = 063 new float[FavoredNodeAssignmentHelper.FAVORED_NODES_NUM]; 064 private float actualLocalitySummary = 0; 065 066 // For region balancing information 067 private float avgRegionsOnRS = 0; 068 private int maxRegionsOnRS = 0; 069 private int minRegionsOnRS = Integer.MAX_VALUE; 070 private Set<ServerName> mostLoadedRSSet = new HashSet<>(); 071 private Set<ServerName> leastLoadedRSSet = new HashSet<>(); 072 073 private float avgDispersionScore = 0; 074 private float maxDispersionScore = 0; 075 private Set<ServerName> maxDispersionScoreServerSet = new HashSet<>(); 076 private float minDispersionScore = Float.MAX_VALUE; 077 private Set<ServerName> minDispersionScoreServerSet = new HashSet<>(); 078 079 private float avgDispersionNum = 0; 080 private float maxDispersionNum = 0; 081 private Set<ServerName> maxDispersionNumServerSet = new HashSet<>(); 082 private float minDispersionNum = Float.MAX_VALUE; 083 private Set<ServerName> minDispersionNumServerSet = new HashSet<>(); 084 085 public void fillUp(TableName tableName, SnapshotOfRegionAssignmentFromMeta snapshot, 086 Map<String, Map<String, Float>> regionLocalityMap) { 087 // Set the table name 088 this.tableName = tableName; 089 090 // Get all the regions for this table 091 List<RegionInfo> regionInfoList = snapshot.getTableToRegionMap().get(tableName); 092 // Get the total region num for the current table 093 this.totalRegions = regionInfoList.size(); 094 095 // Get the existing assignment plan 096 FavoredNodesPlan favoredNodesAssignment = snapshot.getExistingAssignmentPlan(); 097 // Get the region to region server mapping 098 Map<RegionInfo, ServerName> currentAssignment = snapshot.getRegionToRegionServerMap(); 099 // Initialize the server to its hosing region counter map 100 Map<ServerName, Integer> serverToHostingRegionCounterMap = new HashMap<>(); 101 102 Map<ServerName, Integer> primaryRSToRegionCounterMap = new HashMap<>(); 103 Map<ServerName, Set<ServerName>> primaryToSecTerRSMap = new HashMap<>(); 104 105 // Check the favored nodes and its locality information 106 // Also keep tracker of the most loaded and least loaded region servers 107 for (RegionInfo region : regionInfoList) { 108 try { 109 ServerName currentRS = currentAssignment.get(region); 110 // Handle unassigned regions 111 if (currentRS == null) { 112 unAssignedRegionsList.add(region); 113 continue; 114 } 115 116 // Keep updating the server to is hosting region counter map 117 Integer hostRegionCounter = serverToHostingRegionCounterMap.get(currentRS); 118 if (hostRegionCounter == null) { 119 hostRegionCounter = Integer.valueOf(0); 120 } 121 hostRegionCounter = hostRegionCounter.intValue() + 1; 122 serverToHostingRegionCounterMap.put(currentRS, hostRegionCounter); 123 124 // Get the favored nodes from the assignment plan and verify it. 125 List<ServerName> favoredNodes = favoredNodesAssignment.getFavoredNodes(region); 126 if ( 127 favoredNodes == null 128 || favoredNodes.size() != FavoredNodeAssignmentHelper.FAVORED_NODES_NUM 129 ) { 130 regionsWithoutValidFavoredNodes.add(region); 131 continue; 132 } 133 // Get the primary, secondary and tertiary region server 134 ServerName primaryRS = favoredNodes.get(FavoredNodesPlan.Position.PRIMARY.ordinal()); 135 ServerName secondaryRS = favoredNodes.get(FavoredNodesPlan.Position.SECONDARY.ordinal()); 136 ServerName tertiaryRS = favoredNodes.get(FavoredNodesPlan.Position.TERTIARY.ordinal()); 137 138 // Update the primary rs to its region set map 139 Integer regionCounter = primaryRSToRegionCounterMap.get(primaryRS); 140 if (regionCounter == null) { 141 regionCounter = Integer.valueOf(0); 142 } 143 regionCounter = regionCounter.intValue() + 1; 144 primaryRSToRegionCounterMap.put(primaryRS, regionCounter); 145 146 // Update the primary rs to secondary and tertiary rs map 147 Set<ServerName> secAndTerSet = primaryToSecTerRSMap.get(primaryRS); 148 if (secAndTerSet == null) { 149 secAndTerSet = new HashSet<>(); 150 } 151 secAndTerSet.add(secondaryRS); 152 secAndTerSet.add(tertiaryRS); 153 primaryToSecTerRSMap.put(primaryRS, secAndTerSet); 154 155 // Get the position of the current region server in the favored nodes list 156 FavoredNodesPlan.Position favoredNodePosition = 157 FavoredNodesPlan.getFavoredServerPosition(favoredNodes, currentRS); 158 159 // Handle the non favored assignment. 160 if (favoredNodePosition == null) { 161 nonFavoredAssignedRegionList.add(region); 162 continue; 163 } 164 // Increase the favored nodes assignment. 165 this.favoredNodes[favoredNodePosition.ordinal()]++; 166 totalFavoredAssignments++; 167 168 // Summary the locality information for each favored nodes 169 if (regionLocalityMap != null) { 170 // Set the enforce locality as true; 171 this.enforceLocality = true; 172 173 // Get the region degree locality map 174 Map<String, Float> regionDegreeLocalityMap = 175 regionLocalityMap.get(region.getEncodedName()); 176 if (regionDegreeLocalityMap == null) { 177 continue; // ignore the region which doesn't have any store files. 178 } 179 180 // Get the locality summary for each favored nodes 181 for (FavoredNodesPlan.Position p : FavoredNodesPlan.Position.values()) { 182 ServerName favoredNode = favoredNodes.get(p.ordinal()); 183 // Get the locality for the current favored nodes 184 Float locality = regionDegreeLocalityMap.get(favoredNode.getHostname()); 185 if (locality != null) { 186 this.favoredNodesLocalitySummary[p.ordinal()] += locality; 187 } 188 } 189 190 // Get the locality summary for the current region server 191 Float actualLocality = regionDegreeLocalityMap.get(currentRS.getHostname()); 192 if (actualLocality != null) { 193 this.actualLocalitySummary += actualLocality; 194 } 195 } 196 } catch (Exception e) { 197 LOG.error("Cannot verify the region assignment for region " 198 + ((region == null) ? " null " : region.getRegionNameAsString()) + "because of " + e); 199 } 200 } 201 202 float dispersionScoreSummary = 0; 203 float dispersionNumSummary = 0; 204 // Calculate the secondary score for each primary region server 205 for (Map.Entry<ServerName, Integer> entry : primaryRSToRegionCounterMap.entrySet()) { 206 ServerName primaryRS = entry.getKey(); 207 Integer regionsOnPrimary = entry.getValue(); 208 209 // Process the dispersion number and score 210 float dispersionScore = 0; 211 int dispersionNum = 0; 212 if (primaryToSecTerRSMap.get(primaryRS) != null && regionsOnPrimary.intValue() != 0) { 213 dispersionNum = primaryToSecTerRSMap.get(primaryRS).size(); 214 dispersionScore = dispersionNum / ((float) regionsOnPrimary.intValue() * 2); 215 } 216 // Update the max dispersion score 217 if (dispersionScore > this.maxDispersionScore) { 218 this.maxDispersionScoreServerSet.clear(); 219 this.maxDispersionScoreServerSet.add(primaryRS); 220 this.maxDispersionScore = dispersionScore; 221 } else if (dispersionScore == this.maxDispersionScore) { 222 this.maxDispersionScoreServerSet.add(primaryRS); 223 } 224 225 // Update the max dispersion num 226 if (dispersionNum > this.maxDispersionNum) { 227 this.maxDispersionNumServerSet.clear(); 228 this.maxDispersionNumServerSet.add(primaryRS); 229 this.maxDispersionNum = dispersionNum; 230 } else if (dispersionNum == this.maxDispersionNum) { 231 this.maxDispersionNumServerSet.add(primaryRS); 232 } 233 234 // Update the min dispersion score 235 if (dispersionScore < this.minDispersionScore) { 236 this.minDispersionScoreServerSet.clear(); 237 this.minDispersionScoreServerSet.add(primaryRS); 238 this.minDispersionScore = dispersionScore; 239 } else if (dispersionScore == this.minDispersionScore) { 240 this.minDispersionScoreServerSet.add(primaryRS); 241 } 242 243 // Update the min dispersion num 244 if (dispersionNum < this.minDispersionNum) { 245 this.minDispersionNumServerSet.clear(); 246 this.minDispersionNumServerSet.add(primaryRS); 247 this.minDispersionNum = dispersionNum; 248 } else if (dispersionNum == this.minDispersionNum) { 249 this.minDispersionNumServerSet.add(primaryRS); 250 } 251 252 dispersionScoreSummary += dispersionScore; 253 dispersionNumSummary += dispersionNum; 254 } 255 256 // Update the avg dispersion score 257 if (primaryRSToRegionCounterMap.keySet().size() != 0) { 258 this.avgDispersionScore = 259 dispersionScoreSummary / (float) primaryRSToRegionCounterMap.keySet().size(); 260 this.avgDispersionNum = 261 dispersionNumSummary / (float) primaryRSToRegionCounterMap.keySet().size(); 262 } 263 264 // Fill up the most loaded and least loaded region server information 265 for (Map.Entry<ServerName, Integer> entry : serverToHostingRegionCounterMap.entrySet()) { 266 ServerName currentRS = entry.getKey(); 267 int hostRegionCounter = entry.getValue().intValue(); 268 269 // Update the most loaded region server list and maxRegionsOnRS 270 if (hostRegionCounter > this.maxRegionsOnRS) { 271 maxRegionsOnRS = hostRegionCounter; 272 this.mostLoadedRSSet.clear(); 273 this.mostLoadedRSSet.add(currentRS); 274 } else if (hostRegionCounter == this.maxRegionsOnRS) { 275 this.mostLoadedRSSet.add(currentRS); 276 } 277 278 // Update the least loaded region server list and minRegionsOnRS 279 if (hostRegionCounter < this.minRegionsOnRS) { 280 this.minRegionsOnRS = hostRegionCounter; 281 this.leastLoadedRSSet.clear(); 282 this.leastLoadedRSSet.add(currentRS); 283 } else if (hostRegionCounter == this.minRegionsOnRS) { 284 this.leastLoadedRSSet.add(currentRS); 285 } 286 } 287 288 // and total region servers 289 this.totalRegionServers = serverToHostingRegionCounterMap.keySet().size(); 290 this.avgRegionsOnRS = 291 (totalRegionServers == 0) ? 0 : (totalRegions / (float) totalRegionServers); 292 // Set the isFilledUp as true 293 isFilledUp = true; 294 } 295 296 /** 297 * Use this to project the dispersion scores 298 */ 299 public void fillUpDispersion(TableName tableName, SnapshotOfRegionAssignmentFromMeta snapshot, 300 FavoredNodesPlan newPlan) { 301 // Set the table name 302 this.tableName = tableName; 303 // Get all the regions for this table 304 List<RegionInfo> regionInfoList = snapshot.getTableToRegionMap().get(tableName); 305 // Get the total region num for the current table 306 this.totalRegions = regionInfoList.size(); 307 FavoredNodesPlan plan = null; 308 if (newPlan == null) { 309 plan = snapshot.getExistingAssignmentPlan(); 310 } else { 311 plan = newPlan; 312 } 313 // Get the region to region server mapping 314 Map<ServerName, Integer> primaryRSToRegionCounterMap = new HashMap<>(); 315 Map<ServerName, Set<ServerName>> primaryToSecTerRSMap = new HashMap<>(); 316 317 // Check the favored nodes and its locality information 318 // Also keep tracker of the most loaded and least loaded region servers 319 for (RegionInfo region : regionInfoList) { 320 try { 321 // Get the favored nodes from the assignment plan and verify it. 322 List<ServerName> favoredNodes = plan.getFavoredNodes(region); 323 if ( 324 favoredNodes == null 325 || favoredNodes.size() != FavoredNodeAssignmentHelper.FAVORED_NODES_NUM 326 ) { 327 regionsWithoutValidFavoredNodes.add(region); 328 continue; 329 } 330 // Get the primary, secondary and tertiary region server 331 ServerName primaryRS = favoredNodes.get(FavoredNodesPlan.Position.PRIMARY.ordinal()); 332 ServerName secondaryRS = favoredNodes.get(FavoredNodesPlan.Position.SECONDARY.ordinal()); 333 ServerName tertiaryRS = favoredNodes.get(FavoredNodesPlan.Position.TERTIARY.ordinal()); 334 335 // Update the primary rs to its region set map 336 Integer regionCounter = primaryRSToRegionCounterMap.get(primaryRS); 337 if (regionCounter == null) { 338 regionCounter = Integer.valueOf(0); 339 } 340 regionCounter = regionCounter.intValue() + 1; 341 primaryRSToRegionCounterMap.put(primaryRS, regionCounter); 342 343 // Update the primary rs to secondary and tertiary rs map 344 Set<ServerName> secAndTerSet = primaryToSecTerRSMap.get(primaryRS); 345 if (secAndTerSet == null) { 346 secAndTerSet = new HashSet<>(); 347 } 348 secAndTerSet.add(secondaryRS); 349 secAndTerSet.add(tertiaryRS); 350 primaryToSecTerRSMap.put(primaryRS, secAndTerSet); 351 } catch (Exception e) { 352 LOG.error("Cannot verify the region assignment for region " 353 + ((region == null) ? " null " : region.getRegionNameAsString()) + "because of " + e); 354 } 355 } 356 float dispersionScoreSummary = 0; 357 float dispersionNumSummary = 0; 358 // Calculate the secondary score for each primary region server 359 for (Map.Entry<ServerName, Integer> entry : primaryRSToRegionCounterMap.entrySet()) { 360 ServerName primaryRS = entry.getKey(); 361 Integer regionsOnPrimary = entry.getValue(); 362 363 // Process the dispersion number and score 364 float dispersionScore = 0; 365 int dispersionNum = 0; 366 if (primaryToSecTerRSMap.get(primaryRS) != null && regionsOnPrimary.intValue() != 0) { 367 dispersionNum = primaryToSecTerRSMap.get(primaryRS).size(); 368 dispersionScore = dispersionNum / ((float) regionsOnPrimary.intValue() * 2); 369 } 370 371 // Update the max dispersion num 372 if (dispersionNum > this.maxDispersionNum) { 373 this.maxDispersionNumServerSet.clear(); 374 this.maxDispersionNumServerSet.add(primaryRS); 375 this.maxDispersionNum = dispersionNum; 376 } else if (dispersionNum == this.maxDispersionNum) { 377 this.maxDispersionNumServerSet.add(primaryRS); 378 } 379 380 // Update the min dispersion score 381 if (dispersionScore < this.minDispersionScore) { 382 this.minDispersionScoreServerSet.clear(); 383 this.minDispersionScoreServerSet.add(primaryRS); 384 this.minDispersionScore = dispersionScore; 385 } else if (dispersionScore == this.minDispersionScore) { 386 this.minDispersionScoreServerSet.add(primaryRS); 387 } 388 389 // Update the min dispersion num 390 if (dispersionNum < this.minDispersionNum) { 391 this.minDispersionNumServerSet.clear(); 392 this.minDispersionNumServerSet.add(primaryRS); 393 this.minDispersionNum = dispersionNum; 394 } else if (dispersionNum == this.minDispersionNum) { 395 this.minDispersionNumServerSet.add(primaryRS); 396 } 397 398 dispersionScoreSummary += dispersionScore; 399 dispersionNumSummary += dispersionNum; 400 } 401 402 // Update the avg dispersion score 403 if (primaryRSToRegionCounterMap.keySet().size() != 0) { 404 this.avgDispersionScore = 405 dispersionScoreSummary / (float) primaryRSToRegionCounterMap.keySet().size(); 406 this.avgDispersionNum = 407 dispersionNumSummary / (float) primaryRSToRegionCounterMap.keySet().size(); 408 } 409 } 410 411 /** 412 * Return a list which contains 3 elements: average dispersion score, max dispersion score and min 413 * dispersion score as first, second and third elements, respectively. 414 */ 415 public List<Float> getDispersionInformation() { 416 List<Float> dispersion = new ArrayList<>(); 417 dispersion.add(avgDispersionScore); 418 dispersion.add(maxDispersionScore); 419 dispersion.add(minDispersionScore); 420 return dispersion; 421 } 422 423 public void print(boolean isDetailMode) { 424 if (!isFilledUp) { 425 System.err.println("[Error] Region assignment verification report" + "hasn't been filled up"); 426 } 427 DecimalFormat df = new java.text.DecimalFormat("#.##"); 428 429 // Print some basic information 430 System.out.println("Region Assignment Verification for Table: " + tableName 431 + "\n\tTotal regions : " + totalRegions); 432 433 // Print the number of regions on each kinds of the favored nodes 434 System.out.println("\tTotal regions on favored nodes " + totalFavoredAssignments); 435 for (FavoredNodesPlan.Position p : FavoredNodesPlan.Position.values()) { 436 System.out.println( 437 "\t\tTotal regions on " + p.toString() + " region servers: " + favoredNodes[p.ordinal()]); 438 } 439 // Print the number of regions in each kinds of invalid assignment 440 System.out.println("\tTotal unassigned regions: " + unAssignedRegionsList.size()); 441 if (isDetailMode) { 442 for (RegionInfo region : unAssignedRegionsList) { 443 System.out.println("\t\t" + region.getRegionNameAsString()); 444 } 445 } 446 447 System.out 448 .println("\tTotal regions NOT on favored nodes: " + nonFavoredAssignedRegionList.size()); 449 if (isDetailMode) { 450 for (RegionInfo region : nonFavoredAssignedRegionList) { 451 System.out.println("\t\t" + region.getRegionNameAsString()); 452 } 453 } 454 455 System.out 456 .println("\tTotal regions without favored nodes: " + regionsWithoutValidFavoredNodes.size()); 457 if (isDetailMode) { 458 for (RegionInfo region : regionsWithoutValidFavoredNodes) { 459 System.out.println("\t\t" + region.getRegionNameAsString()); 460 } 461 } 462 463 // Print the locality information if enabled 464 if (this.enforceLocality && totalRegions != 0) { 465 // Print the actual locality for this table 466 float actualLocality = 100 * this.actualLocalitySummary / (float) totalRegions; 467 System.out.println("\n\tThe actual avg locality is " + df.format(actualLocality) + " %"); 468 469 // Print the expected locality if regions are placed on the each kinds of 470 // favored nodes 471 for (FavoredNodesPlan.Position p : FavoredNodesPlan.Position.values()) { 472 float avgLocality = 100 * (favoredNodesLocalitySummary[p.ordinal()] / (float) totalRegions); 473 System.out.println("\t\tThe expected avg locality if all regions" + " on the " 474 + p.toString() + " region servers: " + df.format(avgLocality) + " %"); 475 } 476 } 477 478 // Print the region balancing information 479 System.out.println("\n\tTotal hosting region servers: " + totalRegionServers); 480 // Print the region balance information 481 if (totalRegionServers != 0) { 482 System.out.println("\tAvg dispersion num: " + df.format(avgDispersionNum) 483 + " hosts;\tMax dispersion num: " + df.format(maxDispersionNum) 484 + " hosts;\tMin dispersion num: " + df.format(minDispersionNum) + " hosts;"); 485 486 System.out.println("\t\tThe number of the region servers with the max" + " dispersion num: " 487 + this.maxDispersionNumServerSet.size()); 488 if (isDetailMode) { 489 printHServerAddressSet(maxDispersionNumServerSet); 490 } 491 492 System.out.println("\t\tThe number of the region servers with the min" + " dispersion num: " 493 + this.minDispersionNumServerSet.size()); 494 if (isDetailMode) { 495 printHServerAddressSet(maxDispersionNumServerSet); 496 } 497 498 System.out.println("\tAvg dispersion score: " + df.format(avgDispersionScore) 499 + ";\tMax dispersion score: " + df.format(maxDispersionScore) + ";\tMin dispersion score: " 500 + df.format(minDispersionScore) + ";"); 501 502 System.out.println("\t\tThe number of the region servers with the max" + " dispersion score: " 503 + this.maxDispersionScoreServerSet.size()); 504 if (isDetailMode) { 505 printHServerAddressSet(maxDispersionScoreServerSet); 506 } 507 508 System.out.println("\t\tThe number of the region servers with the min" + " dispersion score: " 509 + this.minDispersionScoreServerSet.size()); 510 if (isDetailMode) { 511 printHServerAddressSet(minDispersionScoreServerSet); 512 } 513 514 System.out.println("\tAvg regions/region server: " + df.format(avgRegionsOnRS) 515 + ";\tMax regions/region server: " + maxRegionsOnRS + ";\tMin regions/region server: " 516 + minRegionsOnRS + ";"); 517 518 // Print the details about the most loaded region servers 519 System.out 520 .println("\t\tThe number of the most loaded region servers: " + mostLoadedRSSet.size()); 521 if (isDetailMode) { 522 printHServerAddressSet(mostLoadedRSSet); 523 } 524 525 // Print the details about the least loaded region servers 526 System.out 527 .println("\t\tThe number of the least loaded region servers: " + leastLoadedRSSet.size()); 528 if (isDetailMode) { 529 printHServerAddressSet(leastLoadedRSSet); 530 } 531 } 532 System.out.println("=============================="); 533 } 534 535 /** 536 * Return the unassigned regions 537 * @return unassigned regions 538 */ 539 List<RegionInfo> getUnassignedRegions() { 540 return unAssignedRegionsList; 541 } 542 543 /** 544 * Return the regions without favored nodes 545 * @return regions without favored nodes 546 */ 547 List<RegionInfo> getRegionsWithoutValidFavoredNodes() { 548 return regionsWithoutValidFavoredNodes; 549 } 550 551 /** 552 * Return the regions not assigned to its favored nodes 553 * @return regions not assigned to its favored nodes 554 */ 555 List<RegionInfo> getNonFavoredAssignedRegions() { 556 return nonFavoredAssignedRegionList; 557 } 558 559 /** 560 * Return the number of regions assigned to their favored nodes 561 * @return number of regions assigned to their favored nodes 562 */ 563 int getTotalFavoredAssignments() { 564 return totalFavoredAssignments; 565 } 566 567 /** 568 * Return the number of regions based on the position (primary/secondary/ tertiary) assigned to 569 * their favored nodes 570 * @return the number of regions 571 */ 572 int getNumRegionsOnFavoredNodeByPosition(FavoredNodesPlan.Position position) { 573 return favoredNodes[position.ordinal()]; 574 } 575 576 private void printHServerAddressSet(Set<ServerName> serverSet) { 577 if (serverSet == null) { 578 return; 579 } 580 int i = 0; 581 for (ServerName addr : serverSet) { 582 if (i++ % 3 == 0) { 583 System.out.print("\n\t\t\t"); 584 } 585 System.out.print(addr.getAddress() + " ; "); 586 } 587 System.out.println("\n"); 588 } 589}