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.balancer; 019 020import com.google.errorprone.annotations.RestrictedApi; 021import java.io.IOException; 022import java.util.Collection; 023import java.util.Collections; 024import java.util.List; 025import java.util.Map; 026import java.util.function.Predicate; 027import java.util.function.Supplier; 028import org.apache.hadoop.conf.Configuration; 029import org.apache.hadoop.hbase.HDFSBlocksDistribution; 030import org.apache.hadoop.hbase.ServerMetrics; 031import org.apache.hadoop.hbase.ServerName; 032import org.apache.hadoop.hbase.TableDescriptors; 033import org.apache.hadoop.hbase.TableName; 034import org.apache.hadoop.hbase.client.BalancerDecision; 035import org.apache.hadoop.hbase.client.BalancerRejection; 036import org.apache.hadoop.hbase.client.Connection; 037import org.apache.hadoop.hbase.client.RegionInfo; 038import org.apache.hadoop.hbase.client.TableDescriptor; 039import org.apache.hadoop.hbase.master.MasterServices; 040import org.apache.hadoop.hbase.master.ServerManager; 041import org.apache.hadoop.hbase.master.assignment.AssignmentManager; 042import org.apache.hadoop.hbase.namequeues.BalancerDecisionDetails; 043import org.apache.hadoop.hbase.namequeues.BalancerRejectionDetails; 044import org.apache.hadoop.hbase.namequeues.NamedQueueRecorder; 045import org.apache.hadoop.hbase.regionserver.HRegion; 046import org.apache.hadoop.hbase.regionserver.compactions.OffPeakHours; 047import org.apache.yetus.audience.InterfaceAudience; 048 049/** 050 * Master based cluster info provider. 051 */ 052@InterfaceAudience.Private 053public class MasterClusterInfoProvider implements ClusterInfoProvider { 054 055 private final MasterServices services; 056 057 private boolean isBalancerDecisionRecording; 058 059 private boolean isBalancerRejectionRecording; 060 061 /** 062 * Use to add balancer decision history to ring-buffer 063 */ 064 private NamedQueueRecorder namedQueueRecorder; 065 066 private OffPeakHours offPeakHours; 067 068 private void loadConf(Configuration conf) { 069 this.offPeakHours = OffPeakHours.getInstance(conf); 070 isBalancerDecisionRecording = conf.getBoolean(BaseLoadBalancer.BALANCER_DECISION_BUFFER_ENABLED, 071 BaseLoadBalancer.DEFAULT_BALANCER_DECISION_BUFFER_ENABLED); 072 isBalancerRejectionRecording = 073 conf.getBoolean(BaseLoadBalancer.BALANCER_REJECTION_BUFFER_ENABLED, 074 BaseLoadBalancer.DEFAULT_BALANCER_REJECTION_BUFFER_ENABLED); 075 if (isBalancerDecisionRecording || isBalancerRejectionRecording) { 076 this.namedQueueRecorder = NamedQueueRecorder.getInstance(conf); 077 } else { 078 this.namedQueueRecorder = null; 079 } 080 } 081 082 public MasterClusterInfoProvider(MasterServices services) { 083 this.services = services; 084 loadConf(services.getConfiguration()); 085 } 086 087 @Override 088 public Configuration getConfiguration() { 089 return services.getConfiguration(); 090 } 091 092 @Override 093 public Connection getConnection() { 094 return services.getConnection(); 095 } 096 097 @Override 098 public List<RegionInfo> getAssignedRegions() { 099 AssignmentManager am = services.getAssignmentManager(); 100 return am != null ? am.getAssignedRegions() : Collections.emptyList(); 101 } 102 103 @Override 104 public void unassign(RegionInfo regionInfo) throws IOException { 105 AssignmentManager am = services.getAssignmentManager(); 106 if (am != null) { 107 am.unassign(regionInfo); 108 } 109 } 110 111 @Override 112 public TableDescriptor getTableDescriptor(TableName tableName) throws IOException { 113 TableDescriptors tds = services.getTableDescriptors(); 114 return tds != null ? tds.get(tableName) : null; 115 } 116 117 @Override 118 public HDFSBlocksDistribution computeHDFSBlocksDistribution(Configuration conf, 119 TableDescriptor tableDescriptor, RegionInfo regionInfo) throws IOException { 120 return HRegion.computeHDFSBlocksDistribution(conf, tableDescriptor, regionInfo); 121 } 122 123 @Override 124 public boolean hasRegionReplica(Collection<RegionInfo> regions) throws IOException { 125 TableDescriptors tds = services.getTableDescriptors(); 126 if (tds == null) { 127 return false; 128 } 129 for (RegionInfo region : regions) { 130 TableDescriptor td = tds.get(region.getTable()); 131 if (td != null && td.getRegionReplication() > 1) { 132 return true; 133 } 134 } 135 return false; 136 } 137 138 @Override 139 public List<ServerName> getOnlineServersList() { 140 ServerManager sm = services.getServerManager(); 141 return sm != null ? sm.getOnlineServersList() : Collections.emptyList(); 142 } 143 144 @Override 145 public List<ServerName> getOnlineServersListWithPredicator(List<ServerName> servers, 146 Predicate<ServerMetrics> filter) { 147 ServerManager sm = services.getServerManager(); 148 return sm != null 149 ? sm.getOnlineServersListWithPredicator(servers, filter) 150 : Collections.emptyList(); 151 } 152 153 @Override 154 public Map<ServerName, List<RegionInfo>> getSnapShotOfAssignment(Collection<RegionInfo> regions) { 155 AssignmentManager am = services.getAssignmentManager(); 156 return am != null ? am.getSnapShotOfAssignment(regions) : Collections.emptyMap(); 157 } 158 159 @Override 160 public int getNumberOfTables() throws IOException { 161 return services.getTableDescriptors().getAll().size(); 162 } 163 164 @Override 165 public boolean isOffPeakHour() { 166 return offPeakHours.isOffPeakHour(); 167 } 168 169 @Override 170 public void onConfigurationChange(Configuration conf) { 171 loadConf(conf); 172 } 173 174 @Override 175 public void recordBalancerDecision(Supplier<BalancerDecision> decision) { 176 if (isBalancerDecisionRecording) { 177 namedQueueRecorder.addRecord(new BalancerDecisionDetails(decision.get())); 178 } 179 } 180 181 @Override 182 public void recordBalancerRejection(Supplier<BalancerRejection> rejection) { 183 if (isBalancerRejectionRecording) { 184 namedQueueRecorder.addRecord(new BalancerRejectionDetails(rejection.get())); 185 } 186 } 187 188 @Override 189 public ServerMetrics getLoad(ServerName serverName) { 190 ServerManager sm = services.getServerManager(); 191 return sm != null ? sm.getLoad(serverName) : null; 192 } 193 194 @RestrictedApi(explanation = "Should only be called in tests", link = "", 195 allowedOnPath = ".*/src/test/.*") 196 NamedQueueRecorder getNamedQueueRecorder() { 197 return namedQueueRecorder; 198 } 199}