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 org.apache.commons.lang.StringUtils;
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24 import org.apache.hadoop.classification.InterfaceAudience;
25 import org.apache.hadoop.classification.InterfaceStability;
26 import org.apache.hadoop.conf.Configuration;
27 import org.apache.hadoop.hbase.HConstants;
28 import org.apache.hadoop.hbase.ServerName;
29 import org.apache.hadoop.hbase.exceptions.DeserializationException;
30 import org.apache.hadoop.hbase.util.Bytes;
31 import org.apache.hadoop.hbase.util.Threads;
32 import org.apache.hadoop.hbase.zookeeper.ZKUtil.ZKUtilOp.CreateAndFailSilent;
33 import org.apache.hadoop.hbase.zookeeper.ZKUtil.ZKUtilOp.DeleteNodeFailSilent;
34 import org.apache.hadoop.hbase.zookeeper.ZKUtil.ZKUtilOp.SetData;
35 import org.apache.hadoop.security.SecurityUtil;
36 import org.apache.hadoop.security.authentication.util.KerberosUtil;
37 import org.apache.zookeeper.AsyncCallback;
38 import org.apache.zookeeper.CreateMode;
39 import org.apache.zookeeper.KeeperException;
40 import org.apache.zookeeper.KeeperException.NoNodeException;
41 import org.apache.zookeeper.Op;
42 import org.apache.zookeeper.Watcher;
43 import org.apache.zookeeper.ZooDefs.Ids;
44 import org.apache.zookeeper.ZooKeeper;
45 import org.apache.zookeeper.client.ZooKeeperSaslClient;
46 import org.apache.zookeeper.data.ACL;
47 import org.apache.zookeeper.data.Stat;
48 import org.apache.zookeeper.proto.CreateRequest;
49 import org.apache.zookeeper.proto.DeleteRequest;
50 import org.apache.zookeeper.proto.SetDataRequest;
51 import org.apache.zookeeper.server.ZooKeeperSaslServer;
52
53 import javax.security.auth.login.AppConfigurationEntry;
54 import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;
55 import java.io.BufferedReader;
56 import java.io.IOException;
57 import java.io.InputStreamReader;
58 import java.io.PrintWriter;
59 import java.net.InetSocketAddress;
60 import java.net.Socket;
61 import java.util.ArrayList;
62 import java.util.Arrays;
63 import java.util.HashMap;
64 import java.util.LinkedList;
65 import java.util.List;
66 import java.util.Map;
67 import java.util.Properties;
68
69
70
71
72
73
74
75
76
77
78 @InterfaceAudience.Public
79 @InterfaceStability.Evolving
80 public class ZKUtil {
81 private static final Log LOG = LogFactory.getLog(ZKUtil.class);
82
83
84 public static final char ZNODE_PATH_SEPARATOR = '/';
85 private static int zkDumpConnectionTimeOut;
86
87
88
89
90
91
92
93
94
95
96
97
98 public static RecoverableZooKeeper connect(Configuration conf, Watcher watcher)
99 throws IOException {
100 Properties properties = ZKConfig.makeZKProps(conf);
101 String ensemble = ZKConfig.getZKQuorumServersString(properties);
102 return connect(conf, ensemble, watcher);
103 }
104
105 public static RecoverableZooKeeper connect(Configuration conf, String ensemble,
106 Watcher watcher)
107 throws IOException {
108 return connect(conf, ensemble, watcher, null);
109 }
110
111 public static RecoverableZooKeeper connect(Configuration conf, String ensemble,
112 Watcher watcher, final String identifier)
113 throws IOException {
114 if(ensemble == null) {
115 throw new IOException("Unable to determine ZooKeeper ensemble");
116 }
117 int timeout = conf.getInt(HConstants.ZK_SESSION_TIMEOUT,
118 HConstants.DEFAULT_ZK_SESSION_TIMEOUT);
119 LOG.debug(identifier + " opening connection to ZooKeeper with ensemble (" +
120 ensemble + ")");
121 int retry = conf.getInt("zookeeper.recovery.retry", 3);
122 int retryIntervalMillis =
123 conf.getInt("zookeeper.recovery.retry.intervalmill", 1000);
124 zkDumpConnectionTimeOut = conf.getInt("zookeeper.dump.connection.timeout",
125 1000);
126 return new RecoverableZooKeeper(ensemble, timeout, watcher,
127 retry, retryIntervalMillis, identifier);
128 }
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144 public static void loginServer(Configuration conf, String keytabFileKey,
145 String userNameKey, String hostname) throws IOException {
146 login(conf, keytabFileKey, userNameKey, hostname,
147 ZooKeeperSaslServer.LOGIN_CONTEXT_NAME_KEY,
148 JaasConfiguration.SERVER_KEYTAB_KERBEROS_CONFIG_NAME);
149 }
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165 public static void loginClient(Configuration conf, String keytabFileKey,
166 String userNameKey, String hostname) throws IOException {
167 login(conf, keytabFileKey, userNameKey, hostname,
168 ZooKeeperSaslClient.LOGIN_CONTEXT_NAME_KEY,
169 JaasConfiguration.CLIENT_KEYTAB_KERBEROS_CONFIG_NAME);
170 }
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188 private static void login(Configuration conf, String keytabFileKey,
189 String userNameKey, String hostname,
190 String loginContextProperty, String loginContextName)
191 throws IOException {
192 if (!isSecureZooKeeper(conf))
193 return;
194
195
196
197 if (System.getProperty("java.security.auth.login.config") != null)
198 return;
199
200
201 String keytabFilename = conf.get(keytabFileKey);
202 if (keytabFilename == null) {
203 LOG.warn("no keytab specified for: " + keytabFileKey);
204 return;
205 }
206
207 String principalConfig = conf.get(userNameKey, System.getProperty("user.name"));
208 String principalName = SecurityUtil.getServerPrincipal(principalConfig, hostname);
209
210
211
212
213 JaasConfiguration jaasConf = new JaasConfiguration(loginContextName,
214 principalName, keytabFilename);
215 javax.security.auth.login.Configuration.setConfiguration(jaasConf);
216 System.setProperty(loginContextProperty, loginContextName);
217 }
218
219
220
221
222 private static class JaasConfiguration extends javax.security.auth.login.Configuration {
223 private static final String SERVER_KEYTAB_KERBEROS_CONFIG_NAME =
224 "zookeeper-server-keytab-kerberos";
225 private static final String CLIENT_KEYTAB_KERBEROS_CONFIG_NAME =
226 "zookeeper-client-keytab-kerberos";
227
228 private static final Map<String, String> BASIC_JAAS_OPTIONS =
229 new HashMap<String,String>();
230 static {
231 String jaasEnvVar = System.getenv("HBASE_JAAS_DEBUG");
232 if (jaasEnvVar != null && "true".equalsIgnoreCase(jaasEnvVar)) {
233 BASIC_JAAS_OPTIONS.put("debug", "true");
234 }
235 }
236
237 private static final Map<String,String> KEYTAB_KERBEROS_OPTIONS =
238 new HashMap<String,String>();
239 static {
240 KEYTAB_KERBEROS_OPTIONS.put("doNotPrompt", "true");
241 KEYTAB_KERBEROS_OPTIONS.put("storeKey", "true");
242 KEYTAB_KERBEROS_OPTIONS.put("refreshKrb5Config", "true");
243 KEYTAB_KERBEROS_OPTIONS.putAll(BASIC_JAAS_OPTIONS);
244 }
245
246 private static final AppConfigurationEntry KEYTAB_KERBEROS_LOGIN =
247 new AppConfigurationEntry(KerberosUtil.getKrb5LoginModuleName(),
248 LoginModuleControlFlag.REQUIRED,
249 KEYTAB_KERBEROS_OPTIONS);
250
251 private static final AppConfigurationEntry[] KEYTAB_KERBEROS_CONF =
252 new AppConfigurationEntry[]{KEYTAB_KERBEROS_LOGIN};
253
254 private javax.security.auth.login.Configuration baseConfig;
255 private final String loginContextName;
256 private final boolean useTicketCache;
257 private final String keytabFile;
258 private final String principal;
259
260 public JaasConfiguration(String loginContextName, String principal) {
261 this(loginContextName, principal, null, true);
262 }
263
264 public JaasConfiguration(String loginContextName, String principal, String keytabFile) {
265 this(loginContextName, principal, keytabFile, keytabFile == null || keytabFile.length() == 0);
266 }
267
268 private JaasConfiguration(String loginContextName, String principal,
269 String keytabFile, boolean useTicketCache) {
270 try {
271 this.baseConfig = javax.security.auth.login.Configuration.getConfiguration();
272 } catch (SecurityException e) {
273 this.baseConfig = null;
274 }
275 this.loginContextName = loginContextName;
276 this.useTicketCache = useTicketCache;
277 this.keytabFile = keytabFile;
278 this.principal = principal;
279 LOG.info("JaasConfiguration loginContextName=" + loginContextName +
280 " principal=" + principal + " useTicketCache=" + useTicketCache +
281 " keytabFile=" + keytabFile);
282 }
283
284 @Override
285 public AppConfigurationEntry[] getAppConfigurationEntry(String appName) {
286 if (loginContextName.equals(appName)) {
287 if (!useTicketCache) {
288 KEYTAB_KERBEROS_OPTIONS.put("keyTab", keytabFile);
289 KEYTAB_KERBEROS_OPTIONS.put("useKeyTab", "true");
290 }
291 KEYTAB_KERBEROS_OPTIONS.put("principal", principal);
292 KEYTAB_KERBEROS_OPTIONS.put("useTicketCache", useTicketCache ? "true" : "false");
293 return KEYTAB_KERBEROS_CONF;
294 }
295 if (baseConfig != null) return baseConfig.getAppConfigurationEntry(appName);
296 return(null);
297 }
298 }
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314 public static String joinZNode(String prefix, String suffix) {
315 return prefix + ZNODE_PATH_SEPARATOR + suffix;
316 }
317
318
319
320
321
322
323 public static String getParent(String node) {
324 int idx = node.lastIndexOf(ZNODE_PATH_SEPARATOR);
325 return idx <= 0 ? null : node.substring(0, idx);
326 }
327
328
329
330
331
332
333 public static String getNodeName(String path) {
334 return path.substring(path.lastIndexOf("/")+1);
335 }
336
337
338
339
340
341
342
343 public static String getZooKeeperClusterKey(Configuration conf) {
344 return getZooKeeperClusterKey(conf, null);
345 }
346
347
348
349
350
351
352
353
354 public static String getZooKeeperClusterKey(Configuration conf, String name) {
355 String ensemble = conf.get(HConstants.ZOOKEEPER_QUORUM.replaceAll(
356 "[\\t\\n\\x0B\\f\\r]", ""));
357 StringBuilder builder = new StringBuilder(ensemble);
358 builder.append(":");
359 builder.append(conf.get(HConstants.ZOOKEEPER_CLIENT_PORT));
360 builder.append(":");
361 builder.append(conf.get(HConstants.ZOOKEEPER_ZNODE_PARENT));
362 if (name != null && !name.isEmpty()) {
363 builder.append(",");
364 builder.append(name);
365 }
366 return builder.toString();
367 }
368
369
370
371
372
373
374
375
376 public static void applyClusterKeyToConf(Configuration conf, String key)
377 throws IOException{
378 String[] parts = transformClusterKey(key);
379 conf.set(HConstants.ZOOKEEPER_QUORUM, parts[0]);
380 conf.set(HConstants.ZOOKEEPER_CLIENT_PORT, parts[1]);
381 conf.set(HConstants.ZOOKEEPER_ZNODE_PARENT, parts[2]);
382 }
383
384
385
386
387
388
389
390
391
392 public static String[] transformClusterKey(String key) throws IOException {
393 String[] parts = key.split(":");
394 if (parts.length != 3) {
395 throw new IOException("Cluster key invalid, the format should be:" +
396 HConstants.ZOOKEEPER_QUORUM + ":hbase.zookeeper.client.port:"
397 + HConstants.ZOOKEEPER_ZNODE_PARENT);
398 }
399 return parts;
400 }
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416 public static boolean watchAndCheckExists(ZooKeeperWatcher zkw, String znode)
417 throws KeeperException {
418 try {
419 Stat s = zkw.getRecoverableZooKeeper().exists(znode, zkw);
420 boolean exists = s != null ? true : false;
421 if (exists) {
422 LOG.debug(zkw.prefix("Set watcher on existing znode " + znode));
423 } else {
424 LOG.debug(zkw.prefix(znode+" does not exist. Watcher is set."));
425 }
426 return exists;
427 } catch (KeeperException e) {
428 LOG.warn(zkw.prefix("Unable to set watcher on znode " + znode), e);
429 zkw.keeperException(e);
430 return false;
431 } catch (InterruptedException e) {
432 LOG.warn(zkw.prefix("Unable to set watcher on znode " + znode), e);
433 zkw.interruptedException(e);
434 return false;
435 }
436 }
437
438
439
440
441
442
443
444
445
446
447
448 public static boolean setWatchIfNodeExists(ZooKeeperWatcher zkw, String znode)
449 throws KeeperException {
450 try {
451 zkw.getRecoverableZooKeeper().getData(znode, true, null);
452 return true;
453 } catch (NoNodeException e) {
454 return false;
455 } catch (InterruptedException e) {
456 LOG.warn(zkw.prefix("Unable to set watcher on znode " + znode), e);
457 zkw.interruptedException(e);
458 return false;
459 }
460 }
461
462
463
464
465
466
467
468
469
470 public static int checkExists(ZooKeeperWatcher zkw, String znode)
471 throws KeeperException {
472 try {
473 Stat s = zkw.getRecoverableZooKeeper().exists(znode, null);
474 return s != null ? s.getVersion() : -1;
475 } catch (KeeperException e) {
476 LOG.warn(zkw.prefix("Unable to set watcher on znode (" + znode + ")"), e);
477 zkw.keeperException(e);
478 return -1;
479 } catch (InterruptedException e) {
480 LOG.warn(zkw.prefix("Unable to set watcher on znode (" + znode + ")"), e);
481 zkw.interruptedException(e);
482 return -1;
483 }
484 }
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506 public static List<String> listChildrenAndWatchForNewChildren(
507 ZooKeeperWatcher zkw, String znode)
508 throws KeeperException {
509 try {
510 List<String> children = zkw.getRecoverableZooKeeper().getChildren(znode, zkw);
511 return children;
512 } catch(KeeperException.NoNodeException ke) {
513 LOG.debug(zkw.prefix("Unable to list children of znode " + znode + " " +
514 "because node does not exist (not an error)"));
515 return null;
516 } catch (KeeperException e) {
517 LOG.warn(zkw.prefix("Unable to list children of znode " + znode + " "), e);
518 zkw.keeperException(e);
519 return null;
520 } catch (InterruptedException e) {
521 LOG.warn(zkw.prefix("Unable to list children of znode " + znode + " "), e);
522 zkw.interruptedException(e);
523 return null;
524 }
525 }
526
527
528
529
530
531
532
533
534
535
536 public static List<String> listChildrenAndWatchThem(ZooKeeperWatcher zkw,
537 String znode) throws KeeperException {
538 List<String> children = listChildrenAndWatchForNewChildren(zkw, znode);
539 if (children == null) {
540 return null;
541 }
542 for (String child : children) {
543 watchAndCheckExists(zkw, joinZNode(znode, child));
544 }
545 return children;
546 }
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562 public static List<String> listChildrenNoWatch(ZooKeeperWatcher zkw, String znode)
563 throws KeeperException {
564 List<String> children = null;
565 try {
566
567 children = zkw.getRecoverableZooKeeper().getChildren(znode, null);
568 } catch(KeeperException.NoNodeException nne) {
569 return null;
570 } catch(InterruptedException ie) {
571 zkw.interruptedException(ie);
572 }
573 return children;
574 }
575
576
577
578
579
580 @Deprecated
581 public static class NodeAndData {
582 private String node;
583 private byte [] data;
584 public NodeAndData(String node, byte [] data) {
585 this.node = node;
586 this.data = data;
587 }
588 public String getNode() {
589 return node;
590 }
591 public byte [] getData() {
592 return data;
593 }
594 @Override
595 public String toString() {
596 return node;
597 }
598 public boolean isEmpty() {
599 return (data.length == 0);
600 }
601 }
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619 public static boolean nodeHasChildren(ZooKeeperWatcher zkw, String znode)
620 throws KeeperException {
621 try {
622 return !zkw.getRecoverableZooKeeper().getChildren(znode, null).isEmpty();
623 } catch(KeeperException.NoNodeException ke) {
624 LOG.debug(zkw.prefix("Unable to list children of znode " + znode + " " +
625 "because node does not exist (not an error)"));
626 return false;
627 } catch (KeeperException e) {
628 LOG.warn(zkw.prefix("Unable to list children of znode " + znode), e);
629 zkw.keeperException(e);
630 return false;
631 } catch (InterruptedException e) {
632 LOG.warn(zkw.prefix("Unable to list children of znode " + znode), e);
633 zkw.interruptedException(e);
634 return false;
635 }
636 }
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651 public static int getNumberOfChildren(ZooKeeperWatcher zkw, String znode)
652 throws KeeperException {
653 try {
654 Stat stat = zkw.getRecoverableZooKeeper().exists(znode, null);
655 return stat == null ? 0 : stat.getNumChildren();
656 } catch(KeeperException e) {
657 LOG.warn(zkw.prefix("Unable to get children of node " + znode));
658 zkw.keeperException(e);
659 } catch(InterruptedException e) {
660 zkw.interruptedException(e);
661 }
662 return 0;
663 }
664
665
666
667
668
669
670
671
672
673
674 public static byte [] getData(ZooKeeperWatcher zkw, String znode)
675 throws KeeperException {
676 try {
677 byte [] data = zkw.getRecoverableZooKeeper().getData(znode, null, null);
678 logRetrievedMsg(zkw, znode, data, false);
679 return data;
680 } catch (KeeperException.NoNodeException e) {
681 LOG.debug(zkw.prefix("Unable to get data of znode " + znode + " " +
682 "because node does not exist (not an error)"));
683 return null;
684 } catch (KeeperException e) {
685 LOG.warn(zkw.prefix("Unable to get data of znode " + znode), e);
686 zkw.keeperException(e);
687 return null;
688 } catch (InterruptedException e) {
689 LOG.warn(zkw.prefix("Unable to get data of znode " + znode), e);
690 zkw.interruptedException(e);
691 return null;
692 }
693 }
694
695
696
697
698
699
700
701
702
703
704
705
706 public static byte [] getDataAndWatch(ZooKeeperWatcher zkw, String znode)
707 throws KeeperException {
708 return getDataInternal(zkw, znode, null, true);
709 }
710
711
712
713
714
715
716
717
718
719
720
721
722
723 public static byte[] getDataAndWatch(ZooKeeperWatcher zkw, String znode,
724 Stat stat) throws KeeperException {
725 return getDataInternal(zkw, znode, stat, true);
726 }
727
728 private static byte[] getDataInternal(ZooKeeperWatcher zkw, String znode, Stat stat,
729 boolean watcherSet)
730 throws KeeperException {
731 try {
732 byte [] data = zkw.getRecoverableZooKeeper().getData(znode, zkw, stat);
733 logRetrievedMsg(zkw, znode, data, watcherSet);
734 return data;
735 } catch (KeeperException.NoNodeException e) {
736
737
738 LOG.trace(zkw.prefix("Unable to get data of znode " + znode + " " +
739 "because node does not exist (not an error)"));
740 return null;
741 } catch (KeeperException e) {
742 LOG.warn(zkw.prefix("Unable to get data of znode " + znode), e);
743 zkw.keeperException(e);
744 return null;
745 } catch (InterruptedException e) {
746 LOG.warn(zkw.prefix("Unable to get data of znode " + znode), e);
747 zkw.interruptedException(e);
748 return null;
749 }
750 }
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767 public static byte [] getDataNoWatch(ZooKeeperWatcher zkw, String znode,
768 Stat stat)
769 throws KeeperException {
770 try {
771 byte [] data = zkw.getRecoverableZooKeeper().getData(znode, null, stat);
772 logRetrievedMsg(zkw, znode, data, false);
773 return data;
774 } catch (KeeperException.NoNodeException e) {
775 LOG.debug(zkw.prefix("Unable to get data of znode " + znode + " " +
776 "because node does not exist (not necessarily an error)"));
777 return null;
778 } catch (KeeperException e) {
779 LOG.warn(zkw.prefix("Unable to get data of znode " + znode), e);
780 zkw.keeperException(e);
781 return null;
782 } catch (InterruptedException e) {
783 LOG.warn(zkw.prefix("Unable to get data of znode " + znode), e);
784 zkw.interruptedException(e);
785 return null;
786 }
787 }
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806 public static List<NodeAndData> getChildDataAndWatchForNewChildren(
807 ZooKeeperWatcher zkw, String baseNode) throws KeeperException {
808 List<String> nodes =
809 ZKUtil.listChildrenAndWatchForNewChildren(zkw, baseNode);
810 List<NodeAndData> newNodes = new ArrayList<NodeAndData>();
811 if (nodes != null) {
812 for (String node : nodes) {
813 String nodePath = ZKUtil.joinZNode(baseNode, node);
814 byte[] data = ZKUtil.getDataAndWatch(zkw, nodePath);
815 newNodes.add(new NodeAndData(nodePath, data));
816 }
817 }
818 return newNodes;
819 }
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837 public static void updateExistingNodeData(ZooKeeperWatcher zkw, String znode,
838 byte [] data, int expectedVersion)
839 throws KeeperException {
840 try {
841 zkw.getRecoverableZooKeeper().setData(znode, data, expectedVersion);
842 } catch(InterruptedException ie) {
843 zkw.interruptedException(ie);
844 }
845 }
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871 public static boolean setData(ZooKeeperWatcher zkw, String znode,
872 byte [] data, int expectedVersion)
873 throws KeeperException, KeeperException.NoNodeException {
874 try {
875 return zkw.getRecoverableZooKeeper().setData(znode, data, expectedVersion) != null;
876 } catch (InterruptedException e) {
877 zkw.interruptedException(e);
878 return false;
879 }
880 }
881
882
883
884
885
886
887
888
889
890
891 public static void createSetData(final ZooKeeperWatcher zkw, final String znode,
892 final byte [] data)
893 throws KeeperException {
894 if (checkExists(zkw, znode) == -1) {
895 ZKUtil.createWithParents(zkw, znode, data);
896 } else {
897 ZKUtil.setData(zkw, znode, data);
898 }
899 }
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917 public static void setData(ZooKeeperWatcher zkw, String znode, byte [] data)
918 throws KeeperException, KeeperException.NoNodeException {
919 setData(zkw, (SetData)ZKUtilOp.setData(znode, data));
920 }
921
922 private static void setData(ZooKeeperWatcher zkw, SetData setData)
923 throws KeeperException, KeeperException.NoNodeException {
924 SetDataRequest sd = (SetDataRequest)toZooKeeperOp(zkw, setData).toRequestRecord();
925 setData(zkw, sd.getPath(), sd.getData(), sd.getVersion());
926 }
927
928
929
930
931
932
933 public static boolean isSecureZooKeeper(Configuration conf) {
934
935
936
937 if (System.getProperty("java.security.auth.login.config") != null)
938 return true;
939
940
941 return("kerberos".equalsIgnoreCase(conf.get("hbase.security.authentication")) &&
942 conf.get("hbase.zookeeper.client.keytab.file") != null);
943 }
944
945 private static ArrayList<ACL> createACL(ZooKeeperWatcher zkw, String node) {
946 if (isSecureZooKeeper(zkw.getConfiguration())) {
947
948
949 if ((node.equals(zkw.baseZNode) == true) ||
950 (node.equals(zkw.metaServerZNode) == true) ||
951 (node.equals(zkw.getMasterAddressZNode()) == true) ||
952 (node.equals(zkw.clusterIdZNode) == true) ||
953 (node.equals(zkw.rsZNode) == true) ||
954 (node.equals(zkw.backupMasterAddressesZNode) == true) ||
955 (node.startsWith(zkw.assignmentZNode) == true) ||
956 (node.startsWith(zkw.tableZNode) == true)) {
957 return ZooKeeperWatcher.CREATOR_ALL_AND_WORLD_READABLE;
958 }
959 return Ids.CREATOR_ALL_ACL;
960 } else {
961 return Ids.OPEN_ACL_UNSAFE;
962 }
963 }
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987 public static boolean createEphemeralNodeAndWatch(ZooKeeperWatcher zkw,
988 String znode, byte [] data)
989 throws KeeperException {
990 try {
991 zkw.getRecoverableZooKeeper().create(znode, data, createACL(zkw, znode),
992 CreateMode.EPHEMERAL);
993 } catch (KeeperException.NodeExistsException nee) {
994 if(!watchAndCheckExists(zkw, znode)) {
995
996 return createEphemeralNodeAndWatch(zkw, znode, data);
997 }
998 return false;
999 } catch (InterruptedException e) {
1000 LOG.info("Interrupted", e);
1001 Thread.currentThread().interrupt();
1002 }
1003 return true;
1004 }
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026 public static boolean createNodeIfNotExistsAndWatch(
1027 ZooKeeperWatcher zkw, String znode, byte [] data)
1028 throws KeeperException {
1029 try {
1030 zkw.getRecoverableZooKeeper().create(znode, data, createACL(zkw, znode),
1031 CreateMode.PERSISTENT);
1032 } catch (KeeperException.NodeExistsException nee) {
1033 try {
1034 zkw.getRecoverableZooKeeper().exists(znode, zkw);
1035 } catch (InterruptedException e) {
1036 zkw.interruptedException(e);
1037 return false;
1038 }
1039 return false;
1040 } catch (InterruptedException e) {
1041 zkw.interruptedException(e);
1042 return false;
1043 }
1044 return true;
1045 }
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061 public static String createNodeIfNotExistsNoWatch(ZooKeeperWatcher zkw, String znode,
1062 byte[] data, CreateMode createMode) throws KeeperException {
1063
1064 String createdZNode = null;
1065 try {
1066 createdZNode = zkw.getRecoverableZooKeeper().create(znode, data,
1067 createACL(zkw, znode), createMode);
1068 } catch (KeeperException.NodeExistsException nee) {
1069 return znode;
1070 } catch (InterruptedException e) {
1071 zkw.interruptedException(e);
1072 return null;
1073 }
1074 return createdZNode;
1075 }
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093 public static int createAndWatch(ZooKeeperWatcher zkw,
1094 String znode, byte [] data)
1095 throws KeeperException, KeeperException.NodeExistsException {
1096 try {
1097 zkw.getRecoverableZooKeeper().create(znode, data, createACL(zkw, znode),
1098 CreateMode.PERSISTENT);
1099 Stat stat = zkw.getRecoverableZooKeeper().exists(znode, zkw);
1100 if (stat == null){
1101
1102 throw KeeperException.create(KeeperException.Code.SYSTEMERROR,
1103 "ZK.exists returned null (i.e.: znode does not exist) for znode=" + znode);
1104 }
1105 return stat.getVersion();
1106 } catch (InterruptedException e) {
1107 zkw.interruptedException(e);
1108 return -1;
1109 }
1110 }
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127 public static void asyncCreate(ZooKeeperWatcher zkw,
1128 String znode, byte [] data, final AsyncCallback.StringCallback cb,
1129 final Object ctx) {
1130 zkw.getRecoverableZooKeeper().getZooKeeper().create(znode, data,
1131 createACL(zkw, znode), CreateMode.PERSISTENT, cb, ctx);
1132 }
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144 public static void createAndFailSilent(ZooKeeperWatcher zkw,
1145 String znode) throws KeeperException {
1146 createAndFailSilent(zkw, znode, new byte[0]);
1147 }
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160 public static void createAndFailSilent(ZooKeeperWatcher zkw,
1161 String znode, byte[] data)
1162 throws KeeperException {
1163 createAndFailSilent(zkw,
1164 (CreateAndFailSilent)ZKUtilOp.createAndFailSilent(znode, data));
1165 }
1166
1167 private static void createAndFailSilent(ZooKeeperWatcher zkw, CreateAndFailSilent cafs)
1168 throws KeeperException {
1169 CreateRequest create = (CreateRequest)toZooKeeperOp(zkw, cafs).toRequestRecord();
1170 String znode = create.getPath();
1171 try {
1172 RecoverableZooKeeper zk = zkw.getRecoverableZooKeeper();
1173 if (zk.exists(znode, false) == null) {
1174 zk.create(znode, create.getData(), create.getAcl(), CreateMode.fromFlag(create.getFlags()));
1175 }
1176 } catch(KeeperException.NodeExistsException nee) {
1177 } catch(KeeperException.NoAuthException nee){
1178 try {
1179 if (null == zkw.getRecoverableZooKeeper().exists(znode, false)) {
1180
1181 throw(nee);
1182 }
1183 } catch (InterruptedException ie) {
1184 zkw.interruptedException(ie);
1185 }
1186
1187 } catch(InterruptedException ie) {
1188 zkw.interruptedException(ie);
1189 }
1190 }
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203 public static void createWithParents(ZooKeeperWatcher zkw, String znode)
1204 throws KeeperException {
1205 createWithParents(zkw, znode, new byte[0]);
1206 }
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221 public static void createWithParents(ZooKeeperWatcher zkw, String znode, byte[] data)
1222 throws KeeperException {
1223 try {
1224 if(znode == null) {
1225 return;
1226 }
1227 zkw.getRecoverableZooKeeper().create(znode, data, createACL(zkw, znode),
1228 CreateMode.PERSISTENT);
1229 } catch(KeeperException.NodeExistsException nee) {
1230 return;
1231 } catch(KeeperException.NoNodeException nne) {
1232 createWithParents(zkw, getParent(znode));
1233 createWithParents(zkw, znode);
1234 } catch(InterruptedException ie) {
1235 zkw.interruptedException(ie);
1236 }
1237 }
1238
1239
1240
1241
1242
1243
1244
1245
1246 public static void deleteNode(ZooKeeperWatcher zkw, String node)
1247 throws KeeperException {
1248 deleteNode(zkw, node, -1);
1249 }
1250
1251
1252
1253
1254
1255 public static boolean deleteNode(ZooKeeperWatcher zkw, String node,
1256 int version)
1257 throws KeeperException {
1258 try {
1259 zkw.getRecoverableZooKeeper().delete(node, version);
1260 return true;
1261 } catch(KeeperException.BadVersionException bve) {
1262 return false;
1263 } catch(InterruptedException ie) {
1264 zkw.interruptedException(ie);
1265 return false;
1266 }
1267 }
1268
1269
1270
1271
1272
1273
1274
1275 public static void deleteNodeFailSilent(ZooKeeperWatcher zkw, String node)
1276 throws KeeperException {
1277 deleteNodeFailSilent(zkw,
1278 (DeleteNodeFailSilent)ZKUtilOp.deleteNodeFailSilent(node));
1279 }
1280
1281 private static void deleteNodeFailSilent(ZooKeeperWatcher zkw,
1282 DeleteNodeFailSilent dnfs) throws KeeperException {
1283 DeleteRequest delete = (DeleteRequest)toZooKeeperOp(zkw, dnfs).toRequestRecord();
1284 try {
1285 zkw.getRecoverableZooKeeper().delete(delete.getPath(), delete.getVersion());
1286 } catch(KeeperException.NoNodeException nne) {
1287 } catch(InterruptedException ie) {
1288 zkw.interruptedException(ie);
1289 }
1290 }
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301 public static void deleteNodeRecursively(ZooKeeperWatcher zkw, String node)
1302 throws KeeperException {
1303 try {
1304 List<String> children = ZKUtil.listChildrenNoWatch(zkw, node);
1305
1306 if (children == null) return;
1307
1308 if(!children.isEmpty()) {
1309 for(String child : children) {
1310 deleteNodeRecursively(zkw, joinZNode(node, child));
1311 }
1312 }
1313 zkw.getRecoverableZooKeeper().delete(node, -1);
1314 } catch(InterruptedException ie) {
1315 zkw.interruptedException(ie);
1316 }
1317 }
1318
1319
1320
1321
1322
1323
1324
1325 public static void deleteChildrenRecursively(ZooKeeperWatcher zkw, String node)
1326 throws KeeperException {
1327 List<String> children = ZKUtil.listChildrenNoWatch(zkw, node);
1328 if (children == null || children.isEmpty()) return;
1329 for(String child : children) {
1330 deleteNodeRecursively(zkw, joinZNode(node, child));
1331 }
1332 }
1333
1334
1335
1336
1337
1338
1339 public abstract static class ZKUtilOp {
1340 private String path;
1341
1342 private ZKUtilOp(String path) {
1343 this.path = path;
1344 }
1345
1346
1347
1348
1349 public static ZKUtilOp createAndFailSilent(String path, byte[] data) {
1350 return new CreateAndFailSilent(path, data);
1351 }
1352
1353
1354
1355
1356 public static ZKUtilOp deleteNodeFailSilent(String path) {
1357 return new DeleteNodeFailSilent(path);
1358 }
1359
1360
1361
1362
1363 public static ZKUtilOp setData(String path, byte [] data) {
1364 return new SetData(path, data);
1365 }
1366
1367
1368
1369
1370 public String getPath() {
1371 return path;
1372 }
1373
1374
1375
1376
1377
1378 public static class CreateAndFailSilent extends ZKUtilOp {
1379 private byte [] data;
1380
1381 private CreateAndFailSilent(String path, byte [] data) {
1382 super(path);
1383 this.data = data;
1384 }
1385
1386 public byte[] getData() {
1387 return data;
1388 }
1389
1390 @Override
1391 public boolean equals(Object o) {
1392 if (this == o) return true;
1393 if (!(o instanceof CreateAndFailSilent)) return false;
1394
1395 CreateAndFailSilent op = (CreateAndFailSilent) o;
1396 return getPath().equals(op.getPath()) && Arrays.equals(data, op.data);
1397 }
1398
1399 @Override
1400 public int hashCode() {
1401 int ret = 17 + getPath().hashCode() * 31;
1402 return ret * 31 + Bytes.hashCode(data);
1403 }
1404 }
1405
1406
1407
1408
1409
1410 public static class DeleteNodeFailSilent extends ZKUtilOp {
1411 private DeleteNodeFailSilent(String path) {
1412 super(path);
1413 }
1414
1415 @Override
1416 public boolean equals(Object o) {
1417 if (this == o) return true;
1418 if (!(o instanceof DeleteNodeFailSilent)) return false;
1419
1420 return super.equals(o);
1421 }
1422
1423 @Override
1424 public int hashCode() {
1425 return getPath().hashCode();
1426 }
1427 }
1428
1429
1430
1431
1432 public static class SetData extends ZKUtilOp {
1433 private byte [] data;
1434
1435 private SetData(String path, byte [] data) {
1436 super(path);
1437 this.data = data;
1438 }
1439
1440 public byte[] getData() {
1441 return data;
1442 }
1443
1444 @Override
1445 public boolean equals(Object o) {
1446 if (this == o) return true;
1447 if (!(o instanceof SetData)) return false;
1448
1449 SetData op = (SetData) o;
1450 return getPath().equals(op.getPath()) && Arrays.equals(data, op.data);
1451 }
1452
1453 @Override
1454 public int hashCode() {
1455 int ret = getPath().hashCode();
1456 return ret * 31 + Bytes.hashCode(data);
1457 }
1458 }
1459 }
1460
1461
1462
1463
1464 private static Op toZooKeeperOp(ZooKeeperWatcher zkw, ZKUtilOp op)
1465 throws UnsupportedOperationException {
1466 if(op == null) return null;
1467
1468 if (op instanceof CreateAndFailSilent) {
1469 CreateAndFailSilent cafs = (CreateAndFailSilent)op;
1470 return Op.create(cafs.getPath(), cafs.getData(), createACL(zkw, cafs.getPath()),
1471 CreateMode.PERSISTENT);
1472 } else if (op instanceof DeleteNodeFailSilent) {
1473 DeleteNodeFailSilent dnfs = (DeleteNodeFailSilent)op;
1474 return Op.delete(dnfs.getPath(), -1);
1475 } else if (op instanceof SetData) {
1476 SetData sd = (SetData)op;
1477 return Op.setData(sd.getPath(), sd.getData(), -1);
1478 } else {
1479 throw new UnsupportedOperationException("Unexpected ZKUtilOp type: "
1480 + op.getClass().getName());
1481 }
1482 }
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505 public static void multiOrSequential(ZooKeeperWatcher zkw, List<ZKUtilOp> ops,
1506 boolean runSequentialOnMultiFailure) throws KeeperException {
1507 if (ops == null) return;
1508 boolean useMulti = zkw.getConfiguration().getBoolean(HConstants.ZOOKEEPER_USEMULTI, false);
1509
1510 if (useMulti) {
1511 List<Op> zkOps = new LinkedList<Op>();
1512 for (ZKUtilOp op : ops) {
1513 zkOps.add(toZooKeeperOp(zkw, op));
1514 }
1515 try {
1516 zkw.getRecoverableZooKeeper().multi(zkOps);
1517 } catch (KeeperException ke) {
1518 switch (ke.code()) {
1519 case NODEEXISTS:
1520 case NONODE:
1521 case BADVERSION:
1522 case NOAUTH:
1523
1524
1525 if (runSequentialOnMultiFailure) {
1526 LOG.info("On call to ZK.multi, received exception: " + ke.toString() + "."
1527 + " Attempting to run operations sequentially because"
1528 + " runSequentialOnMultiFailure is: " + runSequentialOnMultiFailure + ".");
1529 processSequentially(zkw, ops);
1530 break;
1531 }
1532 default:
1533 throw ke;
1534 }
1535 } catch (InterruptedException ie) {
1536 zkw.interruptedException(ie);
1537 }
1538 } else {
1539
1540 processSequentially(zkw, ops);
1541 }
1542 }
1543
1544 private static void processSequentially(ZooKeeperWatcher zkw, List<ZKUtilOp> ops)
1545 throws KeeperException, NoNodeException {
1546 for (ZKUtilOp op : ops) {
1547 if (op instanceof CreateAndFailSilent) {
1548 createAndFailSilent(zkw, (CreateAndFailSilent) op);
1549 } else if (op instanceof DeleteNodeFailSilent) {
1550 deleteNodeFailSilent(zkw, (DeleteNodeFailSilent) op);
1551 } else if (op instanceof SetData) {
1552 setData(zkw, (SetData) op);
1553 } else {
1554 throw new UnsupportedOperationException("Unexpected ZKUtilOp type: "
1555 + op.getClass().getName());
1556 }
1557 }
1558 }
1559
1560
1561
1562
1563
1564
1565 public static String dump(ZooKeeperWatcher zkw) {
1566 StringBuilder sb = new StringBuilder();
1567 try {
1568 sb.append("HBase is rooted at ").append(zkw.baseZNode);
1569 sb.append("\nActive master address: ");
1570 try {
1571 sb.append(MasterAddressTracker.getMasterAddress(zkw));
1572 } catch (IOException e) {
1573 sb.append("<<FAILED LOOKUP: " + e.getMessage() + ">>");
1574 }
1575 sb.append("\nBackup master addresses:");
1576 for (String child : listChildrenNoWatch(zkw,
1577 zkw.backupMasterAddressesZNode)) {
1578 sb.append("\n ").append(child);
1579 }
1580 sb.append("\nRegion server holding .META.: " + MetaRegionTracker.getMetaRegionLocation(zkw));
1581 sb.append("\nRegion servers:");
1582 for (String child : listChildrenNoWatch(zkw, zkw.rsZNode)) {
1583 sb.append("\n ").append(child);
1584 }
1585 try {
1586 getReplicationZnodesDump(zkw, sb);
1587 } catch (KeeperException ke) {
1588 LOG.warn("Couldn't get the replication znode dump", ke);
1589 }
1590 sb.append("\nQuorum Server Statistics:");
1591 String[] servers = zkw.getQuorum().split(",");
1592 for (String server : servers) {
1593 sb.append("\n ").append(server);
1594 try {
1595 String[] stat = getServerStats(server, ZKUtil.zkDumpConnectionTimeOut);
1596
1597 if (stat == null) {
1598 sb.append("[Error] invalid quorum server: " + server);
1599 break;
1600 }
1601
1602 for (String s : stat) {
1603 sb.append("\n ").append(s);
1604 }
1605 } catch (Exception e) {
1606 sb.append("\n ERROR: ").append(e.getMessage());
1607 }
1608 }
1609 } catch (KeeperException ke) {
1610 sb.append("\nFATAL ZooKeeper Exception!\n");
1611 sb.append("\n" + ke.getMessage());
1612 }
1613 return sb.toString();
1614 }
1615
1616 private static void getReplicationZnodesDump(ZooKeeperWatcher zkw, StringBuilder sb)
1617 throws KeeperException {
1618 String replicationZNodeName = zkw.getConfiguration().get("zookeeper.znode.replication",
1619 "replication");
1620 String replicationZnode = joinZNode(zkw.baseZNode, replicationZNodeName);
1621 if (ZKUtil.checkExists(zkw, replicationZnode) == -1) return;
1622
1623 List<String> stack = new LinkedList<String>();
1624 stack.add(replicationZnode);
1625 do {
1626 String znodeToProcess = stack.remove(stack.size() - 1);
1627 sb.append("\n").append(znodeToProcess).append(": ")
1628 .append(Bytes.toString(ZKUtil.getData(zkw, znodeToProcess)));
1629 for (String zNodeChild : ZKUtil.listChildrenNoWatch(zkw, znodeToProcess)) {
1630 stack.add(ZKUtil.joinZNode(znodeToProcess, zNodeChild));
1631 }
1632 } while (stack.size() > 0);
1633 }
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643 public static String[] getServerStats(String server, int timeout)
1644 throws IOException {
1645 String[] sp = server.split(":");
1646 if (sp == null || sp.length == 0) {
1647 return null;
1648 }
1649
1650 String host = sp[0];
1651 int port = sp.length > 1 ? Integer.parseInt(sp[1])
1652 : HConstants.DEFAULT_ZOOKEPER_CLIENT_PORT;
1653
1654 Socket socket = new Socket();
1655 InetSocketAddress sockAddr = new InetSocketAddress(host, port);
1656 socket.connect(sockAddr, timeout);
1657
1658 socket.setSoTimeout(timeout);
1659 PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
1660 BufferedReader in = new BufferedReader(new InputStreamReader(
1661 socket.getInputStream()));
1662 out.println("stat");
1663 out.flush();
1664 ArrayList<String> res = new ArrayList<String>();
1665 while (true) {
1666 String line = in.readLine();
1667 if (line != null) {
1668 res.add(line);
1669 } else {
1670 break;
1671 }
1672 }
1673 socket.close();
1674 return res.toArray(new String[res.size()]);
1675 }
1676
1677 private static void logRetrievedMsg(final ZooKeeperWatcher zkw,
1678 final String znode, final byte [] data, final boolean watcherSet) {
1679 if (!LOG.isDebugEnabled()) return;
1680 LOG.debug(zkw.prefix("Retrieved " + ((data == null)? 0: data.length) +
1681 " byte(s) of data from znode " + znode +
1682 (watcherSet? " and set watcher; ": "; data=") +
1683 (data == null? "null": data.length == 0? "empty": (
1684 znode.startsWith(zkw.assignmentZNode)?
1685 ZKAssign.toString(data):
1686 znode.startsWith(zkw.metaServerZNode)?
1687 getServerNameOrEmptyString(data):
1688 znode.startsWith(zkw.backupMasterAddressesZNode)?
1689 getServerNameOrEmptyString(data):
1690 StringUtils.abbreviate(Bytes.toStringBinary(data), 32)))));
1691 }
1692
1693 private static String getServerNameOrEmptyString(final byte [] data) {
1694 try {
1695 return ServerName.parseFrom(data).toString();
1696 } catch (DeserializationException e) {
1697 return "";
1698 }
1699 }
1700
1701
1702
1703
1704
1705 public static void waitForBaseZNode(Configuration conf) throws IOException {
1706 LOG.info("Waiting until the base znode is available");
1707 String parentZNode = conf.get(HConstants.ZOOKEEPER_ZNODE_PARENT,
1708 HConstants.DEFAULT_ZOOKEEPER_ZNODE_PARENT);
1709 ZooKeeper zk = new ZooKeeper(ZKConfig.getZKQuorumServersString(conf),
1710 conf.getInt(HConstants.ZK_SESSION_TIMEOUT,
1711 HConstants.DEFAULT_ZK_SESSION_TIMEOUT), EmptyWatcher.instance);
1712
1713 final int maxTimeMs = 10000;
1714 final int maxNumAttempts = maxTimeMs / HConstants.SOCKET_RETRY_WAIT_MS;
1715
1716 KeeperException keeperEx = null;
1717 try {
1718 try {
1719 for (int attempt = 0; attempt < maxNumAttempts; ++attempt) {
1720 try {
1721 if (zk.exists(parentZNode, false) != null) {
1722 LOG.info("Parent znode exists: " + parentZNode);
1723 keeperEx = null;
1724 break;
1725 }
1726 } catch (KeeperException e) {
1727 keeperEx = e;
1728 }
1729 Threads.sleepWithoutInterrupt(HConstants.SOCKET_RETRY_WAIT_MS);
1730 }
1731 } finally {
1732 zk.close();
1733 }
1734 } catch (InterruptedException ex) {
1735 Thread.currentThread().interrupt();
1736 }
1737
1738 if (keeperEx != null) {
1739 throw new IOException(keeperEx);
1740 }
1741 }
1742
1743
1744 public static byte[] blockUntilAvailable(
1745 final ZooKeeperWatcher zkw, final String znode, final long timeout)
1746 throws InterruptedException {
1747 if (timeout < 0) throw new IllegalArgumentException();
1748 if (zkw == null) throw new IllegalArgumentException();
1749 if (znode == null) throw new IllegalArgumentException();
1750
1751 byte[] data = null;
1752 boolean finished = false;
1753 final long endTime = System.currentTimeMillis() + timeout;
1754 while (!finished) {
1755 try {
1756 data = ZKUtil.getData(zkw, znode);
1757 } catch(KeeperException e) {
1758 LOG.warn("Unexpected exception handling blockUntilAvailable", e);
1759 }
1760
1761 if (data == null && (System.currentTimeMillis() +
1762 HConstants.SOCKET_RETRY_WAIT_MS < endTime)) {
1763 Thread.sleep(HConstants.SOCKET_RETRY_WAIT_MS);
1764 } else {
1765 finished = true;
1766 }
1767 }
1768
1769 return data;
1770 }
1771
1772
1773
1774
1775
1776
1777
1778
1779 public static KeeperException convert(final DeserializationException e) {
1780 KeeperException ke = new KeeperException.DataInconsistencyException();
1781 ke.initCause(e);
1782 return ke;
1783 }
1784
1785
1786
1787
1788
1789
1790 public static void logZKTree(ZooKeeperWatcher zkw, String root) {
1791 if (!LOG.isDebugEnabled()) return;
1792 LOG.debug("Current zk system:");
1793 String prefix = "|-";
1794 LOG.debug(prefix + root);
1795 try {
1796 logZKTree(zkw, root, prefix);
1797 } catch (KeeperException e) {
1798 throw new RuntimeException(e);
1799 }
1800 }
1801
1802
1803
1804
1805
1806
1807 protected static void logZKTree(ZooKeeperWatcher zkw, String root, String prefix) throws KeeperException {
1808 List<String> children = ZKUtil.listChildrenNoWatch(zkw, root);
1809 if (children == null) return;
1810 for (String child : children) {
1811 LOG.debug(prefix + child);
1812 String node = ZKUtil.joinZNode(root.equals("/") ? "" : root, child);
1813 logZKTree(zkw, node, prefix + "---");
1814 }
1815 }
1816
1817 }