1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.master;
21
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24 import org.apache.hadoop.conf.Configuration;
25 import org.apache.hadoop.hbase.Chore;
26 import org.apache.hadoop.hbase.HConstants;
27 import org.apache.hadoop.hbase.HMsg;
28 import org.apache.hadoop.hbase.HRegionInfo;
29 import org.apache.hadoop.hbase.HRegionLocation;
30 import org.apache.hadoop.hbase.HServerAddress;
31 import org.apache.hadoop.hbase.HServerInfo;
32 import org.apache.hadoop.hbase.HServerLoad;
33 import org.apache.hadoop.hbase.PleaseHoldException;
34 import org.apache.hadoop.hbase.YouAreDeadException;
35 import org.apache.hadoop.hbase.client.Get;
36 import org.apache.hadoop.hbase.client.Result;
37 import org.apache.hadoop.hbase.ipc.HRegionInterface;
38 import org.apache.hadoop.hbase.master.RegionManager.RegionState;
39 import org.apache.hadoop.hbase.util.Bytes;
40 import org.apache.hadoop.hbase.util.Threads;
41 import org.apache.zookeeper.WatchedEvent;
42 import org.apache.zookeeper.Watcher;
43 import org.apache.zookeeper.Watcher.Event.EventType;
44
45 import java.io.IOException;
46 import java.util.ArrayList;
47 import java.util.Collections;
48 import java.util.HashSet;
49 import java.util.Map;
50 import java.util.Set;
51 import java.util.SortedMap;
52 import java.util.TreeMap;
53 import java.util.concurrent.ConcurrentHashMap;
54 import java.util.concurrent.atomic.AtomicBoolean;
55 import java.util.concurrent.atomic.AtomicInteger;
56
57
58
59
60
61 public class ServerManager {
62 private static final Log LOG =
63 LogFactory.getLog(ServerManager.class.getName());
64
65 private final AtomicInteger quiescedServers = new AtomicInteger(0);
66
67
68 private final Map<String, HServerInfo> serversToServerInfo =
69 new ConcurrentHashMap<String, HServerInfo>();
70
71
72
73
74
75
76
77
78 private final Set<String> deadServers =
79 Collections.synchronizedSet(new HashSet<String>());
80
81
82 private final SortedMap<HServerLoad, Set<String>> loadToServers =
83 Collections.synchronizedSortedMap(new TreeMap<HServerLoad, Set<String>>());
84
85 private final Map<String, HServerLoad> serversToLoad =
86 new ConcurrentHashMap<String, HServerLoad>();
87
88 private HMaster master;
89
90
91
92
93 private final int nobalancingCount;
94
95 private final ServerMonitor serverMonitorThread;
96
97 private int minimumServerCount;
98
99 private final LogsCleaner logCleaner;
100
101
102
103
104
105 class ServerMonitor extends Chore {
106 ServerMonitor(final int period, final AtomicBoolean stop) {
107 super("ServerMonitor", period, stop);
108 }
109
110 @Override
111 protected void chore() {
112 int numServers = serversToServerInfo.size();
113 int numDeadServers = deadServers.size();
114 double averageLoad = getAverageLoad();
115 String deadServersList = null;
116 if (numDeadServers > 0) {
117 StringBuilder sb = new StringBuilder("Dead Server [");
118 boolean first = true;
119 synchronized (deadServers) {
120 for (String server: deadServers) {
121 if (!first) {
122 sb.append(", ");
123 first = false;
124 }
125 sb.append(server);
126 }
127 }
128 sb.append("]");
129 deadServersList = sb.toString();
130 }
131 LOG.info(numServers + " region servers, " + numDeadServers +
132 " dead, average load " + averageLoad +
133 (deadServersList != null? deadServers: ""));
134 }
135 }
136
137
138
139
140
141 public ServerManager(HMaster master) {
142 this.master = master;
143 Configuration c = master.getConfiguration();
144 this.nobalancingCount = c.getInt("hbase.regions.nobalancing.count", 4);
145 int metaRescanInterval = c.getInt("hbase.master.meta.thread.rescanfrequency",
146 60 * 1000);
147 this.minimumServerCount = c.getInt("hbase.regions.server.count.min", 0);
148 this.serverMonitorThread = new ServerMonitor(metaRescanInterval,
149 this.master.getShutdownRequested());
150 String n = Thread.currentThread().getName();
151 Threads.setDaemonThreadRunning(this.serverMonitorThread,
152 n + ".serverMonitor");
153 this.logCleaner = new LogsCleaner(
154 c.getInt("hbase.master.meta.thread.rescanfrequency",60 * 1000),
155 this.master.getShutdownRequested(), c,
156 master.getFileSystem(), master.getOldLogDir());
157 Threads.setDaemonThreadRunning(logCleaner,
158 n + ".oldLogCleaner");
159
160 }
161
162
163
164
165
166
167 void regionServerStartup(final HServerInfo serverInfo)
168 throws IOException {
169
170
171
172
173
174
175
176 HServerInfo info = new HServerInfo(serverInfo);
177 String hostAndPort = info.getServerAddress().toString();
178 HServerInfo existingServer = haveServerWithSameHostAndPortAlready(info.getHostnamePort());
179 if (existingServer != null) {
180 String message = "Server start rejected; we already have " + hostAndPort +
181 " registered; existingServer=" + existingServer + ", newServer=" + info;
182 LOG.info(message);
183 if (existingServer.getStartCode() < info.getStartCode()) {
184 LOG.info("Triggering server recovery; existingServer looks stale");
185 expireServer(existingServer);
186 }
187 throw new PleaseHoldException(message);
188 }
189 checkIsDead(info.getServerName(), "STARTUP");
190 LOG.info("Received start message from: " + info.getServerName());
191 recordNewServer(info);
192 }
193
194 private HServerInfo haveServerWithSameHostAndPortAlready(final String hostnamePort) {
195 synchronized (this.serversToServerInfo) {
196 for (Map.Entry<String, HServerInfo> e: this.serversToServerInfo.entrySet()) {
197 if (e.getValue().getHostnamePort().equals(hostnamePort)) {
198 return e.getValue();
199 }
200 }
201 }
202 return null;
203 }
204
205
206
207
208
209
210
211 private void checkIsDead(final String serverName, final String what)
212 throws YouAreDeadException {
213 if (!isDead(serverName)) return;
214 String message = "Server " + what + " rejected; currently processing " +
215 serverName + " as dead server";
216 LOG.debug(message);
217 throw new YouAreDeadException(message);
218 }
219
220
221
222
223
224 public void recordNewServer(HServerInfo info) {
225 recordNewServer(info, false);
226 }
227
228
229
230
231
232
233
234 void recordNewServer(HServerInfo info, boolean useInfoLoad) {
235 HServerLoad load = useInfoLoad ? info.getLoad() : new HServerLoad();
236 String serverName = info.getServerName();
237 info.setLoad(load);
238
239
240 Watcher watcher = new ServerExpirer(new HServerInfo(info));
241 this.master.getZooKeeperWrapper().updateRSLocationGetWatch(info, watcher);
242 this.serversToServerInfo.put(serverName, info);
243 this.serversToLoad.put(serverName, load);
244 synchronized (this.loadToServers) {
245 Set<String> servers = this.loadToServers.get(load);
246 if (servers == null) {
247 servers = new HashSet<String>();
248 }
249 servers.add(serverName);
250 this.loadToServers.put(load, servers);
251 }
252 }
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267 HMsg [] regionServerReport(final HServerInfo serverInfo,
268 final HMsg msgs[], final HRegionInfo[] mostLoadedRegions)
269 throws IOException {
270 HServerInfo info = new HServerInfo(serverInfo);
271 checkIsDead(info.getServerName(), "REPORT");
272 if (msgs.length > 0) {
273 if (msgs[0].isType(HMsg.Type.MSG_REPORT_EXITING)) {
274 processRegionServerExit(info, msgs);
275 return HMsg.EMPTY_HMSG_ARRAY;
276 } else if (msgs[0].isType(HMsg.Type.MSG_REPORT_QUIESCED)) {
277 LOG.info("Region server " + info.getServerName() + " quiesced");
278 this.quiescedServers.incrementAndGet();
279 }
280 }
281 if (this.master.getShutdownRequested().get()) {
282 if (quiescedServers.get() >= serversToServerInfo.size()) {
283
284
285 LOG.info("All user tables quiesced. Proceeding with shutdown");
286 this.master.startShutdown();
287 }
288 if (!this.master.isClosed()) {
289 if (msgs.length > 0 &&
290 msgs[0].isType(HMsg.Type.MSG_REPORT_QUIESCED)) {
291
292
293 return HMsg.EMPTY_HMSG_ARRAY;
294 }
295
296 return new HMsg [] {HMsg.REGIONSERVER_QUIESCE};
297 }
298 }
299 if (this.master.isClosed()) {
300
301
302
303 return new HMsg [] {HMsg.REGIONSERVER_STOP};
304 }
305
306 HServerInfo storedInfo = this.serversToServerInfo.get(info.getServerName());
307 if (storedInfo == null) {
308 LOG.warn("Received report from unknown server -- telling it " +
309 "to " + HMsg.REGIONSERVER_STOP + ": " + info.getServerName());
310
311
312 return new HMsg[] {HMsg.REGIONSERVER_STOP};
313 } else if (storedInfo.getStartCode() != info.getStartCode()) {
314
315
316
317
318
319
320
321
322
323 if (LOG.isDebugEnabled()) {
324 LOG.debug("region server race condition detected: " +
325 info.getServerName());
326 }
327
328 synchronized (this.serversToServerInfo) {
329 removeServerInfo(info.getServerName());
330 notifyServers();
331 }
332
333 return new HMsg[] {HMsg.REGIONSERVER_STOP};
334 } else {
335 return processRegionServerAllsWell(info, mostLoadedRegions, msgs);
336 }
337 }
338
339
340
341
342
343
344
345
346
347 private void processRegionServerExit(HServerInfo serverInfo, HMsg[] msgs) {
348 synchronized (this.serversToServerInfo) {
349
350
351 if (removeServerInfo(serverInfo.getServerName())) {
352
353
354 LOG.info("Region server " + serverInfo.getServerName() +
355 ": MSG_REPORT_EXITING");
356
357
358 if (!master.closed.get()) {
359 for (int i = 1; i < msgs.length; i++) {
360 LOG.info("Processing " + msgs[i] + " from " +
361 serverInfo.getServerName());
362 assert msgs[i].getType() == HMsg.Type.MSG_REGION_CLOSE;
363 HRegionInfo info = msgs[i].getRegionInfo();
364
365 if (!info.isMetaRegion()) {
366 synchronized (master.getRegionManager()) {
367 if (!master.getRegionManager().isOfflined(info.getRegionNameAsString())) {
368 master.getRegionManager().setUnassigned(info, true);
369 } else {
370 master.getRegionManager().removeRegion(info);
371 }
372 }
373 }
374 }
375 }
376
377
378 Map<String, RegionState> inTransition = master.getRegionManager()
379 .getRegionsInTransitionOnServer(serverInfo.getServerName());
380 for (Map.Entry<String, RegionState> entry : inTransition.entrySet()) {
381 LOG.warn("Region server " + serverInfo.getServerName()
382 + " shut down with region " + entry.getKey() + " in transition "
383 + "state " + entry.getValue());
384 master.getRegionManager().setUnassigned(entry.getValue().getRegionInfo(),
385 true);
386 }
387 }
388 }
389 }
390
391
392
393
394
395
396
397
398
399 private HMsg[] processRegionServerAllsWell(HServerInfo serverInfo,
400 final HRegionInfo[] mostLoadedRegions, HMsg[] msgs)
401 throws IOException {
402
403 this.serversToServerInfo.put(serverInfo.getServerName(), serverInfo);
404 HServerLoad load = this.serversToLoad.get(serverInfo.getServerName());
405 if (load != null) {
406 this.master.getMetrics().incrementRequests(load.getNumberOfRequests());
407 if (!load.equals(serverInfo.getLoad())) {
408 updateLoadToServers(serverInfo.getServerName(), load);
409 }
410 }
411
412
413 load = serverInfo.getLoad();
414 this.serversToLoad.put(serverInfo.getServerName(), load);
415 synchronized (loadToServers) {
416 Set<String> servers = this.loadToServers.get(load);
417 if (servers == null) {
418 servers = new HashSet<String>();
419 }
420 servers.add(serverInfo.getServerName());
421 this.loadToServers.put(load, servers);
422 }
423
424
425 return processMsgs(serverInfo, mostLoadedRegions, msgs);
426 }
427
428
429
430
431
432
433
434
435
436
437 private HMsg[] processMsgs(HServerInfo serverInfo,
438 HRegionInfo[] mostLoadedRegions, HMsg incomingMsgs[]) {
439 ArrayList<HMsg> returnMsgs = new ArrayList<HMsg>();
440 if (serverInfo.getServerAddress() == null) {
441 throw new NullPointerException("Server address cannot be null; " +
442 "hbase-958 debugging");
443 }
444
445
446
447 int openingCount = 0;
448 for (int i = 0; i < incomingMsgs.length; i++) {
449 HRegionInfo region = incomingMsgs[i].getRegionInfo();
450 LOG.info("Processing " + incomingMsgs[i] + " from " +
451 serverInfo.getServerName() + "; " + (i + 1) + " of " +
452 incomingMsgs.length);
453 if (!this.master.getRegionServerOperationQueue().
454 process(serverInfo, incomingMsgs[i])) {
455 continue;
456 }
457 switch (incomingMsgs[i].getType()) {
458 case MSG_REPORT_PROCESS_OPEN:
459 openingCount++;
460 break;
461
462 case MSG_REPORT_OPEN:
463 processRegionOpen(serverInfo, region, returnMsgs);
464 break;
465
466 case MSG_REPORT_CLOSE:
467 processRegionClose(region);
468 break;
469
470 case MSG_REPORT_SPLIT:
471 processSplitRegion(region, incomingMsgs[++i].getRegionInfo(),
472 incomingMsgs[++i].getRegionInfo());
473 break;
474
475 case MSG_REPORT_SPLIT_INCLUDES_DAUGHTERS:
476 processSplitRegion(region, incomingMsgs[i].getDaughterA(),
477 incomingMsgs[i].getDaughterB());
478 break;
479
480 default:
481 LOG.warn("Impossible state during message processing. Instruction: " +
482 incomingMsgs[i].getType());
483 }
484 }
485
486 synchronized (this.master.getRegionManager()) {
487
488 for (HRegionInfo i:
489 this.master.getRegionManager().getMarkedToClose(serverInfo.getServerName())) {
490 returnMsgs.add(new HMsg(HMsg.Type.MSG_REGION_CLOSE, i));
491
492 this.master.getRegionManager().setPendingClose(i.getRegionNameAsString());
493 }
494
495
496
497
498
499 if (openingCount < this.nobalancingCount) {
500 this.master.getRegionManager().assignRegions(serverInfo, mostLoadedRegions,
501 returnMsgs);
502 }
503
504
505 this.master.getRegionManager().applyActions(serverInfo, returnMsgs);
506 }
507 return returnMsgs.toArray(new HMsg[returnMsgs.size()]);
508 }
509
510
511
512
513
514
515
516
517
518 private void processSplitRegion(HRegionInfo region, HRegionInfo a, HRegionInfo b) {
519 synchronized (master.getRegionManager()) {
520
521
522
523 this.master.getRegionManager().endActions(region.getRegionName());
524 assignSplitDaughter(a);
525 assignSplitDaughter(b);
526 if (region.isMetaTable()) {
527
528 this. master.getRegionManager().offlineMetaRegionWithStartKey(region.getStartKey());
529 this.master.getRegionManager().incrementNumMetaRegions();
530 }
531 }
532 }
533
534
535
536
537
538
539
540
541
542 private void assignSplitDaughter(final HRegionInfo hri) {
543 MetaRegion mr =
544 this.master.getRegionManager().getFirstMetaRegionForRegion(hri);
545 Get g = new Get(hri.getRegionName());
546 g.addFamily(HConstants.CATALOG_FAMILY);
547 try {
548 HRegionInterface server =
549 this.master.getServerConnection().getHRegionConnection(mr.getServer());
550 Result r = server.get(mr.getRegionName(), g);
551
552
553 if (r.size() >= 3) return;
554 } catch (IOException e) {
555 LOG.warn("Failed get on " + HConstants.CATALOG_FAMILY_STR +
556 "; possible double-assignment?", e);
557 }
558 this.master.getRegionManager().setUnassigned(hri, false);
559 }
560
561
562
563
564
565
566
567 public void processRegionOpen(HServerInfo serverInfo,
568 HRegionInfo region, ArrayList<HMsg> returnMsgs) {
569 boolean duplicateAssignment = false;
570 synchronized (master.getRegionManager()) {
571 if (!this.master.getRegionManager().isUnassigned(region) &&
572 !this.master.getRegionManager().isPendingOpen(region.getRegionNameAsString())) {
573 if (region.isRootRegion()) {
574
575 HServerAddress rootServer =
576 this.master.getRegionManager().getRootRegionLocation();
577 if (rootServer != null) {
578 if (rootServer.compareTo(serverInfo.getServerAddress()) == 0) {
579
580 return;
581 }
582
583
584 duplicateAssignment = true;
585 }
586 } else {
587
588
589
590 if (this.master.getRegionManager().isPendingOpen(
591 region.getRegionNameAsString())) {
592
593 return;
594 }
595 duplicateAssignment = true;
596 }
597 }
598
599 if (duplicateAssignment) {
600 LOG.warn("region server " + serverInfo.getServerAddress().toString() +
601 " should not have opened region " + Bytes.toString(region.getRegionName()));
602
603
604
605
606
607 returnMsgs.add(new HMsg(HMsg.Type.MSG_REGION_CLOSE_WITHOUT_REPORT,
608 region, "Duplicate assignment".getBytes()));
609 } else {
610 if (region.isRootRegion()) {
611
612
613 this.master.getRegionManager().removeRegion(region);
614
615
616 HServerAddress rootServer = serverInfo.getServerAddress();
617 this.master.getServerConnection().setRootRegionLocation(
618 new HRegionLocation(region, rootServer));
619 this.master.getRegionManager().setRootRegionLocation(rootServer);
620 } else {
621
622
623 this.master.getRegionManager().setOpen(region.getRegionNameAsString());
624 RegionServerOperation op =
625 new ProcessRegionOpen(master, serverInfo, region);
626 this.master.getRegionServerOperationQueue().put(op);
627 }
628 }
629 }
630 }
631
632
633
634
635
636 public void processRegionClose(HRegionInfo region) {
637 synchronized (this.master.getRegionManager()) {
638 if (region.isRootRegion()) {
639
640 this.master.getRegionManager().unsetRootRegion();
641 if (region.isOffline()) {
642
643 LOG.fatal("root region is marked offline");
644 this.master.shutdown();
645 return;
646 }
647
648 } else if (region.isMetaTable()) {
649
650 this.master.getRegionManager().offlineMetaRegionWithStartKey(region.getStartKey());
651 }
652
653 boolean offlineRegion =
654 this.master.getRegionManager().isOfflined(region.getRegionNameAsString());
655 boolean reassignRegion = !region.isOffline() && !offlineRegion;
656
657
658
659
660
661
662 this.master.getRegionManager().setClosed(region.getRegionNameAsString());
663 RegionServerOperation op =
664 new ProcessRegionClose(master, region, offlineRegion, reassignRegion);
665 this.master.getRegionServerOperationQueue().put(op);
666 }
667 }
668
669
670 private boolean removeServerInfo(final String serverName) {
671 boolean infoUpdated = false;
672 HServerInfo info = this.serversToServerInfo.remove(serverName);
673
674
675 if (info != null) {
676 LOG.info("Removing server's info " + serverName);
677 this.master.getRegionManager().offlineMetaServer(info.getServerAddress());
678
679
680 if (this.master.getRegionManager().isRootInTransitionOnThisServer(serverName)) {
681 this.master.getRegionManager().unsetRootRegion();
682 this.master.getRegionManager().reassignRootRegion();
683 }
684
685
686 HRegionInfo metaServerRegionInfo = this.master.getRegionManager().getMetaServerRegionInfo (serverName);
687 if (metaServerRegionInfo != null) {
688 this.master.getRegionManager().setUnassigned(metaServerRegionInfo, true);
689 }
690
691 infoUpdated = true;
692
693 updateLoadToServers(serverName, this.serversToLoad.remove(serverName));
694 }
695 return infoUpdated;
696 }
697
698 private void updateLoadToServers(final String serverName,
699 final HServerLoad load) {
700 if (load == null) return;
701 synchronized (this.loadToServers) {
702 Set<String> servers = this.loadToServers.get(load);
703 if (servers != null) {
704 servers.remove(serverName);
705 if (servers.size() > 0)
706 this.loadToServers.put(load, servers);
707 else
708 this.loadToServers.remove(load);
709 }
710 }
711 }
712
713
714
715
716
717
718
719 public double getAverageLoad() {
720 int totalLoad = 0;
721 int numServers = 0;
722 double averageLoad = 0.0;
723 synchronized (serversToLoad) {
724 numServers = serversToLoad.size();
725 for (HServerLoad load : serversToLoad.values()) {
726 totalLoad += load.getNumberOfRegions();
727 }
728 averageLoad = (double)totalLoad / (double)numServers;
729 }
730 return averageLoad;
731 }
732
733
734 public int numServers() {
735 return this.serversToServerInfo.size();
736 }
737
738
739
740
741
742 public HServerInfo getServerInfo(String name) {
743 return this.serversToServerInfo.get(name);
744 }
745
746
747
748
749 public Map<String, HServerInfo> getServersToServerInfo() {
750 synchronized (this.serversToServerInfo) {
751 return Collections.unmodifiableMap(this.serversToServerInfo);
752 }
753 }
754
755
756
757
758
759
760 public HServerInfo getHServerInfo(final HServerAddress hsa) {
761 synchronized(this.serversToServerInfo) {
762
763 for (Map.Entry<String, HServerInfo> e: this.serversToServerInfo.entrySet()) {
764 if (e.getValue().getServerAddress().equals(hsa)) return e.getValue();
765 }
766 }
767 return null;
768 }
769
770
771
772
773 public Map<String, HServerLoad> getServersToLoad() {
774 synchronized (this.serversToLoad) {
775 return Collections.unmodifiableMap(serversToLoad);
776 }
777 }
778
779
780
781
782 public SortedMap<HServerLoad, Set<String>> getLoadToServers() {
783 synchronized (this.loadToServers) {
784 return Collections.unmodifiableSortedMap(this.loadToServers);
785 }
786 }
787
788
789
790
791 public void notifyServers() {
792 synchronized (this.serversToServerInfo) {
793 this.serversToServerInfo.notifyAll();
794 }
795 }
796
797
798
799
800
801
802
803 void letRegionServersShutdown() {
804 if (!master.checkFileSystem()) {
805
806
807 return;
808 }
809 synchronized (serversToServerInfo) {
810 while (serversToServerInfo.size() > 0) {
811 LOG.info("Waiting on following regionserver(s) to go down " +
812 this.serversToServerInfo.values());
813 try {
814 this.serversToServerInfo.wait(500);
815 } catch (InterruptedException e) {
816
817 }
818 }
819 }
820 }
821
822
823 private class ServerExpirer implements Watcher {
824 private HServerInfo server;
825
826 ServerExpirer(final HServerInfo hsi) {
827 this.server = hsi;
828 }
829
830 public void process(WatchedEvent event) {
831 if (!event.getType().equals(EventType.NodeDeleted)) {
832 LOG.warn("Unexpected event=" + event);
833 return;
834 }
835 LOG.info(this.server.getServerName() + " znode expired");
836 expireServer(this.server);
837 }
838 }
839
840
841
842
843
844 private synchronized void expireServer(final HServerInfo hsi) {
845
846
847 String serverName = hsi.getServerName();
848 HServerInfo info = this.serversToServerInfo.get(serverName);
849 if (info == null) {
850 LOG.warn("No HServerInfo for " + serverName);
851 return;
852 }
853 if (this.deadServers.contains(serverName)) {
854 LOG.warn("Already processing shutdown of " + serverName);
855 return;
856 }
857
858 this.serversToServerInfo.remove(serverName);
859 HServerLoad load = this.serversToLoad.remove(serverName);
860 if (load != null) {
861 synchronized (this.loadToServers) {
862 Set<String> servers = this.loadToServers.get(load);
863 if (servers != null) {
864 servers.remove(serverName);
865 if (servers.isEmpty()) this.loadToServers.remove(load);
866 }
867 }
868 }
869
870 LOG.debug("Added=" + serverName +
871 " to dead servers, added shutdown processing operation");
872 this.deadServers.add(serverName);
873 this.master.getRegionServerOperationQueue().
874 put(new ProcessServerShutdown(master, info));
875 }
876
877
878
879
880 void removeDeadServer(String serverName) {
881 this.deadServers.remove(serverName);
882 }
883
884
885
886
887
888 public boolean isDead(final String serverName) {
889 return isDead(serverName, false);
890 }
891
892
893
894
895
896
897
898
899
900 boolean isDead(final String serverName, final boolean hostAndPortOnly) {
901 return isDead(this.deadServers, serverName, hostAndPortOnly);
902 }
903
904 static boolean isDead(final Set<String> deadServers,
905 final String serverName, final boolean hostAndPortOnly) {
906 return HServerInfo.isServer(deadServers, serverName, hostAndPortOnly);
907 }
908
909 Set<String> getDeadServers() {
910 return this.deadServers;
911 }
912
913
914
915
916
917
918
919 void getLightServers(final HServerLoad l,
920 SortedMap<HServerLoad, Set<String>> m) {
921 synchronized (this.loadToServers) {
922 m.putAll(this.loadToServers.headMap(l));
923 }
924 }
925
926 public boolean canAssignUserRegions() {
927 if (minimumServerCount == 0) {
928 return true;
929 }
930 return (numServers() >= minimumServerCount);
931 }
932
933 public void setMinimumServerCount(int minimumServerCount) {
934 this.minimumServerCount = minimumServerCount;
935 }
936 }