Added: dev/zookeeper/zookeeper-3.9.2-candidate-0/website/zookeeperQuotas.html
==============================================================================
--- dev/zookeeper/zookeeper-3.9.2-candidate-0/website/zookeeperQuotas.html 
(added)
+++ dev/zookeeper/zookeeper-3.9.2-candidate-0/website/zookeeperQuotas.html Mon 
Feb 12 21:24:47 2024
@@ -0,0 +1,238 @@
+
+<!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.9 
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="zookeeperSnapshotAndRestore.html">Snapshot and 
Restore 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 Quota's Guide</h1>
+<h3>A Guide to Deployment and Administration</h3>
+<ul>
+<li><a href="#zookeeper_quotas">Quotas</a>
+<ul>
+<li><a href="#Setting+Quotas">Setting Quotas</a></li>
+<li><a href="#Listing+Quotas">Listing Quotas</a></li>
+<li><a href="#Deleting+Quotas">Deleting Quotas</a></li>
+</ul>
+</li>
+</ul>
+<p><a name="zookeeper_quotas"></a></p>
+<h2>Quotas</h2>
+<p>ZooKeeper has both namespace and bytes quotas. You can use the 
ZooKeeperMain class to setup quotas. ZooKeeper prints <em>WARN</em> messages if 
users exceed the quota assigned to them. The messages are printed in the log of 
the ZooKeeper.</p>
+<p>Notice: What the <code>namespace</code> quota means is the count quota 
which limits the number of children under the path(included itself).</p>
+<pre><code>$ bin/zkCli.sh -server host:port**
+</code></pre>
+<p>The above command gives you a command line option of using quotas.</p>
+<p><a name="Setting+Quotas"></a></p>
+<h3>Setting Quotas</h3>
+<ul>
+<li>
+<p>You can use <code>setquota</code> to set a quota on a ZooKeeper node. It 
has an option of setting quota with <code>-n</code> (for namespace/count) and 
<code>-b</code> (for bytes/data length).</p>
+</li>
+<li>
+<p>The ZooKeeper quota is stored in ZooKeeper itself in 
<strong>/zookeeper/quota</strong>. To disable other people from changing the 
quotas, users can set the ACL for <strong>/zookeeper/quota</strong> ,so that 
only admins are able to read and write to it.</p>
+</li>
+<li>
+<p>If the quota doesn't exist in the specified path,create the quota, 
otherwise update the quota.</p>
+</li>
+<li>
+<p>The Scope of the quota users set is all the nodes under the path specified 
(included itself).</p>
+</li>
+<li>
+<p>In order to simplify the calculation of quota in the current 
directory/hierarchy structure, a complete tree path(from root to leaf node) can 
be set only one quota. In the situation when setting a quota in a path which 
its parent or child node already has a quota. <code>setquota</code> will reject 
and tell the specified parent or child path, users can adjust allocations of 
quotas(delete/move-up/move-down the quota) according to specific 
circumstances.</p>
+</li>
+<li>
+<p>Combined with the Chroot, the quota will have a better isolation 
effectiveness between different applications.For example:</p>
+<pre><code class="language-bash"># Chroot is:
+192.168.0.1:2181,192.168.0.2:2181,192.168.0.3:2181/apps/app1
+setquota -n 100000 /apps/app1
+</code></pre>
+</li>
+<li>
+<p>Users cannot set the quota on the path under 
<strong>/zookeeper/quota</strong></p>
+</li>
+<li>
+<p>The quota supports the soft and hard quota. The soft quota just logs the 
warning info when exceeding the quota, but the hard quota also throws a 
<code>QuotaExceededException</code>. When setting soft and hard quota on the 
same path, the hard quota has the priority.</p>
+</li>
+</ul>
+<p><a name="Listing+Quotas"></a></p>
+<h3>Listing Quotas</h3>
+<p>You can use <em>listquota</em> to list a quota on a ZooKeeper node.</p>
+<p><a name="Deleting+Quotas"></a></p>
+<h3>Deleting Quotas</h3>
+<p>You can use <em>delquota</em> to delete quota on a ZooKeeper node.</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.9.2-candidate-0/website/zookeeperReconfig.html
==============================================================================
--- dev/zookeeper/zookeeper-3.9.2-candidate-0/website/zookeeperReconfig.html 
(added)
+++ dev/zookeeper/zookeeper-3.9.2-candidate-0/website/zookeeperReconfig.html 
Mon Feb 12 21:24:47 2024
@@ -0,0 +1,511 @@
+
+<!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.9 
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="zookeeperSnapshotAndRestore.html">Snapshot and 
Restore 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 Dynamic Reconfiguration</h1>
+<ul>
+<li><a href="#ch_reconfig_intro">Overview</a></li>
+<li><a href="#ch_reconfig_format">Changes to Configuration Format</a>
+<ul>
+<li><a href="#sc_reconfig_clientport">Specifying the client port</a></li>
+<li><a href="#sc_multiaddress">Specifying multiple server addresses</a></li>
+<li><a href="#sc_reconfig_standaloneEnabled">The standaloneEnabled 
flag</a></li>
+<li><a href="#sc_reconfig_reconfigEnabled">The reconfigEnabled flag</a></li>
+<li><a href="#sc_reconfig_file">Dynamic configuration file</a></li>
+<li><a href="#sc_reconfig_backward">Backward compatibility</a></li>
+</ul>
+</li>
+<li><a href="#ch_reconfig_upgrade">Upgrading to 3.5.0</a></li>
+<li><a href="#ch_reconfig_dyn">Dynamic Reconfiguration of the ZooKeeper 
Ensemble</a>
+<ul>
+<li><a href="#ch_reconfig_api">API</a></li>
+<li><a href="#sc_reconfig_access_control">Security</a></li>
+<li><a href="#sc_reconfig_retrieving">Retrieving the current dynamic 
configuration</a></li>
+<li><a href="#sc_reconfig_modifying">Modifying the current dynamic 
configuration</a>
+<ul>
+<li><a href="#sc_reconfig_general">General</a></li>
+<li><a href="#sc_reconfig_incremental">Incremental mode</a></li>
+<li><a href="#sc_reconfig_nonincremental">Non-incremental mode</a></li>
+<li><a href="#sc_reconfig_conditional">Conditional reconfig</a></li>
+<li><a href="#sc_reconfig_errors">Error conditions</a></li>
+<li><a href="#sc_reconfig_additional">Additional comments</a></li>
+</ul>
+</li>
+</ul>
+</li>
+<li><a href="#ch_reconfig_rebalancing">Rebalancing Client Connections</a></li>
+</ul>
+<p><a name="ch_reconfig_intro"></a></p>
+<h2>Overview</h2>
+<p>Prior to the 3.5.0 release, the membership and all other configuration 
parameters of Zookeeper were static - loaded during boot and immutable at 
runtime. Operators resorted to ''rolling restarts'' - a manually intensive and 
error-prone method of changing the configuration that has caused data loss and 
inconsistency in production.</p>
+<p>Starting with 3.5.0, “rolling restarts” are no longer needed! ZooKeeper 
comes with full support for automated configuration changes: the set of 
Zookeeper servers, their roles (participant / observer), all ports, and even 
the quorum system can be changed dynamically, without service interruption and 
while maintaining data consistency. Reconfigurations are performed immediately, 
just like other operations in ZooKeeper. Multiple changes can be done using a 
single reconfiguration command. The dynamic reconfiguration functionality does 
not limit operation concurrency, does not require client operations to be 
stopped during reconfigurations, has a very simple interface for administrators 
and no added complexity to other client operations.</p>
+<p>New client-side features allow clients to find out about configuration 
changes and to update the connection string (list of servers and their client 
ports) stored in their ZooKeeper handle. A probabilistic algorithm is used to 
rebalance clients across the new configuration servers while keeping the extent 
of client migrations proportional to the change in ensemble membership.</p>
+<p>This document provides the administrator manual for reconfiguration. For a 
detailed description of the reconfiguration algorithms, performance 
measurements, and more, please see our paper:</p>
+<ul>
+<li><em>Shraer, A., Reed, B., Malkhi, D., Junqueira, F. Dynamic 
Reconfiguration of Primary/Backup Clusters. In <em>USENIX Annual Technical 
Conference (ATC)</em>(2012), 425-437</em> : Links: <a 
href="https://www.usenix.org/system/files/conference/atc12/atc12-final74.pdf";>paper
 (pdf)</a>, <a 
