Author: andor
Date: Thu Oct  5 10:45:12 2023
New Revision: 64335

Log:
Add ZooKeeper 3.8.3 release candidate 0

Added:
    dev/zookeeper/zookeeper-3.8.3-candidate-0/
    dev/zookeeper/zookeeper-3.8.3-candidate-0/apache-zookeeper-3.8.3-bin.tar.gz 
  (with props)
    
dev/zookeeper/zookeeper-3.8.3-candidate-0/apache-zookeeper-3.8.3-bin.tar.gz.asc
    
dev/zookeeper/zookeeper-3.8.3-candidate-0/apache-zookeeper-3.8.3-bin.tar.gz.sha512
    dev/zookeeper/zookeeper-3.8.3-candidate-0/apache-zookeeper-3.8.3.tar.gz   
(with props)
    dev/zookeeper/zookeeper-3.8.3-candidate-0/apache-zookeeper-3.8.3.tar.gz.asc
    
dev/zookeeper/zookeeper-3.8.3-candidate-0/apache-zookeeper-3.8.3.tar.gz.sha512
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/2pc.jpg   (with 
props)
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/bk-overview.jpg   
(with props)
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/favicon.ico   
(with props)
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/state_dia.dia   
(with props)
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/state_dia.jpg   
(with props)
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/zkAuditLogs.jpg   
(with props)
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/zkarch.jpg   (with 
props)
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/zkcomponents.jpg   
(with props)
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/zknamespace.jpg   
(with props)
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/zkperfRW-3.2.jpg   
(with props)
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/zkperfRW.jpg   
(with props)
    
dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/zkperfreliability.jpg  
 (with props)
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/zkservice.jpg   
(with props)
    
dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/zookeeper_small.gif   
(with props)
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/index.html
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/javaExample.html
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/recipes.html
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/releasenotes.html
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/skin/
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/skin/basic.css
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/skin/chapter.gif   (with 
props)
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/skin/chapter_open.gif   
(with props)
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/skin/current.gif   (with 
props)
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/skin/getBlank.js
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/skin/getMenu.js
    
dev/zookeeper/zookeeper-3.8.3-candidate-0/website/skin/header_white_line.gif   
(with props)
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/skin/init.js
    
dev/zookeeper/zookeeper-3.8.3-candidate-0/website/skin/instruction_arrow.png   
(with props)
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/skin/menu.js
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/skin/page.gif   (with 
props)
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/skin/print.css
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/skin/printer.gif   (with 
props)
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/skin/profile.css
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/skin/prototype.js
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/skin/screen.css
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/zookeeperAdmin.html
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/zookeeperAuditLogs.html
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/zookeeperCLI.html
    
dev/zookeeper/zookeeper-3.8.3-candidate-0/website/zookeeperHierarchicalQuorums.html
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/zookeeperInternals.html
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/zookeeperJMX.html
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/zookeeperMonitor.html
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/zookeeperObservers.html
    
dev/zookeeper/zookeeper-3.8.3-candidate-0/website/zookeeperOracleQuorums.html
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/zookeeperOver.html
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/zookeeperProgrammers.html
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/zookeeperQuotas.html
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/zookeeperReconfig.html
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/zookeeperStarted.html
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/zookeeperTools.html
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/zookeeperTutorial.html
    dev/zookeeper/zookeeper-3.8.3-candidate-0/website/zookeeperUseCases.html

Added: 
dev/zookeeper/zookeeper-3.8.3-candidate-0/apache-zookeeper-3.8.3-bin.tar.gz
==============================================================================
Binary file - no diff available.

Propchange: 
dev/zookeeper/zookeeper-3.8.3-candidate-0/apache-zookeeper-3.8.3-bin.tar.gz
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: 
dev/zookeeper/zookeeper-3.8.3-candidate-0/apache-zookeeper-3.8.3-bin.tar.gz.asc
==============================================================================
--- 
dev/zookeeper/zookeeper-3.8.3-candidate-0/apache-zookeeper-3.8.3-bin.tar.gz.asc 
(added)
+++ 
dev/zookeeper/zookeeper-3.8.3-candidate-0/apache-zookeeper-3.8.3-bin.tar.gz.asc 
Thu Oct  5 10:45:12 2023
@@ -0,0 +1,17 @@
+-----BEGIN PGP SIGNATURE-----
+
+iQJFBAABCgAvFiEEP3odFvpCF7HcdeHJ/+NbfxXfoboFAmUekV8RHGFuZG9yQGFw
+YWNoZS5vcmcACgkQ/+NbfxXfobpWww//b6epSATnB5JiU5kYWqXeP2gi+NEm5P7r
+Rx/DkVfvm6uGBMhR6esHd48Y0pTjo+/im5MldbP5s5qqpvlT8a6q7wcRjTCq8GsP
+7vrho2hue2G9zHIspCxn2y2Yvz7N2te0hkNaGNxQwqn8//mG2KteHKJ6blCBrqTZ
+n2mdzpB5lLKU072aM54vjmMlizdwsUkeAnK3un20zqeUUat2rSiVOpvHw8h2x0c0
+8fe8OlwOTe7+a6KMxv7Q4RhxS0u+RDyO+FJpy5EMUuiOsZMrBBpB8OYKPxvwhHsa
+UGvNk9FTsHQHqJdBguebWZiAae8j+VmP7k2bVyvl0FZEXuO3qAIti8o0guTnzY7d
+Uoy2IVtmk5YRxgR8HU9GickHcvsKB8Nd26KSaS3iH+PjQ1OiX+upR/b6HPGMO7gO
+ToySiP0tBBD68ZZhM0eEAhvefZwJxZildzqHwh2xX+fk5eK9SYYETNt6P0alzXhc
+h6fuChOBDoWnhkSeRlFpW7yynKyu2yPnRyw4/A8vPDCqsYpmLyhkhCwOuSqw5tNg
+gQb6kirz7puA7k0SVel6+fKHhy+ZwFqMyJubgg2SXJpQe2jO/u17SE24YKpLrYae
+gTUnrHAIkvwuz1KV0q26eszihJKUTeiQejKsYt0uQuA4sie4Ia61iDf4dsOH2zlp
+xdh0JpRiZ9s=
+=AYU/
+-----END PGP SIGNATURE-----

Added: 
dev/zookeeper/zookeeper-3.8.3-candidate-0/apache-zookeeper-3.8.3-bin.tar.gz.sha512
==============================================================================
--- 
dev/zookeeper/zookeeper-3.8.3-candidate-0/apache-zookeeper-3.8.3-bin.tar.gz.sha512
 (added)
+++ 
dev/zookeeper/zookeeper-3.8.3-candidate-0/apache-zookeeper-3.8.3-bin.tar.gz.sha512
 Thu Oct  5 10:45:12 2023
@@ -0,0 +1 @@
+eb1a5e79fe55fa50e36021ca8b752e40584d5e24f23985c43e9f56abfbf23c0239dce37d18f27213c9a38fcb6f68daf1a9468fc352e6ac2364faaf9b56145bdf
  apache-zookeeper-3.8.3-bin.tar.gz
\ No newline at end of file

Added: dev/zookeeper/zookeeper-3.8.3-candidate-0/apache-zookeeper-3.8.3.tar.gz
==============================================================================
Binary file - no diff available.

