Author: mahadev Date: Tue Aug 11 21:26:12 2009 New Revision: 803305 URL: http://svn.apache.org/viewvc?rev=803305&view=rev Log: ZOOKEEPER-498. Unending Leader Elections : WAN configuration (flavio via mahadev)
Added: hadoop/zookeeper/branches/branch-3.2/docs/zookeeperHierarchicalQuorums.html hadoop/zookeeper/branches/branch-3.2/docs/zookeeperHierarchicalQuorums.pdf hadoop/zookeeper/branches/branch-3.2/src/docs/src/documentation/content/xdocs/zookeeperHierarchicalQuorums.xml Modified: hadoop/zookeeper/branches/branch-3.2/CHANGES.txt hadoop/zookeeper/branches/branch-3.2/docs/index.html hadoop/zookeeper/branches/branch-3.2/docs/index.pdf hadoop/zookeeper/branches/branch-3.2/docs/zookeeperAdmin.html hadoop/zookeeper/branches/branch-3.2/docs/zookeeperAdmin.pdf hadoop/zookeeper/branches/branch-3.2/src/docs/src/documentation/content/xdocs/index.xml hadoop/zookeeper/branches/branch-3.2/src/docs/src/documentation/content/xdocs/zookeeperAdmin.xml hadoop/zookeeper/branches/branch-3.2/src/java/main/org/apache/zookeeper/server/quorum/FastLeaderElection.java hadoop/zookeeper/branches/branch-3.2/src/java/main/org/apache/zookeeper/server/quorum/QuorumCnxManager.java hadoop/zookeeper/branches/branch-3.2/src/java/main/org/apache/zookeeper/server/quorum/flexible/QuorumHierarchical.java hadoop/zookeeper/branches/branch-3.2/src/java/test/org/apache/zookeeper/test/FLEZeroWeightTest.java hadoop/zookeeper/branches/branch-3.2/src/java/test/org/apache/zookeeper/test/HierarchicalQuorumTest.java Modified: hadoop/zookeeper/branches/branch-3.2/CHANGES.txt URL: http://svn.apache.org/viewvc/hadoop/zookeeper/branches/branch-3.2/CHANGES.txt?rev=803305&r1=803304&r2=803305&view=diff ============================================================================== --- hadoop/zookeeper/branches/branch-3.2/CHANGES.txt (original) +++ hadoop/zookeeper/branches/branch-3.2/CHANGES.txt Tue Aug 11 21:26:12 2009 @@ -58,6 +58,9 @@ ZOOKEEPER-477. zkCleanup.sh is flaky (fernando via mahadev) + ZOOKEEPER-498. Unending Leader Elections : WAN configuration (flavio via + mahadev) + IMPROVEMENTS: NEW FEATURES: Modified: hadoop/zookeeper/branches/branch-3.2/docs/index.html URL: http://svn.apache.org/viewvc/hadoop/zookeeper/branches/branch-3.2/docs/index.html?rev=803305&r1=803304&r2=803305&view=diff ============================================================================== --- hadoop/zookeeper/branches/branch-3.2/docs/index.html (original) +++ hadoop/zookeeper/branches/branch-3.2/docs/index.html Tue Aug 11 21:26:12 2009 @@ -284,6 +284,10 @@ <li> <a href="zookeeperJMX.html">JMX</a> - how to enable JMX in ZooKeeper</li> +<li> +<a href="zookeeperHierarchicalQuorums.html">Hierarchical quorums</a> +</li> + </ul> </li> Modified: hadoop/zookeeper/branches/branch-3.2/docs/index.pdf URL: http://svn.apache.org/viewvc/hadoop/zookeeper/branches/branch-3.2/docs/index.pdf?rev=803305&r1=803304&r2=803305&view=diff ============================================================================== Binary files - no diff available. Modified: hadoop/zookeeper/branches/branch-3.2/docs/zookeeperAdmin.html URL: http://svn.apache.org/viewvc/hadoop/zookeeper/branches/branch-3.2/docs/zookeeperAdmin.html?rev=803305&r1=803304&r2=803305&view=diff ============================================================================== --- hadoop/zookeeper/branches/branch-3.2/docs/zookeeperAdmin.html (original) +++ hadoop/zookeeper/branches/branch-3.2/docs/zookeeperAdmin.html Tue Aug 11 21:26:12 2009 @@ -1150,6 +1150,9 @@ The left-hand side of the assignment is a colon-separated list of server identifiers. Note that groups must be disjoint and the union of all groups must be the ZooKeeper ensemble. </p> +<p> You will find an example <a href="zookeeperHierarchicalQuorums.html">here</a> + +</p> </dd> @@ -1165,11 +1168,14 @@ the weight of server is 1. If the configuration defines groups, but not weights, then a value of 1 will be assigned to all servers. </p> +<p> You will find an example <a href="zookeeperHierarchicalQuorums.html">here</a> + +</p> </dd> </dl> <p></p> -<a name="N10383"></a><a name="sc_authOptions"></a> +<a name="N1038F"></a><a name="sc_authOptions"></a> <h4>Authentication & Authorization Options</h4> <p>The options in this section allow control over authentication/authorization performed by the service.</p> @@ -1203,7 +1209,7 @@ </dd> </dl> -<a name="N103A6"></a><a name="Unsafe+Options"></a> +<a name="N103B2"></a><a name="Unsafe+Options"></a> <h4>Unsafe Options</h4> <p>The following options can be useful, but be careful when you use them. The risk of each is explained along with the explanation of what @@ -1248,7 +1254,7 @@ </dd> </dl> -<a name="N103D8"></a><a name="sc_zkCommands"></a> +<a name="N103E4"></a><a name="sc_zkCommands"></a> <h3 class="h4">ZooKeeper Commands: The Four Letter Words</h3> <p>ZooKeeper responds to a small set of commands. Each command is composed of four letters. You issue the commands to ZooKeeper via telnet @@ -1312,7 +1318,7 @@ <pre class="code">$ echo ruok | nc 127.0.0.1 5111 imok </pre> -<a name="N10418"></a><a name="sc_dataFileManagement"></a> +<a name="N10424"></a><a name="sc_dataFileManagement"></a> <h3 class="h4">Data File Management</h3> <p>ZooKeeper stores its data in a data directory and its transaction log in a transaction log directory. By default these two directories are @@ -1320,7 +1326,7 @@ transaction log files in a separate directory than the data files. Throughput increases and latency decreases when transaction logs reside on a dedicated log devices.</p> -<a name="N10421"></a><a name="The+Data+Directory"></a> +<a name="N1042D"></a><a name="The+Data+Directory"></a> <h4>The Data Directory</h4> <p>This directory has two files in it:</p> <ul> @@ -1366,14 +1372,14 @@ idempotent nature of its updates. By replaying the transaction log against fuzzy snapshots ZooKeeper gets the state of the system at the end of the log.</p> -<a name="N1045D"></a><a name="The+Log+Directory"></a> +<a name="N10469"></a><a name="The+Log+Directory"></a> <h4>The Log Directory</h4> <p>The Log Directory contains the ZooKeeper transaction logs. Before any update takes place, ZooKeeper ensures that the transaction that represents the update is written to non-volatile storage. A new log file is started each time a snapshot is begun. The log file's suffix is the first zxid written to that log.</p> -<a name="N10467"></a><a name="sc_filemanagement"></a> +<a name="N10473"></a><a name="sc_filemanagement"></a> <h4>File Management</h4> <p>The format of snapshot and log files does not change between standalone ZooKeeper servers and different configurations of @@ -1393,7 +1399,7 @@ this document for more details on setting a retention policy and maintenance of ZooKeeper storage. </p> -<a name="N1047C"></a><a name="sc_commonProblems"></a> +<a name="N10488"></a><a name="sc_commonProblems"></a> <h3 class="h4">Things to Avoid</h3> <p>Here are some common problems you can avoid by configuring ZooKeeper correctly:</p> @@ -1447,7 +1453,7 @@ </dd> </dl> -<a name="N104A0"></a><a name="sc_bestPractices"></a> +<a name="N104AC"></a><a name="sc_bestPractices"></a> <h3 class="h4">Best Practices</h3> <p>For best results, take note of the following list of good Zookeeper practices:</p> Modified: hadoop/zookeeper/branches/branch-3.2/docs/zookeeperAdmin.pdf URL: http://svn.apache.org/viewvc/hadoop/zookeeper/branches/branch-3.2/docs/zookeeperAdmin.pdf?rev=803305&r1=803304&r2=803305&view=diff ============================================================================== Binary files - no diff available. Added: hadoop/zookeeper/branches/branch-3.2/docs/zookeeperHierarchicalQuorums.html URL: http://svn.apache.org/viewvc/hadoop/zookeeper/branches/branch-3.2/docs/zookeeperHierarchicalQuorums.html?rev=803305&view=auto ============================================================================== --- hadoop/zookeeper/branches/branch-3.2/docs/zookeeperHierarchicalQuorums.html (added) +++ hadoop/zookeeper/branches/branch-3.2/docs/zookeeperHierarchicalQuorums.html Tue Aug 11 21:26:12 2009 @@ -0,0 +1,272 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html> +<head> +<META http-equiv="Content-Type" content="text/html; charset=UTF-8"> +<meta content="Apache Forrest" name="Generator"> +<meta name="Forrest-version" content="0.8"> +<meta name="Forrest-skin-name" content="pelt"> +<title>Introduction to hierarchical quorums</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/fontsize.js" language="javascript" type="text/javascript"></script> +<link rel="shortcut icon" href="images/favicon.ico"> +</head> +<body onload="init()"> +<script type="text/javascript">ndeSetTextSize();</script> +<div id="top"> +<!--+ + |breadtrail + +--> +<div class="breadtrail"> +<a href="http://www.apache.org/">Apache</a> > <a href="http://hadoop.apache.org/">Hadoop</a> > <a href="http://hadoop.apache.org/zookeeper/">ZooKeeper</a><script src="skin/breadcrumbs.js" language="JavaScript" type="text/javascript"></script> +</div> +<!--+ + |header + +--> +<div class="header"> +<!--+ + |start group logo + +--> +<div class="grouplogo"> +<a href="http://hadoop.apache.org/"><img class="logoImage" alt="Hadoop" src="images/hadoop-logo.jpg" title="Apache Hadoop"></a> +</div> +<!--+ + |end group logo + +--> +<!--+ + |start Project Logo + +--> +<div class="projectlogo"> +<a href="http://hadoop.apache.org/zookeeper/"><img class="logoImage" alt="ZooKeeper" src="images/zookeeper_small.gif" title="ZooKeeper: distributed coordination"></a> +</div> +<!--+ + |end Project Logo + +--> +<!--+ + |start Search + +--> +<div class="searchbox"> +<form action="http://www.google.com/search" method="get" class="roundtopsmall"> +<input value="hadoop.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"> + <input name="Search" value="Search" type="submit"> +</form> +</div> +<!--+ + |end search + +--> +<!--+ + |start Tabs + +--> +<ul id="tabs"> +<li> +<a class="unselected" href="http://hadoop.apache.org/zookeeper/">Project</a> +</li> +<li> +<a class="unselected" href="http://wiki.apache.org/hadoop/ZooKeeper">Wiki</a> +</li> +<li class="current"> +<a class="selected" href="index.html">ZooKeeper 3.2 Documentation</a> +</li> +</ul> +<!--+ + |end Tabs + +--> +</div> +</div> +<div id="main"> +<div id="publishedStrip"> +<!--+ + |start Subtabs + +--> +<div id="level2tabs"></div> +<!--+ + |end Endtabs + +--> +<script type="text/javascript"><!-- +document.write("Last Published: " + document.lastModified); +// --></script> +</div> +<!--+ + |breadtrail + +--> +<div class="breadtrail"> + + + </div> +<!--+ + |start Menu, mainarea + +--> +<!--+ + |start Menu + +--> +<div id="menu"> +<div onclick="SwitchMenu('menu_1.1', 'skin/')" id="menu_1.1Title" class="menutitle">Overview</div> +<div id="menu_1.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_1.2', 'skin/')" id="menu_1.2Title" class="menutitle">Developer</div> +<div id="menu_1.2" class="menuitemgroup"> +<div class="menuitem"> +<a href="api/index.html">API Docs</a> +</div> +<div class="menuitem"> +<a href="zookeeperProgrammers.html">Programmer's Guide</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_1.3', 'skin/')" id="menu_1.3Title" class="menutitle">BookKeeper</div> +<div id="menu_1.3" class="menuitemgroup"> +<div class="menuitem"> +<a href="bookkeeperStarted.html">Getting started</a> +</div> +<div class="menuitem"> +<a href="bookkeeperOverview.html">Overview</a> +</div> +<div class="menuitem"> +<a href="bookkeeperConfig.html">Setup guide</a> +</div> +<div class="menuitem"> +<a href="bookkeeperProgrammer.html">Programmer's guide</a> +</div> +</div> +<div onclick="SwitchMenu('menu_1.4', 'skin/')" id="menu_1.4Title" class="menutitle">Admin & Ops</div> +<div id="menu_1.4" 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> +<div onclick="SwitchMenu('menu_1.5', 'skin/')" id="menu_1.5Title" class="menutitle">Contributor</div> +<div id="menu_1.5" class="menuitemgroup"> +<div class="menuitem"> +<a href="zookeeperInternals.html">ZooKeeper Internals</a> +</div> +</div> +<div onclick="SwitchMenu('menu_1.6', 'skin/')" id="menu_1.6Title" class="menutitle">Miscellaneous</div> +<div id="menu_1.6" class="menuitemgroup"> +<div class="menuitem"> +<a href="http://wiki.apache.org/hadoop/ZooKeeper">Wiki</a> +</div> +<div class="menuitem"> +<a href="http://wiki.apache.org/hadoop/ZooKeeper/FAQ">FAQ</a> +</div> +<div class="menuitem"> +<a href="http://hadoop.apache.org/zookeeper/mailing_lists.html">Mailing Lists</a> +</div> +</div> +<div id="credit"></div> +<div id="roundbottom"> +<img style="display: none" class="corner" height="15" width="15" alt="" src="skin/images/rc-b-l-15-1body-2menu-3menu.png"></div> +<!--+ + |alternative credits + +--> +<div id="credit2"></div> +</div> +<!--+ + |end Menu + +--> +<!--+ + |start content + +--> +<div id="content"> +<div title="Portable Document Format" class="pdflink"> +<a class="dida" href="zookeeperHierarchicalQuorums.pdf"><img alt="PDF -icon" src="skin/images/pdfdoc.gif" class="skin"><br> + PDF</a> +</div> +<h1>Introduction to hierarchical quorums</h1> + + + + + +<p> + This document gives an example of how to use hierarchical quorums. The basic idea is + very simple. First, we split servers into groups, and add a line for each group listing + the servers that form this group. Next we have to assign a weight to each server. + </p> + + +<p> + The following example shows how to configure a system with three groups of three servers + each, and we assign a weight of 1 to each server: + </p> + + +<pre class="code"> + group.1=1:2:3 + group.2=4:5:6 + group.3=7:8:9 + + weight.1=1 + weight.2=1 + weight.3=1 + weight.4=1 + weight.5=1 + weight.6=1 + weight.7=1 + weight.8=1 + weight.9=1 + </pre> + + +<p> + When running the system, we are able to form a quorum once we have a majority of votes from + a majority of non-zero-weight groups. Groups that have zero weight are discarded and not + considered when forming quorums. Looking at the example, we are able to form a quorum once + we have votes from at least two servers from each of two different groups. + </p> + +<p align="right"> +<font size="-2"></font> +</p> +</div> +<!--+ + |end content + +--> +<div class="clearboth"> </div> +</div> +<div id="footer"> +<!--+ + |start bottomstrip + +--> +<div class="lastmodified"> +<script type="text/javascript"><!-- +document.write("Last Published: " + document.lastModified); +// --></script> +</div> +<div class="copyright"> + Copyright © + 2008 <a href="http://www.apache.org/licenses/">The Apache Software Foundation.</a> +</div> +<!--+ + |end bottomstrip + +--> +</div> +</body> +</html> Added: hadoop/zookeeper/branches/branch-3.2/docs/zookeeperHierarchicalQuorums.pdf URL: http://svn.apache.org/viewvc/hadoop/zookeeper/branches/branch-3.2/docs/zookeeperHierarchicalQuorums.pdf?rev=803305&view=auto ============================================================================== --- hadoop/zookeeper/branches/branch-3.2/docs/zookeeperHierarchicalQuorums.pdf (added) +++ hadoop/zookeeper/branches/branch-3.2/docs/zookeeperHierarchicalQuorums.pdf Tue Aug 11 21:26:12 2009 @@ -0,0 +1,94 @@ +%PDF-1.3 +%ª«¬ +4 0 obj +<< /Type /Info +/Producer (FOP 0.20.5) >> +endobj +5 0 obj +<< /Length 1156 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gatm;d>jt['Re;/pi0?gEG]2>7%/mKeQK;[.^b8cLUI^%R,F:gX::AarVDr_iL2Kr[]8m0Y&j+*3PI]/q/Fu7ob\jl0gUS07u"3V8'l6G&TJnMZ=,<C"@l...@%o^o'h03^KFP.J$dd9,<c...@%0gf`'3CF)\mMHUa?Z]'@u[HUK\*VojY^;$Pi`iNLH3/MSe9rX^jDWhp7(4pu...@88tiq?x(D":9Q+H0TZL*s?UO&4+OLNE>r1'D)NEc[0[63(;Z32E"n[Z-eNA^$AFCL5rO[BRaHHN?>Q;Ei%#8())ZS]!*^&SbcC_jgdJHX'eW/U-#0C]4A[c^*\ENCuL#KWiI8G-Y<J%"g>H6ihh(bC`-C-fj3)k_F^e>qimHaZl?&Z?1.].Gl_#G[[1EccH\H.bu46E'<04j`Rdq7-m6<p.da>R\0NlIZ;P\4CbD]C9UM%O3hNU;jMJVb="9\i,P^G^@''BBtEl&Deu&6...@p-o7cfge:6T]/C_2:U,H\IoY<KL]b\I:GcmRc%_R4c$LGK5d1V`Ep>[d=8l!qe<1i*d40GD^J_N(_J<4,hVT<g^$7/Lphg2q'4UQ'V.Oe,"DL!i1;u*bE.kMC%p*E_r/lZU;SuT8dEQ%$,qM8UGcTkdg*Hsqe2he"HP!,'+`a0pc...@5rik90@Ik+SP%`$c<k"/=k^ob/7u2=D-cdq,k(Z,n.hNO,Z'%;9#g_5*g+q;he6=A)f/B?oVA19=D(-K@(DmZ%\/^bZ<NI/M)r:?ZF8,fZamD;1[d'r;9_kE%4Q=[Vr\BorN'gO5)OIVe3g[IEr(pE,:Hj'Xi](BCZKJ9QA5Te4+R6iM6=P3uR[SLi=?YH;m...@hfd#""X`!UB8>GY*AhmO2BI"[$*pC'YTA)'[[SM1+Qc^)S.4+>lK,;8!b;+t>9XiP[6Ke!lh)>b4jPn_1Y^9])]Y;VfT_2Y5"OcnaC$J7hF$0[4$g4*;iW!(n;t\qoqIK^V2DVb 'nHCK;ew%_d`pyb`f+glawif...@o&P*QVO>YOj7Upsr%CG!=t*8MrF>G&&?+VbB)E>Aj9oNcF3o.#XU&N:MClcS&l__snNB4,`>90ga;7RP#mrnFbK)"7\%Ul7UODO!B^sDp*P')h...@%j\+cc##`tyf:c-qVSQ%#.F~> +endstream +endobj +6 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 5 0 R +>> +endobj +7 0 obj +<< /Type /Font +/Subtype /Type1 +/Name /F3 +/BaseFont /Helvetica-Bold +/Encoding /WinAnsiEncoding >> +endobj +8 0 obj +<< /Type /Font +/Subtype /Type1 +/Name /F5 +/BaseFont /Times-Roman +/Encoding /WinAnsiEncoding >> +endobj +9 0 obj +<< /Type /Font +/Subtype /Type1 +/Name /F1 +/BaseFont /Helvetica +/Encoding /WinAnsiEncoding >> +endobj +10 0 obj +<< /Type /Font +/Subtype /Type1 +/Name /F9 +/BaseFont /Courier +/Encoding /WinAnsiEncoding >> +endobj +11 0 obj +<< /Type /Font +/Subtype /Type1 +/Name /F2 +/BaseFont /Helvetica-Oblique +/Encoding /WinAnsiEncoding >> +endobj +1 0 obj +<< /Type /Pages +/Count 1 +/Kids [6 0 R ] >> +endobj +2 0 obj +<< /Type /Catalog +/Pages 1 0 R + >> +endobj +3 0 obj +<< +/Font << /F3 7 0 R /F5 8 0 R /F1 9 0 R /F9 10 0 R /F2 11 0 R >> +/ProcSet [ /PDF /ImageC /Text ] >> +endobj +xref +0 12 +0000000000 65535 f +0000001975 00000 n +0000002033 00000 n +0000002083 00000 n +0000000015 00000 n +0000000071 00000 n +0000001319 00000 n +0000001425 00000 n +0000001537 00000 n +0000001646 00000 n +0000001753 00000 n +0000001859 00000 n +trailer +<< +/Size 12 +/Root 2 0 R +/Info 4 0 R +>> +startxref +2203 +%%EOF Modified: hadoop/zookeeper/branches/branch-3.2/src/docs/src/documentation/content/xdocs/index.xml URL: http://svn.apache.org/viewvc/hadoop/zookeeper/branches/branch-3.2/src/docs/src/documentation/content/xdocs/index.xml?rev=803305&r1=803304&r2=803305&view=diff ============================================================================== --- hadoop/zookeeper/branches/branch-3.2/src/docs/src/documentation/content/xdocs/index.xml (original) +++ hadoop/zookeeper/branches/branch-3.2/src/docs/src/documentation/content/xdocs/index.xml Tue Aug 11 21:26:12 2009 @@ -63,6 +63,7 @@ <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></li> </ul> </li> Modified: hadoop/zookeeper/branches/branch-3.2/src/docs/src/documentation/content/xdocs/zookeeperAdmin.xml URL: http://svn.apache.org/viewvc/hadoop/zookeeper/branches/branch-3.2/src/docs/src/documentation/content/xdocs/zookeeperAdmin.xml?rev=803305&r1=803304&r2=803305&view=diff ============================================================================== --- hadoop/zookeeper/branches/branch-3.2/src/docs/src/documentation/content/xdocs/zookeeperAdmin.xml (original) +++ hadoop/zookeeper/branches/branch-3.2/src/docs/src/documentation/content/xdocs/zookeeperAdmin.xml Tue Aug 11 21:26:12 2009 @@ -800,6 +800,9 @@ The left-hand side of the assignment is a colon-separated list of server identifiers. Note that groups must be disjoint and the union of all groups must be the ZooKeeper ensemble. </para> + + <para> You will find an example <ulink url="zookeeperHierarchicalQuorums.html">here</ulink> + </para> </listitem> </varlistentry> @@ -816,6 +819,9 @@ the weight of server is 1. If the configuration defines groups, but not weights, then a value of 1 will be assigned to all servers. </para> + + <para> You will find an example <ulink url="zookeeperHierarchicalQuorums.html">here</ulink> + </para> </listitem> </varlistentry> </variablelist> Added: hadoop/zookeeper/branches/branch-3.2/src/docs/src/documentation/content/xdocs/zookeeperHierarchicalQuorums.xml URL: http://svn.apache.org/viewvc/hadoop/zookeeper/branches/branch-3.2/src/docs/src/documentation/content/xdocs/zookeeperHierarchicalQuorums.xml?rev=803305&view=auto ============================================================================== --- hadoop/zookeeper/branches/branch-3.2/src/docs/src/documentation/content/xdocs/zookeeperHierarchicalQuorums.xml (added) +++ hadoop/zookeeper/branches/branch-3.2/src/docs/src/documentation/content/xdocs/zookeeperHierarchicalQuorums.xml Tue Aug 11 21:26:12 2009 @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> + +<!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V1.0//EN" +"http://www.oasis-open.org/docbook/xml/simple/1.0/sdocbook.dtd"> +<article id="zk_HierarchicalQuorums"> + <title>Introduction to hierarchical quorums</title> + + <articleinfo> + <legalnotice> + <para>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 <ulink + url="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</ulink>.</para> + + <para>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.</para> + </legalnotice> + + <abstract> + <para>This document contains information about hierarchical quorums.</para> + </abstract> + </articleinfo> + + <para> + This document gives an example of how to use hierarchical quorums. The basic idea is + very simple. First, we split servers into groups, and add a line for each group listing + the servers that form this group. Next we have to assign a weight to each server. + </para> + + <para> + The following example shows how to configure a system with three groups of three servers + each, and we assign a weight of 1 to each server: + </para> + + <programlisting> + group.1=1:2:3 + group.2=4:5:6 + group.3=7:8:9 + + weight.1=1 + weight.2=1 + weight.3=1 + weight.4=1 + weight.5=1 + weight.6=1 + weight.7=1 + weight.8=1 + weight.9=1 + </programlisting> + + <para> + When running the system, we are able to form a quorum once we have a majority of votes from + a majority of non-zero-weight groups. Groups that have zero weight are discarded and not + considered when forming quorums. Looking at the example, we are able to form a quorum once + we have votes from at least two servers from each of two different groups. + </para> + </article> \ No newline at end of file Modified: hadoop/zookeeper/branches/branch-3.2/src/java/main/org/apache/zookeeper/server/quorum/FastLeaderElection.java URL: http://svn.apache.org/viewvc/hadoop/zookeeper/branches/branch-3.2/src/java/main/org/apache/zookeeper/server/quorum/FastLeaderElection.java?rev=803305&r1=803304&r2=803305&view=diff ============================================================================== --- hadoop/zookeeper/branches/branch-3.2/src/java/main/org/apache/zookeeper/server/quorum/FastLeaderElection.java (original) +++ hadoop/zookeeper/branches/branch-3.2/src/java/main/org/apache/zookeeper/server/quorum/FastLeaderElection.java Tue Aug 11 21:26:12 2009 @@ -172,20 +172,22 @@ */ class WorkerReceiver implements Runnable { - + volatile boolean stop; QuorumCnxManager manager; WorkerReceiver(QuorumCnxManager manager) { + this.stop = false; this.manager = manager; } public void run() { Message response; - while (true) { + while (!stop) { // Sleeps on receive try{ - response = manager.recvQueue.take(); + response = manager.recvQueue.poll(3000, TimeUnit.MILLISECONDS); + if(response == null) continue; // Receive new message LOG.debug("Receive new message."); @@ -266,6 +268,7 @@ e.toString()); } } + LOG.info("WorkerReceiver is down"); } } @@ -276,23 +279,26 @@ */ class WorkerSender implements Runnable { - + volatile boolean stop; QuorumCnxManager manager; WorkerSender(QuorumCnxManager manager){ + this.stop = false; this.manager = manager; } public void run() { - while (true) { + while (!stop) { try { - ToSend m = sendqueue.take(); + ToSend m = sendqueue.poll(3000, TimeUnit.MILLISECONDS); + if(m == null) continue; + process(m); } catch (InterruptedException e) { break; } - } + LOG.info("WorkerSender is down"); } /** @@ -326,6 +332,10 @@ return (sendqueue.isEmpty() || recvqueue.isEmpty()); } + + WorkerSender ws; + WorkerReceiver wr; + /** * Constructor of class Messenger. * @@ -333,20 +343,33 @@ */ Messenger(QuorumCnxManager manager) { - Thread t = new Thread(new WorkerSender(manager), + this.ws = new WorkerSender(manager); + + Thread t = new Thread(this.ws, "WorkerSender Thread"); t.setDaemon(true); t.start(); - t = new Thread(new WorkerReceiver(manager), + this.wr = new WorkerReceiver(manager); + + t = new Thread(this.wr, "WorkerReceiver Thread"); t.setDaemon(true); t.start(); } + + /** + * Stops instances of WorkerSender and WorkerReceiver + */ + void halt(){ + this.ws.stop = true; + this.wr.stop = true; + } } - QuorumPeer self; + QuorumPeer self; + Messenger messenger; volatile long logicalclock; /* Election instance */ long proposedLeader; long proposedZxid; @@ -369,7 +392,8 @@ * @param manager Connection manager */ public FastLeaderElection(QuorumPeer self, QuorumCnxManager manager){ - this.manager = manager; + this.stop = false; + this.manager = manager; starter(self, manager); } @@ -390,7 +414,7 @@ sendqueue = new LinkedBlockingQueue<ToSend>(); recvqueue = new LinkedBlockingQueue<Notification>(); - new Messenger(manager); + this.messenger = new Messenger(manager); } private void leaveInstance() { @@ -401,9 +425,14 @@ return manager; } + volatile boolean stop; public void shutdown(){ + stop = true; LOG.debug("Shutting down connection manager"); manager.halt(); + LOG.debug("Shutting down messenger"); + messenger.halt(); + LOG.debug("FLE is down"); } @@ -434,6 +463,10 @@ */ private boolean totalOrderPredicate(long newId, long newZxid, long curId, long curZxid) { LOG.debug("id: " + newId + ", proposed id: " + curId + ", zxid: " + newZxid + ", proposed zxid: " + curZxid); + if(self.getQuorumVerifier().getWeight(newId) == 0){ + return false; + } + if ((newZxid > curZxid) || ((newZxid == curZxid) && (newId > curId))) return true; @@ -550,7 +583,8 @@ * Loop in which we exchange notifications until we find a leader */ - while (self.getPeerState() == ServerState.LOOKING) { + while ((self.getPeerState() == ServerState.LOOKING) && + (!stop)){ /* * Remove next notification from queue, times out after 2 times * the termination time @@ -606,14 +640,12 @@ } LOG.info("Adding vote"); - /* - * Skip zero-weight servers - */ - if(self.getQuorumVerifier().getWeight(n.sid) != 0) - recvset.put(n.sid, new Vote(n.leader, n.zxid, n.epoch)); + + recvset.put(n.sid, new Vote(n.leader, n.zxid, n.epoch)); //If have received from all nodes, then terminate - if (self.quorumPeers.size() == recvset.size()) { + if ((self.quorumPeers.size() == recvset.size()) && + (self.getQuorumVerifier().getWeight(proposedLeader) != 0)){ self.setPeerState((proposedLeader == self.getId()) ? ServerState.LEADING: ServerState.FOLLOWING); leaveInstance(); Modified: hadoop/zookeeper/branches/branch-3.2/src/java/main/org/apache/zookeeper/server/quorum/QuorumCnxManager.java URL: http://svn.apache.org/viewvc/hadoop/zookeeper/branches/branch-3.2/src/java/main/org/apache/zookeeper/server/quorum/QuorumCnxManager.java?rev=803305&r1=803304&r2=803305&view=diff ============================================================================== --- hadoop/zookeeper/branches/branch-3.2/src/java/main/org/apache/zookeeper/server/quorum/QuorumCnxManager.java (original) +++ hadoop/zookeeper/branches/branch-3.2/src/java/main/org/apache/zookeeper/server/quorum/QuorumCnxManager.java Tue Aug 11 21:26:12 2009 @@ -338,7 +338,7 @@ e); } } else { - LOG.error("There is a connection for server " + sid); + LOG.debug("There is a connection for server " + sid); } } Modified: hadoop/zookeeper/branches/branch-3.2/src/java/main/org/apache/zookeeper/server/quorum/flexible/QuorumHierarchical.java URL: http://svn.apache.org/viewvc/hadoop/zookeeper/branches/branch-3.2/src/java/main/org/apache/zookeeper/server/quorum/flexible/QuorumHierarchical.java?rev=803305&r1=803304&r2=803305&view=diff ============================================================================== --- hadoop/zookeeper/branches/branch-3.2/src/java/main/org/apache/zookeeper/server/quorum/flexible/QuorumHierarchical.java (original) +++ hadoop/zookeeper/branches/branch-3.2/src/java/main/org/apache/zookeeper/server/quorum/flexible/QuorumHierarchical.java Tue Aug 11 21:26:12 2009 @@ -121,8 +121,8 @@ this.serverGroup = serverGroup; this.groupWeight = new HashMap<Long, Long>(); - computeGroupWeight(); this.numGroups = numGroups; + computeGroupWeight(); } @@ -219,7 +219,11 @@ * Do not consider groups with weight zero */ for(long weight: groupWeight.values()){ - if(weight == 0) numGroups--; + LOG.debug("Group weight: " + weight); + if(weight == ((long) 0)){ + numGroups--; + LOG.debug("One zero-weight group: " + 1 + ", " + numGroups); + } } } @@ -233,7 +237,7 @@ * Adds up weights per group */ if(set.size() == 0) return false; - else LOG.info("Set size: " + set.size()); + else LOG.debug("Set size: " + set.size()); for(long sid : set){ Long gid = serverGroup.get(sid); @@ -250,17 +254,18 @@ */ int majGroupCounter = 0; for(long gid : expansion.keySet()) { - LOG.info("gid: " + expansion.get(gid)); + LOG.debug("Group info: " + expansion.get(gid) + ", " + gid + ", " + groupWeight.get(gid)); if(expansion.get(gid) > (groupWeight.get(gid) / 2) ) majGroupCounter++; } + LOG.debug("Majority group counter: " + majGroupCounter + ", " + numGroups); if((majGroupCounter > (numGroups / 2))){ - LOG.info("Positive set size: " + set.size()); + LOG.debug("Positive set size: " + set.size()); return true; } else { - LOG.info("Negative set size: " + set.size()); + LOG.debug("Negative set size: " + set.size()); return false; } } Modified: hadoop/zookeeper/branches/branch-3.2/src/java/test/org/apache/zookeeper/test/FLEZeroWeightTest.java URL: http://svn.apache.org/viewvc/hadoop/zookeeper/branches/branch-3.2/src/java/test/org/apache/zookeeper/test/FLEZeroWeightTest.java?rev=803305&r1=803304&r2=803305&view=diff ============================================================================== --- hadoop/zookeeper/branches/branch-3.2/src/java/test/org/apache/zookeeper/test/FLEZeroWeightTest.java (original) +++ hadoop/zookeeper/branches/branch-3.2/src/java/test/org/apache/zookeeper/test/FLEZeroWeightTest.java Tue Aug 11 21:26:12 2009 @@ -105,7 +105,7 @@ class LEThread extends Thread { int i; QuorumPeer peer; - //int peerRound = 1; + boolean fail; LEThread(QuorumPeer peer, int i) { this.i = i; @@ -116,6 +116,7 @@ public void run() { try { Vote v = null; + fail = false; while(true){ //while(true) { @@ -137,7 +138,7 @@ votes[i] = v; if((peer.getPeerState() == ServerState.LEADING) && - (peer.getId() > 2)) fail("Elected zero-weight server"); + (peer.getId() > 2)) fail = true; if((peer.getPeerState() == ServerState.FOLLOWING) || (peer.getPeerState() == ServerState.LEADING)) break; @@ -150,10 +151,10 @@ } @Test - public void testHierarchicalQuorum() throws Exception { + public void testZeroWeightQuorum() throws Exception { FastLeaderElection le[] = new FastLeaderElection[count]; - LOG.info("TestHierarchicalQuorum: " + getName()+ ", " + count); + LOG.info("TestZeroWeightQuorum: " + getName()+ ", " + count); for(int i = 0; i < count; i++) { peers.put(Long.valueOf(i), new QuorumServer(i, @@ -177,6 +178,9 @@ threads.get(i).join(15000); if (threads.get(i).isAlive()) { fail("Threads didn't join"); + } else { + if(threads.get(i).fail) + fail("Elected zero-weight server"); } } } Modified: hadoop/zookeeper/branches/branch-3.2/src/java/test/org/apache/zookeeper/test/HierarchicalQuorumTest.java URL: http://svn.apache.org/viewvc/hadoop/zookeeper/branches/branch-3.2/src/java/test/org/apache/zookeeper/test/HierarchicalQuorumTest.java?rev=803305&r1=803304&r2=803305&view=diff ============================================================================== --- hadoop/zookeeper/branches/branch-3.2/src/java/test/org/apache/zookeeper/test/HierarchicalQuorumTest.java (original) +++ hadoop/zookeeper/branches/branch-3.2/src/java/test/org/apache/zookeeper/test/HierarchicalQuorumTest.java Tue Aug 11 21:26:12 2009 @@ -1,5 +1,4 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one +/* Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file @@ -17,168 +16,259 @@ */ package org.apache.zookeeper.test; + import java.io.ByteArrayInputStream; import java.io.File; +import java.io.IOException; import java.net.InetSocketAddress; -import java.util.ArrayList; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.Properties; -import java.util.Random; - -import junit.framework.TestCase; +import java.util.Set; import org.apache.log4j.Logger; +import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.server.quorum.FastLeaderElection; import org.apache.zookeeper.server.quorum.QuorumPeer; -import org.apache.zookeeper.server.quorum.Vote; import org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer; -import org.apache.zookeeper.server.quorum.QuorumPeer.ServerState; import org.apache.zookeeper.server.quorum.flexible.QuorumHierarchical; +import org.junit.After; import org.junit.Before; import org.junit.Test; -public class HierarchicalQuorumTest extends TestCase { - private static final Logger LOG = Logger.getLogger(HierarchicalQuorumTest.class); - - Properties qp; +/** + * Comprehensive test of hierarchical quorums, assuming servers with zero weight. + * This test uses ClientTest to verify that the ensemble works after a leader is + * elected. + * + * This implementation is based on QuorumBase, the main difference being that it + * uses hierarchical quorums and FLE. + */ - int count; - int baseport; - int baseLEport; - HashMap<Long,QuorumServer> peers; - ArrayList<LEThread> threads; - File tmpdir[]; - int port[]; - Object finalObj; - - volatile Vote votes[]; - volatile boolean leaderDies; - volatile long leader = -1; - Random rand = new Random(); +public class HierarchicalQuorumTest extends ClientBase { + private static final Logger LOG = Logger.getLogger(QuorumBase.class); + File s1dir, s2dir, s3dir, s4dir, s5dir; + QuorumPeer s1, s2, s3, s4, s5; + private int port1; + private int port2; + private int port3; + private int port4; + private int port5; + + private int leport1; + private int leport2; + private int leport3; + private int leport4; + private int leport5; - @Before + Properties qp; + private final ClientTest ct = new ClientTest(); + @Override protected void setUp() throws Exception { - count = 9; - baseport= 33003; - baseLEport = 43003; - - peers = new HashMap<Long,QuorumServer>(count); - threads = new ArrayList<LEThread>(count); - votes = new Vote[count]; - tmpdir = new File[count]; - port = new int[count]; - finalObj = new Object(); - - String config = "group.1=0:1:2\n" + - "group.2=3:4:5\n" + - "group.3=6:7:8\n\n" + - "weight.0=1\n" + + LOG.info("STARTING " + getName()); + int baseport = 12333; + int baseLEport = 14333; + + setupTestEnv(); + + JMXEnv.setUp(); + + //setUpAll(); + + port1 = baseport; + port2 = baseport + 1; + port3 = baseport + 2; + port4 = baseport + 3; + port5 = baseport + 4; + leport1 = baseLEport; + leport2 = baseLEport + 1; + leport3 = baseLEport + 2; + leport4 = baseLEport + 3; + leport5 = baseLEport + 4; + + hostPort = "127.0.0.1:" + port1 + + ",127.0.0.1:" + port2 + + ",127.0.0.1:" + port3 + + ",127.0.0.1:" + port4 + + ",127.0.0.1:" + port5; + LOG.info("Ports are: " + hostPort); + + s1dir = ClientBase.createTmpDir(); + s2dir = ClientBase.createTmpDir(); + s3dir = ClientBase.createTmpDir(); + s4dir = ClientBase.createTmpDir(); + s5dir = ClientBase.createTmpDir(); + + String config = "group.1=1:2:3\n" + + "group.2=4:5\n" + "weight.1=1\n" + "weight.2=1\n" + "weight.3=1\n" + - "weight.4=1\n" + - "weight.5=1\n" + - "weight.6=1\n" + - "weight.7=1\n" + - "weight.8=1"; + "weight.4=0\n" + + "weight.5=0\n"; ByteArrayInputStream is = new ByteArrayInputStream(config.getBytes()); this.qp = new Properties(); + qp.load(is); + startServers(); + + ct.hostPort = hostPort; + //ct.setUpAll(); + + LOG.info("Setup finished"); + } + + + void startServers() throws Exception { + int tickTime = 2000; + int initLimit = 3; + int syncLimit = 3; + HashMap<Long,QuorumServer> peers = new HashMap<Long,QuorumServer>(); + peers.put(Long.valueOf(1), new QuorumServer(1, + new InetSocketAddress("127.0.0.1", port1 + 1000), + new InetSocketAddress("127.0.0.1", leport1 + 1000))); + peers.put(Long.valueOf(2), new QuorumServer(2, + new InetSocketAddress("127.0.0.1", port2 + 1000), + new InetSocketAddress("127.0.0.1", leport2 + 1000))); + peers.put(Long.valueOf(3), new QuorumServer(3, + new InetSocketAddress("127.0.0.1", port3 + 1000), + new InetSocketAddress("127.0.0.1", leport3 + 1000))); + peers.put(Long.valueOf(4), new QuorumServer(4, + new InetSocketAddress("127.0.0.1", port4 + 1000), + new InetSocketAddress("127.0.0.1", leport4 + 1000))); + peers.put(Long.valueOf(5), new QuorumServer(5, + new InetSocketAddress("127.0.0.1", port5 + 1000), + new InetSocketAddress("127.0.0.1", leport5 + 1000))); + + LOG.info("creating QuorumPeer 1 port " + port1); + QuorumHierarchical hq1 = new QuorumHierarchical(qp); + s1 = new QuorumPeer(peers, s1dir, s1dir, port1, 3, 1, tickTime, initLimit, syncLimit, hq1); + assertEquals(port1, s1.getClientPort()); + + LOG.info("creating QuorumPeer 2 port " + port2); + QuorumHierarchical hq2 = new QuorumHierarchical(qp); + s2 = new QuorumPeer(peers, s2dir, s2dir, port2, 3, 2, tickTime, initLimit, syncLimit, hq2); + assertEquals(port2, s2.getClientPort()); + + LOG.info("creating QuorumPeer 3 port " + port3); + QuorumHierarchical hq3 = new QuorumHierarchical(qp); + s3 = new QuorumPeer(peers, s3dir, s3dir, port3, 3, 3, tickTime, initLimit, syncLimit, hq3); + assertEquals(port3, s3.getClientPort()); + + LOG.info("creating QuorumPeer 4 port " + port4); + QuorumHierarchical hq4 = new QuorumHierarchical(qp); + s4 = new QuorumPeer(peers, s4dir, s4dir, port4, 3, 4, tickTime, initLimit, syncLimit, hq4); + assertEquals(port4, s4.getClientPort()); + + LOG.info("creating QuorumPeer 5 port " + port5); + QuorumHierarchical hq5 = new QuorumHierarchical(qp); + s5 = new QuorumPeer(peers, s5dir, s5dir, port5, 3, 5, tickTime, initLimit, syncLimit, hq5); + assertEquals(port5, s5.getClientPort()); + LOG.info("start QuorumPeer 1"); + s1.start(); + LOG.info("start QuorumPeer 2"); + s2.start(); + LOG.info("start QuorumPeer 3"); + s3.start(); + LOG.info("start QuorumPeer 4"); + s4.start(); + LOG.info("start QuorumPeer 5"); + s5.start(); + LOG.info("started QuorumPeer 5"); + + LOG.info ("Closing ports " + hostPort); + for (String hp : hostPort.split(",")) { + assertTrue("waiting for server up", + ClientBase.waitForServerUp(hp, + CONNECTION_TIMEOUT)); + LOG.info(hp + " is accepting client connections"); + } - LOG.info("SetUp " + getName()); + // interesting to see what's there... + JMXEnv.dump(); + // make sure we have these 5 servers listed + Set<String> ensureNames = new LinkedHashSet<String>(); + for (int i = 1; i <= 5; i++) { + ensureNames.add("InMemoryDataTree"); + } + for (int i = 1; i <= 5; i++) { + ensureNames.add("name0=ReplicatedServer_id" + i + + ",name1=replica." + i + ",name2="); + } + for (int i = 1; i <= 5; i++) { + for (int j = 1; j <= 5; j++) { + ensureNames.add("name0=ReplicatedServer_id" + i + + ",name1=replica." + j); + } + } + for (int i = 1; i <= 5; i++) { + ensureNames.add("name0=ReplicatedServer_id" + i); + } + JMXEnv.ensureAll(ensureNames.toArray(new String[ensureNames.size()])); } + @After + @Override protected void tearDown() throws Exception { - for(int i = 0; i < threads.size(); i++) { - threads.get(i).peer.shutdown(); - ((FastLeaderElection) threads.get(i).peer.getElectionAlg()).shutdown(); + LOG.info("TearDown started"); + //ct.tearDownAll(); + + LOG.info("Shutting down server 1"); + shutdown(s1); + LOG.info("Shutting down server 2"); + shutdown(s2); + LOG.info("Shutting down server 3"); + shutdown(s3); + LOG.info("Shutting down server 4"); + shutdown(s4); + LOG.info("Shutting down server 5"); + shutdown(s5); + + for (String hp : hostPort.split(",")) { + assertTrue("waiting for server down", + ClientBase.waitForServerDown(hp, + ClientBase.CONNECTION_TIMEOUT)); + LOG.info(hp + " is no longer accepting client connections"); } + + JMXEnv.tearDown(); + LOG.info("FINISHED " + getName()); } - class LEThread extends Thread { - int i; - QuorumPeer peer; - //int peerRound = 1; - - LEThread(QuorumPeer peer, int i) { - this.i = i; - this.peer = peer; - LOG.info("Constructor: " + getName()); - } - - public void run() { - try { - Vote v = null; - while(true){ - - //while(true) { - peer.setPeerState(ServerState.LOOKING); - LOG.info("Going to call leader election."); - v = peer.getElectionAlg().lookForLeader(); - if(v == null){ - LOG.info("Thread " + i + " got a null vote"); - return; - } - - /* - * A real zookeeper would take care of setting the current vote. Here - * we do it manually. - */ - peer.setCurrentVote(v); - - LOG.info("Finished election: " + i + ", " + v.id); - votes[i] = v; - - if((peer.getPeerState() == ServerState.FOLLOWING) || - (peer.getPeerState() == ServerState.LEADING)) break; - } - LOG.debug("Thread " + i + " votes " + v); - } catch (InterruptedException e) { - e.printStackTrace(); + protected void shutdown(QuorumPeer qp) { + try { + ((FastLeaderElection) qp.getElectionAlg()).shutdown(); + LOG.info("Done with leader election"); + qp.shutdown(); + LOG.info("Done with quorum peer"); + qp.join(30000); + if (qp.isAlive()) { + fail("QP failed to shutdown in 30 seconds"); } + } catch (InterruptedException e) { + LOG.debug("QP interrupted", e); } } - @Test - public void testHierarchicalQuorum() throws Exception { - runTest(0); + protected ZooKeeper createClient() + throws IOException, InterruptedException + { + return createClient(hostPort); } - - @Test - public void testHierarchicalQuorumPartial() throws Exception { - runTest(3); + + protected ZooKeeper createClient(String hp) + throws IOException, InterruptedException + { + CountdownWatcher watcher = new CountdownWatcher(); + return createClient(watcher, hp); } - - private void runTest(int delta) throws Exception { - FastLeaderElection le[] = new FastLeaderElection[count]; - LOG.info("TestHierarchicalQuorum: " + getName()+ ", " + count); - for(int i = 0; i < count; i++) { - peers.put(Long.valueOf(i), new QuorumServer(i, new InetSocketAddress(baseport+i), - new InetSocketAddress(baseLEport+i))); - tmpdir[i] = ClientBase.createTmpDir(); - port[i] = baseport+i; - } - - for(int i = 0; i < (le.length - delta); i++) { - QuorumHierarchical hq = new QuorumHierarchical(qp); - QuorumPeer peer = new QuorumPeer(peers, tmpdir[i], tmpdir[i], port[i], 3, i, 2, 2, 2, hq); - peer.startLeaderElection(); - LEThread thread = new LEThread(peer, i); - thread.start(); - threads.add(thread); - } - LOG.info("Started threads " + getName()); - - for(int i = 0; i < threads.size(); i++) { - threads.get(i).join(15000); - if (threads.get(i).isAlive()) { - fail("Threads didn't join"); - } - } + @Test + public void testHierarchicalQuorum() throws Throwable { + ct.testHammerBasic(); } } \ No newline at end of file