|
21 | 21 | import java.io.IOException; |
22 | 22 | import java.util.Collections; |
23 | 23 | import java.util.List; |
| 24 | +import java.util.Objects; |
24 | 25 | import java.util.Optional; |
25 | 26 | import java.util.Set; |
26 | 27 | import java.util.stream.Collectors; |
27 | 28 | import org.apache.hadoop.hbase.CoprocessorEnvironment; |
28 | | -import org.apache.hadoop.hbase.HBaseIOException; |
29 | 29 | import org.apache.hadoop.hbase.HConstants; |
30 | 30 | import org.apache.hadoop.hbase.NamespaceDescriptor; |
31 | 31 | import org.apache.hadoop.hbase.ServerName; |
@@ -68,7 +68,7 @@ public void start(CoprocessorEnvironment env) throws IOException { |
68 | 68 | groupInfoManager = RSGroupInfoManagerImpl.getInstance(master); |
69 | 69 | groupAdminServer = new RSGroupAdminServer(master, groupInfoManager); |
70 | 70 | Class<?> clazz = |
71 | | - master.getConfiguration().getClass(HConstants.HBASE_MASTER_LOADBALANCER_CLASS, null); |
| 71 | + master.getConfiguration().getClass(HConstants.HBASE_MASTER_LOADBALANCER_CLASS, null); |
72 | 72 | if (!RSGroupableBalancer.class.isAssignableFrom(clazz)) { |
73 | 73 | throw new IOException("Configured balancer does not support RegionServer groups."); |
74 | 74 | } |
@@ -108,85 +108,120 @@ RSGroupAdminServiceImpl getGroupAdminService() { |
108 | 108 |
|
109 | 109 | @Override |
110 | 110 | public void postClearDeadServers(ObserverContext<MasterCoprocessorEnvironment> ctx, |
111 | | - List<ServerName> servers, List<ServerName> notClearedServers) throws IOException { |
| 111 | + List<ServerName> servers, List<ServerName> notClearedServers) throws IOException { |
112 | 112 | Set<Address> clearedServer = |
113 | | - servers.stream().filter(server -> !notClearedServers.contains(server)) |
114 | | - .map(ServerName::getAddress).collect(Collectors.toSet()); |
| 113 | + servers.stream().filter(server -> !notClearedServers.contains(server)) |
| 114 | + .map(ServerName::getAddress).collect(Collectors.toSet()); |
115 | 115 | if (!clearedServer.isEmpty()) { |
116 | 116 | groupAdminServer.removeServers(clearedServer); |
117 | 117 | } |
118 | 118 | } |
119 | 119 |
|
120 | | - private void checkGroupExists(Optional<String> optGroupName) throws IOException { |
| 120 | + private RSGroupInfo checkGroupExists(Optional<String> optGroupName) throws IOException { |
121 | 121 | if (optGroupName.isPresent()) { |
122 | 122 | String groupName = optGroupName.get(); |
123 | | - if (groupAdminServer.getRSGroupInfo(groupName) == null) { |
| 123 | + RSGroupInfo group = groupAdminServer.getRSGroupInfo(groupName); |
| 124 | + if (group == null) { |
124 | 125 | throw new ConstraintException("Region server group " + groupName + " does not exit"); |
125 | 126 | } |
| 127 | + return group; |
126 | 128 | } |
| 129 | + return null; |
127 | 130 | } |
128 | 131 |
|
129 | | - private boolean rsgroupHasServersOnline(TableDescriptor desc) throws IOException { |
| 132 | + // Do not allow creating new tables which has an empty rs group, expect the default rs group. |
| 133 | + // Notice that we do not check for online servers, as this is not stable because region server can |
| 134 | + // die at any time. |
| 135 | + private void checkForEmptyGroup(TableDescriptor desc) throws IOException { |
| 136 | + if (desc.getTableName().isSystemTable()) { |
| 137 | + // do not check for system tables as we may block the bootstrap. |
| 138 | + return; |
| 139 | + } |
130 | 140 | RSGroupInfo rsGroupInfo; |
131 | 141 | Optional<String> optGroupName = desc.getRegionServerGroup(); |
132 | 142 | if (optGroupName.isPresent()) { |
133 | 143 | String groupName = optGroupName.get(); |
134 | 144 | if (groupName.equals(RSGroupInfo.DEFAULT_GROUP)) { |
135 | 145 | // do not check for default group |
136 | | - return true; |
| 146 | + return; |
137 | 147 | } |
138 | 148 | rsGroupInfo = groupAdminServer.getRSGroupInfo(groupName); |
139 | 149 | if (rsGroupInfo == null) { |
140 | 150 | throw new ConstraintException( |
141 | | - "RSGroup " + groupName + " for table " + desc.getTableName() + " does not exist"); |
| 151 | + "RSGroup " + groupName + " for table " + desc.getTableName() + " does not exist"); |
142 | 152 | } |
143 | 153 | } else { |
144 | 154 | NamespaceDescriptor nd = |
145 | | - master.getClusterSchema().getNamespace(desc.getTableName().getNamespaceAsString()); |
| 155 | + master.getClusterSchema().getNamespace(desc.getTableName().getNamespaceAsString()); |
146 | 156 | String groupNameOfNs = nd.getConfigurationValue(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP); |
147 | 157 | if (groupNameOfNs == null || groupNameOfNs.equals(RSGroupInfo.DEFAULT_GROUP)) { |
148 | 158 | // do not check for default group |
149 | | - return true; |
| 159 | + return; |
150 | 160 | } |
151 | 161 | rsGroupInfo = groupAdminServer.getRSGroupInfo(groupNameOfNs); |
152 | 162 | if (rsGroupInfo == null) { |
153 | 163 | throw new ConstraintException("RSGroup " + groupNameOfNs + " for table " + |
154 | | - desc.getTableName() + "(inherit from namespace) does not exist"); |
| 164 | + desc.getTableName() + "(inherit from namespace) does not exist"); |
155 | 165 | } |
156 | 166 | } |
157 | | - return master.getServerManager().createDestinationServersList().stream() |
158 | | - .anyMatch(onlineServer -> rsGroupInfo.containsServer(onlineServer.getAddress())); |
| 167 | + if (rsGroupInfo.getServers().isEmpty()) { |
| 168 | + throw new ConstraintException( |
| 169 | + "No servers in the rsgroup " + rsGroupInfo.getName() + " for " + desc); |
| 170 | + } |
159 | 171 | } |
160 | 172 |
|
161 | 173 | @Override |
162 | 174 | public void preCreateTableAction(ObserverContext<MasterCoprocessorEnvironment> ctx, |
163 | | - TableDescriptor desc, RegionInfo[] regions) throws IOException { |
| 175 | + TableDescriptor desc, RegionInfo[] regions) throws IOException { |
164 | 176 | checkGroupExists(desc.getRegionServerGroup()); |
165 | | - if (!desc.getTableName().isSystemTable() && !rsgroupHasServersOnline(desc)) { |
166 | | - throw new HBaseIOException("No online servers in the rsgroup for " + desc); |
167 | | - } |
| 177 | + checkForEmptyGroup(desc); |
168 | 178 | } |
169 | 179 |
|
170 | 180 | @Override |
171 | 181 | public TableDescriptor preModifyTable(ObserverContext<MasterCoprocessorEnvironment> ctx, |
172 | | - TableName tableName, TableDescriptor currentDescriptor, TableDescriptor newDescriptor) |
173 | | - throws IOException { |
174 | | - checkGroupExists(newDescriptor.getRegionServerGroup()); |
| 182 | + TableName tableName, TableDescriptor currentDescriptor, TableDescriptor newDescriptor) |
| 183 | + throws IOException { |
| 184 | + if (!currentDescriptor.getRegionServerGroup().equals(newDescriptor.getRegionServerGroup())) { |
| 185 | + RSGroupInfo group = checkGroupExists(newDescriptor.getRegionServerGroup()); |
| 186 | + if (group != null && group.getServers().isEmpty()) { |
| 187 | + throw new ConstraintException( |
| 188 | + "No servers in the rsgroup " + group.getName() + " for " + newDescriptor); |
| 189 | + } |
| 190 | + } |
175 | 191 | return MasterObserver.super.preModifyTable(ctx, tableName, currentDescriptor, newDescriptor); |
176 | 192 | } |
177 | 193 |
|
| 194 | + private void checkNamespaceGroup(NamespaceDescriptor ns) throws IOException { |
| 195 | + String groupName = ns.getConfigurationValue(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP); |
| 196 | + if (groupName == null || groupName.equals(RSGroupInfo.DEFAULT_GROUP)) { |
| 197 | + // do not check for default group |
| 198 | + return; |
| 199 | + } |
| 200 | + RSGroupInfo group = groupAdminServer.getRSGroupInfo(groupName); |
| 201 | + if (group == null) { |
| 202 | + throw new ConstraintException( |
| 203 | + "RSGroup " + groupName + " for namespace " + ns.getName() + " does not exist"); |
| 204 | + } |
| 205 | + if (group.getServers().isEmpty()) { |
| 206 | + throw new ConstraintException( |
| 207 | + "No servers in the rsgroup " + group.getName() + " for namespace " + ns.getName()); |
| 208 | + } |
| 209 | + } |
| 210 | + |
178 | 211 | @Override |
179 | 212 | public void preCreateNamespace(ObserverContext<MasterCoprocessorEnvironment> ctx, |
180 | | - NamespaceDescriptor ns) throws IOException { |
181 | | - checkGroupExists( |
182 | | - Optional.ofNullable(ns.getConfigurationValue(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP))); |
| 213 | + NamespaceDescriptor ns) throws IOException { |
| 214 | + checkNamespaceGroup(ns); |
183 | 215 | } |
184 | 216 |
|
185 | 217 | @Override |
186 | 218 | public void preModifyNamespace(ObserverContext<MasterCoprocessorEnvironment> ctx, |
187 | | - NamespaceDescriptor currentNsDescriptor, NamespaceDescriptor newNsDescriptor) |
188 | | - throws IOException { |
189 | | - checkGroupExists(Optional |
190 | | - .ofNullable(newNsDescriptor.getConfigurationValue(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP))); |
| 219 | + NamespaceDescriptor currentNsDescriptor, NamespaceDescriptor newNsDescriptor) |
| 220 | + throws IOException { |
| 221 | + if (!Objects.equals( |
| 222 | + currentNsDescriptor.getConfigurationValue(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP), |
| 223 | + newNsDescriptor.getConfigurationValue(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP))) { |
| 224 | + checkNamespaceGroup(newNsDescriptor); |
| 225 | + } |
191 | 226 | } |
192 | 227 | } |
0 commit comments