Propchange: 
dev/zookeeper/zookeeper-3.8.3-candidate-0/apache-zookeeper-3.8.3.tar.gz
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: 
dev/zookeeper/zookeeper-3.8.3-candidate-0/apache-zookeeper-3.8.3.tar.gz.asc
==============================================================================
--- dev/zookeeper/zookeeper-3.8.3-candidate-0/apache-zookeeper-3.8.3.tar.gz.asc 
(added)
+++ dev/zookeeper/zookeeper-3.8.3-candidate-0/apache-zookeeper-3.8.3.tar.gz.asc 
Thu Oct  5 10:45:12 2023
@@ -0,0 +1,17 @@
+-----BEGIN PGP SIGNATURE-----
+
+iQJFBAABCgAvFiEEP3odFvpCF7HcdeHJ/+NbfxXfoboFAmUekQ0RHGFuZG9yQGFw
+YWNoZS5vcmcACgkQ/+NbfxXfobrL3g//e30us2kOOHMe+w1qrYe7/BF5XdiT18z9
+aWdgjuu0u6+ox1Ug0QYbDdoHbsu21ZEEUz53jXqh7vvTJ0KVrEqFYncK3yjkGwQ8
+G0kqNWS3EsYSk4VPB+n6ZEXpcSMCL71glAlQwN3cYWaYyDjsCvSBgnuXTbL6AUli
+X3XzLJSZLo7ilGHEfPy2FaGHZm3jn0ayf8CSH23gbvPKVBv3IaNvu4+7l7Wx/Nta
+Sos85s4H9JqZMO7bXXMBdwYnmvL6Y3CjMwdKSpuuUJJA2lFXPOdTd2pJZ43Vc7XG
+AguKj6lzsBvqeSmlunIP+w1GT7BzBZ24cye9U9Qe57cj7w8Rt0jy6k/RRlhJcZzi
+RmRmbShwv/CPBTBgWxQXTUFWojC3hp8oii6oSPAXbhuU/vLsU8APxhZTEqAZnFz4
+tYF8RcnYfP00/ZR8fDotk/3oMjPvwfA1/ZU3VHP/Cr7mwil1Jqt965emYFqQ5z4J
+9DscmmXLVfiLlvQOo9XgIddxoEwaAg5a2fvkwphpyW/hHJBUm66ESWArlYq16vCH
+KqfaZbra1TOY3m/4BVEVOFJer/vCOZddjLnjBxn0S9NsW5IFhtcE22ZPQQPlkzRP
+gwxqyAQe7+No8ku7ULw7QRy1Wxula20lkGUHQdeiW94F5/ULmv9g6KVzKnujJi7H
+stspd5myGXY=
+=2TkE
+-----END PGP SIGNATURE-----

Added: 
dev/zookeeper/zookeeper-3.8.3-candidate-0/apache-zookeeper-3.8.3.tar.gz.sha512
==============================================================================
--- 
dev/zookeeper/zookeeper-3.8.3-candidate-0/apache-zookeeper-3.8.3.tar.gz.sha512 
(added)
+++ 
dev/zookeeper/zookeeper-3.8.3-candidate-0/apache-zookeeper-3.8.3.tar.gz.sha512 
Thu Oct  5 10:45:12 2023
@@ -0,0 +1 @@
+4f68434a55a93b88e422029a8583ebdc060e1cc2aed38cdc0170c5612be6f6209947d10b488eae671ff7279201c166d34095b0be446b930a918a24f509b159e5
  apache-zookeeper-3.8.3.tar.gz
\ No newline at end of file

Added: dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/2pc.jpg
==============================================================================
Binary file - no diff available.

Propchange: dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/2pc.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/bk-overview.jpg
==============================================================================
Binary file - no diff available.

Propchange: 
dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/bk-overview.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/favicon.ico
==============================================================================
Binary file - no diff available.

Propchange: dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/favicon.ico
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/state_dia.dia
==============================================================================
Binary file - no diff available.

Propchange: 
dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/state_dia.dia
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/state_dia.jpg
==============================================================================
Binary file - no diff available.

Propchange: 
dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/state_dia.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/zkAuditLogs.jpg
==============================================================================
Binary file - no diff available.

Propchange: 
dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/zkAuditLogs.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/zkarch.jpg
==============================================================================
Binary file - no diff available.

Propchange: dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/zkarch.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/zkcomponents.jpg
==============================================================================
Binary file - no diff available.

Propchange: 
dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/zkcomponents.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/zknamespace.jpg
==============================================================================
Binary file - no diff available.

Propchange: 
dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/zknamespace.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/zkperfRW-3.2.jpg
==============================================================================
Binary file - no diff available.

Propchange: 
dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/zkperfRW-3.2.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/zkperfRW.jpg
==============================================================================
Binary file - no diff available.

Propchange: 
dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/zkperfRW.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: 
dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/zkperfreliability.jpg
==============================================================================
Binary file - no diff available.

Propchange: 
dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/zkperfreliability.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/zkservice.jpg
==============================================================================
Binary file - no diff available.

Propchange: 
dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/zkservice.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: 
dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/zookeeper_small.gif
==============================================================================
Binary file - no diff available.

