zookeeper-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From an...@apache.org
Subject [10/10] zookeeper git commit: ZOOKEEPER-3033: MAVEN MIGRATION - fix directory structure
Date Fri, 17 Aug 2018 09:56:26 GMT
ZOOKEEPER-3033: MAVEN MIGRATION - fix directory structure

I reopened step 1.2 to fix the directory structure of the recipes, as it is better to do every directory change at once. (As it has been done in step 1.3 already - first step, docs is irrelevant in this manner).

Author: Norbert Kalmar <nkalmar@yahoo.com>

Reviewers: andor@apache.org

Closes #599 from nkalmar/ZOOKEEPER-3033_fix


Project: http://git-wip-us.apache.org/repos/asf/zookeeper/repo
Commit: http://git-wip-us.apache.org/repos/asf/zookeeper/commit/2584625c
Tree: http://git-wip-us.apache.org/repos/asf/zookeeper/tree/2584625c
Diff: http://git-wip-us.apache.org/repos/asf/zookeeper/diff/2584625c

Branch: refs/heads/master
Commit: 2584625cdf4bb917192479f637222d6e64518336
Parents: b5d6786
Author: Norbert Kalmar <nkalmar@yahoo.com>
Authored: Fri Aug 17 11:56:09 2018 +0200
Committer: Andor Molnar <andor@apache.org>
Committed: Fri Aug 17 11:56:09 2018 +0200

----------------------------------------------------------------------
 zookeeper-recipes/build-recipes.xml             |    2 +-
 .../zookeeper-recipes-election/README.txt       |    2 +-
 .../zookeeper-recipes-election/build.xml        |   16 +-
 .../recipes/leader/LeaderElectionAware.java     |   37 -
 .../recipes/leader/LeaderElectionSupport.java   |  461 -------
 .../zookeeper/recipes/leader/LeaderOffer.java   |   84 --
 .../recipes/leader/LeaderElectionAware.java     |   37 +
 .../recipes/leader/LeaderElectionSupport.java   |  461 +++++++
 .../zookeeper/recipes/leader/LeaderOffer.java   |   84 ++
 .../leader/LeaderElectionSupportTest.java       |  298 +++++
 .../leader/LeaderElectionSupportTest.java       |  298 -----
 .../zookeeper-recipes-lock/README.txt           |    4 +-
 .../zookeeper-recipes-lock/build.xml            |   18 +-
 .../zookeeper-recipes-lock/src/c/INSTALL        |  234 ----
 .../zookeeper-recipes-lock/src/c/LICENSE        |  202 ---
 .../zookeeper-recipes-lock/src/c/Makefile.am    |   46 -
 .../zookeeper-recipes-lock/src/c/README.txt     |   28 -
 .../zookeeper-recipes-lock/src/c/acinclude.m4   |  312 -----
 .../zookeeper-recipes-lock/src/c/aminclude.am   |  186 ---
 .../zookeeper-recipes-lock/src/c/c-doc.Doxyfile | 1252 ------------------
 .../zookeeper-recipes-lock/src/c/configure.ac   |   82 --
 .../src/c/include/zoo_lock.h                    |  168 ---
 .../zookeeper-recipes-lock/src/c/src/zoo_lock.c |  396 ------
 .../src/c/tests/TestClient.cc                   |  201 ---
 .../src/c/tests/TestDriver.cc                   |  114 --
 .../zookeeper-recipes-lock/src/c/tests/Util.cc  |   30 -
 .../zookeeper-recipes-lock/src/c/tests/Util.h   |  134 --
 .../src/c/tests/zkServer.sh                     |   75 --
 .../zookeeper/recipes/lock/LockListener.java    |   38 -
 .../zookeeper/recipes/lock/ProtocolSupport.java |  193 ---
 .../zookeeper/recipes/lock/WriteLock.java       |  296 -----
 .../zookeeper/recipes/lock/ZNodeName.java       |  112 --
 .../recipes/lock/ZooKeeperOperation.java        |   38 -
 .../zookeeper-recipes-lock/src/main/c/INSTALL   |  234 ++++
 .../zookeeper-recipes-lock/src/main/c/LICENSE   |  202 +++
 .../src/main/c/Makefile.am                      |   46 +
 .../src/main/c/README.txt                       |   28 +
 .../src/main/c/acinclude.m4                     |  312 +++++
 .../src/main/c/aminclude.am                     |  186 +++
 .../src/main/c/c-doc.Doxyfile                   | 1252 ++++++++++++++++++
 .../src/main/c/configure.ac                     |   82 ++
 .../src/main/c/include/zoo_lock.h               |  168 +++
 .../src/main/c/src/zoo_lock.c                   |  396 ++++++
 .../src/main/c/tests/TestClient.cc              |  201 +++
 .../src/main/c/tests/TestDriver.cc              |  114 ++
 .../src/main/c/tests/Util.cc                    |   30 +
 .../src/main/c/tests/Util.h                     |  134 ++
 .../src/main/c/tests/zkServer.sh                |   75 ++
 .../zookeeper/recipes/lock/LockListener.java    |   38 +
 .../zookeeper/recipes/lock/ProtocolSupport.java |  193 +++
 .../zookeeper/recipes/lock/WriteLock.java       |  296 +++++
 .../zookeeper/recipes/lock/ZNodeName.java       |  112 ++
 .../recipes/lock/ZooKeeperOperation.java        |   38 +
 .../zookeeper/recipes/lock/WriteLockTest.java   |  156 +++
 .../zookeeper/recipes/lock/ZNodeNameTest.java   |   71 +
 .../zookeeper/recipes/lock/WriteLockTest.java   |  156 ---
 .../zookeeper/recipes/lock/ZNodeNameTest.java   |   71 -
 .../zookeeper-recipes-queue/build.xml           |   18 +-
 .../zookeeper-recipes-queue/src/c/INSTALL       |  234 ----
 .../zookeeper-recipes-queue/src/c/LICENSE       |  202 ---
 .../zookeeper-recipes-queue/src/c/Makefile.am   |   46 -
 .../zookeeper-recipes-queue/src/c/README.txt    |   30 -
 .../zookeeper-recipes-queue/src/c/acinclude.m4  |  312 -----
 .../zookeeper-recipes-queue/src/c/aminclude.am  |  186 ---
 .../src/c/c-doc.Doxyfile                        | 1252 ------------------
 .../zookeeper-recipes-queue/src/c/configure.ac  |   82 --
 .../src/c/include/zoo_queue.h                   |  118 --
 .../src/c/src/zoo_queue.c                       |  442 -------
 .../src/c/tests/TestClient.cc                   |  452 -------
 .../src/c/tests/TestDriver.cc                   |  114 --
 .../zookeeper-recipes-queue/src/c/tests/Util.cc |   30 -
 .../zookeeper-recipes-queue/src/c/tests/Util.h  |  134 --
 .../src/c/tests/zkServer.sh                     |   75 --
 .../recipes/queue/DistributedQueue.java         |  314 -----
 .../zookeeper-recipes-queue/src/main/c/INSTALL  |  234 ++++
 .../zookeeper-recipes-queue/src/main/c/LICENSE  |  202 +++
 .../src/main/c/Makefile.am                      |   46 +
 .../src/main/c/README.txt                       |   30 +
 .../src/main/c/acinclude.m4                     |  312 +++++
 .../src/main/c/aminclude.am                     |  186 +++
 .../src/main/c/c-doc.Doxyfile                   | 1252 ++++++++++++++++++
 .../src/main/c/configure.ac                     |   82 ++
 .../src/main/c/include/zoo_queue.h              |  118 ++
 .../src/main/c/src/zoo_queue.c                  |  442 +++++++
 .../src/main/c/tests/TestClient.cc              |  452 +++++++
 .../src/main/c/tests/TestDriver.cc              |  114 ++
 .../src/main/c/tests/Util.cc                    |   30 +
 .../src/main/c/tests/Util.h                     |  134 ++
 .../src/main/c/tests/zkServer.sh                |   75 ++
 .../recipes/queue/DistributedQueue.java         |  314 +++++
 .../recipes/queue/DistributedQueueTest.java     |  286 ++++
 .../recipes/queue/DistributedQueueTest.java     |  286 ----
 92 files changed, 9587 insertions(+), 9579 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/zookeeper/blob/2584625c/zookeeper-recipes/build-recipes.xml
----------------------------------------------------------------------
diff --git a/zookeeper-recipes/build-recipes.xml b/zookeeper-recipes/build-recipes.xml
index b8457eb..29bc8ad 100644
--- a/zookeeper-recipes/build-recipes.xml
+++ b/zookeeper-recipes/build-recipes.xml
@@ -26,7 +26,7 @@
 
   <property name="zk.root" location="${root}/../../"/>
 
-  <property name="src.dir"  location="${root}/src/java"/>
+  <property name="src.dir"  location="${root}/src/main/java"/>
   <property name="src.test" location="${root}/src/test"/>
 
   <property name="build.dir" location="${zk.root}/build/recipes/${name}"/>

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/2584625c/zookeeper-recipes/zookeeper-recipes-election/README.txt
----------------------------------------------------------------------
diff --git a/zookeeper-recipes/zookeeper-recipes-election/README.txt b/zookeeper-recipes/zookeeper-recipes-election/README.txt
index 10447ed..f854b27 100644
--- a/zookeeper-recipes/zookeeper-recipes-election/README.txt
+++ b/zookeeper-recipes/zookeeper-recipes-election/README.txt
@@ -16,7 +16,7 @@
 -->
 
 1) This election interface recipe implements the leader election recipe
-mentioned in ../../../docs/recipes.[html,pdf].
+mentioned in ../../docs/recipes.[html,pdf].
 
 2) To compile the leader election java recipe you can just run ant jar from
 this directory.

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/2584625c/zookeeper-recipes/zookeeper-recipes-election/build.xml
----------------------------------------------------------------------
diff --git a/zookeeper-recipes/zookeeper-recipes-election/build.xml b/zookeeper-recipes/zookeeper-recipes-election/build.xml
index 8e1d00a..6f091a5 100644
--- a/zookeeper-recipes/zookeeper-recipes-election/build.xml
+++ b/zookeeper-recipes/zookeeper-recipes-election/build.xml
@@ -19,7 +19,7 @@
   <import file="../build-recipes.xml"/>
     <property name="test.main.classes" value="${zk.root}/build/test/classes"/>
     <property name="test.build.dir" value="${build.test}" />
