View Javadoc

1   /**
2    * Copyright 2010 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  package org.apache.hadoop.hbase.master;
21  
22  import java.util.Collection;
23  import java.util.HashSet;
24  import java.util.Iterator;
25  import java.util.LinkedList;
26  import java.util.List;
27  import java.util.Set;
28  
29  import org.apache.commons.lang.NotImplementedException;
30  import org.apache.hadoop.hbase.HServerInfo;
31  
32  /**
33   * Class to hold dead servers list and utility querying dead server list.
34   */
35  public class DeadServer implements Set<String> {
36    /**
37     * Set of known dead servers.  On znode expiration, servers are added here.
38     * This is needed in case of a network partitioning where the server's lease
39     * expires, but the server is still running. After the network is healed,
40     * and it's server logs are recovered, it will be told to call server startup
41     * because by then, its regions have probably been reassigned.
42     */
43    private final Set<String> deadServers = new HashSet<String>();
44  
45    /** Linked list of dead servers used to bound size of dead server set */
46    private final List<String> deadServerList = new LinkedList<String>();
47  
48    /** Maximum number of dead servers to keep track of */
49    private final int maxDeadServers;
50  
51    /** Number of dead servers currently being processed */
52    private int numProcessing;
53  
54    public DeadServer(int maxDeadServers) {
55      super();
56      this.maxDeadServers = maxDeadServers;
57      this.numProcessing = 0;
58    }
59  
60    /**
61     * @param serverName
62     * @return true if server is dead
63     */
64    public boolean isDeadServer(final String serverName) {
65      return isDeadServer(serverName, false);
66    }
67  
68    /**
69     * @param serverName Servername as either <code>host:port</code> or
70     * <code>host,port,startcode</code>.
71     * @param hostAndPortOnly True if <code>serverName</code> is host and
72     * port only (<code>host:port</code>) and if so, then we do a prefix compare
73     * (ignoring start codes) looking for dead server.
74     * @return true if server is dead
75     */
76    boolean isDeadServer(final String serverName, final boolean hostAndPortOnly) {
77      return HServerInfo.isServer(this, serverName, hostAndPortOnly);
78    }
79  
80    /**
81     * Checks if there are currently any dead servers being processed by the
82     * master.  Returns true if at least one region server is currently being
83     * processed as dead.
84     * @return true if any RS are being processed as dead
85     */
86    public boolean areDeadServersInProgress() {
87      return numProcessing != 0;
88    }
89  
90    public synchronized Set<String> clone() {
91      Set<String> clone = new HashSet<String>(this.deadServers.size());
92      clone.addAll(this.deadServers);
93      return clone;
94    }
95  
96    public synchronized boolean add(String e) {
97      this.numProcessing++;
98      // Check to see if we are at capacity for dead servers
99      if (deadServerList.size() == this.maxDeadServers) {
100       deadServers.remove(deadServerList.remove(0));
101     }
102     deadServerList.add(e);
103     return deadServers.add(e);
104   }
105 
106   public synchronized void finish(String e) {
107     this.numProcessing--;
108   }
109 
110   public synchronized int size() {
111     return deadServers.size();
112   }
113 
114   public synchronized boolean isEmpty() {
115     return deadServers.isEmpty();
116   }
117 
118   public synchronized boolean contains(Object o) {
119     return deadServers.contains(o);
120   }
121 
122   public Iterator<String> iterator() {
123     return this.deadServers.iterator();
124   }
125 
126   public synchronized Object[] toArray() {
127     return deadServers.toArray();
128   }
129 
130   public synchronized <T> T[] toArray(T[] a) {
131     return deadServers.toArray(a);
132   }
133 
134   public synchronized boolean remove(Object o) {
135     throw new UnsupportedOperationException();
136   }
137 
138   public synchronized boolean containsAll(Collection<?> c) {
139     return deadServers.containsAll(c);
140   }
141 
142   public synchronized boolean addAll(Collection<? extends String> c) {
143     return deadServers.addAll(c);
144   }
145 
146   public synchronized boolean retainAll(Collection<?> c) {
147     return deadServers.retainAll(c);
148   }
149 
150   public synchronized boolean removeAll(Collection<?> c) {
151     return deadServers.removeAll(c);
152   }
153 
154   public synchronized void clear() {
155     throw new NotImplementedException();
156   }
157 
158   public synchronized boolean equals(Object o) {
159     return deadServers.equals(o);
160   }
161 
162   public synchronized int hashCode() {
163     return deadServers.hashCode();
164   }
165 
166   public synchronized String toString() {
167     return this.deadServers.toString();
168   }
169 }