hadoop-zookeeper-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From maha...@apache.org
Subject svn commit: r881882 [1/2] - in /hadoop/zookeeper/trunk: ./ docs/ src/docs/src/documentation/content/xdocs/ src/java/main/org/apache/zookeeper/server/ src/java/main/org/apache/zookeeper/server/quorum/ src/java/test/org/apache/zookeeper/server/quorum/ sr...
Date Wed, 18 Nov 2009 19:06:41 GMT
Author: mahadev
Date: Wed Nov 18 19:06:39 2009
New Revision: 881882

URL: http://svn.apache.org/viewvc?rev=881882&view=rev
Log:
ZOOKEEPER-368. Observers: core functionality (henry robinson via mahadev)

Added:
    hadoop/zookeeper/trunk/docs/zookeeperObservers.html
    hadoop/zookeeper/trunk/docs/zookeeperObservers.pdf
    hadoop/zookeeper/trunk/src/docs/src/documentation/content/xdocs/zookeeperObservers.xml
    hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/ObserverBean.java
    hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/Observer.java
    hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/ObserverMXBean.java
    hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/ObserverRequestProcessor.java
    hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/ObserverZooKeeperServer.java
    hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/server/quorum/ObserverTest.java
    hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/server/quorum/QuorumPeerTestBase.java
    hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/test/ObserverHierarchicalQuorumTest.java
    hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/test/ObserverQuorumHammerTest.java
    hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/test/ObserverTest.java
Modified:
    hadoop/zookeeper/trunk/CHANGES.txt
    hadoop/zookeeper/trunk/docs/bookkeeperConfig.html
    hadoop/zookeeper/trunk/docs/bookkeeperOverview.html
    hadoop/zookeeper/trunk/docs/bookkeeperProgrammer.html
    hadoop/zookeeper/trunk/docs/bookkeeperStarted.html
    hadoop/zookeeper/trunk/docs/index.html
    hadoop/zookeeper/trunk/docs/index.pdf
    hadoop/zookeeper/trunk/docs/javaExample.html
    hadoop/zookeeper/trunk/docs/linkmap.html
    hadoop/zookeeper/trunk/docs/linkmap.pdf
    hadoop/zookeeper/trunk/docs/recipes.html
    hadoop/zookeeper/trunk/docs/releasenotes.html
    hadoop/zookeeper/trunk/docs/zookeeperAdmin.html
    hadoop/zookeeper/trunk/docs/zookeeperHierarchicalQuorums.html
    hadoop/zookeeper/trunk/docs/zookeeperInternals.html
    hadoop/zookeeper/trunk/docs/zookeeperJMX.html
    hadoop/zookeeper/trunk/docs/zookeeperOver.html
    hadoop/zookeeper/trunk/docs/zookeeperProgrammers.html
    hadoop/zookeeper/trunk/docs/zookeeperQuotas.html
    hadoop/zookeeper/trunk/docs/zookeeperStarted.html
    hadoop/zookeeper/trunk/docs/zookeeperTutorial.html
    hadoop/zookeeper/trunk/src/docs/src/documentation/content/xdocs/index.xml
    hadoop/zookeeper/trunk/src/docs/src/documentation/content/xdocs/site.xml
    hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/AuthFastLeaderElection.java
    hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/FastLeaderElection.java
    hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/Leader.java
    hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/LeaderElection.java
    hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/LearnerHandler.java
    hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/QuorumCnxManager.java
    hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/QuorumPeer.java
    hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/QuorumPeerConfig.java
    hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/QuorumPeerMain.java
    hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/QuorumStats.java
    hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/server/quorum/QuorumPeerMainTest.java
    hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/test/AsyncHammerTest.java
    hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/test/HierarchicalQuorumTest.java
    hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/test/QuorumBase.java
    hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/test/QuorumHammerTest.java

Modified: hadoop/zookeeper/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/CHANGES.txt?rev=881882&r1=881881&r2=881882&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/CHANGES.txt (original)
+++ hadoop/zookeeper/trunk/CHANGES.txt Wed Nov 18 19:06:39 2009
@@ -152,6 +152,8 @@
 
   ZOOKEEPER-550.  Java Queue Recipe. (steven cheng via mahadev)
 
+  ZOOKEEPER-368. Observers: core functionality (henry robinson via mahadev)
+
 Release 3.2.0 - 2009-06-30
 
 Non-backward compatible changes:

Modified: hadoop/zookeeper/trunk/docs/bookkeeperConfig.html
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/docs/bookkeeperConfig.html?rev=881882&r1=881881&r2=881882&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/docs/bookkeeperConfig.html (original)
+++ hadoop/zookeeper/trunk/docs/bookkeeperConfig.html Wed Nov 18 19:06:39 2009
@@ -161,6 +161,9 @@
 <div class="menuitem">
 <a href="zookeeperJMX.html">JMX</a>
 </div>
+<div class="menuitem">
+<a href="zookeeperObservers.html">Observers Guide</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">

Modified: hadoop/zookeeper/trunk/docs/bookkeeperOverview.html
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/docs/bookkeeperOverview.html?rev=881882&r1=881881&r2=881882&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/docs/bookkeeperOverview.html (original)
+++ hadoop/zookeeper/trunk/docs/bookkeeperOverview.html Wed Nov 18 19:06:39 2009
@@ -161,6 +161,9 @@
 <div class="menuitem">
 <a href="zookeeperJMX.html">JMX</a>
 </div>
+<div class="menuitem">
+<a href="zookeeperObservers.html">Observers Guide</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">

Modified: hadoop/zookeeper/trunk/docs/bookkeeperProgrammer.html
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/docs/bookkeeperProgrammer.html?rev=881882&r1=881881&r2=881882&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/docs/bookkeeperProgrammer.html (original)
+++ hadoop/zookeeper/trunk/docs/bookkeeperProgrammer.html Wed Nov 18 19:06:39 2009
@@ -161,6 +161,9 @@
 <div class="menuitem">
 <a href="zookeeperJMX.html">JMX</a>
 </div>
+<div class="menuitem">
+<a href="zookeeperObservers.html">Observers Guide</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">

Modified: hadoop/zookeeper/trunk/docs/bookkeeperStarted.html
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/docs/bookkeeperStarted.html?rev=881882&r1=881881&r2=881882&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/docs/bookkeeperStarted.html (original)
+++ hadoop/zookeeper/trunk/docs/bookkeeperStarted.html Wed Nov 18 19:06:39 2009
@@ -161,6 +161,9 @@
 <div class="menuitem">
 <a href="zookeeperJMX.html">JMX</a>
 </div>
+<div class="menuitem">
+<a href="zookeeperObservers.html">Observers Guide</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">

Modified: hadoop/zookeeper/trunk/docs/index.html
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/docs/index.html?rev=881882&r1=881881&r2=881882&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/docs/index.html (original)
+++ hadoop/zookeeper/trunk/docs/index.html Wed Nov 18 19:06:39 2009
@@ -161,6 +161,9 @@
 <div class="menuitem">
 <a href="zookeeperJMX.html">JMX</a>
 </div>
+<div class="menuitem">
+<a href="zookeeperObservers.html">Observers Guide</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">
@@ -288,6 +291,9 @@
 <a href="zookeeperHierarchicalQuorums.html">Hierarchical quorums</a>
 </li>
       
+<li>
+<a href="zookeeperObservers.html">Observers</a> - non-voting ensemble members that easily improve ZooKeeper's scalability</li>
+      
 </ul>
       
 </li>

Modified: hadoop/zookeeper/trunk/docs/index.pdf
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/docs/index.pdf?rev=881882&r1=881881&r2=881882&view=diff
==============================================================================
Binary files - no diff available.

Modified: hadoop/zookeeper/trunk/docs/javaExample.html
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/docs/javaExample.html?rev=881882&r1=881881&r2=881882&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/docs/javaExample.html (original)
+++ hadoop/zookeeper/trunk/docs/javaExample.html Wed Nov 18 19:06:39 2009
@@ -161,6 +161,9 @@
 <div class="menuitem">
 <a href="zookeeperJMX.html">JMX</a>
 </div>
+<div class="menuitem">
+<a href="zookeeperObservers.html">Observers Guide</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">

Modified: hadoop/zookeeper/trunk/docs/linkmap.html
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/docs/linkmap.html?rev=881882&r1=881881&r2=881882&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/docs/linkmap.html (original)
+++ hadoop/zookeeper/trunk/docs/linkmap.html Wed Nov 18 19:06:39 2009
@@ -161,6 +161,9 @@
 <div class="menuitem">
 <a href="zookeeperJMX.html">JMX</a>
 </div>
+<div class="menuitem">
+<a href="zookeeperObservers.html">Observers Guide</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">
@@ -341,6 +344,12 @@
 <a href="zookeeperJMX.html">JMX</a>&nbsp;&nbsp;___________________&nbsp;&nbsp;<em>jmx</em>
 </li>
 </ul>
+      
+<ul>
+<li>
+<a href="zookeeperObservers.html">Observers Guide</a>&nbsp;&nbsp;___________________&nbsp;&nbsp;<em>observers</em>
+</li>
+</ul>
   
 </ul>
 </ul>

Modified: hadoop/zookeeper/trunk/docs/linkmap.pdf
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/docs/linkmap.pdf?rev=881882&r1=881881&r2=881882&view=diff
==============================================================================
Binary files - no diff available.

Modified: hadoop/zookeeper/trunk/docs/recipes.html
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/docs/recipes.html?rev=881882&r1=881881&r2=881882&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/docs/recipes.html (original)
+++ hadoop/zookeeper/trunk/docs/recipes.html Wed Nov 18 19:06:39 2009
@@ -161,6 +161,9 @@
 <div class="menuitem">
 <a href="zookeeperJMX.html">JMX</a>
 </div>
