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.zookeeper;
21
22 import java.io.IOException;
23 import java.util.ArrayList;
24 import java.util.HashSet;
25 import java.util.List;
26 import java.util.Set;
27 import java.util.concurrent.CopyOnWriteArrayList;
28 import java.util.concurrent.CountDownLatch;
29
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.apache.hadoop.conf.Configuration;
33 import org.apache.hadoop.hbase.Abortable;
34 import org.apache.hadoop.hbase.HConstants;
35 import org.apache.hadoop.hbase.ZooKeeperConnectionException;
36 import org.apache.hadoop.hbase.util.Threads;
37 import org.apache.zookeeper.KeeperException;
38 import org.apache.zookeeper.WatchedEvent;
39 import org.apache.zookeeper.Watcher;
40 import org.apache.zookeeper.ZooDefs;
41 import org.apache.zookeeper.data.ACL;
42
43
44
45
46
47
48
49
50
51
52
53
54 public class ZooKeeperWatcher implements Watcher, Abortable {
55 private static final Log LOG = LogFactory.getLog(ZooKeeperWatcher.class);
56
57
58
59 private String identifier;
60
61
62 private String quorum;
63
64
65 private RecoverableZooKeeper recoverableZooKeeper;
66
67
68 private Abortable abortable;
69
70
71 private final List<ZooKeeperListener> listeners =
72 new CopyOnWriteArrayList<ZooKeeperListener>();
73
74
75 private Set<String> unassignedNodes = new HashSet<String>();
76
77
78
79
80 public String baseZNode;
81
82 public String rootServerZNode;
83
84 public String rsZNode;
85
86 public String drainingZNode;
87
88 public String masterAddressZNode;
89
90 public String backupMasterAddressesZNode;
91
92 public String clusterStateZNode;
93
94 public String assignmentZNode;
95
96 public String masterTableZNode;
97
98 public String clientTableZNode;
99
100
101 public String masterTableZNode92;
102
103 public String clusterIdZNode;
104
105 public String splitLogZNode;
106
107
108 public static final ArrayList<ACL> CREATOR_ALL_AND_WORLD_READABLE =
109 new ArrayList<ACL>() { {
110 add(new ACL(ZooDefs.Perms.READ,ZooDefs.Ids.ANYONE_ID_UNSAFE));
111 add(new ACL(ZooDefs.Perms.ALL,ZooDefs.Ids.AUTH_IDS));
112 }};
113
114 private final Configuration conf;
115
116 private final Exception constructorCaller;
117
118
119
120
121
122
123
124
125 public ZooKeeperWatcher(Configuration conf, String descriptor,
126 Abortable abortable) throws ZooKeeperConnectionException, IOException {
127 this(conf, descriptor, abortable, false);
128 }
129
130
131
132
133
134
135
136 public ZooKeeperWatcher(Configuration conf, String descriptor,
137 Abortable abortable, boolean canCreateBaseZNode)
138 throws IOException, ZooKeeperConnectionException {
139 this.conf = conf;
140
141
142 try {
143 throw new Exception("ZKW CONSTRUCTOR STACK TRACE FOR DEBUGGING");
144 } catch (Exception e) {
145 this.constructorCaller = e;
146 }
147 this.quorum = ZKConfig.getZKQuorumServersString(conf);
148
149
150 this.identifier = descriptor;
151 this.abortable = abortable;
152 setNodeNames(conf);
153 this.recoverableZooKeeper = ZKUtil.connect(conf, quorum, this, descriptor);
154 if (canCreateBaseZNode) {
155 createBaseZNodes();
156 }
157 }
158
159 private void createBaseZNodes() throws ZooKeeperConnectionException {
160 try {
161
162 ZKUtil.createAndFailSilent(this, baseZNode);
163 ZKUtil.createAndFailSilent(this, assignmentZNode);
164 ZKUtil.createAndFailSilent(this, rsZNode);
165 ZKUtil.createAndFailSilent(this, drainingZNode);
166 ZKUtil.createAndFailSilent(this, masterTableZNode);
167 ZKUtil.createAndFailSilent(this, masterTableZNode92);
168 ZKUtil.createAndFailSilent(this, splitLogZNode);
169 ZKUtil.createAndFailSilent(this, backupMasterAddressesZNode);
170 } catch (KeeperException e) {
171 throw new ZooKeeperConnectionException(
172 prefix("Unexpected KeeperException creating base node"), e);
173 }
174 }
175
176 private boolean isFinishedRetryingRecoverable(final long finished) {
177 return System.currentTimeMillis() < finished;
178 }
179
180 @Override
181 public String toString() {
182 return this.identifier;
183 }
184
185
186
187
188
189
190
191 public String prefix(final String str) {
192 return this.toString() + " " + str;
193 }
194
195
196
197
198 private void setNodeNames(Configuration conf) {
199 baseZNode = conf.get(HConstants.ZOOKEEPER_ZNODE_PARENT,
200 HConstants.DEFAULT_ZOOKEEPER_ZNODE_PARENT);
201 rootServerZNode = ZKUtil.joinZNode(baseZNode,
202 conf.get("zookeeper.znode.rootserver", "root-region-server"));
203 rsZNode = ZKUtil.joinZNode(baseZNode,
204 conf.get("zookeeper.znode.rs", "rs"));
205 drainingZNode = ZKUtil.joinZNode(baseZNode,
206 conf.get("zookeeper.znode.draining.rs", "draining"));
207 masterAddressZNode = ZKUtil.joinZNode(baseZNode,
208 conf.get("zookeeper.znode.master", "master"));
209 backupMasterAddressesZNode = ZKUtil.joinZNode(baseZNode,
210 conf.get("zookeeper.znode.backup.masters", "backup-masters"));
211 clusterStateZNode = ZKUtil.joinZNode(baseZNode,
212 conf.get("zookeeper.znode.state", "shutdown"));
213 assignmentZNode = ZKUtil.joinZNode(baseZNode,
214 conf.get("zookeeper.znode.unassigned", "unassigned"));
215 String tableZNodeDefault = "table";
216 masterTableZNode = ZKUtil.joinZNode(baseZNode,
217 conf.get("zookeeper.znode.masterTableEnableDisable", tableZNodeDefault));
218 clientTableZNode = ZKUtil.joinZNode(baseZNode,
219 conf.get("zookeeper.znode.clientTableEnableDisable", tableZNodeDefault));
220 masterTableZNode92 = ZKUtil.joinZNode(baseZNode,
221 conf.get("zookeeper.znode.masterTableEnableDisable92", "table92"));
222 clusterIdZNode = ZKUtil.joinZNode(baseZNode,
223 conf.get("zookeeper.znode.clusterId", "hbaseid"));
224 splitLogZNode = ZKUtil.joinZNode(baseZNode,
225 conf.get("zookeeper.znode.splitlog", HConstants.SPLIT_LOGDIR_NAME));
226 }
227
228
229
230
231
232 public void registerListener(ZooKeeperListener listener) {
233 listeners.add(listener);
234 }
235
236
237
238
239
240
241 public void registerListenerFirst(ZooKeeperListener listener) {
242 listeners.add(0, listener);
243 }
244
245
246
247
248 public void unregisterAllListeners() {
249 listeners.clear();
250 }
251
252
253
254
255 public List<ZooKeeperListener> getListeners() {
256 return new ArrayList<ZooKeeperListener>(listeners);
257 }
258
259
260
261
262 public int getNumberOfListeners() {
263 return listeners.size();
264 }
265
266
267
268
269
270 public RecoverableZooKeeper getRecoverableZooKeeper() {
271 return recoverableZooKeeper;
272 }
273
274 public void reconnectAfterExpiration() throws IOException, InterruptedException {
275 recoverableZooKeeper.reconnectAfterExpiration();
276 }
277
278
279
280
281
282 public String getQuorum() {
283 return quorum;
284 }
285
286
287
288
289
290
291
292 @Override
293 public void process(WatchedEvent event) {
294 LOG.debug(prefix("Received ZooKeeper Event, " +
295 "type=" + event.getType() + ", " +
296 "state=" + event.getState() + ", " +
297 "path=" + event.getPath()));
298
299 switch(event.getType()) {
300
301
302 case None: {
303 connectionEvent(event);
304 break;
305 }
306
307
308
309 case NodeCreated: {
310 for(ZooKeeperListener listener : listeners) {
311 listener.nodeCreated(event.getPath());
312 }
313 break;
314 }
315
316 case NodeDeleted: {
317 for(ZooKeeperListener listener : listeners) {
318 listener.nodeDeleted(event.getPath());
319 }
320 break;
321 }
322
323 case NodeDataChanged: {
324 for(ZooKeeperListener listener : listeners) {
325 listener.nodeDataChanged(event.getPath());
326 }
327 break;
328 }
329
330 case NodeChildrenChanged: {
331 for(ZooKeeperListener listener : listeners) {
332 listener.nodeChildrenChanged(event.getPath());
333 }
334 break;
335 }
336 }
337 }
338
339
340
341
342
343
344
345
346
347
348
349
350
351 private void connectionEvent(WatchedEvent event) {
352 switch(event.getState()) {
353 case SyncConnected:
354
355
356 long finished = System.currentTimeMillis() +
357 this.conf.getLong("hbase.zookeeper.watcher.sync.connected.wait", 2000);
358 while (System.currentTimeMillis() < finished) {
359 Threads.sleep(1);
360 if (this.recoverableZooKeeper != null) break;
361 }
362 if (this.recoverableZooKeeper == null) {
363 LOG.error("ZK is null on connection event -- see stack trace " +
364 "for the stack trace when constructor was called on this zkw",
365 this.constructorCaller);
366 throw new NullPointerException("ZK is null");
367 }
368 this.identifier = this.identifier + "-0x" +
369 Long.toHexString(this.recoverableZooKeeper.getSessionId());
370
371 LOG.debug(this.identifier + " connected");
372 break;
373
374
375 case Disconnected:
376 LOG.debug(prefix("Received Disconnected from ZooKeeper, ignoring"));
377 break;
378
379 case Expired:
380 String msg = prefix(this.identifier + " received expired from " +
381 "ZooKeeper, aborting");
382
383
384 if (this.abortable != null) this.abortable.abort(msg,
385 new KeeperException.SessionExpiredException());
386 break;
387 }
388 }
389
390
391
392
393
394
395
396
397
398
399
400
401
402 public void sync(String path) {
403 this.recoverableZooKeeper.sync(path, null, null);
404 }
405
406
407
408
409
410
411
412
413
414
415
416 public void keeperException(KeeperException ke)
417 throws KeeperException {
418 LOG.error(prefix("Received unexpected KeeperException, re-throwing exception"), ke);
419 throw ke;
420 }
421
422
423
424
425
426
427
428
429
430
431
432
433 public void interruptedException(InterruptedException ie) {
434 LOG.debug(prefix("Received InterruptedException, doing nothing here"), ie);
435
436 Thread.currentThread().interrupt();
437
438 }
439
440
441
442
443
444 public void close() {
445 try {
446 if (recoverableZooKeeper != null) {
447 recoverableZooKeeper.close();
448
449 }
450 } catch (InterruptedException e) {
451 }
452 }
453
454 public Configuration getConfiguration() {
455 return conf;
456 }
457
458 @Override
459 public void abort(String why, Throwable e) {
460 this.abortable.abort(why, e);
461 }
462
463 @Override
464 public boolean isAborted() {
465 return this.abortable.isAborted();
466 }
467 }