You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zookeeper.apache.org by ar...@apache.org on 2022/04/25 01:07:46 UTC

svn commit: r54054 [10/11] - in /dev/zookeeper/zookeeper-3.7.1-rc0: ./ website/ website/images/ website/skin/

Added: dev/zookeeper/zookeeper-3.7.1-rc0/website/zookeeperTools.html
==============================================================================
--- dev/zookeeper/zookeeper-3.7.1-rc0/website/zookeeperTools.html (added)
+++ dev/zookeeper/zookeeper-3.7.1-rc0/website/zookeeperTools.html Mon Apr 25 01:07:46 2022
@@ -0,0 +1,618 @@
+
+<!DOCTYPE html>
+<html>
+<head>
+    <META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+    <title>ZooKeeper: Because Coordinating Distributed Systems is a Zoo</title>
+    <link type="text/css" href="skin/basic.css" rel="stylesheet">
+    <link media="screen" type="text/css" href="skin/screen.css" rel="stylesheet">
+    <link media="print" type="text/css" href="skin/print.css" rel="stylesheet">
+    <link type="text/css" href="skin/profile.css" rel="stylesheet">
+    <script src="skin/getBlank.js" language="javascript" type="text/javascript"></script>
+    <script src="skin/getMenu.js" language="javascript" type="text/javascript"></script>
+    <script src="skin/init.js" language="javascript" type="text/javascript"></script>
+    <link rel="shortcut icon" href="images/favicon.ico">
+</head>
+<body onload="init();">
+<div id="top">
+    <div class="breadtrail">
+        <a href="http://www.apache.org/">Apache</a> &gt; <a href="http://zookeeper.apache.org/">ZooKeeper</a>
+    </div>
+    <div class="header">
+        <div class="projectlogo">
+            <a href="http://zookeeper.apache.org/"><img class="logoImage" alt="ZooKeeper" src="images/zookeeper_small.gif" title="ZooKeeper: distributed coordination"></a>
+        </div>
+        <div class="searchbox">
+            <form action="http://www.google.com/search" method="get">
+                <input value="zookeeper.apache.org" name="sitesearch" type="hidden"><input onFocus="getBlank (this, 'Search the site with google');" size="25" name="q" id="query" type="text" value="Search the site with google">&nbsp;
+                <input name="Search" value="Search" type="submit">
+            </form>
+        </div>
+        <ul id="tabs">
+            <li>
+                <a class="unselected" href="http://zookeeper.apache.org/">Project</a>
+            </li>
+            <li>
+                <a class="unselected" href="https://cwiki.apache.org/confluence/display/ZOOKEEPER/">Wiki</a>
+            </li>
+            <li class="current">
+                <a class="selected" href="index.html">ZooKeeper 3.7 Documentation</a>
+            </li>
+        </ul>
+    </div>
+</div>
+<div id="main">
+    <div id="publishedStrip">
+        <div id="level2tabs"></div>
+        <script type="text/javascript"><!--
+document.write("Last Published: " + document.lastModified);
+//  --></script>
+    </div>
+    <div class="breadtrail">
+        &nbsp;
+    </div>
+    <div id="menu">
+        <div onclick="SwitchMenu('menu_1', 'skin/')" id="menu_1Title" class="menutitle">Overview</div>
+        <div id="menu_1" class="menuitemgroup">
+            <div class="menuitem">
+                <a href="index.html">Welcome</a>
+            </div>
+            <div class="menuitem">
+                <a href="zookeeperOver.html">Overview</a>
+            </div>
+            <div class="menuitem">
+                <a href="zookeeperStarted.html">Getting Started</a>
+            </div>
+            <div class="menuitem">
+                <a href="releasenotes.html">Release Notes</a>
+            </div>
+        </div>
+        <div onclick="SwitchMenu('menu_2', 'skin/')" id="menu_2Title" class="menutitle">Developer</div>
+        <div id="menu_2" class="menuitemgroup">
+            <div class="menuitem">
+                <a href="apidocs/zookeeper-server/index.html">API Docs</a>
+            </div>
+            <div class="menuitem">
+                <a href="zookeeperProgrammers.html">Programmer's Guide</a>
+            </div>
+            <div class="menuitem">
+                <a href="zookeeperUseCases.html">Use Cases</a>
+            </div>
+            <div class="menuitem">
+                <a href="javaExample.html">Java Example</a>
+            </div>
+            <div class="menuitem">
+                <a href="zookeeperTutorial.html">Barrier and Queue Tutorial</a>
+            </div>
+            <div class="menuitem">
+                <a href="recipes.html">Recipes</a>
+            </div>
+        </div>
+        <div onclick="SwitchMenu('menu_3', 'skin/')" id="menu_3Title" class="menutitle">Admin &amp; Ops</div>
+        <div id="menu_3" class="menuitemgroup">
+            <div class="menuitem">
+                <a href="zookeeperAdmin.html">Administrator's Guide</a>
+            </div>
+            <div class="menuitem">
+                <a href="zookeeperQuotas.html">Quota Guide</a>
+            </div>
+            <div class="menuitem">
+                <a href="zookeeperJMX.html">JMX</a>
+            </div>
+            <div class="menuitem">
+                <a href="zookeeperHierarchicalQuorums.html">Hierarchical Quorums</a>
+            </div>
+            <div class="menuitem">
+                <a href="zookeeperObservers.html">Observers Guide</a>
+            </div>
+            <div class="menuitem">
+                <a href="zookeeperReconfig.html">Dynamic Reconfiguration</a>
+            </div>
+            <div class="menuitem">
+                <a href="zookeeperCLI.html">ZooKeeper CLI</a>
+            </div>
+            <div class="menuitem">
+                <a href="zookeeperTools.html">ZooKeeper Tools</a>
+            </div>
+            <div class="menuitem">
+                <a href="zookeeperMonitor.html">ZooKeeper Monitor</a>
+            </div>
+			<div class="menuitem">
+                <a href="zookeeperAuditLogs.html">Audit Logs</a>
+            </div>
+        </div>
+        <div onclick="SwitchMenu('menu_4', 'skin/')" id="menu_4Title" class="menutitle">Contributor</div>
+        <div id="menu_4" class="menuitemgroup">
+            <div class="menuitem">
+                <a href="zookeeperInternals.html">ZooKeeper Internals</a>
+            </div>
+        </div>
+        <div onclick="SwitchMenu('menu_5', 'skin/')" id="menu_5Title" class="menutitle">Miscellaneous</div>
+        <div id="menu_5" class="menuitemgroup">
+            <div class="menuitem">
+                <a href="https://cwiki.apache.org/confluence/display/ZOOKEEPER">Wiki</a>
+            </div>
+            <div class="menuitem">
+                <a href="https://cwiki.apache.org/confluence/display/ZOOKEEPER/FAQ">FAQ</a>
+            </div>
+            <div class="menuitem">
+                <a href="http://zookeeper.apache.org/mailing_lists.html">Mailing Lists</a>
+            </div>
+        </div>
+    </div>
+    <div id="content">
+<!--
+Copyright 2002-2021 The Apache Software Foundation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+//-->
+<h1>A series of tools for ZooKeeper</h1>
+<ul>
+<li>
+<p><a href="#Scripts">Scripts</a></p>
+<ul>
+<li><a href="#zkServer">zkServer.sh</a></li>
+<li><a href="#zkCli">zkCli.sh</a></li>
+<li><a href="#zkEnv">zkEnv.sh</a></li>
+<li><a href="#zkCleanup">zkCleanup.sh</a></li>
+<li><a href="#zkTxnLogToolkit">zkTxnLogToolkit.sh</a></li>
+<li><a href="#zkSnapShotToolkit">zkSnapShotToolkit.sh</a></li>
+<li><a href="#zkSnapshotComparer">zkSnapshotComparer.sh</a></li>
+</ul>
+</li>
+<li>
+<p><a href="#Benchmark">Benchmark</a></p>
+<ul>
+<li><a href="#YCSB">YCSB</a></li>
+<li><a href="#zk-smoketest">zk-smoketest</a></li>
+</ul>
+</li>
+<li>
+<p><a href="#Testing">Testing</a></p>
+<ul>
+<li><a href="#jepsen-test">Jepsen Test</a></li>
+</ul>
+</li>
+</ul>
+<p><a name="Scripts"></a></p>
+<h2>Scripts</h2>
+<p><a name="zkServer"></a></p>
+<h3>zkServer.sh</h3>
+<p>A command for the operations for the ZooKeeper server.</p>
+<pre><code class="language-bash">Usage: ./zkServer.sh {start|start-foreground|stop|version|restart|status|upgrade|print-cmd}
+# start the server
+./zkServer.sh start
+
+# start the server in the foreground for debugging
+./zkServer.sh start-foreground
+
+# stop the server
+./zkServer.sh stop
+
+# restart the server
+./zkServer.sh restart
+
+# show the status,mode,role of the server
+./zkServer.sh status
+JMX enabled by default
+Using config: /data/software/zookeeper/conf/zoo.cfg
+Mode: standalone
+
+# Deprecated
+./zkServer.sh upgrade
+
+# print the parameters of the start-up
+./zkServer.sh print-cmd
+
+# show the version of the ZooKeeper server
+./zkServer.sh version
+Apache ZooKeeper, version 3.6.0-SNAPSHOT 06/11/2019 05:39 GMT
+
+</code></pre>
+<p>The <code>status</code> command establishes a client connection to the server to execute diagnostic commands. When the ZooKeeper cluster is started in client SSL only mode (by omitting the clientPort from the zoo.cfg), then additional SSL related configuration has to be provided before using the <code>./zkServer.sh status</code> command to find out if the ZooKeeper server is running. An example:</p>
+<pre><code>CLIENT_JVMFLAGS=&quot;-Dzookeeper.clientCnxnSocket=org.apache.zookeeper.ClientCnxnSocketNetty -Dzookeeper.ssl.trustStore.location=/tmp/clienttrust.jks -Dzookeeper.ssl.trustStore.password=password -Dzookeeper.ssl.keyStore.location=/tmp/client.jks -Dzookeeper.ssl.keyStore.password=password -Dzookeeper.client.secure=true&quot; ./zkServer.sh status
+</code></pre>
+<p><a name="zkCli"></a></p>
+<h3>zkCli.sh</h3>
+<p>Look at the <a href="zookeeperCLI.html">ZooKeeperCLI</a></p>
+<p><a name="zkEnv"></a></p>
+<h3>zkEnv.sh</h3>
+<p>The environment setting for the ZooKeeper server</p>
+<pre><code class="language-bash"># the setting of log property
+ZOO_LOG_DIR: the directory to store the logs
+ZOO_LOG4J_PROP: the level of logs to print
+</code></pre>
+<p><a name="zkCleanup"></a></p>
+<h3>zkCleanup.sh</h3>
+<p>Clean up the old snapshots and transaction logs.</p>
+<pre><code class="language-bash">Usage:
+     * args dataLogDir [snapDir] -n count
+     * dataLogDir -- path to the txn log directory
+     * snapDir -- path to the snapshot directory
+     * count -- the number of old snaps/logs you want to keep, value should be greater than or equal to 3
+# Keep the latest 5 logs and snapshots
+./zkCleanup.sh -n 5
+</code></pre>
+<p><a name="zkTxnLogToolkit"></a></p>
+<h3>zkTxnLogToolkit.sh</h3>
+<p>TxnLogToolkit is a command line tool shipped with ZooKeeper which is capable of recovering transaction log entries with broken CRC.</p>
+<p>Running it without any command line parameters or with the <code>-h,--help</code> argument, it outputs the following help page:</p>
+<pre><code>$ bin/zkTxnLogToolkit.sh
+usage: TxnLogToolkit [-dhrv] txn_log_file_name
+-d,--dump      Dump mode. Dump all entries of the log file. (this is the default)
+-h,--help      Print help message
+-r,--recover   Recovery mode. Re-calculate CRC for broken entries.
+-v,--verbose   Be verbose in recovery mode: print all entries, not just fixed ones.
+-y,--yes       Non-interactive mode: repair all CRC errors without asking
+</code></pre>
+<p>The default behaviour is safe: it dumps the entries of the given transaction log file to the screen: (same as using <code>-d,--dump</code> parameter)</p>
+<pre><code>$ bin/zkTxnLogToolkit.sh log.100000001
+ZooKeeper Transactional Log File with dbid 0 txnlog format version 2
+4/5/18 2:15:58 PM CEST session 0x16295bafcc40000 cxid 0x0 zxid 0x100000001 createSession 30000
+CRC ERROR - 4/5/18 2:16:05 PM CEST session 0x16295bafcc40000 cxid 0x1 zxid 0x100000002 closeSession null
+4/5/18 2:16:05 PM CEST session 0x16295bafcc40000 cxid 0x1 zxid 0x100000002 closeSession null
+4/5/18 2:16:12 PM CEST session 0x26295bafcc90000 cxid 0x0 zxid 0x100000003 createSession 30000
+4/5/18 2:17:34 PM CEST session 0x26295bafcc90000 cxid 0x0 zxid 0x200000001 closeSession null
+4/5/18 2:17:34 PM CEST session 0x16295bd23720000 cxid 0x0 zxid 0x200000002 createSession 30000
+4/5/18 2:18:02 PM CEST session 0x16295bd23720000 cxid 0x2 zxid 0x200000003 create '/andor,#626262,v{s{31,s{'world,'anyone}}},F,1
+EOF reached after 6 txns.
+</code></pre>
+<p>There's a CRC error in the 2nd entry of the above transaction log file. In <strong>dump</strong> mode, the toolkit only prints this information to the screen without touching the original file. In <strong>recovery</strong> mode (<code>-r,--recover</code> flag) the original file still remains untouched and all transactions will be copied over to a new txn log file with &quot;.fixed&quot; suffix. It recalculates CRC values and copies the calculated value, if it doesn't match the original txn entry. By default, the tool works interactively: it asks for confirmation whenever CRC error encountered.</p>
+<pre><code>$ bin/zkTxnLogToolkit.sh -r log.100000001
+ZooKeeper Transactional Log File with dbid 0 txnlog format version 2
+CRC ERROR - 4/5/18 2:16:05 PM CEST session 0x16295bafcc40000 cxid 0x1 zxid 0x100000002 closeSession null
+Would you like to fix it (Yes/No/Abort) ?
+</code></pre>
+<p>Answering <strong>Yes</strong> means the newly calculated CRC value will be outputted to the new file. <strong>No</strong> means that the original CRC value will be copied over. <strong>Abort</strong> will abort the entire operation and exits. (In this case the &quot;.fixed&quot; will not be deleted and left in a half-complete state: contains only entries which have already been processed or only the header if the operation was aborted at the first entry.)</p>
+<pre><code>$ bin/zkTxnLogToolkit.sh -r log.100000001
+ZooKeeper Transactional Log File with dbid 0 txnlog format version 2
+CRC ERROR - 4/5/18 2:16:05 PM CEST session 0x16295bafcc40000 cxid 0x1 zxid 0x100000002 closeSession null
+Would you like to fix it (Yes/No/Abort) ? y
+EOF reached after 6 txns.
+Recovery file log.100000001.fixed has been written with 1 fixed CRC error(s)
+</code></pre>
+<p>The default behaviour of recovery is to be silent: only entries with CRC error get printed to the screen. One can turn on verbose mode with the <code>-v,--verbose</code> parameter to see all records. Interactive mode can be turned off with the <code>-y,--yes</code> parameter. In this case all CRC errors will be fixed in the new transaction file.</p>
+<p><a name="zkSnapShotToolkit"></a></p>
+<h3>zkSnapShotToolkit.sh</h3>
+<p>Dump a snapshot file to stdout, showing the detailed information of the each zk-node.</p>
+<pre><code class="language-bash"># help
+./zkSnapShotToolkit.sh
+/usr/bin/java
+USAGE: SnapshotFormatter [-d|-json] snapshot_file
+       -d dump the data for each znode
+       -json dump znode info in json format
+
+# show the each zk-node info without data content
+./zkSnapShotToolkit.sh /data/zkdata/version-2/snapshot.fa01000186d
+/zk-latencies_4/session_946
+  cZxid = 0x00000f0003110b
+  ctime = Wed Sep 19 21:58:22 CST 2018
+  mZxid = 0x00000f0003110b
+  mtime = Wed Sep 19 21:58:22 CST 2018
+  pZxid = 0x00000f0003110b
+  cversion = 0
+  dataVersion = 0
+  aclVersion = 0
+  ephemeralOwner = 0x00000000000000
+  dataLength = 100
+
+# [-d] show the each zk-node info with data content
+./zkSnapShotToolkit.sh -d /data/zkdata/version-2/snapshot.fa01000186d
+/zk-latencies2/session_26229
+  cZxid = 0x00000900007ba0
+  ctime = Wed Aug 15 20:13:52 CST 2018
+  mZxid = 0x00000900007ba0
+  mtime = Wed Aug 15 20:13:52 CST 2018
+  pZxid = 0x00000900007ba0
+  cversion = 0
+  dataVersion = 0
+  aclVersion = 0
+  ephemeralOwner = 0x00000000000000
+  data = eHh4eHh4eHh4eHh4eA==
+
+# [-json] show the each zk-node info with json format
+./zkSnapShotToolkit.sh -json /data/zkdata/version-2/snapshot.fa01000186d
+[[1,0,{&quot;progname&quot;:&quot;SnapshotFormatter.java&quot;,&quot;progver&quot;:&quot;0.01&quot;,&quot;timestamp&quot;:1559788148637},[{&quot;name&quot;:&quot;\/&quot;,&quot;asize&quot;:0,&quot;dsize&quot;:0,&quot;dev&quot;:0,&quot;ino&quot;:1001},[{&quot;name&quot;:&quot;zookeeper&quot;,&quot;asize&quot;:0,&quot;dsize&quot;:0,&quot;dev&quot;:0,&quot;ino&quot;:1002},{&quot;name&quot;:&quot;config&quot;,&quot;asize&quot;:0,&quot;dsize&quot;:0,&quot;dev&quot;:0,&quot;ino&quot;:1003},[{&quot;name&quot;:&quot;quota&quot;,&quot;asize&quot;:0,&quot;dsize&quot;:0,&quot;dev&quot;:0,&quot;ino&quot;:1004},[{&quot;name&quot;:&quot;test&quot;,&quot;asize&quot;:0,&quot;dsize&quot;:0,&quot;dev&quot;:0,&quot;ino&quot;:1005},{&quot;name&quot;:&quot;zookeeper_limits&quot;,&quot;asize&quot;:52,&quot;dsize&quot;:52,&quot;dev&quot;:0,&quot;ino&quot;:1006},{&quot;name&quot;:&quot;zookeeper_stats&quot;,&quot;asize&quot;:15,&quot;dsize&quot;:15,&quot;dev&quot;:0,&quot;ino&quot;:1007}]]],{&quot;name&quo
 t;:&quot;test&quot;,&quot;asize&quot;:0,&quot;dsize&quot;:0,&quot;dev&quot;:0,&quot;ino&quot;:1008}]]
+</code></pre>
+<p><a name="zkSnapshotComparer"></a></p>
+<h3>zkSnapshotComparer.sh</h3>
+<p>SnapshotComparer is a tool that loads and compares two snapshots with configurable threshold and various filters, and outputs information about the delta.</p>
+<p>The delta includes specific znode paths added, updated, deleted comparing one snapshot to another.</p>
+<p>It's useful in use cases that involve snapshot analysis, such as offline data consistency checking, and data trending analysis (e.g. what's growing under which zNode path during when).</p>
+<p>This tool only outputs information about permanent nodes, ignoring both sessions and ephemeral nodes.</p>
+<p>It provides two tuning parameters to help filter out noise: 1. <code>--nodes</code> Threshold number of children added/removed; 2. <code>--bytes</code> Threshold number of bytes added/removed.</p>
+<h4>Locate Snapshots</h4>
+<p>Snapshots can be found in <a href="zookeeperAdmin.html#The+Data+Directory">Zookeeper Data Directory</a> which configured in <a href="zookeeperStarted.html#sc_InstallingSingleMode">conf/zoo.cfg</a> when set up Zookeeper server.</p>
+<h4>Supported Snapshot Formats</h4>
+<p>This tool supports uncompressed snapshot format, and compressed snapshot file formats: <code>snappy</code> and <code>gz</code>. Snapshots with different formats can be compared using this tool directly without decompression.</p>
+<h4>Running the Tool</h4>
+<p>Running the tool with no command line argument or an unrecognized argument, it outputs the following help page:</p>
+<pre><code>usage: java -cp &lt;classPath&gt; org.apache.zookeeper.server.SnapshotComparer
+ -b,--bytes &lt;BYTETHRESHOLD&gt;   (Required) The node data delta size threshold, in bytes, for printing the node.
+ -d,--debug                   Use debug output.
+ -i,--interactive             Enter interactive mode.
+ -l,--left &lt;LEFT&gt;             (Required) The left snapshot file.
+ -n,--nodes &lt;NODETHRESHOLD&gt;   (Required) The descendant node delta size threshold, in nodes, for printing the node.
+ -r,--right &lt;RIGHT&gt;           (Required) The right snapshot file.
+</code></pre>
+<p>Example Command:</p>
+<pre><code>./bin/zkSnapshotComparer.sh -l /zookeeper-data/backup/snapshot.d.snappy -r /zookeeper-data/backup/snapshot.44 -b 2 -n 1
+</code></pre>
+<p>Example Output:</p>
+<pre><code>...
+Deserialized snapshot in snapshot.44 in 0.002741 seconds
+Processed data tree in 0.000361 seconds
+Node count: 10
+Total size: 0
+Max depth: 4
+Count of nodes at depth 0: 1
+Count of nodes at depth 1: 2
+Count of nodes at depth 2: 4
+Count of nodes at depth 3: 3
+
+Node count: 22
+Total size: 2903
+Max depth: 5
+Count of nodes at depth 0: 1
+Count of nodes at depth 1: 2
+Count of nodes at depth 2: 4
+Count of nodes at depth 3: 7
+Count of nodes at depth 4: 8
+
+Printing analysis for nodes difference larger than 2 bytes or node count difference larger than 1.
+Analysis for depth 0
+Node  found in both trees. Delta: 2903 bytes, 12 descendants
+Analysis for depth 1
+Node /zk_test found in both trees. Delta: 2903 bytes, 12 descendants
+Analysis for depth 2
+Node /zk_test/gz found in both trees. Delta: 730 bytes, 3 descendants
+Node /zk_test/snappy found in both trees. Delta: 2173 bytes, 9 descendants
+Analysis for depth 3
+Node /zk_test/gz/12345 found in both trees. Delta: 9 bytes, 1 descendants
+Node /zk_test/gz/a found only in right tree. Descendant size: 721. Descendant count: 0
+Node /zk_test/snappy/anotherTest found in both trees. Delta: 1738 bytes, 2 descendants
+Node /zk_test/snappy/test_1 found only in right tree. Descendant size: 344. Descendant count: 3
+Node /zk_test/snappy/test_2 found only in right tree. Descendant size: 91. Descendant count: 2
+Analysis for depth 4
+Node /zk_test/gz/12345/abcdef found only in right tree. Descendant size: 9. Descendant count: 0
+Node /zk_test/snappy/anotherTest/abc found only in right tree. Descendant size: 1738. Descendant count: 0
+Node /zk_test/snappy/test_1/a found only in right tree. Descendant size: 93. Descendant count: 0
+Node /zk_test/snappy/test_1/b found only in right tree. Descendant size: 251. Descendant count: 0
+Node /zk_test/snappy/test_2/xyz found only in right tree. Descendant size: 33. Descendant count: 0
+Node /zk_test/snappy/test_2/y found only in right tree. Descendant size: 58. Descendant count: 0
+All layers compared.
+</code></pre>
+<h4>Interactive Mode</h4>
+<p>Use &quot;-i&quot; or &quot;--interactive&quot; to enter interactive mode:</p>
+<pre><code>./bin/zkSnapshotComparer.sh -l /zookeeper-data/backup/snapshot.d.snappy -r /zookeeper-data/backup/snapshot.44 -b 2 -n 1 -i
+</code></pre>
+<p>There are three options to proceed:</p>
+<pre><code>- Press enter to move to print current depth layer;
+- Type a number to jump to and print all nodes at a given depth;
+- Enter an ABSOLUTE path to print the immediate subtree of a node. Path must start with '/'.
+</code></pre>
+<p>Note: As indicated by the interactive messages, the tool only shows analysis on the result that filtered by tuning parameters bytes threshold and nodes threshold.</p>
+<p>Press enter to print current depth layer:</p>
+<pre><code>Current depth is 0
+Press enter to move to print current depth layer;
+...
+Printing analysis for nodes difference larger than 2 bytes or node count difference larger than 1.
+Analysis for depth 0
+Node  found in both trees. Delta: 2903 bytes, 12 descendants
+</code></pre>
+<p>Type a number to jump to and print all nodes at a given depth:</p>
+<p>(Jump forward)</p>
+<pre><code>Current depth is 1
+...
+Type a number to jump to and print all nodes at a given depth;
+...
+3
+Printing analysis for nodes difference larger than 2 bytes or node count difference larger than 1.
+Analysis for depth 3
+Node /zk_test/gz/12345 found in both trees. Delta: 9 bytes, 1 descendants
+Node /zk_test/gz/a found only in right tree. Descendant size: 721. Descendant count: 0
+Filtered node /zk_test/gz/anotherOne of left size 0, right size 0
+Filtered right node /zk_test/gz/b of size 0
+Node /zk_test/snappy/anotherTest found in both trees. Delta: 1738 bytes, 2 descendants
+Node /zk_test/snappy/test_1 found only in right tree. Descendant size: 344. Descendant count: 3
+Node /zk_test/snappy/test_2 found only in right tree. Descendant size: 91. Descendant count: 2
+</code></pre>
+<p>(Jump back)</p>
+<pre><code>Current depth is 3
+...
+Type a number to jump to and print all nodes at a given depth;
+...
+0
+Printing analysis for nodes difference larger than 2 bytes or node count difference larger than 1.
+Analysis for depth 0
+Node  found in both trees. Delta: 2903 bytes, 12 descendants
+</code></pre>
+<p>Out of range depth is handled:</p>
+<pre><code>Current depth is 1
+...
+Type a number to jump to and print all nodes at a given depth;
+...
+10
+Printing analysis for nodes difference larger than 2 bytes or node count difference larger than 1.
+Depth must be in range [0, 4]
+</code></pre>
+<p>Enter an ABSOLUTE path to print the immediate subtree of a node:</p>
+<pre><code>Current depth is 3
+...
+Enter an ABSOLUTE path to print the immediate subtree of a node.
+/zk_test
+Printing analysis for nodes difference larger than 2 bytes or node count difference larger than 1.
+Analysis for node /zk_test
+Node /zk_test/gz found in both trees. Delta: 730 bytes, 3 descendants
+Node /zk_test/snappy found in both trees. Delta: 2173 bytes, 9 descendants
+</code></pre>
+<p>Invalid path is handled:</p>
+<pre><code>Current depth is 3
+...
+Enter an ABSOLUTE path to print the immediate subtree of a node.
+/non-exist-path
+Printing analysis for nodes difference larger than 2 bytes or node count difference larger than 1.
+Analysis for node /non-exist-path
+Path /non-exist-path is neither found in left tree nor right tree.
+</code></pre>
+<p>Invalid input is handled:</p>
+<pre><code>Current depth is 1
+- Press enter to move to print current depth layer;
+- Type a number to jump to and print all nodes at a given depth;
+- Enter an ABSOLUTE path to print the immediate subtree of a node. Path must start with '/'.
+12223999999999999999999999999999999999999
+Printing analysis for nodes difference larger than 2 bytes or node count difference larger than 1.
+Input 12223999999999999999999999999999999999999 is not valid. Depth must be in range [0, 4]. Path must be an absolute path which starts with '/'.
+</code></pre>
+<p>Exit interactive mode automatically when all layers are compared:</p>
+<pre><code>Printing analysis for nodes difference larger than 2 bytes or node count difference larger than 1.
+Analysis for depth 4
+Node /zk_test/gz/12345/abcdef found only in right tree. Descendant size: 9. Descendant count: 0
+Node /zk_test/snappy/anotherTest/abc found only in right tree. Descendant size: 1738. Descendant count: 0
+Filtered right node /zk_test/snappy/anotherTest/abcd of size 0
+Node /zk_test/snappy/test_1/a found only in right tree. Descendant size: 93. Descendant count: 0
+Node /zk_test/snappy/test_1/b found only in right tree. Descendant size: 251. Descendant count: 0
+Filtered right node /zk_test/snappy/test_1/c of size 0
+Node /zk_test/snappy/test_2/xyz found only in right tree. Descendant size: 33. Descendant count: 0
+Node /zk_test/snappy/test_2/y found only in right tree. Descendant size: 58. Descendant count: 0
+All layers compared.
+</code></pre>
+<p>Or use <code>^c</code> to exit interactive mode anytime.</p>
+<p><a name="Benchmark"></a></p>
+<h2>Benchmark</h2>
+<p><a name="YCSB"></a></p>
+<h3>YCSB</h3>
+<h4>Quick Start</h4>
+<p>This section describes how to run YCSB on ZooKeeper.</p>
+<h4>1. Start ZooKeeper Server(s)</h4>
+<h4>2. Install Java and Maven</h4>
+<h4>3. Set Up YCSB</h4>
+<p>Git clone YCSB and compile:</p>
+<pre><code>git clone http://github.com/brianfrankcooper/YCSB.git
+# more details in the landing page for instructions on downloading YCSB(https://github.com/brianfrankcooper/YCSB#getting-started).
+cd YCSB
+mvn -pl site.ycsb:zookeeper-binding -am clean package -DskipTests
+</code></pre>
+<h4>4. Provide ZooKeeper Connection Parameters</h4>
+<p>Set connectString, sessionTimeout, watchFlag in the workload you plan to run.</p>
+<ul>
+<li><code>zookeeper.connectString</code></li>
+<li><code>zookeeper.sessionTimeout</code></li>
+<li><code>zookeeper.watchFlag</code></li>
+<li>A parameter for enabling ZooKeeper's watch, optional values:true or false.the default value is false.</li>
+<li>This parameter cannot test the watch performance, but for testing what effect will take on the read/write requests when enabling the watch.
+<pre><code class="language-bash">./bin/ycsb run zookeeper -s -P workloads/workloadb -p zookeeper.connectString=127.0.0.1:2181/benchmark -p zookeeper.watchFlag=true
+</code></pre>
+</li>
+</ul>
+<p>Or, you can set configs with the shell command, EG:</p>
+<pre><code># create a /benchmark namespace for sake of cleaning up the workspace after test.
+# e.g the CLI:create /benchmark
+./bin/ycsb run zookeeper -s -P workloads/workloadb -p zookeeper.connectString=127.0.0.1:2181/benchmark -p zookeeper.sessionTimeout=30000
+</code></pre>
+<h4>5. Load data and run tests</h4>
+<p>Load the data:</p>
+<pre><code># -p recordcount,the count of records/paths you want to insert
+./bin/ycsb load zookeeper -s -P workloads/workloadb -p zookeeper.connectString=127.0.0.1:2181/benchmark -p recordcount=10000 &gt; outputLoad.txt
+</code></pre>
+<p>Run the workload test:</p>
+<pre><code># YCSB workloadb is the most suitable workload for read-heavy workload for the ZooKeeper in the real world.
+
+# -p fieldlength, test the length of value/data-content took effect on performance
+./bin/ycsb run zookeeper -s -P workloads/workloadb -p zookeeper.connectString=127.0.0.1:2181/benchmark -p fieldlength=1000
+
+# -p fieldcount
+./bin/ycsb run zookeeper -s -P workloads/workloadb -p zookeeper.connectString=127.0.0.1:2181/benchmark -p fieldcount=20
+
+# -p hdrhistogram.percentiles,show the hdrhistogram benchmark result
+./bin/ycsb run zookeeper -threads 1 -P workloads/workloadb -p zookeeper.connectString=127.0.0.1:2181/benchmark -p hdrhistogram.percentiles=10,25,50,75,90,95,99,99.9 -p histogram.buckets=500
+
+# -threads: multi-clients test, increase the **maxClientCnxns** in the zoo.cfg to handle more connections.
+./bin/ycsb run zookeeper -threads 10 -P workloads/workloadb -p zookeeper.connectString=127.0.0.1:2181/benchmark
+
+# show the timeseries benchmark result
+./bin/ycsb run zookeeper -threads 1 -P workloads/workloadb -p zookeeper.connectString=127.0.0.1:2181/benchmark -p measurementtype=timeseries -p timeseries.granularity=50
+
+# cluster test
+./bin/ycsb run zookeeper -P workloads/workloadb -p zookeeper.connectString=192.168.10.43:2181,192.168.10.45:2181,192.168.10.27:2181/benchmark
+
+# test leader's read/write performance by setting zookeeper.connectString to leader's(192.168.10.43:2181)
+./bin/ycsb run zookeeper -P workloads/workloadb -p zookeeper.connectString=192.168.10.43:2181/benchmark
+
+# test for large znode(by default: jute.maxbuffer is 1048575 bytes/1 MB ). Notice:jute.maxbuffer should also be set the same value in all the zk servers.
+./bin/ycsb run zookeeper -jvm-args=&quot;-Djute.maxbuffer=4194304&quot; -s -P workloads/workloadc -p zookeeper.connectString=127.0.0.1:2181/benchmark
+
+# Cleaning up the workspace after finishing the benchmark.
+# e.g the CLI:deleteall /benchmark
+</code></pre>
+<p><a name="zk-smoketest"></a></p>
+<h3>zk-smoketest</h3>
+<p><strong>zk-smoketest</strong> provides a simple smoketest client for a ZooKeeper ensemble. Useful for verifying new, updated, existing installations. More details are <a href="https://github.com/phunt/zk-smoketest">here</a>.</p>
+<p><a name="Testing"></a></p>
+<h2>Testing</h2>
+<p><a name="jepsen-test"></a></p>
+<h3>Jepsen Test</h3>
+<p>A framework for distributed systems verification, with fault injection. Jepsen has been used to verify everything from eventually-consistent commutative databases to linearizable coordination systems to distributed task schedulers. more details can be found in <a href="https://github.com/jepsen-io/jepsen">jepsen-io</a></p>
+<p>Running the <a href="https://github.com/jepsen-io/jepsen/blob/master/docker/README.md">Dockerized Jepsen</a> is the simplest way to use the Jepsen.</p>
+<p>Installation:</p>
+<pre><code class="language-bash">git clone git@github.com:jepsen-io/jepsen.git
+cd docker
+# maybe a long time for the first init.
+./up.sh
+# docker ps to check one control node and five db nodes are up
+docker ps
+     CONTAINER ID        IMAGE               COMMAND                 CREATED             STATUS              PORTS                     NAMES
+     8265f1d3f89c        docker_control      &quot;/bin/sh -c /init.sh&quot;   9 hours ago         Up 4 hours          0.0.0.0:32769-&gt;8080/tcp   jepsen-control
+     8a646102da44        docker_n5           &quot;/run.sh&quot;               9 hours ago         Up 3 hours          22/tcp                    jepsen-n5
+     385454d7e520        docker_n1           &quot;/run.sh&quot;               9 hours ago         Up 9 hours          22/tcp                    jepsen-n1
+     a62d6a9d5f8e        docker_n2           &quot;/run.sh&quot;               9 hours ago         Up 9 hours          22/tcp                    jepsen-n2
+     1485e89d0d9a        docker_n3           &quot;/run.sh&quot;               9 hours ago         Up 9 hours          22/tcp                    jepsen-n3
+     27ae01e1a0c5        docker_node         &quot;/run.sh&quot;               9 hours ago         Up 9 hours          22/tcp                    jepsen-node
+     53c444b00ebd        docker_n4           &quot;/run.sh&quot;               9 hours ago         Up 9 hours          22/tcp                    jepsen-n4
+</code></pre>
+<p>Running &amp; Test</p>
+<pre><code class="language-bash"># Enter into the container:jepsen-control
+docker exec -it jepsen-control bash
+# Test
+cd zookeeper &amp;&amp; lein run test --concurrency 10
+# See something like the following to assert that ZooKeeper has passed the Jepsen test
+INFO [2019-04-01 11:25:23,719] jepsen worker 8 - jepsen.util 8	:ok	:read	2
+INFO [2019-04-01 11:25:23,722] jepsen worker 3 - jepsen.util 3	:invoke	:cas	[0 4]
+INFO [2019-04-01 11:25:23,760] jepsen worker 3 - jepsen.util 3	:fail	:cas	[0 4]
+INFO [2019-04-01 11:25:23,791] jepsen worker 1 - jepsen.util 1	:invoke	:read	nil
+INFO [2019-04-01 11:25:23,794] jepsen worker 1 - jepsen.util 1	:ok	:read	2
+INFO [2019-04-01 11:25:24,038] jepsen worker 0 - jepsen.util 0	:invoke	:write	4
+INFO [2019-04-01 11:25:24,073] jepsen worker 0 - jepsen.util 0	:ok	:write	4
+...............................................................................
+Everything looks good! ヽ(‘ー`)ノ
+
+</code></pre>
+<p>Reference: read <a href="https://aphyr.com/posts/291-call-me-maybe-zookeeper">this blog</a> to learn more about the Jepsen test for the Zookeeper.</p>
+</div>
+<div class="clearboth">&nbsp;</div>
+</div>
+<div id="footer">
+    <div class="lastmodified">
+        <script type="text/javascript">
+        <!--
+            document.write("Last Published: " + document.lastModified);
+        //  -->
+        </script>
+    </div>
+    <div class="copyright">
+        Copyright &copy; <a href="http://www.apache.org/licenses/">The Apache Software Foundation.</a>
+    </div>
+    <div id="logos"></div>
+</div>
+</body>
+</html>
\ No newline at end of file

Added: dev/zookeeper/zookeeper-3.7.1-rc0/website/zookeeperTutorial.html
==============================================================================
--- dev/zookeeper/zookeeper-3.7.1-rc0/website/zookeeperTutorial.html (added)
+++ dev/zookeeper/zookeeper-3.7.1-rc0/website/zookeeperTutorial.html Mon Apr 25 01:07:46 2022
@@ -0,0 +1,730 @@
+
+<!DOCTYPE html>
+<html>
+<head>
+    <META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+    <title>ZooKeeper: Because Coordinating Distributed Systems is a Zoo</title>
+    <link type="text/css" href="skin/basic.css" rel="stylesheet">
+    <link media="screen" type="text/css" href="skin/screen.css" rel="stylesheet">
+    <link media="print" type="text/css" href="skin/print.css" rel="stylesheet">
+    <link type="text/css" href="skin/profile.css" rel="stylesheet">
+    <script src="skin/getBlank.js" language="javascript" type="text/javascript"></script>
+    <script src="skin/getMenu.js" language="javascript" type="text/javascript"></script>
+    <script src="skin/init.js" language="javascript" type="text/javascript"></script>
+    <link rel="shortcut icon" href="images/favicon.ico">
+</head>
+<body onload="init();">
+<div id="top">
+    <div class="breadtrail">
+        <a href="http://www.apache.org/">Apache</a> &gt; <a href="http://zookeeper.apache.org/">ZooKeeper</a>
+    </div>
+    <div class="header">
+        <div class="projectlogo">
+            <a href="http://zookeeper.apache.org/"><img class="logoImage" alt="ZooKeeper" src="images/zookeeper_small.gif" title="ZooKeeper: distributed coordination"></a>
+        </div>
+        <div class="searchbox">
+            <form action="http://www.google.com/search" method="get">
+                <input value="zookeeper.apache.org" name="sitesearch" type="hidden"><input onFocus="getBlank (this, 'Search the site with google');" size="25" name="q" id="query" type="text" value="Search the site with google">&nbsp;
+                <input name="Search" value="Search" type="submit">
+            </form>
+        </div>
+        <ul id="tabs">
+            <li>
+                <a class="unselected" href="http://zookeeper.apache.org/">Project</a>
+            </li>
+            <li>
+                <a class="unselected" href="https://cwiki.apache.org/confluence/display/ZOOKEEPER/">Wiki</a>
+            </li>
+            <li class="current">
+                <a class="selected" href="index.html">ZooKeeper 3.7 Documentation</a>
+            </li>
+        </ul>
+    </div>
+</div>
+<div id="main">
+    <div id="publishedStrip">
+        <div id="level2tabs"></div>
+        <script type="text/javascript"><!--
+document.write("Last Published: " + document.lastModified);
+//  --></script>
+    </div>
+    <div class="breadtrail">
+        &nbsp;
+    </div>
+    <div id="menu">
+        <div onclick="SwitchMenu('menu_1', 'skin/')" id="menu_1Title" class="menutitle">Overview</div>
+        <div id="menu_1" class="menuitemgroup">
+            <div class="menuitem">
+                <a href="index.html">Welcome</a>
+            </div>
+            <div class="menuitem">
+                <a href="zookeeperOver.html">Overview</a>
+            </div>
+            <div class="menuitem">
+                <a href="zookeeperStarted.html">Getting Started</a>
+            </div>
+            <div class="menuitem">
+                <a href="releasenotes.html">Release Notes</a>
+            </div>
+        </div>
+        <div onclick="SwitchMenu('menu_2', 'skin/')" id="menu_2Title" class="menutitle">Developer</div>
+        <div id="menu_2" class="menuitemgroup">
+            <div class="menuitem">
+                <a href="apidocs/zookeeper-server/index.html">API Docs</a>
+            </div>
+            <div class="menuitem">
+                <a href="zookeeperProgrammers.html">Programmer's Guide</a>
+            </div>
+            <div class="menuitem">
+                <a href="zookeeperUseCases.html">Use Cases</a>
+            </div>
+            <div class="menuitem">
+                <a href="javaExample.html">Java Example</a>
+            </div>
+            <div class="menuitem">
+                <a href="zookeeperTutorial.html">Barrier and Queue Tutorial</a>
+            </div>
+            <div class="menuitem">
+                <a href="recipes.html">Recipes</a>
+            </div>
+        </div>
+        <div onclick="SwitchMenu('menu_3', 'skin/')" id="menu_3Title" class="menutitle">Admin &amp; Ops</div>
+        <div id="menu_3" class="menuitemgroup">
+            <div class="menuitem">
+                <a href="zookeeperAdmin.html">Administrator's Guide</a>
+            </div>
+            <div class="menuitem">
+                <a href="zookeeperQuotas.html">Quota Guide</a>
+            </div>
+            <div class="menuitem">
+                <a href="zookeeperJMX.html">JMX</a>
+            </div>
+            <div class="menuitem">
+                <a href="zookeeperHierarchicalQuorums.html">Hierarchical Quorums</a>
+            </div>
+            <div class="menuitem">
+                <a href="zookeeperObservers.html">Observers Guide</a>
+            </div>
+            <div class="menuitem">
+                <a href="zookeeperReconfig.html">Dynamic Reconfiguration</a>
+            </div>
+            <div class="menuitem">
+                <a href="zookeeperCLI.html">ZooKeeper CLI</a>
+            </div>
+            <div class="menuitem">
+                <a href="zookeeperTools.html">ZooKeeper Tools</a>
+            </div>
+            <div class="menuitem">
+                <a href="zookeeperMonitor.html">ZooKeeper Monitor</a>
+            </div>
+			<div class="menuitem">
+                <a href="zookeeperAuditLogs.html">Audit Logs</a>
+            </div>
+        </div>
+        <div onclick="SwitchMenu('menu_4', 'skin/')" id="menu_4Title" class="menutitle">Contributor</div>
+        <div id="menu_4" class="menuitemgroup">
+            <div class="menuitem">
+                <a href="zookeeperInternals.html">ZooKeeper Internals</a>
+            </div>
+        </div>
+        <div onclick="SwitchMenu('menu_5', 'skin/')" id="menu_5Title" class="menutitle">Miscellaneous</div>
+        <div id="menu_5" class="menuitemgroup">
+            <div class="menuitem">
+                <a href="https://cwiki.apache.org/confluence/display/ZOOKEEPER">Wiki</a>
+            </div>
+            <div class="menuitem">
+                <a href="https://cwiki.apache.org/confluence/display/ZOOKEEPER/FAQ">FAQ</a>
+            </div>
+            <div class="menuitem">
+                <a href="http://zookeeper.apache.org/mailing_lists.html">Mailing Lists</a>
+            </div>
+        </div>
+    </div>
+    <div id="content">
+<!--
+Copyright 2002-2004 The Apache Software Foundation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+//-->
+<h1>Programming with ZooKeeper - A basic tutorial</h1>
+<ul>
+<li><a href="#ch_Introduction">Introduction</a></li>
+<li><a href="#sc_barriers">Barriers</a></li>
+<li><a href="#sc_producerConsumerQueues">Producer-Consumer Queues</a></li>
+<li><a href="#Complete+example">Complete example</a>
+<ul>
+<li><a href="#Queue+test">Queue test</a></li>
+<li><a href="#Barrier+test">Barrier test</a></li>
+<li><a href="#sc_sourceListing">Source Listing</a></li>
+</ul>
+</li>
+</ul>
+<p><a name="ch_Introduction"></a></p>
+<h2>Introduction</h2>
+<p>In this tutorial, we show simple implementations of barriers and producer-consumer queues using ZooKeeper. We call the respective classes Barrier and Queue. These examples assume that you have at least one ZooKeeper server running.</p>
+<p>Both primitives use the following common excerpt of code:</p>
+<pre><code>static ZooKeeper zk = null;
+static Integer mutex;
+
+String root;
+
+SyncPrimitive(String address) {
+    if(zk == null){
+        try {
+            System.out.println(&quot;Starting ZK:&quot;);
+            zk = new ZooKeeper(address, 3000, this);
+            mutex = new Integer(-1);
+            System.out.println(&quot;Finished starting ZK: &quot; + zk);
+        } catch (IOException e) {
+            System.out.println(e.toString());
+            zk = null;
+        }
+    }
+}
+
+synchronized public void process(WatchedEvent event) {
+    synchronized (mutex) {
+        mutex.notify();
+    }
+}
+</code></pre>
+<p>Both classes extend SyncPrimitive. In this way, we execute steps that are common to all primitives in the constructor of SyncPrimitive. To keep the examples simple, we create a ZooKeeper object the first time we instantiate either a barrier object or a queue object, and we declare a static variable that is a reference to this object. The subsequent instances of Barrier and Queue check whether a ZooKeeper object exists. Alternatively, we could have the application creating a ZooKeeper object and passing it to the constructor of Barrier and Queue.</p>
+<p>We use the process() method to process notifications triggered due to watches. In the following discussion, we present code that sets watches. A watch is internal structure that enables ZooKeeper to notify a client of a change to a node. For example, if a client is waiting for other clients to leave a barrier, then it can set a watch and wait for modifications to a particular node, which can indicate that it is the end of the wait. This point becomes clear once we go over the examples.</p>
+<p><a name="sc_barriers"></a></p>
+<h2>Barriers</h2>
+<p>A barrier is a primitive that enables a group of processes to synchronize the beginning and the end of a computation. The general idea of this implementation is to have a barrier node that serves the purpose of being a parent for individual process nodes. Suppose that we call the barrier node &quot;/b1&quot;. Each process &quot;p&quot; then creates a node &quot;/b1/p&quot;. Once enough processes have created their corresponding nodes, joined processes can start the computation.</p>
+<p>In this example, each process instantiates a Barrier object, and its constructor takes as parameters:</p>
+<ul>
+<li>the address of a ZooKeeper server (e.g., &quot;zoo1.foo.com:2181&quot;)</li>
+<li>the path of the barrier node on ZooKeeper (e.g., &quot;/b1&quot;)</li>
+<li>the size of the group of processes</li>
+</ul>
+<p>The constructor of Barrier passes the address of the Zookeeper server to the constructor of the parent class. The parent class creates a ZooKeeper instance if one does not exist. The constructor of Barrier then creates a barrier node on ZooKeeper, which is the parent node of all process nodes, and we call root (<strong>Note:</strong> This is not the ZooKeeper root &quot;/&quot;).</p>
+<pre><code>/**
+ * Barrier constructor
+ *
+ * @param address
+ * @param root
+ * @param size
+ */
+Barrier(String address, String root, int size) {
+    super(address);
+    this.root = root;
+    this.size = size;
+    // Create barrier node
+    if (zk != null) {
+        try {
+            Stat s = zk.exists(root, false);
+            if (s == null) {
+                zk.create(root, new byte[0], Ids.OPEN_ACL_UNSAFE,
+                        CreateMode.PERSISTENT);
+            }
+        } catch (KeeperException e) {
+            System.out
+                    .println(&quot;Keeper exception when instantiating queue: &quot;
+                            + e.toString());
+        } catch (InterruptedException e) {
+            System.out.println(&quot;Interrupted exception&quot;);
+        }
+    }
+
+    // My node name
+    try {
+        name = new String(InetAddress.getLocalHost().getCanonicalHostName().toString());
+    } catch (UnknownHostException e) {
+        System.out.println(e.toString());
+    }
+}
+</code></pre>
+<p>To enter the barrier, a process calls enter(). The process creates a node under the root to represent it, using its host name to form the node name. It then wait until enough processes have entered the barrier. A process does it by checking the number of children the root node has with &quot;getChildren()&quot;, and waiting for notifications in the case it does not have enough. To receive a notification when there is a change to the root node, a process has to set a watch, and does it through the call to &quot;getChildren()&quot;. In the code, we have that &quot;getChildren()&quot; has two parameters. The first one states the node to read from, and the second is a boolean flag that enables the process to set a watch. In the code the flag is true.</p>
+<pre><code>/**
+ * Join barrier
+ *
+ * @return
+ * @throws KeeperException
+ * @throws InterruptedException
+ */
+
+boolean enter() throws KeeperException, InterruptedException{
+    zk.create(root + &quot;/&quot; + name, new byte[0], Ids.OPEN_ACL_UNSAFE,
+            CreateMode.EPHEMERAL_SEQUENTIAL);
+    while (true) {
+        synchronized (mutex) {
+            List&lt;String&gt; list = zk.getChildren(root, true);
+
+            if (list.size() &lt; size) {
+                mutex.wait();
+            } else {
+                return true;
+            }
+        }
+    }
+}
+</code></pre>
+<p>Note that enter() throws both KeeperException and InterruptedException, so it is the responsibility of the application to catch and handle such exceptions.</p>
+<p>Once the computation is finished, a process calls leave() to leave the barrier. First it deletes its corresponding node, and then it gets the children of the root node. If there is at least one child, then it waits for a notification (obs: note that the second parameter of the call to getChildren() is true, meaning that ZooKeeper has to set a watch on the root node). Upon reception of a notification, it checks once more whether the root node has any children.</p>
+<pre><code>/**
+ * Wait until all reach barrier
+ *
+ * @return
+ * @throws KeeperException
+ * @throws InterruptedException
+ */
+
+boolean leave() throws KeeperException, InterruptedException {
+    zk.delete(root + &quot;/&quot; + name, 0);
+    while (true) {
+        synchronized (mutex) {
+            List&lt;String&gt; list = zk.getChildren(root, true);
+                if (list.size() &gt; 0) {
+                    mutex.wait();
+                } else {
+                    return true;
+                }
+            }
+        }
+    }
+</code></pre>
+<p><a name="sc_producerConsumerQueues"></a></p>
+<h2>Producer-Consumer Queues</h2>
+<p>A producer-consumer queue is a distributed data structure that groups of processes use to generate and consume items. Producer processes create new elements and add them to the queue. Consumer processes remove elements from the list, and process them. In this implementation, the elements are simple integers. The queue is represented by a root node, and to add an element to the queue, a producer process creates a new node, a child of the root node.</p>
+<p>The following excerpt of code corresponds to the constructor of the object. As with Barrier objects, it first calls the constructor of the parent class, SyncPrimitive, that creates a ZooKeeper object if one doesn't exist. It then verifies if the root node of the queue exists, and creates if it doesn't.</p>
+<pre><code>/**
+ * Constructor of producer-consumer queue
+ *
+ * @param address
+ * @param name
+ */
+Queue(String address, String name) {
+    super(address);
+    this.root = name;
+    // Create ZK node name
+    if (zk != null) {
+        try {
+            Stat s = zk.exists(root, false);
+            if (s == null) {
+                zk.create(root, new byte[0], Ids.OPEN_ACL_UNSAFE,
+                        CreateMode.PERSISTENT);
+            }
+        } catch (KeeperException e) {
+            System.out
+                    .println(&quot;Keeper exception when instantiating queue: &quot;
+                            + e.toString());
+        } catch (InterruptedException e) {
+            System.out.println(&quot;Interrupted exception&quot;);
+        }
+    }
+}
+</code></pre>
+<p>A producer process calls &quot;produce()&quot; to add an element to the queue, and passes an integer as an argument. To add an element to the queue, the method creates a new node using &quot;create()&quot;, and uses the SEQUENCE flag to instruct ZooKeeper to append the value of the sequencer counter associated to the root node. In this way, we impose a total order on the elements of the queue, thus guaranteeing that the oldest element of the queue is the next one consumed.</p>
+<pre><code>/**
+ * Add element to the queue.
+ *
+ * @param i
+ * @return
+ */
+
+boolean produce(int i) throws KeeperException, InterruptedException{
+    ByteBuffer b = ByteBuffer.allocate(4);
+    byte[] value;
+
+    // Add child with value i
+    b.putInt(i);
+    value = b.array();
+    zk.create(root + &quot;/element&quot;, value, Ids.OPEN_ACL_UNSAFE,
+                CreateMode.PERSISTENT_SEQUENTIAL);
+
+    return true;
+}
+</code></pre>
+<p>To consume an element, a consumer process obtains the children of the root node, reads the node with smallest counter value, and returns the element. Note that if there is a conflict, then one of the two contending processes won't be able to delete the node and the delete operation will throw an exception.</p>
+<p>A call to getChildren() returns the list of children in lexicographic order. As lexicographic order does not necessarily follow the numerical order of the counter values, we need to decide which element is the smallest. To decide which one has the smallest counter value, we traverse the list, and remove the prefix &quot;element&quot; from each one.</p>
+<pre><code>/**
+ * Remove first element from the queue.
+ *
+ * @return
+ * @throws KeeperException
+ * @throws InterruptedException
+ */
+int consume() throws KeeperException, InterruptedException{
+    int retvalue = -1;
+    Stat stat = null;
+
+    // Get the first element available
+    while (true) {
+        synchronized (mutex) {
+            List&lt;String&gt; list = zk.getChildren(root, true);
+            if (list.size() == 0) {
+                System.out.println(&quot;Going to wait&quot;);
+                mutex.wait();
+            } else {
+                Integer min = new Integer(list.get(0).substring(7));
+                for(String s : list){
+                    Integer tempValue = new Integer(s.substring(7));
+                    //System.out.println(&quot;Temporary value: &quot; + tempValue);
+                    if(tempValue &lt; min) min = tempValue;
+                }
+                System.out.println(&quot;Temporary value: &quot; + root + &quot;/element&quot; + min);
+                byte[] b = zk.getData(root + &quot;/element&quot; + min,
+                            false, stat);
+                zk.delete(root + &quot;/element&quot; + min, 0);
+                ByteBuffer buffer = ByteBuffer.wrap(b);
+                retvalue = buffer.getInt();
+
+                return retvalue;
+                }
+            }
+        }
+    }
+}
+</code></pre>
+<p><a name="Complete+example"></a></p>
+<h2>Complete example</h2>
+<p>In the following section you can find a complete command line application to demonstrate the above mentioned recipes. Use the following command to run it.</p>
+<pre><code>ZOOBINDIR=&quot;[path_to_distro]/bin&quot;
+. &quot;$ZOOBINDIR&quot;/zkEnv.sh
+java SyncPrimitive [Test Type] [ZK server] [No of elements] [Client type]
+</code></pre>
+<p><a name="Queue+test"></a></p>
+<h3>Queue test</h3>
+<p>Start a producer to create 100 elements</p>
+<pre><code>java SyncPrimitive qTest localhost 100 p
+</code></pre>
+<p>Start a consumer to consume 100 elements</p>
+<pre><code>java SyncPrimitive qTest localhost 100 c
+</code></pre>
+<p><a name="Barrier+test"></a></p>
+<h3>Barrier test</h3>
+<p>Start a barrier with 2 participants (start as many times as many participants you'd like to enter)</p>
+<pre><code>java SyncPrimitive bTest localhost 2
+</code></pre>
+<p><a name="sc_sourceListing"></a></p>
+<h3>Source Listing</h3>
+<h4>SyncPrimitive.Java</h4>
+<pre><code>import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.Random;
+
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.ZooDefs.Ids;
+import org.apache.zookeeper.data.Stat;
+
+public class SyncPrimitive implements Watcher {
+
+    static ZooKeeper zk = null;
+    static Integer mutex;
+    String root;
+
+    SyncPrimitive(String address) {
+        if(zk == null){
+            try {
+                System.out.println(&quot;Starting ZK:&quot;);
+                zk = new ZooKeeper(address, 3000, this);
+                mutex = new Integer(-1);
+                System.out.println(&quot;Finished starting ZK: &quot; + zk);
+            } catch (IOException e) {
+                System.out.println(e.toString());
+                zk = null;
+            }
+        }
+        //else mutex = new Integer(-1);
+    }
+
+    synchronized public void process(WatchedEvent event) {
+        synchronized (mutex) {
+            //System.out.println(&quot;Process: &quot; + event.getType());
+            mutex.notify();
+        }
+    }
+
+    /**
+     * Barrier
+     */
+    static public class Barrier extends SyncPrimitive {
+        int size;
+        String name;
+
+        /**
+         * Barrier constructor
+         *
+         * @param address
+         * @param root
+         * @param size
+         */
+        Barrier(String address, String root, int size) {
+            super(address);
+            this.root = root;
+            this.size = size;
+
+            // Create barrier node
+            if (zk != null) {
+                try {
+                    Stat s = zk.exists(root, false);
+                    if (s == null) {
+                        zk.create(root, new byte[0], Ids.OPEN_ACL_UNSAFE,
+                                CreateMode.PERSISTENT);
+                    }
+                } catch (KeeperException e) {
+                    System.out
+                            .println(&quot;Keeper exception when instantiating queue: &quot;
+                                    + e.toString());
+                } catch (InterruptedException e) {
+                    System.out.println(&quot;Interrupted exception&quot;);
+                }
+            }
+
+            // My node name
+            try {
+                name = new String(InetAddress.getLocalHost().getCanonicalHostName().toString());
+            } catch (UnknownHostException e) {
+                System.out.println(e.toString());
+            }
+
+        }
+
+        /**
+         * Join barrier
+         *
+         * @return
+         * @throws KeeperException
+         * @throws InterruptedException
+         */
+
+        boolean enter() throws KeeperException, InterruptedException{
+            zk.create(root + &quot;/&quot; + name, new byte[0], Ids.OPEN_ACL_UNSAFE,
+                    CreateMode.EPHEMERAL_SEQUENTIAL);
+            while (true) {
+                synchronized (mutex) {
+                    List&lt;String&gt; list = zk.getChildren(root, true);
+
+                    if (list.size() &lt; size) {
+                        mutex.wait();
+                    } else {
+                        return true;
+                    }
+                }
+            }
+        }
+
+        /**
+         * Wait until all reach barrier
+         *
+         * @return
+         * @throws KeeperException
+         * @throws InterruptedException
+         */
+        boolean leave() throws KeeperException, InterruptedException{
+            zk.delete(root + &quot;/&quot; + name, 0);
+            while (true) {
+                synchronized (mutex) {
+                    List&lt;String&gt; list = zk.getChildren(root, true);
+                        if (list.size() &gt; 0) {
+                            mutex.wait();
+                        } else {
+                            return true;
+                        }
+                    }
+                }
+            }
+        }
+
+    /**
+     * Producer-Consumer queue
+     */
+    static public class Queue extends SyncPrimitive {
+
+        /**
+         * Constructor of producer-consumer queue
+         *
+         * @param address
+         * @param name
+         */
+        Queue(String address, String name) {
+            super(address);
+            this.root = name;
+            // Create ZK node name
+            if (zk != null) {
+                try {
+                    Stat s = zk.exists(root, false);
+                    if (s == null) {
+                        zk.create(root, new byte[0], Ids.OPEN_ACL_UNSAFE,
+                                CreateMode.PERSISTENT);
+                    }
+                } catch (KeeperException e) {
+                    System.out
+                            .println(&quot;Keeper exception when instantiating queue: &quot;
+                                    + e.toString());
+                } catch (InterruptedException e) {
+                    System.out.println(&quot;Interrupted exception&quot;);
+                }
+            }
+        }
+
+        /**
+         * Add element to the queue.
+         *
+         * @param i
+         * @return
+         */
+
+        boolean produce(int i) throws KeeperException, InterruptedException{
+            ByteBuffer b = ByteBuffer.allocate(4);
+            byte[] value;
+
+            // Add child with value i
+            b.putInt(i);
+            value = b.array();
+            zk.create(root + &quot;/element&quot;, value, Ids.OPEN_ACL_UNSAFE,
+                        CreateMode.PERSISTENT_SEQUENTIAL);
+
+            return true;
+        }
+
+        /**
+         * Remove first element from the queue.
+         *
+         * @return
+         * @throws KeeperException
+         * @throws InterruptedException
+         */
+        int consume() throws KeeperException, InterruptedException{
+            int retvalue = -1;
+            Stat stat = null;
+
+            // Get the first element available
+            while (true) {
+                synchronized (mutex) {
+                    List&lt;String&gt; list = zk.getChildren(root, true);
+                    if (list.size() == 0) {
+                        System.out.println(&quot;Going to wait&quot;);
+                        mutex.wait();
+                    } else {
+                        Integer min = new Integer(list.get(0).substring(7));
+                        String minNode = list.get(0);
+                        for(String s : list){
+                            Integer tempValue = new Integer(s.substring(7));
+                            //System.out.println(&quot;Temporary value: &quot; + tempValue);
+                            if(tempValue &lt; min) {
+                                min = tempValue;
+                                minNode = s;
+                            }
+                        }
+                        System.out.println(&quot;Temporary value: &quot; + root + &quot;/&quot; + minNode);
+                        byte[] b = zk.getData(root + &quot;/&quot; + minNode,
+                        false, stat);
+                        zk.delete(root + &quot;/&quot; + minNode, 0);
+                        ByteBuffer buffer = ByteBuffer.wrap(b);
+                        retvalue = buffer.getInt();
+
+                        return retvalue;
+                    }
+                }
+            }
+        }
+    }
+
+    public static void main(String args[]) {
+        if (args[0].equals(&quot;qTest&quot;))
+            queueTest(args);
+        else
+            barrierTest(args);
+    }
+
+    public static void queueTest(String args[]) {
+        Queue q = new Queue(args[1], &quot;/app1&quot;);
+
+        System.out.println(&quot;Input: &quot; + args[1]);
+        int i;
+        Integer max = new Integer(args[2]);
+
+        if (args[3].equals(&quot;p&quot;)) {
+            System.out.println(&quot;Producer&quot;);
+            for (i = 0; i &lt; max; i++)
+                try{
+                    q.produce(10 + i);
+                } catch (KeeperException e){
+
+                } catch (InterruptedException e){
+
+                }
+        } else {
+            System.out.println(&quot;Consumer&quot;);
+
+            for (i = 0; i &lt; max; i++) {
+                try{
+                    int r = q.consume();
+                    System.out.println(&quot;Item: &quot; + r);
+                } catch (KeeperException e){
+                    i--;
+                } catch (InterruptedException e){
+                }
+            }
+        }
+    }
+
+    public static void barrierTest(String args[]) {
+        Barrier b = new Barrier(args[1], &quot;/b1&quot;, new Integer(args[2]));
+        try{
+            boolean flag = b.enter();
+            System.out.println(&quot;Entered barrier: &quot; + args[2]);
+            if(!flag) System.out.println(&quot;Error when entering the barrier&quot;);
+        } catch (KeeperException e){
+        } catch (InterruptedException e){
+        }
+
+        // Generate random integer
+        Random rand = new Random();
+        int r = rand.nextInt(100);
+        // Loop for rand iterations
+        for (int i = 0; i &lt; r; i++) {
+            try {
+                Thread.sleep(100);
+            } catch (InterruptedException e) {
+            }
+        }
+        try{
+            b.leave();
+        } catch (KeeperException e){
+
+        } catch (InterruptedException e){
+
+        }
+        System.out.println(&quot;Left barrier&quot;);
+    }
+}
+</code></pre>
+</div>
+<div class="clearboth">&nbsp;</div>
+</div>
+<div id="footer">
+    <div class="lastmodified">
+        <script type="text/javascript">
+        <!--
+            document.write("Last Published: " + document.lastModified);
+        //  -->
+        </script>
+    </div>
+    <div class="copyright">
+        Copyright &copy; <a href="http://www.apache.org/licenses/">The Apache Software Foundation.</a>
+    </div>
+    <div id="logos"></div>
+</div>
+</body>
+</html>
\ No newline at end of file