+<div class="menuitem">
+<a href="zookeeperObservers.html">Observers Guide</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">

Modified: hadoop/zookeeper/trunk/docs/releasenotes.html
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/docs/releasenotes.html?rev=881882&r1=881881&r2=881882&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/docs/releasenotes.html (original)
+++ hadoop/zookeeper/trunk/docs/releasenotes.html Wed Nov 18 19:06:39 2009
@@ -161,6 +161,9 @@
 <div class="menuitem">
 <a href="zookeeperJMX.html">JMX</a>
 </div>
+<div class="menuitem">
+<a href="zookeeperObservers.html">Observers Guide</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">

Modified: hadoop/zookeeper/trunk/docs/zookeeperAdmin.html
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/docs/zookeeperAdmin.html?rev=881882&r1=881881&r2=881882&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/docs/zookeeperAdmin.html (original)
+++ hadoop/zookeeper/trunk/docs/zookeeperAdmin.html Wed Nov 18 19:06:39 2009
@@ -161,6 +161,9 @@
 <div class="menuitem">
 <a href="zookeeperJMX.html">JMX</a>
 </div>
+<div class="menuitem">
+<a href="zookeeperObservers.html">Observers Guide</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">

Modified: hadoop/zookeeper/trunk/docs/zookeeperHierarchicalQuorums.html
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/docs/zookeeperHierarchicalQuorums.html?rev=881882&r1=881881&r2=881882&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/docs/zookeeperHierarchicalQuorums.html (original)
+++ hadoop/zookeeper/trunk/docs/zookeeperHierarchicalQuorums.html Wed Nov 18 19:06:39 2009
@@ -161,6 +161,9 @@
 <div class="menuitem">
 <a href="zookeeperJMX.html">JMX</a>
 </div>
+<div class="menuitem">
+<a href="zookeeperObservers.html">Observers Guide</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">

Modified: hadoop/zookeeper/trunk/docs/zookeeperInternals.html
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/docs/zookeeperInternals.html?rev=881882&r1=881881&r2=881882&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/docs/zookeeperInternals.html (original)
+++ hadoop/zookeeper/trunk/docs/zookeeperInternals.html Wed Nov 18 19:06:39 2009
@@ -161,6 +161,9 @@
 <div class="menuitem">
 <a href="zookeeperJMX.html">JMX</a>
 </div>
+<div class="menuitem">
+<a href="zookeeperObservers.html">Observers Guide</a>
+</div>
 </div>
 <div onclick="SwitchMenu('menu_selected_1.5', 'skin/')" id="menu_selected_1.5Title" class="menutitle" style="background-image: url('skin/images/chapter_open.gif');">Contributor</div>
 <div id="menu_selected_1.5" class="selectedmenuitemgroup" style="display: block;">

Modified: hadoop/zookeeper/trunk/docs/zookeeperJMX.html
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/docs/zookeeperJMX.html?rev=881882&r1=881881&r2=881882&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/docs/zookeeperJMX.html (original)
+++ hadoop/zookeeper/trunk/docs/zookeeperJMX.html Wed Nov 18 19:06:39 2009
@@ -161,6 +161,9 @@
 <div class="menupage">
 <div class="menupagetitle">JMX</div>
 </div>
+<div class="menuitem">
+<a href="zookeeperObservers.html">Observers Guide</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">

Added: hadoop/zookeeper/trunk/docs/zookeeperObservers.html
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/docs/zookeeperObservers.html?rev=881882&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/docs/zookeeperObservers.html (added)
+++ hadoop/zookeeper/trunk/docs/zookeeperObservers.html Wed Nov 18 19:06:39 2009
@@ -0,0 +1,399 @@
+<!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>ZooKeeper Observers</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> &gt; <a href="http://hadoop.apache.org/">Hadoop</a> &gt; <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">&nbsp; 
+                    <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.3 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">
+
+             &nbsp;
+           </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_selected_1.4', 'skin/')" id="menu_selected_1.4Title" class="menutitle" style="background-image: url('skin/images/chapter_open.gif');">Admin &amp; Ops</div>
+<div id="menu_selected_1.4" class="selectedmenuitemgroup" style="display: block;">
+<div class="menuitem">
+<a href="zookeeperAdmin.html">Administrator's Guide</a>
+</div>
+<div class="menuitem">
+<a href="zookeeperQuotas.html">Quota Guide</a>
+</div>
+<div class="menuitem">
+<a href="zookeeperJMX.html">JMX</a>
+</div>
+<div class="menupage">
+<div class="menupagetitle">Observers Guide</div>
+</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="zookeeperObservers.pdf"><img alt="PDF -icon" src="skin/images/pdfdoc.gif" class="skin"><br>
+        PDF</a>
+</div>
+<h1>ZooKeeper Observers</h1>
+<div id="minitoc-area">
+<ul class="minitoc">
+<li>
+<a href="#ch_Introduction">Observers: Scaling ZooKeeper Without Hurting Write Performance
+      </a>
+</li>
+<li>
+<a href="#sc_UsingObservers">How to use Observers</a>
+</li>
+<li>
+<a href="#ch_UseCases">Example use cases</a>
+</li>
+</ul>
+</div>
+  
+
+  
+
+  
+<a name="N10009"></a><a name="ch_Introduction"></a>
+<h2 class="h3">Observers: Scaling ZooKeeper Without Hurting Write Performance
+      </h2>
+<div class="section">
+<p>
+      
+<em>
+	Please note: the Observers feature currently only works with the basic
+	leader election protocol, not fast leader election or authenticated fast
+	leader election. This will be remedied when a bug in the leader election
+	protocol code is fixed in the near future. An exception will be thrown
+	if you try to start a cluster containing Observers without
+	electionAlg=0. See below for more details.
+      </em>
+    
+</p>
+<p>
+      Although ZooKeeper performs very well by having clients connect directly
+      to voting members of the ensemble, this architecture makes it hard to
+      scale out to huge numbers of clients. The problem is that as we add more
+      voting members, the write performance drops. This is due to the fact that
+      a write operation requires the agreement of (in general) at least half the
+      nodes in an ensemble and therefore the cost of a vote can increase
+      significantly as more voters are added.
+    </p>
+<p>
+      We have introduced a new type of ZooKeeper node called
+      an <em>Observer</em> which helps address this problem and
+      further improves ZooKeeper's scalability. Observers are non-voting members
+      of an ensemble which only hear the results of votes, not the agreement
+      protocol that leads up to them. Other than this simple distinction,
+      Observers function exactly the same as Followers - clients may connect to
+      them and send read and write requests to them. Observers forward these
+      requests to the Leader like Followers do, but they then simply wait to
+      hear the result of the vote. Because of this, we can increase the number
+      of Observers as much as we like without harming the performance of votes.
+    </p>
+<p>
+      Observers have other advantages. Because they do not vote, they are not a
+      critical part of the ZooKeeper ensemble. Therefore they can fail, or be
+      disconnected from the cluster, without harming the availability of the
+      ZooKeeper service. The benefit to the user is that Observers may connect
+      over less reliable network links than Followers. In fact, Observers may be
+      used to talk to a ZooKeeper server from another data center. Clients of
+      the Observer will see fast reads, as all reads are served locally, and
+      writes result in minimal network traffic as the number of messages
+      required in the absence of the vote protocol is smaller.
+    </p>
+</div>
+  
+<a name="N10022"></a><a name="sc_UsingObservers"></a>
+<h2 class="h3">How to use Observers</h2>
+<div class="section">
+<p>
+      
+<em>
+	Note that
+	until <a href="https://issues.apache.org/jira/browse/ZOOKEEPER-578">ZOOKEEPER-578</a>
+	is resolved, you must set electionAlg=0 in every server configuration
+	file. Otherwise an exception will be thrown when you try to start your
+	ensemble.
+      </em>
+    
+</p>
+<p>
+      
+<em>
+	The reason: because Observers do not participate in leader elections,
+	they rely on voting Followers to inform them of changes to the
+	Leader. Currently, only the basic leader election algorithm starts a
+	thread that responds to requests from Observers to identify the current
+	Leader. Work is in progress on other JIRAs to bring this functionality
+	to all leader election protocols.
+      </em>
+    
+</p>
+<p>Setting up a ZooKeeper ensemble that uses Observers is very simple,
+    and requires just two changes to your config files. Firstly, in the config
+    file of every node that is to be an Observer, you must place this line:
+    </p>
+<pre class="code">
+      peerType=observer
+    </pre>
+<p>
+      This line tells ZooKeeper that the server is to be an Observer. Secondly,
+      in every server config file, you must add :observer to the server
+      definition line of each Observer. For example:
+    </p>
+<pre class="code">
+      server.1:localhost:2181:3181:observer
+    </pre>
+<p>
+      This tells every other server that server.1 is an Observer, and that they
+      should not expect it to vote. This is all the configuration you need to do
+      to add an Observer to your ZooKeeper cluster. Now you can connect to it as
+      though it were an ordinary Follower. Try it out, by running:</p>
+<pre class="code">
+      bin/zkCli.sh -server localhost:2181
+    </pre>
+<p>
+      where localhost:2181 is the hostname and port number of the Observer as
+      specified in every config file. You should see a command line prompt
+      through which you can issue commands like <em>ls</em> to query
+      the ZooKeeper service.
+    </p>
+</div>
+  
+  
+<a name="N10051"></a><a name="ch_UseCases"></a>
+<h2 class="h3">Example use cases</h2>
+<div class="section">
+<p>
+      Two example use cases for Observers are listed below. In fact, wherever
+      you wish to scale the numbe of clients of your ZooKeeper ensemble, or
+      where you wish to insulate the critical part of an ensemble from the load
+      of dealing with client requests, Observers are a good architectural
+      choice.
+    </p>
+<ul>
+      
+<li>
+	
+<p> As a datacenter bridge: Forming a ZK ensemble between two
+	datacenters is a problematic endeavour as the high variance in latency
+	between the datacenters could lead to false positive failure detection
+	and partitioning. However if the ensemble runs entirely in one
+	datacenter, and the second datacenter runs only Observers, partitions
+	aren't problematic as the ensemble remains connected. Clients of the
+	Observers may still see and issue proposals.</p>
+      
+</li>
+      
+<li>
+	
+<p>As a link to a message bus: Some companies have expressed an
+	interest in using ZK as a component of a persistent reliable message
+	bus. Observers would give a natural integration point for this work: a
+	plug-in mechanism could be used to attach the stream of proposals an
+	Observer sees to a publish-subscribe system, again without loading the
+	core ensemble.
+	</p>
+      
+</li>
+    
+</ul>
+</div>
+
+<p align="right">
+<font size="-2"></font>
+</p>
+</div>
+<!--+
+    |end content
+    +-->
+<div class="clearboth">&nbsp;</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 &copy;
+         2008 <a href="http://www.apache.org/licenses/">The Apache Software Foundation.</a>
+</div>
+<!--+
+    |end bottomstrip
+    +-->
+</div>
+</body>
+</html>