href="https://www.usenix.org/sites/default/files/conference/protected-files/shraer_atc12_slides.pdf";>slides
 (pdf)</a>, <a 
href="https://www.usenix.org/conference/atc12/technical-sessions/presentation/shraer";>video</a>,
 <a 
href="http://www.slideshare.net/Hadoop_Summit/dynamic-reconfiguration-of-zookeeper";>hadoop
 summit slides</a></li>
+</ul>
+<p><strong>Note:</strong> Starting with 3.5.3, the dynamic reconfiguration 
feature is disabled by default, and has to be explicitly turned on via <a 
href="zookeeperAdmin.html#sc_advancedConfiguration">reconfigEnabled</a> 
configuration option.</p>
+<p><a name="ch_reconfig_format"></a></p>
+<h2>Changes to Configuration Format</h2>
+<p><a name="sc_reconfig_clientport"></a></p>
+<h3>Specifying the client port</h3>
+<p>A client port of a server is the port on which the server accepts client 
connection requests. Starting with 3.5.0 the <em>clientPort</em> and 
<em>clientPortAddress</em> configuration parameters should no longer be used. 
Instead, this information is now part of the server keyword specification, 
which becomes as follows:</p>
+<pre><code>server.&lt;positive id&gt; = 
&lt;address1&gt;:&lt;port1&gt;:&lt;port2&gt;[:role];[&lt;client port 
address&gt;:]&lt;client port&gt;**
+</code></pre>
+<p>The client port specification is to the right of the semicolon. The client 
port address is optional, and if not specified it defaults to 
&quot;0.0.0.0&quot;. As usual, role is also optional, it can be 
<em>participant</em> or <em>observer</em> (<em>participant</em> by default).</p>
+<p>Examples of legal server statements:</p>
+<pre><code>server.5 = 125.23.63.23:1234:1235;1236
+server.5 = 125.23.63.23:1234:1235:participant;1236
+server.5 = 125.23.63.23:1234:1235:observer;1236
+server.5 = 125.23.63.23:1234:1235;125.23.63.24:1236
+server.5 = 125.23.63.23:1234:1235:participant;125.23.63.23:1236
+</code></pre>
+<p><a name="sc_multiaddress"></a></p>
+<h3>Specifying multiple server addresses</h3>
+<p>Since ZooKeeper 3.6.0 it is possible to specify multiple addresses for each 
ZooKeeper server (see <a 
href="https://issues.apache.org/jira/projects/ZOOKEEPER/issues/ZOOKEEPER-3188";>ZOOKEEPER-3188</a>).
 This helps to increase availability and adds network level resiliency to 
