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 com.google.common.base.Preconditions;
22
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.Comparator;
26 import java.util.Date;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Set;
33
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36 import org.apache.hadoop.hbase.classification.InterfaceAudience;
37 import org.apache.hadoop.hbase.ServerName;
38 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
39 import org.apache.hadoop.hbase.util.Pair;
40
41
42
43
44
45 @InterfaceAudience.Private
46 public class DeadServer {
47 private static final Log LOG = LogFactory.getLog(DeadServer.class);
48
49
50
51
52
53
54
55
56 private final Map<ServerName, Long> deadServers = new HashMap<ServerName, Long>();
57
58
59
60
61 private final Set<ServerName> processingServers = new HashSet<ServerName>();
62
63
64
65
66
67
68
69
70
71 public synchronized boolean cleanPreviousInstance(final ServerName newServerName) {
72 Iterator<ServerName> it = deadServers.keySet().iterator();
73 while (it.hasNext()) {
74 ServerName sn = it.next();
75 if (ServerName.isSameHostnameAndPort(sn, newServerName)) {
76
77 it.remove();
78
79 boolean removed = processingServers.remove(sn);
80 if (removed) {
81 LOG.debug("Removed " + sn + " ; numProcessing=" + processingServers.size());
82 }
83 return true;
84 }
85 }
86
87 return false;
88 }
89
90
91
92
93
94 public synchronized boolean isDeadServer(final ServerName serverName) {
95 return deadServers.containsKey(serverName);
96 }
97
98
99
100
101
102 public synchronized boolean isProcessingServer(final ServerName serverName) {
103 return processingServers.contains(serverName);
104 }
105
106
107
108
109
110
111
112
113 public synchronized boolean areDeadServersInProgress() {
114 return !processingServers.isEmpty();
115 }
116
117 public synchronized Set<ServerName> copyServerNames() {
118 Set<ServerName> clone = new HashSet<ServerName>(deadServers.size());
119 clone.addAll(deadServers.keySet());
120 return clone;
121 }
122
123
124
125
126
127 public synchronized void add(ServerName sn) {
128 if (!deadServers.containsKey(sn)){
129 deadServers.put(sn, EnvironmentEdgeManager.currentTime());
130 }
131 boolean added = processingServers.add(sn);
132 if (LOG.isDebugEnabled() && added) {
133 LOG.debug("Added " + sn + "; numProcessing=" + processingServers.size());
134 }
135 }
136
137
138
139
140
141 public synchronized void notifyServer(ServerName sn) {
142 boolean added = processingServers.add(sn);
143 if (LOG.isDebugEnabled()) {
144 if (added) {
145 LOG.debug("Added " + sn + "; numProcessing=" + processingServers.size());
146 }
147 LOG.debug("Started processing " + sn + "; numProcessing=" + processingServers.size());
148 }
149 }
150
151
152
153
154
155 public synchronized void finish(ServerName sn) {
156 boolean removed = processingServers.remove(sn);
157 if (LOG.isDebugEnabled()) {
158 LOG.debug("Finished processing " + sn + "; numProcessing=" + processingServers.size());
159 if (removed) {
160 LOG.debug("Removed " + sn + " ; numProcessing=" + processingServers.size());
161 }
162 }
163 }
164
165 public synchronized int size() {
166 return deadServers.size();
167 }
168
169 public synchronized boolean isEmpty() {
170 return deadServers.isEmpty();
171 }
172
173 public synchronized void cleanAllPreviousInstances(final ServerName newServerName) {
174 Iterator<ServerName> it = deadServers.keySet().iterator();
175 while (it.hasNext()) {
176 ServerName sn = it.next();
177 if (ServerName.isSameHostnameAndPort(sn, newServerName)) {
178
179 it.remove();
180
181 boolean removed = processingServers.remove(sn);
182 if (removed) {
183 LOG.debug("Removed " + sn + " ; numProcessing=" + processingServers.size());
184 }
185 }
186 }
187 }
188
189 public synchronized String toString() {
190
191 Set<ServerName> servers = new HashSet<ServerName>();
192 servers.addAll(deadServers.keySet());
193 servers.addAll(processingServers);
194 StringBuilder sb = new StringBuilder();
195 for (ServerName sn : servers) {
196 if (sb.length() > 0) {
197 sb.append(", ");
198 }
199 sb.append(sn.toString());
200
201 if (processingServers.contains(sn)) {
202 sb.append("*");
203 }
204 }
205 sb.append(" (numProcessing=");
206 sb.append(processingServers.size());
207 sb.append(')');
208 return sb.toString();
209 }
210
211
212
213
214
215
216 public synchronized List<Pair<ServerName, Long>> copyDeadServersSince(long ts){
217 List<Pair<ServerName, Long>> res = new ArrayList<Pair<ServerName, Long>>(size());
218
219 for (Map.Entry<ServerName, Long> entry:deadServers.entrySet()){
220 if (entry.getValue() >= ts){
221 res.add(new Pair<ServerName, Long>(entry.getKey(), entry.getValue()));
222 }
223 }
224
225 Collections.sort(res, ServerNameDeathDateComparator);
226 return res;
227 }
228
229
230
231
232
233
234 public synchronized Date getTimeOfDeath(final ServerName deadServerName){
235 Long time = deadServers.get(deadServerName);
236 return time == null ? null : new Date(time);
237 }
238
239 private static Comparator<Pair<ServerName, Long>> ServerNameDeathDateComparator =
240 new Comparator<Pair<ServerName, Long>>(){
241
242 @Override
243 public int compare(Pair<ServerName, Long> o1, Pair<ServerName, Long> o2) {
244 return o1.getSecond().compareTo(o2.getSecond());
245 }
246 };
247 }