Added: hadoop/zookeeper/trunk/docs/zookeeperObservers.pdf
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/docs/zookeeperObservers.pdf?rev=881882&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/docs/zookeeperObservers.pdf (added)
+++ hadoop/zookeeper/trunk/docs/zookeeperObservers.pdf Wed Nov 18 19:06:39 2009
@@ -0,0 +1,276 @@
+%PDF-1.3
+%ª«¬­
+4 0 obj
+<< /Type /Info
+/Producer (FOP 0.20.5) >>
+endobj
+5 0 obj
+<< /Length 521 /Filter [ /ASCII85Decode /FlateDecode ]
+ >>
+stream
+GauHHa_nsL&A@6Wjp6aR?F09).M->*D+,_G/r'uXL]fGT9IYHuP*FUuWktI0F,4K,4>ZG?4G2:u*&4*+@>H]M=238&Yj_qV_abiLHp5T,q'![lGj[^DFXQ9?l98J"+?UY<mUrBGmo#L#G_Pq$NYs\t4)or"OO(Z#bk<VL!5a5;F+H"g%6RBt.p8\_ePT+RG+YeOaMQTr!XS56,FDL4.7&oN-6R<eoGbHWhgr6VYAE2iR]Q'h@3$A*)V6f)9=6Y.1#?Zo\MVjIEL8m[SLM6IMUZX??e5<K!fC*fTLVfDJ/KP$@e@#;/psaD[Oe3?ITnl+3ZW30rI;:+-2auJJtJe@%loN-eC[>=3q2)uZJN)Sfhikd9)7B2>7G8q1]rGte1gUQlBbd@/V4'=#iKj-(f:<;6KUFWK5)UW<\97s)B9%;JO"lROY7hd8-Fn`2eo\Nq-n()7!PDW=GpW.=t<oOCKte@e?pYR1V6%:Srq_Bo>K^i5gHdfar5Ejd]mB>HuihtIff32&j-~>
+endstream
+endobj
+6 0 obj
+<< /Type /Page
+/Parent 1 0 R
+/MediaBox [ 0 0 612 792 ]
+/Resources 3 0 R
+/Contents 5 0 R
+/Annots 7 0 R
+>>
+endobj
+7 0 obj
+[
+8 0 R
+10 0 R
+12 0 R
+]
+endobj
+8 0 obj
+<< /Type /Annot
+/Subtype /Link
+/Rect [ 102.0 529.541 435.26 517.541 ]
+/C [ 0 0 0 ]
+/Border [ 0 0 0 ]
+/A 9 0 R
+/H /I
+>>
+endobj
+10 0 obj
+<< /Type /Annot
+/Subtype /Link
+/Rect [ 102.0 511.341 216.308 499.341 ]
+/C [ 0 0 0 ]
+/Border [ 0 0 0 ]
+/A 11 0 R
+/H /I
+>>
+endobj
+12 0 obj
+<< /Type /Annot
+/Subtype /Link
+/Rect [ 102.0 493.141 199.976 481.141 ]
+/C [ 0 0 0 ]
+/Border [ 0 0 0 ]
+/A 13 0 R
+/H /I
+>>
+endobj
+14 0 obj
+<< /Length 2546 /Filter [ /ASCII85Decode /FlateDecode ]
+ >>
+stream
+GatU59on'f'#"%Ccn,PXUZbos"+.6S44tm8^$u(,ZJG[fU:Q2Da:9LjHiEu0>$k8BfcKTk/jm$7Z6!AdH6hB1m!a>K3e$.9c9o/6SE%n=4S\N=]a)lH.!5DAE?8lXhr">!&'fS7pWpU(IqZ?@ijsEC4StMP9$$&`i%LpUj8@-oo&u9N:TA2s#JYAl,p.Q`U?,&>"4sBt23U$_r/^I=lgF/XmVeJ(5LZ6K_^r^Hc'$#%Y+OL)C$Z%ak0@E0YMG[3_Skts+[R)Qi4DiI"S\VLX?kl=eT)@.HfBe<QU`?7D5YcCH)ENdD=tP(;A-Gk8jB$[/c^iA\-$M7^,08m"br7C4E#q:,<ReL06;b#_R!:Fb#NRSJj^cdVL?Q7F#`Abf"m;V.rs53i`j#_[!F\<Jk8rc(_@s]f=V[n:tqAtII)8ibSQW]RO.7#6^/84K)F4dQp=(JY6rb]%]:"J0K@W\-"go8ZKm@$0RA_mj'QhUVDB,U1Vf1LDDo@`TkmM.?-r>?>lK4R*I:R-p9n`3^M0*RN@<sif<cC1>fi9<8J9mA9p`7[9YeEGNrSS[(*>Q^'4.Yr1%Z`4P;2\Be$`::AIAuhWu?3Kil?8J=Z57fSRpi(e^*lD;V*%;k<[!^J.O?!!`"!#IQ=Y\JlQ+`8@+$N.KLG%K[A)K/5,Z3#-g$n"<'<M7Et-#=V"MA^*(M,CuF-,hr3HIkF'UkT]\<Ma-o/3oTEm-`4E2"%*AtCKCAuXGNt2JR6!\dL@ClN9VO7n9OnJ&#Up8rfB+&k:CO-&jtu@T'duOD_J+_d?\c&!ZRinG<m*;%Q89ho3mXn);1%Q/#ul6@s$auQ8<]I+%+B0LK6>$<B$@3(C&W;],]50nYbU?Rrj&@n3rT)Hkj":'keHul"8\TiUqT*2JVj*JX;E<cg#t(TlS3(_emOaaZNU;3O=iCD#n+g&\S<\3,$][Xp_,d&OL_7NV@c<I8uU=jT_*=`@$*#nBu<r6>"hk
 To>8S[..LoKq1QH^Z,;i*[TXDON_:^V=7Q`NlhScL#T;,oOoc)e;NW-`/H8r+(hSW:pEC6d<5*6LN<lmKNYD!:jWnkG2,:eF2Zu7a!:t4ropM&%C@+KX#g5gog*_i3W8W@Vbhj;>n'JsYG1f/\U4"rqJ'7+M-1C6?-47XnGA\1cgKCo#OS\8VED\!T!8=Sj/OT6-DJUBiCJ(tAK7a^R+:,V_@="E"B%*<QEa.QMTZ[WD&OVDCdD/pqi!RlIdTdgCh9@f/41R,Zr!Q`^$OfVEC(-2l^trOmhPgiE)]A5GL>/[F)L,b?elZ&fU#EKbb#hbP>a;>'0(B-AkLSWD=De]VpP[W)h7le0F5kHRN4Lip?gUlDnVDWO5[>eFqM1+%S1ZO*^m.UG]eX#;@bVSRJ<;G/CIh-??BS.^,XlC]iAp3B9*sf\!QB>0H'tJ9rb<_'6^Z@7e$d.L[5N^C8<UrXd7)i,N5.'t`%R96)suQQm#4@oN07>9%,oT;Xf)r=iX)+Y47_Ob)GuM0Lc7_Bq^LCT^09&,b:XM"(q^=kjYPSoDHLL9!t*VT=U%MRPpX(R0UOmP?^Q0dCckRVG`R0D\im&73G$U<[Lcj%J7JFO$o.r'/GA-_YLjN4G;KIVaArCP4eY9hD0r>dq"E,_/#7*V'_XB7Xk7JVp(gGH]>gcsU9I^[[RbNe(bmG%\,A$'Q=Te^Vhdkt.l9TST7eJ8Hb3OH\K<4l`j;sY^DJ[,0rlA?i3TU>.rJ:#1:\$TK!dR6U"FFGK)]Ojs/c]69_cJGI&>?MF/%*gkmOf9P4c6`<t-_7%/6j&G9_]]SJ+WF9(ffUBADmoD\,+[C5B?cOIW&bP.%&fX'&TbF(<e&^b[*p/Cs/g]rQ_Y]t@:5!h8nM*,dT7.r.H)<-]bC)fJG%DV]6loQ#2cghP1I_o0g4@#-O&AG\gS%4,IG.9^L)fj7,N60?0q0O707rKl>/"Fe#=[/<2kVaAtV<`F>9TbH
 V8T:MOF"E#&fcroT#TsNGZim@A2j[nQYDAK.q`VDJeB`)$USU!Cl05*t-]mp(:gUA9]rcoT`ff2+./dgTK*!gs<.%=3?l%%D^NgK&AT5ldDG5>ud(oJa]A4o[;pA?EP_b$J`V)WYa'<"fj;L[G8>m.#*fpCF<i(ZPN5&I26'`ZX-4+(RteB]m/SK^K4`UG4MI6>4=5^1AP;=YH^A`_n[<QJq:HJ9`dEFtToGSP)i/WJ9\6Hpf8Cd^B:V[n4r\`"7*@9\Di(:#mGA9?><b*>=G-^+7iI2]80dp4-*JC;$Nr]ffQrQ&?OP>t*V-0J72W.iD4@4p4_;cSG94tBc<_V]6?WA-)gLb(m?h^t-P4N=GQ=nr.IF!G`)(8l&;`_HjbkQcHeNDEJsT-f+Xhg:n5hufSWr=%*aAi]:E]pt>C?]Q/DG[V@KYhdXRES(e<\=K!W%+)Y8Dl=);d6S\i87)6SG5"SpA._5f%pf.0cHfZ6:Y0/KZQ>"M60p8,!!IR]NJTeT?CtA\gE0GK?:ONA4F*hc=g7^NG5Q1'[@qR\]0U9t(`mn;m_:)8kh?~>
+endstream
+endobj
+15 0 obj
+<< /Type /Page
+/Parent 1 0 R
+/MediaBox [ 0 0 612 792 ]
+/Resources 3 0 R
+/Contents 14 0 R
+/Annots 16 0 R
+>>
+endobj
+16 0 obj
+[
+17 0 R
+]
+endobj
+17 0 obj
+<< /Type /Annot
+/Subtype /Link
+/Rect [ 162.348 223.332 253.008 211.332 ]
+/C [ 0 0 0 ]
+/Border [ 0 0 0 ]
+/A << /URI (https://issues.apache.org/jira/browse/ZOOKEEPER-578)
+/S /URI >>
+/H /I
+>>
+endobj
+18 0 obj
+<< /Length 2247 /Filter [ /ASCII85Decode /FlateDecode ]
+ >>
+stream
+Gatm=gN)%,&:N/3n?'fkNUT]c1OVeLELP)C&o4AngB0i1&o%\K#h"V,oj(I[\1<-9dq1^^"Hg4\fs>=8iE*A-S(Zlo,k.,hn*OZN1Z(jS'Rn(oqtW8[6^G\t-+s'7QcZ;]jMc!$"X-!s/LGp*c%hq,gJ:OAQMRjF>C1i^q^?\<.e_Z0%_K-?rG&A0@3dH$XG>,kat,&Od8P[hRX-9[@JKiXVjHVlg'jV:Q./J!BSABM1qKW^d9Oe>kFU"b)@!4JAJbe$](s[c^V&7s'+j/Z`<QsiRbAHF=k:@ai\igV8#HC9iF1H2W,$GOAqNi:I/Mff%mk*RdBjYS\J!P:?DEde5X>6(\"\0[Q$#.mSfi9Z>]5k:67:1B0W;qQ7TOd(^Di(hY.)CWQTo'\_<tdOohp`nFCuM&B4:F!,(p_0$&dGZ.k=i)h3FI@5blLq+j)AJ\.fKkb#+\j(bZ'4n(\RX/s)61_X[e"JAX'X9ebEP?B>iZ;^eWa9ttujp-).0bYL?nAO2Q7mJe&Oj*B2')h7YIXg]+(,gQ^h#cB5qM,$aX^o':*_H'g&b\)4LLPHGkCpt#6S)4"^U*PR/k(c)2ZSV37ks?ikck.\U?%`cEZi"0;,!+Qe?s,M4`tMno0IQou_"%R-0&iT7/eE`'-us51oNbL(KVfFkWT@Foh4>bZ_i*&6Qu7o<l6'a(_.rLo[lX.UW=2bN_lr6D4H3I3m>ofP'&4m6E4%I0^'TES\;ApH:ZZejAh9"6r'"Q]$"H^Cj-`+<fagSq1OMTUS>(KK7$tnCdjXjk2X"02AHO@q*MB:j46Jl!`8JZWRKlb!6lV!t0a=OqL[$f5VrT-iUP1,\\W4<]mdE_T\WD22DF81#^`a1iI))FP&Cr+YIPfdk@g[T'Y[.tJi6u(HE(iRek]5d6D_%h"2)J;^2907@2+j8g3VEkGa6T1k7c^'-S</Ca$P/=uNRgofI7njA6Q[HN&+\XK/=c-h24+0Y5PM@
 HA@=o\ofIN'O/2!ST]5L/>XV`7ij:Xl]-8je?-/MYE'Uf!C;)$$6tG/A$FrSalT$:J<dD"93U\\t/?")(8/u3$[!;$/.#hAs?:]^)>/0#=3#*_iYe<"[en\_Y9kmMVY;\lF.N05[Q,KY>4:n?sNB#\E3fQl9jr]O_nm3=#Oe0rF#_KB#p&^cdBKt3+SBSd;n@9_<LA9Cu?+!FoKc&O8bR7krK-@UrBtE1T6=,#Fcgnsid(!Hh]/F8WE72Tm?l_Yn+^fpBZ8;m?O`1Z*3Qn-\q/2>bi[KXCda(nUoZ&D;7&^=f7PpSB:dtT*4%,>;0<c48nP19dY\YgA+s;'*"^qrpJq\KeP2:ZIi%Ea>_-SN=FD]hE8(60(fY1QYAmt=,,jgH^8SoEcCXNJsG?%JC!X)7$ZB.L<!ZR.'&"A:5pUoBiJ2W@&XUHl=99t/[dd_6e]fJT-(q7buYdHp04iT<(DG+J3VtJ/r"hjTA.TWj0&cjI-<'h<M6c(l$M'OKIP$l&QT4+*l;BA'k-VXE>nWaSFFieF_DKUs71Tt?"Cg2Ia[&DOY7snP3iKDsXU>?6.mg--!%%E:mRNso/b%iCVM\D>%>Jia=KEfaeO>,Xg$!Q<so=ulu2/`/.k%sjsMqo]NnBt)'$CWI!9/(S*/\&*aK$p,,%#V>F('<q*7gbT__&P$qICNC#f,tWf?*ahi7O%X1'U,n4+0.lVh%&Njm](@\/"q-(:lQO$dN;Fu5]XMM,5lV106!??oS>usiuOoob(11j!rX.R.=-ZB6&qaKN0"N+@7dF)LUoZ:PfR.60;T(inVH%-F516U')-UWR)?0%<L1hT/3+%JJ-%"XppP?6hh!+ddF[Sd4!D5;DkR-oI[i6[aF%DJ?Xh]'/<[b0KBm_0-9#1&>b%lT%RB6pgUhV`d^.)^LB??PiFlmU&R)9=S6G-.4W]9M4XPiJ*m;!J[6TGS@%sVs8PVh?_MDJCeWq]@P,K)K?h6H%\h&
 ^C&SQ`"T&)#7N5Xm+AKngeh4!X.`XRH5QIjaqCXM",9=r2M-cY)]Xg)C1)8*,oh&I0/\e9Bb^!lR9oPt_>Ka0H_:k8;20.Hdk@@_"E8A'KLFK"3nn`=C79DS_HB495Smu'R/*]Q*L`[oI44b)nuJ(uYC-U'BQm@@T"-g7a95ltMW-=.b2nb_g)D)T!512l?eXS"D<HkHj_d.d-?1tr,A+2$A/W+^Qk(A5,>b4a`JRRWVa;&Gb1(Ua47gY8I-k^Y2:!8P?L*i\l~>
+endstream
+endobj
+19 0 obj
+<< /Type /Page
+/Parent 1 0 R
+/MediaBox [ 0 0 612 792 ]
+/Resources 3 0 R
+/Contents 18 0 R
+>>
+endobj
+20 0 obj
+<< /Length 456 /Filter [ /ASCII85Decode /FlateDecode ]
+ >>
+stream
+Gar&:bAMqd&A7ljHq^BVZ&KiECoX@1HYBI#lJl7b#ET4g2DiS6f0COl&Mi'C4?MoR3X60Up]1M`r]Gc@,7K8;rlt4?0,&mRZl0_<%BOWTg2KT]s,c[MSk.Ku";75b9J2FB%-@fi\`g-ZN)P_JJP/$5>GsI0087mK=52)A>"<d`'CeEB%7O4-C?^JiD/ESBLjsHY528W7;UpohZ0j+uoV'YL[B&%;d]B0_>@ThmLAB<kQ7P>gZDDH04qruGkGtWmKrMQ*qf?1#/l<fQPU&PJAi&nnQtNP5H%.8?-3XjU\F['VSC-LK(kO()F67!eU3mA]IgLj7lZ01qU^>6^9''4L<L*EQ,)cGii,c+NV3:@.?HuCp3)#atJBXeV9m<mc=\XXnd?qlhjWkt+E>hY;HTQkl:2OM=DYF$+fr2536b?9FD-@Y$RO3PVgI54?hX+//mLKhZXip~>
+endstream
+endobj
+21 0 obj
+<< /Type /Page
+/Parent 1 0 R
+/MediaBox [ 0 0 612 792 ]
+/Resources 3 0 R
+/Contents 20 0 R
+>>
+endobj
+23 0 obj
+<<
+ /Title (\376\377\0\61\0\40\0\117\0\142\0\163\0\145\0\162\0\166\0\145\0\162\0\163\0\72\0\40\0\123\0\143\0\141\0\154\0\151\0\156\0\147\0\40\0\132\0\157\0\157\0\113\0\145\0\145\0\160\0\145\0\162\0\40\0\127\0\151\0\164\0\150\0\157\0\165\0\164\0\40\0\110\0\165\0\162\0\164\0\151\0\156\0\147\0\40\0\127\0\162\0\151\0\164\0\145\0\40\0\120\0\145\0\162\0\146\0\157\0\162\0\155\0\141\0\156\0\143\0\145)
+ /Parent 22 0 R
+ /Next 24 0 R
+ /A 9 0 R
+>> endobj
+24 0 obj
+<<
+ /Title (\376\377\0\62\0\40\0\110\0\157\0\167\0\40\0\164\0\157\0\40\0\165\0\163\0\145\0\40\0\117\0\142\0\163\0\145\0\162\0\166\0\145\0\162\0\163)
+ /Parent 22 0 R
+ /Prev 23 0 R
+ /Next 25 0 R
+ /A 11 0 R
+>> endobj
+25 0 obj
+<<
+ /Title (\376\377\0\63\0\40\0\105\0\170\0\141\0\155\0\160\0\154\0\145\0\40\0\165\0\163\0\145\0\40\0\143\0\141\0\163\0\145\0\163)
+ /Parent 22 0 R
+ /Prev 24 0 R
+ /A 13 0 R
+>> endobj
+26 0 obj
+<< /Type /Font
+/Subtype /Type1
+/Name /F3
+/BaseFont /Helvetica-Bold
+/Encoding /WinAnsiEncoding >>
+endobj
+27 0 obj
+<< /Type /Font
+/Subtype /Type1
+/Name /F5
+/BaseFont /Times-Roman
+/Encoding /WinAnsiEncoding >>
+endobj
+28 0 obj
+<< /Type /Font
+/Subtype /Type1
+/Name /F6
+/BaseFont /Times-Italic
+/Encoding /WinAnsiEncoding >>
+endobj
+29 0 obj
+<< /Type /Font
+/Subtype /Type1
+/Name /F1
+/BaseFont /Helvetica
+/Encoding /WinAnsiEncoding >>
+endobj
+30 0 obj
+<< /Type /Font
+/Subtype /Type1
+/Name /F9
+/BaseFont /Courier
+/Encoding /WinAnsiEncoding >>
+endobj
+31 0 obj
+<< /Type /Font
+/Subtype /Type1
+/Name /F2
+/BaseFont /Helvetica-Oblique
+/Encoding /WinAnsiEncoding >>
+endobj
+32 0 obj
+<< /Type /Font
+/Subtype /Type1
+/Name /F7
+/BaseFont /Times-Bold
+/Encoding /WinAnsiEncoding >>
+endobj
+1 0 obj
+<< /Type /Pages
+/Count 4
+/Kids [6 0 R 15 0 R 19 0 R 21 0 R ] >>
+endobj
+2 0 obj
+<< /Type /Catalog
+/Pages 1 0 R
+ /Outlines 22 0 R
+ /PageMode /UseOutlines
+ >>
+endobj
+3 0 obj
+<< 
+/Font << /F3 26 0 R /F5 27 0 R /F1 29 0 R /F6 28 0 R /F9 30 0 R /F2 31 0 R /F7 32 0 R >> 
+/ProcSet [ /PDF /ImageC /Text ] >> 
+endobj
+9 0 obj
+<<
+/S /GoTo
+/D [15 0 R /XYZ 85.0 659.0 null]
+>>
+endobj
+11 0 obj
+<<
+/S /GoTo
+/D [15 0 R /XYZ 85.0 252.666 null]
+>>
+endobj
+13 0 obj
+<<
+/S /GoTo
+/D [19 0 R /XYZ 85.0 336.26 null]
+>>
+endobj
+22 0 obj
+<<
+ /First 23 0 R
+ /Last 25 0 R
+>> endobj
+xref
+0 33
+0000000000 65535 f 
+0000008992 00000 n 
+0000009071 00000 n 
+0000009163 00000 n 
+0000000015 00000 n 
+0000000071 00000 n 
+0000000683 00000 n 
+0000000803 00000 n 
+0000000842 00000 n 
+0000009308 00000 n 
+0000000976 00000 n 
+0000009371 00000 n 
+0000001113 00000 n 
+0000009437 00000 n 
+0000001250 00000 n 
+0000003889 00000 n 
+0000004012 00000 n 
+0000004039 00000 n 
+0000004244 00000 n 
+0000006584 00000 n 
+0000006692 00000 n 
+0000007240 00000 n 
+0000009502 00000 n 
+0000007348 00000 n 
+0000007804 00000 n 
+0000008027 00000 n 
+0000008219 00000 n 
+0000008332 00000 n 
+0000008442 00000 n 
+0000008553 00000 n 
+0000008661 00000 n 
+0000008767 00000 n 
+0000008883 00000 n 
+trailer
+<<
+/Size 33
+/Root 2 0 R
+/Info 4 0 R
+>>
+startxref
+9553
+%%EOF

Modified: hadoop/zookeeper/trunk/docs/zookeeperOver.html
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/docs/zookeeperOver.html?rev=881882&r1=881881&r2=881882&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/docs/zookeeperOver.html (original)
+++ hadoop/zookeeper/trunk/docs/zookeeperOver.html Wed Nov 18 19:06:39 2009
@@ -161,6 +161,9 @@
 <div class="menuitem">
 <a href="zookeeperJMX.html">JMX</a>
 </div>
+<div class="menuitem">
+<a href="zookeeperObservers.html">Observers Guide</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">

Modified: hadoop/zookeeper/trunk/docs/zookeeperProgrammers.html
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/docs/zookeeperProgrammers.html?rev=881882&r1=881881&r2=881882&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/docs/zookeeperProgrammers.html (original)
+++ hadoop/zookeeper/trunk/docs/zookeeperProgrammers.html Wed Nov 18 19:06:39 2009
@@ -161,6 +161,9 @@
 <div class="menuitem">
 <a href="zookeeperJMX.html">JMX</a>
 </div>
+<div class="menuitem">
+<a href="zookeeperObservers.html">Observers Guide</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">

Modified: hadoop/zookeeper/trunk/docs/zookeeperQuotas.html
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/docs/zookeeperQuotas.html?rev=881882&r1=881881&r2=881882&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/docs/zookeeperQuotas.html (original)
+++ hadoop/zookeeper/trunk/docs/zookeeperQuotas.html Wed Nov 18 19:06:39 2009
@@ -161,6 +161,9 @@
 <div class="menuitem">
 <a href="zookeeperJMX.html">JMX</a>
 </div>
+<div class="menuitem">
+<a href="zookeeperObservers.html">Observers Guide</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">

Modified: hadoop/zookeeper/trunk/docs/zookeeperStarted.html
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/docs/zookeeperStarted.html?rev=881882&r1=881881&r2=881882&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/docs/zookeeperStarted.html (original)
+++ hadoop/zookeeper/trunk/docs/zookeeperStarted.html Wed Nov 18 19:06:39 2009
@@ -161,6 +161,9 @@
 <div class="menuitem">
 <a href="zookeeperJMX.html">JMX</a>
 </div>
+<div class="menuitem">
+<a href="zookeeperObservers.html">Observers Guide</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">

Modified: hadoop/zookeeper/trunk/docs/zookeeperTutorial.html
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/docs/zookeeperTutorial.html?rev=881882&r1=881881&r2=881882&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/docs/zookeeperTutorial.html (original)
+++ hadoop/zookeeper/trunk/docs/zookeeperTutorial.html Wed Nov 18 19:06:39 2009
@@ -161,6 +161,9 @@
 <div class="menuitem">
 <a href="zookeeperJMX.html">JMX</a>
 </div>
+<div class="menuitem">
+<a href="zookeeperObservers.html">Observers Guide</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">

Modified: hadoop/zookeeper/trunk/src/docs/src/documentation/content/xdocs/index.xml
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/docs/src/documentation/content/xdocs/index.xml?rev=881882&r1=881881&r2=881882&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/src/docs/src/documentation/content/xdocs/index.xml (original)
+++ hadoop/zookeeper/trunk/src/docs/src/documentation/content/xdocs/index.xml Wed Nov 18 19:06:39 2009
@@ -64,6 +64,7 @@
       <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>
+      <li><a href="zookeeperObservers.html">Observers</a> - non-voting ensemble members that easily improve ZooKeeper's scalability</li>
       </ul>
       </li>
       

Modified: hadoop/zookeeper/trunk/src/docs/src/documentation/content/xdocs/site.xml
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/docs/src/documentation/content/xdocs/site.xml?rev=881882&r1=881881&r2=881882&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/src/docs/src/documentation/content/xdocs/site.xml (original)
+++ hadoop/zookeeper/trunk/src/docs/src/documentation/content/xdocs/site.xml Wed Nov 18 19:06:39 2009
@@ -57,6 +57,7 @@
       <admin label="Administrator's Guide"  href="zookeeperAdmin.html" />
       <quota label="Quota Guide"            href="zookeeperQuotas.html" />
       <jmx   label="JMX"                    href="zookeeperJMX.html" />
+      <observers label="Observers Guide" href="zookeeperObservers.html" />
   </docs>
   
   <docs label="Contributor">

Added: hadoop/zookeeper/trunk/src/docs/src/documentation/content/xdocs/zookeeperObservers.xml
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/docs/src/documentation/content/xdocs/zookeeperObservers.xml?rev=881882&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/docs/src/documentation/content/xdocs/zookeeperObservers.xml (added)
+++ hadoop/zookeeper/trunk/src/docs/src/documentation/content/xdocs/zookeeperObservers.xml Wed Nov 18 19:06:39 2009
@@ -0,0 +1,174 @@
+<?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="bk_GettStartedGuide">
+  <title>ZooKeeper Observers</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 guide contains information about using non-voting servers, or
+      observers in your ZooKeeper ensembles.</para>
+    </abstract>
+  </articleinfo>
+
+  <section id="ch_Introduction">
+    <title>Observers: Scaling ZooKeeper Without Hurting Write Performance
+      </title>
+    <para>
+      <emphasis>
+	Please note: the Observers feature currently only works with the basic
+	leader election protocol, not fast leader election or authenticated fast
+	leader election. This will be remedied when a bug in the leader election
+	protocol code is fixed in the near future. An exception will be thrown
+	if you try to start a cluster containing Observers without
+	electionAlg=0. See below for more details.
+      </emphasis>
+    </para>
+    <para>
+      Although ZooKeeper performs very well by having clients connect directly
+      to voting members of the ensemble, this architecture makes it hard to
+      scale out to huge numbers of clients. The problem is that as we add more
+      voting members, the write performance drops. This is due to the fact that
+      a write operation requires the agreement of (in general) at least half the
+      nodes in an ensemble and therefore the cost of a vote can increase
+      significantly as more voters are added.
+    </para>
+    <para>
+      We have introduced a new type of ZooKeeper node called
+      an <emphasis>Observer</emphasis> which helps address this problem and
+      further improves ZooKeeper's scalability. Observers are non-voting members
+      of an ensemble which only hear the results of votes, not the agreement
+      protocol that leads up to them. Other than this simple distinction,
+      Observers function exactly the same as Followers - clients may connect to
+      them and send read and write requests to them. Observers forward these
+      requests to the Leader like Followers do, but they then simply wait to
+      hear the result of the vote. Because of this, we can increase the number
+      of Observers as much as we like without harming the performance of votes.
+    </para>
+    <para>
+      Observers have other advantages. Because they do not vote, they are not a
+      critical part of the ZooKeeper ensemble. Therefore they can fail, or be
+      disconnected from the cluster, without harming the availability of the
+      ZooKeeper service. The benefit to the user is that Observers may connect
+      over less reliable network links than Followers. In fact, Observers may be
+      used to talk to a ZooKeeper server from another data center. Clients of
+      the Observer will see fast reads, as all reads are served locally, and
+      writes result in minimal network traffic as the number of messages
+      required in the absence of the vote protocol is smaller.
+    </para>
+  </section>
+  <section id="sc_UsingObservers">
+    <title>How to use Observers</title>
+    <para>
+      <emphasis>
+	Note that
+	until <ulink url="https://issues.apache.org/jira/browse/ZOOKEEPER-578">ZOOKEEPER-578</ulink>
+	is resolved, you must set electionAlg=0 in every server configuration
+	file. Otherwise an exception will be thrown when you try to start your
+	ensemble.
+      </emphasis>
+    </para>
+    <para>
+      <emphasis>
+	The reason: because Observers do not participate in leader elections,
+	they rely on voting Followers to inform them of changes to the
+	Leader. Currently, only the basic leader election algorithm starts a
+	thread that responds to requests from Observers to identify the current
+	Leader. Work is in progress on other JIRAs to bring this functionality
+	to all leader election protocols.
+      </emphasis>
+    </para>
+    <para>Setting up a ZooKeeper ensemble that uses Observers is very simple,
+    and requires just two changes to your config files. Firstly, in the config
+    file of every node that is to be an Observer, you must place this line:
+    </para>
+    <programlisting>
+      peerType=observer
+    </programlisting>
+    
+    <para>
+      This line tells ZooKeeper that the server is to be an Observer. Secondly,
+      in every server config file, you must add :observer to the server
+      definition line of each Observer. For example:
+    </para>
+    
+    <programlisting>
+      server.1:localhost:2181:3181:observer
+    </programlisting>
+    
+    <para>
+      This tells every other server that server.1 is an Observer, and that they
+      should not expect it to vote. This is all the configuration you need to do
+      to add an Observer to your ZooKeeper cluster. Now you can connect to it as
+      though it were an ordinary Follower. Try it out, by running:</para>
+    <programlisting>
+      bin/zkCli.sh -server localhost:2181
+    </programlisting>
+    <para>
+      where localhost:2181 is the hostname and port number of the Observer as
+      specified in every config file. You should see a command line prompt
+      through which you can issue commands like <emphasis>ls</emphasis> to query
+      the ZooKeeper service.
+    </para>
+  </section>
+  
+  <section id="ch_UseCases">
+    <title>Example use cases</title>
+    <para>
+      Two example use cases for Observers are listed below. In fact, wherever
+      you wish to scale the numbe of clients of your ZooKeeper ensemble, or
+      where you wish to insulate the critical part of an ensemble from the load
+      of dealing with client requests, Observers are a good architectural
+      choice.
+    </para>
+    <itemizedlist>
+      <listitem>
+	<para> As a datacenter bridge: Forming a ZK ensemble between two
+	datacenters is a problematic endeavour as the high variance in latency
+	between the datacenters could lead to false positive failure detection
+	and partitioning. However if the ensemble runs entirely in one
+	datacenter, and the second datacenter runs only Observers, partitions
+	aren't problematic as the ensemble remains connected. Clients of the
+	Observers may still see and issue proposals.</para>
+      </listitem>
+      <listitem>
+	<para>As a link to a message bus: Some companies have expressed an
+	interest in using ZK as a component of a persistent reliable message
+	bus. Observers would give a natural integration point for this work: a
+	plug-in mechanism could be used to attach the stream of proposals an
+	Observer sees to a publish-subscribe system, again without loading the
+	core ensemble.
+	</para>
+      </listitem>
+    </itemizedlist>
+  </section>
+</article>

Added: hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/ObserverBean.java
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/ObserverBean.java?rev=881882&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/ObserverBean.java (added)
+++ hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/ObserverBean.java Wed Nov 18 19:06:39 2009
@@ -0,0 +1,45 @@
+/**
+ * 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
+ * to you 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.
+ */
+
+package org.apache.zookeeper.server;
+
+import org.apache.zookeeper.server.quorum.Observer;
+import org.apache.zookeeper.server.quorum.ObserverMXBean;
+
+/**
+ * ObserverBean
+ *
+ */
+public class ObserverBean extends ZooKeeperServerBean implements ObserverMXBean{
+
+    private Observer observer;
+    
+    public ObserverBean(Observer observer, ZooKeeperServer zks) {
+        super(zks);        
+        this.observer = observer;
+    }
+
+    public int getPendingRevalidationCount() {
+       return this.observer.getPendingRevalidationsCount(); 
+    }
+
+    public String getQuorumAddress() {
+        return observer.getSocket().toString();
+    }
+
+}

Modified: hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/AuthFastLeaderElection.java
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/AuthFastLeaderElection.java?rev=881882&r1=881881&r2=881882&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/AuthFastLeaderElection.java (original)
+++ hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/AuthFastLeaderElection.java Wed Nov 18 19:06:39 2009
@@ -712,7 +712,7 @@
                 t.start();
             }
 
-            for (QuorumServer server : self.quorumPeers.values()) {
+            for (QuorumServer server : self.getVotingView().values()) {
                 InetSocketAddress saddr = new InetSocketAddress(server.addr
                         .getAddress(), port);
                 addrChallengeMap.put(saddr, new HashMap<Long, Long>());
@@ -744,7 +744,7 @@
 
     private void starter(QuorumPeer self) {
         this.self = self;
-        port = self.quorumPeers.get(self.getId()).electionAddr.getPort();
+        port = self.getVotingView().get(self.getId()).electionAddr.getPort();
         proposedLeader = -1;
         proposedZxid = -1;
 
@@ -755,10 +755,10 @@
             e1.printStackTrace();
             throw new RuntimeException();
         }
-        sendqueue = new LinkedBlockingQueue<ToSend>(2 * self.quorumPeers.size());
-        recvqueue = new LinkedBlockingQueue<Notification>(2 * self.quorumPeers
+        sendqueue = new LinkedBlockingQueue<ToSend>(2 * self.getVotingView().size());
+        recvqueue = new LinkedBlockingQueue<Notification>(2 * self.getVotingView()
                 .size());
-        new Messenger(self.quorumPeers.size() * 2, mySocket);
+        new Messenger(self.getVotingView().size() * 2, mySocket);
     }
 
     private void leaveInstance() {
@@ -766,12 +766,12 @@
     }
 
     private void sendNotifications() {
-        for (QuorumServer server : self.quorumPeers.values()) {
+        for (QuorumServer server : self.getView().values()) {
 
             ToSend notmsg = new ToSend(ToSend.mType.notification,
                     AuthFastLeaderElection.sequencer++, proposedLeader,
                     proposedZxid, logicalclock, QuorumPeer.ServerState.LOOKING,
-                    self.quorumPeers.get(server.id).electionAddr);
+                    self.getView().get(server.id).electionAddr);
 
             sendqueue.offer(notmsg);
         }
@@ -801,7 +801,7 @@
                 count++;
         }
 
-        if (count > (self.quorumPeers.size() / 2))
+        if (count > (self.getVotingView().size() / 2))
             return true;
         else
             return false;
@@ -875,7 +875,7 @@
                         recvset.put(n.addr, new Vote(n.leader, n.zxid));
     
                         // If have received from all nodes, then terminate
-                        if (self.quorumPeers.size() == recvset.size()) {
+                        if (self.getVotingView().size() == recvset.size()) {
                             self.setPeerState((proposedLeader == self.getId()) ? 
                                     ServerState.LEADING: ServerState.FOLLOWING);
                             // if (self.state == ServerState.FOLLOWING) {

Modified: hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/FastLeaderElection.java
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/FastLeaderElection.java?rev=881882&r1=881881&r2=881882&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/FastLeaderElection.java (original)
+++ hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/FastLeaderElection.java Wed Nov 18 19:06:39 2009
@@ -440,7 +440,7 @@
      * Send notifications to all peers upon a change in our vote
      */
     private void sendNotifications() {
-        for (QuorumServer server : self.quorumPeers.values()) {
+        for (QuorumServer server : self.getVotingView().values()) {
             long sid = server.id;
 
             ToSend notmsg = new ToSend(ToSend.mType.notification, 

Modified: hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/Leader.java
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/Leader.java?rev=881882&r1=881881&r2=881882&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/Leader.java (original)
+++ hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/Leader.java Wed Nov 18 19:06:39 2009
@@ -42,6 +42,7 @@
 import org.apache.zookeeper.server.FinalRequestProcessor;
 import org.apache.zookeeper.server.Request;
 import org.apache.zookeeper.server.RequestProcessor;
+import org.apache.zookeeper.server.quorum.QuorumPeer.LearnerType;
 
 /**
  * This class has the control logic for the Leader.
@@ -79,6 +80,8 @@
 
     // list of followers that are ready to follow (i.e synced with the leader)    
     public HashSet<LearnerHandler> forwardingFollowers = new HashSet<LearnerHandler>();
+    
+    protected HashSet<LearnerHandler> observingLearners = new HashSet<LearnerHandler>();
         
     //Pending sync requests
     public HashMap<Long,List<LearnerSyncRequest>> pendingSyncs = new HashMap<Long,List<LearnerSyncRequest>>();
@@ -147,6 +150,11 @@
     final static int SNAP = 15;
     
     /**
+     * This tells the leader that the connecting peer is actually an observer
+     */
+    final static int OBSERVERINFO = 16;
+    
+    /**
      * This message type is sent by the leader to indicate it's zxid and if
      * needed, its database.
      */
@@ -202,6 +210,11 @@
      * between the leader and the follower.
      */
     final static int SYNC = 7;
+        
+    /**
+     * This message type informs observers of a committed proposal.
+     */
+    final static int INFORM = 8;
     
     private ConcurrentMap<Long, Proposal> outstandingProposals = new ConcurrentHashMap<Long, Proposal>();
 
@@ -267,9 +280,10 @@
             synchronized(this){
                 lastProposed = zk.getZxid();
             }
-                      
+                        
             newLeaderProposal.packet = new QuorumPacket(NEWLEADER, zk.getZxid(),
-                    null, null);            
+                    null, null);
+
 
             if ((newLeaderProposal.packet.getZxid() & 0xffffffffL) != 0) {
                 LOG.info("NEWLEADER proposal has Zxid of "
@@ -346,8 +360,9 @@
               if (!tickSkip && !self.getQuorumVerifier().containsQuorum(syncedSet)) {
                 //if (!tickSkip && syncedCount < self.quorumPeers.size() / 2) {
                     // Lost quorum, shutdown
+                  // TODO: message is wrong unless majority quorums used
                     shutdown("Only " + syncedCount + " followers, need "
-                            + (self.quorumPeers.size() / 2));
+                            + (self.getVotingView().size() / 2));
                     // make sure the order is the same!
                     // the leader goes to looking
                     return;
@@ -362,7 +377,7 @@
     boolean isShutdown;
 
     /**
-     * Close down all the FollowerHandlers
+     * Close down all the LearnerHandlers
      */
     void shutdown(String reason) {
         if (isShutdown) {
@@ -465,6 +480,7 @@
                     LOG.warn("Going to commmit null: " + p);
                 }
                 commit(zxid);
+                inform(p);
                 zk.commitProcessor.commit(p.request);
                 if(pendingSyncs.containsKey(zxid)){
                     for(LearnerSyncRequest r: pendingSyncs.remove(zxid)) {
@@ -545,6 +561,17 @@
         }
     }
     
+    /**
+     * send a packet to all observers     
+     */
+    void sendObserverPacket(QuorumPacket qp) {        
+        synchronized(observingLearners) {
+            for (LearnerHandler f : observingLearners) {                
+                f.queuePacket(qp);
+            }
+        }
+    }
+
     long lastCommitted = -1;
 
     /**
@@ -559,6 +586,17 @@
         QuorumPacket qp = new QuorumPacket(Leader.COMMIT, zxid, null, null);
         sendPacket(qp);
     }
+    
+    /**
+     * Create an inform packet and send it to all observers.
+     * @param zxid
+     * @param proposal
+     */
+    public void inform(Proposal proposal) {   
+        QuorumPacket qp = new QuorumPacket(Leader.INFORM, proposal.request.zxid, 
+                                            proposal.packet.getData(), null);
+        sendObserverPacket(qp);
+    }
 
     long lastProposed;
 
@@ -569,7 +607,6 @@
      * @return the proposal that is queued to send to all the members
      */
     public Proposal propose(Request request) {
-        
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         BinaryOutputArchive boa = BinaryOutputArchive.getArchive(baos);
         try {
@@ -662,10 +699,16 @@
                 handler.queuePacket(outstandingProposals.get(zxid).packet);
             }
         }
-        synchronized (forwardingFollowers) {
-            forwardingFollowers.add(handler);
+        if (handler.getLearnerType() == LearnerType.PARTICIPANT) {
+            synchronized (forwardingFollowers) {
+                forwardingFollowers.add(handler);
+            }
+        } else {
+            synchronized (observingLearners) {
+                observingLearners.add(handler);
+            }
         }
-        
+                
         return lastProposed;
     }
 

Modified: hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/LeaderElection.java
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/LeaderElection.java?rev=881882&r1=881881&r2=881882&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/LeaderElection.java (original)
+++ hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/LeaderElection.java Wed Nov 18 19:06:39 2009
@@ -35,6 +35,7 @@
 
 import org.apache.zookeeper.jmx.MBeanRegistry;
 import org.apache.zookeeper.server.quorum.Vote;
+import org.apache.zookeeper.server.quorum.QuorumPeer.LearnerType;
 import org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer;
 import org.apache.zookeeper.server.quorum.QuorumPeer.ServerState;
 
@@ -142,7 +143,7 @@
             DatagramPacket responsePacket = new DatagramPacket(responseBytes,
                     responseBytes.length);
             HashMap<InetSocketAddress, Vote> votes =
-                new HashMap<InetSocketAddress, Vote>(self.quorumPeers.size());
+                new HashMap<InetSocketAddress, Vote>(self.getVotingView().size());
             int xid = epochGen.nextInt();
             while (self.running) {
                 votes.clear();
@@ -150,7 +151,7 @@
                 requestBuffer.putInt(xid);
                 requestPacket.setLength(4);
                 HashSet<Long> heardFrom = new HashSet<Long>();
-                for (QuorumServer server : self.quorumPeers.values()) {
+                for (QuorumServer server : self.getVotingView().values()) {
                     LOG.info("Server address: " + server.addr);
                     try {
                         requestPacket.setSocketAddress(server.addr);
@@ -200,16 +201,38 @@
                 ElectionResult result = countVotes(votes, heardFrom);
                 if (result.winner.id >= 0) {
                     self.setCurrentVote(result.vote);
-                    if (result.winningCount > (self.quorumPeers.size() / 2)) {
+                    // To do: this doesn't use a quorum verifier
+                    if (result.winningCount > (self.getVotingView().size() / 2)) {
                         self.setCurrentVote(result.winner);
                         s.close();
                         Vote current = self.getCurrentVote();
-                        self.setPeerState((current.id == self.getId())
-                                ? ServerState.LEADING: ServerState.FOLLOWING);
-                        if (self.getPeerState() == ServerState.FOLLOWING) {
-                            Thread.sleep(100);
+                        LOG.info("Found leader: my type is: " + self.getPeerType());
+                        /**
+                         * We want to make sure we implement the state machine
+                         * correctly. If we are a PARTICIPANT, once a leader
+                         * is elected we can move either to LEADING or 
+                         * FOLLOWING. However if we are an OBSERVER, it is an
+                         * error to be elected as a Leader.
+                         */
+                        if (self.getPeerType() == LearnerType.OBSERVER) {
+                            if (current.id == self.getId()) {
+                                // This should never happen!
+                                LOG.error("OBSERVER elected as leader!");
+                                Thread.sleep(100);
+                            }
+                            else {
+                                self.setPeerState(ServerState.OBSERVING);
+                                Thread.sleep(100);
+                                return current;
+                            }
+                        } else {
+                            self.setPeerState((current.id == self.getId())
+                                    ? ServerState.LEADING: ServerState.FOLLOWING);
+                            if (self.getPeerState() == ServerState.FOLLOWING) {
+                                Thread.sleep(100);
+                            }                            
+                            return current;
                         }
-                        return current;
                     }
                 }
                 Thread.sleep(1000);

Modified: hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/LearnerHandler.java
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/LearnerHandler.java?rev=881882&r1=881881&r2=881882&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/LearnerHandler.java (original)
+++ hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/LearnerHandler.java Wed Nov 18 19:06:39 2009
@@ -38,6 +38,7 @@
 import org.apache.zookeeper.server.Request;
 import org.apache.zookeeper.server.ZooTrace;
 import org.apache.zookeeper.server.quorum.Leader.Proposal;
+import org.apache.zookeeper.server.quorum.QuorumPeer.LearnerType;
 import org.apache.zookeeper.server.util.SerializeUtils;
 import org.apache.zookeeper.txn.TxnHeader;
 
@@ -101,7 +102,12 @@
      * If this packet is queued, the sender thread will exit
      */
     final QuorumPacket proposalOfDeath = new QuorumPacket();
-   
+
+    private LearnerType  learnerType = LearnerType.PARTICIPANT;
+    public LearnerType getLearnerType() {
+        return learnerType;
+    }
+
     /**
      * This method will use the thread to send packets added to the
      * queuedPackets list
@@ -217,9 +223,9 @@
 
             QuorumPacket qp = new QuorumPacket();
             ia.readRecord(qp, "packet");
-            if(qp.getType() != Leader.FOLLOWERINFO) {
+            if(qp.getType() != Leader.FOLLOWERINFO && qp.getType() != Leader.OBSERVERINFO){
             	LOG.error("First packet " + qp.toString()
-                        + " is not FOLLOWERINFO!");
+                        + " is not FOLLOWERINFO or OBSERVERINFO!");
                 return;
             }
             if (qp.getData() != null) {
@@ -231,9 +237,11 @@
 
             LOG.info("Follower sid: " + this.sid + " : info : "
                     + leader.self.quorumPeers.get(this.sid));
+                        
+            if (qp.getType() == Leader.OBSERVERINFO) {
+                  learnerType = LearnerType.OBSERVER;
+            }            
             
-            /* this is the last zxid from the follower but the leader might have to
-              restart the follower from a different zxid depending on truncate and diff. */
             long peerLastZxid = qp.getZxid();
             /* the default to send to the follower */
             int packetToSend = Leader.SNAP;
@@ -356,6 +364,9 @@
 
                 switch (qp.getType()) {
                 case Leader.ACK:
+                    if (this.learnerType == LearnerType.OBSERVER) {
+                        LOG.error("Received ACK from Observer  " + this.sid);
+                    }
                     leader.processAck(this.sid, qp.getZxid(), sock.getLocalSocketAddress());
                     break;
                 case Leader.PING:

Added: hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/Observer.java
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/Observer.java?rev=881882&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/Observer.java (added)
+++ hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/Observer.java Wed Nov 18 19:06:39 2009
@@ -0,0 +1,147 @@
+/**
+ * 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
+ * to you 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.
+ */
+
+package org.apache.zookeeper.server.quorum;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+
+import org.apache.jute.BinaryInputArchive;
+import org.apache.jute.Record;
+import org.apache.zookeeper.server.ObserverBean;
+import org.apache.zookeeper.server.Request;
+import org.apache.zookeeper.server.util.SerializeUtils;
+import org.apache.zookeeper.txn.TxnHeader;
+
+/**
+ * Observers are peers that do not take part in the atomic broadcast protocol.
+ * Instead, they are informed of successful proposals by the Leader. Observers
+ * therefore naturally act as a relay point for publishing the proposal stream
+ * and can relieve Followers of some of the connection load. Observers may
+ * submit proposals, but do not vote in their acceptance. 
+ *
+ * See ZOOKEEPER-368 for a discussion of this feature. 
+ */
+public class Observer extends Learner{      
+
+    Observer(QuorumPeer self,ObserverZooKeeperServer observerZooKeeperServer) {
+        this.self = self;
+        this.zk=observerZooKeeperServer;
+    }
+
+    @Override
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+        sb.append("Observer ").append(sock);        
+        sb.append(" pendingRevalidationCount:")
+            .append(pendingRevalidations.size());
+        return sb.toString();
+    }
+    
+    /**
+     * the main method called by the observer to observe the leader
+     *
+     * @throws InterruptedException
+     */
+    void observeLeader() throws InterruptedException {
+        zk.registerJMX(new ObserverBean(this, zk), self.jmxLocalPeerBean);
+
+        try {
+            InetSocketAddress addr = findLeader();
+            LOG.info("Observing " + addr);
+            try {
+                connectToLeader(addr);
+                long newLeaderZxid = registerWithLeader(Leader.OBSERVERINFO);
+                
+                syncWithLeader(newLeaderZxid);
+                QuorumPacket qp = new QuorumPacket();
+                while (self.running) {
+                    readPacket(qp);
+                    processPacket(qp);                   
+                }
+            } catch (IOException e) {
+                LOG.warn("Exception when observing the leader", e);
+                try {
+                    sock.close();
+                } catch (IOException e1) {
+                    e1.printStackTrace();
+                }
+    
+                synchronized (pendingRevalidations) {
+                    // clear pending revalidations
+                    pendingRevalidations.clear();
+                    pendingRevalidations.notifyAll();
+                }
+            }
+        } finally {
+            zk.unregisterJMX(this);
+        }
+    }
+    
+    /**
+     * Controls the response of an observer to the receipt of a quorumpacket
+     * @param qp
+     * @throws IOException
+     */
+    protected void processPacket(QuorumPacket qp) throws IOException{
+        switch (qp.getType()) {
+        case Leader.PING:
+            ping(qp);
+            break;
+        case Leader.PROPOSAL:
+            LOG.warn("Ignoring proposal");
+            break;
+        case Leader.COMMIT:
+            LOG.warn("Ignoring commit");            
+            break;            
+        case Leader.UPTODATE:
+            zk.takeSnapshot();
+            self.cnxnFactory.setZooKeeperServer(zk);
+            break;
+        case Leader.REVALIDATE:
+            revalidate(qp);
+            break;
+        case Leader.SYNC:
+            ((ObserverZooKeeperServer)zk).sync();
+            break;
+        case Leader.INFORM:            
+            TxnHeader hdr = new TxnHeader();
+            BinaryInputArchive ia = BinaryInputArchive
+                    .getArchive(new ByteArrayInputStream(qp.getData()));
+            Record txn = SerializeUtils.deserializeTxn(ia, hdr);
+            Request request = new Request (null, hdr.getClientId(), 
+                                           hdr.getCxid(),
+                                           hdr.getType(), null, null);
+            request.txn = txn;
+            request.hdr = hdr;
+            ObserverZooKeeperServer obs = (ObserverZooKeeperServer)zk;
+            obs.commitRequest(request);            
+            break;
+        }
+    }
+
+    /**
+     * Shutdown the Observer.
+     */
+    public void shutdown() {       
+        LOG.info("shutdown called", new Exception("shutdown Observer"));
+        super.shutdown();
+    }
+}
+

Added: hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/ObserverMXBean.java
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/ObserverMXBean.java?rev=881882&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/ObserverMXBean.java (added)
+++ hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/ObserverMXBean.java Wed Nov 18 19:06:39 2009
@@ -0,0 +1,37 @@
+/**
+ * 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
+ * to you 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.
+ */
+
+package org.apache.zookeeper.server.quorum;
+
+import org.apache.zookeeper.server.ZooKeeperServerMXBean;
+
+/**
+ * Observer MX Bean interface, implemented by ObserverBean
+ *
+ */
+public interface ObserverMXBean extends ZooKeeperServerMXBean {
+    /**
+     * @return count of pending revalidations
+     */
+    public int getPendingRevalidationCount();
+    
+    /**
+     * @return socket address
+     */
+    public String getQuorumAddress();
+}

Added: hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/ObserverRequestProcessor.java
URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/ObserverRequestProcessor.java?rev=881882&view=auto
==============================================================================
--- hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/ObserverRequestProcessor.java (added)
+++ hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/ObserverRequestProcessor.java Wed Nov 18 19:06:39 2009
@@ -0,0 +1,123 @@
+/**
+ * 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
+ * to you 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.
+ */
+
+package org.apache.zookeeper.server.quorum;
+
+import java.util.concurrent.LinkedBlockingQueue;
+
+import org.apache.log4j.Logger;
+
+import org.apache.zookeeper.ZooDefs.OpCode;
+import org.apache.zookeeper.server.RequestProcessor;
+import org.apache.zookeeper.server.Request;
+import org.apache.zookeeper.server.ZooTrace;
+
+/**
+ * This RequestProcessor forwards any requests that modify the state of the
+ * system to the Leader.
+ */
+public class ObserverRequestProcessor extends Thread implements
+        RequestProcessor {
+    private static final Logger LOG = Logger.getLogger(ObserverRequestProcessor.class);
+
+    ObserverZooKeeperServer zks;
+
+    RequestProcessor nextProcessor;
+
+    // We keep a queue of requests. As requests get submitted they are 
+    // stored here. The queue is drained in the run() method. 
+    LinkedBlockingQueue<Request> queuedRequests = new LinkedBlockingQueue<Request>();
+
+    boolean finished = false;
+
+    /**
+     * Constructor - takes an ObserverZooKeeperServer to associate with
+     * and the next processor to pass requests to after we're finished. 
+     * @param zks
+     * @param nextProcessor
+     */
+    public ObserverRequestProcessor(ObserverZooKeeperServer zks,
+            RequestProcessor nextProcessor) {
+        super("ObserverRequestProcessor:" + zks.getServerId());
+        this.zks = zks;
+        this.nextProcessor = nextProcessor;
+    }
+
+    @Override
+    public void run() {
+        try {
+            while (!finished) {
+                Request request = queuedRequests.take();
+                if (LOG.isTraceEnabled()) {
+                    ZooTrace.logRequest(LOG, ZooTrace.CLIENT_REQUEST_TRACE_MASK,
+                            'F', request, "");
+                }
+                if (request == Request.requestOfDeath) {
+                    break;
+                }
+                // We want to queue the request to be processed before we submit
+                // the request to the leader so that we are ready to receive
+                // the response
+                nextProcessor.processRequest(request);
+                
+                // We now ship the request to the leader. As with all
+                // other quorum operations, sync also follows this code
+                // path, but different from others, we need to keep track
+                // of the sync operations this Observer has pending, so we
+                // add it to pendingSyncs.
+                switch (request.type) {
+                case OpCode.sync:
+                    zks.pendingSyncs.add(request);
+                    zks.getObserver().request(request);
+                    break;
+                case OpCode.create:
+                case OpCode.delete:
+                case OpCode.setData:
+                case OpCode.setACL:
+                case OpCode.createSession:
+                case OpCode.closeSession:
+                    zks.getObserver().request(request);
+                    break;
+                }
+            }
+        } catch (Exception e) {
+            LOG.error("Unexpected exception causing exit", e);
+        }
+        LOG.info("ObserverRequestProcessor exited loop!");
+    }
+
+    /**
+     * Simply queue the request, which will be processed in FIFO order. 
+     */
+    public void processRequest(Request request) {
+        if (!finished) {
+            queuedRequests.add(request);
+        }
+    }
+
+    /**
+     * Shutdown the processor.
+     */
+    public void shutdown() {
+        finished = true;
+        queuedRequests.clear();
+        queuedRequests.add(Request.requestOfDeath);
+        nextProcessor.shutdown();
+    }
+
+}



Mime
View raw message