1 /**
2 * Copyright 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.zookeeper;
21
22 import java.util.concurrent.CountDownLatch;
23
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.apache.hadoop.classification.InterfaceAudience;
27 import org.apache.zookeeper.KeeperException;
28
29 /**
30 * A ZooKeeper watcher meant to detect deletions of ZNodes.
31 */
32 @InterfaceAudience.Private
33 public class DeletionListener extends ZooKeeperListener {
34
35 private static final Log LOG = LogFactory.getLog(DeletionListener.class);
36
37 private final String pathToWatch;
38 private final CountDownLatch deletedLatch;
39
40 private volatile Throwable exception;
41
42 /**
43 * Create a new instance of the deletion watcher.
44 * @param zkWatcher ZookeeperWatcher instance
45 * @param pathToWatch (Fully qualified) ZNode path that we are waiting to
46 * be deleted.
47 * @param deletedLatch Count down on this latch when deletion has occured.
48 */
49 public DeletionListener(ZooKeeperWatcher zkWatcher, String pathToWatch,
50 CountDownLatch deletedLatch) {
51 super(zkWatcher);
52 this.pathToWatch = pathToWatch;
53 this.deletedLatch = deletedLatch;
54 exception = null;
55 }
56
57 /**
58 * Check if an exception has occurred when re-setting the watch.
59 * @return True if we were unable to re-set a watch on a ZNode due to
60 * an exception.
61 */
62 public boolean hasException() {
63 return exception != null;
64 }
65
66 /**
67 * Get the last exception which has occurred when re-setting the watch.
68 * Use hasException() to check whether or not an exception has occurred.
69 * @return The last exception observed when re-setting the watch.
70 */
71 public Throwable getException() {
72 return exception;
73 }
74
75 @Override
76 public void nodeDataChanged(String path) {
77 if (!path.equals(pathToWatch)) {
78 return;
79 }
80 try {
81 if (!(ZKUtil.setWatchIfNodeExists(watcher, pathToWatch))) {
82 deletedLatch.countDown();
83 }
84 } catch (KeeperException ex) {
85 exception = ex;
86 deletedLatch.countDown();
87 LOG.error("Error when re-setting the watch on " + pathToWatch, ex);
88 }
89 }
90
91 @Override
92 public void nodeDeleted(String path) {
93 if (!path.equals(pathToWatch)) {
94 return;
95 }
96 if (LOG.isDebugEnabled()) {
97 LOG.debug("Processing delete on " + pathToWatch);
98 }
99 deletedLatch.countDown();
100 }
101 }