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.favored; 020 021import java.util.List; 022import java.util.Map; 023import java.util.concurrent.ConcurrentHashMap; 024 025import org.apache.hadoop.hbase.ServerName; 026import org.apache.hadoop.hbase.client.RegionInfo; 027import org.apache.yetus.audience.InterfaceAudience; 028 029/** 030 * This class contains the mapping information between each region name and 031 * its favored region server list. Used by {@link FavoredNodeLoadBalancer} set 032 * of classes and from unit tests (hence the class is public) 033 * 034 * All the access to this class is thread-safe. 035 */ 036@InterfaceAudience.Private 037public class FavoredNodesPlan { 038 039 /** the map between each region name and its favored region server list */ 040 private Map<String, List<ServerName>> favoredNodesMap; 041 042 public static enum Position { 043 PRIMARY, 044 SECONDARY, 045 TERTIARY 046 } 047 048 public FavoredNodesPlan() { 049 favoredNodesMap = new ConcurrentHashMap<>(); 050 } 051 052 /** 053 * Update an assignment to the plan 054 * @param region 055 * @param servers 056 */ 057 public void updateFavoredNodesMap(RegionInfo region, List<ServerName> servers) { 058 if (region == null || servers == null || servers.isEmpty()) { 059 return; 060 } 061 this.favoredNodesMap.put(region.getRegionNameAsString(), servers); 062 } 063 064 /** 065 * Remove a favored node assignment 066 * @param region region 067 * @return the list of favored region server for this region based on the plan 068 */ 069 public List<ServerName> removeFavoredNodes(RegionInfo region) { 070 return favoredNodesMap.remove(region.getRegionNameAsString()); 071 } 072 073 /** 074 * @param region 075 * @return the list of favored region server for this region based on the plan 076 */ 077 public List<ServerName> getFavoredNodes(RegionInfo region) { 078 return favoredNodesMap.get(region.getRegionNameAsString()); 079 } 080 081 /** 082 * Return the position of the server in the favoredNodes list. Assumes the 083 * favoredNodes list is of size 3. 084 * @param favoredNodes 085 * @param server 086 * @return position 087 */ 088 public static Position getFavoredServerPosition( 089 List<ServerName> favoredNodes, ServerName server) { 090 if (favoredNodes == null || server == null || 091 favoredNodes.size() != FavoredNodeAssignmentHelper.FAVORED_NODES_NUM) { 092 return null; 093 } 094 for (Position p : Position.values()) { 095 if (ServerName.isSameAddress(favoredNodes.get(p.ordinal()),server)) { 096 return p; 097 } 098 } 099 return null; 100 } 101 102 /** 103 * @return the mapping between each region to its favored region server list 104 */ 105 public Map<String, List<ServerName>> getAssignmentMap() { 106 return favoredNodesMap; 107 } 108 109 @Override 110 public boolean equals(Object o) { 111 if (this == o) { 112 return true; 113 } 114 if (o == null) { 115 return false; 116 } 117 if (getClass() != o.getClass()) { 118 return false; 119 } 120 // To compare the map from objec o is identical to current assignment map. 121 Map<String, List<ServerName>> comparedMap = ((FavoredNodesPlan)o).getAssignmentMap(); 122 123 // compare the size 124 if (comparedMap.size() != this.favoredNodesMap.size()) 125 return false; 126 127 // compare each element in the assignment map 128 for (Map.Entry<String, List<ServerName>> entry : 129 comparedMap.entrySet()) { 130 List<ServerName> serverList = this.favoredNodesMap.get(entry.getKey()); 131 if (serverList == null && entry.getValue() != null) { 132 return false; 133 } else if (serverList != null && !serverList.equals(entry.getValue())) { 134 return false; 135 } 136 } 137 return true; 138 } 139 140 @Override 141 public int hashCode() { 142 return favoredNodesMap.hashCode(); 143 } 144}