2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 package org
.apache
.hadoop
.hbase
.rsgroup
;
20 import java
.io
.IOException
;
21 import java
.util
.ArrayList
;
22 import java
.util
.Collections
;
23 import java
.util
.HashMap
;
24 import java
.util
.HashSet
;
25 import java
.util
.Iterator
;
26 import java
.util
.LinkedList
;
27 import java
.util
.List
;
31 import org
.apache
.commons
.lang3
.StringUtils
;
32 import org
.apache
.hadoop
.hbase
.NamespaceDescriptor
;
33 import org
.apache
.hadoop
.hbase
.ServerName
;
34 import org
.apache
.hadoop
.hbase
.TableName
;
35 import org
.apache
.hadoop
.hbase
.client
.RegionInfo
;
36 import org
.apache
.hadoop
.hbase
.constraint
.ConstraintException
;
37 import org
.apache
.hadoop
.hbase
.master
.HMaster
;
38 import org
.apache
.hadoop
.hbase
.master
.LoadBalancer
;
39 import org
.apache
.hadoop
.hbase
.master
.MasterServices
;
40 import org
.apache
.hadoop
.hbase
.master
.RegionPlan
;
41 import org
.apache
.hadoop
.hbase
.master
.RegionState
;
42 import org
.apache
.hadoop
.hbase
.master
.ServerManager
;
43 import org
.apache
.hadoop
.hbase
.master
.assignment
.AssignmentManager
;
44 import org
.apache
.hadoop
.hbase
.master
.assignment
.RegionStateNode
;
45 import org
.apache
.hadoop
.hbase
.net
.Address
;
46 import org
.apache
.yetus
.audience
.InterfaceAudience
;
47 import org
.slf4j
.Logger
;
48 import org
.slf4j
.LoggerFactory
;
50 import org
.apache
.hbase
.thirdparty
.com
.google
.common
.collect
.Lists
;
51 import org
.apache
.hbase
.thirdparty
.com
.google
.common
.collect
.Maps
;
54 * Service to support Region Server Grouping (HBase-6721).
56 @InterfaceAudience.Private
57 public class RSGroupAdminServer
implements RSGroupAdmin
{
58 private static final Logger LOG
= LoggerFactory
.getLogger(RSGroupAdminServer
.class);
59 public static final String KEEP_ONE_SERVER_IN_DEFAULT_ERROR_MESSAGE
= "should keep at least " +
60 "one server in 'default' RSGroup.";
62 private MasterServices master
;
63 private final RSGroupInfoManager rsGroupInfoManager
;
65 public RSGroupAdminServer(MasterServices master
, RSGroupInfoManager rsGroupInfoManager
)
68 this.rsGroupInfoManager
= rsGroupInfoManager
;
72 public RSGroupInfo
getRSGroupInfo(String groupName
) throws IOException
{
73 return rsGroupInfoManager
.getRSGroup(groupName
);
77 public RSGroupInfo
getRSGroupInfoOfTable(TableName tableName
) throws IOException
{
78 // We are reading across two Maps in the below with out synchronizing across
79 // them; should be safe most of the time.
80 String groupName
= rsGroupInfoManager
.getRSGroupOfTable(tableName
);
81 return groupName
== null?
null: rsGroupInfoManager
.getRSGroup(groupName
);
84 private void checkOnlineServersOnly(Set
<Address
> servers
) throws ConstraintException
{
85 // This uglyness is because we only have Address, not ServerName.
86 // Online servers are keyed by ServerName.
87 Set
<Address
> onlineServers
= new HashSet
<>();
88 for(ServerName server
: master
.getServerManager().getOnlineServers().keySet()) {
89 onlineServers
.add(server
.getAddress());
91 for (Address address
: servers
) {
92 if (!onlineServers
.contains(address
)) {
93 throw new ConstraintException(
94 "Server " + address
+ " is not an online server in 'default' RSGroup.");
100 * Check passed name. Fail if nulls or if corresponding RSGroupInfo not found.
101 * @return The RSGroupInfo named <code>name</code>
103 private RSGroupInfo
getAndCheckRSGroupInfo(String name
)
105 if (StringUtils
.isEmpty(name
)) {
106 throw new ConstraintException("RSGroup cannot be null.");
108 RSGroupInfo rsGroupInfo
= getRSGroupInfo(name
);
109 if (rsGroupInfo
== null) {
110 throw new ConstraintException("RSGroup does not exist: " + name
);
116 * @return List of Regions associated with this <code>server</code>.
118 private List
<RegionInfo
> getRegions(final Address server
) {
119 LinkedList
<RegionInfo
> regions
= new LinkedList
<>();
120 for (Map
.Entry
<RegionInfo
, ServerName
> el
:
121 master
.getAssignmentManager().getRegionStates().getRegionAssignments().entrySet()) {
122 if (el
.getValue() == null) {
126 if (el
.getValue().getAddress().equals(server
)) {
127 addRegion(regions
, el
.getKey());
130 for (RegionStateNode state
: master
.getAssignmentManager().getRegionsInTransition()) {
131 if (state
.getRegionLocation().getAddress().equals(server
)) {
132 addRegion(regions
, state
.getRegionInfo());
138 private void addRegion(final LinkedList
<RegionInfo
> regions
, RegionInfo hri
) {
139 // If meta, move it last otherwise other unassigns fail because meta is not
140 // online for them to update state in. This is dodgy. Needs to be made more
141 // robust. See TODO below.
142 if (hri
.isMetaRegion()) {
143 regions
.addLast(hri
);
145 regions
.addFirst(hri
);
150 * Check servers and tables.
152 * @param servers servers to move
153 * @param tables tables to move
154 * @param targetGroupName target group name
155 * @throws IOException if nulls or if servers and tables not belong to the same group
157 private void checkServersAndTables(Set
<Address
> servers
, Set
<TableName
> tables
,
158 String targetGroupName
) throws IOException
{
159 // Presume first server's source group. Later ensure all servers are from this group.
160 Address firstServer
= servers
.iterator().next();
161 RSGroupInfo tmpSrcGrp
= rsGroupInfoManager
.getRSGroupOfServer(firstServer
);
162 if (tmpSrcGrp
== null) {
163 // Be careful. This exception message is tested for in TestRSGroupsBase...
164 throw new ConstraintException("Source RSGroup for server " + firstServer
165 + " does not exist.");
167 RSGroupInfo srcGrp
= new RSGroupInfo(tmpSrcGrp
);
168 if (srcGrp
.getName().equals(targetGroupName
)) {
169 throw new ConstraintException("Target RSGroup " + targetGroupName
+
170 " is same as source " + srcGrp
.getName() + " RSGroup.");
172 // Only move online servers
173 checkOnlineServersOnly(servers
);
175 // Ensure all servers are of same rsgroup.
176 for (Address server
: servers
) {
177 String tmpGroup
= rsGroupInfoManager
.getRSGroupOfServer(server
).getName();
178 if (!tmpGroup
.equals(srcGrp
.getName())) {
179 throw new ConstraintException("Move server request should only come from one source " +
180 "RSGroup. Expecting only " + srcGrp
.getName() + " but contains " + tmpGroup
);
184 // Ensure all tables and servers are of same rsgroup.
185 for (TableName table
: tables
) {
186 String tmpGroup
= rsGroupInfoManager
.getRSGroupOfTable(table
);
187 if (!tmpGroup
.equals(srcGrp
.getName())) {
188 throw new ConstraintException("Move table request should only come from one source " +
189 "RSGroup. Expecting only " + srcGrp
.getName() + " but contains " + tmpGroup
);
193 if (srcGrp
.getServers().size() <= servers
.size() && srcGrp
.getTables().size() > tables
.size()) {
194 throw new ConstraintException("Cannot leave a RSGroup " + srcGrp
.getName() +
195 " that contains tables without servers to host them.");
200 * Moves every region from servers which are currently located on these servers,
201 * but should not be located there.
202 * @param servers the servers that will move to new group
203 * @param tables these tables will be kept on the servers, others will be moved
204 * @param targetGroupName the target group name
205 * @throws IOException if moving the server and tables fail
207 private void moveRegionsFromServers(Set
<Address
> servers
, Set
<TableName
> tables
,
208 String targetGroupName
) throws IOException
{
209 boolean foundRegionsToMove
;
210 RSGroupInfo targetGrp
= getRSGroupInfo(targetGroupName
);
211 Set
<Address
> allSevers
= new HashSet
<>(servers
);
213 foundRegionsToMove
= false;
214 for (Iterator
<Address
> iter
= allSevers
.iterator(); iter
.hasNext();) {
215 Address rs
= iter
.next();
216 // Get regions that are associated with this server and filter regions by tables.
217 List
<RegionInfo
> regions
= new ArrayList
<>();
218 for (RegionInfo region
: getRegions(rs
)) {
219 if (!tables
.contains(region
.getTable())) {
224 LOG
.info("Moving " + regions
.size() + " region(s) from " + rs
+
225 " for server move to " + targetGroupName
);
226 if (!regions
.isEmpty()) {
227 for (RegionInfo region
: regions
) {
228 // Regions might get assigned from tables of target group so we need to filter
229 if (!targetGrp
.containsTable(region
.getTable())) {
230 this.master
.getAssignmentManager().move(region
);
231 if (master
.getAssignmentManager().getRegionStates().
232 getRegionState(region
).isFailedOpen()) {
235 foundRegionsToMove
= true;
239 if (!foundRegionsToMove
) {
244 rsGroupInfoManager
.wait(1000);
245 } catch (InterruptedException e
) {
246 LOG
.warn("Sleep interrupted", e
);
247 Thread
.currentThread().interrupt();
249 } while (foundRegionsToMove
);
253 * Moves every region of tables which should be kept on the servers,
254 * but currently they are located on other servers.
255 * @param servers the regions of these servers will be kept on the servers, others will be moved
256 * @param tables the tables that will move to new group
257 * @param targetGroupName the target group name
258 * @throws IOException if moving the region fails
260 private void moveRegionsToServers(Set
<Address
> servers
, Set
<TableName
> tables
,
261 String targetGroupName
) throws IOException
{
262 for (TableName table
: tables
) {
263 LOG
.info("Moving region(s) from " + table
+ " for table move to " + targetGroupName
);
264 for (RegionInfo region
: master
.getAssignmentManager().getRegionStates()
265 .getRegionsOfTable(table
)) {
266 ServerName sn
= master
.getAssignmentManager().getRegionStates()
267 .getRegionServerOfRegion(region
);
268 if (!servers
.contains(sn
.getAddress())) {
269 master
.getAssignmentManager().move(region
);
275 @edu.umd
.cs
.findbugs
.annotations
.SuppressWarnings(
276 value
="RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE",
277 justification
="Ignoring complaint because don't know what it is complaining about")
279 public void moveServers(Set
<Address
> servers
, String targetGroupName
)
281 if (servers
== null) {
282 throw new ConstraintException("The list of servers to move cannot be null.");
284 if (servers
.isEmpty()) {
285 // For some reason this difference between null servers and isEmpty is important distinction.
286 // TODO. Why? Stuff breaks if I equate them.
289 RSGroupInfo targetGrp
= getAndCheckRSGroupInfo(targetGroupName
);
291 // Hold a lock on the manager instance while moving servers to prevent
292 // another writer changing our state while we are working.
293 synchronized (rsGroupInfoManager
) {
294 // Presume first server's source group. Later ensure all servers are from this group.
295 Address firstServer
= servers
.iterator().next();
296 RSGroupInfo srcGrp
= rsGroupInfoManager
.getRSGroupOfServer(firstServer
);
297 if (srcGrp
== null) {
298 // Be careful. This exception message is tested for in TestRSGroupsBase...
299 throw new ConstraintException("Source RSGroup for server " + firstServer
300 + " does not exist.");
302 if (srcGrp
.getName().equals(targetGroupName
)) {
303 throw new ConstraintException("Target RSGroup " + targetGroupName
+
304 " is same as source " + srcGrp
+ " RSGroup.");
306 // Only move online servers (when moving from 'default') or servers from other
307 // groups. This prevents bogus servers from entering groups
308 if (RSGroupInfo
.DEFAULT_GROUP
.equals(srcGrp
.getName())) {
309 if (srcGrp
.getServers().size() <= servers
.size()) {
310 throw new ConstraintException(KEEP_ONE_SERVER_IN_DEFAULT_ERROR_MESSAGE
);
312 checkOnlineServersOnly(servers
);
314 // Ensure all servers are of same rsgroup.
315 for (Address server
: servers
) {
316 String tmpGroup
= rsGroupInfoManager
.getRSGroupOfServer(server
).getName();
317 if (!tmpGroup
.equals(srcGrp
.getName())) {
318 throw new ConstraintException("Move server request should only come from one source " +
319 "RSGroup. Expecting only " + srcGrp
.getName() + " but contains " + tmpGroup
);
322 if (srcGrp
.getServers().size() <= servers
.size() && srcGrp
.getTables().size() > 0) {
323 throw new ConstraintException("Cannot leave a RSGroup " + srcGrp
.getName() +
324 " that contains tables without servers to host them.");
327 // MovedServers may be < passed in 'servers'.
328 Set
<Address
> movedServers
= rsGroupInfoManager
.moveServers(servers
, srcGrp
.getName(),
330 List
<Address
> editableMovedServers
= Lists
.newArrayList(movedServers
);
331 boolean foundRegionsToMove
;
333 foundRegionsToMove
= false;
334 for (Iterator
<Address
> iter
= editableMovedServers
.iterator(); iter
.hasNext();) {
335 Address rs
= iter
.next();
336 // Get regions that are associated with this server.
337 List
<RegionInfo
> regions
= getRegions(rs
);
339 LOG
.info("Moving " + regions
.size() + " region(s) from " + rs
+
340 " for server move to " + targetGroupName
);
342 for (RegionInfo region
: regions
) {
343 // Regions might get assigned from tables of target group so we need to filter
344 if (targetGrp
.containsTable(region
.getTable())) {
347 LOG
.info("Moving region " + region
.getShortNameToLog());
348 this.master
.getAssignmentManager().move(region
);
349 if (master
.getAssignmentManager().getRegionStates().
350 getRegionState(region
).isFailedOpen()) {
351 // If region is in FAILED_OPEN state, it won't recover, not without
352 // operator intervention... in hbase-2.0.0 at least. Continue rather
353 // than mark region as 'foundRegionsToMove'.
356 foundRegionsToMove
= true;
358 if (!foundRegionsToMove
) {
363 rsGroupInfoManager
.wait(1000);
364 } catch (InterruptedException e
) {
365 LOG
.warn("Sleep interrupted", e
);
366 Thread
.currentThread().interrupt();
368 } while (foundRegionsToMove
);
370 LOG
.info("Move server done: " + srcGrp
.getName() + "=>" + targetGroupName
);
375 public void moveTables(Set
<TableName
> tables
, String targetGroup
) throws IOException
{
376 if (tables
== null) {
377 throw new ConstraintException("The list of servers cannot be null.");
379 if (tables
.size() < 1) {
380 LOG
.debug("moveTables() passed an empty set. Ignoring.");
384 // Hold a lock on the manager instance while moving servers to prevent
385 // another writer changing our state while we are working.
386 synchronized (rsGroupInfoManager
) {
387 if(targetGroup
!= null) {
388 RSGroupInfo destGroup
= rsGroupInfoManager
.getRSGroup(targetGroup
);
389 if(destGroup
== null) {
390 throw new ConstraintException("Target " + targetGroup
+ " RSGroup does not exist.");
392 if(destGroup
.getServers().size() < 1) {
393 throw new ConstraintException("Target RSGroup must have at least one server.");
397 for (TableName table
: tables
) {
398 String srcGroup
= rsGroupInfoManager
.getRSGroupOfTable(table
);
399 if(srcGroup
!= null && srcGroup
.equals(targetGroup
)) {
400 throw new ConstraintException(
401 "Source RSGroup " + srcGroup
+ " is same as target " + targetGroup
+
402 " RSGroup for table " + table
);
404 LOG
.info("Moving table " + table
.getNameAsString() + " to RSGroup " + targetGroup
);
406 rsGroupInfoManager
.moveTables(tables
, targetGroup
);
408 // targetGroup is null when a table is being deleted. In this case no further
409 // action is required.
410 if (targetGroup
!= null) {
411 for (TableName table
: tables
) {
412 if (master
.getAssignmentManager().isTableDisabled(table
)) {
413 LOG
.debug("Skipping move regions because the table" + table
+ " is disabled.");
416 for (RegionInfo region
:
417 master
.getAssignmentManager().getRegionStates().getRegionsOfTable(table
)) {
418 LOG
.info("Moving region " + region
.getShortNameToLog() +
419 " to RSGroup " + targetGroup
);
420 master
.getAssignmentManager().move(region
);
428 public void addRSGroup(String name
) throws IOException
{
429 rsGroupInfoManager
.addRSGroup(new RSGroupInfo(name
));
433 public void removeRSGroup(String name
) throws IOException
{
434 // Hold a lock on the manager instance while moving servers to prevent
435 // another writer changing our state while we are working.
436 synchronized (rsGroupInfoManager
) {
437 RSGroupInfo rsGroupInfo
= rsGroupInfoManager
.getRSGroup(name
);
438 if (rsGroupInfo
== null) {
439 throw new ConstraintException("RSGroup " + name
+ " does not exist");
441 int tableCount
= rsGroupInfo
.getTables().size();
442 if (tableCount
> 0) {
443 throw new ConstraintException("RSGroup " + name
+ " has " + tableCount
+
444 " tables; you must remove these tables from the rsgroup before " +
445 "the rsgroup can be removed.");
447 int serverCount
= rsGroupInfo
.getServers().size();
448 if (serverCount
> 0) {
449 throw new ConstraintException("RSGroup " + name
+ " has " + serverCount
+
450 " servers; you must remove these servers from the RSGroup before" +
451 "the RSGroup can be removed.");
453 for (NamespaceDescriptor ns
: master
.getClusterSchema().getNamespaces()) {
454 String nsGroup
= ns
.getConfigurationValue(rsGroupInfo
.NAMESPACE_DESC_PROP_GROUP
);
455 if (nsGroup
!= null && nsGroup
.equals(name
)) {
456 throw new ConstraintException("RSGroup " + name
+ " is referenced by namespace: " +
460 rsGroupInfoManager
.removeRSGroup(name
);
465 public boolean balanceRSGroup(String groupName
) throws IOException
{
466 ServerManager serverManager
= master
.getServerManager();
467 AssignmentManager assignmentManager
= master
.getAssignmentManager();
468 LoadBalancer balancer
= master
.getLoadBalancer();
470 synchronized (balancer
) {
471 // If balance not true, don't run balancer.
472 if (!((HMaster
) master
).isBalancerOn()) {
476 if (getRSGroupInfo(groupName
) == null) {
477 throw new ConstraintException("RSGroup does not exist: "+groupName
);
479 // Only allow one balance run at at time.
480 Map
<String
, RegionState
> groupRIT
= rsGroupGetRegionsInTransition(groupName
);
481 if (groupRIT
.size() > 0) {
482 LOG
.debug("Not running balancer because " + groupRIT
.size() + " region(s) in transition: " +
483 StringUtils
.abbreviate(
484 master
.getAssignmentManager().getRegionStates().getRegionsInTransition().toString(),
488 if (serverManager
.areDeadServersInProgress()) {
489 LOG
.debug("Not running balancer because processing dead regionserver(s): " +
490 serverManager
.getDeadServers());
494 //We balance per group instead of per table
495 List
<RegionPlan
> plans
= new ArrayList
<>();
496 for(Map
.Entry
<TableName
, Map
<ServerName
, List
<RegionInfo
>>> tableMap
:
497 getRSGroupAssignmentsByTable(groupName
).entrySet()) {
498 LOG
.info("Creating partial plan for table " + tableMap
.getKey() + ": "
499 + tableMap
.getValue());
500 List
<RegionPlan
> partialPlans
= balancer
.balanceCluster(tableMap
.getValue());
501 LOG
.info("Partial plan for table " + tableMap
.getKey() + ": " + partialPlans
);
502 if (partialPlans
!= null) {
503 plans
.addAll(partialPlans
);
506 long startTime
= System
.currentTimeMillis();
507 boolean balancerRan
= !plans
.isEmpty();
509 LOG
.info("RSGroup balance " + groupName
+ " starting with plan count: " + plans
.size());
510 for (RegionPlan plan
: plans
) {
511 LOG
.info("balance " + plan
);
512 assignmentManager
.moveAsync(plan
);
514 LOG
.info("RSGroup balance " + groupName
+ " completed after " +
515 (System
.currentTimeMillis()-startTime
) + " seconds");
522 public List
<RSGroupInfo
> listRSGroups() throws IOException
{
523 return rsGroupInfoManager
.listRSGroups();
527 public RSGroupInfo
getRSGroupOfServer(Address hostPort
) throws IOException
{
528 return rsGroupInfoManager
.getRSGroupOfServer(hostPort
);
532 public void moveServersAndTables(Set
<Address
> servers
, Set
<TableName
> tables
, String targetGroup
)
534 if (servers
== null || servers
.isEmpty()) {
535 throw new ConstraintException("The list of servers to move cannot be null or empty.");
537 if (tables
== null || tables
.isEmpty()) {
538 throw new ConstraintException("The list of tables to move cannot be null or empty.");
542 getAndCheckRSGroupInfo(targetGroup
);
544 // Hold a lock on the manager instance while moving servers and tables to prevent
545 // another writer changing our state while we are working.
546 synchronized (rsGroupInfoManager
) {
547 //check servers and tables status
548 checkServersAndTables(servers
, tables
, targetGroup
);
550 //Move servers and tables to a new group.
551 String srcGroup
= getRSGroupOfServer(servers
.iterator().next()).getName();
552 rsGroupInfoManager
.moveServersAndTables(servers
, tables
, srcGroup
, targetGroup
);
554 //move regions which should not belong to these tables
555 moveRegionsFromServers(servers
, tables
, targetGroup
);
556 //move regions which should belong to these servers
557 moveRegionsToServers(servers
, tables
, targetGroup
);
559 LOG
.info("Move servers and tables done. Severs :"
560 + servers
+ " , Tables : " + tables
+ " => " + targetGroup
);
564 public void removeServers(Set
<Address
> servers
) throws IOException
{
566 if (servers
== null || servers
.isEmpty()) {
567 throw new ConstraintException("The set of servers to remove cannot be null or empty.");
569 // Hold a lock on the manager instance while moving servers to prevent
570 // another writer changing our state while we are working.
571 synchronized (rsGroupInfoManager
) {
572 //check the set of servers
573 checkForDeadOrOnlineServers(servers
);
574 rsGroupInfoManager
.removeServers(servers
);
575 LOG
.info("Remove decommissioned servers " + servers
+ " from rsgroup done.");
580 private Map
<String
, RegionState
> rsGroupGetRegionsInTransition(String groupName
)
582 Map
<String
, RegionState
> rit
= Maps
.newTreeMap();
583 AssignmentManager am
= master
.getAssignmentManager();
584 for(TableName tableName
: getRSGroupInfo(groupName
).getTables()) {
585 for(RegionInfo regionInfo
: am
.getRegionStates().getRegionsOfTable(tableName
)) {
586 RegionState state
= am
.getRegionStates().getRegionTransitionState(regionInfo
);
588 rit
.put(regionInfo
.getEncodedName(), state
);
595 private Map
<TableName
, Map
<ServerName
, List
<RegionInfo
>>>
596 getRSGroupAssignmentsByTable(String groupName
) throws IOException
{
597 Map
<TableName
, Map
<ServerName
, List
<RegionInfo
>>> result
= Maps
.newHashMap();
598 RSGroupInfo rsGroupInfo
= getRSGroupInfo(groupName
);
599 Map
<TableName
, Map
<ServerName
, List
<RegionInfo
>>> assignments
= Maps
.newHashMap();
600 for(Map
.Entry
<RegionInfo
, ServerName
> entry
:
601 master
.getAssignmentManager().getRegionStates().getRegionAssignments().entrySet()) {
602 TableName currTable
= entry
.getKey().getTable();
603 ServerName currServer
= entry
.getValue();
604 RegionInfo currRegion
= entry
.getKey();
605 if (rsGroupInfo
.getTables().contains(currTable
)) {
606 assignments
.putIfAbsent(currTable
, new HashMap
<>());
607 assignments
.get(currTable
).putIfAbsent(currServer
, new ArrayList
<>());
608 assignments
.get(currTable
).get(currServer
).add(currRegion
);
612 Map
<ServerName
, List
<RegionInfo
>> serverMap
= Maps
.newHashMap();
613 for(ServerName serverName
: master
.getServerManager().getOnlineServers().keySet()) {
614 if(rsGroupInfo
.getServers().contains(serverName
.getAddress())) {
615 serverMap
.put(serverName
, Collections
.emptyList());
619 // add all tables that are members of the group
620 for(TableName tableName
: rsGroupInfo
.getTables()) {
621 if(assignments
.containsKey(tableName
)) {
622 result
.put(tableName
, new HashMap
<>());
623 result
.get(tableName
).putAll(serverMap
);
624 result
.get(tableName
).putAll(assignments
.get(tableName
));
625 LOG
.debug("Adding assignments for " + tableName
+ ": " + assignments
.get(tableName
));
633 * Check if the set of servers are belong to dead servers list or online servers list.
634 * @param servers servers to remove
636 private void checkForDeadOrOnlineServers(Set
<Address
> servers
) throws ConstraintException
{
637 // This uglyness is because we only have Address, not ServerName.
638 Set
<Address
> onlineServers
= new HashSet
<>();
639 List
<ServerName
> drainingServers
= master
.getServerManager().getDrainingServersList();
640 for (ServerName server
: master
.getServerManager().getOnlineServers().keySet()) {
641 // Only online but not decommissioned servers are really online
642 if (!drainingServers
.contains(server
)) {
643 onlineServers
.add(server
.getAddress());
647 Set
<Address
> deadServers
= new HashSet
<>();
648 for(ServerName server
: master
.getServerManager().getDeadServers().copyServerNames()) {
649 deadServers
.add(server
.getAddress());
652 for (Address address
: servers
) {
653 if (onlineServers
.contains(address
)) {
654 throw new ConstraintException(
655 "Server " + address
+ " is an online server, not allowed to remove.");
657 if (deadServers
.contains(address
)) {
658 throw new ConstraintException(
659 "Server " + address
+ " is on the dead servers list,"
660 + " Maybe it will come back again, not allowed to remove.");