ZooKeeper. When multiple physical network interfaces are used for the servers, 
ZooKeeper is able to bind on all interfaces and runtime switching to a working 
interface in case a network error. The different addresses can be specified in 
the config using a pipe ('|') character.</p>
+<p>Examples for a valid configurations using multiple addresses:</p>
+<pre><code>server.2=zoo2-net1:2888:3888|zoo2-net2:2889:3889;2188
+server.2=zoo2-net1:2888:3888|zoo2-net2:2889:3889|zoo2-net3:2890:3890;2188
+server.2=zoo2-net1:2888:3888|zoo2-net2:2889:3889;zoo2-net1:2188
+server.2=zoo2-net1:2888:3888:observer|zoo2-net2:2889:3889:observer;2188
+</code></pre>
+<p><a name="sc_reconfig_standaloneEnabled"></a></p>
+<h3>The <em>standaloneEnabled</em> flag</h3>
+<p>Prior to 3.5.0, one could run ZooKeeper in Standalone mode or in a 
Distributed mode. These are separate implementation stacks, and switching 
between them during run time is not possible. By default (for backward 
compatibility) <em>standaloneEnabled</em> is set to <em>true</em>. The 
consequence of using this default is that if started with a single server the 
ensemble will not be allowed to grow, and if started with more than one server 
it will not be allowed to shrink to contain fewer than two participants.</p>
+<p>Setting the flag to <em>false</em> instructs the system to run the 
Distributed software stack even if there is only a single participant in the 
ensemble. To achieve this the (static) configuration file should contain:</p>
+<pre><code>standaloneEnabled=false**
+</code></pre>
+<p>With this setting it is possible to start a ZooKeeper ensemble containing a 
single participant and to dynamically grow it by adding more servers. 
Similarly, it is possible to shrink an ensemble so that just a single 
participant remains, by removing servers.</p>
+<p>Since running the Distributed mode allows more flexibility, we recommend 
setting the flag to <em>false</em>. We expect that the legacy Standalone mode 
will be deprecated in the future.</p>
+<p><a name="sc_reconfig_reconfigEnabled"></a></p>
+<h3>The <em>reconfigEnabled</em> flag</h3>
+<p>Starting with 3.5.0 and prior to 3.5.3, there is no way to disable dynamic 
reconfiguration feature. We would like to offer the option of disabling 
reconfiguration feature because with reconfiguration enabled, we have a 
security concern that a malicious actor can make arbitrary changes to the 
configuration of a ZooKeeper ensemble, including adding a compromised server to 
the ensemble. We prefer to leave to the discretion of the user to decide 
whether to enable it or not and make sure that the appropriate security measure 
are in place. So in 3.5.3 the <a 
href="zookeeperAdmin.html#sc_advancedConfiguration">reconfigEnabled</a> 
configuration option is introduced such that the reconfiguration feature can be 
completely disabled and any attempts to reconfigure a cluster through reconfig 
API with or without authentication will fail by default, unless 
<strong>reconfigEnabled</strong> is set to <strong>true</strong>.</p>
+<p>To set the option to true, the configuration file (zoo.cfg) should 
contain:</p>
+<pre><code>reconfigEnabled=true
+</code></pre>
+<p><a name="sc_reconfig_file"></a></p>
+<h3>Dynamic configuration file</h3>
+<p>Starting with 3.5.0 we're distinguishing between dynamic configuration 
parameters, which can be changed during runtime, and static configuration 
parameters, which are read from a configuration file when a server boots and 
don't change during its execution. For now, the following configuration 
keywords are considered part of the dynamic configuration: <em>server</em>, 
<em>group</em> and <em>weight</em>.</p>
+<p>Dynamic configuration parameters are stored in a separate file on the 
server (which we call the dynamic configuration file). This file is linked from 
the static config file using the new <em>dynamicConfigFile</em> keyword.</p>
+<p><strong>Example</strong></p>
+<h4>zoo_replicated1.cfg</h4>
+<pre><code>tickTime=2000
+dataDir=/zookeeper/data/zookeeper1
+initLimit=5
+syncLimit=2
+dynamicConfigFile=/zookeeper/conf/zoo_replicated1.cfg.dynamic
+</code></pre>
+<h4>zoo_replicated1.cfg.dynamic</h4>
+<pre><code>server.1=125.23.63.23:2780:2783:participant;2791
+server.2=125.23.63.24:2781:2784:participant;2792
+server.3=125.23.63.25:2782:2785:participant;2793
+</code></pre>
+<p>When the ensemble configuration changes, the static configuration 
parameters remain the same. The dynamic parameters are pushed by ZooKeeper and 
overwrite the dynamic configuration files on all servers. Thus, the dynamic 
configuration files on the different servers are usually identical (they can 
only differ momentarily when a reconfiguration is in progress, or if a new 
configuration hasn't propagated yet to some of the servers). Once created, the 
dynamic configuration file should not be manually altered. Changed are only 
made through the new reconfiguration commands outlined below. Note that 
changing the config of an offline cluster could result in an inconsistency with 
respect to configuration information stored in the ZooKeeper log (and the 
special configuration znode, populated from the log) and is therefore highly 
discouraged.</p>
+<p><strong>Example 2</strong></p>
+<p>Users may prefer to initially specify a single configuration file. The 
following is thus also legal:</p>
+<h4>zoo_replicated1.cfg</h4>
+<pre><code>tickTime=2000
+dataDir=/zookeeper/data/zookeeper1
+initLimit=5
+syncLimit=2
+clientPort=
+</code></pre>
+<p>The configuration files on each server will be automatically split into 
dynamic and static files, if they are not already in this format. So the 
configuration file above will be automatically transformed into the two files 
in Example 1. Note that the clientPort and clientPortAddress lines (if 
specified) will be automatically removed during this process, if they are 
redundant (as in the example above). The original static configuration file is 
backed up (in a .bak file).</p>
+<p><a name="sc_reconfig_backward"></a></p>
+<h3>Backward compatibility</h3>
+<p>We still support the old configuration format. For example, the following 
configuration file is acceptable (but not recommended):</p>
+<h4>zoo_replicated1.cfg</h4>
+<pre><code>tickTime=2000
+dataDir=/zookeeper/data/zookeeper1
+initLimit=5
+syncLimit=2
+clientPort=2791
+server.1=125.23.63.23:2780:2783:participant
+server.2=125.23.63.24:2781:2784:participant
+server.3=125.23.63.25:2782:2785:participant
+</code></pre>
+<p>During boot, a dynamic configuration file is created and contains the 
dynamic part of the configuration as explained earlier. In this case, however, 
the line &quot;clientPort=2791&quot; will remain in the static configuration 
file of server 1 since it is not redundant -- it was not specified as part of 
the &quot;server.1=...&quot; using the format explained in the section <a 
href="#ch_reconfig_format">Changes to Configuration Format</a>. If a 
reconfiguration is invoked that sets the client port of server 1, we remove 
&quot;clientPort=2791&quot; from the static configuration file (the dynamic 
file now contain this information as part of the specification of server 1).</p>
+<p><a name="ch_reconfig_upgrade"></a></p>
+<h2>Upgrading to 3.5.0</h2>
+<p>Upgrading a running ZooKeeper ensemble to 3.5.0 should be done only after 
upgrading your ensemble to the 3.4.6 release. Note that this is only necessary 
for rolling upgrades (if you're fine with shutting down the system completely, 
you don't have to go through 3.4.6). If you attempt a rolling upgrade without 
going through 3.4.6 (for example from 3.4.5), you may get the following 
error:</p>
+<pre><code>2013-01-30 11:32:10,663 [myid:2] - INFO 
[localhost/127.0.0.1:2784:QuorumCnxManager$Listener@498] - Received connection 
request /127.0.0.1:60876
+2013-01-30 11:32:10,663 [myid:2] - WARN 
[localhost/127.0.0.1:2784:QuorumCnxManager@349] - Invalid server id: -65536
+</code></pre>
+<p>During a rolling upgrade, each server is taken down in turn and rebooted 
with the new 3.5.0 binaries. Before starting the server with 3.5.0 binaries, we 
highly recommend updating the configuration file so that all server statements 
&quot;server.x=...&quot; contain client ports (see the section <a 
href="#sc_reconfig_clientport">Specifying the client port</a>). As explained 
earlier you may leave the configuration in a single file, as well as leave the 
clientPort/clientPortAddress statements (although if you specify client ports 
in the new format, these statements are now redundant).</p>
+<p><a name="ch_reconfig_dyn"></a></p>
+<h2>Dynamic Reconfiguration of the ZooKeeper Ensemble</h2>
+<p>The ZooKeeper Java and C API were extended with getConfig and reconfig 
commands that facilitate reconfiguration. Both commands have a synchronous 
(blocking) variant and an asynchronous one. We demonstrate these commands here 
using the Java CLI, but note that you can similarly use the C CLI or invoke the 
commands directly from a program just like any other ZooKeeper command.</p>
+<p><a name="ch_reconfig_api"></a></p>
+<h3>API</h3>
+<p>There are two sets of APIs for both Java and C client.</p>
+<ul>
+<li>
+<p><strong><em>Reconfiguration API</em></strong> : Reconfiguration API is used 
to reconfigure the ZooKeeper cluster. Starting with 3.5.3, reconfiguration Java 
APIs are moved into ZooKeeperAdmin class from ZooKeeper class, and use of this 
API requires ACL setup and user authentication (see <a 
href="#sc_reconfig_access_control">Security</a> for more information.).</p>
+</li>
+<li>
+<p><strong><em>Get Configuration API</em></strong> : Get configuration APIs 
are used to retrieve ZooKeeper cluster configuration information stored in 
/zookeeper/config znode. Use of this API does not require specific setup or 
authentication, because /zookeeper/config is readable to any users.</p>
+</li>
+</ul>
+<p><a name="sc_reconfig_access_control"></a></p>
+<h3>Security</h3>
+<p>Prior to <strong>3.5.3</strong>, there is no enforced security mechanism 
over reconfig so any ZooKeeper clients that can connect to ZooKeeper server 
ensemble will have the ability to change the state of a ZooKeeper cluster via 
reconfig. It is thus possible for a malicious client to add compromised server 
to an ensemble, e.g., add a compromised server, or remove legitimate servers. 
Cases like these could be security vulnerabilities on a case by case basis.</p>
+<p>To address this security concern, we introduced access control over 
reconfig starting from <strong>3.5.3</strong> such that only a specific set of 
users can use reconfig commands or APIs, and these users need be configured 
explicitly. In addition, the setup of ZooKeeper cluster must enable 
authentication so ZooKeeper clients can be authenticated.</p>
+<p>We also provide an escape hatch for users who operate and interact with a 
ZooKeeper ensemble in a secured environment (i.e. behind company firewall). For 
those users who want to use reconfiguration feature but don't want the overhead 
of configuring an explicit list of authorized user for reconfig access checks, 
they can set <a 
href="zookeeperAdmin.html#sc_authOptions">&quot;skipACL&quot;</a> to 
&quot;yes&quot; which will skip ACL check and allow any user to reconfigure 
cluster.</p>
+<p>Overall, ZooKeeper provides flexible configuration options for the 
reconfigure feature that allow a user to choose based on user's security 
requirement. We leave to the discretion of the user to decide appropriate 
security measure are in place.</p>
+<ul>
+<li>
+<p><strong><em>Access Control</em></strong> : The dynamic configuration is 
stored in a special znode ZooDefs.CONFIG_NODE = /zookeeper/config. This node by 
default is read only for all users, except super user and users that's 
explicitly configured for write access. Clients that need to use reconfig 
commands or reconfig API should be configured as users that have write access 
to CONFIG_NODE. By default, only the super user has full control including 
write access to CONFIG_NODE. Additional users can be granted write access 
through superuser by setting an ACL that has write permission associated with 
specified user. A few examples of how to setup ACLs and use reconfiguration API 
with authentication can be found in ReconfigExceptionTest.java and 
TestReconfigServer.cc.</p>
+</li>
+<li>
+<p><strong><em>Authentication</em></strong> : Authentication of users is 
orthogonal to the access control and is delegated to existing authentication 
mechanism supported by ZooKeeper's pluggable authentication schemes. See <a 
href="https://cwiki.apache.org/confluence/display/ZOOKEEPER/Zookeeper+and+SASL";>ZooKeeper
 and SASL</a> for more details on this topic.</p>
+</li>
+<li>
+<p><strong><em>Disable ACL check</em></strong> : ZooKeeper supports <a 
href="zookeeperAdmin.html#sc_authOptions">&quot;skipACL&quot;</a> option such 
that ACL check will be completely skipped, if skipACL is set to 
&quot;yes&quot;. In such cases any unauthenticated users can use reconfig 
API.</p>
+</li>
+</ul>
+<p><a name="sc_reconfig_retrieving"></a></p>
+<h3>Retrieving the current dynamic configuration</h3>
+<p>The dynamic configuration is stored in a special znode ZooDefs.CONFIG_NODE 
= /zookeeper/config. The new <code>config</code> CLI command reads this znode 
(currently it is simply a wrapper to <code>get /zookeeper/config</code>). As 
with normal reads, to retrieve the latest committed value you should do a 
<code>sync</code> first.</p>
+<pre><code>[zk: 127.0.0.1:2791(CONNECTED) 3] config
+server.1=localhost:2780:2783:participant;localhost:2791
+server.2=localhost:2781:2784:participant;localhost:2792
+server.3=localhost:2782:2785:participant;localhost:2793
+</code></pre>
+<p>Notice the last line of the output. This is the configuration version. The 
version equals to the zxid of the reconfiguration command which created this 
configuration. The version of the first established configuration equals to the 
zxid of the NEWLEADER message sent by the first successfully established 
leader. When a configuration is written to a dynamic configuration file, the 
version automatically becomes part of the filename and the static configuration 
file is updated with the path to the new dynamic configuration file. 
Configuration files corresponding to earlier versions are retained for backup 
purposes.</p>
+<p>During boot time the version (if it exists) is extracted from the filename. 
The version should never be altered manually by users or the system 
administrator. It is used by the system to know which configuration is most 
up-to-date. Manipulating it manually can result in data loss and 
inconsistency.</p>
+<p>Just like a <code>get</code> command, the <code>config</code> CLI command 
accepts the <em>-w</em> flag for setting a watch on the znode, and <em>-s</em> 
flag for displaying the Stats of the znode. It additionally accepts a new flag 
<em>-c</em> which outputs only the version and the client connection string 
corresponding to the current configuration. For example, for the configuration 
above we would get:</p>
+<pre><code>[zk: 127.0.0.1:2791(CONNECTED) 17] config -c
+400000003 localhost:2791,localhost:2793,localhost:2792
+</code></pre>
+<p>Note that when using the API directly, this command is called 
<code>getConfig</code>.</p>
+<p>As any read command it returns the configuration known to the follower to 
which your client is connected, which may be slightly out-of-date. One can use 
the <code>sync</code> command for stronger guarantees. For example using the 
Java API:</p>
+<pre><code>zk.sync(ZooDefs.CONFIG_NODE, void_callback, context);
+zk.getConfig(watcher, callback, context);
+</code></pre>
+<p>Note: in 3.5.0 it doesn't really matter which path is passed to the 
<code>sync()</code> command as all the server's state is brought up to date 
with the leader (so one could use a different path instead of 
ZooDefs.CONFIG_NODE). However, this may change in the future.</p>
+<p><a name="sc_reconfig_modifying"></a></p>
+<h3>Modifying the current dynamic configuration</h3>
+<p>Modifying the configuration is done through the <code>reconfig</code> 
command. There are two modes of reconfiguration: incremental and 
non-incremental (bulk). The non-incremental simply specifies the new dynamic 
configuration of the system. The incremental specifies changes to the current 
configuration. The <code>reconfig</code> command returns the new 
configuration.</p>
+<p>A few examples are in: <em>ReconfigTest.java</em>, 
<em>ReconfigRecoveryTest.java</em> and <em>TestReconfigServer.cc</em>.</p>
+<p><a name="sc_reconfig_general"></a></p>
+<h4>General</h4>
+<p><strong>Removing servers:</strong> Any server can be removed, including the 
leader (although removing the leader will result in a short unavailability, see 
Figures 6 and 8 in the <a 
href="https://www.usenix.org/conference/usenixfederatedconferencesweek/dynamic-recon%EF%AC%81guration-primarybackup-clusters";>paper</a>).
 The server will not be shut-down automatically. Instead, it becomes a 
&quot;non-voting follower&quot;. This is somewhat similar to an observer in 
that its votes don't count towards the Quorum of votes necessary to commit 
operations. However, unlike a non-voting follower, an observer doesn't actually 
see any operation proposals and does not ACK them. Thus a non-voting follower 
has a more significant negative effect on system throughput compared to an 
observer. Non-voting follower mode should only be used as a temporary mode, 
before shutting the server down, or adding it as a follower or as an observer 
to the ensemble. We do not shut the server down automatically for 
 two main reasons. The first reason is that we do not want all the clients 
connected to this server to be immediately disconnected, causing a flood of 
connection requests to other servers. Instead, it is better if each client 
decides when to migrate independently. The second reason is that removing a 
server may sometimes (rarely) be necessary in order to change it from 
&quot;observer&quot; to &quot;participant&quot; (this is explained in the 
section <a href="#sc_reconfig_additional">Additional comments</a>).</p>
+<p>Note that the new configuration should have some minimal number of 
participants in order to be considered legal. If the proposed change would 
leave the cluster with less than 2 participants and standalone mode is enabled 
(standaloneEnabled=true, see the section <a 
href="#sc_reconfig_standaloneEnabled">The <em>standaloneEnabled</em> flag</a>), 
the reconfig will not be processed (BadArgumentsException). If standalone mode 
is disabled (standaloneEnabled=false) then it's legal to remain with 1 or more 
participants.</p>
+<p><strong>Adding servers:</strong> Before a reconfiguration is invoked, the 
administrator must make sure that a quorum (majority) of participants from the 
new configuration are already connected and synced with the current leader. To 
achieve this we need to connect a new joining server to the leader before it is 
officially part of the ensemble. This is done by starting the joining server 
using an initial list of servers which is technically not a legal configuration 
of the system but (a) contains the joiner, and (b) gives sufficient information 
to the joiner in order for it to find and connect to the current leader. We 
list a few different options of doing this safely.</p>
+<ol>
+<li>Initial configuration of joiners is comprised of servers in the last 
committed configuration and one or more joiners, where <strong>joiners are 
listed as observers.</strong> For example, if servers D and E are added at the 
same time to (A, B, C) and server C is being removed, the initial configuration 
of D could be (A, B, C, D) or (A, B, C, D, E), where D and E are listed as 
observers. Similarly, the configuration of E could be (A, B, C, E) or (A, B, C, 
D, E), where D and E are listed as observers. <strong>Note that listing the 
joiners as observers will not actually make them observers - it will only 
prevent them from accidentally forming a quorum with other joiners.</strong> 
Instead, they will contact the servers in the current configuration and adopt 
the last committed configuration (A, B, C), where the joiners are absent. 
Configuration files of joiners are backed up and replaced automatically as this 
happens. After connecting to the current leader, joiners become non-voting f
 ollowers until the system is reconfigured and they are added to the ensemble 
(as participant or observer, as appropriate).</li>
+<li>Initial configuration of each joiner is comprised of servers in the last 
committed configuration + <strong>the joiner itself, listed as a 
participant.</strong> For example, to add a new server D to a configuration 
consisting of servers (A, B, C), the administrator can start D using an initial 
configuration file consisting of servers (A, B, C, D). If both D and E are 
added at the same time to (A, B, C), the initial configuration of D could be 
(A, B, C, D) and the configuration of E could be (A, B, C, E). Similarly, if D 
is added and C is removed at the same time, the initial configuration of D 
could be (A, B, C, D). Never list more than one joiner as participant in the 
initial configuration (see warning below).</li>
+<li>Whether listing the joiner as an observer or as participant, it is also 
fine not to list all the current configuration servers, as long as the current 
leader is in the list. For example, when adding D we could start D with a 
configuration file consisting of just (A, D) if A is the current leader. 
however this is more fragile since if A fails before D officially joins the 
ensemble, D doesn’t know anyone else and therefore the administrator will 
have to intervene and restart D with another server list.</li>
+</ol>
+<h6>Note</h6>
+<blockquote>
+<h5>Warning</h5>
+<p>Never specify more than one joining server in the same initial 
configuration as participants. Currently, the joining servers don’t know that 
they are joining an existing ensemble; if multiple joiners are listed as 
participants they may form an independent quorum creating a split-brain 
situation such as processing operations independently from your main ensemble. 
It is OK to list multiple joiners as observers in an initial config.</p>
+</blockquote>
+<p>If the configuration of existing servers changes or they become unavailable 
before the joiner succeeds to connect and learn about configuration changes, 
the joiner may need to be restarted with an updated configuration file in order 
to be able to connect.</p>
+<p>Finally, note that once connected to the leader, a joiner adopts the last 
committed configuration, in which it is absent (the initial config of the 
joiner is backed up before being rewritten). If the joiner restarts in this 
state, it will not be able to boot since it is absent from its configuration 
file. In order to start it you’ll once again have to specify an initial 
configuration.</p>
+<p><strong>Modifying server parameters:</strong> One can modify any of the 
ports of a server, or its role (participant/observer) by adding it to the 
ensemble with different parameters. This works in both the incremental and the 
bulk reconfiguration modes. It is not necessary to remove the server and then 
add it back; just specify the new parameters as if the server is not yet in the 
system. The server will detect the configuration change and perform the 
necessary adjustments. See an example in the section <a 
href="#sc_reconfig_incremental">Incremental mode</a> and an exception to this 
rule in the section <a href="#sc_reconfig_additional">Additional 
comments</a>.</p>
+<p>It is also possible to change the Quorum System used by the ensemble (for 
example, change the Majority Quorum System to a Hierarchical Quorum System on 
the fly). This, however, is only allowed using the bulk (non-incremental) 
reconfiguration mode. In general, incremental reconfiguration only works with 
the Majority Quorum System. Bulk reconfiguration works with both Hierarchical 
and Majority Quorum Systems.</p>
+<p><strong>Performance Impact:</strong> There is practically no performance 
impact when removing a follower, since it is not being automatically shut down 
(the effect of removal is that the server's votes are no longer being counted). 
When adding a server, there is no leader change and no noticeable performance 
disruption. For details and graphs please see Figures 6, 7 and 8 in the <a 
href="https://www.usenix.org/conference/usenixfederatedconferencesweek/dynamic-recon%EF%AC%81guration-primarybackup-clusters";>paper</a>.</p>
+<p>The most significant disruption will happen when a leader change is caused, 
in one of the following cases:</p>
+<ol>
+<li>Leader is removed from the ensemble.</li>
+<li>Leader's role is changed from participant to observer.</li>
+<li>The port used by the leader to send transactions to others (quorum port) 
is modified.</li>
+</ol>
+<p>In these cases we perform a leader hand-off where the old leader nominates 
a new leader. The resulting unavailability is usually shorter than when a 
leader crashes since detecting leader failure is unnecessary and electing a new 
leader can usually be avoided during a hand-off (see Figures 6 and 8 in the <a 
href="https://www.usenix.org/conference/usenixfederatedconferencesweek/dynamic-recon%EF%AC%81guration-primarybackup-clusters";>paper</a>).</p>
+<p>When the client port of a server is modified, it does not drop existing 
client connections. New connections to the server will have to use the new 
client port.</p>
+<p><strong>Progress guarantees:</strong> Up to the invocation of the reconfig 
operation, a quorum of the old configuration is required to be available and 
connected for ZooKeeper to be able to make progress. Once reconfig is invoked, 
a quorum of both the old and of the new configurations must be available. The 
final transition happens once (a) the new configuration is activated, and (b) 
all operations scheduled before the new configuration is activated by the 
leader are committed. Once (a) and (b) happen, only a quorum of the new 
configuration is required. Note, however, that neither (a) nor (b) are visible 
to a client. Specifically, when a reconfiguration operation commits, it only 
means that an activation message was sent out by the leader. It does not 
necessarily mean that a quorum of the new configuration got this message (which 
is required in order to activate it) or that (b) has happened. If one wants to 
make sure that both (a) and (b) has already occurred (for example, in ord
 er to know that it is safe to shut down old servers that were removed), one 
can simply invoke an update (<code>set-data</code>, or some other quorum 
operation, but not a <code>sync</code>) and wait for it to commit. An 
alternative way to achieve this was to introduce another round to the 
reconfiguration protocol (which, for simplicity and compatibility with Zab, we 
decided to avoid).</p>
+<p><a name="sc_reconfig_incremental"></a></p>
+<h4>Incremental mode</h4>
+<p>The incremental mode allows adding and removing servers to the current 
configuration. Multiple changes are allowed. For example:</p>
+<pre><code>&gt; reconfig -remove 3 -add
+server.5=125.23.63.23:1234:1235;1236
+</code></pre>
+<p>Both the add and the remove options get a list of comma separated arguments 
(no spaces):</p>
+<pre><code>&gt; reconfig -remove 3,4 -add
+server.5=localhost:2111:2112;2113,6=localhost:2114:2115:observer;2116
+</code></pre>
+<p>The format of the server statement is exactly the same as described in the 
section <a href="#sc_reconfig_clientport">Specifying the client port</a> and 
includes the client port. Notice that here instead of &quot;server.5=&quot; you 
can just say &quot;5=&quot;. In the example above, if server 5 is already in 
the system, but has different ports or is not an observer, it is updated and 
once the configuration commits becomes an observer and starts using these new 
ports. This is an easy way to turn participants into observers and vice versa 
or change any of their ports, without rebooting the server.</p>
+<p>ZooKeeper supports two types of Quorum Systems – the simple Majority 
system (where the leader commits operations after receiving ACKs from a 
majority of voters) and a more complex Hierarchical system, where votes of 
different servers have different weights and servers are divided into voting 
groups. Currently, incremental reconfiguration is allowed only if the last 
proposed configuration known to the leader uses a Majority Quorum System 
(BadArgumentsException is thrown otherwise).</p>
+<p>Incremental mode - examples using the Java API:</p>
+<pre><code>List&lt;String&gt; leavingServers = new ArrayList&lt;String&gt;();
+leavingServers.add(&quot;1&quot;);
+leavingServers.add(&quot;2&quot;);
+byte[] config = zk.reconfig(null, leavingServers, null, -1, new Stat());
+
+List&lt;String&gt; leavingServers = new ArrayList&lt;String&gt;();
+List&lt;String&gt; joiningServers = new ArrayList&lt;String&gt;();
+leavingServers.add(&quot;1&quot;);
+joiningServers.add(&quot;server.4=localhost:1234:1235;1236&quot;);
+byte[] config = zk.reconfig(joiningServers, leavingServers, null, -1, new 
Stat());
+
+String configStr = new String(config);
+System.out.println(configStr);
+</code></pre>
+<p>There is also an asynchronous API, and an API accepting comma separated 
Strings instead of List<String>. See 
src/java/main/org/apache/zookeeper/ZooKeeper.java.</p>
+<p><a name="sc_reconfig_nonincremental"></a></p>
+<h4>Non-incremental mode</h4>
+<p>The second mode of reconfiguration is non-incremental, whereby a client 
gives a complete specification of the new dynamic system configuration. The new 
configuration can either be given in place or read from a file:</p>
+<pre><code>&gt; reconfig -file newconfig.cfg
+</code></pre>
+<p>//newconfig.cfg is a dynamic config file, see <a 
href="#sc_reconfig_file">Dynamic configuration file</a></p>
+<pre><code>&gt; reconfig -members
+server.1=125.23.63.23:2780:2783:participant;2791,server.2=125.23.63.24:2781:2784:participant;2792,server.3=125.23.63.25:2782:2785:participant;2793}}
+</code></pre>
+<p>The new configuration may use a different Quorum System. For example, you 
may specify a Hierarchical Quorum System even if the current ensemble uses a 
Majority Quorum System.</p>
+<p>Bulk mode - example using the Java API:</p>
+<pre><code>List&lt;String&gt; newMembers = new ArrayList&lt;String&gt;();
+newMembers.add(&quot;server.1=1111:1234:1235;1236&quot;);
+newMembers.add(&quot;server.2=1112:1237:1238;1239&quot;);
+newMembers.add(&quot;server.3=1114:1240:1241:observer;1242&quot;);
+
+byte[] config = zk.reconfig(null, null, newMembers, -1, new Stat());
+
+String configStr = new String(config);
+System.out.println(configStr);
+</code></pre>
+<p>There is also an asynchronous API, and an API accepting comma separated 
String containing the new members instead of List<String>. See 
src/java/main/org/apache/zookeeper/ZooKeeper.java.</p>
+<p><a name="sc_reconfig_conditional"></a></p>
+<h4>Conditional reconfig</h4>
+<p>Sometimes (especially in non-incremental mode) a new proposed configuration 
depends on what the client &quot;believes&quot; to be the current 
configuration, and should be applied only to that configuration. Specifically, 
the <code>reconfig</code> succeeds only if the last configuration at the leader 
has the specified version.</p>
+<pre><code>&gt; reconfig -file &lt;filename&gt; -v &lt;version&gt;
+</code></pre>
+<p>In the previously listed Java examples, instead of -1 one could specify a 
configuration version to condition the reconfiguration.</p>
+<p><a name="sc_reconfig_errors"></a></p>
+<h4>Error conditions</h4>
+<p>In addition to normal ZooKeeper error conditions, a reconfiguration may 
fail for the following reasons:</p>
+<ol>
+<li>another reconfig is currently in progress (ReconfigInProgress)</li>
+<li>the proposed change would leave the cluster with less than 2 participants, 
in case standalone mode is enabled, or, if standalone mode is disabled then its 
legal to remain with 1 or more participants (BadArgumentsException)</li>
+<li>no quorum of the new configuration was connected and up-to-date with the 
leader when the reconfiguration processing began (NewConfigNoQuorum)</li>
+<li><code>-v x</code> was specified, but the version <code>y</code> of the 
latest configuration is not <code>x</code> (BadVersionException)</li>
+<li>an incremental reconfiguration was requested but the last configuration at 
the leader uses a Quorum System which is different from the Majority system 
(BadArgumentsException)</li>
+<li>syntax error (BadArgumentsException)</li>
+<li>I/O exception when reading the configuration from a file 
(BadArgumentsException)</li>
+</ol>
+<p>Most of these are illustrated by test-cases in 
<em>ReconfigFailureCases.java</em>.</p>
+<p><a name="sc_reconfig_additional"></a></p>
+<h4>Additional comments</h4>
+<p><strong>Liveness:</strong> To better understand the difference between 
incremental and non-incremental reconfiguration, suppose that client C1 adds 
server D to the system while a different client C2 adds server E. With the 
non-incremental mode, each client would first invoke <code>config</code> to 
find out the current configuration, and then locally create a new list of 
servers by adding its own suggested server. The new configuration can then be 
submitted using the non-incremental <code>reconfig</code> command. After both 
reconfigurations complete, only one of E or D will be added (not both), 
depending on which client's request arrives second to the leader, overwriting 
the previous configuration. The other client can repeat the process until its 
change takes effect. This method guarantees system-wide progress (i.e., for one 
of the clients), but does not ensure that every client succeeds. To have more 
control C2 may request to only execute the reconfiguration in case the version 
 of the current configuration hasn't changed, as explained in the section <a 
href="#sc_reconfig_conditional">Conditional reconfig</a>. In this way it may 
avoid blindly overwriting the configuration of C1 if C1's configuration reached 
the leader first.</p>
+<p>With incremental reconfiguration, both changes will take effect as they are 
simply applied by the leader one after the other to the current configuration, 
whatever that is (assuming that the second reconfig request reaches the leader 
after it sends a commit message for the first reconfig request -- currently the 
leader will refuse to propose a reconfiguration if another one is already 
pending). Since both clients are guaranteed to make progress, this method 
guarantees stronger liveness. In practice, multiple concurrent reconfigurations 
are probably rare. Non-incremental reconfiguration is currently the only way to 
dynamically change the Quorum System. Incremental configuration is currently 
only allowed with the Majority Quorum System.</p>
+<p><strong>Changing an observer into a follower:</strong> Clearly, changing a 
server that participates in voting into an observer may fail if error (2) 
occurs, i.e., if fewer than the minimal allowed number of participants would 
remain. However, converting an observer into a participant may sometimes fail 
for a more subtle reason: Suppose, for example, that the current configuration 
is (A, B, C, D), where A is the leader, B and C are followers and D is an 
observer. In addition, suppose that B has crashed. If a reconfiguration is 
submitted where D is said to become a follower, it will fail with error (3) 
since in this configuration, a majority of voters in the new configuration (any 
3 voters), must be connected and up-to-date with the leader. An observer cannot 
acknowledge the history prefix sent during reconfiguration, and therefore it 
does not count towards these 3 required servers and the reconfiguration will be 
aborted. In case this happens, a client can achieve the same task by 
 two reconfig commands: first invoke a reconfig to remove D from the 
configuration and then invoke a second command to add it back as a participant 
(follower). During the intermediate state D is a non-voting follower and can 
ACK the state transfer performed during the second reconfig command.</p>
+<p><a name="ch_reconfig_rebalancing"></a></p>
+<h2>Rebalancing Client Connections</h2>
+<p>When a ZooKeeper cluster is started, if each client is given the same 
connection string (list of servers), the client will randomly choose a server 
in the list to connect to, which makes the expected number of client 
connections per server the same for each of the servers. We implemented a 
method that preserves this property when the set of servers changes through 
reconfiguration. See Sections 4 and 5.1 in the <a 
href="https://www.usenix.org/conference/usenixfederatedconferencesweek/dynamic-recon%EF%AC%81guration-primarybackup-clusters";>paper</a>.</p>
+<p>In order for the method to work, all clients must subscribe to 
configuration changes (by setting a watch on /zookeeper/config either directly 
or through the <code>getConfig</code> API command). When the watch is 
triggered, the client should read the new configuration by invoking 
<code>sync</code> and <code>getConfig</code> and if the configuration is indeed 
new invoke the <code>updateServerList</code> API command. To avoid mass client 
migration at the same time, it is better to have each client sleep a random 
short period of time before invoking <code>updateServerList</code>.</p>
+<p>A few examples can be found in: <em>StaticHostProviderTest.java</em> and 
<em>TestReconfig.cc</em></p>
+<p>Example (this is not a recipe, but a simplified example just to explain the 
general idea):</p>
+<pre><code>public void process(WatchedEvent event) {
+    synchronized (this) {
+        if (event.getType() == EventType.None) {
+            connected = (event.getState() == KeeperState.SyncConnected);
+            notifyAll();
+        } else if (event.getPath()!=null &amp;&amp;  
event.getPath().equals(ZooDefs.CONFIG_NODE)) {
+            // in prod code never block the event thread!
+            zk.sync(ZooDefs.CONFIG_NODE, this, null);
+            zk.getConfig(this, this, null);
+        }
+    }
+}
+
+public void processResult(int rc, String path, Object ctx, byte[] data, Stat 
stat) {
+    if (path!=null &amp;&amp;  path.equals(ZooDefs.CONFIG_NODE)) {
+        String config[] = ConfigUtils.getClientConfigStr(new 
String(data)).split(&quot; &quot;);   // similar to config -c
+        long version = Long.parseLong(config[0], 16);
+        if (this.configVersion == null){
+             this.configVersion = version;
+        } else if (version &gt; this.configVersion) {
+            hostList = config[1];
+            try {
+                // the following command is not blocking but may cause the 
client to close the socket and
+                // migrate to a different server. In practice it's better to 
wait a short period of time, chosen
+                // randomly, so that different clients migrate at different 
times
+                zk.updateServerList(hostList);
+            } catch (IOException e) {
+                System.err.println(&quot;Error updating server list&quot;);
+                e.printStackTrace();
+            }
+            this.configVersion = version;
+        }
+    }
+}
+</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.9.2-candidate-0/website/zookeeperSnapshotAndRestore.html
==============================================================================
--- 
dev/zookeeper/zookeeper-3.9.2-candidate-0/website/zookeeperSnapshotAndRestore.html
 (added)
+++ 
dev/zookeeper/zookeeper-3.9.2-candidate-0/website/zookeeperSnapshotAndRestore.html
 Mon Feb 12 21:24:47 2024
@@ -0,0 +1,215 @@
+
+<!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.9 
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="zookeeperSnapshotAndRestore.html">Snapshot and 
Restore 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 Snapshot and Restore Guide</h1>
+<p>Zookeeper is designed to withstand machine failures. A Zookeeper cluster 
can automatically recover from temporary failures such as machine reboot. It 
can also tolerate up to (N-1)/2 permanent failures for a cluster of N members 
due to hardware failures or disk corruption, etc. When a member permanently 
fails, it loses access to the cluster. If the cluster permanently loses more 
than (N-1)/2 members, it disastrously fails and loses quorum. Once the quorum 
is lost, the cluster cannot reach consensus and therefore cannot continue to 
accept updates.</p>
+<p>To recover from such disastrous failures, Zookeeper provides snapshot and 
restore functionalities to restore a cluster from a snapshot.</p>
+<ol>
+<li>Snapshot and restore operate on the connected server via Admin Server 
APIs</li>
+<li>Snapshot and restore are rate limited to protect the server from being 
overloaded</li>
+<li>Snapshot and restore require authentication and authorization on the root 
path with ALL permission. The supported auth schemas are digest, x509 and 
IP.</li>
+</ol>
+<ul>
+<li><a href="#zookeeper_snapshot">Snapshot</a></li>
+<li><a href="#zookeeper_restore">Restore</a></li>
+</ul>
+<p><a name="zookeeper_snapshot"></a></p>
+<h2>Snapshot</h2>
+<p>Recovering a cluster needs a snapshot from a ZooKeeper cluster. Users can 
periodically take snapshots from a live server which has the highest zxid and 
stream out data to a local or external storage/file system (e.g., S3).</p>
+<pre><code class="language-bash"># The snapshot command takes snapshot from 
the server it connects to and rate limited to once every 5 mins by default
+curl -H 'Authorization: digest root:root_passwd' 
http://hostname:adminPort/commands/snapshot?streaming=true --output 
snapshotFileName
+</code></pre>
+<p><a name="zookeeper_restore"></a></p>
+<h2>Restore</h2>
+<p>Restoring a cluster needs a single snapshot as input stream. Restore can be 
used for recovering a cluster for quorum lost or building a brand-new cluster 
with seed data.</p>
+<p>All members should restore using the same snapshot. The following are the 
recommended steps:</p>
+<ul>
+<li>Blocking traffic on the client port or client secure port before restore 
starts</li>
+<li>Take a snapshot of the latest database state using the snapshot admin 
server command if applicable</li>
+<li>For each server</li>
+<li>Moving the files in dataDir and dataLogDir to different location to 
prevent the restored database from being overwritten when server restarts after 
restore</li>
+<li>Restore the server using restore admin server command</li>
+<li>Unblocking traffic on the client port or client secure port after restore 
completes</li>
+</ul>
+<pre><code class="language-bash"># The restore command takes a snapshot as 
input stream and restore the db of the server it connects. It is rate limited 
to once every 5 mins by default
+curl -H 'Content-Type:application/octet-stream' -H 'Authorization: digest 
root:root_passwd' -POST http://hostname:adminPort/commands/restore 
--data-binary &quot;@snapshotFileName&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


Reply via email to