1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.master;
20
21 import java.io.IOException;
22 import java.net.InetAddress;
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.Iterator;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Map.Entry;
31 import java.util.Set;
32 import java.util.SortedMap;
33 import java.util.concurrent.ConcurrentHashMap;
34 import java.util.concurrent.ConcurrentSkipListMap;
35
36 import org.apache.commons.logging.Log;
37 import org.apache.commons.logging.LogFactory;
38 import org.apache.hadoop.classification.InterfaceAudience;
39 import org.apache.hadoop.conf.Configuration;
40 import org.apache.hadoop.hbase.HRegionInfo;
41 import org.apache.hadoop.hbase.RegionLoad;
42 import org.apache.hadoop.hbase.Server;
43 import org.apache.hadoop.hbase.ServerLoad;
44 import org.apache.hadoop.hbase.ServerName;
45 import org.apache.hadoop.hbase.client.HConnection;
46 import org.apache.hadoop.hbase.client.HConnectionManager;
47 import org.apache.hadoop.hbase.client.RetriesExhaustedException;
48 import org.apache.hadoop.hbase.exceptions.ClockOutOfSyncException;
49 import org.apache.hadoop.hbase.exceptions.PleaseHoldException;
50 import org.apache.hadoop.hbase.exceptions.YouAreDeadException;
51 import org.apache.hadoop.hbase.exceptions.ZooKeeperConnectionException;
52 import org.apache.hadoop.hbase.master.handler.MetaServerShutdownHandler;
53 import org.apache.hadoop.hbase.master.handler.ServerShutdownHandler;
54 import org.apache.hadoop.hbase.monitoring.MonitoredTask;
55 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
56 import org.apache.hadoop.hbase.protobuf.RequestConverter;
57 import org.apache.hadoop.hbase.protobuf.ResponseConverter;
58 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.AdminService;
59 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.OpenRegionRequest;
60 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.OpenRegionResponse;
61 import org.apache.hadoop.hbase.regionserver.RegionOpeningState;
62 import org.apache.hadoop.hbase.util.Bytes;
63 import org.apache.hadoop.hbase.util.Triple;
64
65 import com.google.protobuf.ServiceException;
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89 @InterfaceAudience.Private
90 public class ServerManager {
91 public static final String WAIT_ON_REGIONSERVERS_MAXTOSTART =
92 "hbase.master.wait.on.regionservers.maxtostart";
93
94 public static final String WAIT_ON_REGIONSERVERS_MINTOSTART =
95 "hbase.master.wait.on.regionservers.mintostart";
96
97 public static final String WAIT_ON_REGIONSERVERS_TIMEOUT =
98 "hbase.master.wait.on.regionservers.timeout";
99
100 public static final String WAIT_ON_REGIONSERVERS_INTERVAL =
101 "hbase.master.wait.on.regionservers.interval";
102
103 private static final Log LOG = LogFactory.getLog(ServerManager.class);
104
105
106 private volatile boolean clusterShutdown = false;
107
108 private final SortedMap<byte[], Long> flushedSequenceIdByRegion =
109 new ConcurrentSkipListMap<byte[], Long>(Bytes.BYTES_COMPARATOR);
110
111
112 private final Map<ServerName, ServerLoad> onlineServers =
113 new ConcurrentHashMap<ServerName, ServerLoad>();
114
115
116
117
118
119 private final Map<ServerName, AdminService.BlockingInterface> rsAdmins =
120 new HashMap<ServerName, AdminService.BlockingInterface>();
121
122
123
124
125
126 private final ArrayList<ServerName> drainingServers =
127 new ArrayList<ServerName>();
128
129 private final Server master;
130 private final MasterServices services;
131 private final HConnection connection;
132
133 private final DeadServer deadservers = new DeadServer();
134
135 private final long maxSkew;
136 private final long warningSkew;
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154 private Set<ServerName> queuedDeadServers = new HashSet<ServerName>();
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171 private Map<ServerName, Boolean> requeuedDeadServers = new HashMap<ServerName, Boolean>();
172
173
174
175
176
177
178
179 public ServerManager(final Server master, final MasterServices services)
180 throws IOException {
181 this(master, services, true);
182 }
183
184 ServerManager(final Server master, final MasterServices services,
185 final boolean connect) throws IOException {
186 this.master = master;
187 this.services = services;
188 Configuration c = master.getConfiguration();
189 maxSkew = c.getLong("hbase.master.maxclockskew", 30000);
190 warningSkew = c.getLong("hbase.master.warningclockskew", 10000);
191 this.connection = connect ? HConnectionManager.getConnection(c) : null;
192 }
193
194
195
196
197
198
199
200
201
202
203 ServerName regionServerStartup(final InetAddress ia, final int port,
204 final long serverStartcode, long serverCurrentTime)
205 throws IOException {
206
207
208
209
210
211
212
213 ServerName sn = new ServerName(ia.getHostName(), port, serverStartcode);
214 checkClockSkew(sn, serverCurrentTime);
215 checkIsDead(sn, "STARTUP");
216 if (!checkAlreadySameHostPortAndRecordNewServer(
217 sn, ServerLoad.EMPTY_SERVERLOAD)) {
218 LOG.warn("THIS SHOULD NOT HAPPEN, RegionServerStartup"
219 + " could not record the server: " + sn);
220 }
221 return sn;
222 }
223
224
225
226
227
228
229 private void updateLastFlushedSequenceIds(ServerName sn, ServerLoad hsl) {
230 Map<byte[], RegionLoad> regionsLoad = hsl.getRegionsLoad();
231 for (Entry<byte[], RegionLoad> entry : regionsLoad.entrySet()) {
232 Long existingValue = flushedSequenceIdByRegion.get(entry.getKey());
233 long l = entry.getValue().getCompleteSequenceId();
234 if (existingValue != null) {
235 if (l != -1 && l < existingValue) {
236 if (LOG.isDebugEnabled()) {
237 LOG.debug("RegionServer " + sn +
238 " indicates a last flushed sequence id (" + entry.getValue() +
239 ") that is less than the previous last flushed sequence id (" +
240 existingValue + ") for region " +
241 Bytes.toString(entry.getKey()) + " Ignoring.");
242 }
243 continue;
244
245 }
246 }
247 flushedSequenceIdByRegion.put(entry.getKey(), l);
248 }
249 }
250
251 void regionServerReport(ServerName sn,
252 ServerLoad sl) throws YouAreDeadException {
253 checkIsDead(sn, "REPORT");
254 if (!this.onlineServers.containsKey(sn)) {
255
256
257
258
259
260
261 if (!checkAlreadySameHostPortAndRecordNewServer(sn, sl)) {
262 LOG.info("RegionServerReport ignored, could not record the sever: " + sn);
263 return;
264 }
265 } else {
266 this.onlineServers.put(sn, sl);
267 }
268 updateLastFlushedSequenceIds(sn, sl);
269 }
270
271
272
273
274
275
276
277
278
279 boolean checkAlreadySameHostPortAndRecordNewServer(
280 final ServerName serverName, final ServerLoad sl) {
281 ServerName existingServer = findServerWithSameHostnamePort(serverName);
282 if (existingServer != null) {
283 if (existingServer.getStartcode() > serverName.getStartcode()) {
284 LOG.info("Server serverName=" + serverName +
285 " rejected; we already have " + existingServer.toString() +
286 " registered with same hostname and port");
287 return false;
288 }
289 LOG.info("Triggering server recovery; existingServer " +
290 existingServer + " looks stale, new server:" + serverName);
291 expireServer(existingServer);
292 }
293 recordNewServer(serverName, sl);
294 return true;
295 }
296
297
298
299
300
301
302
303
304
305 private void checkClockSkew(final ServerName serverName, final long serverCurrentTime)
306 throws ClockOutOfSyncException {
307 long skew = System.currentTimeMillis() - serverCurrentTime;
308 if (skew > maxSkew) {
309 String message = "Server " + serverName + " has been " +
310 "rejected; Reported time is too far out of sync with master. " +
311 "Time difference of " + skew + "ms > max allowed of " + maxSkew + "ms";
312 LOG.warn(message);
313 throw new ClockOutOfSyncException(message);
314 } else if (skew > warningSkew){
315 String message = "Reported time for server " + serverName + " is out of sync with master " +
316 "by " + skew + "ms. (Warning threshold is " + warningSkew + "ms; " +
317 "error threshold is " + maxSkew + "ms)";
318 LOG.warn(message);
319 }
320 }
321
322
323
324
325
326
327
328
329
330 private void checkIsDead(final ServerName serverName, final String what)
331 throws YouAreDeadException {
332 if (this.deadservers.isDeadServer(serverName)) {
333
334
335 String message = "Server " + what + " rejected; currently processing " +
336 serverName + " as dead server";
337 LOG.debug(message);
338 throw new YouAreDeadException(message);
339 }
340
341
342 if ((this.services == null || ((HMaster) this.services).isInitialized())
343 && this.deadservers.cleanPreviousInstance(serverName)) {
344
345
346 LOG.debug(what + ":" + " Server " + serverName + " came back up," +
347 " removed it from the dead servers list");
348 }
349 }
350
351
352
353
354 private ServerName findServerWithSameHostnamePort(
355 final ServerName serverName) {
356 for (ServerName sn: getOnlineServersList()) {
357 if (ServerName.isSameHostnameAndPort(serverName, sn)) return sn;
358 }
359 return null;
360 }
361
362
363
364
365
366
367 void recordNewServer(final ServerName serverName, final ServerLoad sl) {
368 LOG.info("Registering server=" + serverName);
369 this.onlineServers.put(serverName, sl);
370 this.rsAdmins.remove(serverName);
371 }
372
373 public long getLastFlushedSequenceId(byte[] regionName) {
374 long seqId = -1;
375 if (flushedSequenceIdByRegion.containsKey(regionName)) {
376 seqId = flushedSequenceIdByRegion.get(regionName);
377 }
378 return seqId;
379 }
380
381
382
383
384
385 public ServerLoad getLoad(final ServerName serverName) {
386 return this.onlineServers.get(serverName);
387 }
388
389
390
391
392
393
394
395 public double getAverageLoad() {
396 int totalLoad = 0;
397 int numServers = 0;
398 double averageLoad;
399 for (ServerLoad sl: this.onlineServers.values()) {
400 numServers++;
401 totalLoad += sl.getNumberOfRegions();
402 }
403 averageLoad = (double)totalLoad / (double)numServers;
404 return averageLoad;
405 }
406
407
408 int countOfRegionServers() {
409
410 return this.onlineServers.size();
411 }
412
413
414
415
416 public Map<ServerName, ServerLoad> getOnlineServers() {
417
418 synchronized (this.onlineServers) {
419 return Collections.unmodifiableMap(this.onlineServers);
420 }
421 }
422
423
424 public DeadServer getDeadServers() {
425 return this.deadservers;
426 }
427
428
429
430
431
432 public boolean areDeadServersInProgress() {
433 return this.deadservers.areDeadServersInProgress();
434 }
435
436 void letRegionServersShutdown() {
437 long previousLogTime = 0;
438 while (!onlineServers.isEmpty()) {
439
440 if (System.currentTimeMillis() > (previousLogTime + 1000)) {
441 StringBuilder sb = new StringBuilder();
442 for (ServerName key : this.onlineServers.keySet()) {
443 if (sb.length() > 0) {
444 sb.append(", ");
445 }
446 sb.append(key);
447 }
448 LOG.info("Waiting on regionserver(s) to go down " + sb.toString());
449 previousLogTime = System.currentTimeMillis();
450 }
451
452 synchronized (onlineServers) {
453 try {
454 onlineServers.wait(100);
455 } catch (InterruptedException ignored) {
456
457 }
458 }
459 }
460 }
461
462
463
464
465
466 public synchronized void expireServer(final ServerName serverName) {
467 if (!services.isServerShutdownHandlerEnabled()) {
468 LOG.info("Master doesn't enable ServerShutdownHandler during initialization, "
469 + "delay expiring server " + serverName);
470 this.queuedDeadServers.add(serverName);
471 return;
472 }
473 if (!this.onlineServers.containsKey(serverName)) {
474 LOG.warn("Received expiration of " + serverName +
475 " but server is not currently online");
476 }
477 if (this.deadservers.isDeadServer(serverName)) {
478
479 LOG.warn("Received expiration of " + serverName +
480 " but server shutdown is already in progress");
481 return;
482 }
483
484
485
486 this.deadservers.add(serverName);
487 this.onlineServers.remove(serverName);
488 synchronized (onlineServers) {
489 onlineServers.notifyAll();
490 }
491 this.rsAdmins.remove(serverName);
492
493
494 if (this.clusterShutdown) {
495 LOG.info("Cluster shutdown set; " + serverName +
496 " expired; onlineServers=" + this.onlineServers.size());
497 if (this.onlineServers.isEmpty()) {
498 master.stop("Cluster shutdown set; onlineServer=0");
499 }
500 return;
501 }
502
503 boolean carryingMeta = services.getAssignmentManager().isCarryingMeta(serverName);
504 if (carryingMeta) {
505 this.services.getExecutorService().submit(new MetaServerShutdownHandler(this.master,
506 this.services, this.deadservers, serverName));
507 } else {
508 this.services.getExecutorService().submit(new ServerShutdownHandler(this.master,
509 this.services, this.deadservers, serverName, true));
510 }
511 LOG.debug("Added=" + serverName +
512 " to dead servers, submitted shutdown handler to be executed meta=" + carryingMeta);
513 }
514
515 public synchronized void processDeadServer(final ServerName serverName) {
516 this.processDeadServer(serverName, false);
517 }
518
519 public synchronized void processDeadServer(final ServerName serverName, boolean shouldSplitHlog) {
520
521
522
523
524
525
526
527
528 if (!services.getAssignmentManager().isFailoverCleanupDone()) {
529 requeuedDeadServers.put(serverName, shouldSplitHlog);
530 return;
531 }
532
533 this.deadservers.add(serverName);
534 this.services.getExecutorService().submit(
535 new ServerShutdownHandler(this.master, this.services, this.deadservers, serverName,
536 shouldSplitHlog));
537 }
538
539
540
541
542
543 synchronized void processQueuedDeadServers() {
544 if (!services.isServerShutdownHandlerEnabled()) {
545 LOG.info("Master hasn't enabled ServerShutdownHandler");
546 }
547 Iterator<ServerName> serverIterator = queuedDeadServers.iterator();
548 while (serverIterator.hasNext()) {
549 ServerName tmpServerName = serverIterator.next();
550 expireServer(tmpServerName);
551 serverIterator.remove();
552 requeuedDeadServers.remove(tmpServerName);
553 }
554
555 if (!services.getAssignmentManager().isFailoverCleanupDone()) {
556 LOG.info("AssignmentManager hasn't finished failover cleanup");
557 }
558
559 for(ServerName tmpServerName : requeuedDeadServers.keySet()){
560 processDeadServer(tmpServerName, requeuedDeadServers.get(tmpServerName));
561 }
562 requeuedDeadServers.clear();
563 }
564
565
566
567
568 public boolean removeServerFromDrainList(final ServerName sn) {
569
570
571
572 if (!this.isServerOnline(sn)) {
573 LOG.warn("Server " + sn + " is not currently online. " +
574 "Removing from draining list anyway, as requested.");
575 }
576
577 return this.drainingServers.remove(sn);
578 }
579
580
581
582
583 public boolean addServerToDrainList(final ServerName sn) {
584
585
586
587 if (!this.isServerOnline(sn)) {
588 LOG.warn("Server " + sn + " is not currently online. " +
589 "Ignoring request to add it to draining list.");
590 return false;
591 }
592
593
594 if (this.drainingServers.contains(sn)) {
595 LOG.warn("Server " + sn + " is already in the draining server list." +
596 "Ignoring request to add it again.");
597 return false;
598 }
599 return this.drainingServers.add(sn);
600 }
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615 public RegionOpeningState sendRegionOpen(final ServerName server,
616 HRegionInfo region, int versionOfOfflineNode, List<ServerName> favoredNodes)
617 throws IOException {
618 AdminService.BlockingInterface admin = getRsAdmin(server);
619 if (admin == null) {
620 LOG.warn("Attempting to send OPEN RPC to server " + server.toString() +
621 " failed because no RPC connection found to this server");
622 return RegionOpeningState.FAILED_OPENING;
623 }
624 OpenRegionRequest request =
625 RequestConverter.buildOpenRegionRequest(region, versionOfOfflineNode, favoredNodes);
626 try {
627 OpenRegionResponse response = admin.openRegion(null, request);
628 return ResponseConverter.getRegionOpeningState(response);
629 } catch (ServiceException se) {
630 throw ProtobufUtil.getRemoteException(se);
631 }
632 }
633
634
635
636
637
638
639
640
641
642
643 public List<RegionOpeningState> sendRegionOpen(ServerName server,
644 List<Triple<HRegionInfo, Integer, List<ServerName>>> regionOpenInfos)
645 throws IOException {
646 AdminService.BlockingInterface admin = getRsAdmin(server);
647 if (admin == null) {
648 LOG.warn("Attempting to send OPEN RPC to server " + server.toString() +
649 " failed because no RPC connection found to this server");
650 return null;
651 }
652
653 OpenRegionRequest request =
654 RequestConverter.buildOpenRegionRequest(regionOpenInfos);
655 try {
656 OpenRegionResponse response = admin.openRegion(null, request);
657 return ResponseConverter.getRegionOpeningStateList(response);
658 } catch (ServiceException se) {
659 throw ProtobufUtil.getRemoteException(se);
660 }
661 }
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677 public boolean sendRegionClose(ServerName server, HRegionInfo region,
678 int versionOfClosingNode, ServerName dest, boolean transitionInZK) throws IOException {
679 if (server == null) throw new NullPointerException("Passed server is null");
680 AdminService.BlockingInterface admin = getRsAdmin(server);
681 if (admin == null) {
682 throw new IOException("Attempting to send CLOSE RPC to server " +
683 server.toString() + " for region " +
684 region.getRegionNameAsString() +
685 " failed because no RPC connection found to this server");
686 }
687 return ProtobufUtil.closeRegion(admin, region.getRegionName(),
688 versionOfClosingNode, dest, transitionInZK);
689 }
690
691 public boolean sendRegionClose(ServerName server,
692 HRegionInfo region, int versionOfClosingNode) throws IOException {
693 return sendRegionClose(server, region, versionOfClosingNode, null, true);
694 }
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709 public void sendRegionsMerge(ServerName server, HRegionInfo region_a,
710 HRegionInfo region_b, boolean forcible) throws IOException {
711 if (server == null)
712 throw new NullPointerException("Passed server is null");
713 if (region_a == null || region_b == null)
714 throw new NullPointerException("Passed region is null");
715 AdminService.BlockingInterface admin = getRsAdmin(server);
716 if (admin == null) {
717 throw new IOException("Attempting to send MERGE REGIONS RPC to server "
718 + server.toString() + " for region "
719 + region_a.getRegionNameAsString() + ","
720 + region_b.getRegionNameAsString()
721 + " failed because no RPC connection found to this server");
722 }
723 ProtobufUtil.mergeRegions(admin, region_a, region_b, forcible);
724 }
725
726
727
728
729
730
731
732 private AdminService.BlockingInterface getRsAdmin(final ServerName sn)
733 throws IOException {
734 AdminService.BlockingInterface admin = this.rsAdmins.get(sn);
735 if (admin == null) {
736 LOG.debug("New admin connection to " + sn.toString());
737 admin = this.connection.getAdmin(sn);
738 this.rsAdmins.put(sn, admin);
739 }
740 return admin;
741 }
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756 public void waitForRegionServers(MonitoredTask status)
757 throws InterruptedException {
758 final long interval = this.master.getConfiguration().
759 getLong(WAIT_ON_REGIONSERVERS_INTERVAL, 1500);
760 final long timeout = this.master.getConfiguration().
761 getLong(WAIT_ON_REGIONSERVERS_TIMEOUT, 4500);
762 int minToStart = this.master.getConfiguration().
763 getInt(WAIT_ON_REGIONSERVERS_MINTOSTART, 1);
764 if (minToStart < 1) {
765 LOG.warn(String.format(
766 "The value of '%s' (%d) can not be less than 1, ignoring.",
767 WAIT_ON_REGIONSERVERS_MINTOSTART, minToStart));
768 minToStart = 1;
769 }
770 int maxToStart = this.master.getConfiguration().
771 getInt(WAIT_ON_REGIONSERVERS_MAXTOSTART, Integer.MAX_VALUE);
772 if (maxToStart < minToStart) {
773 LOG.warn(String.format(
774 "The value of '%s' (%d) is set less than '%s' (%d), ignoring.",
775 WAIT_ON_REGIONSERVERS_MAXTOSTART, maxToStart,
776 WAIT_ON_REGIONSERVERS_MINTOSTART, minToStart));
777 maxToStart = Integer.MAX_VALUE;
778 }
779
780 long now = System.currentTimeMillis();
781 final long startTime = now;
782 long slept = 0;
783 long lastLogTime = 0;
784 long lastCountChange = startTime;
785 int count = countOfRegionServers();
786 int oldCount = 0;
787 while (
788 !this.master.isStopped() &&
789 count < maxToStart &&
790 (lastCountChange+interval > now || timeout > slept || count < minToStart)
791 ){
792
793
794 if (oldCount != count || lastLogTime+interval < now){
795 lastLogTime = now;
796 String msg =
797 "Waiting for region servers count to settle; currently"+
798 " checked in " + count + ", slept for " + slept + " ms," +
799 " expecting minimum of " + minToStart + ", maximum of "+ maxToStart+
800 ", timeout of "+timeout+" ms, interval of "+interval+" ms.";
801 LOG.info(msg);
802 status.setStatus(msg);
803 }
804
805
806 final long sleepTime = 50;
807 Thread.sleep(sleepTime);
808 now = System.currentTimeMillis();
809 slept = now - startTime;
810
811 oldCount = count;
812 count = countOfRegionServers();
813 if (count != oldCount) {
814 lastCountChange = now;
815 }
816 }
817
818 LOG.info("Finished waiting for region servers count to settle;" +
819 " checked in " + count + ", slept for " + slept + " ms," +
820 " expecting minimum of " + minToStart + ", maximum of "+ maxToStart+","+
821 " master is "+ (this.master.isStopped() ? "stopped.": "running.")
822 );
823 }
824
825
826
827
828 public List<ServerName> getOnlineServersList() {
829
830
831 return new ArrayList<ServerName>(this.onlineServers.keySet());
832 }
833
834
835
836
837 public List<ServerName> getDrainingServersList() {
838 return new ArrayList<ServerName>(this.drainingServers);
839 }
840
841
842
843
844 Set<ServerName> getDeadNotExpiredServers() {
845 return new HashSet<ServerName>(this.queuedDeadServers);
846 }
847
848
849
850
851
852 Map<ServerName, Boolean> getRequeuedDeadServers() {
853 return Collections.unmodifiableMap(this.requeuedDeadServers);
854 }
855
856 public boolean isServerOnline(ServerName serverName) {
857 return serverName != null && onlineServers.containsKey(serverName);
858 }
859
860
861
862
863
864
865
866 public synchronized boolean isServerDead(ServerName serverName) {
867 return serverName == null || deadservers.isDeadServer(serverName)
868 || queuedDeadServers.contains(serverName)
869 || requeuedDeadServers.containsKey(serverName);
870 }
871
872 public void shutdownCluster() {
873 this.clusterShutdown = true;
874 this.master.stop("Cluster shutdown requested");
875 }
876
877 public boolean isClusterShutdown() {
878 return this.clusterShutdown;
879 }
880
881
882
883
884 public void stop() {
885 if (connection != null) {
886 try {
887 connection.close();
888 } catch (IOException e) {
889 LOG.error("Attempt to close connection to master failed", e);
890 }
891 }
892 }
893
894
895
896
897
898
899 public List<ServerName> createDestinationServersList(final ServerName serverToExclude){
900 final List<ServerName> destServers = getOnlineServersList();
901
902 if (serverToExclude != null){
903 destServers.remove(serverToExclude);
904 }
905
906
907 final List<ServerName> drainingServersCopy = getDrainingServersList();
908 if (!drainingServersCopy.isEmpty()) {
909 for (final ServerName server: drainingServersCopy) {
910 destServers.remove(server);
911 }
912 }
913
914
915 removeDeadNotExpiredServers(destServers);
916
917 return destServers;
918 }
919
920
921
922
923 public List<ServerName> createDestinationServersList(){
924 return createDestinationServersList(null);
925 }
926
927
928
929
930
931
932
933 void removeDeadNotExpiredServers(List<ServerName> servers) {
934 Set<ServerName> deadNotExpiredServersCopy = this.getDeadNotExpiredServers();
935 if (!deadNotExpiredServersCopy.isEmpty()) {
936 for (ServerName server : deadNotExpiredServersCopy) {
937 LOG.debug("Removing dead but not expired server: " + server
938 + " from eligible server pool.");
939 servers.remove(server);
940 }
941 }
942 }
943
944
945
946
947 void clearDeadServersWithSameHostNameAndPortOfOnlineServer() {
948 for (ServerName serverName : getOnlineServersList()) {
949 deadservers.cleanAllPreviousInstances(serverName);
950 }
951 }
952 }