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.rsgroup; 019 020import java.io.IOException; 021import java.util.ArrayList; 022import java.util.Collection; 023import java.util.List; 024import java.util.Optional; 025import java.util.function.Predicate; 026import org.apache.hadoop.conf.Configuration; 027import org.apache.hadoop.hbase.NamespaceDescriptor; 028import org.apache.hadoop.hbase.TableName; 029import org.apache.hadoop.hbase.client.TableDescriptor; 030import org.apache.hadoop.hbase.master.ClusterSchema; 031import org.apache.hadoop.hbase.master.MasterServices; 032import org.apache.yetus.audience.InterfaceAudience; 033import org.slf4j.Logger; 034import org.slf4j.LoggerFactory; 035 036/** 037 * Helper class for RSGroup implementation 038 */ 039@InterfaceAudience.Private 040public final class RSGroupUtil { 041 042 private static final Logger LOG = LoggerFactory.getLogger(RSGroupUtil.class); 043 044 public static final String RS_GROUP_ENABLED = "hbase.balancer.rsgroup.enabled"; 045 046 private RSGroupUtil() { 047 } 048 049 public static boolean isRSGroupEnabled(Configuration conf) { 050 return conf.getBoolean(RS_GROUP_ENABLED, false); 051 } 052 053 public static void enableRSGroup(Configuration conf) { 054 conf.setBoolean(RS_GROUP_ENABLED, true); 055 } 056 057 public static List<TableName> listTablesInRSGroup(MasterServices master, String groupName) 058 throws IOException { 059 List<TableName> tables = new ArrayList<>(); 060 boolean isDefaultGroup = RSGroupInfo.DEFAULT_GROUP.equals(groupName); 061 for (TableDescriptor td : master.getTableDescriptors().getAll().values()) { 062 // no config means in default group 063 if ( 064 RSGroupUtil.getRSGroupInfo(master, master.getRSGroupInfoManager(), td.getTableName()) 065 .map(g -> g.getName().equals(groupName)).orElse(isDefaultGroup) 066 ) { 067 tables.add(td.getTableName()); 068 } 069 } 070 return tables; 071 } 072 073 /** 074 * Will try to get the rsgroup from {@link TableDescriptor} first, and then try to get the rsgroup 075 * from the {@link NamespaceDescriptor}. If still not present, return empty. 076 */ 077 public static Optional<RSGroupInfo> getRSGroupInfo(MasterServices master, 078 RSGroupInfoManager manager, TableName tableName) throws IOException { 079 TableDescriptor td = master.getTableDescriptors().get(tableName); 080 if (td == null) { 081 return Optional.empty(); 082 } 083 // RSGroup information determined by client. 084 Optional<String> optGroupNameOfTable = td.getRegionServerGroup(); 085 if (optGroupNameOfTable.isPresent()) { 086 RSGroupInfo group = manager.getRSGroup(optGroupNameOfTable.get()); 087 if (group != null) { 088 return Optional.of(group); 089 } 090 } 091 // for backward compatible, where we may still have table configs in the RSGroupInfo after 092 // upgrading when migrating is still on-going. 093 RSGroupInfo groupFromOldRSGroupInfo = manager.getRSGroupForTable(tableName); 094 if (groupFromOldRSGroupInfo != null) { 095 return Optional.of(groupFromOldRSGroupInfo); 096 } 097 // RSGroup information determined by administrator. 098 String groupDeterminedByAdmin = manager.determineRSGroupInfoForTable(tableName); 099 RSGroupInfo groupInfo = null; 100 if (groupDeterminedByAdmin != null) { 101 groupInfo = manager.getRSGroup(groupDeterminedByAdmin); 102 } 103 if (groupInfo != null) { 104 return Optional.of(groupInfo); 105 } 106 // Finally, we will try to fall back to namespace as rsgroup if exists 107 ClusterSchema clusterSchema = master.getClusterSchema(); 108 if (clusterSchema == null) { 109 if (TableName.isMetaTableName(tableName)) { 110 LOG.info("Can not get the namespace rs group config for meta table, since the" 111 + " meta table is not online yet, will use default group to assign meta first"); 112 } else { 113 LOG.warn("ClusterSchema is null, can only use default rsgroup, should not happen?"); 114 } 115 return Optional.empty(); 116 } 117 NamespaceDescriptor nd = clusterSchema.getNamespace(tableName.getNamespaceAsString()); 118 String groupNameOfNs = nd.getConfigurationValue(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP); 119 if (groupNameOfNs == null) { 120 return Optional.empty(); 121 } 122 return Optional.ofNullable(manager.getRSGroup(groupNameOfNs)); 123 } 124 125 /** 126 * Fill the tables field for {@link RSGroupInfo}, for backward compatibility. 127 */ 128 @SuppressWarnings("deprecation") 129 public static RSGroupInfo fillTables(RSGroupInfo rsGroupInfo, Collection<TableDescriptor> tds) { 130 RSGroupInfo newRsGroupInfo = new RSGroupInfo(rsGroupInfo); 131 Predicate<TableDescriptor> filter; 132 if (rsGroupInfo.getName().equals(RSGroupInfo.DEFAULT_GROUP)) { 133 filter = td -> { 134 Optional<String> optGroupName = td.getRegionServerGroup(); 135 return !optGroupName.isPresent() || optGroupName.get().equals(RSGroupInfo.DEFAULT_GROUP); 136 }; 137 } else { 138 filter = td -> { 139 Optional<String> optGroupName = td.getRegionServerGroup(); 140 return optGroupName.isPresent() && optGroupName.get().equals(newRsGroupInfo.getName()); 141 }; 142 } 143 tds.stream().filter(filter).map(TableDescriptor::getTableName) 144 .forEach(newRsGroupInfo::addTable); 145 return newRsGroupInfo; 146 } 147}