-    <property name="test.src.dir" value="test"/>
+    <property name="test.src.dir" value="src/test/java"/>
     <property name="test.log.dir" value="${test.build.dir}/logs" />
     <property name="test.data.dir" value="${test.build.dir}/data" />
     <property name="test.data.upgrade.dir" value="${test.data.dir}/upgrade" />
@@ -52,7 +52,7 @@
 
 	<target name="compile-test" depends="compile">
   		<property name="target.jdk" value="${ant.java.version}" />	
-		<property name="src.test.local" location="${basedir}/test" />
+		<property name="src.test.local" location="${basedir}/src/test/java" />
 		<mkdir dir="${build.test}"/>
 		<javac srcdir="${src.test.local}" 
 			destdir="${build.test}" 
@@ -114,13 +114,13 @@
 
     <copy file="${basedir}/build.xml" todir="${dist.dir}/recipes/${name}"/>
 
-    <mkdir dir="${dist.dir}/recipes/${name}/test"/>
-    <copy todir="${dist.dir}/recipes/${name}/test">
-      <fileset dir="${basedir}/test"/>
+    <mkdir dir="${dist.dir}/recipes/${name}/src/test/java"/>
+    <copy todir="${dist.dir}/recipes/${name}/src/test/java">
+      <fileset dir="${basedir}/src/test/java"/>
     </copy>
