1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.zookeeper;
20
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertFalse;
23 import static org.junit.Assert.assertNotNull;
24 import static org.junit.Assert.assertNull;
25 import static org.junit.Assert.assertTrue;
26
27 import java.io.IOException;
28 import java.lang.reflect.Method;
29 import java.util.Random;
30 import java.util.concurrent.Semaphore;
31
32 import junit.framework.Assert;
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35 import org.apache.hadoop.hbase.*;
36 import org.apache.hadoop.hbase.client.HConnectionManager;
37 import org.apache.hadoop.hbase.master.TestActiveMasterManager.NodeDeletionListener;
38 import org.apache.hadoop.hbase.util.Bytes;
39 import org.apache.hadoop.hbase.util.Threads;
40 import org.apache.zookeeper.CreateMode;
41 import org.apache.zookeeper.KeeperException;
42 import org.apache.zookeeper.WatchedEvent;
43 import org.apache.zookeeper.Watcher;
44 import org.apache.zookeeper.ZooDefs.Ids;
45 import org.apache.zookeeper.ZooKeeper;
46 import org.junit.AfterClass;
47 import org.junit.BeforeClass;
48 import org.junit.Test;
49 import org.junit.experimental.categories.Category;
50
51 @Category(MediumTests.class)
52 public class TestZooKeeperNodeTracker {
53 private static final Log LOG = LogFactory.getLog(TestZooKeeperNodeTracker.class);
54 private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
55
56 private final static Random rand = new Random();
57
58 @BeforeClass
59 public static void setUpBeforeClass() throws Exception {
60 TEST_UTIL.startMiniZKCluster();
61 }
62
63 @AfterClass
64 public static void tearDownAfterClass() throws Exception {
65 TEST_UTIL.shutdownMiniZKCluster();
66 }
67
68
69
70
71
72
73 @Test public void testInterruptible() throws IOException, InterruptedException {
74 Abortable abortable = new StubAbortable();
75 ZooKeeperWatcher zk = new ZooKeeperWatcher(TEST_UTIL.getConfiguration(),
76 "testInterruptible", abortable);
77 final TestTracker tracker = new TestTracker(zk, "/xyz", abortable);
78 tracker.start();
79 Thread t = new Thread() {
80 @Override
81 public void run() {
82 try {
83 tracker.blockUntilAvailable();
84 } catch (InterruptedException e) {
85 throw new RuntimeException("Interrupted", e);
86 }
87 }
88 };
89 t.start();
90 while (!t.isAlive()) Threads.sleep(1);
91 tracker.stop();
92 t.join();
93
94 }
95
96 @Test
97 public void testNodeTracker() throws Exception {
98 Abortable abortable = new StubAbortable();
99 ZooKeeperWatcher zk = new ZooKeeperWatcher(TEST_UTIL.getConfiguration(),
100 "testNodeTracker", abortable);
101 ZKUtil.createAndFailSilent(zk, zk.baseZNode);
102
103 final String node =
104 ZKUtil.joinZNode(zk.baseZNode, new Long(rand.nextLong()).toString());
105
106 final byte [] dataOne = Bytes.toBytes("dataOne");
107 final byte [] dataTwo = Bytes.toBytes("dataTwo");
108
109
110 TestTracker localTracker = new TestTracker(zk, node, abortable);
111 localTracker.start();
112 zk.registerListener(localTracker);
113
114
115 assertNull(localTracker.getData(false));
116
117
118 WaitToGetDataThread thread = new WaitToGetDataThread(zk, node);
119 thread.start();
120
121
122 assertFalse(thread.hasData);
123
124
125 TestTracker secondTracker = new TestTracker(zk, node, null);
126 secondTracker.start();
127 zk.registerListener(secondTracker);
128
129
130 TestingZKListener zkListener = new TestingZKListener(zk, node);
131 zk.registerListener(zkListener);
132 assertEquals(0, zkListener.createdLock.availablePermits());
133
134
135
136 final ZooKeeper zkconn = new ZooKeeper(
137 ZKConfig.getZKQuorumServersString(TEST_UTIL.getConfiguration()), 60000,
138 new StubWatcher());
139
140
141 zkconn.create(node, dataOne, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
142
143
144 zkListener.waitForCreation();
145 thread.join();
146
147
148 assertNotNull(localTracker.getData(false));
149 assertNotNull(localTracker.blockUntilAvailable());
150 assertTrue(Bytes.equals(localTracker.getData(false), dataOne));
151 assertTrue(thread.hasData);
152 assertTrue(Bytes.equals(thread.tracker.getData(false), dataOne));
153 LOG.info("Successfully got data one");
154
155
156 assertNotNull(secondTracker.getData(false));
157 assertNotNull(secondTracker.blockUntilAvailable());
158 assertTrue(Bytes.equals(secondTracker.getData(false), dataOne));
159 LOG.info("Successfully got data one with the second tracker");
160
161
162 zkconn.delete(node, -1);
163 zkListener.waitForDeletion();
164
165
166 TestTracker threadTracker = thread.tracker;
167 thread = new WaitToGetDataThread(zk, node, threadTracker);
168 thread.start();
169
170
171 assertFalse(thread.hasData);
172 assertNull(secondTracker.getData(false));
173 assertNull(localTracker.getData(false));
174 LOG.info("Successfully made unavailable");
175
176
177 zkconn.create(node, dataTwo, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
178
179
180 zkListener.waitForCreation();
181 thread.join();
182
183
184 assertNotNull(localTracker.getData(false));
185 assertNotNull(localTracker.blockUntilAvailable());
186 assertTrue(Bytes.equals(localTracker.getData(false), dataTwo));
187 assertNotNull(secondTracker.getData(false));
188 assertNotNull(secondTracker.blockUntilAvailable());
189 assertTrue(Bytes.equals(secondTracker.getData(false), dataTwo));
190 assertTrue(thread.hasData);
191 assertTrue(Bytes.equals(thread.tracker.getData(false), dataTwo));
192 LOG.info("Successfully got data two on all trackers and threads");
193
194
195 zkconn.setData(node, dataOne, -1);
196
197
198 zkListener.waitForDataChange();
199
200
201 assertNotNull(localTracker.getData(false));
202 assertNotNull(localTracker.blockUntilAvailable());
203 assertTrue(Bytes.equals(localTracker.getData(false), dataOne));
204 assertNotNull(secondTracker.getData(false));
205 assertNotNull(secondTracker.blockUntilAvailable());
206 assertTrue(Bytes.equals(secondTracker.getData(false), dataOne));
207 assertTrue(thread.hasData);
208 assertTrue(Bytes.equals(thread.tracker.getData(false), dataOne));
209 LOG.info("Successfully got data one following a data change on all trackers and threads");
210 }
211
212 public static class WaitToGetDataThread extends Thread {
213
214 TestTracker tracker;
215 boolean hasData;
216
217 public WaitToGetDataThread(ZooKeeperWatcher zk, String node) {
218 tracker = new TestTracker(zk, node, null);
219 tracker.start();
220 zk.registerListener(tracker);
221 hasData = false;
222 }
223
224 public WaitToGetDataThread(ZooKeeperWatcher zk, String node,
225 TestTracker tracker) {
226 this.tracker = tracker;
227 hasData = false;
228 }
229
230 @Override
231 public void run() {
232 LOG.info("Waiting for data to be available in WaitToGetDataThread");
233 try {
234 tracker.blockUntilAvailable();
235 } catch (InterruptedException e) {
236 e.printStackTrace();
237 }
238 LOG.info("Data now available in tracker from WaitToGetDataThread");
239 hasData = true;
240 }
241 }
242
243 public static class TestTracker extends ZooKeeperNodeTracker {
244 public TestTracker(ZooKeeperWatcher watcher, String node,
245 Abortable abortable) {
246 super(watcher, node, abortable);
247 }
248 }
249
250 public static class TestingZKListener extends ZooKeeperListener {
251 private static final Log LOG = LogFactory.getLog(NodeDeletionListener.class);
252
253 private Semaphore deletedLock;
254 private Semaphore createdLock;
255 private Semaphore changedLock;
256 private String node;
257
258 public TestingZKListener(ZooKeeperWatcher watcher, String node) {
259 super(watcher);
260 deletedLock = new Semaphore(0);
261 createdLock = new Semaphore(0);
262 changedLock = new Semaphore(0);
263 this.node = node;
264 }
265
266 @Override
267 public void nodeDeleted(String path) {
268 if(path.equals(node)) {
269 LOG.debug("nodeDeleted(" + path + ")");
270 deletedLock.release();
271 }
272 }
273
274 @Override
275 public void nodeCreated(String path) {
276 if(path.equals(node)) {
277 LOG.debug("nodeCreated(" + path + ")");
278 createdLock.release();
279 }
280 }
281
282 @Override
283 public void nodeDataChanged(String path) {
284 if(path.equals(node)) {
285 LOG.debug("nodeDataChanged(" + path + ")");
286 changedLock.release();
287 }
288 }
289
290 public void waitForDeletion() throws InterruptedException {
291 deletedLock.acquire();
292 }
293
294 public void waitForCreation() throws InterruptedException {
295 createdLock.acquire();
296 }
297
298 public void waitForDataChange() throws InterruptedException {
299 changedLock.acquire();
300 }
301 }
302
303 public static class StubAbortable implements Abortable {
304 @Override
305 public void abort(final String msg, final Throwable t) {}
306
307 @Override
308 public boolean isAborted() {
309 return false;
310 }
311
312 }
313
314 public static class StubWatcher implements Watcher {
315 @Override
316 public void process(WatchedEvent event) {}
317 }
318
319 @Test
320 public void testCleanZNode() throws Exception {
321 ZooKeeperWatcher zkw = new ZooKeeperWatcher(TEST_UTIL.getConfiguration(),
322 "testNodeTracker", new TestZooKeeperNodeTracker.StubAbortable());
323
324 final ServerName sn = new ServerName("127.0.0.1:52",45L);
325
326 ZKUtil.createAndFailSilent(zkw,
327 TEST_UTIL.getConfiguration().get(HConstants.ZOOKEEPER_ZNODE_PARENT,
328 HConstants.DEFAULT_ZOOKEEPER_ZNODE_PARENT));
329
330 final String nodeName = zkw.getMasterAddressZNode();
331
332
333 ZKUtil.createAndFailSilent(zkw, nodeName);
334 MasterAddressTracker.deleteIfEquals(zkw, sn.toString());
335 Assert.assertFalse(ZKUtil.getData(zkw, nodeName) == null);
336
337
338 ZKUtil.setData(zkw, nodeName, MasterAddressTracker.toByteArray(sn));
339 MasterAddressTracker.deleteIfEquals(zkw, new ServerName("127.0.0.2:52",45L).toString());
340 Assert.assertFalse(ZKUtil.getData(zkw, nodeName) == null);
341
342
343 ZKUtil.setData(zkw, nodeName,MasterAddressTracker.toByteArray(sn));
344 MasterAddressTracker.deleteIfEquals(zkw, sn.toString());
345 Assert.assertTrue( ZKUtil.getData(zkw, nodeName)== null );
346
347
348 MasterAddressTracker.deleteIfEquals(zkw, sn.toString());
349 }
350
351 }
352