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