-    <mkdir dir="${dist.dir}/recipes/${name}/src"/>
-    <copy todir="${dist.dir}/recipes/${name}/src">
-      <fileset dir="${basedir}/src"/>
+    <mkdir dir="${dist.dir}/recipes/${name}/src/main/java"/>
+    <copy todir="${dist.dir}/recipes/${name}/src/main/java">
+      <fileset dir="${basedir}/src/main/java"/>
     </copy>
   </target>
 

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/2584625c/zookeeper-recipes/zookeeper-recipes-election/src/java/org/apache/zookeeper/recipes/leader/LeaderElectionAware.java
----------------------------------------------------------------------
diff --git a/zookeeper-recipes/zookeeper-recipes-election/src/java/org/apache/zookeeper/recipes/leader/LeaderElectionAware.java b/zookeeper-recipes/zookeeper-recipes-election/src/java/org/apache/zookeeper/recipes/leader/LeaderElectionAware.java
deleted file mode 100644
index 6c32ebc..0000000
--- a/zookeeper-recipes/zookeeper-recipes-election/src/java/org/apache/zookeeper/recipes/leader/LeaderElectionAware.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.recipes.leader;
-
-import org.apache.zookeeper.recipes.leader.LeaderElectionSupport.EventType;
-
-/**
- * An interface to be implemented by clients that want to receive election
- * events.
- */
-public interface LeaderElectionAware {
-
-  /**
-   * Called during each state transition. Current, low level events are provided
-   * at the beginning and end of each state. For instance, START may be followed
-   * by OFFER_START, OFFER_COMPLETE, DETERMINE_START, DETERMINE_COMPLETE, and so
-   * on.
-   * 
-   * @param eventType
-   */
-  public void onElectionEvent(EventType eventType);
-
-}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/2584625c/zookeeper-recipes/zookeeper-recipes-election/src/java/org/apache/zookeeper/recipes/leader/LeaderElectionSupport.java
----------------------------------------------------------------------
diff --git a/zookeeper-recipes/zookeeper-recipes-election/src/java/org/apache/zookeeper/recipes/leader/LeaderElectionSupport.java b/zookeeper-recipes/zookeeper-recipes-election/src/java/org/apache/zookeeper/recipes/leader/LeaderElectionSupport.java
deleted file mode 100644
index 8d4096d..0000000
--- a/zookeeper-recipes/zookeeper-recipes-election/src/java/org/apache/zookeeper/recipes/leader/LeaderElectionSupport.java
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- * 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.recipes.leader;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.zookeeper.CreateMode;
-import org.apache.zookeeper.KeeperException;
-import org.apache.zookeeper.WatchedEvent;
-import org.apache.zookeeper.Watcher;
-import org.apache.zookeeper.ZooDefs;
-import org.apache.zookeeper.ZooKeeper;
-import org.apache.zookeeper.data.Stat;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * <p>
- * A leader election support library implementing the ZooKeeper election recipe.
- * </p>
- * <p>
- * This support library is meant to simplify the construction of an exclusive
- * leader system on top of Apache ZooKeeper. Any application that can become the
- * leader (usually a process that provides a service, exclusively) would
- * configure an instance of this class with their hostname, at least one
- * listener (an implementation of {@link LeaderElectionAware}), and either an
- * instance of {@link ZooKeeper} or the proper connection information. Once
- * configured, invoking {@link #start()} will cause the client to connect to
- * ZooKeeper and create a leader offer. The library then determines if it has
- * been elected the leader using the algorithm described below. The client
- * application can follow all state transitions via the listener callback.
- * </p>
- * <p>
- * Leader election algorithm
- * </p>
- * <p>
- * The library starts in a START state. Through each state transition, a state
- * start and a state complete event are sent to all listeners. When
- * {@link #start()} is called, a leader offer is created in ZooKeeper. A leader
- * offer is an ephemeral sequential node that indicates a process that can act
- * as a leader for this service. A read of all leader offers is then performed.
- * The offer with the lowest sequence number is said to be the leader. The
- * process elected leader will transition to the leader state. All other
- * processes will transition to a ready state. Internally, the library creates a
- * ZooKeeper watch on the leader offer with the sequence ID of N - 1 (where N is
- * the process's sequence ID). If that offer disappears due to a process
- * failure, the watching process will run through the election determination
- * process again to see if it should become the leader. Note that sequence ID
- * may not be contiguous due to failed processes. A process may revoke its offer
- * to be the leader at any time by calling {@link #stop()}.
- * </p>
- * <p>
- * Guarantees (not) Made and Caveats
- * </p>
- * <p>
- * <ul>
- * <li>It is possible for a (poorly implemented) process to create a leader
- * offer, get the lowest sequence ID, but have something terrible occur where it
- * maintains its connection to ZK (and thus its ephemeral leader offer node) but
- * doesn't actually provide the service in question. It is up to the user to
- * ensure any failure to become the leader - and whatever that means in the
- * context of the user's application - results in a revocation of its leader
- * offer (i.e. that {@link #stop()} is called).</li>
- * <li>It is possible for ZK timeouts and retries to play a role in service
- * liveliness. In other words, if process A has the lowest sequence ID but
- * requires a few attempts to read the other leader offers' sequence IDs,
- * election can seem slow. Users should apply timeouts during the determination
- * process if they need to hit a specific SLA.</li>
- * <li>The library makes a "best effort" to detect catastrophic failures of the
- * process. It is possible that an unforeseen event results in (for instance) an
- * unchecked exception that propagates passed normal error handling code. This
- * normally doesn't matter as the same exception would almost certain destroy
- * the entire process and thus the connection to ZK and the leader offer
- * resulting in another round of leader determination.</li>
- * </ul>
- * </p>
- */
-public class LeaderElectionSupport implements Watcher {
-
-  private static final Logger logger = LoggerFactory
-      .getLogger(LeaderElectionSupport.class);
-
-  private ZooKeeper zooKeeper;
-
-  private State state;
-  private Set<LeaderElectionAware> listeners;
-
-  private String rootNodeName;
-  private LeaderOffer leaderOffer;
-  private String hostName;
-
-  public LeaderElectionSupport() {
-    state = State.STOP;
-    listeners = Collections.synchronizedSet(new HashSet<LeaderElectionAware>());
-  }
-
-  /**
-   * <p>
-   * Start the election process. This method will create a leader offer,
-   * determine its status, and either become the leader or become ready. If an
-   * instance of {@link ZooKeeper} has not yet been configured by the user, a
-   * new instance is created using the connectString and sessionTime specified.
-   * </p>
-   * <p>
-   * Any (anticipated) failures result in a failed event being sent to all
-   * listeners.
-   * </p>
-   */
-  public synchronized void start() {
-    state = State.START;
-    dispatchEvent(EventType.START);
-
-    logger.info("Starting leader election support");
-
-    if (zooKeeper == null) {
-      throw new IllegalStateException(
-          "No instance of zookeeper provided. Hint: use setZooKeeper()");
-    }
-
-    if (hostName == null) {
-      throw new IllegalStateException(
-          "No hostname provided. Hint: use setHostName()");
-    }
-
-    try {
-      makeOffer();
-      determineElectionStatus();
-    } catch (KeeperException e) {
-      becomeFailed(e);
-      return;
-    } catch (InterruptedException e) {
-      becomeFailed(e);
-      return;
-    }
-  }
-
-  /**
-   * Stops all election services, revokes any outstanding leader offers, and
-   * disconnects from ZooKeeper.
-   */
-  public synchronized void stop() {
-    state = State.STOP;
-    dispatchEvent(EventType.STOP_START);
-
-    logger.info("Stopping leader election support");
-
-    if (leaderOffer != null) {
-      try {
-        zooKeeper.delete(leaderOffer.getNodePath(), -1);
-        logger.info("Removed leader offer {}", leaderOffer.getNodePath());
-      } catch (InterruptedException e) {
-        becomeFailed(e);
-      } catch (KeeperException e) {
-        becomeFailed(e);
-      }
-    }
-
-    dispatchEvent(EventType.STOP_COMPLETE);
-  }
-
-  private void makeOffer() throws KeeperException, InterruptedException {
-    state = State.OFFER;
-    dispatchEvent(EventType.OFFER_START);
-
-    leaderOffer = new LeaderOffer();
-
-    leaderOffer.setHostName(hostName);
-    leaderOffer.setNodePath(zooKeeper.create(rootNodeName + "/" + "n_",
-        hostName.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,
-        CreateMode.EPHEMERAL_SEQUENTIAL));
-
-    logger.debug("Created leader offer {}", leaderOffer);
-
-    dispatchEvent(EventType.OFFER_COMPLETE);
-  }
-
-  private void determineElectionStatus() throws KeeperException,
-      InterruptedException {
-
-    state = State.DETERMINE;
-    dispatchEvent(EventType.DETERMINE_START);
-
-    String[] components = leaderOffer.getNodePath().split("/");
-
-    leaderOffer.setId(Integer.valueOf(components[components.length - 1]
-        .substring("n_".length())));
-
-    List<LeaderOffer> leaderOffers = toLeaderOffers(zooKeeper.getChildren(
-        rootNodeName, false));
-
-    /*
-     * For each leader offer, find out where we fit in. If we're first, we
-     * become the leader. If we're not elected the leader, attempt to stat the
-     * offer just less than us. If they exist, watch for their failure, but if
-     * they don't, become the leader.
-     */
-    for (int i = 0; i < leaderOffers.size(); i++) {
-      LeaderOffer leaderOffer = leaderOffers.get(i);
-
-      if (leaderOffer.getId().equals(this.leaderOffer.getId())) {
-        logger.debug("There are {} leader offers. I am {} in line.",
-            leaderOffers.size(), i);
-
-        dispatchEvent(EventType.DETERMINE_COMPLETE);
-
-        if (i == 0) {
-          becomeLeader();
-        } else {
-          becomeReady(leaderOffers.get(i - 1));
-        }
-
-        /* Once we've figured out where we are, we're done. */
-        break;
-      }
-    }
-  }
-
-  private void becomeReady(LeaderOffer neighborLeaderOffer)
-      throws KeeperException, InterruptedException {
-
-    logger.info("{} not elected leader. Watching node:{}",
-        leaderOffer.getNodePath(), neighborLeaderOffer.getNodePath());
-
-    /*
-     * Make sure to pass an explicit Watcher because we could be sharing this
-     * zooKeeper instance with someone else.
-     */
-    Stat stat = zooKeeper.exists(neighborLeaderOffer.getNodePath(), this);
-
-    if (stat != null) {
-      dispatchEvent(EventType.READY_START);
-      logger.debug(
-          "We're behind {} in line and they're alive. Keeping an eye on them.",
-          neighborLeaderOffer.getNodePath());
-      state = State.READY;
-      dispatchEvent(EventType.READY_COMPLETE);
-    } else {
-      /*
-       * If the stat fails, the node has gone missing between the call to
-       * getChildren() and exists(). We need to try and become the leader.
-       */
-      logger
-          .info(
-              "We were behind {} but it looks like they died. Back to determination.",
-              neighborLeaderOffer.getNodePath());
-      determineElectionStatus();
-    }
-
-  }
-
-  private void becomeLeader() {
-    state = State.ELECTED;
-    dispatchEvent(EventType.ELECTED_START);
-
-    logger.info("Becoming leader with node:{}", leaderOffer.getNodePath());
-
-    dispatchEvent(EventType.ELECTED_COMPLETE);
-  }
-
-  private void becomeFailed(Exception e) {
-    logger.error("Failed in state {} - Exception:{}", state, e);
-
-    state = State.FAILED;
-    dispatchEvent(EventType.FAILED);
-  }
-
-  /**
-   * Fetch the (user supplied) hostname of the current leader. Note that by the
-   * time this method returns, state could have changed so do not depend on this
-   * to be strongly consistent. This method has to read all leader offers from
-   * ZooKeeper to deterime who the leader is (i.e. there is no caching) so
-   * consider the performance implications of frequent invocation. If there are
-   * no leader offers this method returns null.
-   * 
-   * @return hostname of the current leader
-   * @throws KeeperException
-   * @throws InterruptedException
-   */
-  public String getLeaderHostName() throws KeeperException,
-      InterruptedException {
-
-    List<LeaderOffer> leaderOffers = toLeaderOffers(zooKeeper.getChildren(
-        rootNodeName, false));
-
-    if (leaderOffers.size() > 0) {
-      return leaderOffers.get(0).getHostName();
-    }
-
-    return null;
-  }
-
-  private List<LeaderOffer> toLeaderOffers(List<String> strings)
-      throws KeeperException, InterruptedException {
-
-    List<LeaderOffer> leaderOffers = new ArrayList<LeaderOffer>(strings.size());
-
-    /*
-     * Turn each child of rootNodeName into a leader offer. This is a tuple of
-     * the sequence number and the node name.
-     */
-    for (String offer : strings) {
-      String hostName = new String(zooKeeper.getData(
-          rootNodeName + "/" + offer, false, null));
-
-      leaderOffers.add(new LeaderOffer(Integer.valueOf(offer.substring("n_"
-          .length())), rootNodeName + "/" + offer, hostName));
-    }
-
-    /*
-     * We sort leader offers by sequence number (which may not be zero-based or
-     * contiguous) and keep their paths handy for setting watches.
-     */
-    Collections.sort(leaderOffers, new LeaderOffer.IdComparator());
-
-    return leaderOffers;
-  }
-
-  @Override
-  public void process(WatchedEvent event) {
-    if (event.getType().equals(Watcher.Event.EventType.NodeDeleted)) {
-      if (!event.getPath().equals(leaderOffer.getNodePath())
-          && state != State.STOP) {
-        logger.debug(
-            "Node {} deleted. Need to run through the election process.",
-            event.getPath());
-        try {
-          determineElectionStatus();
-        } catch (KeeperException e) {
-          becomeFailed(e);
-        } catch (InterruptedException e) {
-          becomeFailed(e);
-        }
-      }
-    }
-  }
-
-  private void dispatchEvent(EventType eventType) {
-    logger.debug("Dispatching event:{}", eventType);
-
-    synchronized (listeners) {
-      if (listeners.size() > 0) {
-        for (LeaderElectionAware observer : listeners) {
-          observer.onElectionEvent(eventType);
-        }
-      }
-    }
-  }
-
-  /**
-   * Adds {@code listener} to the list of listeners who will receive events.
-   * 
-   * @param listener
-   */
-  public void addListener(LeaderElectionAware listener) {
-    listeners.add(listener);
-  }
-
-  /**
-   * Remove {@code listener} from the list of listeners who receive events.
-   * 
-   * @param listener
-   */
-  public void removeListener(LeaderElectionAware listener) {
-    listeners.remove(listener);
-  }
-
-  @Override
-  public String toString() {
-    return "{ state:" + state + " leaderOffer:" + leaderOffer + " zooKeeper:"
-        + zooKeeper + " hostName:" + hostName + " listeners:" + listeners
-        + " }";
-  }
-
-  /**
-   * <p>
-   * Gets the ZooKeeper root node to use for this service.
-   * </p>
-   * <p>
-   * For instance, a root node of {@code /mycompany/myservice} would be the
-   * parent of all leader offers for this service. Obviously all processes that
-   * wish to contend for leader status need to use the same root node. Note: We
-   * assume this node already exists.
-   * </p>
-   * 
-   * @return a znode path
-   */
-  public String getRootNodeName() {
-    return rootNodeName;
-  }
-
-  /**
-   * <p>
-   * Sets the ZooKeeper root node to use for this service.
-   * </p>
-   * <p>
-   * For instance, a root node of {@code /mycompany/myservice} would be the
-   * parent of all leader offers for this service. Obviously all processes that
-   * wish to contend for leader status need to use the same root node. Note: We
-   * assume this node already exists.
-   * </p>
-   */
-  public void setRootNodeName(String rootNodeName) {
-    this.rootNodeName = rootNodeName;
-  }
-
-  /**
-   * The {@link ZooKeeper} instance to use for all operations. Provided this
-   * overrides any connectString or sessionTimeout set.
-   */
-  public ZooKeeper getZooKeeper() {
-    return zooKeeper;
-  }
-
-  public void setZooKeeper(ZooKeeper zooKeeper) {
-    this.zooKeeper = zooKeeper;
-  }
-
-  /**
-   * The hostname of this process. Mostly used as a convenience for logging and
-   * to respond to {@link #getLeaderHostName()} requests.
-   */
-  public String getHostName() {
-    return hostName;
-  }
-
-  public void setHostName(String hostName) {
-    this.hostName = hostName;
-  }
-
-  /**
-   * The type of event.
-   */
-  public static enum EventType {
-    START, OFFER_START, OFFER_COMPLETE, DETERMINE_START, DETERMINE_COMPLETE, ELECTED_START, ELECTED_COMPLETE, READY_START, READY_COMPLETE, FAILED, STOP_START, STOP_COMPLETE,
-  }
-
-  /**
-   * The internal state of the election support service.
-   */
-  public static enum State {
-    START, OFFER, DETERMINE, ELECTED, READY, FAILED, STOP
-  }
-}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/2584625c/zookeeper-recipes/zookeeper-recipes-election/src/java/org/apache/zookeeper/recipes/leader/LeaderOffer.java
----------------------------------------------------------------------
diff --git a/zookeeper-recipes/zookeeper-recipes-election/src/java/org/apache/zookeeper/recipes/leader/LeaderOffer.java b/zookeeper-recipes/zookeeper-recipes-election/src/java/org/apache/zookeeper/recipes/leader/LeaderOffer.java
deleted file mode 100644
index 188a6d5..0000000
--- a/zookeeper-recipes/zookeeper-recipes-election/src/java/org/apache/zookeeper/recipes/leader/LeaderOffer.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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.recipes.leader;
-
-import java.util.Comparator;
-
-/**
- * A leader offer is a numeric id / path pair. The id is the sequential node id
- * assigned by ZooKeeper where as the path is the absolute path to the ZNode.
- */
-public class LeaderOffer {
-
-  private Integer id;
-  private String nodePath;
-  private String hostName;
-
-  public LeaderOffer() {
-    // Default constructor
-  }
-
-  public LeaderOffer(Integer id, String nodePath, String hostName) {
-    this.id = id;
-    this.nodePath = nodePath;
-    this.hostName = hostName;
-  }
-
-  @Override
-  public String toString() {
-    return "{ id:" + id + " nodePath:" + nodePath + " hostName:" + hostName
-        + " }";
-  }
-
-  public Integer getId() {
-    return id;
-  }
-
-  public void setId(Integer id) {
-    this.id = id;
-  }
-
-  public String getNodePath() {
-    return nodePath;
-  }
-
-  public void setNodePath(String nodePath) {
-    this.nodePath = nodePath;
-  }
-
-  public String getHostName() {
-    return hostName;
-  }
-
-  public void setHostName(String hostName) {
-    this.hostName = hostName;
-  }
-
-  /**
-   * Compare two instances of {@link LeaderOffer} using only the {code}id{code}
-   * member.
-   */
-  public static class IdComparator implements Comparator<LeaderOffer> {
-
-    @Override
-    public int compare(LeaderOffer o1, LeaderOffer o2) {
-      return o1.getId().compareTo(o2.getId());
-    }
-
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/2584625c/zookeeper-recipes/zookeeper-recipes-election/src/main/java/org/apache/zookeeper/recipes/leader/LeaderElectionAware.java
----------------------------------------------------------------------
diff --git a/zookeeper-recipes/zookeeper-recipes-election/src/main/java/org/apache/zookeeper/recipes/leader/LeaderElectionAware.java b/zookeeper-recipes/zookeeper-recipes-election/src/main/java/org/apache/zookeeper/recipes/leader/LeaderElectionAware.java
new file mode 100644
index 0000000..6c32ebc
--- /dev/null
+++ b/zookeeper-recipes/zookeeper-recipes-election/src/main/java/org/apache/zookeeper/recipes/leader/LeaderElectionAware.java
@@ -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.recipes.leader;
+
+import org.apache.zookeeper.recipes.leader.LeaderElectionSupport.EventType;
+
+/**
+ * An interface to be implemented by clients that want to receive election
+ * events.
+ */
+public interface LeaderElectionAware {
+
+  /**
+   * Called during each state transition. Current, low level events are provided
+   * at the beginning and end of each state. For instance, START may be followed
+   * by OFFER_START, OFFER_COMPLETE, DETERMINE_START, DETERMINE_COMPLETE, and so
+   * on.
+   * 
+   * @param eventType
+   */
+  public void onElectionEvent(EventType eventType);
+
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/2584625c/zookeeper-recipes/zookeeper-recipes-election/src/main/java/org/apache/zookeeper/recipes/leader/LeaderElectionSupport.java
----------------------------------------------------------------------
diff --git a/zookeeper-recipes/zookeeper-recipes-election/src/main/java/org/apache/zookeeper/recipes/leader/LeaderElectionSupport.java b/zookeeper-recipes/zookeeper-recipes-election/src/main/java/org/apache/zookeeper/recipes/leader/LeaderElectionSupport.java
new file mode 100644
index 0000000..8d4096d
--- /dev/null
+++ b/zookeeper-recipes/zookeeper-recipes-election/src/main/java/org/apache/zookeeper/recipes/leader/LeaderElectionSupport.java
@@ -0,0 +1,461 @@
+/*
+ * 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.recipes.leader;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.ZooDefs;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.data.Stat;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * <p>
+ * A leader election support library implementing the ZooKeeper election recipe.
+ * </p>
+ * <p>
+ * This support library is meant to simplify the construction of an exclusive
+ * leader system on top of Apache ZooKeeper. Any application that can become the
+ * leader (usually a process that provides a service, exclusively) would
+ * configure an instance of this class with their hostname, at least one
+ * listener (an implementation of {@link LeaderElectionAware}), and either an
+ * instance of {@link ZooKeeper} or the proper connection information. Once
+ * configured, invoking {@link #start()} will cause the client to connect to
+ * ZooKeeper and create a leader offer. The library then determines if it has
+ * been elected the leader using the algorithm described below. The client
+ * application can follow all state transitions via the listener callback.
+ * </p>
+ * <p>
+ * Leader election algorithm
+ * </p>
+ * <p>
+ * The library starts in a START state. Through each state transition, a state
+ * start and a state complete event are sent to all listeners. When
+ * {@link #start()} is called, a leader offer is created in ZooKeeper. A leader
+ * offer is an ephemeral sequential node that indicates a process that can act
+ * as a leader for this service. A read of all leader offers is then performed.
+ * The offer with the lowest sequence number is said to be the leader. The
+ * process elected leader will transition to the leader state. All other
+ * processes will transition to a ready state. Internally, the library creates a
+ * ZooKeeper watch on the leader offer with the sequence ID of N - 1 (where N is
+ * the process's sequence ID). If that offer disappears due to a process
+ * failure, the watching process will run through the election determination
+ * process again to see if it should become the leader. Note that sequence ID
+ * may not be contiguous due to failed processes. A process may revoke its offer
+ * to be the leader at any time by calling {@link #stop()}.
+ * </p>
+ * <p>
+ * Guarantees (not) Made and Caveats
+ * </p>
+ * <p>
+ * <ul>
+ * <li>It is possible for a (poorly implemented) process to create a leader
+ * offer, get the lowest sequence ID, but have something terrible occur where it
+ * maintains its connection to ZK (and thus its ephemeral leader offer node) but
+ * doesn't actually provide the service in question. It is up to the user to
+ * ensure any failure to become the leader - and whatever that means in the
+ * context of the user's application - results in a revocation of its leader
+ * offer (i.e. that {@link #stop()} is called).</li>
+ * <li>It is possible for ZK timeouts and retries to play a role in service
+ * liveliness. In other words, if process A has the lowest sequence ID but
+ * requires a few attempts to read the other leader offers' sequence IDs,
+ * election can seem slow. Users should apply timeouts during the determination
+ * process if they need to hit a specific SLA.</li>
+ * <li>The library makes a "best effort" to detect catastrophic failures of the
+ * process. It is possible that an unforeseen event results in (for instance) an
+ * unchecked exception that propagates passed normal error handling code. This
+ * normally doesn't matter as the same exception would almost certain destroy
+ * the entire process and thus the connection to ZK and the leader offer
+ * resulting in another round of leader determination.</li>
+ * </ul>
+ * </p>
+ */
+public class LeaderElectionSupport implements Watcher {
+
+  private static final Logger logger = LoggerFactory
+      .getLogger(LeaderElectionSupport.class);
+
+  private ZooKeeper zooKeeper;
+
+  private State state;
+  private Set<LeaderElectionAware> listeners;
+
+  private String rootNodeName;
+  private LeaderOffer leaderOffer;
+  private String hostName;
+
+  public LeaderElectionSupport() {
+    state = State.STOP;
+    listeners = Collections.synchronizedSet(new HashSet<LeaderElectionAware>());
+  }
+
+  /**
+   * <p>
+   * Start the election process. This method will create a leader offer,
+   * determine its status, and either become the leader or become ready. If an
+   * instance of {@link ZooKeeper} has not yet been configured by the user, a
+   * new instance is created using the connectString and sessionTime specified.
+   * </p>
+   * <p>
+   * Any (anticipated) failures result in a failed event being sent to all
+   * listeners.
+   * </p>
+   */
+  public synchronized void start() {
+    state = State.START;
+    dispatchEvent(EventType.START);
+
+    logger.info("Starting leader election support");
+
+    if (zooKeeper == null) {
+      throw new IllegalStateException(
+          "No instance of zookeeper provided. Hint: use setZooKeeper()");
+    }
+
+    if (hostName == null) {
+      throw new IllegalStateException(
+          "No hostname provided. Hint: use setHostName()");
+    }
+
+    try {
+      makeOffer();
+      determineElectionStatus();
+    } catch (KeeperException e) {
+      becomeFailed(e);
+      return;
+    } catch (InterruptedException e) {
+      becomeFailed(e);
+      return;
+    }
+  }
+
+  /**
+   * Stops all election services, revokes any outstanding leader offers, and
+   * disconnects from ZooKeeper.
+   */
+  public synchronized void stop() {
+    state = State.STOP;
+    dispatchEvent(EventType.STOP_START);
+
+    logger.info("Stopping leader election support");
+
+    if (leaderOffer != null) {
+      try {
+        zooKeeper.delete(leaderOffer.getNodePath(), -1);
+        logger.info("Removed leader offer {}", leaderOffer.getNodePath());
+      } catch (InterruptedException e) {
+        becomeFailed(e);
+      } catch (KeeperException e) {
+        becomeFailed(e);
+      }
+    }
+
+    dispatchEvent(EventType.STOP_COMPLETE);
+  }
+
+  private void makeOffer() throws KeeperException, InterruptedException {
+    state = State.OFFER;
+    dispatchEvent(EventType.OFFER_START);
+
+    leaderOffer = new LeaderOffer();
+
+    leaderOffer.setHostName(hostName);
+    leaderOffer.setNodePath(zooKeeper.create(rootNodeName + "/" + "n_",
+        hostName.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,
+        CreateMode.EPHEMERAL_SEQUENTIAL));
+
+    logger.debug("Created leader offer {}", leaderOffer);
+
+    dispatchEvent(EventType.OFFER_COMPLETE);
+  }
+
+  private void determineElectionStatus() throws KeeperException,
+      InterruptedException {
+
+    state = State.DETERMINE;
+    dispatchEvent(EventType.DETERMINE_START);
+
+    String[] components = leaderOffer.getNodePath().split("/");
+
+    leaderOffer.setId(Integer.valueOf(components[components.length - 1]
+        .substring("n_".length())));
+
+    List<LeaderOffer> leaderOffers = toLeaderOffers(zooKeeper.getChildren(
+        rootNodeName, false));
+
+    /*
+     * For each leader offer, find out where we fit in. If we're first, we
+     * become the leader. If we're not elected the leader, attempt to stat the
+     * offer just less than us. If they exist, watch for their failure, but if
+     * they don't, become the leader.
+     */
+    for (int i = 0; i < leaderOffers.size(); i++) {
+      LeaderOffer leaderOffer = leaderOffers.get(i);
+
+      if (leaderOffer.getId().equals(this.leaderOffer.getId())) {
+        logger.debug("There are {} leader offers. I am {} in line.",
+            leaderOffers.size(), i);
+
+        dispatchEvent(EventType.DETERMINE_COMPLETE);
+
+        if (i == 0) {
+          becomeLeader();
+        } else {
+          becomeReady(leaderOffers.get(i - 1));
+        }
+
+        /* Once we've figured out where we are, we're done. */
+        break;
+      }
+    }
+  }
+
+  private void becomeReady(LeaderOffer neighborLeaderOffer)
+      throws KeeperException, InterruptedException {
+
+    logger.info("{} not elected leader. Watching node:{}",
+        leaderOffer.getNodePath(), neighborLeaderOffer.getNodePath());
+
+    /*
+     * Make sure to pass an explicit Watcher because we could be sharing this
+     * zooKeeper instance with someone else.
+     */
+    Stat stat = zooKeeper.exists(neighborLeaderOffer.getNodePath(), this);
+
+    if (stat != null) {
+      dispatchEvent(EventType.READY_START);
+      logger.debug(
+          "We're behind {} in line and they're alive. Keeping an eye on them.",
+          neighborLeaderOffer.getNodePath());
+      state = State.READY;
+      dispatchEvent(EventType.READY_COMPLETE);
+    } else {
+      /*
+       * If the stat fails, the node has gone missing between the call to
+       * getChildren() and exists(). We need to try and become the leader.
+       */
+      logger
+          .info(
+              "We were behind {} but it looks like they died. Back to determination.",
+              neighborLeaderOffer.getNodePath());
+      determineElectionStatus();
+    }
+
+  }
+
+  private void becomeLeader() {
+    state = State.ELECTED;
+    dispatchEvent(EventType.ELECTED_START);
+
+    logger.info("Becoming leader with node:{}", leaderOffer.getNodePath());
+
+    dispatchEvent(EventType.ELECTED_COMPLETE);
+  }
+
+  private void becomeFailed(Exception e) {
+    logger.error("Failed in state {} - Exception:{}", state, e);
+
+    state = State.FAILED;
+    dispatchEvent(EventType.FAILED);
+  }
+
+  /**
+   * Fetch the (user supplied) hostname of the current leader. Note that by the
+   * time this method returns, state could have changed so do not depend on this
+   * to be strongly consistent. This method has to read all leader offers from
+   * ZooKeeper to deterime who the leader is (i.e. there is no caching) so
+   * consider the performance implications of frequent invocation. If there are
+   * no leader offers this method returns null.
+   * 
+   * @return hostname of the current leader
+   * @throws KeeperException
+   * @throws InterruptedException
+   */
+  public String getLeaderHostName() throws KeeperException,
+      InterruptedException {
+
+    List<LeaderOffer> leaderOffers = toLeaderOffers(zooKeeper.getChildren(
+        rootNodeName, false));
+
+    if (leaderOffers.size() > 0) {
+      return leaderOffers.get(0).getHostName();
+    }
+
+    return null;
+  }
+
+  private List<LeaderOffer> toLeaderOffers(List<String> strings)
+      throws KeeperException, InterruptedException {
+
+    List<LeaderOffer> leaderOffers = new ArrayList<LeaderOffer>(strings.size());
+
+    /*
+     * Turn each child of rootNodeName into a leader offer. This is a tuple of
+     * the sequence number and the node name.
+     */
+    for (String offer : strings) {
+      String hostName = new String(zooKeeper.getData(
+          rootNodeName + "/" + offer, false, null));
+
+      leaderOffers.add(new LeaderOffer(Integer.valueOf(offer.substring("n_"
+          .length())), rootNodeName + "/" + offer, hostName));
+    }
+
+    /*
+     * We sort leader offers by sequence number (which may not be zero-based or
+     * contiguous) and keep their paths handy for setting watches.
+     */
+    Collections.sort(leaderOffers, new LeaderOffer.IdComparator());
+
+    return leaderOffers;
+  }
+
+  @Override
+  public void process(WatchedEvent event) {
+    if (event.getType().equals(Watcher.Event.EventType.NodeDeleted)) {
+      if (!event.getPath().equals(leaderOffer.getNodePath())
+          && state != State.STOP) {
+        logger.debug(
+            "Node {} deleted. Need to run through the election process.",
+            event.getPath());
+        try {
+          determineElectionStatus();
+        } catch (KeeperException e) {
+          becomeFailed(e);
+        } catch (InterruptedException e) {
+          becomeFailed(e);
+        }
+      }
+    }
+  }
+
+  private void dispatchEvent(EventType eventType) {
+    logger.debug("Dispatching event:{}", eventType);
+
+    synchronized (listeners) {
+      if (listeners.size() > 0) {
+        for (LeaderElectionAware observer : listeners) {
+          observer.onElectionEvent(eventType);
+        }
+      }
+    }
+  }
+
+  /**
+   * Adds {@code listener} to the list of listeners who will receive events.
+   * 
+   * @param listener
+   */
+  public void addListener(LeaderElectionAware listener) {
+    listeners.add(listener);
+  }
+
+  /**
+   * Remove {@code listener} from the list of listeners who receive events.
+   * 
+   * @param listener
+   */
+  public void removeListener(LeaderElectionAware listener) {
+    listeners.remove(listener);
+  }
+
+  @Override
+  public String toString() {
+    return "{ state:" + state + " leaderOffer:" + leaderOffer + " zooKeeper:"
+        + zooKeeper + " hostName:" + hostName + " listeners:" + listeners
+        + " }";
+  }
+
+  /**
+   * <p>
+   * Gets the ZooKeeper root node to use for this service.
+   * </p>
+   * <p>
+   * For instance, a root node of {@code /mycompany/myservice} would be the
+   * parent of all leader offers for this service. Obviously all processes that
+   * wish to contend for leader status need to use the same root node. Note: We
+   * assume this node already exists.
+   * </p>
+   * 
+   * @return a znode path
+   */
+  public String getRootNodeName() {
+    return rootNodeName;
+  }
+
+  /**
+   * <p>
+   * Sets the ZooKeeper root node to use for this service.
+   * </p>
+   * <p>
+   * For instance, a root node of {@code /mycompany/myservice} would be the
+   * parent of all leader offers for this service. Obviously all processes that
+   * wish to contend for leader status need to use the same root node. Note: We
+   * assume this node already exists.
+   * </p>
+   */
+  public void setRootNodeName(String rootNodeName) {
+    this.rootNodeName = rootNodeName;
+  }
+
+  /**
+   * The {@link ZooKeeper} instance to use for all operations. Provided this
+   * overrides any connectString or sessionTimeout set.
+   */
+  public ZooKeeper getZooKeeper() {
+    return zooKeeper;
+  }
+
+  public void setZooKeeper(ZooKeeper zooKeeper) {
+    this.zooKeeper = zooKeeper;
+  }
+
+  /**
+   * The hostname of this process. Mostly used as a convenience for logging and
+   * to respond to {@link #getLeaderHostName()} requests.
+   */
+  public String getHostName() {
+    return hostName;
+  }
+
+  public void setHostName(String hostName) {
+    this.hostName = hostName;
+  }
+
+  /**
+   * The type of event.
+   */
+  public static enum EventType {
+    START, OFFER_START, OFFER_COMPLETE, DETERMINE_START, DETERMINE_COMPLETE, ELECTED_START, ELECTED_COMPLETE, READY_START, READY_COMPLETE, FAILED, STOP_START, STOP_COMPLETE,
+  }
+
+  /**
+   * The internal state of the election support service.
+   */
+  public static enum State {
+    START, OFFER, DETERMINE, ELECTED, READY, FAILED, STOP
+  }
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/2584625c/zookeeper-recipes/zookeeper-recipes-election/src/main/java/org/apache/zookeeper/recipes/leader/LeaderOffer.java
----------------------------------------------------------------------
diff --git a/zookeeper-recipes/zookeeper-recipes-election/src/main/java/org/apache/zookeeper/recipes/leader/LeaderOffer.java b/zookeeper-recipes/zookeeper-recipes-election/src/main/java/org/apache/zookeeper/recipes/leader/LeaderOffer.java
new file mode 100644
index 0000000..188a6d5
--- /dev/null
+++ b/zookeeper-recipes/zookeeper-recipes-election/src/main/java/org/apache/zookeeper/recipes/leader/LeaderOffer.java
@@ -0,0 +1,84 @@
+/*
+ * 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.recipes.leader;
+
+import java.util.Comparator;
+
+/**
+ * A leader offer is a numeric id / path pair. The id is the sequential node id
+ * assigned by ZooKeeper where as the path is the absolute path to the ZNode.
+ */
+public class LeaderOffer {
+
+  private Integer id;
+  private String nodePath;
+  private String hostName;
+
+  public LeaderOffer() {
+    // Default constructor
+  }
+
+  public LeaderOffer(Integer id, String nodePath, String hostName) {
+    this.id = id;
+    this.nodePath = nodePath;
+    this.hostName = hostName;
+  }
+
+  @Override
+  public String toString() {
+    return "{ id:" + id + " nodePath:" + nodePath + " hostName:" + hostName
+        + " }";
+  }
+
+  public Integer getId() {
+    return id;
+  }
+
+  public void setId(Integer id) {
+    this.id = id;
+  }
+
+  public String getNodePath() {
+    return nodePath;
+  }
+
+  public void setNodePath(String nodePath) {
+    this.nodePath = nodePath;
+  }
+
+  public String getHostName() {
+    return hostName;
+  }
+
+  public void setHostName(String hostName) {
+    this.hostName = hostName;
+  }
+
+  /**
+   * Compare two instances of {@link LeaderOffer} using only the {code}id{code}
+   * member.
+   */
+  public static class IdComparator implements Comparator<LeaderOffer> {
+
+    @Override
+    public int compare(LeaderOffer o1, LeaderOffer o2) {
+      return o1.getId().compareTo(o2.getId());
+    }
+
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/2584625c/zookeeper-recipes/zookeeper-recipes-election/src/test/java/org/apache/zookeeper/recipes/leader/LeaderElectionSupportTest.java
----------------------------------------------------------------------
diff --git a/zookeeper-recipes/zookeeper-recipes-election/src/test/java/org/apache/zookeeper/recipes/leader/LeaderElectionSupportTest.java b/zookeeper-recipes/zookeeper-recipes-election/src/test/java/org/apache/zookeeper/recipes/leader/LeaderElectionSupportTest.java
new file mode 100644
index 0000000..7e19dc7
--- /dev/null
+++ b/zookeeper-recipes/zookeeper-recipes-election/src/test/java/org/apache/zookeeper/recipes/leader/LeaderElectionSupportTest.java
@@ -0,0 +1,298 @@
+/*
+ * 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.recipes.leader;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.ZooDefs;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.recipes.leader.LeaderElectionSupport.EventType;
+import org.apache.zookeeper.test.ClientBase;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class LeaderElectionSupportTest extends ClientBase {
+
+  private static final Logger logger = LoggerFactory
+      .getLogger(LeaderElectionSupportTest.class);
+  private static final String testRootNode = "/" + System.currentTimeMillis()
+      + "_";
+
+  private ZooKeeper zooKeeper;
+
+  @Before
+  public void setUp() throws Exception {
+    super.setUp();
+
+    zooKeeper = createClient();
+
+    zooKeeper.create(testRootNode + Thread.currentThread().getId(),
+        new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    if (zooKeeper != null) {
+      zooKeeper.delete(testRootNode + Thread.currentThread().getId(), -1);
+    }
+
+    super.tearDown();
+  }
+
+  @Test
+  public void testNode() throws IOException, InterruptedException,
+      KeeperException {
+
+    LeaderElectionSupport electionSupport = createLeaderElectionSupport();
+
+    electionSupport.start();
+    Thread.sleep(3000);
+    electionSupport.stop();
+  }
+
+  @Test
+  public void testNodes3() throws IOException, InterruptedException,
+      KeeperException {
+
+    int testIterations = 3;
+    final CountDownLatch latch = new CountDownLatch(testIterations);
+    final AtomicInteger failureCounter = new AtomicInteger();
+
+    for (int i = 0; i < testIterations; i++) {
+      runElectionSupportThread(latch, failureCounter);
+    }
+
+    Assert.assertEquals(0, failureCounter.get());
+
+    if (!latch.await(10, TimeUnit.SECONDS)) {
+      logger
+          .info(
+              "Waited for all threads to start, but timed out. We had {} failures.",
+              failureCounter);
+    }
+  }
+
+  @Test
+  public void testNodes9() throws IOException, InterruptedException,
+      KeeperException {
+
+    int testIterations = 9;
+    final CountDownLatch latch = new CountDownLatch(testIterations);
+    final AtomicInteger failureCounter = new AtomicInteger();
+
+    for (int i = 0; i < testIterations; i++) {
+      runElectionSupportThread(latch, failureCounter);
+    }
+
+    Assert.assertEquals(0, failureCounter.get());
+
+    if (!latch.await(10, TimeUnit.SECONDS)) {
+      logger
+          .info(
+              "Waited for all threads to start, but timed out. We had {} failures.",
+              failureCounter);
+    }
+  }
+
+  @Test
+  public void testNodes20() throws IOException, InterruptedException,
+      KeeperException {
+
+    int testIterations = 20;
+    final CountDownLatch latch = new CountDownLatch(testIterations);
+    final AtomicInteger failureCounter = new AtomicInteger();
+
+    for (int i = 0; i < testIterations; i++) {
+      runElectionSupportThread(latch, failureCounter);
+    }
+
+    Assert.assertEquals(0, failureCounter.get());
+
+    if (!latch.await(10, TimeUnit.SECONDS)) {
+      logger
+          .info(
+              "Waited for all threads to start, but timed out. We had {} failures.",
+              failureCounter);
+    }
+  }
+
+  @Test
+  public void testNodes100() throws IOException, InterruptedException,
+      KeeperException {
+
+    int testIterations = 100;
+    final CountDownLatch latch = new CountDownLatch(testIterations);
+    final AtomicInteger failureCounter = new AtomicInteger();
+
+    for (int i = 0; i < testIterations; i++) {
+      runElectionSupportThread(latch, failureCounter);
+    }
+
+    Assert.assertEquals(0, failureCounter.get());
+
+    if (!latch.await(20, TimeUnit.SECONDS)) {
+      logger
+          .info(
+              "Waited for all threads to start, but timed out. We had {} failures.",
+              failureCounter);
+    }
+  }
+
+  @Test
+  public void testOfferShuffle() throws InterruptedException {
+    int testIterations = 10;
+    final CountDownLatch latch = new CountDownLatch(testIterations);
+    final AtomicInteger failureCounter = new AtomicInteger();
+    List<Thread> threads = new ArrayList<Thread>(testIterations);
+
+    for (int i = 1; i <= testIterations; i++) {
+      threads.add(runElectionSupportThread(latch, failureCounter,
+          Math.min(i * 1200, 10000)));
+    }
+
+    if (!latch.await(60, TimeUnit.SECONDS)) {
+      logger
+          .info(
+              "Waited for all threads to start, but timed out. We had {} failures.",
+              failureCounter);
+    }
+  }
+
+  @Test
+  public void testGetLeaderHostName() throws KeeperException,
+      InterruptedException {
+
+    LeaderElectionSupport electionSupport = createLeaderElectionSupport();
+
+    electionSupport.start();
+
+    // Sketchy: We assume there will be a leader (probably us) in 3 seconds.
+    Thread.sleep(3000);
+
+    String leaderHostName = electionSupport.getLeaderHostName();
+
+    Assert.assertNotNull(leaderHostName);
+    Assert.assertEquals("foohost", leaderHostName);
+
+    electionSupport.stop();
+  }
+
+  @Test
+  public void testReadyOffer() throws Exception {
+      final ArrayList<EventType> events = new ArrayList<EventType>();
+      final CountDownLatch electedComplete = new CountDownLatch(1);
+
+      final LeaderElectionSupport electionSupport1 = createLeaderElectionSupport();
+      electionSupport1.start();
+      LeaderElectionSupport electionSupport2 = createLeaderElectionSupport();
+      LeaderElectionAware listener = new LeaderElectionAware() {
+          boolean stoppedElectedNode = false;
+          @Override
+          public void onElectionEvent(EventType eventType) {
+              events.add(eventType);
+              if (!stoppedElectedNode
+                      && eventType == EventType.DETERMINE_COMPLETE) {
+                  stoppedElectedNode = true;
+                  try {
+                      // stopping the ELECTED node, so re-election will happen.
+                      electionSupport1.stop();
+                  } catch (Exception e) {
+                      logger.error("Unexpected error", e);
+                  }
+              }
+              if (eventType == EventType.ELECTED_COMPLETE) {
+                  electedComplete.countDown();
+              }
+          }
+      };
+      electionSupport2.addListener(listener);
+      electionSupport2.start();
+      // waiting for re-election.
+      electedComplete.await(CONNECTION_TIMEOUT / 3, TimeUnit.MILLISECONDS);
+
+      final ArrayList<EventType> expectedevents = new ArrayList<EventType>();
+      expectedevents.add(EventType.START);
+      expectedevents.add(EventType.OFFER_START);
+      expectedevents.add(EventType.OFFER_COMPLETE);
+      expectedevents.add(EventType.DETERMINE_START);
+      expectedevents.add(EventType.DETERMINE_COMPLETE);
+      expectedevents.add(EventType.DETERMINE_START);
+      expectedevents.add(EventType.DETERMINE_COMPLETE);
+      expectedevents.add(EventType.ELECTED_START);
+      expectedevents.add(EventType.ELECTED_COMPLETE);
+      Assert.assertEquals("Events has failed to executed in the order",
+              expectedevents, events);
+      electionSupport2.stop();
+  }
+  
+  private LeaderElectionSupport createLeaderElectionSupport() {
+    LeaderElectionSupport electionSupport = new LeaderElectionSupport();
+
+    electionSupport.setZooKeeper(zooKeeper);
+    electionSupport.setRootNodeName(testRootNode
+        + Thread.currentThread().getId());
+    electionSupport.setHostName("foohost");
+
+    return electionSupport;
+  }
+
+  private Thread runElectionSupportThread(final CountDownLatch latch,
+      final AtomicInteger failureCounter) {
+    return runElectionSupportThread(latch, failureCounter, 3000);
+  }
+
+  private Thread runElectionSupportThread(final CountDownLatch latch,
+      final AtomicInteger failureCounter, final long sleepDuration) {
+
+    final LeaderElectionSupport electionSupport = createLeaderElectionSupport();
+
+    Thread t = new Thread() {
+
+      @Override
+      public void run() {
+        try {
+          electionSupport.start();
+          Thread.sleep(sleepDuration);
+          electionSupport.stop();
+
+          latch.countDown();
+        } catch (Exception e) {
+          logger.warn("Failed to run leader election due to: {}",
+              e.getMessage());
+          failureCounter.incrementAndGet();
+        }
+      }
+    };
+
+    t.start();
+
+    return t;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/2584625c/zookeeper-recipes/zookeeper-recipes-election/test/org/apache/zookeeper/recipes/leader/LeaderElectionSupportTest.java
----------------------------------------------------------------------
diff --git a/zookeeper-recipes/zookeeper-recipes-election/test/org/apache/zookeeper/recipes/leader/LeaderElectionSupportTest.java b/zookeeper-recipes/zookeeper-recipes-election/test/org/apache/zookeeper/recipes/leader/LeaderElectionSupportTest.java
deleted file mode 100644
index 7e19dc7..0000000
--- a/zookeeper-recipes/zookeeper-recipes-election/test/org/apache/zookeeper/recipes/leader/LeaderElectionSupportTest.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * 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.recipes.leader;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-
-import org.apache.zookeeper.CreateMode;
-import org.apache.zookeeper.KeeperException;
-import org.apache.zookeeper.ZooDefs;
-import org.apache.zookeeper.ZooKeeper;
-import org.apache.zookeeper.recipes.leader.LeaderElectionSupport.EventType;
-import org.apache.zookeeper.test.ClientBase;
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class LeaderElectionSupportTest extends ClientBase {
-
-  private static final Logger logger = LoggerFactory
-      .getLogger(LeaderElectionSupportTest.class);
-  private static final String testRootNode = "/" + System.currentTimeMillis()
-      + "_";
-
-  private ZooKeeper zooKeeper;
-
-  @Before
-  public void setUp() throws Exception {
-    super.setUp();
-
-    zooKeeper = createClient();
-
-    zooKeeper.create(testRootNode + Thread.currentThread().getId(),
-        new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
-  }
-
-  @After
-  public void tearDown() throws Exception {
-    if (zooKeeper != null) {
-      zooKeeper.delete(testRootNode + Thread.currentThread().getId(), -1);
-    }
-
-    super.tearDown();
-  }
-
-  @Test
-  public void testNode() throws IOException, InterruptedException,
-      KeeperException {
-
-    LeaderElectionSupport electionSupport = createLeaderElectionSupport();
-
-    electionSupport.start();
-    Thread.sleep(3000);
-    electionSupport.stop();
-  }
-
-  @Test
-  public void testNodes3() throws IOException, InterruptedException,
-      KeeperException {
-
-    int testIterations = 3;
-    final CountDownLatch latch = new CountDownLatch(testIterations);
-    final AtomicInteger failureCounter = new AtomicInteger();
-
-    for (int i = 0; i < testIterations; i++) {
-      runElectionSupportThread(latch, failureCounter);
-    }
-
-    Assert.assertEquals(0, failureCounter.get());
-
-    if (!latch.await(10, TimeUnit.SECONDS)) {
-      logger
-          .info(
-              "Waited for all threads to start, but timed out. We had {} failures.",
-              failureCounter);
-    }
-  }
-
-  @Test
-  public void testNodes9() throws IOException, InterruptedException,
-      KeeperException {
-
-    int testIterations = 9;
-    final CountDownLatch latch = new CountDownLatch(testIterations);
-    final AtomicInteger failureCounter = new AtomicInteger();
-
-    for (int i = 0; i < testIterations; i++) {
-      runElectionSupportThread(latch, failureCounter);
-    }
-
-    Assert.assertEquals(0, failureCounter.get());
-
-    if (!latch.await(10, TimeUnit.SECONDS)) {
-      logger
-          .info(
-              "Waited for all threads to start, but timed out. We had {} failures.",
-              failureCounter);
-    }
-  }
-
-  @Test
-  public void testNodes20() throws IOException, InterruptedException,
-      KeeperException {
-
-    int testIterations = 20;
-    final CountDownLatch latch = new CountDownLatch(testIterations);
-    final AtomicInteger failureCounter = new AtomicInteger();
-
-    for (int i = 0; i < testIterations; i++) {
-      runElectionSupportThread(latch, failureCounter);
-    }
-
-    Assert.assertEquals(0, failureCounter.get());
-
-    if (!latch.await(10, TimeUnit.SECONDS)) {
-      logger
-          .info(
-              "Waited for all threads to start, but timed out. We had {} failures.",
-              failureCounter);
-    }
-  }
-
-  @Test
-  public void testNodes100() throws IOException, InterruptedException,
-      KeeperException {
-
-    int testIterations = 100;
-    final CountDownLatch latch = new CountDownLatch(testIterations);
-    final AtomicInteger failureCounter = new AtomicInteger();
-
-    for (int i = 0; i < testIterations; i++) {
-      runElectionSupportThread(latch, failureCounter);
-    }
-
-    Assert.assertEquals(0, failureCounter.get());
-
-    if (!latch.await(20, TimeUnit.SECONDS)) {
-      logger
-          .info(
-              "Waited for all threads to start, but timed out. We had {} failures.",
-              failureCounter);
-    }
-  }
-
-  @Test
-  public void testOfferShuffle() throws InterruptedException {
-    int testIterations = 10;
-    final CountDownLatch latch = new CountDownLatch(testIterations);
-    final AtomicInteger failureCounter = new AtomicInteger();
-    List<Thread> threads = new ArrayList<Thread>(testIterations);
-
-    for (int i = 1; i <= testIterations; i++) {
-      threads.add(runElectionSupportThread(latch, failureCounter,
-          Math.min(i * 1200, 10000)));
-    }
-
-    if (!latch.await(60, TimeUnit.SECONDS)) {
-      logger
-          .info(
-              "Waited for all threads to start, but timed out. We had {} failures.",
-              failureCounter);
-    }
-  }
-
-  @Test
-  public void testGetLeaderHostName() throws KeeperException,
-      InterruptedException {
-
-    LeaderElectionSupport electionSupport = createLeaderElectionSupport();
-
-    electionSupport.start();
-
-    // Sketchy: We assume there will be a leader (probably us) in 3 seconds.
-    Thread.sleep(3000);
-
-    String leaderHostName = electionSupport.getLeaderHostName();
-
-    Assert.assertNotNull(leaderHostName);
-    Assert.assertEquals("foohost", leaderHostName);
-
-    electionSupport.stop();
-  }
-
-  @Test
-  public void testReadyOffer() throws Exception {
-      final ArrayList<EventType> events = new ArrayList<EventType>();
-      final CountDownLatch electedComplete = new CountDownLatch(1);
-
-      final LeaderElectionSupport electionSupport1 = createLeaderElectionSupport();
-      electionSupport1.start();
-      LeaderElectionSupport electionSupport2 = createLeaderElectionSupport();
-      LeaderElectionAware listener = new LeaderElectionAware() {
-          boolean stoppedElectedNode = false;
-          @Override
-          public void onElectionEvent(EventType eventType) {
-              events.add(eventType);
-              if (!stoppedElectedNode
-                      && eventType == EventType.DETERMINE_COMPLETE) {
-                  stoppedElectedNode = true;
-                  try {
-                      // stopping the ELECTED node, so re-election will happen.
-                      electionSupport1.stop();
-                  } catch (Exception e) {
-                      logger.error("Unexpected error", e);
-                  }
-              }
-              if (eventType == EventType.ELECTED_COMPLETE) {
-                  electedComplete.countDown();
-              }
-          }
-      };
-      electionSupport2.addListener(listener);
-      electionSupport2.start();
-      // waiting for re-election.
-      electedComplete.await(CONNECTION_TIMEOUT / 3, TimeUnit.MILLISECONDS);
-
-      final ArrayList<EventType> expectedevents = new ArrayList<EventType>();
-      expectedevents.add(EventType.START);
-      expectedevents.add(EventType.OFFER_START);
-      expectedevents.add(EventType.OFFER_COMPLETE);
-      expectedevents.add(EventType.DETERMINE_START);
-      expectedevents.add(EventType.DETERMINE_COMPLETE);
-      expectedevents.add(EventType.DETERMINE_START);
-      expectedevents.add(EventType.DETERMINE_COMPLETE);
-      expectedevents.add(EventType.ELECTED_START);
-      expectedevents.add(EventType.ELECTED_COMPLETE);
-      Assert.assertEquals("Events has failed to executed in the order",
-              expectedevents, events);
-      electionSupport2.stop();
-  }
-  
-  private LeaderElectionSupport createLeaderElectionSupport() {
-    LeaderElectionSupport electionSupport = new LeaderElectionSupport();
-
-    electionSupport.setZooKeeper(zooKeeper);
-    electionSupport.setRootNodeName(testRootNode
-        + Thread.currentThread().getId());
-    electionSupport.setHostName("foohost");
-
-    return electionSupport;
-  }
-
-  private Thread runElectionSupportThread(final CountDownLatch latch,
-      final AtomicInteger failureCounter) {
-    return runElectionSupportThread(latch, failureCounter, 3000);
-  }
-
-  private Thread runElectionSupportThread(final CountDownLatch latch,
-      final AtomicInteger failureCounter, final long sleepDuration) {
-
-    final LeaderElectionSupport electionSupport = createLeaderElectionSupport();
-
-    Thread t = new Thread() {
-
-      @Override
-      public void run() {
-        try {
-          electionSupport.start();
-          Thread.sleep(sleepDuration);
-          electionSupport.stop();
-
-          latch.countDown();
-        } catch (Exception e) {
-          logger.warn("Failed to run leader election due to: {}",
-              e.getMessage());
-          failureCounter.incrementAndGet();
-        }
-      }
-    };
-
-    t.start();
-
-    return t;
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/2584625c/zookeeper-recipes/zookeeper-recipes-lock/README.txt
----------------------------------------------------------------------
diff --git a/zookeeper-recipes/zookeeper-recipes-lock/README.txt b/zookeeper-recipes/zookeeper-recipes-lock/README.txt
index 1fc4fbf..1322651 100644
--- a/zookeeper-recipes/zookeeper-recipes-lock/README.txt
+++ b/zookeeper-recipes/zookeeper-recipes-lock/README.txt
@@ -16,10 +16,10 @@
 -->
 
 1) This lock interface recipe implements the lock recipe
-mentioned in ../../../docs/recipes.[html,pdf].
+mentioned in ../../docs/recipes.[html,pdf].
 
 2) To compile the lock java recipe you can just run ant jar from 
-this directory. For compiling the c libarary go to src/c and read
+this directory. For compiling the c libarary go to src/main/c and read
 the INSTALLATION instructions. 
 Please report any bugs on the jira 
 

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/2584625c/zookeeper-recipes/zookeeper-recipes-lock/build.xml
----------------------------------------------------------------------
diff --git a/zookeeper-recipes/zookeeper-recipes-lock/build.xml b/zookeeper-recipes/zookeeper-recipes-lock/build.xml
index 1fa7b22..6d7d736 100644
--- a/zookeeper-recipes/zookeeper-recipes-lock/build.xml
+++ b/zookeeper-recipes/zookeeper-recipes-lock/build.xml
@@ -19,7 +19,7 @@
   <import file="../build-recipes.xml"/>
     <property name="test.main.classes" value="${zk.root}/build/test/classes"/>
     <property name="test.build.dir" value="${build.test}" />
-    <property name="test.src.dir" value="test"/>
+    <property name="test.src.dir" value="src/test/java"/>
     <property name="test.log.dir" value="${test.build.dir}/logs" />
     <property name="test.data.dir" value="${test.build.dir}/data" />
     <property name="test.data.upgrade.dir" value="${test.data.dir}/upgrade" />
@@ -114,13 +114,17 @@
 
     <copy file="${basedir}/build.xml" todir="${dist.dir}${package.share}/recipes/${name}"/>
 
-    <mkdir dir="${dist.dir}${package.share}/recipes/${name}/test"/>
-    <copy todir="${dist.dir}${package.share}/recipes/${name}/test">
-      <fileset dir="${basedir}/test"/>
+    <mkdir dir="${dist.dir}${package.share}/recipes/${name}/src/test/java"/>
+    <copy todir="${dist.dir}${package.share}/recipes/${name}/src/test/java">
+      <fileset dir="${basedir}/src/test/java"/>
     </copy>
-    <mkdir dir="${dist.dir}${package.share}/recipes/${name}/src"/>
-    <copy todir="${dist.dir}${package.share}/recipes/${name}/src">
-      <fileset dir="${basedir}/src"/>
+    <mkdir dir="${dist.dir}${package.share}/recipes/${name}/src/main/java"/>
+    <copy todir="${dist.dir}${package.share}/recipes/${name}/src/main/java">
+      <fileset dir="${basedir}/src/main/java"/>
+    </copy>
+    <mkdir dir="${dist.dir}${package.share}/recipes/${name}/src/main/c"/>
+    <copy todir="${dist.dir}${package.share}/recipes/${name}/src/main/c">
+      <fileset dir="${basedir}/src/main/c"/>
     </copy>
   </target>
 

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/2584625c/zookeeper-recipes/zookeeper-recipes-lock/src/c/INSTALL
----------------------------------------------------------------------
diff --git a/zookeeper-recipes/zookeeper-recipes-lock/src/c/INSTALL b/zookeeper-recipes/zookeeper-recipes-lock/src/c/INSTALL
deleted file mode 100644
index 5458714..0000000
--- a/zookeeper-recipes/zookeeper-recipes-lock/src/c/INSTALL
+++ /dev/null
@@ -1,234 +0,0 @@
-Installation Instructions
-*************************
-
-Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
-2006 Free Software Foundation, Inc.
-
-This file is free documentation; the Free Software Foundation gives
-unlimited permission to copy, distribute and modify it.
-
-Basic Installation
-==================
-
-Briefly, the shell commands `./configure; make; make install' should
-configure, build, and install this package.  The following
-more-detailed instructions are generic; see the `README' file for
-instructions specific to this package.
-
-   The `configure' shell script attempts to guess correct values for
-various system-dependent variables used during compilation.  It uses
-those values to create a `Makefile' in each directory of the package.
-It may also create one or more `.h' files containing system-dependent
-definitions.  Finally, it creates a shell script `config.status' that
-you can run in the future to recreate the current configuration, and a
-file `config.log' containing compiler output (useful mainly for
-debugging `configure').
-
-   It can also use an optional file (typically called `config.cache'
-and enabled with `--cache-file=config.cache' or simply `-C') that saves
-the results of its tests to speed up reconfiguring.  Caching is
-disabled by default to prevent problems with accidental use of stale
-cache files.
-
-   If you need to do unusual things to compile the package, please try
-to figure out how `configure' could check whether to do them, and mail
-diffs or instructions to the address given in the `README' so they can
-be considered for the next release.  If you are using the cache, and at
-some point `config.cache' contains results you don't want to keep, you
-may remove or edit it.
-
-   The file `configure.ac' (or `configure.in') is used to create
-`configure' by a program called `autoconf'.  You need `configure.ac' if
-you want to change it or regenerate `configure' using a newer version
-of `autoconf'.
-
-The simplest way to compile this package is:
-
-  1. `cd' to the directory containing the package's source code and type
-     `./configure' to configure the package for your system.
-
-     Running `configure' might take a while.  While running, it prints
-     some messages telling which features it is checking for.
-
-  2. Type `make' to compile the package.
-
-  3. Optionally, type `make check' to run any self-tests that come with
-     the package.
-
-  4. Type `make install' to install the programs and any data files and
-     documentation.
-
-  5. You can remove the program binaries and object files from the
-     source code directory by typing `make clean'.  To also remove the
-     files that `configure' created (so you can compile the package for
-     a different kind of computer), type `make distclean'.  There is
-     also a `make maintainer-clean' target, but that is intended mainly
-     for the package's developers.  If you use it, you may have to get
-     all sorts of other programs in order to regenerate files that came
-     with the distribution.
-
-Compilers and Options
-=====================
-
-Some systems require unusual options for compilation or linking that the
-`configure' script does not know about.  Run `./configure --help' for
-details on some of the pertinent environment variables.
-
-   You can give `configure' initial values for configuration parameters
-by setting variables in the command line or in the environment.  Here
-is an example:
-
-     ./configure CC=c99 CFLAGS=-g LIBS=-lposix
-
-   *Note Defining Variables::, for more details.
-
-Compiling For Multiple Architectures
-====================================
-
-You can compile the package for more than one kind of computer at the
-same time, by placing the object files for each architecture in their
-own directory.  To do this, you can use GNU `make'.  `cd' to the
-directory where you want the object files and executables to go and run
-the `configure' script.  `configure' automatically checks for the
-source code in the directory that `configure' is in and in `..'.
-
-   With a non-GNU `make', it is safer to compile the package for one
-architecture at a time in the source code directory.  After you have
-installed the package for one architecture, use `make distclean' before
-reconfiguring for another architecture.
-
-Installation Names
-==================
-
-By default, `make install' installs the package's commands under
-`/usr/local/bin', include files under `/usr/local/include', etc.  You
-can specify an installation prefix other than `/usr/local' by giving
-`configure' the option `--prefix=PREFIX'.
-
-   You can specify separate installation prefixes for
-architecture-specific files and architecture-independent files.  If you
-pass the option `--exec-prefix=PREFIX' to `configure', the package uses
-PREFIX as the prefix for installing programs and libraries.
-Documentation and other data files still use the regular prefix.
-
-   In addition, if you use an unusual directory layout you can give
-options like `--bindir=DIR' to specify different values for particular
-kinds of files.  Run `configure --help' for a list of the directories
-you can set and what kinds of files go in them.
-
-   If the package supports it, you can cause programs to be installed
-with an extra prefix or suffix on their names by giving `configure' the
-option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
-
-Optional Features
-=================
-
-Some packages pay attention to `--enable-FEATURE' options to
-`configure', where FEATURE indicates an optional part of the package.
-They may also pay attention to `--with-PACKAGE' options, where PACKAGE
-is something like `gnu-as' or `x' (for the X Window System).  The
-`README' should mention any `--enable-' and `--with-' options that the
-package recognizes.
-
-   For packages that use the X Window System, `configure' can usually
-find the X include and library files automatically, but if it doesn't,
-you can use the `configure' options `--x-includes=DIR' and
-`--x-libraries=DIR' to specify their locations.
-
-Specifying the System Type
-==========================
-
-There may be some features `configure' cannot figure out automatically,
-but needs to determine by the type of machine the package will run on.
-Usually, assuming the package is built to be run on the _same_
-architectures, `configure' can figure that out, but if it prints a
-message saying it cannot guess the machine type, give it the
-`--build=TYPE' option.  TYPE can either be a short name for the system
-type, such as `sun4', or a canonical name which has the form:
-
-     CPU-COMPANY-SYSTEM
-
-where SYSTEM can have one of these forms:
-
-     OS KERNEL-OS
-
-   See the file `config.sub' for the possible values of each field.  If
-`config.sub' isn't included in this package, then this package doesn't
-need to know the machine type.
-
-   If you are _building_ compiler tools for cross-compiling, you should
-use the option `--target=TYPE' to select the type of system they will
-produce code for.
-
-   If you want to _use_ a cross compiler, that generates code for a
-platform different from the build platform, you should specify the
-"host" platform (i.e., that on which the generated programs will
-eventually be run) with `--host=TYPE'.
-
-Sharing Defaults
-================
-
-If you want to set default values for `configure' scripts to share, you
-can create a site shell script called `config.site' that gives default
-values for variables like `CC', `cache_file', and `prefix'.
-`configure' looks for `PREFIX/share/config.site' if it exists, then
-`PREFIX/etc/config.site' if it exists.  Or, you can set the
-`CONFIG_SITE' environment variable to the location of the site script.
-A warning: not all `configure' scripts look for a site script.
-
-Defining Variables
-==================
-
-Variables not defined in a site shell script can be set in the
-environment passed to `configure'.  However, some packages may run
-configure again during the build, and the customized values of these
-variables may be lost.  In order to avoid this problem, you should set
-them in the `configure' command line, using `VAR=value'.  For example:
-
-     ./configure CC=/usr/local2/bin/gcc
-
-causes the specified `gcc' to be used as the C compiler (unless it is
-overridden in the site shell script).
-
-Unfortunately, this technique does not work for `CONFIG_SHELL' due to
-an Autoconf bug.  Until the bug is fixed you can use this workaround:
-
-     CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
-
-`configure' Invocation
-======================
-
-`configure' recognizes the following options to control how it operates.
-
-`--help'
-`-h'
-     Print a summary of the options to `configure', and exit.
-
-`--version'
-`-V'
-     Print the version of Autoconf used to generate the `configure'
-     script, and exit.
-
-`--cache-file=FILE'
-     Enable the cache: use and save the results of the tests in FILE,
-     traditionally `config.cache'.  FILE defaults to `/dev/null' to
-     disable caching.
-
-`--config-cache'
-`-C'
-     Alias for `--cache-file=config.cache'.
-
-`--quiet'
-`--silent'
-`-q'
-     Do not print messages saying which checks are being made.  To
-     suppress all normal output, redirect it to `/dev/null' (any error
-     messages will still be shown).
-
-`--srcdir=DIR'
-     Look for the package's source code in directory DIR.  Usually
-     `configure' can determine that directory automatically.
-
-`configure' also accepts some other, not widely useful, options.  Run
-`configure --help' for more details.
-


Mime
View raw message