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