HBASE-21843 RegionGroupingProvider breaks the meta wal file name pattern which may...
[hbase.git] / hbase-server / src / main / java / org / apache / hadoop / hbase / master / DeadServer.java
blob05847923ceedf4416b7d9f9e80bf7212a026dfc7
1 /**
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 package org.apache.hadoop.hbase.master;
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.Comparator;
24 import java.util.Date;
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.Set;
31 import org.apache.hadoop.hbase.ServerName;
32 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
33 import org.apache.hadoop.hbase.util.Pair;
34 import org.apache.yetus.audience.InterfaceAudience;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
38 import org.apache.hbase.thirdparty.com.google.common.base.Preconditions;
41 /**
42 * Class to hold dead servers list and utility querying dead server list.
43 * On znode expiration, servers are added here.
45 @InterfaceAudience.Private
46 public class DeadServer {
47 private static final Logger LOG = LoggerFactory.getLogger(DeadServer.class);
49 /**
50 * Set of known dead servers. On znode expiration, servers are added here.
51 * This is needed in case of a network partitioning where the server's lease
52 * expires, but the server is still running. After the network is healed,
53 * and it's server logs are recovered, it will be told to call server startup
54 * because by then, its regions have probably been reassigned.
56 private final Map<ServerName, Long> deadServers = new HashMap<>();
58 /**
59 * Set of dead servers currently being processed
61 private final Set<ServerName> processingServers = new HashSet<ServerName>();
63 /**
64 * A dead server that comes back alive has a different start code. The new start code should be
65 * greater than the old one, but we don't take this into account in this method.
67 * @param newServerName Servername as either <code>host:port</code> or
68 * <code>host,port,startcode</code>.
69 * @return true if this server was dead before and coming back alive again
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.isSameAddress(sn, newServerName)) {
76 // remove from deadServers
77 it.remove();
78 // remove from processingServers
79 boolean removed = processingServers.remove(sn);
80 if (removed) {
81 LOG.debug("Removed " + sn + " ; numProcessing=" + processingServers.size());
83 return true;
87 return false;
90 /**
91 * @param serverName server name.
92 * @return true if this server is on the dead servers list false otherwise
94 public synchronized boolean isDeadServer(final ServerName serverName) {
95 return deadServers.containsKey(serverName);
98 /**
99 * @param serverName server name.
100 * @return true if this server is on the processing servers list false otherwise
102 public synchronized boolean isProcessingServer(final ServerName serverName) {
103 return processingServers.contains(serverName);
107 * Checks if there are currently any dead servers being processed by the
108 * master. Returns true if at least one region server is currently being
109 * processed as dead.
111 * @return true if any RS are being processed as dead
113 public synchronized boolean areDeadServersInProgress() {
114 return !processingServers.isEmpty();
117 public synchronized Set<ServerName> copyServerNames() {
118 Set<ServerName> clone = new HashSet<>(deadServers.size());
119 clone.addAll(deadServers.keySet());
120 return clone;
124 * Adds the server to the dead server list if it's not there already.
125 * @param sn the server name
127 public synchronized void add(ServerName sn) {
128 if (!deadServers.containsKey(sn)){
129 deadServers.put(sn, EnvironmentEdgeManager.currentTime());
131 boolean added = processingServers.add(sn);
132 if (LOG.isDebugEnabled() && added) {
133 LOG.debug("Added " + sn + "; numProcessing=" + processingServers.size());
138 * Notify that we started processing this dead server.
139 * @param sn ServerName for the dead server.
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());
147 LOG.debug("Started processing " + sn + "; numProcessing=" + processingServers.size());
152 * Complete processing for this dead server.
153 * @param sn ServerName for the dead server.
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());
165 public synchronized int size() {
166 return deadServers.size();
169 public synchronized boolean isEmpty() {
170 return deadServers.isEmpty();
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.isSameAddress(sn, newServerName)) {
178 // remove from deadServers
179 it.remove();
180 // remove from processingServers
181 boolean removed = processingServers.remove(sn);
182 if (removed) {
183 LOG.debug("Removed " + sn + " ; numProcessing=" + processingServers.size());
189 @Override
190 public synchronized String toString() {
191 // Display unified set of servers from both maps
192 Set<ServerName> servers = new HashSet<ServerName>();
193 servers.addAll(deadServers.keySet());
194 servers.addAll(processingServers);
195 StringBuilder sb = new StringBuilder();
196 for (ServerName sn : servers) {
197 if (sb.length() > 0) {
198 sb.append(", ");
200 sb.append(sn.toString());
201 // Star entries that are being processed
202 if (processingServers.contains(sn)) {
203 sb.append("*");
206 return sb.toString();
210 * Extract all the servers dead since a given time, and sort them.
211 * @param ts the time, 0 for all
212 * @return a sorted array list, by death time, lowest values first.
214 public synchronized List<Pair<ServerName, Long>> copyDeadServersSince(long ts){
215 List<Pair<ServerName, Long>> res = new ArrayList<>(size());
217 for (Map.Entry<ServerName, Long> entry:deadServers.entrySet()){
218 if (entry.getValue() >= ts){
219 res.add(new Pair<>(entry.getKey(), entry.getValue()));
223 Collections.sort(res, ServerNameDeathDateComparator);
224 return res;
228 * Get the time when a server died
229 * @param deadServerName the dead server name
230 * @return the date when the server died
232 public synchronized Date getTimeOfDeath(final ServerName deadServerName){
233 Long time = deadServers.get(deadServerName);
234 return time == null ? null : new Date(time);
237 private static Comparator<Pair<ServerName, Long>> ServerNameDeathDateComparator =
238 new Comparator<Pair<ServerName, Long>>(){
240 @Override
241 public int compare(Pair<ServerName, Long> o1, Pair<ServerName, Long> o2) {
242 return o1.getSecond().compareTo(o2.getSecond());
247 * remove the specified dead server
248 * @param deadServerName the dead server name
249 * @return true if this server was removed
252 public synchronized boolean removeDeadServer(final ServerName deadServerName) {
253 Preconditions.checkState(!processingServers.contains(deadServerName),
254 "Asked to remove server still in processingServers set " + deadServerName +
255 " (numProcessing=" + processingServers.size() + ")");
256 if (deadServers.remove(deadServerName) == null) {
257 return false;
259 return true;