1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.hadoop.hbase.zookeeper;
22
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertFalse;
25 import static org.junit.Assert.assertTrue;
26
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.Collections;
30 import java.util.LinkedList;
31 import java.util.List;
32
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35 import org.apache.hadoop.conf.Configuration;
36 import org.apache.hadoop.hbase.Abortable;
37 import org.apache.hadoop.hbase.HBaseTestingUtility;
38 import org.apache.hadoop.hbase.testclassification.MediumTests;
39 import org.apache.hadoop.hbase.util.Bytes;
40 import org.apache.hadoop.hbase.zookeeper.ZKUtil.ZKUtilOp;
41 import org.apache.zookeeper.CreateMode;
42 import org.apache.zookeeper.KeeperException;
43 import org.apache.zookeeper.Op;
44 import org.apache.zookeeper.ZooDefs.Ids;
45 import org.junit.AfterClass;
46 import org.junit.BeforeClass;
47 import org.junit.Test;
48 import org.junit.experimental.categories.Category;
49
50
51
52
53 @Category(MediumTests.class)
54 public class TestZKMulti {
55 private static final Log LOG = LogFactory.getLog(TestZKMulti.class);
56 private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
57 private static ZooKeeperWatcher zkw = null;
58
59 private static class ZKMultiAbortable implements Abortable {
60 @Override
61 public void abort(String why, Throwable e) {
62 LOG.info(why, e);
63 }
64
65 @Override
66 public boolean isAborted() {
67 return false;
68 }
69 }
70
71 @BeforeClass
72 public static void setUpBeforeClass() throws Exception {
73 TEST_UTIL.startMiniZKCluster();
74 Configuration conf = TEST_UTIL.getConfiguration();
75 conf.setBoolean("hbase.zookeeper.useMulti", true);
76 Abortable abortable = new Abortable() {
77 @Override
78 public void abort(String why, Throwable e) {
79 LOG.info(why, e);
80 }
81
82 @Override
83 public boolean isAborted() {
84 return false;
85 }
86 };
87 zkw = new ZooKeeperWatcher(conf,
88 "TestZKMulti", abortable, true);
89 }
90
91 @AfterClass
92 public static void tearDownAfterClass() throws Exception {
93 TEST_UTIL.shutdownMiniZKCluster();
94 }
95
96 @Test (timeout=60000)
97 public void testSimpleMulti() throws Exception {
98
99 ZKUtil.multiOrSequential(zkw, null, false);
100
101
102 ZKUtil.multiOrSequential(zkw, new LinkedList<ZKUtilOp>(), false);
103
104
105 String path = ZKUtil.joinZNode(zkw.baseZNode, "testSimpleMulti");
106 LinkedList<ZKUtilOp> singleCreate = new LinkedList<ZKUtilOp>();
107 singleCreate.add(ZKUtilOp.createAndFailSilent(path, new byte[0]));
108 ZKUtil.multiOrSequential(zkw, singleCreate, false);
109 assertTrue(ZKUtil.checkExists(zkw, path) != -1);
110
111
112 LinkedList<ZKUtilOp> singleSetData = new LinkedList<ZKUtilOp>();
113 byte [] data = Bytes.toBytes("foobar");
114 singleSetData.add(ZKUtilOp.setData(path, data));
115 ZKUtil.multiOrSequential(zkw, singleSetData, false);
116 assertTrue(Bytes.equals(ZKUtil.getData(zkw, path), data));
117
118
119 LinkedList<ZKUtilOp> singleDelete = new LinkedList<ZKUtilOp>();
120 singleDelete.add(ZKUtilOp.deleteNodeFailSilent(path));
121 ZKUtil.multiOrSequential(zkw, singleDelete, false);
122 assertTrue(ZKUtil.checkExists(zkw, path) == -1);
123 }
124
125 @Test (timeout=60000)
126 public void testComplexMulti() throws Exception {
127 String path1 = ZKUtil.joinZNode(zkw.baseZNode, "testComplexMulti1");
128 String path2 = ZKUtil.joinZNode(zkw.baseZNode, "testComplexMulti2");
129 String path3 = ZKUtil.joinZNode(zkw.baseZNode, "testComplexMulti3");
130 String path4 = ZKUtil.joinZNode(zkw.baseZNode, "testComplexMulti4");
131 String path5 = ZKUtil.joinZNode(zkw.baseZNode, "testComplexMulti5");
132 String path6 = ZKUtil.joinZNode(zkw.baseZNode, "testComplexMulti6");
133
134 LinkedList<ZKUtilOp> create4Nodes = new LinkedList<ZKUtilOp>();
135 create4Nodes.add(ZKUtilOp.createAndFailSilent(path1, Bytes.toBytes(path1)));
136 create4Nodes.add(ZKUtilOp.createAndFailSilent(path2, Bytes.toBytes(path2)));
137 create4Nodes.add(ZKUtilOp.createAndFailSilent(path3, Bytes.toBytes(path3)));
138 create4Nodes.add(ZKUtilOp.createAndFailSilent(path4, Bytes.toBytes(path4)));
139 ZKUtil.multiOrSequential(zkw, create4Nodes, false);
140 assertTrue(Bytes.equals(ZKUtil.getData(zkw, path1), Bytes.toBytes(path1)));
141 assertTrue(Bytes.equals(ZKUtil.getData(zkw, path2), Bytes.toBytes(path2)));
142 assertTrue(Bytes.equals(ZKUtil.getData(zkw, path3), Bytes.toBytes(path3)));
143 assertTrue(Bytes.equals(ZKUtil.getData(zkw, path4), Bytes.toBytes(path4)));
144
145
146 LinkedList<ZKUtilOp> ops = new LinkedList<ZKUtilOp>();
147
148 ops.add(ZKUtilOp.setData(path1, Bytes.add(Bytes.toBytes(path1), Bytes.toBytes(path1))));
149 ops.add(ZKUtilOp.setData(path2, Bytes.add(Bytes.toBytes(path2), Bytes.toBytes(path2))));
150
151 ops.add(ZKUtilOp.deleteNodeFailSilent(path3));
152 ops.add(ZKUtilOp.deleteNodeFailSilent(path4));
153
154 ops.add(ZKUtilOp.createAndFailSilent(path5, Bytes.toBytes(path5)));
155 ops.add(ZKUtilOp.createAndFailSilent(path6, Bytes.toBytes(path6)));
156 ZKUtil.multiOrSequential(zkw, ops, false);
157 assertTrue(Bytes.equals(ZKUtil.getData(zkw, path1),
158 Bytes.add(Bytes.toBytes(path1), Bytes.toBytes(path1))));
159 assertTrue(Bytes.equals(ZKUtil.getData(zkw, path2),
160 Bytes.add(Bytes.toBytes(path2), Bytes.toBytes(path2))));
161 assertTrue(ZKUtil.checkExists(zkw, path3) == -1);
162 assertTrue(ZKUtil.checkExists(zkw, path4) == -1);
163 assertTrue(Bytes.equals(ZKUtil.getData(zkw, path5), Bytes.toBytes(path5)));
164 assertTrue(Bytes.equals(ZKUtil.getData(zkw, path6), Bytes.toBytes(path6)));
165 }
166
167 @Test (timeout=60000)
168 public void testSingleFailure() throws Exception {
169
170 boolean caughtNoNode = false;
171 String path = ZKUtil.joinZNode(zkw.baseZNode, "testSingleFailureZ");
172 LinkedList<ZKUtilOp> ops = new LinkedList<ZKUtilOp>();
173 ops.add(ZKUtilOp.deleteNodeFailSilent(path));
174 try {
175 ZKUtil.multiOrSequential(zkw, ops, false);
176 } catch (KeeperException.NoNodeException nne) {
177 caughtNoNode = true;
178 }
179 assertTrue(caughtNoNode);
180
181
182 caughtNoNode = false;
183 ops = new LinkedList<ZKUtilOp>();
184 ops.add(ZKUtilOp.setData(path, Bytes.toBytes(path)));
185 try {
186 ZKUtil.multiOrSequential(zkw, ops, false);
187 } catch (KeeperException.NoNodeException nne) {
188 caughtNoNode = true;
189 }
190 assertTrue(caughtNoNode);
191
192
193 boolean caughtNodeExists = false;
194 ops = new LinkedList<ZKUtilOp>();
195 ops.add(ZKUtilOp.createAndFailSilent(path, Bytes.toBytes(path)));
196 ZKUtil.multiOrSequential(zkw, ops, false);
197 try {
198 ZKUtil.multiOrSequential(zkw, ops, false);
199 } catch (KeeperException.NodeExistsException nee) {
200 caughtNodeExists = true;
201 }
202 assertTrue(caughtNodeExists);
203 }
204
205 @Test (timeout=60000)
206 public void testSingleFailureInMulti() throws Exception {
207
208 String pathA = ZKUtil.joinZNode(zkw.baseZNode, "testSingleFailureInMultiA");
209 String pathB = ZKUtil.joinZNode(zkw.baseZNode, "testSingleFailureInMultiB");
210 String pathC = ZKUtil.joinZNode(zkw.baseZNode, "testSingleFailureInMultiC");
211 LinkedList<ZKUtilOp> ops = new LinkedList<ZKUtilOp>();
212 ops.add(ZKUtilOp.createAndFailSilent(pathA, Bytes.toBytes(pathA)));
213 ops.add(ZKUtilOp.createAndFailSilent(pathB, Bytes.toBytes(pathB)));
214 ops.add(ZKUtilOp.deleteNodeFailSilent(pathC));
215 boolean caughtNoNode = false;
216 try {
217 ZKUtil.multiOrSequential(zkw, ops, false);
218 } catch (KeeperException.NoNodeException nne) {
219 caughtNoNode = true;
220 }
221 assertTrue(caughtNoNode);
222
223 assertTrue(ZKUtil.checkExists(zkw, pathA) == -1);
224 assertTrue(ZKUtil.checkExists(zkw, pathB) == -1);
225 assertTrue(ZKUtil.checkExists(zkw, pathC) == -1);
226 }
227
228 @Test (timeout=60000)
229 public void testMultiFailure() throws Exception {
230 String pathX = ZKUtil.joinZNode(zkw.baseZNode, "testMultiFailureX");
231 String pathY = ZKUtil.joinZNode(zkw.baseZNode, "testMultiFailureY");
232 String pathZ = ZKUtil.joinZNode(zkw.baseZNode, "testMultiFailureZ");
233
234 LinkedList<ZKUtilOp> ops = new LinkedList<ZKUtilOp>();
235 ops.add(ZKUtilOp.createAndFailSilent(pathX, Bytes.toBytes(pathX)));
236 ZKUtil.multiOrSequential(zkw, ops, false);
237
238
239 String pathV = ZKUtil.joinZNode(zkw.baseZNode, "testMultiFailureV");
240 String pathW = ZKUtil.joinZNode(zkw.baseZNode, "testMultiFailureW");
241 ops = new LinkedList<ZKUtilOp>();
242 ops.add(ZKUtilOp.createAndFailSilent(pathX, Bytes.toBytes(pathX)));
243 ops.add(ZKUtilOp.setData(pathY, Bytes.toBytes(pathY)));
244 ops.add(ZKUtilOp.deleteNodeFailSilent(pathZ));
245 ops.add(ZKUtilOp.createAndFailSilent(pathX, Bytes.toBytes(pathV)));
246 ops.add(ZKUtilOp.createAndFailSilent(pathX, Bytes.toBytes(pathW)));
247 boolean caughtNodeExists = false;
248 try {
249 ZKUtil.multiOrSequential(zkw, ops, false);
250 } catch (KeeperException.NodeExistsException nee) {
251
252 caughtNodeExists = true;
253 }
254 assertTrue(caughtNodeExists);
255
256 assertFalse(ZKUtil.checkExists(zkw, pathX) == -1);
257 assertTrue(ZKUtil.checkExists(zkw, pathY) == -1);
258 assertTrue(ZKUtil.checkExists(zkw, pathZ) == -1);
259 assertTrue(ZKUtil.checkExists(zkw, pathW) == -1);
260 assertTrue(ZKUtil.checkExists(zkw, pathV) == -1);
261
262
263 ops = new LinkedList<ZKUtilOp>();
264 ops.add(ZKUtilOp.setData(pathY, Bytes.toBytes(pathY)));
265 ops.add(ZKUtilOp.createAndFailSilent(pathX, Bytes.toBytes(pathX)));
266 boolean caughtNoNode = false;
267 try {
268 ZKUtil.multiOrSequential(zkw, ops, false);
269 } catch (KeeperException.NoNodeException nne) {
270
271 caughtNoNode = true;
272 }
273 assertTrue(caughtNoNode);
274
275 assertFalse(ZKUtil.checkExists(zkw, pathX) == -1);
276 assertTrue(ZKUtil.checkExists(zkw, pathY) == -1);
277 assertTrue(ZKUtil.checkExists(zkw, pathZ) == -1);
278 assertTrue(ZKUtil.checkExists(zkw, pathW) == -1);
279 assertTrue(ZKUtil.checkExists(zkw, pathV) == -1);
280 }
281
282 @Test (timeout=60000)
283 public void testRunSequentialOnMultiFailure() throws Exception {
284 String path1 = ZKUtil.joinZNode(zkw.baseZNode, "runSequential1");
285 String path2 = ZKUtil.joinZNode(zkw.baseZNode, "runSequential2");
286 String path3 = ZKUtil.joinZNode(zkw.baseZNode, "runSequential3");
287 String path4 = ZKUtil.joinZNode(zkw.baseZNode, "runSequential4");
288
289
290 LinkedList<ZKUtilOp> ops = new LinkedList<ZKUtilOp>();
291 ops.add(ZKUtilOp.createAndFailSilent(path1, Bytes.toBytes(path1)));
292 ops.add(ZKUtilOp.createAndFailSilent(path2, Bytes.toBytes(path2)));
293 ZKUtil.multiOrSequential(zkw, ops, false);
294
295
296
297 ops = new LinkedList<ZKUtilOp>();
298 ops.add(ZKUtilOp.setData(path1, Bytes.add(Bytes.toBytes(path1), Bytes.toBytes(path1))));
299 ops.add(ZKUtilOp.deleteNodeFailSilent(path2));
300 ops.add(ZKUtilOp.deleteNodeFailSilent(path3));
301 ops.add(ZKUtilOp.createAndFailSilent(path4,
302 Bytes.add(Bytes.toBytes(path4), Bytes.toBytes(path4))));
303 ZKUtil.multiOrSequential(zkw, ops, true);
304 assertTrue(Bytes.equals(ZKUtil.getData(zkw, path1),
305 Bytes.add(Bytes.toBytes(path1), Bytes.toBytes(path1))));
306 assertTrue(ZKUtil.checkExists(zkw, path2) == -1);
307 assertTrue(ZKUtil.checkExists(zkw, path3) == -1);
308 assertFalse(ZKUtil.checkExists(zkw, path4) == -1);
309 }
310
311
312
313
314
315 @Test (timeout=60000)
316 public void testdeleteChildrenRecursivelyMulti() throws Exception {
317 String parentZNode = "/testRootMulti";
318 createZNodeTree(parentZNode);
319
320 ZKUtil.deleteChildrenRecursivelyMultiOrSequential(zkw, true, parentZNode);
321
322 assertTrue("Wrongly deleted parent znode!",
323 ZKUtil.checkExists(zkw, parentZNode) > -1);
324 List<String> children = zkw.getRecoverableZooKeeper().getChildren(
325 parentZNode, false);
326 assertTrue("Failed to delete child znodes!", 0 == children.size());
327 }
328
329
330
331
332
333 @Test (timeout=60000)
334 public void testdeleteChildrenRecursivelySequential() throws Exception {
335 String parentZNode = "/testRootSeq";
336 createZNodeTree(parentZNode);
337 boolean useMulti = zkw.getConfiguration().getBoolean(
338 "hbase.zookeeper.useMulti", false);
339 zkw.getConfiguration().setBoolean("hbase.zookeeper.useMulti", false);
340 try {
341
342 ZKUtil.deleteChildrenRecursivelyMultiOrSequential(zkw, true, parentZNode);
343
344 assertTrue("Wrongly deleted parent znode!",
345 ZKUtil.checkExists(zkw, parentZNode) > -1);
346 List<String> children = zkw.getRecoverableZooKeeper().getChildren(
347 parentZNode, false);
348 assertTrue("Failed to delete child znodes!", 0 == children.size());
349 } finally {
350
351 zkw.getConfiguration().setBoolean("hbase.zookeeper.useMulti", useMulti);
352 }
353 }
354
355
356
357
358
359 @Test(timeout = 60000)
360 public void testDeleteNodeRecursivelyMulti() throws Exception {
361 String parentZNode = "/testdeleteNodeRecursivelyMulti";
362 createZNodeTree(parentZNode);
363
364 ZKUtil.deleteNodeRecursively(zkw, parentZNode);
365 assertTrue("Parent znode should be deleted.", ZKUtil.checkExists(zkw, parentZNode) == -1);
366 }
367
368
369
370
371
372 @Test(timeout = 60000)
373 public void testDeleteNodeRecursivelySequential() throws Exception {
374 String parentZNode = "/testdeleteNodeRecursivelySequential";
375 createZNodeTree(parentZNode);
376 boolean useMulti = zkw.getConfiguration().getBoolean("hbase.zookeeper.useMulti", false);
377 zkw.getConfiguration().setBoolean("hbase.zookeeper.useMulti", false);
378 try {
379
380 ZKUtil.deleteNodeRecursively(zkw, parentZNode);
381 assertTrue("Parent znode should be deleted.", ZKUtil.checkExists(zkw, parentZNode) == -1);
382 } finally {
383
384 zkw.getConfiguration().setBoolean("hbase.zookeeper.useMulti", useMulti);
385 }
386 }
387
388 @Test(timeout = 60000)
389 public void testDeleteNodeRecursivelyMultiOrSequential() throws Exception {
390 String parentZNode1 = "/testdeleteNode1";
391 String parentZNode2 = "/testdeleteNode2";
392 String parentZNode3 = "/testdeleteNode3";
393 createZNodeTree(parentZNode1);
394 createZNodeTree(parentZNode2);
395 createZNodeTree(parentZNode3);
396
397 ZKUtil.deleteNodeRecursivelyMultiOrSequential(zkw, false, parentZNode1, parentZNode2,
398 parentZNode3);
399 assertTrue("Parent znode 1 should be deleted.", ZKUtil.checkExists(zkw, parentZNode1) == -1);
400 assertTrue("Parent znode 2 should be deleted.", ZKUtil.checkExists(zkw, parentZNode2) == -1);
401 assertTrue("Parent znode 3 should be deleted.", ZKUtil.checkExists(zkw, parentZNode3) == -1);
402 }
403
404 @Test(timeout = 60000)
405 public void testDeleteChildrenRecursivelyMultiOrSequential() throws Exception {
406 String parentZNode1 = "/testdeleteChildren1";
407 String parentZNode2 = "/testdeleteChildren2";
408 String parentZNode3 = "/testdeleteChildren3";
409 createZNodeTree(parentZNode1);
410 createZNodeTree(parentZNode2);
411 createZNodeTree(parentZNode3);
412
413 ZKUtil.deleteChildrenRecursivelyMultiOrSequential(zkw, true, parentZNode1, parentZNode2,
414 parentZNode3);
415
416 assertTrue("Wrongly deleted parent znode 1!", ZKUtil.checkExists(zkw, parentZNode1) > -1);
417 List<String> children = zkw.getRecoverableZooKeeper().getChildren(parentZNode1, false);
418 assertTrue("Failed to delete child znodes of parent znode 1!", 0 == children.size());
419
420 assertTrue("Wrongly deleted parent znode 2!", ZKUtil.checkExists(zkw, parentZNode2) > -1);
421 children = zkw.getRecoverableZooKeeper().getChildren(parentZNode2, false);
422 assertTrue("Failed to delete child znodes of parent znode 1!", 0 == children.size());
423
424 assertTrue("Wrongly deleted parent znode 3!", ZKUtil.checkExists(zkw, parentZNode3) > -1);
425 children = zkw.getRecoverableZooKeeper().getChildren(parentZNode3, false);
426 assertTrue("Failed to delete child znodes of parent znode 1!", 0 == children.size());
427 }
428
429 @Test
430 public void testBatchedDeletesOfWideZNodes() throws Exception {
431
432 final int batchSize = 50;
433 Configuration localConf = new Configuration(TEST_UTIL.getConfiguration());
434 localConf.setInt("zookeeper.multi.max.size", batchSize);
435 try (ZooKeeperWatcher customZkw = new ZooKeeperWatcher(localConf,
436 "TestZKMulti_Custom", new ZKMultiAbortable(), true)) {
437
438
439 final String parent1 = "/batchedDeletes1";
440 final String parent2 = "/batchedDeletes2";
441 final byte[] EMPTY_BYTES = new byte[0];
442
443
444 List<Op> ops = new ArrayList<>();
445 ops.add(Op.create(parent1, EMPTY_BYTES, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT));
446 for (int i = 0; i < batchSize * 2; i++) {
447 ops.add(Op.create(
448 parent1 + "/" + i, EMPTY_BYTES, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT));
449 }
450 customZkw.getRecoverableZooKeeper().multi(ops);
451
452
453 ops.clear();
454 ops.add(Op.create(parent2, EMPTY_BYTES, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT));
455 for (int i = 0; i < batchSize * 4; i++) {
456 ops.add(Op.create(
457 parent2 + "/" + i, EMPTY_BYTES, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT));
458 }
459 customZkw.getRecoverableZooKeeper().multi(ops);
460
461
462 ZKUtil.deleteChildrenRecursively(customZkw, parent1);
463 ZKUtil.deleteChildrenRecursively(customZkw, parent2);
464 }
465 }
466
467 @Test
468 public void testListPartitioning() {
469
470 ZKUtilOp tenByteOp = ZKUtilOp.deleteNodeFailSilent("/123456789");
471
472
473 assertEquals(Collections.singletonList(Collections.singletonList(tenByteOp)),
474 ZKUtil.partitionOps(Collections.singletonList(tenByteOp), 15));
475
476
477 assertEquals(Collections.singletonList(Collections.singletonList(tenByteOp)),
478 ZKUtil.partitionOps(Collections.singletonList(tenByteOp), 5));
479
480
481 assertEquals(
482 Arrays.asList(Arrays.asList(tenByteOp), Arrays.asList(tenByteOp), Arrays.asList(tenByteOp)),
483 ZKUtil.partitionOps(Arrays.asList(tenByteOp, tenByteOp, tenByteOp), 15));
484
485
486 assertEquals(
487 Arrays.asList(Arrays.asList(tenByteOp,tenByteOp), Arrays.asList(tenByteOp)),
488 ZKUtil.partitionOps(Arrays.asList(tenByteOp, tenByteOp, tenByteOp), 20));
489
490
491 assertEquals(
492 Arrays.asList(Arrays.asList(tenByteOp, tenByteOp, tenByteOp)),
493 ZKUtil.partitionOps(Arrays.asList(tenByteOp, tenByteOp, tenByteOp), 50));
494 }
495
496 private void createZNodeTree(String rootZNode) throws KeeperException,
497 InterruptedException {
498 List<Op> opList = new ArrayList<Op>();
499 opList.add(Op.create(rootZNode, new byte[0], Ids.OPEN_ACL_UNSAFE,
500 CreateMode.PERSISTENT));
501 int level = 0;
502 String parentZNode = rootZNode;
503 while (level < 10) {
504
505 parentZNode = parentZNode + "/" + level;
506 opList.add(Op.create(parentZNode, new byte[0], Ids.OPEN_ACL_UNSAFE,
507 CreateMode.PERSISTENT));
508 int elements = 0;
509
510 while (elements < level) {
511 opList.add(Op.create(parentZNode + "/" + elements, new byte[0],
512 Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT));
513 elements++;
514 }
515 level++;
516 }
517 zkw.getRecoverableZooKeeper().multi(opList);
518 }
519 }