Propchange: 
dev/zookeeper/zookeeper-3.8.3-candidate-0/website/images/zookeeper_small.gif
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: dev/zookeeper/zookeeper-3.8.3-candidate-0/website/index.html
==============================================================================
--- dev/zookeeper/zookeeper-3.8.3-candidate-0/website/index.html (added)
+++ dev/zookeeper/zookeeper-3.8.3-candidate-0/website/index.html Thu Oct  5 
10:45:12 2023
@@ -0,0 +1,227 @@
+
+<!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.8 
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="zookeeperOracleQuorums.html">Oracle Quorum</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.
+//-->
+<h2>ZooKeeper: Because Coordinating Distributed Systems is a Zoo</h2>
+<p>ZooKeeper is a high-performance coordination service for distributed 
applications.  It exposes common services - such as naming, configuration 
management, synchronization, and group services - in a simple interface so you 
don't have to write them from scratch.  You can use it off-the-shelf to 
implement consensus, group management, leader election, and presence protocols. 
And you can build on it for your own, specific needs.</p>
+<p>The following documents describe concepts and procedures to get you started 
using ZooKeeper. If you have more questions, please ask the <a 
href="http://zookeeper.apache.org/mailing_lists.html";>mailing list</a> or 
browse the archives.</p>
+<ul>
+<li><strong>ZooKeeper Overview</strong> Technical Overview Documents for 
Client Developers, Administrators, and Contributors
+<ul>
+<li><a href="zookeeperOver.html">Overview</a> - a bird's eye view of 
ZooKeeper, including design concepts and architecture</li>
+<li><a href="zookeeperStarted.html">Getting Started</a> - a tutorial-style 
guide for developers to install, run, and program to ZooKeeper</li>
+<li><a href="releasenotes.html">Release Notes</a> - new developer and user 
facing features, improvements, and incompatibilities</li>
+</ul>
+</li>
+<li><strong>Developers</strong> Documents for Developers using the ZooKeeper 
Client API
+<ul>
+<li><a href="apidocs/zookeeper-server/index.html">API Docs</a> - the technical 
reference to ZooKeeper Client APIs</li>
+<li><a href="zookeeperProgrammers.html">Programmer's Guide</a> - a client 
application developer's guide to ZooKeeper</li>
+<li><a href="zookeeperUseCases.html">ZooKeeper Use Cases</a> - a series of use 
cases using the ZooKeeper.</li>
+<li><a href="javaExample.html">ZooKeeper Java Example</a> - a simple Zookeeper 
client application, written in Java</li>
+<li><a href="zookeeperTutorial.html">Barrier and Queue Tutorial</a> - sample 
implementations of barriers and queues</li>
+<li><a href="recipes.html">ZooKeeper Recipes</a> - higher level solutions to 
common problems in distributed applications</li>
+</ul>
+</li>
+<li><strong>Administrators &amp; Operators</strong> Documents for 
Administrators and Operations Engineers of ZooKeeper Deployments
+<ul>
+<li><a href="zookeeperAdmin.html">Administrator's Guide</a> - a guide for 
system administrators and anyone else who might deploy ZooKeeper</li>
+<li><a href="zookeeperQuotas.html">Quota Guide</a> - a guide for system 
administrators on Quotas in ZooKeeper.</li>
+<li><a href="zookeeperJMX.html">JMX</a> - how to enable JMX in ZooKeeper</li>
+<li><a href="zookeeperHierarchicalQuorums.html">Hierarchical Quorums</a> - a 
guide on how to use hierarchical quorums</li>
+<li><a href="zookeeperOracleQuorums.html">Oracle Quorum</a> - the introduction 
to Oracle Quorum increases the availability of a cluster of 2 ZooKeeper 
instances with a failure detector.</li>
+<li><a href="zookeeperObservers.html">Observers</a> - non-voting ensemble 
members that easily improve ZooKeeper's scalability</li>
+<li><a href="zookeeperReconfig.html">Dynamic Reconfiguration</a> - a guide on 
how to use dynamic reconfiguration in ZooKeeper</li>
+<li><a href="zookeeperCLI.html">ZooKeeper CLI</a> - a guide on how to use the 
ZooKeeper command line interface</li>
+<li><a href="zookeeperTools.html">ZooKeeper Tools</a> - a guide on how to use 
a series of tools for ZooKeeper</li>
+<li><a href="zookeeperMonitor.html">ZooKeeper Monitor</a> - a guide on how to 
monitor the ZooKeeper</li>
+<li><a href="zookeeperAuditLogs.html">Audit Logging</a> - a guide on how to 
configure audit logs in ZooKeeper Server and what contents are logged.</li>
+</ul>
+</li>
+<li><strong>Contributors</strong> Documents for Developers Contributing to the 
ZooKeeper Open Source Project
+<ul>
+<li><a href="zookeeperInternals.html">ZooKeeper Internals</a> - assorted 
topics on the inner workings of ZooKeeper</li>
+</ul>
+</li>
+<li><strong>Miscellaneous ZooKeeper Documentation</strong>
+<ul>
+<li><a 
href="https://cwiki.apache.org/confluence/display/ZOOKEEPER";>Wiki</a></li>
+<li><a 
href="https://cwiki.apache.org/confluence/display/ZOOKEEPER/FAQ";>FAQ</a></li>
+</ul>
+</li>
+</ul>
+</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.8.3-candidate-0/website/javaExample.html
==============================================================================
--- dev/zookeeper/zookeeper-3.8.3-candidate-0/website/javaExample.html (added)
+++ dev/zookeeper/zookeeper-3.8.3-candidate-0/website/javaExample.html Thu Oct  
5 10:45:12 2023
@@ -0,0 +1,690 @@
+
+<!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.8 
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="zookeeperOracleQuorums.html">Oracle Quorum</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>ZooKeeper Java Example</h1>
+<ul>
+<li><a href="#ch_Introduction">A Simple Watch Client</a>
+<ul>
+<li><a href="#sc_requirements">Requirements</a></li>
+<li><a href="#sc_design">Program Design</a></li>
+</ul>
+</li>
+<li><a href="#sc_executor">The Executor Class</a></li>
+<li><a href="#sc_DataMonitor">The DataMonitor Class</a></li>
+<li><a href="#sc_completeSourceCode">Complete Source Listings</a></li>
+</ul>
+<p><a name="ch_Introduction"></a></p>
+<h2>A Simple Watch Client</h2>
+<p>To introduce you to the ZooKeeper Java API, we develop here a very simple 
watch client. This ZooKeeper client watches a znode for changes and responds to 
by starting or stopping a program.</p>
+<p><a name="sc_requirements"></a></p>
+<h3>Requirements</h3>
+<p>The client has four requirements:</p>
+<ul>
+<li>It takes as parameters:</li>
+<li>the address of the ZooKeeper service</li>
+<li>the name of a znode - the one to be watched</li>
+<li>the name of a file to write the output to</li>
+<li>an executable with arguments.</li>
+<li>It fetches the data associated with the znode and starts the 
executable.</li>
+<li>If the znode changes, the client re-fetches the contents and restarts the 
executable.</li>
+<li>If the znode disappears, the client kills the executable.</li>
+</ul>
+<p><a name="sc_design"></a></p>
+<h3>Program Design</h3>
+<p>Conventionally, ZooKeeper applications are broken into two units, one which 
maintains the connection, and the other which monitors data.  In this 
application, the class called the <strong>Executor</strong> maintains the 
ZooKeeper connection, and the class called the <strong>DataMonitor</strong> 
monitors the data in the ZooKeeper tree. Also, Executor contains the main 
thread and contains the execution logic. It is responsible for what little user 
interaction there is, as well as interaction with the executable program you 
pass in as an argument and which the sample (per the requirements) shuts down 
and restarts, according to the state of the znode.</p>
+<p><a name="sc_executor"></a></p>
+<h2>The Executor Class</h2>
+<p>The Executor object is the primary container of the sample application. It 
contains both the <strong>ZooKeeper</strong> object, 
<strong>DataMonitor</strong>, as described above in <a 
href="#sc_design">Program Design</a>.</p>
+<pre><code>// from the Executor class...
+
+public static void main(String[] args) {
+    if (args.length &lt; 4) {
+        System.err
+                .println(&quot;USAGE: Executor hostPort znode filename program 
[args ...]&quot;);
+        System.exit(2);
+    }
+    String hostPort = args[0];
+    String znode = args[1];
+    String filename = args[2];
+    String exec[] = new String[args.length - 3];
+    System.arraycopy(args, 3, exec, 0, exec.length);
+    try {
+        new Executor(hostPort, znode, filename, exec).run();
+    } catch (Exception e) {
+        e.printStackTrace();
+    }
+}
+
+public Executor(String hostPort, String znode, String filename,
+        String exec[]) throws KeeperException, IOException {
+    this.filename = filename;
+    this.exec = exec;
+    zk = new ZooKeeper(hostPort, 3000, this);
+    dm = new DataMonitor(zk, znode, null, this);
+}
+
+public void run() {
+    try {
+        synchronized (this) {
+            while (!dm.dead) {
+                wait();
+            }
+        }
+    } catch (InterruptedException e) {
+    }
+}
+</code></pre>
+<p>Recall that the Executor's job is to start and stop the executable whose 
name you pass in on the command line. It does this in response to events fired 
by the ZooKeeper object. As you can see in the code above, the Executor passes 
a reference to itself as the Watcher argument in the ZooKeeper constructor. It 
also passes a reference to itself as DataMonitorListener argument to the 
DataMonitor constructor. Per the Executor's definition, it implements both 
these interfaces:</p>
+<pre><code>public class Executor implements Watcher, Runnable, 
DataMonitor.DataMonitorListener {
+...
+</code></pre>
+<p>The <strong>Watcher</strong> interface is defined by the ZooKeeper Java 
API. ZooKeeper uses it to communicate back to its container. It supports only 
one method, <code>process()</code>, and ZooKeeper uses it to communicates 
generic events that the main thread would be interested in, such as the state 
of the ZooKeeper connection or the ZooKeeper session. The Executor in this 
example simply forwards those events down to the DataMonitor to decide what to 
do with them. It does this simply to illustrate the point that, by convention, 
the Executor or some Executor-like object &quot;owns&quot; the ZooKeeper 
connection, but it is free to delegate the events to other events to other 
objects. It also uses this as the default channel on which to fire watch 
events. (More on this later.)</p>
+<pre><code>public void process(WatchedEvent event) {
+    dm.process(event);
+}
+</code></pre>
+<p>The <strong>DataMonitorListener</strong> interface, on the other hand, is 
not part of the ZooKeeper API. It is a completely custom interface, designed 
for this sample application. The DataMonitor object uses it to communicate back 
to its container, which is also the Executor object. The DataMonitorListener 
interface looks like this:</p>
+<pre><code>public interface DataMonitorListener {
+    /**
+    * The existence status of the node has changed.
+    */
+    void exists(byte data[]);
+
+    /**
+    * The ZooKeeper session is no longer valid.
+    *
+    * @param rc
+    * the ZooKeeper reason code
+    */
+    void closing(int rc);
+}
+</code></pre>
+<p>This interface is defined in the DataMonitor class and implemented in the 
Executor class. When <code>Executor.exists()</code> is invoked, the Executor 
decides whether to start up or shut down per the requirements. Recall that the 
requires say to kill the executable when the znode ceases to <em>exist</em>.</p>
+<p>When <code>Executor.closing()</code> is invoked, the Executor decides 
whether or not to shut itself down in response to the ZooKeeper connection 
permanently disappearing.</p>
+<p>As you might have guessed, DataMonitor is the object that invokes these 
methods, in response to changes in ZooKeeper's state.</p>
+<p>Here are Executor's implementation of 
<code>DataMonitorListener.exists()</code> and 
<code>DataMonitorListener.closing</code>:</p>
+<pre><code>public void exists( byte[] data ) {
+    if (data == null) {
+        if (child != null) {
+            System.out.println(&quot;Killing process&quot;);
+            child.destroy();
+            try {
+                child.waitFor();
+            } catch (InterruptedException e) {
+           }
+        }
+        child = null;
+    } else {
+        if (child != null) {
+            System.out.println(&quot;Stopping child&quot;);
+            child.destroy();
+            try {
+               child.waitFor();
+            } catch (InterruptedException e) {
+            e.printStackTrace();
+            }
+        }
+        try {
+            FileOutputStream fos = new FileOutputStream(filename);
+            fos.write(data);
+            fos.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        try {
+            System.out.println(&quot;Starting child&quot;);
+            child = Runtime.getRuntime().exec(exec);
+            new StreamWriter(child.getInputStream(), System.out);
+            new StreamWriter(child.getErrorStream(), System.err);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+}
+
+public void closing(int rc) {
+    synchronized (this) {
+        notifyAll();
+    }
+}
+</code></pre>
+<p><a name="sc_DataMonitor"></a></p>
+<h2>The DataMonitor Class</h2>
+<p>The DataMonitor class has the meat of the ZooKeeper logic. It is mostly 
asynchronous and event driven. DataMonitor kicks things off in the constructor 
with:</p>
+<pre><code>public DataMonitor(ZooKeeper zk, String znode, Watcher 
chainedWatcher,
+        DataMonitorListener listener) {
+    this.zk = zk;
+    this.znode = znode;
+    this.chainedWatcher = chainedWatcher;
+    this.listener = listener;
+
+    // Get things started by checking if the node exists. We are going
+    // to be completely event driven
+</code></pre>
+<p>The call to <code>ZooKeeper.exists()</code> checks for the existence of the 
znode, sets a watch, and passes a reference to itself (<code>this</code>) as 
the completion callback object. In this sense, it kicks things off, since the 
real processing happens when the watch is triggered.</p>
+<h6>Note</h6>
+<blockquote>
+<p>Don't confuse the completion callback with the watch callback. The 
<code>ZooKeeper.exists()</code> completion callback, which happens to be the 
method <code>StatCallback.processResult()</code> implemented in the DataMonitor 
object, is invoked when the asynchronous <em>setting of the watch</em> 
operation (by <code>ZooKeeper.exists()</code>) completes on the server.</p>
+<p>The triggering of the watch, on the other hand, sends an event to the 
<em>Executor</em> object, since the Executor registered as the Watcher of the 
ZooKeeper object.</p>
+<p>As an aside, you might note that the DataMonitor could also register itself 
as the Watcher for this particular watch event. This is new to ZooKeeper 3.0.0 
(the support of multiple Watchers). In this example, however, DataMonitor does 
not register as the Watcher.</p>
+</blockquote>
+<p>When the <code>ZooKeeper.exists()</code> operation completes on the server, 
the ZooKeeper API invokes this completion callback on the client:</p>
+<pre><code>public void processResult(int rc, String path, Object ctx, Stat 
stat) {
+    boolean exists;
+    switch (rc) {
+    case Code.Ok:
+        exists = true;
+        break;
+    case Code.NoNode:
+        exists = false;
+        break;
+    case Code.SessionExpired:
+    case Code.NoAuth:
+        dead = true;
+        listener.closing(rc);
+        return;
+    default:
+        // Retry errors
+        zk.exists(znode, true, this, null);
+        return;
+    }
+
+    byte b[] = null;
+    if (exists) {
+        try {
+            b = zk.getData(znode, false, null);
+        } catch (KeeperException e) {
+            // We don't need to worry about recovering now. The watch
+            // callbacks will kick off any exception handling
+            e.printStackTrace();
+        } catch (InterruptedException e) {
+            return;
+        }
+    }     
+    if ((b == null &amp;amp;&amp;amp; b != prevData)
+        || (b != null &amp;amp;&amp;amp; !Arrays.equals(prevData, b))) {
+        listener.exists(b);&lt;/emphasis&gt;
+        prevData = b;
+    }
+}
+</code></pre>
+<p>The code first checks the error codes for znode existence, fatal errors, 
and recoverable errors. If the file (or znode) exists, it gets the data from 
the znode, and then invoke the exists() callback of Executor if the state has 
changed. Note, it doesn't have to do any Exception processing for the getData 
call because it has watches pending for anything that could cause an error: if 
the node is deleted before it calls <code>ZooKeeper.getData()</code>, the watch 
event set by the <code>ZooKeeper.exists()</code> triggers a callback; if there 
is a communication error, a connection watch event fires when the connection 
comes back up.</p>
+<p>Finally, notice how DataMonitor processes watch events:</p>
+<pre><code>public void process(WatchedEvent event) {
+    String path = event.getPath();
+    if (event.getType() == Event.EventType.None) {
+        // We are are being told that the state of the
+        // connection has changed
+        switch (event.getState()) {
+        case SyncConnected:
+            // In this particular example we don't need to do anything
+            // here - watches are automatically re-registered with
+            // server and any watches triggered while the client was
+            // disconnected will be delivered (in order of course)
+            break;
+        case Expired:
+            // It's all over
+            dead = true;
+            listener.closing(KeeperException.Code.SessionExpired);
+            break;
+        }
+    } else {
+        if (path != null &amp;&amp; path.equals(znode)) {
+            // Something has changed on the node, let's find out
+            zk.exists(znode, true, this, null);
+        }
+    }
+    if (chainedWatcher != null) {
+        chainedWatcher.process(event);
+    }
+}
+</code></pre>
+<p>If the client-side ZooKeeper libraries can re-establish the communication 
channel (SyncConnected event) to ZooKeeper before session expiration (Expired 
event) all of the session's watches will automatically be re-established with 
the server (auto-reset of watches is new in ZooKeeper 3.0.0). See <a 
href="zookeeperProgrammers.html#ch_zkWatches">ZooKeeper Watches</a> in the 
programmer guide for more on this. A bit lower down in this function, when 
DataMonitor gets an event for a znode, it calls<code>ZooKeeper.exists()</code> 
to find out what has changed.</p>
+<p><a name="sc_completeSourceCode"></a></p>
+<h2>Complete Source Listings</h2>
+<h3>Executor.java</h3>
+<pre><code>/**
+ * A simple example program to use DataMonitor to start and
+ * stop executables based on a znode. The program watches the
+ * specified znode and saves the data that corresponds to the
+ * znode in the filesystem. It also starts the specified program
+ * with the specified arguments when the znode exists and kills
+ * the program if the znode goes away.
+ */
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.ZooKeeper;
+
+public class Executor
+    implements Watcher, Runnable, DataMonitor.DataMonitorListener
+{
+    String znode;
+    DataMonitor dm;
+    ZooKeeper zk;
+    String filename;
+    String exec[];
+    Process child;
+
+    public Executor(String hostPort, String znode, String filename,
+            String exec[]) throws KeeperException, IOException {
+        this.filename = filename;
+        this.exec = exec;
+        zk = new ZooKeeper(hostPort, 3000, this);
+        dm = new DataMonitor(zk, znode, null, this);
+    }
+
+    /**
+     * @param args
+     */
+    public static void main(String[] args) {
+        if (args.length &lt; 4) {
+            System.err
+                    .println(&quot;USAGE: Executor hostPort znode filename 
program [args ...]&quot;);
+            System.exit(2);
+        }
+        String hostPort = args[0];
+        String znode = args[1];
+        String filename = args[2];
+        String exec[] = new String[args.length - 3];
+        System.arraycopy(args, 3, exec, 0, exec.length);
+        try {
+            new Executor(hostPort, znode, filename, exec).run();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    
/***************************************************************************
+     * We do process any events ourselves, we just need to forward them on.
+     *
+     * @see 
org.apache.zookeeper.Watcher#process(org.apache.zookeeper.proto.WatcherEvent)
+     */
+    public void process(WatchedEvent event) {
+        dm.process(event);
+    }
+
+    public void run() {
+        try {
+            synchronized (this) {
+                while (!dm.dead) {
+                    wait();
+                }
+            }
+        } catch (InterruptedException e) {
+        }
+    }
+
+    public void closing(int rc) {
+        synchronized (this) {
+            notifyAll();
+        }
+    }
+
+    static class StreamWriter extends Thread {
+        OutputStream os;
+
+        InputStream is;
+
+        StreamWriter(InputStream is, OutputStream os) {
+            this.is = is;
+            this.os = os;
+            start();
+        }
+
+        public void run() {
+            byte b[] = new byte[80];
+            int rc;
+            try {
+                while ((rc = is.read(b)) &gt; 0) {
+                    os.write(b, 0, rc);
+                }
+            } catch (IOException e) {
+            }
+
+        }
+    }
+
+    public void exists(byte[] data) {
+        if (data == null) {
+            if (child != null) {
+                System.out.println(&quot;Killing process&quot;);
+                child.destroy();
+                try {
+                    child.waitFor();
+                } catch (InterruptedException e) {
+                }
+            }
+            child = null;
+        } else {
+            if (child != null) {
+                System.out.println(&quot;Stopping child&quot;);
+                child.destroy();
+                try {
+                    child.waitFor();
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+            }
+            try {
+                FileOutputStream fos = new FileOutputStream(filename);
+                fos.write(data);
+                fos.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            try {
+                System.out.println(&quot;Starting child&quot;);
+                child = Runtime.getRuntime().exec(exec);
+                new StreamWriter(child.getInputStream(), System.out);
+                new StreamWriter(child.getErrorStream(), System.err);
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+}
+</code></pre>
+<h3>DataMonitor.java</h3>
+<pre><code>/**
+ * A simple class that monitors the data and existence of a ZooKeeper
+ * node. It uses asynchronous ZooKeeper APIs.
+ */
+import java.util.Arrays;
+
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.AsyncCallback.StatCallback;
+import org.apache.zookeeper.KeeperException.Code;
+import org.apache.zookeeper.data.Stat;
+
+public class DataMonitor implements Watcher, StatCallback {
+
+    ZooKeeper zk;
+    String znode;
+    Watcher chainedWatcher;
+    boolean dead;
+    DataMonitorListener listener;
+    byte prevData[];
+
+    public DataMonitor(ZooKeeper zk, String znode, Watcher chainedWatcher,
+            DataMonitorListener listener) {
+        this.zk = zk;
+        this.znode = znode;
+        this.chainedWatcher = chainedWatcher;
+        this.listener = listener;
+        // Get things started by checking if the node exists. We are going
+        // to be completely event driven
+        zk.exists(znode, true, this, null);
+    }
+
+    /**
+     * Other classes use the DataMonitor by implementing this method
+     */
+    public interface DataMonitorListener {
+        /**
+         * The existence status of the node has changed.
+         */
+        void exists(byte data[]);
+
+        /**
+         * The ZooKeeper session is no longer valid.
+         *
+         * @param rc
+         *                the ZooKeeper reason code
+         */
+        void closing(int rc);
+    }
+
+    public void process(WatchedEvent event) {
+        String path = event.getPath();
+        if (event.getType() == Event.EventType.None) {
+            // We are are being told that the state of the
+            // connection has changed
+            switch (event.getState()) {
+            case SyncConnected:
+                // In this particular example we don't need to do anything
+                // here - watches are automatically re-registered with
+                // server and any watches triggered while the client was
+                // disconnected will be delivered (in order of course)
+                break;
+            case Expired:
+                // It's all over
+                dead = true;
+                listener.closing(KeeperException.Code.SessionExpired);
+                break;
+            }
+        } else {
+            if (path != null &amp;&amp; path.equals(znode)) {
+                // Something has changed on the node, let's find out
+                zk.exists(znode, true, this, null);
+            }
+        }
+        if (chainedWatcher != null) {
+            chainedWatcher.process(event);
+        }
+    }
+
+    public void processResult(int rc, String path, Object ctx, Stat stat) {
+        boolean exists;
+        switch (rc) {
+        case Code.Ok:
+            exists = true;
+            break;
+        case Code.NoNode:
+            exists = false;
+            break;
+        case Code.SessionExpired:
+        case Code.NoAuth:
+            dead = true;
+            listener.closing(rc);
+            return;
+        default:
+            // Retry errors
+            zk.exists(znode, true, this, null);
+            return;
+        }
+
+        byte b[] = null;
+        if (exists) {
+            try {
+                b = zk.getData(znode, false, null);
+            } catch (KeeperException e) {
+                // We don't need to worry about recovering now. The watch
+                // callbacks will kick off any exception handling
+                e.printStackTrace();
+            } catch (InterruptedException e) {
+                return;
+            }
+        }
+        if ((b == null &amp;&amp; b != prevData)
+                || (b != null &amp;&amp; !Arrays.equals(prevData, b))) {
+            listener.exists(b);
+            prevData = b;
+        }
+    }
+}
+</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

Added: dev/zookeeper/zookeeper-3.8.3-candidate-0/website/recipes.html
==============================================================================
--- dev/zookeeper/zookeeper-3.8.3-candidate-0/website/recipes.html (added)
+++ dev/zookeeper/zookeeper-3.8.3-candidate-0/website/recipes.html Thu Oct  5 
10:45:12 2023
@@ -0,0 +1,356 @@
+
+<!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.8 
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="zookeeperOracleQuorums.html">Oracle Quorum</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>ZooKeeper Recipes and Solutions</h1>
+<ul>
+<li><a href="#ch_recipes">A Guide to Creating Higher-level Constructs with 
ZooKeeper</a>
+<ul>
+<li><a href="#sc_recipes_errorHandlingNote">Important Note About Error 
Handling</a></li>
+<li><a href="#sc_outOfTheBox">Out of the Box Applications: Name Service, 
Configuration, Group Membership</a></li>
+<li><a href="#sc_recipes_eventHandles">Barriers</a>
+<ul>
+<li><a href="#sc_doubleBarriers">Double Barriers</a></li>
+</ul>
+</li>
+<li><a href="#sc_recipes_Queues">Queues</a>
+<ul>
+<li><a href="#sc_recipes_priorityQueues">Priority Queues</a></li>
+</ul>
+</li>
+<li><a href="#sc_recipes_Locks">Locks</a>
+<ul>
+<li><a href="#sc_recipes_GuidNote">Recoverable Errors and the GUID</a></li>
+<li><a href="#Shared+Locks">Shared Locks</a></li>
+<li><a href="#sc_revocableSharedLocks">Revocable Shared Locks</a></li>
+</ul>
+</li>
+<li><a href="#sc_recipes_twoPhasedCommit">Two-phased Commit</a></li>
+<li><a href="#sc_leaderElection">Leader Election</a></li>
+</ul>
+</li>
+</ul>
+<p><a name="ch_recipes"></a></p>
+<h2>A Guide to Creating Higher-level Constructs with ZooKeeper</h2>
+<p>In this article, you'll find guidelines for using ZooKeeper to implement 
higher order functions. All of them are conventions implemented at the client 
and do not require special support from ZooKeeper. Hopefully the community will 
capture these conventions in client-side libraries to ease their use and to 
encourage standardization.</p>
+<p>One of the most interesting things about ZooKeeper is that even though 
ZooKeeper uses <em>asynchronous</em> notifications, you can use it to build 
<em>synchronous</em> consistency primitives, such as queues and locks. As you 
will see, this is possible because ZooKeeper imposes an overall order on 
updates, and has mechanisms to expose this ordering.</p>
+<p>Note that the recipes below attempt to employ best practices. In 
particular, they avoid polling, timers or anything else that would result in a 
&quot;herd effect&quot;, causing bursts of traffic and limiting scalability.</p>
+<p>There are many useful functions that can be imagined that aren't included 
here - revocable read-write priority locks, as just one example. And some of 
the constructs mentioned here - locks, in particular - illustrate certain 
points, even though you may find other constructs, such as event handles or 
queues, a more practical means of performing the same function. In general, the 
examples in this section are designed to stimulate thought.</p>
+<p><a name="sc_recipes_errorHandlingNote"></a></p>
+<h3>Important Note About Error Handling</h3>
+<p>When implementing the recipes you must handle recoverable exceptions (see 
the <a 
href="https://cwiki.apache.org/confluence/display/ZOOKEEPER/FAQ";>FAQ</a>). In 
particular, several of the recipes employ sequential ephemeral nodes. When 
creating a sequential ephemeral node there is an error case in which the 
create() succeeds on the server but the server crashes before returning the 
name of the node to the client. When the client reconnects its session is still 
valid and, thus, the node is not removed. The implication is that it is 
difficult for the client to know if its node was created or not. The recipes 
below include measures to handle this.</p>
+<p><a name="sc_outOfTheBox"></a></p>
+<h3>Out of the Box Applications: Name Service, Configuration, Group 
Membership</h3>
+<p>Name service and configuration are two of the primary applications of 
ZooKeeper. These two functions are provided directly by the ZooKeeper API.</p>
+<p>Another function directly provided by ZooKeeper is <em>group 
membership</em>. The group is represented by a node. Members of the group 
create ephemeral nodes under the group node. Nodes of the members that fail 
abnormally will be removed automatically when ZooKeeper detects the failure.</p>
+<p><a name="sc_recipes_eventHandles"></a></p>
+<h3>Barriers</h3>
+<p>Distributed systems use <em>barriers</em> to block processing of a set of 
nodes until a condition is met at which time all the nodes are allowed to 
proceed. Barriers are implemented in ZooKeeper by designating a barrier node. 
The barrier is in place if the barrier node exists. Here's the pseudo code:</p>
+<ol>
+<li>Client calls the ZooKeeper API's <strong>exists()</strong> function on the 
barrier node, with <em>watch</em> set to true.</li>
+<li>If <strong>exists()</strong> returns false, the barrier is gone and the 
client proceeds</li>
+<li>Else, if <strong>exists()</strong> returns true, the clients wait for a 
watch event from ZooKeeper for the barrier node.</li>
+<li>When the watch event is triggered, the client reissues the <strong>exists( 
)</strong> call, again waiting until the barrier node is removed.</li>
+</ol>
+<p><a name="sc_doubleBarriers"></a></p>
+<h4>Double Barriers</h4>
+<p>Double barriers enable clients to synchronize the beginning and the end of 
a computation. When enough processes have joined the barrier, processes start 
their computation and leave the barrier once they have finished. This recipe 
shows how to use a ZooKeeper node as a barrier.</p>
+<p>The pseudo code in this recipe represents the barrier node as <em>b</em>. 
Every client process <em>p</em> registers with the barrier node on entry and 
unregisters when it is ready to leave. A node registers with the barrier node 
via the <strong>Enter</strong> procedure below, it waits until <em>x</em> 
client process register before proceeding with the computation. (The <em>x</em> 
here is up to you to determine for your system.)</p>
+<table>
+<thead>
+<tr><th> <strong>Enter</strong>                         </th><th> 
<strong>Leave</strong>                     </th></tr>
+</thead>
+<tbody>
+<tr><td> 1. Create a name <em><em>n</em> = <em>b</em>+“/”+<em>p</em></em> 
</td><td> 1. <strong>L = getChildren(b, false)</strong> </td></tr>
+<tr><td> 2. Set watch: <strong>exists(<em>b</em> + ‘‘/ready’’, 
true)</strong> </td><td> 2. if no children, exit </td></tr>
+<tr><td> 3. Create child: <strong>create(<em>n</em>, EPHEMERAL)</strong>  
</td><td> 3. if <em>p</em> is only process node in L, delete(n) and exit 
</td></tr>
+<tr><td> 4. <strong>L = getChildren(b, false)</strong>  </td><td> 4. if 
<em>p</em> is the lowest process node in L, wait on highest process node in L 
</td></tr>
+<tr><td> 5. if fewer children in L than_x_, wait for watch event  </td><td> 5. 
else **delete(<em>n</em>)**if still exists and wait on lowest process node in L 
</td></tr>
+<tr><td> 6. else <strong>create(b + ‘‘/ready’’, REGULAR)</strong> 
</td><td> 6. goto 1 </td></tr>
+</tbody>
+</table>
+<p>On entering, all processes watch on a ready node and create an ephemeral 
node as a child of the barrier node. Each process but the last enters the 
barrier and waits for the ready node to appear at line 5. The process that 
creates the xth node, the last process, will see x nodes in the list of 
children and create the ready node, waking up the other processes. Note that 
waiting processes wake up only when it is time to exit, so waiting is 
efficient.</p>
+<p>On exit, you can't use a flag such as <em>ready</em> because you are 
watching for process nodes to go away. By using ephemeral nodes, processes that 
fail after the barrier has been entered do not prevent correct processes from 
finishing. When processes are ready to leave, they need to delete their process 
nodes and wait for all other processes to do the same.</p>
+<p>Processes exit when there are no process nodes left as children of 
<em>b</em>. However, as an efficiency, you can use the lowest process node as 
the ready flag. All other processes that are ready to exit watch for the lowest 
existing process node to go away, and the owner of the lowest process watches 
for any other process node (picking the highest for simplicity) to go away. 
This means that only a single process wakes up on each node deletion except for 
the last node, which wakes up everyone when it is removed.</p>
+<p><a name="sc_recipes_Queues"></a></p>
+<h3>Queues</h3>
+<p>Distributed queues are a common data structure. To implement a distributed 
queue in ZooKeeper, first designate a znode to hold the queue, the queue node. 
The distributed clients put something into the queue by calling create() with a 
pathname ending in &quot;queue-&quot;, with the <em>sequence</em> and 
<em>ephemeral</em> flags in the create() call set to true. Because the 
<em>sequence</em> flag is set, the new pathname will have the form 
<em>path-to-queue-node</em>/queue-X, where X is a monotonic increasing number. 
A client that wants to be removed from the queue calls ZooKeeper's 
<strong>getChildren( )</strong> function, with <em>watch</em> set to true on 
the queue node, and begins processing nodes with the lowest number. The client 
does not need to issue another <strong>getChildren( )</strong> until it 
exhausts the list obtained from the first <strong>getChildren( )</strong> call. 
If there are no children in the queue node, the reader waits for a watch 
notification to check the
  queue again.</p>
+<h6>Note</h6>
+<blockquote>
+<p>There now exists a Queue implementation in ZooKeeper recipes directory. 
This is distributed with the release -- 
zookeeper-recipes/zookeeper-recipes-queue directory of the release artifact.</p>
+</blockquote>
+<p><a name="sc_recipes_priorityQueues"></a></p>
+<h4>Priority Queues</h4>
+<p>To implement a priority queue, you need only make two simple changes to the 
generic <a href="#sc_recipes_Queues">queue recipe</a> . First, to add to a 
queue, the pathname ends with &quot;queue-YY&quot; where YY is the priority of 
the element with lower numbers representing higher priority (just like UNIX). 
Second, when removing from the queue, a client uses an up-to-date children list 
meaning that the client will invalidate previously obtained children lists if a 
watch notification triggers for the queue node.</p>
+<p><a name="sc_recipes_Locks"></a></p>
+<h3>Locks</h3>
+<p>Fully distributed locks that are globally synchronous, meaning at any 
snapshot in time no two clients think they hold the same lock. These can be 
implemented using ZooKeeper. As with priority queues, first define a lock 
node.</p>
+<h6>Note</h6>
+<blockquote>
+<p>There now exists a Lock implementation in ZooKeeper recipes directory. This 
is distributed with the release -- zookeeper-recipes/zookeeper-recipes-lock 
directory of the release artifact.</p>
+</blockquote>
+<p>Clients wishing to obtain a lock do the following:</p>
+<ol>
+<li>Call <strong>create( )</strong> with a pathname of 
&quot;<em>locknode</em>/guid-lock-&quot; and the <em>sequence</em> and 
<em>ephemeral</em> flags set. The <em>guid</em> is needed in case the create() 
result is missed. See the note below.</li>
+<li>Call <strong>getChildren( )</strong> on the lock node <em>without</em> 
setting the watch flag (this is important to avoid the herd effect).</li>
+<li>If the pathname created in step <strong>1</strong> has the lowest sequence 
number suffix, the client has the lock and the client exits the protocol.</li>
+<li>The client calls <strong>exists( )</strong> with the watch flag set on the 
path in the lock directory with the next lowest sequence number.</li>
+<li>if <strong>exists( )</strong> returns null, go to step <strong>2</strong>. 
Otherwise, wait for a notification for the pathname from the previous step 
before going to step <strong>2</strong>.</li>
+</ol>
+<p>The unlock protocol is very simple: clients wishing to release a lock 
simply delete the node they created in step 1.</p>
+<p>Here are a few things to notice:</p>
+<ul>
+<li>
+<p>The removal of a node will only cause one client to wake up since each node 
is watched by exactly one client. In this way, you avoid the herd effect.</p>
+</li>
+<li>
+<p>There is no polling or timeouts.</p>
+</li>
+<li>
+<p>Because of the way you implement locking, it is easy to see the amount of 
lock contention, break locks, debug locking problems, etc.</p>
+</li>
+</ul>
+<p><a name="sc_recipes_GuidNote"></a></p>
+<h4>Recoverable Errors and the GUID</h4>
+<ul>
+<li>If a recoverable error occurs calling <strong>create()</strong> the client 
should call <strong>getChildren()</strong> and check for a node containing the 
<em>guid</em> used in the path name. This handles the case (noted <a 
href="#sc_recipes_errorHandlingNote">above</a>) of the create() succeeding on 
the server but the server crashing before returning the name of the new 
node.</li>
+</ul>
+<p><a name="Shared+Locks"></a></p>
+<h4>Shared Locks</h4>
+<p>You can implement shared locks by with a few changes to the lock 
protocol:</p>
+<table>
+<thead>
+<tr><th> <strong>Obtaining a read lock:</strong> </th><th> <strong>Obtaining a 
write lock:</strong> </th></tr>
+</thead>
+<tbody>
+<tr><td> 1. Call <strong>create( )</strong> to create a node with pathname 
&quot;<em>guid-/read-</em>&quot;. This is the lock node use later in the 
protocol. Make sure to set both the <em>sequence</em> and <em>ephemeral</em> 
flags. </td><td> 1. Call <strong>create( )</strong> to create a node with 
pathname &quot;<em>guid-/write-</em>&quot;. This is the lock node spoken of 
later in the protocol. Make sure to set both <em>sequence</em> and 
<em>ephemeral</em> flags. </td></tr>
+<tr><td> 2. Call <strong>getChildren( )</strong> on the lock node 
<em>without</em> setting the <em>watch</em> flag - this is important, as it 
avoids the herd effect. </td><td> 2. Call <strong>getChildren( )</strong> on 
the lock node <em>without</em> setting the <em>watch</em> flag - this is 
important, as it avoids the herd effect. </td></tr>
+<tr><td> 3. If there are no children with a pathname starting with 
&quot;<em>write-</em>&quot; and having a lower sequence number than the node 
created in step <strong>1</strong>, the client has the lock and can exit the 
protocol. </td><td> 3. If there are no children with a lower sequence number 
than the node created in step <strong>1</strong>, the client has the lock and 
the client exits the protocol. </td></tr>
+<tr><td> 4. Otherwise, call <strong>exists( )</strong>, with <em>watch</em> 
flag, set on the node in lock directory with pathname starting with 
&quot;<em>write-</em>&quot; having the next lowest sequence number. </td><td> 
4. Call <strong>exists( ),</strong> with <em>watch</em> flag set, on the node 
with the pathname that has the next lowest sequence number. </td></tr>
+<tr><td> 5. If <strong>exists( )</strong> returns <em>false</em>, goto step 
<strong>2</strong>. </td><td> 5. If <strong>exists( )</strong> returns 
<em>false</em>, goto step <strong>2</strong>. Otherwise, wait for a 
notification for the pathname from the previous step before going to step 
<strong>2</strong>. </td></tr>
+<tr><td> 6. Otherwise, wait for a notification for the pathname from the 
previous step before going to step <strong>2</strong> </td><td>  </td></tr>
+</tbody>
+</table>
+<p>Notes:</p>
+<ul>
+<li>
+<p>It might appear that this recipe creates a herd effect: when there is a 
large group of clients waiting for a read lock, and all getting notified more 
or less simultaneously when the &quot;<em>write-</em>&quot; node with the 
lowest sequence number is deleted. In fact. that's valid behavior: as all those 
waiting reader clients should be released since they have the lock. The herd 
effect refers to releasing a &quot;herd&quot; when in fact only a single or a 
small number of machines can proceed.</p>
+</li>
+<li>
+<p>See the <a href="#sc_recipes_GuidNote">note for Locks</a> on how to use the 
guid in the node.</p>
+</li>
+</ul>
+<p><a name="sc_revocableSharedLocks"></a></p>
+<h4>Revocable Shared Locks</h4>
+<p>With minor modifications to the Shared Lock protocol, you make shared locks 
revocable by modifying the shared lock protocol:</p>
+<p>In step <strong>1</strong>, of both obtain reader and writer lock 
protocols, call <strong>getData( )</strong> with <em>watch</em> set, 
immediately after the call to <strong>create( )</strong>. If the client 
subsequently receives notification for the node it created in step 
<strong>1</strong>, it does another <strong>getData( )</strong> on that node, 
with <em>watch</em> set and looks for the string &quot;unlock&quot;, which 
signals to the client that it must release the lock. This is because, according 
to this shared lock protocol, you can request the client with the lock give up 
the lock by calling <strong>setData()</strong> on the lock node, writing 
&quot;unlock&quot; to that node.</p>
+<p>Note that this protocol requires the lock holder to consent to releasing 
the lock. Such consent is important, especially if the lock holder needs to do 
some processing before releasing the lock. Of course you can always implement 
<em>Revocable Shared Locks with Freaking Laser Beams</em> by stipulating in 
your protocol that the revoker is allowed to delete the lock node if after some 
length of time the lock isn't deleted by the lock holder.</p>
+<p><a name="sc_recipes_twoPhasedCommit"></a></p>
+<h3>Two-phased Commit</h3>
+<p>A two-phase commit protocol is an algorithm that lets all clients in a 
distributed system agree either to commit a transaction or abort.</p>
+<p>In ZooKeeper, you can implement a two-phased commit by having a coordinator 
create a transaction node, say &quot;/app/Tx&quot;, and one child node per 
participating site, say &quot;/app/Tx/s_i&quot;. When coordinator creates the 
child node, it leaves the content undefined. Once each site involved in the 
transaction receives the transaction from the coordinator, the site reads each 
child node and sets a watch. Each site then processes the query and votes 
&quot;commit&quot; or &quot;abort&quot; by writing to its respective node. Once 
the write completes, the other sites are notified, and as soon as all sites 
have all votes, they can decide either &quot;abort&quot; or &quot;commit&quot;. 
Note that a node can decide &quot;abort&quot; earlier if some site votes for 
&quot;abort&quot;.</p>
+<p>An interesting aspect of this implementation is that the only role of the 
coordinator is to decide upon the group of sites, to create the ZooKeeper 
nodes, and to propagate the transaction to the corresponding sites. In fact, 
even propagating the transaction can be done through ZooKeeper by writing it in 
the transaction node.</p>
+<p>There are two important drawbacks of the approach described above. One is 
the message complexity, which is O(n²). The second is the impossibility of 
detecting failures of sites through ephemeral nodes. To detect the failure of a 
site using ephemeral nodes, it is necessary that the site create the node.</p>
+<p>To solve the first problem, you can have only the coordinator notified of 
changes to the transaction nodes, and then notify the sites once coordinator 
reaches a decision. Note that this approach is scalable, but it is slower too, 
as it requires all communication to go through the coordinator.</p>
+<p>To address the second problem, you can have the coordinator propagate the 
transaction to the sites, and have each site creating its own ephemeral 
node.</p>
+<p><a name="sc_leaderElection"></a></p>
+<h3>Leader Election</h3>
+<p>A simple way of doing leader election with ZooKeeper is to use the 
<strong>SEQUENCE|EPHEMERAL</strong> flags when creating znodes that represent 
&quot;proposals&quot; of clients. The idea is to have a znode, say 
&quot;/election&quot;, such that each znode creates a child znode 
&quot;/election/guid-n_&quot; with both flags SEQUENCE|EPHEMERAL. With the 
sequence flag, ZooKeeper automatically appends a sequence number that is 
greater than anyone previously appended to a child of &quot;/election&quot;. 
The process that created the znode with the smallest appended sequence number 
is the leader.</p>
+<p>That's not all, though. It is important to watch for failures of the 
leader, so that a new client arises as the new leader in the case the current 
leader fails. A trivial solution is to have all application processes watching 
upon the current smallest znode, and checking if they are the new leader when 
the smallest znode goes away (note that the smallest znode will go away if the 
leader fails because the node is ephemeral). But this causes a herd effect: 
upon a failure of the current leader, all other processes receive a 
notification, and execute getChildren on &quot;/election&quot; to obtain the 
current list of children of &quot;/election&quot;. If the number of clients is 
large, it causes a spike on the number of operations that ZooKeeper servers 
have to process. To avoid the herd effect, it is sufficient to watch for the 
next znode down on the sequence of znodes. If a client receives a notification 
that the znode it is watching is gone, then it becomes the new leader in the ca
 se that there is no smaller znode. Note that this avoids the herd effect by 
not having all clients watching the same znode.</p>
+<p>Here's the pseudo code:</p>
+<p>Let ELECTION be a path of choice of the application. To volunteer to be a 
leader:</p>
+<ol>
+<li>Create znode z with path &quot;ELECTION/guid-n_&quot; with both SEQUENCE 
and EPHEMERAL flags;</li>
+<li>Let C be the children of &quot;ELECTION&quot;, and I am the sequence 
number of z;</li>
+<li>Watch for changes on &quot;ELECTION/guid-n_j&quot;, where j is the largest 
sequence number such that j &lt; i and n_j is a znode in C;</li>
+</ol>
+<p>Upon receiving a notification of znode deletion:</p>
+<ol>
+<li>Let C be the new set of children of ELECTION;</li>
+<li>If z is the smallest node in C, then execute leader procedure;</li>
+<li>Otherwise, watch for changes on &quot;ELECTION/guid-n_j&quot;, where j is 
the largest sequence number such that j &lt; i and n_j is a znode in C;</li>
+</ol>
+<p>Notes:</p>
+<ul>
+<li>
+<p>Note that the znode having no preceding znode on the list of children do 
not imply that the creator of this znode is aware that it is the current 
leader. Applications may consider creating a separate znode to acknowledge that 
the leader has executed the leader procedure.</p>
+</li>
+<li>
+<p>See the <a href="#sc_recipes_GuidNote">note for Locks</a> on how to use the 
guid in the node.</p>
+</li>
+</ul>
+</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


Reply via email to