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.util.concurrent.atomic.AtomicBoolean;
23
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.apache.hadoop.hbase.classification.InterfaceAudience;
27 import org.apache.hadoop.hbase.Server;
28 import org.apache.hadoop.hbase.ServerName;
29 import org.apache.hadoop.hbase.ZNodeClearer;
30 import org.apache.hadoop.hbase.exceptions.DeserializationException;
31 import org.apache.hadoop.hbase.monitoring.MonitoredTask;
32 import org.apache.hadoop.hbase.zookeeper.MasterAddressTracker;
33 import org.apache.hadoop.hbase.zookeeper.ZKUtil;
34 import org.apache.hadoop.hbase.zookeeper.ZooKeeperListener;
35 import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
36 import org.apache.zookeeper.KeeperException;
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 @InterfaceAudience.Private
52 @edu.umd.cs.findbugs.annotations.SuppressWarnings(value="JLM_JSR166_UTILCONCURRENT_MONITORENTER",
53 justification="Use of an atomic type both as monitor and condition variable is intended")
54 public class ActiveMasterManager extends ZooKeeperListener {
55 private static final Log LOG = LogFactory.getLog(ActiveMasterManager.class);
56
57 final AtomicBoolean clusterHasActiveMaster = new AtomicBoolean(false);
58 final AtomicBoolean clusterShutDown = new AtomicBoolean(false);
59
60 private final ServerName sn;
61 private int infoPort;
62 private final Server master;
63
64
65
66
67
68
69 ActiveMasterManager(ZooKeeperWatcher watcher, ServerName sn, Server master) {
70 super(watcher);
71 watcher.registerListener(this);
72 this.sn = sn;
73 this.master = master;
74 }
75
76
77 public void setInfoPort(int infoPort) {
78 this.infoPort = infoPort;
79 }
80
81 @Override
82 public void nodeCreated(String path) {
83 handle(path);
84 }
85
86 @Override
87 public void nodeDeleted(String path) {
88
89
90
91
92
93
94
95
96 if(path.equals(watcher.clusterStateZNode) && !master.isStopped()) {
97 clusterShutDown.set(true);
98 }
99
100 handle(path);
101 }
102
103 void handle(final String path) {
104 if (path.equals(watcher.getMasterAddressZNode()) && !master.isStopped()) {
105 handleMasterNodeChange();
106 }
107 }
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122 private void handleMasterNodeChange() {
123
124 try {
125 synchronized(clusterHasActiveMaster) {
126 if (ZKUtil.watchAndCheckExists(watcher, watcher.getMasterAddressZNode())) {
127
128 LOG.debug("A master is now available");
129 clusterHasActiveMaster.set(true);
130 } else {
131
132 LOG.debug("No master available. Notifying waiting threads");
133 clusterHasActiveMaster.set(false);
134
135 clusterHasActiveMaster.notifyAll();
136 }
137 }
138 } catch (KeeperException ke) {
139 master.abort("Received an unexpected KeeperException, aborting", ke);
140 }
141 }
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157 boolean blockUntilBecomingActiveMaster(
158 int checkInterval, MonitoredTask startupStatus) {
159 String backupZNode = ZKUtil.joinZNode(
160 this.watcher.backupMasterAddressesZNode, this.sn.toString());
161 while (!(master.isAborted() || master.isStopped())) {
162 startupStatus.setStatus("Trying to register in ZK as active master");
163
164
165 try {
166 if (MasterAddressTracker.setMasterAddress(this.watcher,
167 this.watcher.getMasterAddressZNode(), this.sn, infoPort)) {
168
169
170
171 if (ZKUtil.checkExists(this.watcher, backupZNode) != -1) {
172 LOG.info("Deleting ZNode for " + backupZNode + " from backup master directory");
173 ZKUtil.deleteNodeFailSilent(this.watcher, backupZNode);
174 }
175
176 ZNodeClearer.writeMyEphemeralNodeOnDisk(this.sn.toString());
177
178
179 startupStatus.setStatus("Successfully registered as active master.");
180 this.clusterHasActiveMaster.set(true);
181 LOG.info("Registered Active Master=" + this.sn);
182 return true;
183 }
184
185
186
187 this.clusterHasActiveMaster.set(true);
188
189 String msg;
190 byte[] bytes =
191 ZKUtil.getDataAndWatch(this.watcher, this.watcher.getMasterAddressZNode());
192 if (bytes == null) {
193 msg = ("A master was detected, but went down before its address " +
194 "could be read. Attempting to become the next active master");
195 } else {
196 ServerName currentMaster;
197 try {
198 currentMaster = ServerName.parseFrom(bytes);
199 } catch (DeserializationException e) {
200 LOG.warn("Failed parse", e);
201
202 continue;
203 }
204 if (ServerName.isSameHostnameAndPort(currentMaster, this.sn)) {
205 msg = ("Current master has this master's address, " +
206 currentMaster + "; master was restarted? Deleting node.");
207
208 ZKUtil.deleteNode(this.watcher, this.watcher.getMasterAddressZNode());
209
210
211
212 ZNodeClearer.deleteMyEphemeralNodeOnDisk();
213 } else {
214 msg = "Another master is the active master, " + currentMaster +
215 "; waiting to become the next active master";
216 }
217 }
218 LOG.info(msg);
219 startupStatus.setStatus(msg);
220 } catch (KeeperException ke) {
221 master.abort("Received an unexpected KeeperException, aborting", ke);
222 return false;
223 }
224 synchronized (this.clusterHasActiveMaster) {
225 while (clusterHasActiveMaster.get() && !master.isStopped()) {
226 try {
227 clusterHasActiveMaster.wait(checkInterval);
228 } catch (InterruptedException e) {
229
230
231 LOG.debug("Interrupted waiting for master to die", e);
232 }
233 }
234 if (clusterShutDown.get()) {
235 this.master.stop(
236 "Cluster went down before this master became active");
237 }
238 }
239 }
240 return false;
241 }
242
243
244
245
246 boolean hasActiveMaster() {
247 try {
248 if (ZKUtil.checkExists(watcher, watcher.getMasterAddressZNode()) >= 0) {
249 return true;
250 }
251 }
252 catch (KeeperException ke) {
253 LOG.info("Received an unexpected KeeperException when checking " +
254 "isActiveMaster : "+ ke);
255 }
256 return false;
257 }
258
259 public void stop() {
260 try {
261 synchronized (clusterHasActiveMaster) {
262
263
264 clusterHasActiveMaster.notifyAll();
265 }
266
267 ServerName activeMaster = null;
268 try {
269 activeMaster = MasterAddressTracker.getMasterAddress(this.watcher);
270 } catch (IOException e) {
271 LOG.warn("Failed get of master address: " + e.toString());
272 }
273 if (activeMaster != null && activeMaster.equals(this.sn)) {
274 ZKUtil.deleteNode(watcher, watcher.getMasterAddressZNode());
275
276
277 ZNodeClearer.deleteMyEphemeralNodeOnDisk();
278 }
279 } catch (KeeperException e) {
280 LOG.error(this.watcher.prefix("Error deleting our own master address node"), e);
281 }
282 }
283 }