You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@curator.apache.org by dr...@apache.org on 2015/08/17 18:54:31 UTC

[01/27] curator git commit: Upgrade to ZooKeeper 3.5.0-alpha.

Repository: curator
Updated Branches:
  refs/heads/CURATOR-215 f1e6183e4 -> 8389371b3 (forced update)


Upgrade to ZooKeeper 3.5.0-alpha.


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/227aaf3f
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/227aaf3f
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/227aaf3f

Branch: refs/heads/CURATOR-215
Commit: 227aaf3f56dd2e587977f97d10b9b8b20525830a
Parents: 7f20986
Author: Ioannis Canellos <io...@gmail.com>
Authored: Thu Nov 6 16:53:09 2014 +0200
Committer: Scott Blum <dr...@apache.org>
Committed: Wed Aug 12 14:24:00 2015 -0400

----------------------------------------------------------------------
 .../framework/recipes/leader/ChaosMonkeyCnxnFactory.java      | 7 -------
 pom.xml                                                       | 2 +-
 2 files changed, 1 insertion(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/227aaf3f/curator-recipes/src/test/java/org/apache/curator/framework/recipes/leader/ChaosMonkeyCnxnFactory.java
----------------------------------------------------------------------
diff --git a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/leader/ChaosMonkeyCnxnFactory.java b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/leader/ChaosMonkeyCnxnFactory.java
index 5f10c5e..ce5b23d 100644
--- a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/leader/ChaosMonkeyCnxnFactory.java
+++ b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/leader/ChaosMonkeyCnxnFactory.java
@@ -59,13 +59,6 @@ public class ChaosMonkeyCnxnFactory extends NIOServerCnxnFactory
         super.startup(new ChaosMonkeyZookeeperServer(zks));
     }
 
-    /**
-     * Build a connection with a Chaos Monkey ZookeeperServer
-     */
-    protected NIOServerCnxn createConnection(SocketChannel sock, SelectionKey sk) throws IOException
-    {
-        return new NIOServerCnxn(zkServer, sock, sk, this);
-    }
 
     public static class ChaosMonkeyZookeeperServer extends ZooKeeperServer
     {

http://git-wip-us.apache.org/repos/asf/curator/blob/227aaf3f/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index f3db843..21eefbf 100644
--- a/pom.xml
+++ b/pom.xml
@@ -74,7 +74,7 @@
         <jetty-version>6.1.26</jetty-version>
         <scannotation-version>1.0.2</scannotation-version>
         <resteasy-jaxrs-version>2.3.0.GA</resteasy-jaxrs-version>
-        <zookeeper-version>3.4.6</zookeeper-version>
+        <zookeeper-version>3.5.0-alpha</zookeeper-version>
         <guava-version>16.0.1</guava-version>
         <testng-version>6.8.8</testng-version>
         <swift-version>0.12.0</swift-version>


[27/27] curator git commit: updated doc

Posted by dr...@apache.org.
updated doc


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/8389371b
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/8389371b
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/8389371b

Branch: refs/heads/CURATOR-215
Commit: 8389371b3bd635d39aecc8e63020ef95896fbc21
Parents: 847dfbe
Author: randgalt <ra...@apache.org>
Authored: Tue May 12 17:24:08 2015 -0500
Committer: Scott Blum <dr...@apache.org>
Committed: Wed Aug 12 17:29:43 2015 -0400

----------------------------------------------------------------------
 .../java/org/apache/curator/framework/CuratorFramework.java     | 5 ++++-
 .../framework/api/transaction/CuratorMultiTransactionMain.java  | 4 ++--
 2 files changed, 6 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/8389371b/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java b/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
index 1bc1535..d56f2ca 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
@@ -22,6 +22,7 @@ package org.apache.curator.framework;
 import org.apache.curator.CuratorZookeeperClient;
 import org.apache.curator.framework.api.*;
 import org.apache.curator.framework.api.transaction.CuratorMultiTransaction;
+import org.apache.curator.framework.api.transaction.CuratorOp;
 import org.apache.curator.framework.api.transaction.CuratorTransaction;
 import org.apache.curator.framework.api.transaction.TransactionOp;
 import org.apache.curator.framework.imps.CuratorFrameworkState;
@@ -152,7 +153,9 @@ public interface CuratorFramework extends Closeable
     public CuratorMultiTransaction transaction();
 
     /**
-     * Allocate an operation that can be used with {@link #transaction()}
+     * Allocate an operation that can be used with {@link #transaction()}.
+     * NOTE: {@link CuratorOp} instances created by this builder are
+     * reusable.
      *
      * @return operation builder
      */

http://git-wip-us.apache.org/repos/asf/curator/blob/8389371b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorMultiTransactionMain.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorMultiTransactionMain.java b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorMultiTransactionMain.java
index 77dae61..2425f5b 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorMultiTransactionMain.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorMultiTransactionMain.java
@@ -28,7 +28,7 @@ public interface CuratorMultiTransactionMain
      * operation instances via {@link CuratorFramework#transactionOp()}
      *
      * @param operations operations that make up the transaction.
-     * @return result details
+     * @return result details for foreground operations or <code>null</code> for background operations
      * @throws Exception errors
      */
     List<CuratorTransactionResult> forOperations(CuratorOp... operations) throws Exception;
@@ -38,7 +38,7 @@ public interface CuratorMultiTransactionMain
      * operation instances via {@link CuratorFramework#transactionOp()}
      *
      * @param operations operations that make up the transaction.
-     * @return result details
+     * @return result details for foreground operations or <code>null</code> for background operations
      * @throws Exception errors
      */
     List<CuratorTransactionResult> forOperations(List<CuratorOp> operations) throws Exception;


[05/27] curator git commit: [CURATOR-160] Add builders and dsl for ZooKeeper's config and reconfig methods.

Posted by dr...@apache.org.
[CURATOR-160] Add builders and dsl for ZooKeeper's config and reconfig methods.


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

Branch: refs/heads/CURATOR-215
Commit: b00cecf4902aeffdba05d9e09d4e9210c5ad80ab
Parents: 2bd53fc
Author: Ioannis Canellos <io...@gmail.com>
Authored: Thu Nov 6 17:34:47 2014 +0200
Committer: Scott Blum <dr...@apache.org>
Committed: Wed Aug 12 17:07:31 2015 -0400

----------------------------------------------------------------------
 .../main/java/org/apache/curator/RetryLoop.java |   3 +-
 .../api/BackgroundStatConfigurable.java         |  24 +++
 .../framework/api/BackgroundStatable.java       |  24 +++
 .../curator/framework/api/Configurable.java     |  29 +++
 .../curator/framework/api/CuratorEventType.java |  10 +
 .../curator/framework/api/Ensembleable.java     |  24 +++
 .../curator/framework/api/GetConfigBuilder.java |   6 +-
 .../api/JoinBackgroundStatConfigurable.java     |  30 +++
 .../apache/curator/framework/api/Joinable.java  |  15 +-
 .../api/LeaveBackgroundStatConfigurable.java    |  30 +++
 .../apache/curator/framework/api/Leaveable.java |  14 +-
 .../curator/framework/api/Memberable.java       |  13 +-
 .../curator/framework/api/ReconfigBuilder.java  |   6 +-
 .../imps/EnsembleServersAndConfig.java          |  52 +++++
 .../framework/imps/GetConfigBuilderImpl.java    | 165 +++++++++++---
 .../framework/imps/ReconfigBuilderImpl.java     | 216 +++++++++++--------
 .../framework/imps/TestReconfiguration.java     | 176 +++++++--------
 .../org/apache/curator/test/InstanceSpec.java   |   4 +
 .../org/apache/curator/test/TestingCluster.java |   1 +
 19 files changed, 594 insertions(+), 248 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/b00cecf4/curator-client/src/main/java/org/apache/curator/RetryLoop.java
----------------------------------------------------------------------
diff --git a/curator-client/src/main/java/org/apache/curator/RetryLoop.java b/curator-client/src/main/java/org/apache/curator/RetryLoop.java
index 6b66e82..065ebef 100644
--- a/curator-client/src/main/java/org/apache/curator/RetryLoop.java
+++ b/curator-client/src/main/java/org/apache/curator/RetryLoop.java
@@ -150,7 +150,8 @@ public class RetryLoop
         return (rc == KeeperException.Code.CONNECTIONLOSS.intValue()) ||
             (rc == KeeperException.Code.OPERATIONTIMEOUT.intValue()) ||
             (rc == KeeperException.Code.SESSIONMOVED.intValue()) ||
-            (rc == KeeperException.Code.SESSIONEXPIRED.intValue());
+            (rc == KeeperException.Code.SESSIONEXPIRED.intValue()) ||
+            (rc == KeeperException.Code.NEWCONFIGNOQUORUM.intValue());
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/curator/blob/b00cecf4/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundStatConfigurable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundStatConfigurable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundStatConfigurable.java
new file mode 100644
index 0000000..e46ba89
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundStatConfigurable.java
@@ -0,0 +1,24 @@
+/**
+ * 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.curator.framework.api;
+
+public interface BackgroundStatConfigurable<T> extends
+    BackgroundStatable<Configurable<T>>,
+    Configurable<T> {
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/b00cecf4/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundStatable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundStatable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundStatable.java
new file mode 100644
index 0000000..77c4e96
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundStatable.java
@@ -0,0 +1,24 @@
+/**
+ * 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.curator.framework.api;
+
+public interface BackgroundStatable<T> extends
+    Backgroundable<T>,
+    Statable<T> {
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/b00cecf4/curator-framework/src/main/java/org/apache/curator/framework/api/Configurable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/Configurable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/Configurable.java
new file mode 100644
index 0000000..a47f9d0
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/Configurable.java
@@ -0,0 +1,29 @@
+/**
+ * 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.curator.framework.api;
+
+public interface Configurable<T> {
+
+    /**
+     * Sets the configuration version to use.
+     * @param config The version of the configuration.
+     * @throws Exception
+     */
+    Ensembleable<T> fromConfig(long config) throws Exception;
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/b00cecf4/curator-framework/src/main/java/org/apache/curator/framework/api/CuratorEventType.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/CuratorEventType.java b/curator-framework/src/main/java/org/apache/curator/framework/api/CuratorEventType.java
index 684d11b..50e9195 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/CuratorEventType.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/CuratorEventType.java
@@ -69,6 +69,16 @@ public enum CuratorEventType
     SET_ACL,
 
     /**
+     * Corresponds to {@link CuratorFramework#getConfig()}
+     */
+    GET_CONFIG,
+
+    /**
+     * Corresponds to {@link CuratorFramework#reconfig()}
+     */
+    RECONFIG,
+
+    /**
      * Corresponds to {@link Watchable#usingWatcher(Watcher)} or {@link Watchable#watched()}
      */
     WATCHED,

http://git-wip-us.apache.org/repos/asf/curator/blob/b00cecf4/curator-framework/src/main/java/org/apache/curator/framework/api/Ensembleable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/Ensembleable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/Ensembleable.java
new file mode 100644
index 0000000..c8a82fe
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/Ensembleable.java
@@ -0,0 +1,24 @@
+/**
+ * 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.curator.framework.api;
+
+public interface Ensembleable<T> {
+
+    T forEnsemble() throws Exception;
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/b00cecf4/curator-framework/src/main/java/org/apache/curator/framework/api/GetConfigBuilder.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/GetConfigBuilder.java b/curator-framework/src/main/java/org/apache/curator/framework/api/GetConfigBuilder.java
index c7c013b..c2fdf6c 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/GetConfigBuilder.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/GetConfigBuilder.java
@@ -19,9 +19,9 @@
 package org.apache.curator.framework.api;
 
 public interface GetConfigBuilder extends
-        Watchable<GetConfigBuilder>,
-        DataCallbackable<Void>,
-        Statable<byte[]> {
+        Watchable<BackgroundStatable<Ensembleable<byte[]>>>,
+        BackgroundStatable<Ensembleable<byte[]>>,
+        Ensembleable<byte[]> {
 }
 
 

http://git-wip-us.apache.org/repos/asf/curator/blob/b00cecf4/curator-framework/src/main/java/org/apache/curator/framework/api/JoinBackgroundStatConfigurable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/JoinBackgroundStatConfigurable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/JoinBackgroundStatConfigurable.java
new file mode 100644
index 0000000..fb18c0c
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/JoinBackgroundStatConfigurable.java
@@ -0,0 +1,30 @@
+/**
+ * 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.curator.framework.api;
+
+/**
+ * An incremental reconfiguration builder.
+ * This builder has access only to the incremental reconfiguration methods joining and leaving, so that we prevent
+ * mixing concepts that can't be used together.
+ */
+public interface JoinBackgroundStatConfigurable extends
+        Joinable<BackgroundStatConfigurable<byte[]>>,
+        BackgroundStatConfigurable<byte[]> {
+
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/b00cecf4/curator-framework/src/main/java/org/apache/curator/framework/api/Joinable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/Joinable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/Joinable.java
index ff1b3c5..dde5b1c 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/Joinable.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/Joinable.java
@@ -18,23 +18,14 @@
  */
 package org.apache.curator.framework.api;
 
-import java.util.Collection;
-
 public interface Joinable<T> {
 
     /**
-     * Adds a server to join the ensemble.
+     * Adds one or more servers to joining the ensemble.
      * The expected format is server.[id]=[hostname]:[peer port]:[election port]:[type];[client port]
-     * @param server The server to join.
+     * @param server The server to joining.
      * @return this.
      */
-    T join(String server);
+    T joining(String... server);
 
-    /**
-     * Adds a collection of servers to the ensemble.
-     * The expected format is server.[id]=[hostname]:[peer port]:[election port]:[type];[client port]
-     * @param servers The collection of servers to join
-     * @return this
-     */
-    T join(Collection<String> servers);
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/b00cecf4/curator-framework/src/main/java/org/apache/curator/framework/api/LeaveBackgroundStatConfigurable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/LeaveBackgroundStatConfigurable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/LeaveBackgroundStatConfigurable.java
new file mode 100644
index 0000000..196ffca
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/LeaveBackgroundStatConfigurable.java
@@ -0,0 +1,30 @@
+/**
+ * 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.curator.framework.api;
+
+/**
+ * An non-incremental reconfiguration builder.
+ * This builder has access only to the non-incremental reconfiguration methods withMembers, so that we prevent
+ * mixing concepts that can't be used together.
+ */
+public interface LeaveBackgroundStatConfigurable extends
+        Leaveable<BackgroundStatConfigurable<byte[]>>,
+        BackgroundStatConfigurable<byte[]> {
+
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/b00cecf4/curator-framework/src/main/java/org/apache/curator/framework/api/Leaveable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/Leaveable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/Leaveable.java
index 8560d65..a3c3358 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/Leaveable.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/Leaveable.java
@@ -18,21 +18,13 @@
  */
 package org.apache.curator.framework.api;
 
-import java.util.Collection;
-
 public interface Leaveable<T> {
 
     /**
-     * Sets a server to leave the ensemble.
-     * @param server The server id.
+     * Sets one or more servers to leaving the ensemble.
+     * @param server The server ids.
      * @return this
      */
-    T leave(String server);
+    T leaving(String... server);
 
-    /**
-     * Sets a collection of servers to leave the ensemble.
-     * @param servers The collection of server ids.
-     * @return this.
-     */
-    T leave(Collection<String> servers);
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/b00cecf4/curator-framework/src/main/java/org/apache/curator/framework/api/Memberable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/Memberable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/Memberable.java
index 5b62dba..6ef54c1 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/Memberable.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/Memberable.java
@@ -18,23 +18,14 @@
  */
 package org.apache.curator.framework.api;
 
-import java.util.Collection;
 
 public interface Memberable<T> {
 
     /**
-     * Sets a member that is meant to be part of the ensemble.
+     * Sets one or more members that are meant to be part of the ensemble.
      * The expected format is server.[id]=[hostname]:[peer port]:[election port]:[type];[client port]
      * @param server The server to add as a member of the ensemble.
      * @return this.
      */
-    T withMember(String server);
-
-    /**
-     * Sets a collection of members member that is meant to be part of the ensemble.
-     * The expected format is server.[id]=[hostname]:[peer port]:[election port]:[type];[client port]
-     * @param servers The collection of server to set as a members of the ensemble.
-     * @return this.
-     */
-    T withMembers(Collection<String> servers);
+    T withMembers(String... server);
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/b00cecf4/curator-framework/src/main/java/org/apache/curator/framework/api/ReconfigBuilder.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/ReconfigBuilder.java b/curator-framework/src/main/java/org/apache/curator/framework/api/ReconfigBuilder.java
index 0e420a1..96ebdf7 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/ReconfigBuilder.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/ReconfigBuilder.java
@@ -19,8 +19,8 @@
 package org.apache.curator.framework.api;
 
 public interface ReconfigBuilder extends
-        Joinable<IncrementalReconfigBuilder<byte[]>>,
-        Leaveable<IncrementalReconfigBuilder<byte[]>>,
-        Memberable<NonIncrementalReconfigBuilder<byte[]>> {
+        Joinable<LeaveBackgroundStatConfigurable>,
+        Leaveable<JoinBackgroundStatConfigurable>,
+        Memberable<BackgroundStatConfigurable<byte[]>> {
 
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/b00cecf4/curator-framework/src/main/java/org/apache/curator/framework/imps/EnsembleServersAndConfig.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/EnsembleServersAndConfig.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/EnsembleServersAndConfig.java
new file mode 100644
index 0000000..df78aa7
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/EnsembleServersAndConfig.java
@@ -0,0 +1,52 @@
+/**
+ * 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.curator.framework.imps;
+
+import java.util.Collections;
+import java.util.List;
+
+class EnsembleServersAndConfig {
+    private final List<String> joiningServers;
+    private final List<String> leavingServers;
+    private final List<String> members;
+    private final long config;
+
+    EnsembleServersAndConfig(List<String> joiningServers, List<String> leavingServers, List<String> members, long config) {
+        this.joiningServers = joiningServers.isEmpty() ? null : Collections.unmodifiableList(joiningServers);
+        this.leavingServers = leavingServers.isEmpty() ? null : Collections.unmodifiableList(leavingServers);
+        this.members = members.isEmpty() ? null : Collections.unmodifiableList(members);
+        this.config = config;
+    }
+
+    public List<String> getJoiningServers() {
+        return joiningServers;
+    }
+
+    public List<String> getLeavingServers() {
+        return leavingServers;
+    }
+
+    public List<String> getMembers() {
+        return members;
+    }
+
+    public long getConfig() {
+        return config;
+    }
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/b00cecf4/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
index a56894d..54b1862 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
@@ -18,63 +18,170 @@
  */
 package org.apache.curator.framework.imps;
 
+import org.apache.curator.RetryLoop;
+import org.apache.curator.TimeTrace;
+import org.apache.curator.framework.api.BackgroundCallback;
+import org.apache.curator.framework.api.BackgroundStatable;
+import org.apache.curator.framework.api.CuratorEvent;
+import org.apache.curator.framework.api.CuratorEventType;
 import org.apache.curator.framework.api.CuratorWatcher;
+import org.apache.curator.framework.api.Ensembleable;
 import org.apache.curator.framework.api.GetConfigBuilder;
 import org.apache.zookeeper.AsyncCallback;
 import org.apache.zookeeper.Watcher;
 import org.apache.zookeeper.data.Stat;
 
-public class GetConfigBuilderImpl implements GetConfigBuilder {
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executor;
+
+public class GetConfigBuilderImpl implements GetConfigBuilder, BackgroundOperation<Void> {
 
     private final CuratorFrameworkImpl client;
-    private boolean watched;
-    private Watcher watcher;
+
+    private Backgrounding backgrounding;
+    private Watching watching;
+    private Stat stat;
 
     public GetConfigBuilderImpl(CuratorFrameworkImpl client) {
         this.client = client;
+        backgrounding = new Backgrounding();
+        watching = new Watching();
     }
 
     @Override
-    public Void usingDataCallback(AsyncCallback.DataCallback callback, Object ctx) {
-        try {
-            if (watcher != null) {
-                client.getZooKeeper().getConfig(watcher, callback, ctx);
-            } else {
-                client.getZooKeeper().getConfig(watched, callback, ctx);
-            }
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-        return null;
+    public Ensembleable<byte[]> storingStatIn(Stat stat) {
+        this.stat = new Stat();
+        return this;
+    }
+
+    @Override
+    public BackgroundStatable<Ensembleable<byte[]>> watched() {
+        watching = new Watching(true);
+        return this;
+    }
+
+    @Override
+    public GetConfigBuilder usingWatcher(Watcher watcher) {
+        watching = new Watching(client, watcher);
+        return this;
+    }
+
+    @Override
+    public GetConfigBuilder usingWatcher(final CuratorWatcher watcher) {
+        watching = new Watching(client, watcher);
+        return this;
+    }
+
+    @Override
+    public Ensembleable<byte[]> inBackground() {
+        backgrounding = new Backgrounding();
+        return this;
+    }
+
+    @Override
+    public Ensembleable<byte[]> inBackground(Object context) {
+        backgrounding = new Backgrounding(context);
+        return this;
+    }
+
+    @Override
+    public Ensembleable<byte[]> inBackground(BackgroundCallback callback) {
+        backgrounding = new Backgrounding(callback);
+        return this;
     }
 
     @Override
-    public byte[] storingStatIn(Stat stat) {
+    public Ensembleable<byte[]> inBackground(BackgroundCallback callback, Object context) {
+        backgrounding = new Backgrounding(callback, context);
+        return this;
+    }
+
+    @Override
+    public Ensembleable<byte[]> inBackground(BackgroundCallback callback, Executor executor) {
+        backgrounding = new Backgrounding(callback, executor);
+        return this;
+    }
+
+    @Override
+    public Ensembleable<byte[]> inBackground(BackgroundCallback callback, Object context, Executor executor) {
+        backgrounding = new Backgrounding(client, callback, context, executor);
+        return this;
+    }
+
+    private void performBackgroundOperation() {
         try {
-            if (watcher != null) {
-               return client.getZooKeeper().getConfig(watcher, stat);
-            } else {
-                return client.getZooKeeper().getConfig(watched, stat);
-            }
+            client.getZooKeeper().getConfig(watching.getWatcher(),
+                    new AsyncCallback.DataCallback() {
+                        @Override
+                        public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat) {
+                            try {
+                                CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.GET_CONFIG,
+                                        rc, path, null, ctx, stat, data, null, null, null);
+                                backgrounding.getCallback().processResult(client, event);
+                            } catch (Exception e) {
+                                throw new RuntimeException(e);
+                            }
+                        }
+                    }, backgrounding.getContext());
         } catch (Exception e) {
             throw new RuntimeException(e);
         }
     }
 
     @Override
-    public GetConfigBuilder watched() {
-        this.watched = true;
-        return this;
+    public byte[] forEnsemble() throws Exception {
+        byte[] responseData = null;
+        if ( backgrounding.inBackground() )
+        {
+            client.processBackgroundOperation(new OperationAndData<Void>(this, null, backgrounding.getCallback(), null, backgrounding.getContext()), null);
+        }
+        else
+        {
+            responseData = configInForeground();
+        }
+        return responseData;
     }
 
     @Override
-    public GetConfigBuilder usingWatcher(Watcher watcher) {
-        this.watcher = watcher;
-        return null;
+    public void performBackgroundOperation(final OperationAndData<Void> operationAndData) throws Exception
+    {
+        final TimeTrace   trace = client.getZookeeperClient().startTracer("GetDataBuilderImpl-Background");
+        AsyncCallback.DataCallback callback = new AsyncCallback.DataCallback()
+        {
+            @Override
+            public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat)
+            {
+                trace.commit();
+                CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.GET_CONFIG, rc, path, null, ctx, stat, data, null, null, null);
+                client.processBackgroundOperation(operationAndData, event);
+            }
+        };
+        if ( watching.isWatched() )
+        {
+            client.getZooKeeper().getConfig(watching.getWatcher(), callback, backgrounding.getContext());
+        }
+        else
+        {
+            client.getZooKeeper().getConfig(false, callback, backgrounding.getContext());
+        }
     }
 
-    @Override
-    public GetConfigBuilder usingWatcher(final CuratorWatcher watcher) {
-        throw new UnsupportedOperationException("GetConfigBuilder doesn't support CuratorWatcher, please use Watcher instead.");
+
+    private byte[] configInForeground() throws Exception {
+        TimeTrace   trace = client.getZookeeperClient().startTracer("GetConfigBuilderImpl-Foreground");
+        try {
+            return RetryLoop.callWithRetry
+                    (
+                            client.getZookeeperClient(),
+                            new Callable<byte[]>() {
+                                @Override
+                                public byte[] call() throws Exception {
+                                    return client.getZooKeeper().getConfig(watching.getWatcher(), stat);
+                                }
+                            }
+                    );
+        } finally {
+            trace.commit();
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/b00cecf4/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java
index 7b39be6..7a33297 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java
@@ -18,165 +18,199 @@
  */
 package org.apache.curator.framework.imps;
 
-import org.apache.curator.framework.api.AsyncReconfigurable;
-import org.apache.curator.framework.api.IncrementalReconfigBuilder;
-import org.apache.curator.framework.api.NonIncrementalReconfigBuilder;
+import org.apache.curator.RetryLoop;
+import org.apache.curator.TimeTrace;
+import org.apache.curator.framework.api.BackgroundCallback;
+import org.apache.curator.framework.api.BackgroundStatConfigurable;
+import org.apache.curator.framework.api.Configurable;
+import org.apache.curator.framework.api.CuratorEvent;
+import org.apache.curator.framework.api.CuratorEventType;
+import org.apache.curator.framework.api.Ensembleable;
+import org.apache.curator.framework.api.JoinBackgroundStatConfigurable;
+import org.apache.curator.framework.api.LeaveBackgroundStatConfigurable;
 import org.apache.curator.framework.api.ReconfigBuilder;
-import org.apache.curator.framework.api.SyncReconfigurable;
-import org.apache.zookeeper.AsyncCallback.DataCallback;
+import org.apache.zookeeper.AsyncCallback;
 import org.apache.zookeeper.data.Stat;
 
-import java.util.Collection;
+import java.util.Arrays;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executor;
 
 public class ReconfigBuilderImpl implements ReconfigBuilder {
 
     private final CuratorFrameworkImpl client;
 
-    private static class IncrementalReconfigBuilderImpl<T> implements IncrementalReconfigBuilder<T> {
+    public ReconfigBuilderImpl(CuratorFrameworkImpl client) {
+        this.client = client;
+    }
 
-        private final CuratorFrameworkImpl client;
-        private List<String> joiningServers = new LinkedList<String>();
-        private List<String> leavingServers = new LinkedList<String>();
+    private static class ReconfigBuilderBase implements BackgroundStatConfigurable<byte[]>, Ensembleable<byte[]>, BackgroundOperation<EnsembleServersAndConfig> {
 
-        private IncrementalReconfigBuilderImpl(CuratorFrameworkImpl client) {
+        final CuratorFrameworkImpl client;
+        final List<String> joiningServers = new LinkedList<String>();
+        final List<String> leavingServers = new LinkedList<String>();
+        final List<String> members = new LinkedList<String>();
+        Backgrounding backgrounding;
+        Stat stat;
+        long config;
+
+        private ReconfigBuilderBase(CuratorFrameworkImpl client) {
             this.client = client;
+            backgrounding = new Backgrounding();
         }
 
         @Override
-        public IncrementalReconfigBuilderImpl<T> join(String server) {
-            joiningServers.add(server);
+        public Configurable<byte[]> inBackground() {
+            backgrounding = new Backgrounding();
             return this;
         }
 
         @Override
-        public IncrementalReconfigBuilder<T> join(Collection<String> servers) {
-            joiningServers.addAll(servers);
+        public Configurable<byte[]> inBackground(Object context) {
+            backgrounding = new Backgrounding(context);
             return this;
         }
 
         @Override
-        public IncrementalReconfigBuilderImpl<T> leave(String server) {
-            leavingServers.add(server);
+        public Configurable<byte[]> inBackground(BackgroundCallback callback) {
+            backgrounding = new Backgrounding(callback);
             return this;
         }
 
         @Override
-        public IncrementalReconfigBuilder<T> leave(Collection<String> servers) {
-            leavingServers.addAll(servers);
+        public Configurable<byte[]> inBackground(BackgroundCallback callback, Object context) {
+            backgrounding = new Backgrounding(callback, context);
             return this;
         }
 
         @Override
-        public SyncReconfigurable storingStatIn(final Stat stat) {
-            return new SyncReconfigurable() {
-                @Override
-                public byte[] fromConfig(long config) throws Exception {
-                    return client
-                            .getZooKeeper()
-                            .reconfig(joiningServers.isEmpty() ? null : joiningServers,
-                                      leavingServers.isEmpty() ? null : leavingServers,
-                                      null,
-                                      config, stat);
-                }
-            };
+        public Configurable<byte[]> inBackground(BackgroundCallback callback, Executor executor) {
+            backgrounding = new Backgrounding(callback, executor);
+            return this;
         }
 
         @Override
-        public AsyncReconfigurable usingDataCallback(final DataCallback callback, final Object ctx) {
-            return new AsyncReconfigurable() {
-                @Override
-                public void fromConfig(long config) throws Exception {
-                     client.getZooKeeper()
-                           .reconfig(joiningServers.isEmpty() ? null : joiningServers,
-                                     leavingServers.isEmpty() ? null : leavingServers,
-                                     null,
-                                     config, callback, ctx);
-                }
-            };
-        }
-    }
-
-    private static class NonIncrementalReconfigBuilderImpl<T> implements NonIncrementalReconfigBuilder<T> {
-
-        private final CuratorFrameworkImpl client;
-        private List<String> newMembers = new LinkedList<String>();
-
-        private NonIncrementalReconfigBuilderImpl(CuratorFrameworkImpl client) {
-            this.client = client;
-        }
-
-        private NonIncrementalReconfigBuilderImpl(CuratorFrameworkImpl client, List<String> newMembers) {
-            this.client = client;
-            this.newMembers = newMembers;
+        public Configurable<byte[]> inBackground(BackgroundCallback callback, Object context, Executor executor) {
+            backgrounding = new Backgrounding(client, callback, context, executor);
+            return this;
         }
 
         @Override
-        public NonIncrementalReconfigBuilder<T> withMember(String server) {
-            newMembers.add(server);
+        public Ensembleable<byte[]> fromConfig(long config) throws Exception {
+            this.config = config;
             return this;
         }
 
         @Override
-        public NonIncrementalReconfigBuilder<T> withMembers(Collection servers) {
-            newMembers.addAll(servers);
+        public Configurable<byte[]> storingStatIn(Stat stat) {
+            this.stat = stat;
             return this;
         }
 
         @Override
-        public SyncReconfigurable storingStatIn(final Stat stat) {
-            return new SyncReconfigurable() {
-                @Override
-                public byte[] fromConfig(long config) throws Exception {
-                    return client.getZooKeeper().reconfig(null, null, newMembers, config, stat);
-                }
-            };
+        public byte[] forEnsemble() throws Exception {
+            if (backgrounding.inBackground()) {
+                client.processBackgroundOperation(new OperationAndData<EnsembleServersAndConfig>(this,
+                        new EnsembleServersAndConfig(joiningServers, leavingServers, members, config),
+                        backgrounding.getCallback(), null, backgrounding.getContext()), null);
+                return new byte[0];
+            } else {
+                return ensembleInForeground();
+            }
+        }
+
+        private byte[] ensembleInForeground() throws Exception {
+            TimeTrace trace = client.getZookeeperClient().startTracer("ReconfigBuilderImpl-Foreground");
+            byte[] responseData = RetryLoop.callWithRetry
+                    (
+                            client.getZookeeperClient(),
+                            new Callable<byte[]>() {
+                                @Override
+                                public byte[] call() throws Exception {
+                                    return client.getZooKeeper().reconfig(
+                                            joiningServers.isEmpty() ? null : joiningServers,
+                                            leavingServers.isEmpty() ? null : leavingServers,
+                                            members.isEmpty() ? null : members,
+                                            config,
+                                            stat
+                                    );
+                                }
+                            }
+                    );
+            trace.commit();
+            return responseData;
         }
 
         @Override
-        public AsyncReconfigurable usingDataCallback(final DataCallback callback, final Object ctx) {
-            return new AsyncReconfigurable() {
+        public void performBackgroundOperation(final OperationAndData<EnsembleServersAndConfig> operationAndData) throws Exception {
+            final TimeTrace trace = client.getZookeeperClient().startTracer("ReconfigBuilderImpl-Background");
+            AsyncCallback.DataCallback callback = new AsyncCallback.DataCallback() {
                 @Override
-                public void fromConfig(long config) throws Exception {
-                    client.getZooKeeper().reconfig(null, null, newMembers, config, callback, ctx);
+                public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat) {
+                    trace.commit();
+                    CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.RECONFIG, rc, path, null, ctx, stat, data, null, null, null);
+                    client.processBackgroundOperation(operationAndData, event);
                 }
             };
+            client.getZooKeeper().reconfig(
+                    operationAndData.getData().getJoiningServers(),
+                    operationAndData.getData().getLeavingServers(),
+                    operationAndData.getData().getMembers(),
+                    operationAndData.getData().getConfig(),
+                    callback,
+                    operationAndData.getContext()
+            );
+
         }
     }
 
+    private static class JoinReconfigBuilder extends ReconfigBuilderBase implements JoinBackgroundStatConfigurable {
 
-    public ReconfigBuilderImpl(CuratorFrameworkImpl client) {
-        this.client = client;
-    }
+        private JoinReconfigBuilder(CuratorFrameworkImpl client) {
+            super(client);
+        }
 
-    @Override
-    public IncrementalReconfigBuilder<byte[]> join(String server) {
-        return new IncrementalReconfigBuilderImpl(client).join(server);
+        @Override
+        public BackgroundStatConfigurable<byte[]> joining(String... servers) {
+            joiningServers.addAll(Arrays.asList(servers));
+            return this;
+        }
     }
 
-    @Override
-    public IncrementalReconfigBuilder<byte[]> join(Collection<String> servers) {
-        return new IncrementalReconfigBuilderImpl(client).join(servers);
-    }
+    private static class LeaveReconfigBuilder extends ReconfigBuilderBase implements LeaveBackgroundStatConfigurable {
 
-    @Override
-    public IncrementalReconfigBuilder<byte[]> leave(String server) {
-        return new IncrementalReconfigBuilderImpl(client).leave(server);
+        private LeaveReconfigBuilder(CuratorFrameworkImpl client) {
+            super(client);
+        }
+
+        @Override
+        public BackgroundStatConfigurable<byte[]> leaving(String... servers) {
+            leavingServers.addAll(Arrays.asList(servers));
+            return this;
+        }
     }
 
+
     @Override
-    public IncrementalReconfigBuilder<byte[]> leave(Collection<String> servers) {
-        return new IncrementalReconfigBuilderImpl(client).leave(servers);
+    public LeaveBackgroundStatConfigurable joining(String... servers) {
+        LeaveReconfigBuilder builder = new LeaveReconfigBuilder(client);
+        builder.joiningServers.addAll(Arrays.asList(servers));
+        return builder;
     }
 
     @Override
-    public NonIncrementalReconfigBuilder<byte[]> withMember(String server) {
-        return new NonIncrementalReconfigBuilderImpl(client).withMember(server);
+    public JoinBackgroundStatConfigurable leaving(String... servers) {
+        JoinReconfigBuilder builder = new JoinReconfigBuilder(client);
+        builder.leavingServers.addAll(Arrays.asList(servers));
+        return builder;
     }
 
     @Override
-    public NonIncrementalReconfigBuilder<byte[]> withMembers(Collection<String> servers) {
-        return new NonIncrementalReconfigBuilderImpl<byte[]>(client).withMembers(servers);
+    public BackgroundStatConfigurable<byte[]> withMembers(String... servers) {
+        ReconfigBuilderBase builder = new ReconfigBuilderBase(client);
+        builder.members.addAll(Arrays.asList(servers));
+        return builder;
     }
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/b00cecf4/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java
index 6918825..e8896ae 100644
--- a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java
@@ -20,16 +20,17 @@ package org.apache.curator.framework.imps;
 
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.framework.api.BackgroundCallback;
+import org.apache.curator.framework.api.CuratorEvent;
 import org.apache.curator.retry.RetryOneTime;
 import org.apache.curator.test.InstanceSpec;
 import org.apache.curator.test.TestingCluster;
-import org.apache.zookeeper.AsyncCallback;
 import org.apache.zookeeper.data.Stat;
 import org.apache.zookeeper.server.quorum.flexible.QuorumMaj;
 import org.apache.zookeeper.server.quorum.flexible.QuorumVerifier;
 import org.testng.Assert;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 import java.io.IOException;
@@ -41,15 +42,15 @@ import java.util.concurrent.atomic.AtomicReference;
 
 public class TestReconfiguration {
 
-    static TestingCluster cluster;
+    TestingCluster cluster;
 
-    @BeforeClass
+    @BeforeMethod
     public void setup() throws Exception {
         cluster = new TestingCluster(5);
         cluster.start();
     }
 
-    @AfterClass
+    @AfterMethod
     public void tearDown() throws IOException {
         cluster.close();
     }
@@ -61,28 +62,28 @@ public class TestReconfiguration {
         client.blockUntilConnected();
         try {
             Stat stat = new Stat();
-            byte[] bytes = client.getConfig().storingStatIn(stat);
+            byte[] bytes = client.getConfig().storingStatIn(stat).forEnsemble();
             Assert.assertNotNull(bytes);
             QuorumVerifier qv = getQuorumVerifier(bytes);
-            Assert.assertEquals(5, qv.getAllMembers().size());
+            Assert.assertEquals(qv.getAllMembers().size(), 5);
             String server1 = getServerString(qv, cluster, 1L);
             String server2 = getServerString(qv, cluster, 2L);
 
             //Remove Servers
-            bytes = client.reconfig().leave("1").storingStatIn(stat).fromConfig(qv.getVersion());
+            bytes = client.reconfig().leaving("1").storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
             qv = getQuorumVerifier(bytes);
-            Assert.assertEquals(4, qv.getAllMembers().size());
-            bytes = client.reconfig().leave("2").storingStatIn(stat).fromConfig(qv.getVersion());
+            Assert.assertEquals(qv.getAllMembers().size(), 4);
+            bytes = client.reconfig().leaving("2").storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
             qv = getQuorumVerifier(bytes);
-            Assert.assertEquals(3, qv.getAllMembers().size());
+            Assert.assertEquals(qv.getAllMembers().size(), 3);
 
             //Add Servers
-            bytes = client.reconfig().join("server.1=" + server1).storingStatIn(stat).fromConfig(qv.getVersion());
+            bytes = client.reconfig().joining("server.1=" + server1).storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
             qv = getQuorumVerifier(bytes);
-            Assert.assertEquals(4, qv.getAllMembers().size());
-            bytes = client.reconfig().join("server.2=" + server2).storingStatIn(stat).fromConfig(qv.getVersion());
+            Assert.assertEquals(qv.getAllMembers().size(), 4);
+            bytes = client.reconfig().joining("server.2=" + server2).storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
             qv = getQuorumVerifier(bytes);
-            Assert.assertEquals(5, qv.getAllMembers().size());
+            Assert.assertEquals(qv.getAllMembers().size(), 5);
         } finally {
             client.close();
         }
@@ -95,47 +96,48 @@ public class TestReconfiguration {
         client.blockUntilConnected();
         try {
             final AtomicReference<byte[]> bytes = new AtomicReference<byte[]>();
-            final AsyncCallback.DataCallback callback = new AsyncCallback.DataCallback() {
+            final BackgroundCallback callback = new BackgroundCallback() {
                 @Override
-                public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat) {
-                    bytes.set(data);
-                    ((CountDownLatch)ctx).countDown();
+                public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
+                    bytes.set(event.getData());
+                    ((CountDownLatch)event.getContext()).countDown();
                 }
+
             };
 
             CountDownLatch latch = new CountDownLatch(1);
-            client.getConfig().usingDataCallback(callback, latch);
+            client.getConfig().inBackground(callback, latch).forEnsemble();
             latch.await(5, TimeUnit.SECONDS);
             Assert.assertNotNull(bytes.get());
             QuorumVerifier qv = getQuorumVerifier(bytes.get());
-            Assert.assertEquals(5, qv.getAllMembers().size());
+            Assert.assertEquals(qv.getAllMembers().size(), 5);
             String server1 = getServerString(qv, cluster, 1L);
             String server2 = getServerString(qv, cluster, 2L);
 
 
             //Remove Servers
             latch = new CountDownLatch(1);
-            client.reconfig().leave("1").usingDataCallback(callback, latch).fromConfig(qv.getVersion());
+            client.reconfig().leaving("1").inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
             latch.await(5, TimeUnit.SECONDS);
             qv = getQuorumVerifier(bytes.get());
-            Assert.assertEquals(4, qv.getAllMembers().size());
+            Assert.assertEquals(qv.getAllMembers().size(), 4);
             latch = new CountDownLatch(1);
-            client.reconfig().leave("2").usingDataCallback(callback, latch).fromConfig(qv.getVersion());
+            client.reconfig().leaving("2").inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
             latch.await(5, TimeUnit.SECONDS);
             qv = getQuorumVerifier(bytes.get());
-            Assert.assertEquals(3, qv.getAllMembers().size());
+            Assert.assertEquals(qv.getAllMembers().size(), 3);
 
             //Add Servers
             latch = new CountDownLatch(1);
-            client.reconfig().join("server.1=" + server1).usingDataCallback(callback, latch).fromConfig(qv.getVersion());
+            client.reconfig().joining("server.1=" + server1).inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
             latch.await(5, TimeUnit.SECONDS);
             qv = getQuorumVerifier(bytes.get());
-            Assert.assertEquals(4, qv.getAllMembers().size());
+            Assert.assertEquals(qv.getAllMembers().size(), 4);
             latch = new CountDownLatch(1);
-            client.reconfig().join("server.2=" + server2).usingDataCallback(callback, latch).fromConfig(qv.getVersion());
+            client.reconfig().joining("server.2=" + server2).inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
             latch.await(5, TimeUnit.SECONDS);
             qv = getQuorumVerifier(bytes.get());
-            Assert.assertEquals(5, qv.getAllMembers().size());
+            Assert.assertEquals(qv.getAllMembers().size(), 5);
         } finally {
             client.close();
         }
@@ -148,10 +150,10 @@ public class TestReconfiguration {
         client.blockUntilConnected();
         try {
             Stat stat = new Stat();
-            byte[] bytes = client.getConfig().storingStatIn(stat);
+            byte[] bytes = client.getConfig().storingStatIn(stat).forEnsemble();
             Assert.assertNotNull(bytes);
             QuorumVerifier qv = getQuorumVerifier(bytes);
-            Assert.assertEquals(5, qv.getAllMembers().size());
+            Assert.assertEquals(qv.getAllMembers().size(), 5);
             String server1 = getServerString(qv, cluster, 1L);
             String server2 = getServerString(qv, cluster, 2L);
             String server3 = getServerString(qv, cluster, 3L);
@@ -160,40 +162,40 @@ public class TestReconfiguration {
 
             //Remove Servers
             bytes = client.reconfig()
-                    .withMember("server.2="+server2)
-                    .withMember("server.3="+server3)
-                    .withMember("server.4="+server4)
-                    .withMember("server.5="+server5)
-                    .storingStatIn(stat).fromConfig(qv.getVersion());
+                    .withMembers("server.2=" + server2,
+                            "server.3=" + server3,
+                            "server.4=" + server4,
+                            "server.5=" + server5)
+                    .storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
             qv = getQuorumVerifier(bytes);
-            Assert.assertEquals(4, qv.getAllMembers().size());
+            Assert.assertEquals(qv.getAllMembers().size(), 4);
             bytes = client.reconfig()
-                    .withMember("server.3=" + server3)
-                    .withMember("server.4=" + server4)
-                    .withMember("server.5=" + server5)
-                    .storingStatIn(stat).fromConfig(qv.getVersion());
+                    .withMembers("server.3=" + server3,
+                            "server.4=" + server4,
+                            "server.5=" + server5)
+                    .storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
 
             qv = getQuorumVerifier(bytes);
-            Assert.assertEquals(3, qv.getAllMembers().size());
+            Assert.assertEquals(qv.getAllMembers().size(), 3);
 
             //Add Servers
             bytes = client.reconfig()
-                    .withMember("server.1="+server1)
-                    .withMember("server.3=" + server3)
-                    .withMember("server.4="+server4)
-                    .withMember("server.5="+server5)
-                    .storingStatIn(stat).fromConfig(qv.getVersion());
+                    .withMembers("server.1=" + server1,
+                            "server.3=" + server3,
+                            "server.4=" + server4,
+                            "server.5=" + server5)
+                    .storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
             qv = getQuorumVerifier(bytes);
-            Assert.assertEquals(4, qv.getAllMembers().size());
+            Assert.assertEquals(qv.getAllMembers().size(), 4);
             bytes = client.reconfig()
-                    .withMember("server.1="+server1)
-                    .withMember("server.2="+server2)
-                    .withMember("server.3=" + server3)
-                    .withMember("server.4="+server4)
-                    .withMember("server.5="+server5)
-                    .storingStatIn(stat).fromConfig(qv.getVersion());
+                    .withMembers("server.1=" + server1,
+                            "server.2=" + server2,
+                            "server.3=" + server3,
+                            "server.4=" + server4,
+                            "server.5=" + server5)
+                    .storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
             qv = getQuorumVerifier(bytes);
-            Assert.assertEquals(5, qv.getAllMembers().size());
+            Assert.assertEquals(qv.getAllMembers().size(), 5);
         } finally {
             client.close();
         }
@@ -206,70 +208,70 @@ public class TestReconfiguration {
         client.blockUntilConnected();
         try {
             final AtomicReference<byte[]> bytes = new AtomicReference<byte[]>();
-            final AsyncCallback.DataCallback callback = new AsyncCallback.DataCallback() {
+            final BackgroundCallback callback = new BackgroundCallback() {
                 @Override
-                public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat) {
-                    bytes.set(data);
-                    ((CountDownLatch)ctx).countDown();
+                public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
+                    bytes.set(event.getData());
+                    ((CountDownLatch)event.getContext()).countDown();
                 }
+
             };
 
             CountDownLatch latch = new CountDownLatch(1);
-            client.getConfig().usingDataCallback(callback, latch);
+            client.getConfig().inBackground(callback, latch).forEnsemble();
             latch.await(5, TimeUnit.SECONDS);
             Assert.assertNotNull(bytes.get());
             QuorumVerifier qv = getQuorumVerifier(bytes.get());
-            Assert.assertEquals(5, qv.getAllMembers().size());
+            Assert.assertEquals(qv.getAllMembers().size(), 5);
             String server1 = getServerString(qv, cluster, 1L);
             String server2 = getServerString(qv, cluster, 2L);
             String server3 = getServerString(qv, cluster, 3L);
             String server4 = getServerString(qv, cluster, 4L);
             String server5 = getServerString(qv, cluster, 5L);
 
-
             //Remove Servers
             latch = new CountDownLatch(1);
             client.reconfig()
-                    .withMember("server.2=" + server2)
-                    .withMember("server.3="+server3)
-                    .withMember("server.4="+server4)
-                    .withMember("server.5="+server5)
-            .usingDataCallback(callback, latch).fromConfig(qv.getVersion());
+                    .withMembers("server.2=" + server2,
+                            "server.3=" + server3,
+                            "server.4=" + server4,
+                            "server.5=" + server5)
+            .inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
             latch.await(5, TimeUnit.SECONDS);
             qv = getQuorumVerifier(bytes.get());
-            Assert.assertEquals(4, qv.getAllMembers().size());
+            Assert.assertEquals(qv.getAllMembers().size(), 4);
             latch = new CountDownLatch(1);
             client.reconfig()
-                    .withMember("server.3="+server3)
-                    .withMember("server.4=" + server4)
-                    .withMember("server.5=" + server5)
-                    .usingDataCallback(callback, latch).fromConfig(qv.getVersion());
+                    .withMembers("server.3=" + server3,
+                            "server.4=" + server4,
+                            "server.5=" + server5)
+                    .inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
             latch.await(5, TimeUnit.SECONDS);
             qv = getQuorumVerifier(bytes.get());
-            Assert.assertEquals(3, qv.getAllMembers().size());
+            Assert.assertEquals(qv.getAllMembers().size(), 3);
 
             //Add Servers
             latch = new CountDownLatch(1);
             client.reconfig()
-                    .withMember("server.1="+server1)
-                    .withMember("server.3=" + server3)
-                    .withMember("server.4=" + server4)
-                    .withMember("server.5=" + server5)
-                    .usingDataCallback(callback, latch).fromConfig(qv.getVersion());
+                    .withMembers("server.1=" + server1,
+                            "server.3=" + server3,
+                            "server.4=" + server4,
+                            "server.5=" + server5)
+                    .inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
             latch.await(5, TimeUnit.SECONDS);
             qv = getQuorumVerifier(bytes.get());
-            Assert.assertEquals(4, qv.getAllMembers().size());
+            Assert.assertEquals(qv.getAllMembers().size(), 4);
             latch = new CountDownLatch(1);
             client.reconfig()
-                    .withMember("server.1="+server1)
-                    .withMember("server.2="+server2)
-                    .withMember("server.3="+server3)
-                    .withMember("server.4=" + server4)
-                    .withMember("server.5=" + server5)
-                    .usingDataCallback(callback, latch).fromConfig(qv.getVersion());
+                    .withMembers("server.1=" + server1,
+                            "server.2=" + server2,
+                            "server.3=" + server3,
+                            "server.4=" + server4,
+                            "server.5=" + server5)
+                    .inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
             latch.await(5, TimeUnit.SECONDS);
             qv = getQuorumVerifier(bytes.get());
-            Assert.assertEquals(5, qv.getAllMembers().size());
+            Assert.assertEquals(qv.getAllMembers().size(), 5);
         } finally {
             client.close();
         }

http://git-wip-us.apache.org/repos/asf/curator/blob/b00cecf4/curator-test/src/main/java/org/apache/curator/test/InstanceSpec.java
----------------------------------------------------------------------
diff --git a/curator-test/src/main/java/org/apache/curator/test/InstanceSpec.java b/curator-test/src/main/java/org/apache/curator/test/InstanceSpec.java
index b39a949..6d495df 100644
--- a/curator-test/src/main/java/org/apache/curator/test/InstanceSpec.java
+++ b/curator-test/src/main/java/org/apache/curator/test/InstanceSpec.java
@@ -70,6 +70,10 @@ public class InstanceSpec
     private final int tickTime;
     private final int maxClientCnxns;
 
+    public static void reset() {
+        nextServerId.set(1);
+    }
+
     public static InstanceSpec newInstanceSpec()
     {
         return new InstanceSpec(null, -1, -1, -1, true, -1, -1, -1);

http://git-wip-us.apache.org/repos/asf/curator/blob/b00cecf4/curator-test/src/main/java/org/apache/curator/test/TestingCluster.java
----------------------------------------------------------------------
diff --git a/curator-test/src/main/java/org/apache/curator/test/TestingCluster.java b/curator-test/src/main/java/org/apache/curator/test/TestingCluster.java
index cd86b72..f6bdbd8 100644
--- a/curator-test/src/main/java/org/apache/curator/test/TestingCluster.java
+++ b/curator-test/src/main/java/org/apache/curator/test/TestingCluster.java
@@ -249,6 +249,7 @@ public class TestingCluster implements Closeable
 
     private static Map<InstanceSpec, Collection<InstanceSpec>> makeSpecs(int instanceQty)
     {
+        InstanceSpec.reset();
         ImmutableList.Builder<InstanceSpec> builder = ImmutableList.builder();
         for ( int i = 0; i < instanceQty; ++i )
         {


[10/27] curator git commit: Merge branch 'CURATOR-160' into CURATOR-3.0

Posted by dr...@apache.org.
Merge branch 'CURATOR-160' into CURATOR-3.0


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/760473d7
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/760473d7
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/760473d7

Branch: refs/heads/CURATOR-215
Commit: 760473d762a8923e8b4266f77095583707037454
Parents: 143044b dbdcf2f
Author: Scott Blum <dr...@apache.org>
Authored: Wed Aug 12 17:27:31 2015 -0400
Committer: Scott Blum <dr...@apache.org>
Committed: Wed Aug 12 17:27:31 2015 -0400

----------------------------------------------------------------------
 .../main/java/org/apache/curator/RetryLoop.java |   3 +-
 .../curator/ensemble/EnsembleListener.java      |  24 ++
 .../dynamic/DynamicEnsembleProvider.java        |  61 +++
 .../curator/framework/CuratorFramework.java     |  12 +
 .../framework/api/AsyncReconfigurable.java      |  29 ++
 .../api/BackgroundStatConfigEnsembleable.java   |  24 ++
 .../api/BackgroundStatEnsembleable.java         |  24 ++
 .../framework/api/BackgroundStatable.java       |  24 ++
 .../curator/framework/api/Configurable.java     |  29 ++
 .../curator/framework/api/CuratorEventType.java |  10 +
 .../curator/framework/api/DataCallbackable.java |  32 ++
 .../curator/framework/api/Ensembleable.java     |  24 ++
 .../curator/framework/api/GetConfigBuilder.java |  27 ++
 .../api/IncrementalReconfigBuilder.java         |  33 ++
 .../JoinBackgroundStatConfigEnsembleable.java   |  30 ++
 .../apache/curator/framework/api/Joinable.java  |  31 ++
 .../LeaveBackgroundStatConfigEnsembleable.java  |  30 ++
 .../apache/curator/framework/api/Leaveable.java |  30 ++
 .../curator/framework/api/Memberable.java       |  31 ++
 .../api/NonIncrementalReconfigBuilder.java      |  32 ++
 .../curator/framework/api/ReconfigBuilder.java  |  26 ++
 .../framework/api/SyncReconfigurable.java       |  30 ++
 .../framework/imps/CuratorFrameworkImpl.java    |  10 +
 .../imps/EnsembleServersAndConfig.java          |  52 +++
 .../curator/framework/imps/EnsembleTracker.java | 167 ++++++++
 .../framework/imps/GetConfigBuilderImpl.java    | 187 +++++++++
 .../framework/imps/ReconfigBuilderImpl.java     | 216 +++++++++++
 .../framework/imps/TestReconfiguration.java     | 388 +++++++++++++++++++
 .../org/apache/curator/test/InstanceSpec.java   |   4 +
 .../curator/test/QuorumConfigBuilder.java       |   2 +-
 .../org/apache/curator/test/TestingCluster.java |   1 +
 31 files changed, 1621 insertions(+), 2 deletions(-)
----------------------------------------------------------------------



[23/27] curator git commit: wip

Posted by dr...@apache.org.
wip


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

Branch: refs/heads/CURATOR-215
Commit: bf0649aff671812919fe8f2d6e26efb164aaae16
Parents: 7f27225
Author: randgalt <ra...@apache.org>
Authored: Tue May 12 14:10:34 2015 -0500
Committer: Scott Blum <dr...@apache.org>
Committed: Wed Aug 12 17:29:42 2015 -0400

----------------------------------------------------------------------
 .../curator/framework/imps/CuratorMultiTransactionImpl.java       | 3 ---
 1 file changed, 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/bf0649af/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorMultiTransactionImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorMultiTransactionImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorMultiTransactionImpl.java
index 6881fc2..577b0d6 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorMultiTransactionImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorMultiTransactionImpl.java
@@ -38,9 +38,6 @@ import java.util.List;
 import java.util.concurrent.Callable;
 import java.util.concurrent.Executor;
 
-/**
- * @deprecated Use {@link CuratorFramework#transaction()}
- */
 public class CuratorMultiTransactionImpl implements
     CuratorMultiTransaction,
     CuratorMultiTransactionMain,


[25/27] curator git commit: TestCompressionInTransactionNew

Posted by dr...@apache.org.
TestCompressionInTransactionNew


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/847dfbea
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/847dfbea
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/847dfbea

Branch: refs/heads/CURATOR-215
Commit: 847dfbea580c9958499978749fe42e5cb0c8e7a4
Parents: 4275b3c
Author: randgalt <ra...@apache.org>
Authored: Tue May 12 16:04:16 2015 -0500
Committer: Scott Blum <dr...@apache.org>
Committed: Wed Aug 12 17:29:43 2015 -0400

----------------------------------------------------------------------
 .../imps/TestCompressionInTransaction.java      | 157 ------------------
 .../imps/TestCompressionInTransactionNew.java   | 162 +++++++++++++++++++
 .../imps/TestCompressionInTransactionOld.java   | 158 ++++++++++++++++++
 3 files changed, 320 insertions(+), 157 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/847dfbea/curator-framework/src/test/java/org/apache/curator/framework/imps/TestCompressionInTransaction.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestCompressionInTransaction.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestCompressionInTransaction.java
deleted file mode 100644
index c18af99..0000000
--- a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestCompressionInTransaction.java
+++ /dev/null
@@ -1,157 +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.curator.framework.imps;
-
-import org.apache.curator.test.BaseClassForTests;
-import org.apache.curator.utils.CloseableUtils;
-import org.apache.curator.framework.CuratorFramework;
-import org.apache.curator.framework.CuratorFrameworkFactory;
-import org.apache.curator.framework.api.CompressionProvider;
-import org.apache.curator.retry.RetryOneTime;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-import java.util.concurrent.atomic.AtomicInteger;
-
-public class TestCompressionInTransaction extends BaseClassForTests
-{
-    @Test
-    public void testSetData() throws Exception
-    {
-        final String path = "/a";
-        final byte[]            data = "here's a string".getBytes();
-
-        CuratorFramework        client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
-        try
-        {
-            client.start();
-
-            //Create uncompressed data in a transaction
-            client.inTransaction().create().forPath(path, data).and().commit();
-            Assert.assertEquals(data, client.getData().forPath(path));
-
-            //Create compressed data in transaction
-            client.inTransaction().setData().compressed().forPath(path, data).and().commit();
-            Assert.assertEquals(data, client.getData().decompressed().forPath(path));
-        }
-        finally
-        {
-            CloseableUtils.closeQuietly(client);
-        }
-    }
-    
-    @Test
-    public void testSetCompressedAndUncompressed() throws Exception
-    {
-        final String path1 = "/a";
-        final String path2 = "/b";
-        
-        final byte[]            data1 = "here's a string".getBytes();
-        final byte[]            data2 = "here's another string".getBytes();
-
-        CuratorFramework        client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
-        try
-        {
-            client.start();
-
-            //Create the nodes
-            client.inTransaction().create().compressed().forPath(path1).and().
-            create().forPath(path2).and().commit();
-
-            //Check they exist
-            Assert.assertNotNull(client.checkExists().forPath(path1));
-            Assert.assertNotNull(client.checkExists().forPath(path2));
-            
-            //Set the nodes, path1 compressed, path2 uncompressed.
-            client.inTransaction().setData().compressed().forPath(path1, data1).and().
-            setData().forPath(path2, data2).and().commit();
-            
-            Assert.assertNotEquals(data1, client.getData().forPath(path1));
-            Assert.assertEquals(data1, client.getData().decompressed().forPath(path1));
-      
-            Assert.assertEquals(data2, client.getData().forPath(path2));            
-        }
-        finally
-        {
-            CloseableUtils.closeQuietly(client);
-        }
-    }    
-    
-    @Test
-    public void testSimple() throws Exception
-    {
-        final String path1 = "/a";
-        final String path2 = "/a/b";
-        
-        final byte[]            data1 = "here's a string".getBytes();
-        final byte[]            data2 = "here's another string".getBytes();
-
-        CuratorFramework        client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
-        try
-        {
-            client.start();
-
-            client.inTransaction().create().compressed().forPath(path1, data1).and().
-            create().compressed().forPath(path2, data2).and().commit();
-
-            Assert.assertNotEquals(data1, client.getData().forPath(path1));
-            Assert.assertEquals(data1, client.getData().decompressed().forPath(path1));
-            
-            Assert.assertNotEquals(data2, client.getData().forPath(path2));
-            Assert.assertEquals(data2, client.getData().decompressed().forPath(path2));            
-        }
-        finally
-        {
-            CloseableUtils.closeQuietly(client);
-        }
-    }    
-    
-    /**
-     * Test the case where both uncompressed and compressed data is generated in
-     * the same transaction
-     * @throws Exception
-     */
-    @Test
-    public void testCreateCompressedAndUncompressed() throws Exception
-    {
-        final String path1 = "/a";
-        final String path2 = "/b";
-        
-        final byte[]            data1 = "here's a string".getBytes();
-        final byte[]            data2 = "here's another string".getBytes();
-
-        CuratorFramework        client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
-        try
-        {
-            client.start();
-
-            client.inTransaction().create().compressed().forPath(path1, data1).and().
-            create().forPath(path2, data2).and().commit();
-
-            Assert.assertNotEquals(data1, client.getData().forPath(path1));
-            Assert.assertEquals(data1, client.getData().decompressed().forPath(path1));
-      
-            Assert.assertEquals(data2, client.getData().forPath(path2));            
-        }
-        finally
-        {
-            CloseableUtils.closeQuietly(client);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/curator/blob/847dfbea/curator-framework/src/test/java/org/apache/curator/framework/imps/TestCompressionInTransactionNew.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestCompressionInTransactionNew.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestCompressionInTransactionNew.java
new file mode 100644
index 0000000..d302119
--- /dev/null
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestCompressionInTransactionNew.java
@@ -0,0 +1,162 @@
+/**
+ * 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.curator.framework.imps;
+
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.framework.api.transaction.CuratorOp;
+import org.apache.curator.retry.RetryOneTime;
+import org.apache.curator.test.BaseClassForTests;
+import org.apache.curator.utils.CloseableUtils;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class TestCompressionInTransactionNew extends BaseClassForTests
+{
+    @Test
+    public void testSetData() throws Exception
+    {
+        final String path = "/a";
+        final byte[]            data = "here's a string".getBytes();
+
+        CuratorFramework        client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
+        try
+        {
+            client.start();
+
+            //Create uncompressed data in a transaction
+            CuratorOp op = client.transactionOp().create().forPath(path, data);
+            client.transaction().forOperations(op);
+            Assert.assertEquals(data, client.getData().forPath(path));
+
+            //Create compressed data in transaction
+            op = client.transactionOp().setData().compressed().forPath(path, data);
+            client.transaction().forOperations(op);
+            Assert.assertEquals(data, client.getData().decompressed().forPath(path));
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }
+    
+    @Test
+    public void testSetCompressedAndUncompressed() throws Exception
+    {
+        final String path1 = "/a";
+        final String path2 = "/b";
+        
+        final byte[]            data1 = "here's a string".getBytes();
+        final byte[]            data2 = "here's another string".getBytes();
+
+        CuratorFramework        client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
+        try
+        {
+            client.start();
+
+            //Create the nodes
+            CuratorOp op1 = client.transactionOp().create().compressed().forPath(path1);
+            CuratorOp op2 = client.transactionOp().create().forPath(path2);
+            client.transaction().forOperations(op1, op2);
+
+            //Check they exist
+            Assert.assertNotNull(client.checkExists().forPath(path1));
+            Assert.assertNotNull(client.checkExists().forPath(path2));
+            
+            //Set the nodes, path1 compressed, path2 uncompressed.
+            op1 = client.transactionOp().setData().compressed().forPath(path1, data1);
+            op2 = client.transactionOp().setData().forPath(path2, data2);
+            client.transaction().forOperations(op1, op2);
+            
+            Assert.assertNotEquals(data1, client.getData().forPath(path1));
+            Assert.assertEquals(data1, client.getData().decompressed().forPath(path1));
+      
+            Assert.assertEquals(data2, client.getData().forPath(path2));            
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }    
+    
+    @Test
+    public void testSimple() throws Exception
+    {
+        final String path1 = "/a";
+        final String path2 = "/a/b";
+        
+        final byte[]            data1 = "here's a string".getBytes();
+        final byte[]            data2 = "here's another string".getBytes();
+
+        CuratorFramework        client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
+        try
+        {
+            client.start();
+
+            CuratorOp op1 = client.transactionOp().create().compressed().forPath(path1, data1);
+            CuratorOp op2 = client.transactionOp().create().compressed().forPath(path2, data2);
+
+            client.transaction().forOperations(op1, op2);
+
+            Assert.assertNotEquals(data1, client.getData().forPath(path1));
+            Assert.assertEquals(data1, client.getData().decompressed().forPath(path1));
+            
+            Assert.assertNotEquals(data2, client.getData().forPath(path2));
+            Assert.assertEquals(data2, client.getData().decompressed().forPath(path2));            
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }    
+    
+    /**
+     * Test the case where both uncompressed and compressed data is generated in
+     * the same transaction
+     * @throws Exception
+     */
+    @Test
+    public void testCreateCompressedAndUncompressed() throws Exception
+    {
+        final String path1 = "/a";
+        final String path2 = "/b";
+        
+        final byte[]            data1 = "here's a string".getBytes();
+        final byte[]            data2 = "here's another string".getBytes();
+
+        CuratorFramework        client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
+        try
+        {
+            client.start();
+
+            CuratorOp op1 = client.transactionOp().create().compressed().forPath(path1, data1);
+            CuratorOp op2 = client.transactionOp().create().forPath(path2, data2);
+            client.transaction().forOperations(op1, op2);
+
+            Assert.assertNotEquals(data1, client.getData().forPath(path1));
+            Assert.assertEquals(data1, client.getData().decompressed().forPath(path1));
+      
+            Assert.assertEquals(data2, client.getData().forPath(path2));            
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/847dfbea/curator-framework/src/test/java/org/apache/curator/framework/imps/TestCompressionInTransactionOld.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestCompressionInTransactionOld.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestCompressionInTransactionOld.java
new file mode 100644
index 0000000..ebf591b
--- /dev/null
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestCompressionInTransactionOld.java
@@ -0,0 +1,158 @@
+/**
+ * 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.curator.framework.imps;
+
+import org.apache.curator.test.BaseClassForTests;
+import org.apache.curator.utils.CloseableUtils;
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.framework.api.CompressionProvider;
+import org.apache.curator.retry.RetryOneTime;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+@SuppressWarnings("deprecation")
+public class TestCompressionInTransactionOld extends BaseClassForTests
+{
+    @Test
+    public void testSetData() throws Exception
+    {
+        final String path = "/a";
+        final byte[]            data = "here's a string".getBytes();
+
+        CuratorFramework        client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
+        try
+        {
+            client.start();
+
+            //Create uncompressed data in a transaction
+            client.inTransaction().create().forPath(path, data).and().commit();
+            Assert.assertEquals(data, client.getData().forPath(path));
+
+            //Create compressed data in transaction
+            client.inTransaction().setData().compressed().forPath(path, data).and().commit();
+            Assert.assertEquals(data, client.getData().decompressed().forPath(path));
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }
+    
+    @Test
+    public void testSetCompressedAndUncompressed() throws Exception
+    {
+        final String path1 = "/a";
+        final String path2 = "/b";
+        
+        final byte[]            data1 = "here's a string".getBytes();
+        final byte[]            data2 = "here's another string".getBytes();
+
+        CuratorFramework        client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
+        try
+        {
+            client.start();
+
+            //Create the nodes
+            client.inTransaction().create().compressed().forPath(path1).and().
+            create().forPath(path2).and().commit();
+
+            //Check they exist
+            Assert.assertNotNull(client.checkExists().forPath(path1));
+            Assert.assertNotNull(client.checkExists().forPath(path2));
+            
+            //Set the nodes, path1 compressed, path2 uncompressed.
+            client.inTransaction().setData().compressed().forPath(path1, data1).and().
+            setData().forPath(path2, data2).and().commit();
+            
+            Assert.assertNotEquals(data1, client.getData().forPath(path1));
+            Assert.assertEquals(data1, client.getData().decompressed().forPath(path1));
+      
+            Assert.assertEquals(data2, client.getData().forPath(path2));            
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }    
+    
+    @Test
+    public void testSimple() throws Exception
+    {
+        final String path1 = "/a";
+        final String path2 = "/a/b";
+        
+        final byte[]            data1 = "here's a string".getBytes();
+        final byte[]            data2 = "here's another string".getBytes();
+
+        CuratorFramework        client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
+        try
+        {
+            client.start();
+
+            client.inTransaction().create().compressed().forPath(path1, data1).and().
+            create().compressed().forPath(path2, data2).and().commit();
+
+            Assert.assertNotEquals(data1, client.getData().forPath(path1));
+            Assert.assertEquals(data1, client.getData().decompressed().forPath(path1));
+            
+            Assert.assertNotEquals(data2, client.getData().forPath(path2));
+            Assert.assertEquals(data2, client.getData().decompressed().forPath(path2));            
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }    
+    
+    /**
+     * Test the case where both uncompressed and compressed data is generated in
+     * the same transaction
+     * @throws Exception
+     */
+    @Test
+    public void testCreateCompressedAndUncompressed() throws Exception
+    {
+        final String path1 = "/a";
+        final String path2 = "/b";
+        
+        final byte[]            data1 = "here's a string".getBytes();
+        final byte[]            data2 = "here's another string".getBytes();
+
+        CuratorFramework        client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
+        try
+        {
+            client.start();
+
+            client.inTransaction().create().compressed().forPath(path1, data1).and().
+            create().forPath(path2, data2).and().commit();
+
+            Assert.assertNotEquals(data1, client.getData().forPath(path1));
+            Assert.assertEquals(data1, client.getData().decompressed().forPath(path1));
+      
+            Assert.assertEquals(data2, client.getData().forPath(path2));            
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }
+}


[09/27] curator git commit: [CURATOR-160] Fix QuorumConfigBuilder to provide a valid server string.

Posted by dr...@apache.org.
[CURATOR-160] Fix QuorumConfigBuilder to provide a valid server string.


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

Branch: refs/heads/CURATOR-215
Commit: ec4083f99d97a0c6557f0ce9b9132a75909bd177
Parents: 0e876c8
Author: Ioannis Canellos <io...@gmail.com>
Authored: Tue Nov 11 12:28:53 2014 +0200
Committer: Scott Blum <dr...@apache.org>
Committed: Wed Aug 12 17:08:33 2015 -0400

----------------------------------------------------------------------
 .../src/main/java/org/apache/curator/test/QuorumConfigBuilder.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/ec4083f9/curator-test/src/main/java/org/apache/curator/test/QuorumConfigBuilder.java
----------------------------------------------------------------------
diff --git a/curator-test/src/main/java/org/apache/curator/test/QuorumConfigBuilder.java b/curator-test/src/main/java/org/apache/curator/test/QuorumConfigBuilder.java
index 8add08e..02979ee 100644
--- a/curator-test/src/main/java/org/apache/curator/test/QuorumConfigBuilder.java
+++ b/curator-test/src/main/java/org/apache/curator/test/QuorumConfigBuilder.java
@@ -99,7 +99,7 @@ public class QuorumConfigBuilder
         {
             for ( InstanceSpec thisSpec : instanceSpecs )
             {
-                properties.setProperty("server." + thisSpec.getServerId(), String.format("localhost:%d:%d", thisSpec.getQuorumPort(), thisSpec.getElectionPort()));
+                properties.setProperty("server." + thisSpec.getServerId(), String.format("localhost:%d:%d;localhost:%d", thisSpec.getQuorumPort(), thisSpec.getElectionPort(), thisSpec.getPort()));
             }
         }
 


[16/27] curator git commit: Moved EnsembleTracker and did some refactoring

Posted by dr...@apache.org.
Moved EnsembleTracker and did some refactoring


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

Branch: refs/heads/CURATOR-215
Commit: d86f51f8c2c473715cddfcd32f087e2510332b4f
Parents: 299a202
Author: randgalt <ra...@apache.org>
Authored: Sat May 9 09:47:04 2015 -0500
Committer: Scott Blum <dr...@apache.org>
Committed: Wed Aug 12 17:28:42 2015 -0400

----------------------------------------------------------------------
 .../framework/ensemble/EnsembleTracker.java     | 191 ++++++++++++++++++
 .../curator/framework/imps/EnsembleTracker.java | 196 -------------------
 .../framework/imps/TestReconfiguration.java     |   1 +
 3 files changed, 192 insertions(+), 196 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/d86f51f8/curator-framework/src/main/java/org/apache/curator/framework/ensemble/EnsembleTracker.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/ensemble/EnsembleTracker.java b/curator-framework/src/main/java/org/apache/curator/framework/ensemble/EnsembleTracker.java
new file mode 100644
index 0000000..375e1f0
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/ensemble/EnsembleTracker.java
@@ -0,0 +1,191 @@
+/**
+ * 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.curator.framework.ensemble;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import org.apache.curator.ensemble.EnsembleListener;
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.api.BackgroundCallback;
+import org.apache.curator.framework.api.CuratorEvent;
+import org.apache.curator.framework.api.CuratorWatcher;
+import org.apache.curator.framework.listen.ListenerContainer;
+import org.apache.curator.framework.state.ConnectionState;
+import org.apache.curator.framework.state.ConnectionStateListener;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.server.quorum.QuorumPeer;
+import org.apache.zookeeper.server.quorum.flexible.QuorumMaj;
+import org.apache.zookeeper.server.quorum.flexible.QuorumVerifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.io.ByteArrayInputStream;
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Tracks changes to the ensemble and notifies registered {@link org.apache.curator.ensemble.EnsembleListener} instances.
+ */
+public class EnsembleTracker implements Closeable
+{
+    private final Logger log = LoggerFactory.getLogger(getClass());
+    private final CuratorFramework client;
+    private final AtomicReference<State> state = new AtomicReference<>(State.LATENT);
+    private final ListenerContainer<EnsembleListener> listeners = new ListenerContainer<>();
+    private final ConnectionStateListener connectionStateListener = new ConnectionStateListener()
+    {
+        @Override
+        public void stateChanged(CuratorFramework client, ConnectionState newState)
+        {
+            if ( (newState == ConnectionState.CONNECTED) || (newState == ConnectionState.RECONNECTED) )
+            {
+                try
+                {
+                    reset();
+                }
+                catch ( Exception e )
+                {
+                    log.error("Trying to reset after reconnection", e);
+                }
+            }
+        }
+    };
+
+    private final CuratorWatcher watcher = new CuratorWatcher()
+    {
+        @Override
+        public void process(WatchedEvent event) throws Exception
+        {
+            if ( event.getType() == Watcher.Event.EventType.NodeDataChanged )
+            {
+                reset();
+            }
+        }
+    };
+
+    private enum State
+    {
+        LATENT,
+        STARTED,
+        CLOSED
+    }
+
+    private final BackgroundCallback backgroundCallback = new BackgroundCallback()
+    {
+        @Override
+        public void processResult(CuratorFramework client, CuratorEvent event) throws Exception
+        {
+            processBackgroundResult(event);
+        }
+    };
+
+    public EnsembleTracker(CuratorFramework client)
+    {
+        this.client = client;
+    }
+
+    public void start() throws Exception
+    {
+        Preconditions.checkState(state.compareAndSet(State.LATENT, State.STARTED), "Cannot be started more than once");
+        client.getConnectionStateListenable().addListener(connectionStateListener);
+        reset();
+    }
+
+    @Override
+    public void close() throws IOException
+    {
+        if ( state.compareAndSet(State.STARTED, State.CLOSED) )
+        {
+            listeners.clear();
+        }
+        client.getConnectionStateListenable().removeListener(connectionStateListener);
+    }
+
+    /**
+     * Return the ensemble listenable
+     *
+     * @return listenable
+     */
+    public ListenerContainer<EnsembleListener> getListenable()
+    {
+        Preconditions.checkState(state.get() != State.CLOSED, "Closed");
+
+        return listeners;
+    }
+
+    private void reset() throws Exception
+    {
+        client.getConfig().usingWatcher(watcher).inBackground(backgroundCallback).forEnsemble();
+    }
+
+    private void processBackgroundResult(CuratorEvent event) throws Exception
+    {
+        switch ( event.getType() )
+        {
+            case GET_CONFIG:
+            {
+                if ( event.getResultCode() == KeeperException.Code.OK.intValue() )
+                {
+                    processConfigData(event.getData());
+                }
+            }
+        }
+    }
+
+    private void processConfigData(byte[] data) throws Exception
+    {
+        Properties properties = new Properties();
+        properties.load(new ByteArrayInputStream(data));
+        QuorumVerifier qv = new QuorumMaj(properties);
+        StringBuilder sb = new StringBuilder();
+        for ( QuorumPeer.QuorumServer server : qv.getAllMembers().values() )
+        {
+            if ( sb.length() != 0 )
+            {
+                sb.append(",");
+            }
+            sb.append(server.clientAddr.getAddress().getHostAddress()).append(":").append(server.clientAddr.getPort());
+        }
+
+        final String connectionString = sb.toString();
+        listeners.forEach
+            (
+                new Function<EnsembleListener, Void>()
+                {
+                    @Override
+                    public Void apply(EnsembleListener listener)
+                    {
+                        try
+                        {
+                            listener.connectionStringUpdated(connectionString);
+                        }
+                        catch ( Exception e )
+                        {
+                            log.error("Calling listener", e);
+                        }
+                        return null;
+                    }
+                }
+            );
+    }
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/d86f51f8/curator-framework/src/main/java/org/apache/curator/framework/imps/EnsembleTracker.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/EnsembleTracker.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/EnsembleTracker.java
deleted file mode 100644
index 6688848..0000000
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/EnsembleTracker.java
+++ /dev/null
@@ -1,196 +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.curator.framework.imps;
-
-import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
-import org.apache.curator.ensemble.EnsembleListener;
-import org.apache.curator.framework.CuratorFramework;
-import org.apache.curator.framework.api.BackgroundCallback;
-import org.apache.curator.framework.api.CuratorEvent;
-import org.apache.curator.framework.api.CuratorWatcher;
-import org.apache.curator.framework.listen.ListenerContainer;
-import org.apache.curator.framework.state.ConnectionState;
-import org.apache.curator.framework.state.ConnectionStateListener;
-import org.apache.zookeeper.KeeperException;
-import org.apache.zookeeper.WatchedEvent;
-import org.apache.zookeeper.server.quorum.QuorumPeer;
-import org.apache.zookeeper.server.quorum.flexible.QuorumMaj;
-import org.apache.zookeeper.server.quorum.flexible.QuorumVerifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import java.io.ByteArrayInputStream;
-import java.io.Closeable;
-import java.io.IOException;
-import java.util.Properties;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * Tracks changes to the ensemble and notifies registered {@link org.apache.curator.ensemble.EnsembleListener} instances.
- */
-public class EnsembleTracker implements Closeable
-{
-    private final Logger log = LoggerFactory.getLogger(getClass());
-    private final CuratorFramework client;
-    private final AtomicReference<State> state = new AtomicReference<State>(State.LATENT);
-    private final ListenerContainer<EnsembleListener> listeners = new ListenerContainer<EnsembleListener>();
-    private final AtomicBoolean isConnected = new AtomicBoolean(true);
-    private final ConnectionStateListener connectionStateListener = new ConnectionStateListener()
-    {
-        @Override
-        public void stateChanged(CuratorFramework client, ConnectionState newState)
-        {
-            if ( (newState == ConnectionState.CONNECTED) || (newState == ConnectionState.RECONNECTED) )
-            {
-                if ( isConnected.compareAndSet(false, true) )
-                {
-                    try
-                    {
-                        reset();
-                    }
-                    catch ( Exception e )
-                    {
-                        log.error("Trying to reset after reconnection", e);
-                    }
-                }
-            }
-            else
-            {
-                isConnected.set(false);
-            }
-        }
-    };
-
-    private final CuratorWatcher watcher = new CuratorWatcher()
-    {
-        @Override
-        public void process(WatchedEvent event) throws Exception
-        {
-            reset();
-        }
-    };
-
-    private enum State
-    {
-        LATENT,
-        STARTED,
-        CLOSED
-    }
-
-    private final BackgroundCallback backgroundCallback = new BackgroundCallback()
-    {
-        @Override
-        public void processResult(CuratorFramework client, CuratorEvent event) throws Exception
-        {
-            processBackgroundResult(event);
-        }
-    };
-
-    public EnsembleTracker(CuratorFramework client)
-    {
-        this.client = client;
-    }
-
-    public void start() throws Exception
-    {
-        Preconditions.checkState(state.compareAndSet(State.LATENT, State.STARTED), "Cannot be started more than once");
-        client.getConnectionStateListenable().addListener(connectionStateListener);
-        reset();
-    }
-
-    @Override
-    public void close() throws IOException
-    {
-        if ( state.compareAndSet(State.STARTED, State.CLOSED) )
-        {
-            listeners.clear();
-        }
-        client.getConnectionStateListenable().removeListener(connectionStateListener);
-    }
-
-    /**
-     * Return the ensemble listenable
-     *
-     * @return listenable
-     */
-    public ListenerContainer<EnsembleListener> getListenable()
-    {
-        Preconditions.checkState(state.get() != State.CLOSED, "Closed");
-
-        return listeners;
-    }
-
-    private void reset() throws Exception
-    {
-        client.getConfig().usingWatcher(watcher).inBackground(backgroundCallback).forEnsemble();
-    }
-
-    private void processBackgroundResult(CuratorEvent event) throws Exception
-    {
-        switch ( event.getType() )
-        {
-        case GET_CONFIG:
-        {
-            if ( event.getResultCode() == KeeperException.Code.OK.intValue() )
-            {
-                processConfigData(event.getData());
-            }
-        }
-        }
-    }
-
-    private void processConfigData(byte[] data) throws Exception
-    {
-        Properties properties = new Properties();
-        properties.load(new ByteArrayInputStream(data));
-        QuorumVerifier qv = new QuorumMaj(properties);
-        StringBuilder sb = new StringBuilder();
-        for ( QuorumPeer.QuorumServer server : qv.getAllMembers().values() )
-        {
-            if ( sb.length() != 0 )
-            {
-                sb.append(",");
-            }
-            sb.append(server.clientAddr.getAddress().getHostAddress()).append(":").append(server.clientAddr.getPort());
-        }
-
-        final String connectionString = sb.toString();
-        listeners.forEach
-            (
-                new Function<EnsembleListener, Void>()
-                {
-                    @Override
-                    public Void apply(EnsembleListener listener)
-                    {
-                        try
-                        {
-                            listener.connectionStringUpdated(connectionString);
-                        }
-                        catch ( Exception e )
-                        {
-                            log.error("Calling listener", e);
-                        }
-                        return null;
-                    }
-                }
-            );
-    }
-}

http://git-wip-us.apache.org/repos/asf/curator/blob/d86f51f8/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java
index 297cf9b..133e690 100644
--- a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java
@@ -25,6 +25,7 @@ import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
 import org.apache.curator.framework.api.BackgroundCallback;
 import org.apache.curator.framework.api.CuratorEvent;
+import org.apache.curator.framework.ensemble.EnsembleTracker;
 import org.apache.curator.retry.RetryOneTime;
 import org.apache.curator.test.InstanceSpec;
 import org.apache.curator.test.TestingCluster;


[18/27] curator git commit: escape underscores

Posted by dr...@apache.org.
escape underscores


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

Branch: refs/heads/CURATOR-215
Commit: d9c394e320a6f36137869b9368cf1e476721f520
Parents: e558c4b
Author: randgalt <ra...@apache.org>
Authored: Sat May 9 10:52:33 2015 -0500
Committer: Scott Blum <dr...@apache.org>
Committed: Wed Aug 12 17:28:42 2015 -0400

----------------------------------------------------------------------
 curator-framework/src/site/confluence/index.confluence | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/d9c394e3/curator-framework/src/site/confluence/index.confluence
----------------------------------------------------------------------
diff --git a/curator-framework/src/site/confluence/index.confluence b/curator-framework/src/site/confluence/index.confluence
index bb1807e..c41b244 100644
--- a/curator-framework/src/site/confluence/index.confluence
+++ b/curator-framework/src/site/confluence/index.confluence
@@ -63,14 +63,14 @@ CuratorEvent depend on the type of event which is exposed via the getType() meth
 |CREATE|getResultCode() and getPath()|
 |DELETE|getResultCode() and getPath()|
 |EXISTS|getResultCode(), getPath() and getStat()|
-|GET_DATA|getResultCode(), getPath(), getStat() and getData()|
-|SET_DATA|getResultCode(), getPath() and getStat()|
+|GET\_DATA|getResultCode(), getPath(), getStat() and getData()|
+|SET\_DATA|getResultCode(), getPath() and getStat()|
 |CHILDREN|getResultCode(), getPath(), getStat(), getChildren()|
 |SYNC|getResultCode(), getStat()|
-|GET_ACL|getResultCode(), getACLList()|
-|SET_ACL|getResultCode()|
+|GET\_ACL|getResultCode(), getACLList()|
+|SET\_ACL|getResultCode()|
 |WATCHED|getWatchedEvent()|
-|GET_CONFIG|getResultCode(), getData()|
+|GET\_CONFIG|getResultCode(), getData()|
 |RECONFIG|getResultCode(), getData()|
 
 h2. Namespaces


[19/27] curator git commit: Initial implementation finished. Uses old transactions internal code for consistency. However, this makes the implementation a bit cumbersome. Old APIs are deprecated. In the future, this can all be cleaned up

Posted by dr...@apache.org.
http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/test/java/org/apache/curator/framework/imps/TestTransactionsNew.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestTransactionsNew.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestTransactionsNew.java
new file mode 100644
index 0000000..eaf94f8
--- /dev/null
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestTransactionsNew.java
@@ -0,0 +1,218 @@
+/**
+ * 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.curator.framework.imps;
+
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Queues;
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.framework.api.BackgroundCallback;
+import org.apache.curator.framework.api.CuratorEvent;
+import org.apache.curator.framework.api.transaction.CuratorOp;
+import org.apache.curator.framework.api.transaction.CuratorTransactionResult;
+import org.apache.curator.framework.api.transaction.OperationType;
+import org.apache.curator.retry.RetryOneTime;
+import org.apache.curator.test.BaseClassForTests;
+import org.apache.curator.utils.CloseableUtils;
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.data.Stat;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+public class TestTransactionsNew extends BaseClassForTests
+{
+    @Test
+    public void testCheckVersion() throws Exception
+    {
+        CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
+        try
+        {
+            client.start();
+            client.create().forPath("/foo");
+            Stat stat = client.setData().forPath("/foo", "new".getBytes());  // up the version
+
+            CuratorOp statOp = client.transactionOp().check().withVersion(stat.getVersion() + 1).forPath("/foo");
+            CuratorOp createOp = client.transactionOp().create().forPath("/bar");
+            try
+            {
+                client.transaction().forOperations(statOp, createOp);
+                Assert.fail();
+            }
+            catch ( KeeperException.BadVersionException correct )
+            {
+                // correct
+            }
+
+            Assert.assertNull(client.checkExists().forPath("/bar"));
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }
+
+    @Test
+    public void testWithNamespace() throws Exception
+    {
+        CuratorFramework client = CuratorFrameworkFactory.builder().connectString(server.getConnectString()).retryPolicy(new RetryOneTime(1)).namespace("galt").build();
+        try
+        {
+            client.start();
+            CuratorOp createOp1 = client.transactionOp().create().forPath("/foo", "one".getBytes());
+            CuratorOp createOp2 = client.transactionOp().create().withMode(CreateMode.PERSISTENT_SEQUENTIAL).forPath("/test-", "one".getBytes());
+            CuratorOp setDataOp = client.transactionOp().setData().forPath("/foo", "two".getBytes());
+            CuratorOp createOp3 = client.transactionOp().create().forPath("/foo/bar");
+            CuratorOp deleteOp = client.transactionOp().delete().forPath("/foo/bar");
+
+            Collection<CuratorTransactionResult> results = client.transaction().forOperations(createOp1, createOp2, setDataOp, createOp3, deleteOp);
+
+            Assert.assertTrue(client.checkExists().forPath("/foo") != null);
+            Assert.assertTrue(client.usingNamespace(null).checkExists().forPath("/galt/foo") != null);
+            Assert.assertEquals(client.getData().forPath("/foo"), "two".getBytes());
+            Assert.assertTrue(client.checkExists().forPath("/foo/bar") == null);
+
+            CuratorTransactionResult ephemeralResult = Iterables.find(results, CuratorTransactionResult.ofTypeAndPath(OperationType.CREATE, "/test-"));
+            Assert.assertNotNull(ephemeralResult);
+            Assert.assertNotEquals(ephemeralResult.getResultPath(), "/test-");
+            Assert.assertTrue(ephemeralResult.getResultPath().startsWith("/test-"));
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }
+
+    @Test
+    public void testBasic() throws Exception
+    {
+        CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
+        try
+        {
+            client.start();
+            CuratorOp createOp1 = client.transactionOp().create().forPath("/foo");
+            CuratorOp createOp2 = client.transactionOp().create().forPath("/foo/bar", "snafu".getBytes());
+
+            Collection<CuratorTransactionResult> results = client.transaction().forOperations(createOp1, createOp2);
+
+            Assert.assertTrue(client.checkExists().forPath("/foo/bar") != null);
+            Assert.assertEquals(client.getData().forPath("/foo/bar"), "snafu".getBytes());
+
+            CuratorTransactionResult fooResult = Iterables.find(results, CuratorTransactionResult.ofTypeAndPath(OperationType.CREATE, "/foo"));
+            CuratorTransactionResult fooBarResult = Iterables.find(results, CuratorTransactionResult.ofTypeAndPath(OperationType.CREATE, "/foo/bar"));
+            Assert.assertNotNull(fooResult);
+            Assert.assertNotNull(fooBarResult);
+            Assert.assertNotSame(fooResult, fooBarResult);
+            Assert.assertEquals(fooResult.getResultPath(), "/foo");
+            Assert.assertEquals(fooBarResult.getResultPath(), "/foo/bar");
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }
+
+    @Test
+    public void testBackground() throws Exception
+    {
+        CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
+        try
+        {
+            client.start();
+            CuratorOp createOp1 = client.transactionOp().create().forPath("/foo");
+            CuratorOp createOp2 = client.transactionOp().create().forPath("/foo/bar", "snafu".getBytes());
+
+            final BlockingQueue<List<CuratorTransactionResult>> queue = Queues.newLinkedBlockingQueue();
+            BackgroundCallback callback = new BackgroundCallback()
+            {
+                @Override
+                public void processResult(CuratorFramework client, CuratorEvent event) throws Exception
+                {
+                    queue.add(event.getOpResults());
+                }
+            };
+            client.transaction().inBackground(callback).forOperations(createOp1, createOp2);
+            Collection<CuratorTransactionResult> results = queue.poll(5, TimeUnit.SECONDS);
+
+            Assert.assertNotNull(results);
+            Assert.assertTrue(client.checkExists().forPath("/foo/bar") != null);
+            Assert.assertEquals(client.getData().forPath("/foo/bar"), "snafu".getBytes());
+
+            CuratorTransactionResult fooResult = Iterables.find(results, CuratorTransactionResult.ofTypeAndPath(OperationType.CREATE, "/foo"));
+            CuratorTransactionResult fooBarResult = Iterables.find(results, CuratorTransactionResult.ofTypeAndPath(OperationType.CREATE, "/foo/bar"));
+            Assert.assertNotNull(fooResult);
+            Assert.assertNotNull(fooBarResult);
+            Assert.assertNotSame(fooResult, fooBarResult);
+            Assert.assertEquals(fooResult.getResultPath(), "/foo");
+            Assert.assertEquals(fooBarResult.getResultPath(), "/foo/bar");
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }
+
+    @Test
+    public void testBackgroundWithNamespace() throws Exception
+    {
+        CuratorFramework client = CuratorFrameworkFactory.builder().connectString(server.getConnectString()).retryPolicy(new RetryOneTime(1)).namespace("galt").build();
+        try
+        {
+            client.start();
+            CuratorOp createOp1 = client.transactionOp().create().forPath("/foo", "one".getBytes());
+            CuratorOp createOp2 = client.transactionOp().create().withMode(CreateMode.PERSISTENT_SEQUENTIAL).forPath("/test-", "one".getBytes());
+            CuratorOp setDataOp = client.transactionOp().setData().forPath("/foo", "two".getBytes());
+            CuratorOp createOp3 = client.transactionOp().create().forPath("/foo/bar");
+            CuratorOp deleteOp = client.transactionOp().delete().forPath("/foo/bar");
+
+            final BlockingQueue<List<CuratorTransactionResult>> queue = Queues.newLinkedBlockingQueue();
+            BackgroundCallback callback = new BackgroundCallback()
+            {
+                @Override
+                public void processResult(CuratorFramework client, CuratorEvent event) throws Exception
+                {
+                    queue.add(event.getOpResults());
+                }
+            };
+            client.transaction().inBackground(callback).forOperations(createOp1, createOp2, setDataOp, createOp3, deleteOp);
+
+            Collection<CuratorTransactionResult> results = queue.poll(5, TimeUnit.SECONDS);
+
+            Assert.assertNotNull(results);
+            Assert.assertTrue(client.checkExists().forPath("/foo") != null);
+            Assert.assertTrue(client.usingNamespace(null).checkExists().forPath("/galt/foo") != null);
+            Assert.assertEquals(client.getData().forPath("/foo"), "two".getBytes());
+            Assert.assertTrue(client.checkExists().forPath("/foo/bar") == null);
+
+            CuratorTransactionResult ephemeralResult = Iterables.find(results, CuratorTransactionResult.ofTypeAndPath(OperationType.CREATE, "/test-"));
+            Assert.assertNotNull(ephemeralResult);
+            Assert.assertNotEquals(ephemeralResult.getResultPath(), "/test-");
+            Assert.assertTrue(ephemeralResult.getResultPath().startsWith("/test-"));
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/test/java/org/apache/curator/framework/imps/TestTransactionsOld.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestTransactionsOld.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestTransactionsOld.java
new file mode 100644
index 0000000..f0147d5
--- /dev/null
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestTransactionsOld.java
@@ -0,0 +1,141 @@
+/**
+ * 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.curator.framework.imps;
+
+import com.google.common.collect.Iterables;
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.framework.api.transaction.CuratorTransactionResult;
+import org.apache.curator.framework.api.transaction.OperationType;
+import org.apache.curator.retry.RetryOneTime;
+import org.apache.curator.test.BaseClassForTests;
+import org.apache.curator.utils.CloseableUtils;
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.data.Stat;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import java.util.Collection;
+
+@SuppressWarnings("deprecation")
+public class TestTransactionsOld extends BaseClassForTests
+{
+    @Test
+    public void     testCheckVersion() throws Exception
+    {
+        CuratorFramework        client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
+        try
+        {
+            client.start();
+            client.create().forPath("/foo");
+            Stat        stat = client.setData().forPath("/foo", "new".getBytes());  // up the version
+
+            try
+            {
+                client.inTransaction()
+                    .check().withVersion(stat.getVersion() + 1).forPath("/foo") // force a bad version
+                .and()
+                    .create().forPath("/bar")
+                .and()
+                    .commit();
+
+                Assert.fail();
+            }
+            catch ( KeeperException.BadVersionException correct )
+            {
+                // correct
+            }
+            
+            Assert.assertNull(client.checkExists().forPath("/bar"));
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }
+
+    @Test
+    public void     testWithNamespace() throws Exception
+    {
+        CuratorFramework        client = CuratorFrameworkFactory.builder().connectString(server.getConnectString()).retryPolicy(new RetryOneTime(1)).namespace("galt").build();
+        try
+        {
+            client.start();
+            Collection<CuratorTransactionResult>    results =
+                client.inTransaction()
+                    .create().forPath("/foo", "one".getBytes())
+                .and()
+                    .create().withMode(CreateMode.PERSISTENT_SEQUENTIAL).forPath("/test-", "one".getBytes())
+                .and()
+                    .setData().forPath("/foo", "two".getBytes())
+                .and()
+                    .create().forPath("/foo/bar")
+                .and()
+                    .delete().forPath("/foo/bar")
+                .and()
+                    .commit();
+
+            Assert.assertTrue(client.checkExists().forPath("/foo") != null);
+            Assert.assertTrue(client.usingNamespace(null).checkExists().forPath("/galt/foo") != null);
+            Assert.assertEquals(client.getData().forPath("/foo"), "two".getBytes());
+            Assert.assertTrue(client.checkExists().forPath("/foo/bar") == null);
+
+            CuratorTransactionResult    ephemeralResult = Iterables.find(results, CuratorTransactionResult.ofTypeAndPath(OperationType.CREATE, "/test-"));
+            Assert.assertNotNull(ephemeralResult);
+            Assert.assertNotEquals(ephemeralResult.getResultPath(), "/test-");
+            Assert.assertTrue(ephemeralResult.getResultPath().startsWith("/test-"));
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }
+
+    @Test
+    public void     testBasic() throws Exception
+    {
+        CuratorFramework        client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
+        try
+        {
+            client.start();
+            Collection<CuratorTransactionResult>    results =
+                client.inTransaction()
+                    .create().forPath("/foo")
+                .and()
+                    .create().forPath("/foo/bar", "snafu".getBytes())
+                .and()
+                    .commit();
+
+            Assert.assertTrue(client.checkExists().forPath("/foo/bar") != null);
+            Assert.assertEquals(client.getData().forPath("/foo/bar"), "snafu".getBytes());
+
+            CuratorTransactionResult    fooResult = Iterables.find(results, CuratorTransactionResult.ofTypeAndPath(OperationType.CREATE, "/foo"));
+            CuratorTransactionResult    fooBarResult = Iterables.find(results, CuratorTransactionResult.ofTypeAndPath(OperationType.CREATE, "/foo/bar"));
+            Assert.assertNotNull(fooResult);
+            Assert.assertNotNull(fooBarResult);
+            Assert.assertNotSame(fooResult, fooBarResult);
+            Assert.assertEquals(fooResult.getResultPath(), "/foo");
+            Assert.assertEquals(fooBarResult.getResultPath(), "/foo/bar");
+        }
+        finally
+        {
+            CloseableUtils.closeQuietly(client);
+        }
+    }
+}


[11/27] curator git commit: Reworked the reconfig() APIs to be more like the rest of Curator

Posted by dr...@apache.org.
http://git-wip-us.apache.org/repos/asf/curator/blob/57dbf2e1/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java
index 44f9d00..297cf9b 100644
--- a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java
@@ -16,6 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
 package org.apache.curator.framework.imps;
 
 import org.apache.curator.ensemble.EnsembleListener;
@@ -27,6 +28,7 @@ import org.apache.curator.framework.api.CuratorEvent;
 import org.apache.curator.retry.RetryOneTime;
 import org.apache.curator.test.InstanceSpec;
 import org.apache.curator.test.TestingCluster;
+import org.apache.curator.utils.CloseableUtils;
 import org.apache.zookeeper.data.Stat;
 import org.apache.zookeeper.server.quorum.flexible.QuorumMaj;
 import org.apache.zookeeper.server.quorum.flexible.QuorumVerifier;
@@ -34,7 +36,6 @@ import org.testng.Assert;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
-
 import java.io.IOException;
 import java.io.StringReader;
 import java.util.HashMap;
@@ -45,32 +46,33 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicReference;
 
-public class TestReconfiguration {
-
-    TestingCluster cluster;
-    DynamicEnsembleProvider dynamicEnsembleProvider;
-    WaitOnDelegateListener waitOnDelegateListener;
-    EnsembleTracker ensembleTracker;
-    CuratorFramework client;
+public class TestReconfiguration
+{
+    private TestingCluster cluster;
+    private DynamicEnsembleProvider dynamicEnsembleProvider;
+    private WaitOnDelegateListener waitOnDelegateListener;
+    private EnsembleTracker ensembleTracker;
+    private CuratorFramework client;
 
-    String connectionString1to5;
-    String connectionString2to5;
-    String connectionString3to5;
+    private String connectionString1to5;
+    private String connectionString2to5;
+    private String connectionString3to5;
 
     @BeforeMethod
-    public void setup() throws Exception {
+    public void setup() throws Exception
+    {
         cluster = new TestingCluster(5);
         cluster.start();
 
         connectionString1to5 = cluster.getConnectString();
-        connectionString2to5 = getConnectionString(cluster, 2,3,4,5);
-        connectionString3to5 = getConnectionString(cluster, 3,4,5);
+        connectionString2to5 = getConnectionString(cluster, 2, 3, 4, 5);
+        connectionString3to5 = getConnectionString(cluster, 3, 4, 5);
 
         dynamicEnsembleProvider = new DynamicEnsembleProvider(connectionString1to5);
         client = CuratorFrameworkFactory.builder()
-                .ensembleProvider(dynamicEnsembleProvider)
-                .retryPolicy(new RetryOneTime(1))
-                .build();
+            .ensembleProvider(dynamicEnsembleProvider)
+            .retryPolicy(new RetryOneTime(1))
+            .build();
         client.start();
         client.blockUntilConnected();
 
@@ -84,14 +86,16 @@ public class TestReconfiguration {
     }
 
     @AfterMethod
-    public void tearDown() throws IOException {
-        ensembleTracker.close();
-        client.close();
-        cluster.close();
+    public void tearDown() throws IOException
+    {
+        CloseableUtils.closeQuietly(ensembleTracker);
+        CloseableUtils.closeQuietly(client);
+        CloseableUtils.closeQuietly(cluster);
     }
 
     @Test
-    public void testSyncIncremental() throws Exception {
+    public void testSyncIncremental() throws Exception
+    {
         Stat stat = new Stat();
         byte[] bytes = client.getConfig().storingStatIn(stat).forEnsemble();
         Assert.assertNotNull(bytes);
@@ -132,15 +136,19 @@ public class TestReconfiguration {
     }
 
     @Test
-    public void testAsyncIncremental() throws Exception {
-        final AtomicReference<byte[]> bytes = new AtomicReference<byte[]>();
-        final BackgroundCallback callback = new BackgroundCallback() {
+    public void testAsyncIncremental() throws Exception
+    {
+        final AtomicReference<byte[]> bytes = new AtomicReference<>();
+        final BackgroundCallback callback = new BackgroundCallback()
+        {
             @Override
-            public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
+            public void processResult(CuratorFramework client, CuratorEvent event) throws Exception
+            {
                 bytes.set(event.getData());
                 //We only need the latch on getConfig.
-                if (event.getContext() != null) {
-                    ((CountDownLatch) event.getContext()).countDown();
+                if ( event.getContext() != null )
+                {
+                    ((CountDownLatch)event.getContext()).countDown();
                 }
             }
 
@@ -155,29 +163,27 @@ public class TestReconfiguration {
         String server1 = getServerString(qv, cluster, 1L);
         String server2 = getServerString(qv, cluster, 2L);
 
-
         //Remove Servers
-        client.reconfig().leaving("1").fromConfig(qv.getVersion()).inBackground(callback).forEnsemble();
+        client.reconfig().inBackground(callback).leaving("1").fromConfig(qv.getVersion()).forEnsemble();
         waitOnDelegateListener.waitForEvent();
         Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString2to5);
         qv = getQuorumVerifier(bytes.get());
         Assert.assertEquals(qv.getAllMembers().size(), 4);
 
-        client.reconfig().leaving("2").fromConfig(qv.getVersion()).inBackground(callback, latch).forEnsemble();
+        client.reconfig().inBackground(callback, latch).leaving("2").fromConfig(qv.getVersion()).forEnsemble();
         waitOnDelegateListener.waitForEvent();
         Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString3to5);
         qv = getQuorumVerifier(bytes.get());
         Assert.assertEquals(qv.getAllMembers().size(), 3);
 
         //Add Servers
-        client.reconfig().joining("server.2=" + server2).fromConfig(qv.getVersion()).inBackground(callback, latch).forEnsemble();
+        client.reconfig().inBackground(callback, latch).joining("server.2=" + server2).fromConfig(qv.getVersion()).forEnsemble();
         waitOnDelegateListener.waitForEvent();
         Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString2to5);
         qv = getQuorumVerifier(bytes.get());
         Assert.assertEquals(qv.getAllMembers().size(), 4);
 
-
-        client.reconfig().joining("server.1=" + server1).fromConfig(qv.getVersion()).inBackground(callback, latch).forEnsemble();
+        client.reconfig().inBackground(callback, latch).joining("server.1=" + server1).fromConfig(qv.getVersion()).forEnsemble();
         waitOnDelegateListener.waitForEvent();
         Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString1to5);
         qv = getQuorumVerifier(bytes.get());
@@ -185,7 +191,8 @@ public class TestReconfiguration {
     }
 
     @Test
-    public void testSyncNonIncremental() throws Exception {
+    public void testSyncNonIncremental() throws Exception
+    {
         Stat stat = new Stat();
         byte[] bytes = client.getConfig().storingStatIn(stat).forEnsemble();
         Assert.assertNotNull(bytes);
@@ -199,11 +206,11 @@ public class TestReconfiguration {
 
         //Remove Servers
         bytes = client.reconfig()
-                .withMembers("server.2=" + server2,
-                        "server.3=" + server3,
-                        "server.4=" + server4,
-                        "server.5=" + server5)
-                .fromConfig(qv.getVersion()).storingStatIn(stat).forEnsemble();
+            .adding("server.2=" + server2,
+                "server.3=" + server3,
+                "server.4=" + server4,
+                "server.5=" + server5)
+            .fromConfig(qv.getVersion()).storingStatIn(stat).forEnsemble();
         qv = getQuorumVerifier(bytes);
         Assert.assertEquals(qv.getAllMembers().size(), 4);
 
@@ -211,10 +218,10 @@ public class TestReconfiguration {
         Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString2to5);
 
         bytes = client.reconfig()
-                .withMembers("server.3=" + server3,
-                        "server.4=" + server4,
-                        "server.5=" + server5)
-                .fromConfig(qv.getVersion()).storingStatIn(stat).forEnsemble();
+            .adding("server.3=" + server3,
+                "server.4=" + server4,
+                "server.5=" + server5)
+            .fromConfig(qv.getVersion()).storingStatIn(stat).forEnsemble();
 
         qv = getQuorumVerifier(bytes);
         Assert.assertEquals(qv.getAllMembers().size(), 3);
@@ -224,11 +231,11 @@ public class TestReconfiguration {
 
         //Add Servers
         bytes = client.reconfig()
-                .withMembers("server.2=" + server2,
-                        "server.3=" + server3,
-                        "server.4=" + server4,
-                        "server.5=" + server5)
-                .fromConfig(qv.getVersion()).storingStatIn(stat).forEnsemble();
+            .adding("server.2=" + server2,
+                "server.3=" + server3,
+                "server.4=" + server4,
+                "server.5=" + server5)
+            .fromConfig(qv.getVersion()).storingStatIn(stat).forEnsemble();
         qv = getQuorumVerifier(bytes);
         Assert.assertEquals(qv.getAllMembers().size(), 4);
 
@@ -236,12 +243,12 @@ public class TestReconfiguration {
         Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString2to5);
 
         bytes = client.reconfig()
-                .withMembers("server.1=" + server1,
-                        "server.2=" + server2,
-                        "server.3=" + server3,
-                        "server.4=" + server4,
-                        "server.5=" + server5)
-                .fromConfig(qv.getVersion()).storingStatIn(stat).forEnsemble();
+            .adding("server.1=" + server1,
+                "server.2=" + server2,
+                "server.3=" + server3,
+                "server.4=" + server4,
+                "server.5=" + server5)
+            .fromConfig(qv.getVersion()).storingStatIn(stat).forEnsemble();
         qv = getQuorumVerifier(bytes);
         Assert.assertEquals(qv.getAllMembers().size(), 5);
 
@@ -250,13 +257,16 @@ public class TestReconfiguration {
     }
 
     @Test
-    public void testAsyncNonIncremental() throws Exception {
-        final AtomicReference<byte[]> bytes = new AtomicReference<byte[]>();
-        final BackgroundCallback callback = new BackgroundCallback() {
+    public void testAsyncNonIncremental() throws Exception
+    {
+        final AtomicReference<byte[]> bytes = new AtomicReference<>();
+        final BackgroundCallback callback = new BackgroundCallback()
+        {
             @Override
-            public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
+            public void processResult(CuratorFramework client, CuratorEvent event) throws Exception
+            {
                 bytes.set(event.getData());
-                ((CountDownLatch) event.getContext()).countDown();
+                ((CountDownLatch)event.getContext()).countDown();
             }
 
         };
@@ -274,86 +284,97 @@ public class TestReconfiguration {
         String server5 = getServerString(qv, cluster, 5L);
 
         //Remove Servers
-        client.reconfig()
-                .withMembers("server.2=" + server2,
-                        "server.3=" + server3,
-                        "server.4=" + server4,
-                        "server.5=" + server5)
-                .fromConfig(qv.getVersion()).inBackground(callback, latch).forEnsemble();
+        client.reconfig().inBackground(callback, latch)
+            .adding("server.2=" + server2,
+                "server.3=" + server3,
+                "server.4=" + server4,
+                "server.5=" + server5)
+            .fromConfig(qv.getVersion()).forEnsemble();
         waitOnDelegateListener.waitForEvent();
         Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString2to5);
         qv = getQuorumVerifier(bytes.get());
         Assert.assertEquals(qv.getAllMembers().size(), 4);
 
-        client.reconfig()
-                .withMembers("server.3=" + server3,
-                        "server.4=" + server4,
-                        "server.5=" + server5)
-                .fromConfig(qv.getVersion()).inBackground(callback, latch).forEnsemble();
+        client.reconfig().inBackground(callback, latch)
+            .adding("server.3=" + server3,
+                "server.4=" + server4,
+                "server.5=" + server5)
+            .fromConfig(qv.getVersion()).forEnsemble();
         waitOnDelegateListener.waitForEvent();
         Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString3to5);
         qv = getQuorumVerifier(bytes.get());
         Assert.assertEquals(qv.getAllMembers().size(), 3);
 
         //Add Servers
-        client.reconfig()
-                .withMembers("server.2=" + server2,
-                        "server.3=" + server3,
-                        "server.4=" + server4,
-                        "server.5=" + server5)
-                .fromConfig(qv.getVersion()).inBackground(callback, latch).forEnsemble();
+        client.reconfig().inBackground(callback, latch)
+            .adding("server.2=" + server2,
+                "server.3=" + server3,
+                "server.4=" + server4,
+                "server.5=" + server5)
+            .fromConfig(qv.getVersion()).forEnsemble();
         waitOnDelegateListener.waitForEvent();
         Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString2to5);
         qv = getQuorumVerifier(bytes.get());
         Assert.assertEquals(qv.getAllMembers().size(), 4);
 
-        client.reconfig()
-                .withMembers("server.1=" + server1,
-                        "server.2=" + server2,
-                        "server.3=" + server3,
-                        "server.4=" + server4,
-                        "server.5=" + server5)
-                .fromConfig(qv.getVersion()).inBackground(callback, latch).forEnsemble();
+        client.reconfig().inBackground(callback, latch)
+            .adding("server.1=" + server1,
+                "server.2=" + server2,
+                "server.3=" + server3,
+                "server.4=" + server4,
+                "server.5=" + server5)
+            .fromConfig(qv.getVersion()).forEnsemble();
         waitOnDelegateListener.waitForEvent();
         Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString1to5);
         qv = getQuorumVerifier(bytes.get());
         Assert.assertEquals(qv.getAllMembers().size(), 5);
     }
 
-
-    static QuorumVerifier getQuorumVerifier(byte[] bytes) throws Exception {
+    static QuorumVerifier getQuorumVerifier(byte[] bytes) throws Exception
+    {
         Properties properties = new Properties();
         properties.load(new StringReader(new String(bytes)));
         return new QuorumMaj(properties);
     }
 
-    static InstanceSpec getInstance(TestingCluster cluster, int id) {
-        for (InstanceSpec spec : cluster.getInstances()) {
-            if (spec.getServerId() == id) {
+    static InstanceSpec getInstance(TestingCluster cluster, int id)
+    {
+        for ( InstanceSpec spec : cluster.getInstances() )
+        {
+            if ( spec.getServerId() == id )
+            {
                 return spec;
             }
         }
         throw new IllegalStateException("InstanceSpec with id:" + id + " not found");
     }
 
-    static String getServerString(QuorumVerifier qv, TestingCluster cluster, long id) throws Exception {
+    static String getServerString(QuorumVerifier qv, TestingCluster cluster, long id) throws Exception
+    {
         String str = qv.getAllMembers().get(id).toString();
         //check if connection string is already there.
-        if (str.contains(";")) {
+        if ( str.contains(";") )
+        {
             return str;
-        } else {
-            return str + ";" + getInstance(cluster, (int) id).getConnectString();
+        }
+        else
+        {
+            return str + ";" + getInstance(cluster, (int)id).getConnectString();
         }
     }
 
-    static String getConnectionString(TestingCluster cluster, long... ids) throws Exception {
+    static String getConnectionString(TestingCluster cluster, long... ids) throws Exception
+    {
         StringBuilder sb = new StringBuilder();
-        Map<Long, InstanceSpec> specs = new HashMap<Long, InstanceSpec>();
-        for (InstanceSpec spec : cluster.getInstances()) {
-            specs.put(new Long(spec.getServerId()), spec);
+        Map<Long, InstanceSpec> specs = new HashMap<>();
+        for ( InstanceSpec spec : cluster.getInstances() )
+        {
+            specs.put((long)spec.getServerId(), spec);
         }
-        for (long id : ids) {
-            if (sb.length() != 0) {
+        for ( long id : ids )
+        {
+            if ( sb.length() != 0 )
+            {
                 sb.append(",");
             }
             sb.append(specs.get(id).getConnectString());
@@ -362,27 +383,34 @@ public class TestReconfiguration {
     }
 
     //Simple EnsembleListener that can wait until the delegate handles the event.
-    private static class WaitOnDelegateListener implements EnsembleListener {
+    private static class WaitOnDelegateListener implements EnsembleListener
+    {
         private CountDownLatch latch = new CountDownLatch(1);
 
         private final EnsembleListener delegate;
 
-        private WaitOnDelegateListener(EnsembleListener delegate) {
+        private WaitOnDelegateListener(EnsembleListener delegate)
+        {
             this.delegate = delegate;
         }
 
         @Override
-        public void connectionStringUpdated(String connectionString) {
+        public void connectionStringUpdated(String connectionString)
+        {
             delegate.connectionStringUpdated(connectionString);
             latch.countDown();
         }
 
-        public void waitForEvent() throws InterruptedException, TimeoutException {
-            if (latch.await(5, TimeUnit.SECONDS)) {
+        public void waitForEvent() throws InterruptedException, TimeoutException
+        {
+            if ( latch.await(5, TimeUnit.SECONDS) )
+            {
                 latch = new CountDownLatch(1);
-            } else {
+            }
+            else
+            {
                 throw new TimeoutException("Failed to receive event in time.");
             }
         }
-    };
+    }
 }
\ No newline at end of file


[12/27] curator git commit: Reworked the reconfig() APIs to be more like the rest of Curator

Posted by dr...@apache.org.
Reworked the reconfig() APIs to be more like the rest of Curator


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/57dbf2e1
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/57dbf2e1
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/57dbf2e1

Branch: refs/heads/CURATOR-215
Commit: 57dbf2e1145d3f11166b89e16fbbeaae09b7ba3e
Parents: 760473d
Author: randgalt <ra...@apache.org>
Authored: Sat May 9 09:13:53 2015 -0500
Committer: Scott Blum <dr...@apache.org>
Committed: Wed Aug 12 17:28:32 2015 -0400

----------------------------------------------------------------------
 .../curator/framework/CuratorFramework.java     |   4 +-
 .../api/AddStatConfigEnsembleable.java          |  32 +
 .../apache/curator/framework/api/Addable.java   |  43 ++
 .../api/BackgroundStatConfigEnsembleable.java   |  24 -
 .../api/BackgroundStatEnsembleable.java         |  24 -
 .../curator/framework/api/Configurable.java     |   6 +-
 .../api/JoinAddStatConfigEnsembleable.java      |  33 ++
 .../JoinBackgroundStatConfigEnsembleable.java   |  30 -
 .../api/JoinLeaveStatConfigEnsembleable.java    |  33 ++
 .../api/JoinStatConfigEnsembleable.java         |  32 +
 .../framework/api/JoinStatConfigurable.java     |  30 +
 .../apache/curator/framework/api/Joinable.java  |  18 +-
 .../api/LeaveAddStatConfigEnsembleable.java     |  32 +
 .../LeaveBackgroundStatConfigEnsembleable.java  |  30 -
 .../api/LeaveStatConfigEnsembleable.java        |  32 +
 .../apache/curator/framework/api/Leaveable.java |  15 +-
 .../curator/framework/api/Memberable.java       |  31 -
 .../api/NonIncrementalReconfigBuilder.java      |  32 -
 .../curator/framework/api/ReconfigBuilder.java  |  10 +-
 .../framework/api/ReconfigBuilderMain.java      |  27 +
 .../framework/api/StatConfigEnsembleable.java   |  26 +
 .../curator/framework/api/StatEnsembleable.java |  26 +
 .../framework/imps/CuratorFrameworkImpl.java    |   6 +-
 .../imps/EnsembleServersAndConfig.java          |  52 --
 .../curator/framework/imps/EnsembleTracker.java | 115 ++--
 .../framework/imps/ReconfigBuilderImpl.java     | 582 ++++++++++++++-----
 .../framework/imps/TestReconfiguration.java     | 240 ++++----
 27 files changed, 1032 insertions(+), 533 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/57dbf2e1/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java b/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
index 181e4e8..7de49ce 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
@@ -123,13 +123,15 @@ public interface CuratorFramework extends Closeable
 
     /**
      * Start a reconfig builder
+     *
      * @return builder object
      */
     public ReconfigBuilder reconfig();
 
     /**
      * Start a getConfig builder
-     * @return
+     *
+     * @return builder object
      */
     public GetConfigBuilder getConfig();
 

http://git-wip-us.apache.org/repos/asf/curator/blob/57dbf2e1/curator-framework/src/main/java/org/apache/curator/framework/api/AddStatConfigEnsembleable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/AddStatConfigEnsembleable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/AddStatConfigEnsembleable.java
new file mode 100644
index 0000000..16f78a2
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/AddStatConfigEnsembleable.java
@@ -0,0 +1,32 @@
+/**
+ * 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.curator.framework.api;
+
+/**
+ * An non-incremental reconfiguration builder.
+ * This builder has access only to the non-incremental reconfiguration methods withMembers, so that we prevent
+ * mixing concepts that can't be used together.
+ */
+public interface AddStatConfigEnsembleable extends
+    Addable<StatConfigEnsembleable>,
+    StatConfigEnsembleable
+{
+
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/57dbf2e1/curator-framework/src/main/java/org/apache/curator/framework/api/Addable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/Addable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/Addable.java
new file mode 100644
index 0000000..e908f1e
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/Addable.java
@@ -0,0 +1,43 @@
+/**
+ * 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.curator.framework.api;
+
+import java.util.List;
+
+public interface Addable<T>
+{
+    /**
+     * Sets one or more members that are meant to be part of the ensemble.
+     * The expected format is server.[id]=[hostname]:[peer port]:[election port]:[type];[client port]
+     *
+     * @param server The server to add as a member of the ensemble.
+     * @return this
+     */
+    T adding(String... server);
+
+    /**
+     * Sets one or more members that are meant to be part of the ensemble.
+     * The expected format is server.[id]=[hostname]:[peer port]:[election port]:[type];[client port]
+     *
+     * @param servers The server to add as a member of the ensemble.
+     * @return this
+     */
+    T adding(List<String> servers);
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/57dbf2e1/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundStatConfigEnsembleable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundStatConfigEnsembleable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundStatConfigEnsembleable.java
deleted file mode 100644
index f109b0f..0000000
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundStatConfigEnsembleable.java
+++ /dev/null
@@ -1,24 +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.curator.framework.api;
-
-public interface BackgroundStatConfigEnsembleable<T> extends
-        Configurable<BackgroundStatEnsembleable<T>>,
-        BackgroundStatEnsembleable<T> {
-}

http://git-wip-us.apache.org/repos/asf/curator/blob/57dbf2e1/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundStatEnsembleable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundStatEnsembleable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundStatEnsembleable.java
deleted file mode 100644
index 62f666d..0000000
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundStatEnsembleable.java
+++ /dev/null
@@ -1,24 +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.curator.framework.api;
-
-public interface BackgroundStatEnsembleable<T> extends
-    BackgroundStatable<Ensembleable<T>>,
-    Ensembleable<T> {
-}

http://git-wip-us.apache.org/repos/asf/curator/blob/57dbf2e1/curator-framework/src/main/java/org/apache/curator/framework/api/Configurable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/Configurable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/Configurable.java
index 39e2c0c..2bc0494 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/Configurable.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/Configurable.java
@@ -16,14 +16,16 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
 package org.apache.curator.framework.api;
 
-public interface Configurable<T> {
+public interface Configurable
+{
 
     /**
      * Sets the configuration version to use.
      * @param config The version of the configuration.
      * @throws Exception
      */
-    BackgroundStatEnsembleable<byte[]> fromConfig(long config) throws Exception;
+    StatEnsembleable<byte[]> fromConfig(long config) throws Exception;
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/57dbf2e1/curator-framework/src/main/java/org/apache/curator/framework/api/JoinAddStatConfigEnsembleable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/JoinAddStatConfigEnsembleable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/JoinAddStatConfigEnsembleable.java
new file mode 100644
index 0000000..a905dd1
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/JoinAddStatConfigEnsembleable.java
@@ -0,0 +1,33 @@
+/**
+ * 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.curator.framework.api;
+
+/**
+ * An incremental reconfiguration builder.
+ * This builder has access only to the incremental reconfiguration methods joining and leaving, so that we prevent
+ * mixing concepts that can't be used together.
+ */
+public interface JoinAddStatConfigEnsembleable extends
+    Joinable<AddStatConfigEnsembleable>,
+    Addable<JoinStatConfigurable>,
+    StatConfigEnsembleable
+{
+
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/57dbf2e1/curator-framework/src/main/java/org/apache/curator/framework/api/JoinBackgroundStatConfigEnsembleable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/JoinBackgroundStatConfigEnsembleable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/JoinBackgroundStatConfigEnsembleable.java
deleted file mode 100644
index ba45efd..0000000
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/JoinBackgroundStatConfigEnsembleable.java
+++ /dev/null
@@ -1,30 +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.curator.framework.api;
-
-/**
- * An incremental reconfiguration builder.
- * This builder has access only to the incremental reconfiguration methods joining and leaving, so that we prevent
- * mixing concepts that can't be used together.
- */
-public interface JoinBackgroundStatConfigEnsembleable extends
-        Joinable<BackgroundStatConfigEnsembleable<byte[]>>,
-        BackgroundStatConfigEnsembleable<byte[]> {
-
-}

http://git-wip-us.apache.org/repos/asf/curator/blob/57dbf2e1/curator-framework/src/main/java/org/apache/curator/framework/api/JoinLeaveStatConfigEnsembleable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/JoinLeaveStatConfigEnsembleable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/JoinLeaveStatConfigEnsembleable.java
new file mode 100644
index 0000000..9642297
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/JoinLeaveStatConfigEnsembleable.java
@@ -0,0 +1,33 @@
+/**
+ * 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.curator.framework.api;
+
+/**
+ * An incremental reconfiguration builder.
+ * This builder has access only to the incremental reconfiguration methods joining and leaving, so that we prevent
+ * mixing concepts that can't be used together.
+ */
+public interface JoinLeaveStatConfigEnsembleable extends
+    Joinable<LeaveStatConfigEnsembleable>,
+    Leaveable<JoinStatConfigEnsembleable>,
+    StatConfigEnsembleable
+{
+
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/57dbf2e1/curator-framework/src/main/java/org/apache/curator/framework/api/JoinStatConfigEnsembleable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/JoinStatConfigEnsembleable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/JoinStatConfigEnsembleable.java
new file mode 100644
index 0000000..5fe7a8c
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/JoinStatConfigEnsembleable.java
@@ -0,0 +1,32 @@
+/**
+ * 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.curator.framework.api;
+
+/**
+ * An incremental reconfiguration builder.
+ * This builder has access only to the incremental reconfiguration methods joining and leaving, so that we prevent
+ * mixing concepts that can't be used together.
+ */
+public interface JoinStatConfigEnsembleable extends
+    Joinable<StatConfigEnsembleable>,
+    StatConfigEnsembleable
+{
+
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/57dbf2e1/curator-framework/src/main/java/org/apache/curator/framework/api/JoinStatConfigurable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/JoinStatConfigurable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/JoinStatConfigurable.java
new file mode 100644
index 0000000..ef17ef4
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/JoinStatConfigurable.java
@@ -0,0 +1,30 @@
+/**
+ * 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.curator.framework.api;
+
+/**
+ * An incremental reconfiguration builder.
+ * This builder has access only to the incremental reconfiguration methods joining and leaving, so that we prevent
+ * mixing concepts that can't be used together.
+ */
+public interface JoinStatConfigurable extends
+    Joinable<Configurable>
+{
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/57dbf2e1/curator-framework/src/main/java/org/apache/curator/framework/api/Joinable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/Joinable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/Joinable.java
index dde5b1c..5cebe4d 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/Joinable.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/Joinable.java
@@ -16,16 +16,28 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
 package org.apache.curator.framework.api;
 
-public interface Joinable<T> {
+import java.util.List;
 
+public interface Joinable<T>
+{
     /**
      * Adds one or more servers to joining the ensemble.
      * The expected format is server.[id]=[hostname]:[peer port]:[election port]:[type];[client port]
-     * @param server The server to joining.
-     * @return this.
+     *
+     * @param server The server joining.
+     * @return this
      */
     T joining(String... server);
 
+    /**
+     * Adds one or more servers to joining the ensemble.
+     * The expected format is server.[id]=[hostname]:[peer port]:[election port]:[type];[client port]
+     *
+     * @param servers The servers joining.
+     * @return this
+     */
+    T joining(List<String> servers);
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/57dbf2e1/curator-framework/src/main/java/org/apache/curator/framework/api/LeaveAddStatConfigEnsembleable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/LeaveAddStatConfigEnsembleable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/LeaveAddStatConfigEnsembleable.java
new file mode 100644
index 0000000..7912d45
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/LeaveAddStatConfigEnsembleable.java
@@ -0,0 +1,32 @@
+/**
+ * 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.curator.framework.api;
+
+/**
+ * An non-incremental reconfiguration builder.
+ * This builder has access only to the non-incremental reconfiguration methods withMembers, so that we prevent
+ * mixing concepts that can't be used together.
+ */
+public interface LeaveAddStatConfigEnsembleable extends
+    Leaveable<AddStatConfigEnsembleable>,
+    Addable<LeaveStatConfigEnsembleable>,
+    StatConfigEnsembleable
+{
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/57dbf2e1/curator-framework/src/main/java/org/apache/curator/framework/api/LeaveBackgroundStatConfigEnsembleable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/LeaveBackgroundStatConfigEnsembleable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/LeaveBackgroundStatConfigEnsembleable.java
deleted file mode 100644
index a6316c1..0000000
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/LeaveBackgroundStatConfigEnsembleable.java
+++ /dev/null
@@ -1,30 +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.curator.framework.api;
-
-/**
- * An non-incremental reconfiguration builder.
- * This builder has access only to the non-incremental reconfiguration methods withMembers, so that we prevent
- * mixing concepts that can't be used together.
- */
-public interface LeaveBackgroundStatConfigEnsembleable extends
-        Leaveable<BackgroundStatConfigEnsembleable<byte[]>>,
-        BackgroundStatConfigEnsembleable<byte[]> {
-
-}

http://git-wip-us.apache.org/repos/asf/curator/blob/57dbf2e1/curator-framework/src/main/java/org/apache/curator/framework/api/LeaveStatConfigEnsembleable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/LeaveStatConfigEnsembleable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/LeaveStatConfigEnsembleable.java
new file mode 100644
index 0000000..ddad854
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/LeaveStatConfigEnsembleable.java
@@ -0,0 +1,32 @@
+/**
+ * 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.curator.framework.api;
+
+/**
+ * An incremental reconfiguration builder.
+ * This builder has access only to the incremental reconfiguration methods joining and leaving, so that we prevent
+ * mixing concepts that can't be used together.
+ */
+public interface LeaveStatConfigEnsembleable extends
+    Leaveable<StatConfigEnsembleable>,
+    StatConfigEnsembleable
+{
+
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/57dbf2e1/curator-framework/src/main/java/org/apache/curator/framework/api/Leaveable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/Leaveable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/Leaveable.java
index a3c3358..6ec3542 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/Leaveable.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/Leaveable.java
@@ -16,15 +16,26 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
 package org.apache.curator.framework.api;
 
-public interface Leaveable<T> {
+import java.util.List;
 
+public interface Leaveable<T>
+{
     /**
      * Sets one or more servers to leaving the ensemble.
-     * @param server The server ids.
+     *
+     * @param server The server ids
      * @return this
      */
     T leaving(String... server);
 
+    /**
+     * Sets one or more servers to leaving the ensemble.
+     *
+     * @param servers The server ids
+     * @return this
+     */
+    T leaving(List<String> servers);
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/57dbf2e1/curator-framework/src/main/java/org/apache/curator/framework/api/Memberable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/Memberable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/Memberable.java
deleted file mode 100644
index 6ef54c1..0000000
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/Memberable.java
+++ /dev/null
@@ -1,31 +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.curator.framework.api;
-
-
-public interface Memberable<T> {
-
-    /**
-     * Sets one or more members that are meant to be part of the ensemble.
-     * The expected format is server.[id]=[hostname]:[peer port]:[election port]:[type];[client port]
-     * @param server The server to add as a member of the ensemble.
-     * @return this.
-     */
-    T withMembers(String... server);
-}

http://git-wip-us.apache.org/repos/asf/curator/blob/57dbf2e1/curator-framework/src/main/java/org/apache/curator/framework/api/NonIncrementalReconfigBuilder.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/NonIncrementalReconfigBuilder.java b/curator-framework/src/main/java/org/apache/curator/framework/api/NonIncrementalReconfigBuilder.java
deleted file mode 100644
index 2f6a9c6..0000000
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/NonIncrementalReconfigBuilder.java
+++ /dev/null
@@ -1,32 +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.curator.framework.api;
-
-/**
- * An non-incremental reconfiguration builder.
- * This builder has access only to the non-incremental reconfiguration methods withMembers, so that we prevent
- * mixing concepts that can't be used together.
- * @param <T>
- */
-public interface NonIncrementalReconfigBuilder<T> extends
-        Memberable<NonIncrementalReconfigBuilder<T>>,
-        DataCallbackable<AsyncReconfigurable>,
-        Statable<SyncReconfigurable> {
-
-}

http://git-wip-us.apache.org/repos/asf/curator/blob/57dbf2e1/curator-framework/src/main/java/org/apache/curator/framework/api/ReconfigBuilder.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/ReconfigBuilder.java b/curator-framework/src/main/java/org/apache/curator/framework/api/ReconfigBuilder.java
index f05b99e..438abcf 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/ReconfigBuilder.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/ReconfigBuilder.java
@@ -16,11 +16,13 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
 package org.apache.curator.framework.api;
 
 public interface ReconfigBuilder extends
-        Joinable<LeaveBackgroundStatConfigEnsembleable>,
-        Leaveable<JoinBackgroundStatConfigEnsembleable>,
-        Memberable<BackgroundStatConfigEnsembleable<byte[]>> {
-
+    Joinable<LeaveAddStatConfigEnsembleable>,
+    Leaveable<JoinAddStatConfigEnsembleable>,
+    Addable<JoinLeaveStatConfigEnsembleable>,
+    Backgroundable<ReconfigBuilderMain>
+{
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/57dbf2e1/curator-framework/src/main/java/org/apache/curator/framework/api/ReconfigBuilderMain.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/ReconfigBuilderMain.java b/curator-framework/src/main/java/org/apache/curator/framework/api/ReconfigBuilderMain.java
new file mode 100644
index 0000000..b86af2d
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/ReconfigBuilderMain.java
@@ -0,0 +1,27 @@
+/**
+ * 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.curator.framework.api;
+
+public interface ReconfigBuilderMain extends
+    Joinable<LeaveAddStatConfigEnsembleable>,
+    Leaveable<JoinAddStatConfigEnsembleable>,
+    Addable<JoinLeaveStatConfigEnsembleable>
+{
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/57dbf2e1/curator-framework/src/main/java/org/apache/curator/framework/api/StatConfigEnsembleable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/StatConfigEnsembleable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/StatConfigEnsembleable.java
new file mode 100644
index 0000000..4700c8c
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/StatConfigEnsembleable.java
@@ -0,0 +1,26 @@
+/**
+ * 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.curator.framework.api;
+
+public interface StatConfigEnsembleable extends
+    Configurable,
+    StatEnsembleable<byte[]>
+{
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/57dbf2e1/curator-framework/src/main/java/org/apache/curator/framework/api/StatEnsembleable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/StatEnsembleable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/StatEnsembleable.java
new file mode 100644
index 0000000..0993b50
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/StatEnsembleable.java
@@ -0,0 +1,26 @@
+/**
+ * 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.curator.framework.api;
+
+public interface StatEnsembleable<T> extends
+    Statable<Ensembleable<T>>,
+    Ensembleable<T>
+{
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/57dbf2e1/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
index b9b9c31..9b96f60 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
@@ -398,12 +398,14 @@ public class CuratorFrameworkImpl implements CuratorFramework
     }
 
     @Override
-    public ReconfigBuilder reconfig() {
+    public ReconfigBuilder reconfig()
+    {
         return new ReconfigBuilderImpl(this);
     }
 
     @Override
-    public GetConfigBuilder getConfig() {
+    public GetConfigBuilder getConfig()
+    {
         return new GetConfigBuilderImpl(this);
     }
 

http://git-wip-us.apache.org/repos/asf/curator/blob/57dbf2e1/curator-framework/src/main/java/org/apache/curator/framework/imps/EnsembleServersAndConfig.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/EnsembleServersAndConfig.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/EnsembleServersAndConfig.java
deleted file mode 100644
index df78aa7..0000000
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/EnsembleServersAndConfig.java
+++ /dev/null
@@ -1,52 +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.curator.framework.imps;
-
-import java.util.Collections;
-import java.util.List;
-
-class EnsembleServersAndConfig {
-    private final List<String> joiningServers;
-    private final List<String> leavingServers;
-    private final List<String> members;
-    private final long config;
-
-    EnsembleServersAndConfig(List<String> joiningServers, List<String> leavingServers, List<String> members, long config) {
-        this.joiningServers = joiningServers.isEmpty() ? null : Collections.unmodifiableList(joiningServers);
-        this.leavingServers = leavingServers.isEmpty() ? null : Collections.unmodifiableList(leavingServers);
-        this.members = members.isEmpty() ? null : Collections.unmodifiableList(members);
-        this.config = config;
-    }
-
-    public List<String> getJoiningServers() {
-        return joiningServers;
-    }
-
-    public List<String> getLeavingServers() {
-        return leavingServers;
-    }
-
-    public List<String> getMembers() {
-        return members;
-    }
-
-    public long getConfig() {
-        return config;
-    }
-}

http://git-wip-us.apache.org/repos/asf/curator/blob/57dbf2e1/curator-framework/src/main/java/org/apache/curator/framework/imps/EnsembleTracker.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/EnsembleTracker.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/EnsembleTracker.java
index a789e42..6688848 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/EnsembleTracker.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/EnsembleTracker.java
@@ -16,6 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
 package org.apache.curator.framework.imps;
 
 import com.google.common.base.Function;
@@ -35,7 +36,6 @@ import org.apache.zookeeper.server.quorum.flexible.QuorumMaj;
 import org.apache.zookeeper.server.quorum.flexible.QuorumVerifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-
 import java.io.ByteArrayInputStream;
 import java.io.Closeable;
 import java.io.IOException;
@@ -46,65 +46,81 @@ import java.util.concurrent.atomic.AtomicReference;
 /**
  * Tracks changes to the ensemble and notifies registered {@link org.apache.curator.ensemble.EnsembleListener} instances.
  */
-public class EnsembleTracker implements Closeable {
-
+public class EnsembleTracker implements Closeable
+{
     private final Logger log = LoggerFactory.getLogger(getClass());
     private final CuratorFramework client;
     private final AtomicReference<State> state = new AtomicReference<State>(State.LATENT);
     private final ListenerContainer<EnsembleListener> listeners = new ListenerContainer<EnsembleListener>();
     private final AtomicBoolean isConnected = new AtomicBoolean(true);
-    private final ConnectionStateListener connectionStateListener = new ConnectionStateListener() {
+    private final ConnectionStateListener connectionStateListener = new ConnectionStateListener()
+    {
         @Override
-        public void stateChanged(CuratorFramework client, ConnectionState newState) {
-            if ((newState == ConnectionState.CONNECTED) || (newState == ConnectionState.RECONNECTED)) {
-                if (isConnected.compareAndSet(false, true)) {
-                    try {
+        public void stateChanged(CuratorFramework client, ConnectionState newState)
+        {
+            if ( (newState == ConnectionState.CONNECTED) || (newState == ConnectionState.RECONNECTED) )
+            {
+                if ( isConnected.compareAndSet(false, true) )
+                {
+                    try
+                    {
                         reset();
-                    } catch (Exception e) {
+                    }
+                    catch ( Exception e )
+                    {
                         log.error("Trying to reset after reconnection", e);
                     }
                 }
-            } else {
+            }
+            else
+            {
                 isConnected.set(false);
             }
         }
     };
 
-    private final CuratorWatcher watcher = new CuratorWatcher() {
+    private final CuratorWatcher watcher = new CuratorWatcher()
+    {
         @Override
-        public void process(WatchedEvent event) throws Exception {
+        public void process(WatchedEvent event) throws Exception
+        {
             reset();
         }
     };
 
-
-    private enum State {
+    private enum State
+    {
         LATENT,
         STARTED,
         CLOSED
     }
 
-    private final BackgroundCallback backgroundCallback = new BackgroundCallback() {
+    private final BackgroundCallback backgroundCallback = new BackgroundCallback()
+    {
         @Override
-        public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
+        public void processResult(CuratorFramework client, CuratorEvent event) throws Exception
+        {
             processBackgroundResult(event);
         }
     };
 
-
-    public EnsembleTracker(CuratorFramework client) {
+    public EnsembleTracker(CuratorFramework client)
+    {
         this.client = client;
     }
 
-    public void start() throws Exception {
+    public void start() throws Exception
+    {
         Preconditions.checkState(state.compareAndSet(State.LATENT, State.STARTED), "Cannot be started more than once");
         client.getConnectionStateListenable().addListener(connectionStateListener);
         reset();
     }
 
     @Override
-    public void close() throws IOException {
-        if (state.compareAndSet(State.STARTED, State.CLOSED)) {
+    public void close() throws IOException
+    {
+        if ( state.compareAndSet(State.STARTED, State.CLOSED) )
+        {
             listeners.clear();
         }
         client.getConnectionStateListenable().removeListener(connectionStateListener);
@@ -122,27 +138,35 @@ public class EnsembleTracker implements Closeable {
         return listeners;
     }
 
-    private void reset() throws Exception {
+    private void reset() throws Exception
+    {
         client.getConfig().usingWatcher(watcher).inBackground(backgroundCallback).forEnsemble();
     }
 
-    private void processBackgroundResult(CuratorEvent event) throws Exception {
-        switch (event.getType()) {
-            case GET_CONFIG: {
-                if (event.getResultCode() == KeeperException.Code.OK.intValue()) {
-                    processConfigData(event.getData());
-                }
+    private void processBackgroundResult(CuratorEvent event) throws Exception
+    {
+        switch ( event.getType() )
+        {
+        case GET_CONFIG:
+        {
+            if ( event.getResultCode() == KeeperException.Code.OK.intValue() )
+            {
+                processConfigData(event.getData());
             }
         }
+        }
     }
 
-    private void processConfigData(byte[] data) throws Exception {
+    private void processConfigData(byte[] data) throws Exception
+    {
         Properties properties = new Properties();
         properties.load(new ByteArrayInputStream(data));
         QuorumVerifier qv = new QuorumMaj(properties);
         StringBuilder sb = new StringBuilder();
-        for (QuorumPeer.QuorumServer server : qv.getAllMembers().values()) {
-            if (sb.length() != 0) {
+        for ( QuorumPeer.QuorumServer server : qv.getAllMembers().values() )
+        {
+            if ( sb.length() != 0 )
+            {
                 sb.append(",");
             }
             sb.append(server.clientAddr.getAddress().getHostAddress()).append(":").append(server.clientAddr.getPort());
@@ -150,18 +174,23 @@ public class EnsembleTracker implements Closeable {
 
         final String connectionString = sb.toString();
         listeners.forEach
-                (
-                        new Function<EnsembleListener, Void>() {
-                            @Override
-                            public Void apply(EnsembleListener listener) {
-                                try {
-                                    listener.connectionStringUpdated(connectionString);
-                                } catch (Exception e) {
-                                    log.error("Calling listener", e);
-                                }
-                                return null;
-                            }
+            (
+                new Function<EnsembleListener, Void>()
+                {
+                    @Override
+                    public Void apply(EnsembleListener listener)
+                    {
+                        try
+                        {
+                            listener.connectionStringUpdated(connectionString);
+                        }
+                        catch ( Exception e )
+                        {
+                            log.error("Calling listener", e);
                         }
-                );
+                        return null;
+                    }
+                }
+            );
     }
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/57dbf2e1/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java
index 5489691..15ed13e 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java
@@ -16,201 +16,489 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
 package org.apache.curator.framework.imps;
 
+import com.google.common.collect.ImmutableList;
 import org.apache.curator.RetryLoop;
 import org.apache.curator.TimeTrace;
-import org.apache.curator.framework.api.BackgroundCallback;
-import org.apache.curator.framework.api.BackgroundStatConfigEnsembleable;
-import org.apache.curator.framework.api.BackgroundStatEnsembleable;
-import org.apache.curator.framework.api.CuratorEvent;
-import org.apache.curator.framework.api.CuratorEventType;
-import org.apache.curator.framework.api.Ensembleable;
-import org.apache.curator.framework.api.JoinBackgroundStatConfigEnsembleable;
-import org.apache.curator.framework.api.LeaveBackgroundStatConfigEnsembleable;
-import org.apache.curator.framework.api.ReconfigBuilder;
+import org.apache.curator.framework.api.*;
 import org.apache.zookeeper.AsyncCallback;
 import org.apache.zookeeper.data.Stat;
-
+import org.apache.zookeeper.server.DataTree;
 import java.util.Arrays;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.concurrent.Callable;
 import java.util.concurrent.Executor;
 
-public class ReconfigBuilderImpl implements ReconfigBuilder {
-
+public class ReconfigBuilderImpl implements
+    ReconfigBuilder,
+    ReconfigBuilderMain,
+    StatEnsembleable<byte[]>,
+    Configurable,
+    StatConfigEnsembleable,
+    BackgroundOperation<Void>
+{
     private final CuratorFrameworkImpl client;
 
-    public ReconfigBuilderImpl(CuratorFrameworkImpl client) {
+    private Backgrounding backgrounding;
+    private Stat responseStat;
+    private long fromConfig = -1;
+    private List<String> adding;
+    private List<String> joining;
+    private List<String> leaving;
+
+    public ReconfigBuilderImpl(CuratorFrameworkImpl client)
+    {
         this.client = client;
     }
 
-    private static class ReconfigBuilderBase implements BackgroundStatConfigEnsembleable<byte[]>, Ensembleable<byte[]>, BackgroundOperation<EnsembleServersAndConfig> {
+    @Override
+    public byte[] forEnsemble() throws Exception
+    {
+        if ( backgrounding != null )
+        {
+            client.processBackgroundOperation(new OperationAndData<>(this, null, backgrounding.getCallback(), null, backgrounding.getContext()), null);
+            return new byte[0];
+        }
+        else
+        {
+            return ensembleInForeground();
+        }
+    }
 
-        final CuratorFrameworkImpl client;
-        final List<String> joiningServers = new LinkedList<String>();
-        final List<String> leavingServers = new LinkedList<String>();
-        final List<String> members = new LinkedList<String>();
-        Backgrounding backgrounding;
-        Stat stat;
-        long config;
+    @Override
+    public Ensembleable<byte[]> storingStatIn(Stat stat)
+    {
+        responseStat = stat;
+        return this;
+    }
 
-        private ReconfigBuilderBase(CuratorFrameworkImpl client) {
-            this.client = client;
-            backgrounding = new Backgrounding();
-        }
+    @Override
+    public StatEnsembleable<byte[]> fromConfig(long config) throws Exception
+    {
+        fromConfig = config;
+        return this;
+    }
 
-        @Override
-        public Ensembleable<byte[]> inBackground() {
-            backgrounding = new Backgrounding();
-            return this;
-        }
+    @Override
+    public JoinLeaveStatConfigEnsembleable adding(String... server)
+    {
+        return adding((server != null) ? Arrays.asList(server) : null);
+    }
 
-        @Override
-        public Ensembleable<byte[]> inBackground(Object context) {
-            backgrounding = new Backgrounding(context);
-            return this;
-        }
+    @Override
+    public JoinLeaveStatConfigEnsembleable adding(List<String> servers)
+    {
+        this.adding = (servers != null) ? ImmutableList.copyOf(servers) : ImmutableList.<String>of();
 
-        @Override
-        public Ensembleable<byte[]> inBackground(BackgroundCallback callback) {
-            backgrounding = new Backgrounding(callback);
-            return this;
-        }
+        return new JoinLeaveStatConfigEnsembleable()
+        {
+            @Override
+            public byte[] forEnsemble() throws Exception
+            {
+                return ReconfigBuilderImpl.this.forEnsemble();
+            }
 
-        @Override
-        public Ensembleable<byte[]> inBackground(BackgroundCallback callback, Object context) {
-            backgrounding = new Backgrounding(callback, context);
-            return this;
-        }
+            @Override
+            public Ensembleable<byte[]> storingStatIn(Stat stat)
+            {
+                return ReconfigBuilderImpl.this.storingStatIn(stat);
+            }
 
-        @Override
-        public Ensembleable<byte[]> inBackground(BackgroundCallback callback, Executor executor) {
-            backgrounding = new Backgrounding(callback, executor);
-            return this;
-        }
+            @Override
+            public StatEnsembleable<byte[]> fromConfig(long config) throws Exception
+            {
+                return ReconfigBuilderImpl.this.fromConfig(config);
+            }
 
-        @Override
-        public Ensembleable<byte[]> inBackground(BackgroundCallback callback, Object context, Executor executor) {
-            backgrounding = new Backgrounding(client, callback, context, executor);
-            return this;
-        }
+            @Override
+            public LeaveStatConfigEnsembleable joining(String... server)
+            {
+                return joining((server != null) ? Arrays.asList(server) : null);
+            }
 
-        @Override
-        public BackgroundStatEnsembleable<byte[]> fromConfig(long config) throws Exception {
-            this.config = config;
-            return this;
-        }
+            @Override
+            public LeaveStatConfigEnsembleable joining(List<String> servers)
+            {
+                return new LeaveStatConfigEnsembleable()
+                {
+                    @Override
+                    public byte[] forEnsemble() throws Exception
+                    {
+                        return ReconfigBuilderImpl.this.forEnsemble();
+                    }
 
-        @Override
-        public Ensembleable<byte[]> storingStatIn(Stat stat) {
-            this.stat = stat;
-            return this;
-        }
+                    @Override
+                    public Ensembleable<byte[]> storingStatIn(Stat stat)
+                    {
+                        return ReconfigBuilderImpl.this.storingStatIn(stat);
+                    }
+
+                    @Override
+                    public StatEnsembleable<byte[]> fromConfig(long config) throws Exception
+                    {
+                        return ReconfigBuilderImpl.this.fromConfig(config);
+                    }
 
-        @Override
-        public byte[] forEnsemble() throws Exception {
-            if (backgrounding.inBackground()) {
-                client.processBackgroundOperation(new OperationAndData<EnsembleServersAndConfig>(this,
-                        new EnsembleServersAndConfig(joiningServers, leavingServers, members, config),
-                        backgrounding.getCallback(), null, backgrounding.getContext()), null);
-                return new byte[0];
-            } else {
-                return ensembleInForeground();
+                    @Override
+                    public StatConfigEnsembleable leaving(List<String> servers)
+                    {
+                        return ReconfigBuilderImpl.this.leaving(servers);
+                    }
+
+                    @Override
+                    public StatConfigEnsembleable leaving(String... server)
+                    {
+                        return ReconfigBuilderImpl.this.leaving(server);
+                    }
+                };
             }
-        }
 
-        private byte[] ensembleInForeground() throws Exception {
-            TimeTrace trace = client.getZookeeperClient().startTracer("ReconfigBuilderImpl-Foreground");
-            byte[] responseData = RetryLoop.callWithRetry
-                    (
-                            client.getZookeeperClient(),
-                            new Callable<byte[]>() {
-                                @Override
-                                public byte[] call() throws Exception {
-                                    return client.getZooKeeper().reconfig(
-                                            joiningServers.isEmpty() ? null : joiningServers,
-                                            leavingServers.isEmpty() ? null : leavingServers,
-                                            members.isEmpty() ? null : members,
-                                            config,
-                                            stat
-                                    );
-                                }
-                            }
-                    );
-            trace.commit();
-            return responseData;
-        }
+            @Override
+            public JoinStatConfigEnsembleable leaving(String... server)
+            {
+                return leaving((server != null) ? Arrays.asList(server) : null);
+            }
 
-        @Override
-        public void performBackgroundOperation(final OperationAndData<EnsembleServersAndConfig> operationAndData) throws Exception {
-            final TimeTrace trace = client.getZookeeperClient().startTracer("ReconfigBuilderImpl-Background");
-            AsyncCallback.DataCallback callback = new AsyncCallback.DataCallback() {
-                @Override
-                public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat) {
-                    trace.commit();
-                    CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.RECONFIG, rc, path, null, ctx, stat, data, null, null, null);
-                    client.processBackgroundOperation(operationAndData, event);
-                }
-            };
-            client.getZooKeeper().reconfig(
-                    operationAndData.getData().getJoiningServers(),
-                    operationAndData.getData().getLeavingServers(),
-                    operationAndData.getData().getMembers(),
-                    operationAndData.getData().getConfig(),
-                    callback,
-                    operationAndData.getContext()
-            );
+            @Override
+            public JoinStatConfigEnsembleable leaving(List<String> servers)
+            {
+                return new JoinStatConfigEnsembleable()
+                {
+                    @Override
+                    public byte[] forEnsemble() throws Exception
+                    {
+                        return ReconfigBuilderImpl.this.forEnsemble();
+                    }
 
-        }
+                    @Override
+                    public Ensembleable<byte[]> storingStatIn(Stat stat)
+                    {
+                        return ReconfigBuilderImpl.this.storingStatIn(stat);
+                    }
+
+                    @Override
+                    public StatEnsembleable<byte[]> fromConfig(long config) throws Exception
+                    {
+                        return ReconfigBuilderImpl.this.fromConfig(config);
+                    }
+
+                    @Override
+                    public StatConfigEnsembleable joining(List<String> servers)
+                    {
+                        return ReconfigBuilderImpl.this.joining(servers);
+                    }
+
+                    @Override
+                    public StatConfigEnsembleable joining(String... server)
+                    {
+                        return ReconfigBuilderImpl.this.joining(server);
+                    }
+                };
+            }
+        };
     }
 
-    private static class JoinReconfigBuilderConfig extends ReconfigBuilderBase implements JoinBackgroundStatConfigEnsembleable {
+    @Override
+    public ReconfigBuilderMain inBackground()
+    {
+        backgrounding = new Backgrounding();
+        return this;
+    }
 
-        private JoinReconfigBuilderConfig(CuratorFrameworkImpl client) {
-            super(client);
-        }
+    @Override
+    public ReconfigBuilderMain inBackground(Object context)
+    {
+        backgrounding = new Backgrounding(context);
+        return this;
+    }
 
-        @Override
-        public BackgroundStatConfigEnsembleable<byte[]> joining(String... servers) {
-            joiningServers.addAll(Arrays.asList(servers));
-            return this;
-        }
+    @Override
+    public ReconfigBuilderMain inBackground(BackgroundCallback callback)
+    {
+        backgrounding = new Backgrounding(callback);
+        return this;
     }
 
-    private static class LeaveReconfigBuilderConfig extends ReconfigBuilderBase implements LeaveBackgroundStatConfigEnsembleable {
+    @Override
+    public ReconfigBuilderMain inBackground(BackgroundCallback callback, Object context)
+    {
+        backgrounding = new Backgrounding(callback, context);
+        return this;
+    }
 
-        private LeaveReconfigBuilderConfig(CuratorFrameworkImpl client) {
-            super(client);
-        }
+    @Override
+    public ReconfigBuilderMain inBackground(BackgroundCallback callback, Executor executor)
+    {
+        backgrounding = new Backgrounding(callback, executor);
+        return this;
+    }
 
-        @Override
-        public BackgroundStatConfigEnsembleable<byte[]> leaving(String... servers) {
-            leavingServers.addAll(Arrays.asList(servers));
-            return this;
-        }
+    @Override
+    public ReconfigBuilderMain inBackground(BackgroundCallback callback, Object context, Executor executor)
+    {
+        backgrounding = new Backgrounding(client, callback, context, executor);
+        return this;
     }
 
+    @Override
+    public LeaveAddStatConfigEnsembleable joining(String... server)
+    {
+        return joining((server != null) ? Arrays.asList(server) : null);
+    }
 
     @Override
-    public LeaveBackgroundStatConfigEnsembleable joining(String... servers) {
-        LeaveReconfigBuilderConfig builder = new LeaveReconfigBuilderConfig(client);
-        builder.joiningServers.addAll(Arrays.asList(servers));
-        return builder;
+    public LeaveAddStatConfigEnsembleable joining(List<String> servers)
+    {
+        joining = (servers != null) ? ImmutableList.copyOf(servers) : ImmutableList.<String>of();
+
+        return new LeaveAddStatConfigEnsembleable()
+        {
+            @Override
+            public byte[] forEnsemble() throws Exception
+            {
+                return ReconfigBuilderImpl.this.forEnsemble();
+            }
+
+            @Override
+            public Ensembleable<byte[]> storingStatIn(Stat stat)
+            {
+                return ReconfigBuilderImpl.this.storingStatIn(stat);
+            }
+
+            @Override
+            public StatEnsembleable<byte[]> fromConfig(long config) throws Exception
+            {
+                return ReconfigBuilderImpl.this.fromConfig(config);
+            }
+
+            @Override
+            public LeaveStatConfigEnsembleable adding(String... server)
+            {
+                return adding((server != null) ? Arrays.asList(server) : null);
+            }
+
+            @Override
+            public LeaveStatConfigEnsembleable adding(List<String> servers)
+            {
+                return new LeaveStatConfigEnsembleable()
+                {
+                    @Override
+                    public byte[] forEnsemble() throws Exception
+                    {
+                        return ReconfigBuilderImpl.this.forEnsemble();
+                    }
+
+                    @Override
+                    public Ensembleable<byte[]> storingStatIn(Stat stat)
+                    {
+                        return ReconfigBuilderImpl.this.storingStatIn(stat);
+                    }
+
+                    @Override
+                    public StatEnsembleable<byte[]> fromConfig(long config) throws Exception
+                    {
+                        return ReconfigBuilderImpl.this.fromConfig(config);
+                    }
+
+                    @Override
+                    public StatConfigEnsembleable leaving(List<String> servers)
+                    {
+                        return ReconfigBuilderImpl.this.leaving(servers);
+                    }
+
+                    @Override
+                    public StatConfigEnsembleable leaving(String... server)
+                    {
+                        return ReconfigBuilderImpl.this.leaving(server);
+                    }
+                };
+            }
+
+            @Override
+            public AddStatConfigEnsembleable leaving(String... server)
+            {
+                return leaving((server != null) ? Arrays.asList(server) : null);
+            }
+
+            @Override
+            public AddStatConfigEnsembleable leaving(List<String> servers)
+            {
+                return new AddStatConfigEnsembleable()
+                {
+                    @Override
+                    public byte[] forEnsemble() throws Exception
+                    {
+                        return ReconfigBuilderImpl.this.forEnsemble();
+                    }
+
+                    @Override
+                    public Ensembleable<byte[]> storingStatIn(Stat stat)
+                    {
+                        return ReconfigBuilderImpl.this.storingStatIn(stat);
+                    }
+
+                    @Override
+                    public StatEnsembleable<byte[]> fromConfig(long config) throws Exception
+                    {
+                        return ReconfigBuilderImpl.this.fromConfig(config);
+                    }
+
+                    @Override
+                    public StatConfigEnsembleable adding(List<String> servers)
+                    {
+                        return ReconfigBuilderImpl.this.adding(servers);
+                    }
+
+                    @Override
+                    public StatConfigEnsembleable adding(String... server)
+                    {
+                        return ReconfigBuilderImpl.this.adding(server);
+                    }
+                };
+            }
+        };
     }
 
     @Override
-    public JoinBackgroundStatConfigEnsembleable leaving(String... servers) {
-        JoinReconfigBuilderConfig builder = new JoinReconfigBuilderConfig(client);
-        builder.leavingServers.addAll(Arrays.asList(servers));
-        return builder;
+    public JoinAddStatConfigEnsembleable leaving(String... server)
+    {
+        return leaving((server != null) ? Arrays.asList(server) : null);
     }
 
     @Override
-    public BackgroundStatConfigEnsembleable<byte[]> withMembers(String... servers) {
-        ReconfigBuilderBase builder = new ReconfigBuilderBase(client);
-        builder.members.addAll(Arrays.asList(servers));
-        return builder;
+    public JoinAddStatConfigEnsembleable leaving(List<String> servers)
+    {
+        leaving = (servers != null) ? ImmutableList.copyOf(servers) : ImmutableList.<String>of();
+
+        return new JoinAddStatConfigEnsembleable()
+        {
+            @Override
+            public byte[] forEnsemble() throws Exception
+            {
+                return ReconfigBuilderImpl.this.forEnsemble();
+            }
+
+            @Override
+            public Ensembleable<byte[]> storingStatIn(Stat stat)
+            {
+                return ReconfigBuilderImpl.this.storingStatIn(stat);
+            }
+
+            @Override
+            public StatEnsembleable<byte[]> fromConfig(long config) throws Exception
+            {
+                return ReconfigBuilderImpl.this.fromConfig(config);
+            }
+
+            @Override
+            public JoinStatConfigurable adding(String... server)
+            {
+                return adding((server != null) ? Arrays.asList(server) : null);
+            }
+
+            @Override
+            public JoinStatConfigurable adding(List<String> servers)
+            {
+                return new JoinStatConfigurable()
+                {
+                    @Override
+                    public Configurable joining(List<String> servers)
+                    {
+                        return ReconfigBuilderImpl.this.joining(servers);
+                    }
+
+                    @Override
+                    public Configurable joining(String... server)
+                    {
+                        return ReconfigBuilderImpl.this.joining(server);
+                    }
+                };
+            }
+
+            @Override
+            public AddStatConfigEnsembleable joining(String... server)
+            {
+                return joining((server != null) ? Arrays.asList(server) : null);
+            }
+
+            @Override
+            public AddStatConfigEnsembleable joining(List<String> servers)
+            {
+                return new AddStatConfigEnsembleable()
+                {
+                    @Override
+                    public byte[] forEnsemble() throws Exception
+                    {
+                        return ReconfigBuilderImpl.this.forEnsemble();
+                    }
+
+                    @Override
+                    public Ensembleable<byte[]> storingStatIn(Stat stat)
+                    {
+                        return ReconfigBuilderImpl.this.storingStatIn(stat);
+                    }
+
+                    @Override
+                    public StatEnsembleable<byte[]> fromConfig(long config) throws Exception
+                    {
+                        return ReconfigBuilderImpl.this.fromConfig(config);
+                    }
+
+                    @Override
+                    public StatConfigEnsembleable adding(List<String> servers)
+                    {
+                        return ReconfigBuilderImpl.this.adding(servers);
+                    }
+
+                    @Override
+                    public StatConfigEnsembleable adding(String... server)
+                    {
+                        return ReconfigBuilderImpl.this.adding(server);
+                    }
+                };
+            }
+        };
+    }
+
+    @Override
+    public void performBackgroundOperation(final OperationAndData<Void> data) throws Exception
+    {
+        final TimeTrace trace = client.getZookeeperClient().startTracer("ReconfigBuilderImpl-Background");
+        AsyncCallback.DataCallback callback = new AsyncCallback.DataCallback()
+        {
+            @Override
+            public void processResult(int rc, String path, Object ctx, byte[] bytes, Stat stat)
+            {
+                trace.commit();
+                if ( (responseStat != null) && (stat != null) )
+                {
+                    DataTree.copyStat(stat, responseStat);
+                }
+                CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.RECONFIG, rc, path, null, ctx, stat, bytes, null, null, null);
+                client.processBackgroundOperation(data, event);
+            }
+        };
+        client.getZooKeeper().reconfig(joining, leaving, adding, fromConfig, callback, backgrounding.getContext());
+    }
+
+    private byte[] ensembleInForeground() throws Exception
+    {
+        TimeTrace trace = client.getZookeeperClient().startTracer("ReconfigBuilderImpl-Foreground");
+        byte[] responseData = RetryLoop.callWithRetry
+            (
+                client.getZookeeperClient(),
+                new Callable<byte[]>()
+                {
+                    @Override
+                    public byte[] call() throws Exception
+                    {
+                        return client.getZooKeeper().reconfig(joining, leaving, adding, fromConfig, responseStat);
+                    }
+                }
+            );
+        trace.commit();
+        return responseData;
     }
 }


[20/27] curator git commit: Initial implementation finished. Uses old transactions internal code for consistency. However, this makes the implementation a bit cumbersome. Old APIs are deprecated. In the future, this can all be cleaned up

Posted by dr...@apache.org.
Initial implementation finished. Uses old transactions internal code for consistency. However, this makes the implementation a bit cumbersome. Old APIs are deprecated. In the future, this can all be cleaned up


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/7df5ab38
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/7df5ab38
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/7df5ab38

Branch: refs/heads/CURATOR-215
Commit: 7df5ab38d6055bfe6439e7337816ea00768a5401
Parents: d1e17eb
Author: randgalt <ra...@apache.org>
Authored: Sat May 9 14:57:28 2015 -0500
Committer: Scott Blum <dr...@apache.org>
Committed: Wed Aug 12 17:29:42 2015 -0400

----------------------------------------------------------------------
 .../curator/framework/CuratorFramework.java     |  10 +-
 .../curator/framework/api/CuratorEvent.java     |   7 +
 .../curator/framework/api/CuratorEventType.java |   5 +
 .../transaction/CuratorMultiTransaction.java    |   5 +-
 .../CuratorMultiTransactionMain.java            |   6 +-
 .../framework/api/transaction/CuratorOp.java    |  28 +++
 .../api/transaction/CuratorTransaction.java     |  11 +-
 .../transaction/CuratorTransactionResult.java   |  11 +-
 .../api/transaction/OperationType.java          |   8 +-
 .../transaction/TransactionCheckBuilder.java    |   6 +-
 .../transaction/TransactionCreateBuilder.java   |  10 +-
 .../transaction/TransactionDeleteBuilder.java   |   6 +-
 .../api/transaction/TransactionOp.java          |  30 +++
 .../transaction/TransactionSetDataBuilder.java  |   8 +-
 .../framework/api/transaction/TypeAndPath.java  |  41 ++++
 .../framework/imps/BackgroundSyncImpl.java      |   2 +-
 .../framework/imps/CreateBuilderImpl.java       |  19 +-
 .../framework/imps/CuratorEventImpl.java        |  35 ++-
 .../framework/imps/CuratorFrameworkImpl.java    |  24 +-
 .../imps/CuratorMultiTransactionImpl.java       |  51 ++++-
 .../imps/CuratorMultiTransactionRecord.java     |  17 +-
 .../framework/imps/CuratorTransactionImpl.java  | 149 +++++++------
 .../framework/imps/DeleteBuilderImpl.java       |  13 +-
 .../framework/imps/ExistsBuilderImpl.java       |   2 +-
 .../framework/imps/ExtractingCuratorOp.java     |  59 +++++
 .../framework/imps/GetACLBuilderImpl.java       |   2 +-
 .../framework/imps/GetChildrenBuilderImpl.java  |   2 +-
 .../framework/imps/GetConfigBuilderImpl.java    |   2 +-
 .../framework/imps/GetDataBuilderImpl.java      |   2 +-
 .../framework/imps/ReconfigBuilderImpl.java     |   2 +-
 .../framework/imps/SetACLBuilderImpl.java       |   2 +-
 .../framework/imps/SetDataBuilderImpl.java      |  23 +-
 .../curator/framework/imps/SyncBuilderImpl.java |   2 +-
 .../framework/imps/TransactionOpImpl.java       |  65 ++++++
 .../framework/imps/TestTransactions.java        | 139 ------------
 .../framework/imps/TestTransactionsNew.java     | 218 +++++++++++++++++++
 .../framework/imps/TestTransactionsOld.java     | 141 ++++++++++++
 37 files changed, 838 insertions(+), 325 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java b/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
index f14253f..1bc1535 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
@@ -23,9 +23,9 @@ import org.apache.curator.CuratorZookeeperClient;
 import org.apache.curator.framework.api.*;
 import org.apache.curator.framework.api.transaction.CuratorMultiTransaction;
 import org.apache.curator.framework.api.transaction.CuratorTransaction;
+import org.apache.curator.framework.api.transaction.TransactionOp;
 import org.apache.curator.framework.imps.CuratorFrameworkState;
 import org.apache.curator.framework.listen.Listenable;
-import org.apache.curator.framework.state.ConnectionState;
 import org.apache.curator.framework.state.ConnectionStateListener;
 import org.apache.curator.utils.EnsurePath;
 import org.apache.zookeeper.Watcher;
@@ -140,6 +140,7 @@ public interface CuratorFramework extends Closeable
      * Start a transaction builder
      *
      * @return builder object
+     * @deprecated use {@link #transaction()} instead
      */
     public CuratorTransaction inTransaction();
 
@@ -151,6 +152,13 @@ public interface CuratorFramework extends Closeable
     public CuratorMultiTransaction transaction();
 
     /**
+     * Allocate an operation that can be used with {@link #transaction()}
+     *
+     * @return operation builder
+     */
+    public TransactionOp transactionOp();
+
+    /**
      * Perform a sync on the given path - syncs are always in the background
      *
      * @param path                    the path

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/api/CuratorEvent.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/CuratorEvent.java b/curator-framework/src/main/java/org/apache/curator/framework/api/CuratorEvent.java
index 2a5408c..673613c 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/CuratorEvent.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/CuratorEvent.java
@@ -18,6 +18,8 @@
  */
 package org.apache.curator.framework.api;
 
+import org.apache.curator.framework.api.transaction.CuratorTransactionResult;
+import org.apache.zookeeper.OpResult;
 import org.apache.zookeeper.WatchedEvent;
 import org.apache.zookeeper.data.ACL;
 import org.apache.zookeeper.data.Stat;
@@ -80,6 +82,11 @@ public interface CuratorEvent
     public List<ACL> getACLList();
 
     /**
+     * @return any operation results or null
+     */
+    public List<CuratorTransactionResult> getOpResults();
+
+    /**
      * If {@link #getType()} returns {@link CuratorEventType#WATCHED} this will
      * return the WatchedEvent
      *

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/api/CuratorEventType.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/CuratorEventType.java b/curator-framework/src/main/java/org/apache/curator/framework/api/CuratorEventType.java
index 50e9195..5a2dc56 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/CuratorEventType.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/CuratorEventType.java
@@ -69,6 +69,11 @@ public enum CuratorEventType
     SET_ACL,
 
     /**
+     * Corresponds to {@link CuratorFramework#transaction()}
+     */
+    TRANSACTION,
+
+    /**
      * Corresponds to {@link CuratorFramework#getConfig()}
      */
     GET_CONFIG,

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorMultiTransaction.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorMultiTransaction.java b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorMultiTransaction.java
index 605ad2e..07bf191 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorMultiTransaction.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorMultiTransaction.java
@@ -20,7 +20,8 @@ package org.apache.curator.framework.api.transaction;
 
 import org.apache.curator.framework.api.Backgroundable;
 
-public interface CuratorMultiTransaction
-    extends Backgroundable<CuratorMultiTransactionMain>
+public interface CuratorMultiTransaction extends
+    Backgroundable<CuratorMultiTransactionMain>,
+    CuratorMultiTransactionMain
 {
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorMultiTransactionMain.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorMultiTransactionMain.java b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorMultiTransactionMain.java
index 02c59af..6b4910d 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorMultiTransactionMain.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorMultiTransactionMain.java
@@ -18,13 +18,11 @@
  */
 package org.apache.curator.framework.api.transaction;
 
-import org.apache.zookeeper.Op;
-import org.apache.zookeeper.OpResult;
 import java.util.List;
 
 public interface CuratorMultiTransactionMain
 {
-    List<OpResult> forOperations(Op... operations) throws Exception;
+    List<CuratorTransactionResult> forOperations(CuratorOp... operations) throws Exception;
 
-    List<OpResult> forOperations(List<Op> operations) throws Exception;
+    List<CuratorTransactionResult> forOperations(List<CuratorOp> operations) throws Exception;
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorOp.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorOp.java b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorOp.java
new file mode 100644
index 0000000..533226b
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorOp.java
@@ -0,0 +1,28 @@
+/**
+ * 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.curator.framework.api.transaction;
+
+import org.apache.zookeeper.Op;
+
+public interface CuratorOp
+{
+    Op get();
+
+    TypeAndPath getTypeAndPath();
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorTransaction.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorTransaction.java b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorTransaction.java
index 3901abf..4f2fb02 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorTransaction.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorTransaction.java
@@ -18,6 +18,7 @@
  */
 package org.apache.curator.framework.api.transaction;
 
+import org.apache.curator.framework.CuratorFramework;
 import org.apache.zookeeper.ZooKeeper;
 
 /**
@@ -49,6 +50,8 @@ import org.apache.zookeeper.ZooKeeper;
  *     <b>Important:</b> the operations are not submitted until
  *     {@link CuratorTransactionFinal#commit()} is called.
  * </p>
+ *
+ * @deprecated Use {@link CuratorFramework#transaction()}
  */
 public interface CuratorTransaction
 {
@@ -57,26 +60,26 @@ public interface CuratorTransaction
      *
      * @return builder object
      */
-    public TransactionCreateBuilder create();
+    public TransactionCreateBuilder<CuratorTransactionBridge> create();
 
     /**
      * Start a delete builder in the transaction
      *
      * @return builder object
      */
-    public TransactionDeleteBuilder delete();
+    public TransactionDeleteBuilder<CuratorTransactionBridge> delete();
 
     /**
      * Start a setData builder in the transaction
      *
      * @return builder object
      */
-    public TransactionSetDataBuilder setData();
+    public TransactionSetDataBuilder<CuratorTransactionBridge> setData();
 
     /**
      * Start a check builder in the transaction
      *ChildData
      * @return builder object
      */
-    public TransactionCheckBuilder check();
+    public TransactionCheckBuilder<CuratorTransactionBridge> check();
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorTransactionResult.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorTransactionResult.java b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorTransactionResult.java
index 03bbca2..8d8dc2d 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorTransactionResult.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorTransactionResult.java
@@ -16,6 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
 package org.apache.curator.framework.api.transaction;
 
 import com.google.common.base.Predicate;
@@ -27,9 +28,9 @@ import org.apache.zookeeper.data.Stat;
 public class CuratorTransactionResult
 {
     private final OperationType type;
-    private final String        forPath;
-    private final String        resultPath;
-    private final Stat          resultStat;
+    private final String forPath;
+    private final String resultPath;
+    private final Stat resultStat;
 
     /**
      * Utility that can be passed to Google Guava to find a particular result. E.g.
@@ -41,7 +42,7 @@ public class CuratorTransactionResult
      * @param forPath path
      * @return predicate
      */
-    public static Predicate<CuratorTransactionResult>       ofTypeAndPath(final OperationType type, final String forPath)
+    public static Predicate<CuratorTransactionResult> ofTypeAndPath(final OperationType type, final String forPath)
     {
         return new Predicate<CuratorTransactionResult>()
         {
@@ -73,7 +74,7 @@ public class CuratorTransactionResult
 
     /**
      * Returns the path that was passed to the operation when added
-     * 
+     *
      * @return operation input path
      */
     public String getForPath()

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/OperationType.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/OperationType.java b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/OperationType.java
index 56dcd33..c0aec68 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/OperationType.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/OperationType.java
@@ -24,22 +24,22 @@ package org.apache.curator.framework.api.transaction;
 public enum OperationType
 {
     /**
-     * {@link CuratorTransaction#create()}
+     * {@link TransactionOp#create()}
      */
     CREATE,
 
     /**
-     * {@link CuratorTransaction#delete()}
+     * {@link TransactionOp#delete()}
      */
     DELETE,
 
     /**
-     * {@link CuratorTransaction#setData()}
+     * {@link TransactionOp#setData()}
      */
     SET_DATA,
 
     /**
-     * {@link CuratorTransaction#check()}
+     * {@link TransactionOp#check()}
      */
     CHECK
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionCheckBuilder.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionCheckBuilder.java b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionCheckBuilder.java
index 2bc13d1..6de675c 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionCheckBuilder.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionCheckBuilder.java
@@ -21,8 +21,8 @@ package org.apache.curator.framework.api.transaction;
 import org.apache.curator.framework.api.Pathable;
 import org.apache.curator.framework.api.Versionable;
 
-public interface TransactionCheckBuilder extends
-    Pathable<CuratorTransactionBridge>,
-    Versionable<Pathable<CuratorTransactionBridge>>
+public interface TransactionCheckBuilder<T> extends
+    Pathable<T>,
+    Versionable<Pathable<T>>
 {
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionCreateBuilder.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionCreateBuilder.java b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionCreateBuilder.java
index 6ac3069..cba0cba 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionCreateBuilder.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionCreateBuilder.java
@@ -23,10 +23,10 @@ import org.apache.curator.framework.api.Compressible;
 import org.apache.curator.framework.api.CreateModable;
 import org.apache.curator.framework.api.PathAndBytesable;
 
-public interface TransactionCreateBuilder extends
-    PathAndBytesable<CuratorTransactionBridge>,
-    CreateModable<ACLPathAndBytesable<CuratorTransactionBridge>>,
-    ACLPathAndBytesable<CuratorTransactionBridge>,
-    Compressible<ACLPathAndBytesable<CuratorTransactionBridge>>
+public interface TransactionCreateBuilder<T> extends
+    PathAndBytesable<T>,
+    CreateModable<ACLPathAndBytesable<T>>,
+    ACLPathAndBytesable<T>,
+    Compressible<ACLPathAndBytesable<T>>
 {
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionDeleteBuilder.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionDeleteBuilder.java b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionDeleteBuilder.java
index e165394..d977290 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionDeleteBuilder.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionDeleteBuilder.java
@@ -21,8 +21,8 @@ package org.apache.curator.framework.api.transaction;
 import org.apache.curator.framework.api.Pathable;
 import org.apache.curator.framework.api.Versionable;
 
-public interface TransactionDeleteBuilder extends
-    Pathable<CuratorTransactionBridge>,
-    Versionable<Pathable<CuratorTransactionBridge>>
+public interface TransactionDeleteBuilder<T> extends
+    Pathable<T>,
+    Versionable<Pathable<T>>
 {
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionOp.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionOp.java b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionOp.java
new file mode 100644
index 0000000..742ac1f
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionOp.java
@@ -0,0 +1,30 @@
+/**
+ * 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.curator.framework.api.transaction;
+
+public interface TransactionOp
+{
+    TransactionCreateBuilder<CuratorOp> create();
+
+    TransactionDeleteBuilder<CuratorOp> delete();
+
+    TransactionSetDataBuilder<CuratorOp> setData();
+
+    TransactionCheckBuilder<CuratorOp> check();
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionSetDataBuilder.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionSetDataBuilder.java b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionSetDataBuilder.java
index 777537a..2d4d255 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionSetDataBuilder.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionSetDataBuilder.java
@@ -22,9 +22,9 @@ import org.apache.curator.framework.api.Compressible;
 import org.apache.curator.framework.api.PathAndBytesable;
 import org.apache.curator.framework.api.Versionable;
 
-public interface TransactionSetDataBuilder extends
-    PathAndBytesable<CuratorTransactionBridge>,
-    Versionable<PathAndBytesable<CuratorTransactionBridge>>,
-    Compressible<PathAndBytesable<CuratorTransactionBridge>>
+public interface TransactionSetDataBuilder<T> extends
+    PathAndBytesable<T>,
+    Versionable<PathAndBytesable<T>>,
+    Compressible<PathAndBytesable<T>>
 {
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TypeAndPath.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TypeAndPath.java b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TypeAndPath.java
new file mode 100644
index 0000000..b1cea95
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TypeAndPath.java
@@ -0,0 +1,41 @@
+/**
+ * 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.curator.framework.api.transaction;
+
+public class TypeAndPath
+{
+    private final OperationType type;
+    private final String forPath;
+
+    public TypeAndPath(OperationType type, String forPath)
+    {
+        this.type = type;
+        this.forPath = forPath;
+    }
+
+    public OperationType getType()
+    {
+        return type;
+    }
+
+    public String getForPath()
+    {
+        return forPath;
+    }
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/imps/BackgroundSyncImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/BackgroundSyncImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/BackgroundSyncImpl.java
index af8e458..f0994e3 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/BackgroundSyncImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/BackgroundSyncImpl.java
@@ -46,7 +46,7 @@ class BackgroundSyncImpl implements BackgroundOperation<String>
                 public void processResult(int rc, String path, Object ctx)
                 {
                     trace.commit();
-                    CuratorEventImpl event = new CuratorEventImpl(client, CuratorEventType.SYNC, rc, path, null, ctx, null, null, null, null, null);
+                    CuratorEventImpl event = new CuratorEventImpl(client, CuratorEventType.SYNC, rc, path, null, ctx, null, null, null, null, null, null);
                     client.processBackgroundOperation(operationAndData, event);
                 }
             },

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/imps/CreateBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/CreateBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/CreateBuilderImpl.java
index 6eef4d4..5432190 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/CreateBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/CreateBuilderImpl.java
@@ -26,7 +26,6 @@ import org.apache.curator.RetryLoop;
 import org.apache.curator.TimeTrace;
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.api.*;
-import org.apache.curator.framework.api.transaction.CuratorTransactionBridge;
 import org.apache.curator.framework.api.transaction.OperationType;
 import org.apache.curator.framework.api.transaction.TransactionCreateBuilder;
 import org.apache.curator.utils.ZKPaths;
@@ -70,39 +69,39 @@ class CreateBuilderImpl implements CreateBuilder, BackgroundOperation<PathAndByt
         protectedId = null;
     }
 
-    TransactionCreateBuilder asTransactionCreateBuilder(final CuratorTransactionImpl curatorTransaction, final CuratorMultiTransactionRecord transaction)
+    <T> TransactionCreateBuilder<T> asTransactionCreateBuilder(final T context, final CuratorMultiTransactionRecord transaction)
     {
-        return new TransactionCreateBuilder()
+        return new TransactionCreateBuilder<T>()
         {
             @Override
-            public PathAndBytesable<CuratorTransactionBridge> withACL(List<ACL> aclList)
+            public PathAndBytesable<T> withACL(List<ACL> aclList)
             {
                 CreateBuilderImpl.this.withACL(aclList);
                 return this;
             }
 
             @Override
-            public ACLPathAndBytesable<CuratorTransactionBridge> withMode(CreateMode mode)
+            public ACLPathAndBytesable<T> withMode(CreateMode mode)
             {
                 CreateBuilderImpl.this.withMode(mode);
                 return this;
             }
             
             @Override
-            public ACLPathAndBytesable<CuratorTransactionBridge> compressed()
+            public ACLPathAndBytesable<T> compressed()
             {
                 CreateBuilderImpl.this.compressed();
                 return this;
             }
             
             @Override
-            public CuratorTransactionBridge forPath(String path) throws Exception
+            public T forPath(String path) throws Exception
             {
                 return forPath(path, client.getDefaultData());
             }
 
             @Override
-            public CuratorTransactionBridge forPath(String path, byte[] data) throws Exception
+            public T forPath(String path, byte[] data) throws Exception
             {               
                 if ( compress )
                 {
@@ -111,7 +110,7 @@ class CreateBuilderImpl implements CreateBuilder, BackgroundOperation<PathAndByt
                 
                 String fixedPath = client.fixForNamespace(path);
                 transaction.add(Op.create(fixedPath, data, acling.getAclList(path), createMode), OperationType.CREATE, path);
-                return curatorTransaction;
+                return context;
             }
         };
     }
@@ -537,7 +536,7 @@ class CreateBuilderImpl implements CreateBuilder, BackgroundOperation<PathAndByt
         path = client.unfixForNamespace(path);
         name = client.unfixForNamespace(name);
 
-        CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.CREATE, rc, path, name, ctx, null, null, null, null, null);
+        CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.CREATE, rc, path, name, ctx, null, null, null, null, null, null);
         client.processBackgroundOperation(operationAndData, event);
     }
 

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorEventImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorEventImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorEventImpl.java
index 929fe6d..4aa125f 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorEventImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorEventImpl.java
@@ -16,11 +16,13 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
 package org.apache.curator.framework.imps;
 
 import com.google.common.collect.ImmutableList;
 import org.apache.curator.framework.api.CuratorEvent;
 import org.apache.curator.framework.api.CuratorEventType;
+import org.apache.curator.framework.api.transaction.CuratorTransactionResult;
 import org.apache.zookeeper.WatchedEvent;
 import org.apache.zookeeper.data.ACL;
 import org.apache.zookeeper.data.Stat;
@@ -29,16 +31,17 @@ import java.util.List;
 
 class CuratorEventImpl implements CuratorEvent
 {
-    private final CuratorEventType  type;
-    private final int               resultCode;
-    private final String            path;
-    private final String            name;
-    private final List<String>      children;
-    private final Object            context;
-    private final Stat              stat;
-    private final byte[]            data;
-    private final WatchedEvent      watchedEvent;
-    private final List<ACL>         aclList;
+    private final CuratorEventType type;
+    private final int resultCode;
+    private final String path;
+    private final String name;
+    private final List<String> children;
+    private final Object context;
+    private final Stat stat;
+    private final byte[] data;
+    private final WatchedEvent watchedEvent;
+    private final List<ACL> aclList;
+    private final List<CuratorTransactionResult> opResults;
 
     @Override
     public CuratorEventType getType()
@@ -101,6 +104,12 @@ class CuratorEventImpl implements CuratorEvent
     }
 
     @Override
+    public List<CuratorTransactionResult> getOpResults()
+    {
+        return opResults;
+    }
+
+    @Override
     public String toString()
     {
         return "CuratorEventImpl{" +
@@ -114,20 +123,22 @@ class CuratorEventImpl implements CuratorEvent
             ", data=" + Arrays.toString(data) +
             ", watchedEvent=" + watchedEvent +
             ", aclList=" + aclList +
+            ", opResults=" + opResults +
             '}';
     }
 
-    CuratorEventImpl(CuratorFrameworkImpl client, CuratorEventType type, int resultCode, String path, String name, Object context, Stat stat, byte[] data, List<String> children, WatchedEvent watchedEvent, List<ACL> aclList)
+    CuratorEventImpl(CuratorFrameworkImpl client, CuratorEventType type, int resultCode, String path, String name, Object context, Stat stat, byte[] data, List<String> children, WatchedEvent watchedEvent, List<ACL> aclList, List<CuratorTransactionResult> opResults)
     {
         this.type = type;
         this.resultCode = resultCode;
+        this.opResults = (opResults != null) ? ImmutableList.copyOf(opResults) : null;
         this.path = client.unfixForNamespace(path);
         this.name = name;
         this.context = context;
         this.stat = stat;
         this.data = data;
         this.children = children;
-        this.watchedEvent = (watchedEvent != null) ? new NamespaceWatchedEvent(client, watchedEvent) : watchedEvent;
+        this.watchedEvent = (watchedEvent != null) ? new NamespaceWatchedEvent(client, watchedEvent) : null;
         this.aclList = (aclList != null) ? ImmutableList.copyOf(aclList) : null;
     }
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
index 9b96f60..b41d995 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
@@ -31,7 +31,9 @@ import org.apache.curator.framework.AuthInfo;
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
 import org.apache.curator.framework.api.*;
+import org.apache.curator.framework.api.transaction.CuratorMultiTransaction;
 import org.apache.curator.framework.api.transaction.CuratorTransaction;
+import org.apache.curator.framework.api.transaction.TransactionOp;
 import org.apache.curator.framework.listen.Listenable;
 import org.apache.curator.framework.listen.ListenerContainer;
 import org.apache.curator.framework.state.ConnectionState;
@@ -102,7 +104,7 @@ public class CuratorFrameworkImpl implements CuratorFramework
             @Override
             public void process(WatchedEvent watchedEvent)
             {
-                CuratorEvent event = new CuratorEventImpl(CuratorFrameworkImpl.this, CuratorEventType.WATCHED, watchedEvent.getState().getIntValue(), unfixForNamespace(watchedEvent.getPath()), null, null, null, null, null, watchedEvent, null);
+                CuratorEvent event = new CuratorEventImpl(CuratorFrameworkImpl.this, CuratorEventType.WATCHED, watchedEvent.getState().getIntValue(), unfixForNamespace(watchedEvent.getPath()), null, null, null, null, null, watchedEvent, null, null);
                 processEvent(event);
             }
         }, builder.getRetryPolicy(), builder.canBeReadOnly());
@@ -276,7 +278,7 @@ public class CuratorFrameworkImpl implements CuratorFramework
                 @Override
                 public Void apply(CuratorListener listener)
                 {
-                    CuratorEvent event = new CuratorEventImpl(CuratorFrameworkImpl.this, CuratorEventType.CLOSING, 0, null, null, null, null, null, null, null, null);
+                    CuratorEvent event = new CuratorEventImpl(CuratorFrameworkImpl.this, CuratorEventType.CLOSING, 0, null, null, null, null, null, null, null, null, null);
                     try
                     {
                         listener.eventReceived(CuratorFrameworkImpl.this, event);
@@ -418,6 +420,22 @@ public class CuratorFrameworkImpl implements CuratorFramework
     }
 
     @Override
+    public CuratorMultiTransaction transaction()
+    {
+        Preconditions.checkState(getState() == CuratorFrameworkState.STARTED, "instance must be started before calling this method");
+
+        return new CuratorMultiTransactionImpl(this);
+    }
+
+    @Override
+    public TransactionOp transactionOp()
+    {
+        Preconditions.checkState(getState() == CuratorFrameworkState.STARTED, "instance must be started before calling this method");
+
+        return new TransactionOpImpl(this);
+    }
+
+    @Override
     public Listenable<ConnectionStateListener> getConnectionStateListenable()
     {
         return connectionStateManager.getListenable();
@@ -834,7 +852,7 @@ public class CuratorFrameworkImpl implements CuratorFramework
             if ( e instanceof CuratorConnectionLossException )
             {
                 WatchedEvent watchedEvent = new WatchedEvent(Watcher.Event.EventType.None, Watcher.Event.KeeperState.Disconnected, null);
-                CuratorEvent event = new CuratorEventImpl(this, CuratorEventType.WATCHED, KeeperException.Code.CONNECTIONLOSS.intValue(), null, null, operationAndData.getContext(), null, null, null, watchedEvent, null);
+                CuratorEvent event = new CuratorEventImpl(this, CuratorEventType.WATCHED, KeeperException.Code.CONNECTIONLOSS.intValue(), null, null, operationAndData.getContext(), null, null, null, watchedEvent, null, null);
                 if ( checkBackgroundRetry(operationAndData, event) )
                 {
                     queueOperation(operationAndData);

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorMultiTransactionImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorMultiTransactionImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorMultiTransactionImpl.java
index 0ba3dc7..6881fc2 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorMultiTransactionImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorMultiTransactionImpl.java
@@ -16,26 +16,35 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
 package org.apache.curator.framework.imps;
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
 import org.apache.curator.RetryLoop;
 import org.apache.curator.TimeTrace;
+import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.api.BackgroundCallback;
+import org.apache.curator.framework.api.CuratorEvent;
+import org.apache.curator.framework.api.CuratorEventType;
 import org.apache.curator.framework.api.transaction.CuratorMultiTransaction;
 import org.apache.curator.framework.api.transaction.CuratorMultiTransactionMain;
-import org.apache.zookeeper.Op;
+import org.apache.curator.framework.api.transaction.CuratorOp;
+import org.apache.curator.framework.api.transaction.CuratorTransactionResult;
+import org.apache.zookeeper.AsyncCallback;
 import org.apache.zookeeper.OpResult;
 import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.Callable;
 import java.util.concurrent.Executor;
 
+/**
+ * @deprecated Use {@link CuratorFramework#transaction()}
+ */
 public class CuratorMultiTransactionImpl implements
     CuratorMultiTransaction,
     CuratorMultiTransactionMain,
-    BackgroundOperation<Void>
+    BackgroundOperation<CuratorMultiTransactionRecord>
 {
     private final CuratorFrameworkImpl client;
     private Backgrounding backgrounding = new Backgrounding();
@@ -88,36 +97,54 @@ public class CuratorMultiTransactionImpl implements
     }
 
     @Override
-    public List<OpResult> forOperations(Op... operations) throws Exception
+    public List<CuratorTransactionResult> forOperations(CuratorOp... operations) throws Exception
     {
-        List<Op> ops = (operations != null) ? Arrays.asList(operations) : Lists.<Op>newArrayList();
+        List<CuratorOp> ops = (operations != null) ? Arrays.asList(operations) : Lists.<CuratorOp>newArrayList();
         return forOperations(ops);
     }
 
     @Override
-    public List<OpResult> forOperations(List<Op> operations) throws Exception
+    public List<CuratorTransactionResult> forOperations(List<CuratorOp> operations) throws Exception
     {
         operations = Preconditions.checkNotNull(operations, "operations cannot be null");
         Preconditions.checkArgument(!operations.isEmpty(), "operations list cannot be empty");
 
+        CuratorMultiTransactionRecord record = new CuratorMultiTransactionRecord();
+        for ( CuratorOp curatorOp : operations )
+        {
+            record.add(curatorOp.get(), curatorOp.getTypeAndPath().getType(), curatorOp.getTypeAndPath().getForPath());
+        }
+
         if ( backgrounding.inBackground() )
         {
-            client.processBackgroundOperation(new OperationAndData<>(this, null, backgrounding.getCallback(), null, backgrounding.getContext()), null);
+            client.processBackgroundOperation(new OperationAndData<>(this, record, backgrounding.getCallback(), null, backgrounding.getContext()), null);
             return null;
         }
         else
         {
-            return forOperationsInForeground(operations);
+            return forOperationsInForeground(record);
         }
     }
 
     @Override
-    public void performBackgroundOperation(OperationAndData<Void> data) throws Exception
+    public void performBackgroundOperation(final OperationAndData<CuratorMultiTransactionRecord> operationAndData) throws Exception
     {
-
+        final TimeTrace trace = client.getZookeeperClient().startTracer("CuratorMultiTransactionImpl-Background");
+        AsyncCallback.MultiCallback callback = new AsyncCallback.MultiCallback()
+        {
+            @Override
+            public void processResult(int rc, String path, Object ctx, List<OpResult> opResults)
+            {
+                trace.commit();
+                List<CuratorTransactionResult> curatorResults = (opResults != null) ? CuratorTransactionImpl.wrapResults(client, opResults, operationAndData.getData()) : null;
+                CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.TRANSACTION, rc, path, null, ctx, null, null, null, null, null, curatorResults);
+                client.processBackgroundOperation(operationAndData, event);
+            }
+        };
+        client.getZooKeeper().multi(operationAndData.getData(), callback, backgrounding.getContext());
     }
 
-    private List<OpResult> forOperationsInForeground(final List<Op> operations) throws Exception
+    private List<CuratorTransactionResult> forOperationsInForeground(final CuratorMultiTransactionRecord record) throws Exception
     {
         TimeTrace trace = client.getZookeeperClient().startTracer("CuratorMultiTransactionImpl-Foreground");
         List<OpResult> responseData = RetryLoop.callWithRetry
@@ -128,12 +155,12 @@ public class CuratorMultiTransactionImpl implements
                 @Override
                 public List<OpResult> call() throws Exception
                 {
-                    return client.getZooKeeper().multi(operations);
+                    return client.getZooKeeper().multi(record);
                 }
             }
         );
         trace.commit();
 
-        return responseData;
+        return CuratorTransactionImpl.wrapResults(client, responseData, record);
     }
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorMultiTransactionRecord.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorMultiTransactionRecord.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorMultiTransactionRecord.java
index 1500d6d..0611df6 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorMultiTransactionRecord.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorMultiTransactionRecord.java
@@ -20,6 +20,7 @@ package org.apache.curator.framework.imps;
 
 import com.google.common.collect.Lists;
 import org.apache.curator.framework.api.transaction.OperationType;
+import org.apache.curator.framework.api.transaction.TypeAndPath;
 import org.apache.zookeeper.MultiTransactionRecord;
 import org.apache.zookeeper.Op;
 import java.util.List;
@@ -28,30 +29,18 @@ class CuratorMultiTransactionRecord extends MultiTransactionRecord
 {
     private final List<TypeAndPath>     metadata = Lists.newArrayList();
 
-    static class TypeAndPath
-    {
-        final OperationType type;
-        final String forPath;
-
-        TypeAndPath(OperationType type, String forPath)
-        {
-            this.type = type;
-            this.forPath = forPath;
-        }
-    }
-
     @Override
     public final void add(Op op)
     {
         throw new UnsupportedOperationException();
     }
-    
+
     void add(Op op, OperationType type, String forPath)
     {
         super.add(op);
         metadata.add(new TypeAndPath(type, forPath));
     }
-    
+
     TypeAndPath     getMetadata(int index)
     {
         return metadata.get(index);

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorTransactionImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorTransactionImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorTransactionImpl.java
index 13ffe82..20ec274 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorTransactionImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorTransactionImpl.java
@@ -16,21 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
 package org.apache.curator.framework.imps;
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import org.apache.curator.RetryLoop;
 import org.apache.curator.framework.api.Pathable;
-import org.apache.curator.framework.api.transaction.CuratorTransaction;
-import org.apache.curator.framework.api.transaction.CuratorTransactionBridge;
-import org.apache.curator.framework.api.transaction.CuratorTransactionFinal;
-import org.apache.curator.framework.api.transaction.CuratorTransactionResult;
-import org.apache.curator.framework.api.transaction.OperationType;
-import org.apache.curator.framework.api.transaction.TransactionCheckBuilder;
-import org.apache.curator.framework.api.transaction.TransactionCreateBuilder;
-import org.apache.curator.framework.api.transaction.TransactionDeleteBuilder;
-import org.apache.curator.framework.api.transaction.TransactionSetDataBuilder;
+import org.apache.curator.framework.api.transaction.*;
 import org.apache.zookeeper.KeeperException;
 import org.apache.zookeeper.Op;
 import org.apache.zookeeper.OpResult;
@@ -43,10 +36,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
 
 class CuratorTransactionImpl implements CuratorTransaction, CuratorTransactionBridge, CuratorTransactionFinal
 {
-    private final CuratorFrameworkImpl              client;
-    private final CuratorMultiTransactionRecord     transaction;
+    private final CuratorFrameworkImpl client;
+    private final CuratorMultiTransactionRecord transaction;
 
-    private boolean         isCommitted = false;
+    private boolean isCommitted = false;
 
     CuratorTransactionImpl(CuratorFrameworkImpl client)
     {
@@ -61,49 +54,58 @@ class CuratorTransactionImpl implements CuratorTransaction, CuratorTransactionBr
     }
 
     @Override
-    public TransactionCreateBuilder create()
+    public TransactionCreateBuilder<CuratorTransactionBridge> create()
     {
         Preconditions.checkState(!isCommitted, "transaction already committed");
 
-        return new CreateBuilderImpl(client).asTransactionCreateBuilder(this, transaction);
+        CuratorTransactionBridge asBridge = this;
+        return new CreateBuilderImpl(client).asTransactionCreateBuilder(asBridge, transaction);
     }
 
     @Override
-    public TransactionDeleteBuilder delete()
+    public TransactionDeleteBuilder<CuratorTransactionBridge> delete()
     {
         Preconditions.checkState(!isCommitted, "transaction already committed");
 
-        return new DeleteBuilderImpl(client).asTransactionDeleteBuilder(this, transaction);
+        CuratorTransactionBridge asBridge = this;
+        return new DeleteBuilderImpl(client).asTransactionDeleteBuilder(asBridge, transaction);
     }
 
     @Override
-    public TransactionSetDataBuilder setData()
+    public TransactionSetDataBuilder<CuratorTransactionBridge> setData()
     {
         Preconditions.checkState(!isCommitted, "transaction already committed");
 
-        return new SetDataBuilderImpl(client).asTransactionSetDataBuilder(this, transaction);
+        CuratorTransactionBridge asBridge = this;
+        return new SetDataBuilderImpl(client).asTransactionSetDataBuilder(asBridge, transaction);
     }
 
     @Override
-    public TransactionCheckBuilder check()
+    public TransactionCheckBuilder<CuratorTransactionBridge> check()
     {
         Preconditions.checkState(!isCommitted, "transaction already committed");
 
-        return new TransactionCheckBuilder()
+        CuratorTransactionBridge asBridge = this;
+        return makeTransactionCheckBuilder(client, asBridge, transaction);
+    }
+
+    static <T> TransactionCheckBuilder<T> makeTransactionCheckBuilder(final CuratorFrameworkImpl client, final T context, final CuratorMultiTransactionRecord transaction)
+    {
+        return new TransactionCheckBuilder<T>()
         {
-            private int         version = -1;
+            private int version = -1;
 
             @Override
-            public CuratorTransactionBridge forPath(String path) throws Exception
+            public T forPath(String path) throws Exception
             {
-                String      fixedPath = client.fixForNamespace(path);
+                String fixedPath = client.fixForNamespace(path);
                 transaction.add(Op.check(fixedPath, version), OperationType.CHECK, path);
 
-                return CuratorTransactionImpl.this;
+                return context;
             }
 
             @Override
-            public Pathable<CuratorTransactionBridge> withVersion(int version)
+            public Pathable<T> withVersion(int version)
             {
                 this.version = version;
                 return this;
@@ -118,65 +120,44 @@ class CuratorTransactionImpl implements CuratorTransaction, CuratorTransactionBr
         isCommitted = true;
 
         final AtomicBoolean firstTime = new AtomicBoolean(true);
-        List<OpResult>      resultList = RetryLoop.callWithRetry
-        (
-            client.getZookeeperClient(),
-            new Callable<List<OpResult>>()
-            {
-                @Override
-                public List<OpResult> call() throws Exception
+        List<OpResult> resultList = RetryLoop.callWithRetry
+            (
+                client.getZookeeperClient(),
+                new Callable<List<OpResult>>()
                 {
-                    return doOperation(firstTime);
+                    @Override
+                    public List<OpResult> call() throws Exception
+                    {
+                        return doOperation(firstTime);
+                    }
                 }
-            }
-        );
-        
+            );
+
         if ( resultList.size() != transaction.metadataSize() )
         {
             throw new IllegalStateException(String.format("Result size (%d) doesn't match input size (%d)", resultList.size(), transaction.metadataSize()));
         }
 
-        ImmutableList.Builder<CuratorTransactionResult>     builder = ImmutableList.builder();
-        for ( int i = 0; i < resultList.size(); ++i )
-        {
-            OpResult                                    opResult = resultList.get(i);
-            CuratorMultiTransactionRecord.TypeAndPath   metadata = transaction.getMetadata(i);
-            CuratorTransactionResult                    curatorResult = makeCuratorResult(opResult, metadata);
-            builder.add(curatorResult);
-        }
-
-        return builder.build();
+        return wrapResults(client, resultList, transaction);
     }
 
-    private List<OpResult> doOperation(AtomicBoolean firstTime) throws Exception
+    static List<CuratorTransactionResult> wrapResults(CuratorFrameworkImpl client, List<OpResult> resultList, CuratorMultiTransactionRecord transaction)
     {
-        boolean         localFirstTime = firstTime.getAndSet(false);
-        if ( !localFirstTime )
+        ImmutableList.Builder<CuratorTransactionResult> builder = ImmutableList.builder();
+        for ( int i = 0; i < resultList.size(); ++i )
         {
-
+            OpResult opResult = resultList.get(i);
+            TypeAndPath metadata = transaction.getMetadata(i);
+            CuratorTransactionResult curatorResult = makeCuratorResult(client, opResult, metadata);
+            builder.add(curatorResult);
         }
 
-        List<OpResult>  opResults = client.getZooKeeper().multi(transaction);
-        if ( opResults.size() > 0 )
-        {
-            OpResult        firstResult = opResults.get(0);
-            if ( firstResult.getType() == ZooDefs.OpCode.error )
-            {
-                OpResult.ErrorResult        error = (OpResult.ErrorResult)firstResult;
-                KeeperException.Code        code = KeeperException.Code.get(error.getErr());
-                if ( code == null )
-                {
-                    code = KeeperException.Code.UNIMPLEMENTED;
-                }
-                throw KeeperException.create(code);
-            }
-        }
-        return opResults;
+        return builder.build();
     }
 
-    private CuratorTransactionResult makeCuratorResult(OpResult opResult, CuratorMultiTransactionRecord.TypeAndPath metadata)
+    static CuratorTransactionResult makeCuratorResult(CuratorFrameworkImpl client, OpResult opResult, TypeAndPath metadata)
     {
-        String                                      resultPath = null;
+        String resultPath = null;
         Stat resultStat = null;
         switch ( opResult.getType() )
         {
@@ -188,19 +169,45 @@ class CuratorTransactionImpl implements CuratorTransaction, CuratorTransactionBr
 
             case ZooDefs.OpCode.create:
             {
-                OpResult.CreateResult       createResult = (OpResult.CreateResult)opResult;
+                OpResult.CreateResult createResult = (OpResult.CreateResult)opResult;
                 resultPath = client.unfixForNamespace(createResult.getPath());
                 break;
             }
 
             case ZooDefs.OpCode.setData:
             {
-                OpResult.SetDataResult      setDataResult = (OpResult.SetDataResult)opResult;
+                OpResult.SetDataResult setDataResult = (OpResult.SetDataResult)opResult;
                 resultStat = setDataResult.getStat();
                 break;
             }
         }
 
-        return new CuratorTransactionResult(metadata.type, metadata.forPath, resultPath, resultStat);
+        return new CuratorTransactionResult(metadata.getType(), metadata.getForPath(), resultPath, resultStat);
+    }
+
+    private List<OpResult> doOperation(AtomicBoolean firstTime) throws Exception
+    {
+        boolean localFirstTime = firstTime.getAndSet(false);
+        if ( !localFirstTime )
+        {
+            // TODO
+        }
+
+        List<OpResult> opResults = client.getZooKeeper().multi(transaction);
+        if ( opResults.size() > 0 )
+        {
+            OpResult firstResult = opResults.get(0);
+            if ( firstResult.getType() == ZooDefs.OpCode.error )
+            {
+                OpResult.ErrorResult error = (OpResult.ErrorResult)firstResult;
+                KeeperException.Code code = KeeperException.Code.get(error.getErr());
+                if ( code == null )
+                {
+                    code = KeeperException.Code.UNIMPLEMENTED;
+                }
+                throw KeeperException.create(code);
+            }
+        }
+        return opResults;
     }
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/imps/DeleteBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/DeleteBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/DeleteBuilderImpl.java
index 9db0013..51641b8 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/DeleteBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/DeleteBuilderImpl.java
@@ -28,7 +28,6 @@ import org.apache.curator.framework.api.CuratorEvent;
 import org.apache.curator.framework.api.CuratorEventType;
 import org.apache.curator.framework.api.DeleteBuilder;
 import org.apache.curator.framework.api.Pathable;
-import org.apache.curator.framework.api.transaction.CuratorTransactionBridge;
 import org.apache.curator.framework.api.transaction.OperationType;
 import org.apache.curator.framework.api.transaction.TransactionDeleteBuilder;
 import org.apache.curator.utils.ZKPaths;
@@ -55,20 +54,20 @@ class DeleteBuilderImpl implements DeleteBuilder, BackgroundOperation<String>
         guaranteed = false;
     }
 
-    TransactionDeleteBuilder asTransactionDeleteBuilder(final CuratorTransactionImpl curatorTransaction, final CuratorMultiTransactionRecord transaction)
+    <T> TransactionDeleteBuilder<T> asTransactionDeleteBuilder(final T context, final CuratorMultiTransactionRecord transaction)
     {
-        return new TransactionDeleteBuilder()
+        return new TransactionDeleteBuilder<T>()
         {
             @Override
-            public CuratorTransactionBridge forPath(String path) throws Exception
+            public T forPath(String path) throws Exception
             {
                 String fixedPath = client.fixForNamespace(path);
                 transaction.add(Op.delete(fixedPath, version), OperationType.DELETE, path);
-                return curatorTransaction;
+                return context;
             }
 
             @Override
-            public Pathable<CuratorTransactionBridge> withVersion(int version)
+            public Pathable<T> withVersion(int version)
             {
                 DeleteBuilderImpl.this.withVersion(version);
                 return this;
@@ -159,7 +158,7 @@ class DeleteBuilderImpl implements DeleteBuilder, BackgroundOperation<String>
                         }
                         else
                         {
-                            CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.DELETE, rc, path, null, ctx, null, null, null, null, null);
+                            CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.DELETE, rc, path, null, ctx, null, null, null, null, null, null);
                             client.processBackgroundOperation(operationAndData, event);
                         }
                     }

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/imps/ExistsBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/ExistsBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/ExistsBuilderImpl.java
index a1e2ee5..4681245 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/ExistsBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/ExistsBuilderImpl.java
@@ -119,7 +119,7 @@ class ExistsBuilderImpl implements ExistsBuilder, BackgroundOperation<String>
             public void processResult(int rc, String path, Object ctx, Stat stat)
             {
                 trace.commit();
-                CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.EXISTS, rc, path, null, ctx, stat, null, null, null, null);
+                CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.EXISTS, rc, path, null, ctx, stat, null, null, null, null, null);
                 client.processBackgroundOperation(operationAndData, event);
             }
         };

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/imps/ExtractingCuratorOp.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/ExtractingCuratorOp.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/ExtractingCuratorOp.java
new file mode 100644
index 0000000..40bd8c8
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/ExtractingCuratorOp.java
@@ -0,0 +1,59 @@
+/**
+ * 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.curator.framework.imps;
+
+import com.google.common.base.Preconditions;
+import org.apache.curator.framework.api.transaction.CuratorOp;
+import org.apache.curator.framework.api.transaction.TypeAndPath;
+import org.apache.zookeeper.Op;
+
+class ExtractingCuratorOp implements CuratorOp
+{
+    private final CuratorMultiTransactionRecord record = new CuratorMultiTransactionRecord();
+
+    CuratorMultiTransactionRecord getRecord()
+    {
+        return record;
+    }
+
+    CuratorOp asCuratorOp()
+    {
+        return this;
+    }
+
+    @Override
+    public TypeAndPath getTypeAndPath()
+    {
+        validate();
+        return record.getMetadata(0);
+    }
+
+    @Override
+    public Op get()
+    {
+        validate();
+        return record.iterator().next();
+    }
+
+    private void validate()
+    {
+        Preconditions.checkArgument(record.size() > 0, "No operation has been added");
+        Preconditions.checkArgument(record.size() == 1, "Multiple operations added");
+    }
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/imps/GetACLBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/GetACLBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/GetACLBuilderImpl.java
index 250c2c8..f65c933 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/GetACLBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/GetACLBuilderImpl.java
@@ -104,7 +104,7 @@ class GetACLBuilderImpl implements GetACLBuilder, BackgroundOperation<String>
             public void processResult(int rc, String path, Object ctx, List<ACL> acl, Stat stat)
             {
                 trace.commit();
-                CuratorEventImpl event = new CuratorEventImpl(client, CuratorEventType.GET_ACL, rc, path, null, ctx, stat, null, null, null, acl);
+                CuratorEventImpl event = new CuratorEventImpl(client, CuratorEventType.GET_ACL, rc, path, null, ctx, stat, null, null, null, acl, null);
                 client.processBackgroundOperation(operationAndData, event);
             }
         };

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/imps/GetChildrenBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/GetChildrenBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/GetChildrenBuilderImpl.java
index 16f6d4b..03010ce 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/GetChildrenBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/GetChildrenBuilderImpl.java
@@ -162,7 +162,7 @@ class GetChildrenBuilderImpl implements GetChildrenBuilder, BackgroundOperation<
                 {
                     strings = Lists.newArrayList();
                 }
-                CuratorEventImpl event = new CuratorEventImpl(client, CuratorEventType.CHILDREN, rc, path, null, o, stat, null, strings, null, null);
+                CuratorEventImpl event = new CuratorEventImpl(client, CuratorEventType.CHILDREN, rc, path, null, o, stat, null, strings, null, null, null);
                 client.processBackgroundOperation(operationAndData, event);
             }
         };

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
index c9bbbf6..a837809 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
@@ -143,7 +143,7 @@ public class GetConfigBuilderImpl implements GetConfigBuilder, BackgroundOperati
             public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat)
             {
                 trace.commit();
-                CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.GET_CONFIG, rc, path, null, ctx, stat, data, null, null, null);
+                CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.GET_CONFIG, rc, path, null, ctx, stat, data, null, null, null, null);
                 client.processBackgroundOperation(operationAndData, event);
             }
         };

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/imps/GetDataBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/GetDataBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/GetDataBuilderImpl.java
index e994b03..23da075 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/GetDataBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/GetDataBuilderImpl.java
@@ -250,7 +250,7 @@ class GetDataBuilderImpl implements GetDataBuilder, BackgroundOperation<String>
                         rc = KeeperException.Code.DATAINCONSISTENCY.intValue();
                     }
                 }
-                CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.GET_DATA, rc, path, null, ctx, stat, data, null, null, null);
+                CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.GET_DATA, rc, path, null, ctx, stat, data, null, null, null, null);
                 client.processBackgroundOperation(operationAndData, event);
             }
         };

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java
index f4dba90..0efa481 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java
@@ -476,7 +476,7 @@ public class ReconfigBuilderImpl implements
                 {
                     DataTree.copyStat(stat, responseStat);
                 }
-                CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.RECONFIG, rc, path, null, ctx, stat, bytes, null, null, null);
+                CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.RECONFIG, rc, path, null, ctx, stat, bytes, null, null, null, null);
                 client.processBackgroundOperation(data, event);
             }
         };

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/imps/SetACLBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/SetACLBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/SetACLBuilderImpl.java
index f7b2480..17e88f8 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/SetACLBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/SetACLBuilderImpl.java
@@ -138,7 +138,7 @@ class SetACLBuilderImpl implements SetACLBuilder, BackgroundPathable<Stat>, Back
                 public void processResult(int rc, String path, Object ctx, Stat stat)
                 {
                     trace.commit();
-                    CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.SET_ACL, rc, path, null, ctx, stat, null, null, null, null);
+                    CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.SET_ACL, rc, path, null, ctx, stat, null, null, null, null, null);
                     client.processBackgroundOperation(operationAndData, event);
                 }
             },

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/imps/SetDataBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/SetDataBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/SetDataBuilderImpl.java
index 8e93cbf..3ea704c 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/SetDataBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/SetDataBuilderImpl.java
@@ -20,7 +20,6 @@ package org.apache.curator.framework.imps;
 
 import org.apache.curator.RetryLoop;
 import org.apache.curator.TimeTrace;
-import org.apache.curator.framework.api.ACLPathAndBytesable;
 import org.apache.curator.framework.api.BackgroundCallback;
 import org.apache.curator.framework.api.BackgroundPathAndBytesable;
 import org.apache.curator.framework.api.CuratorEvent;
@@ -28,13 +27,11 @@ import org.apache.curator.framework.api.CuratorEventType;
 import org.apache.curator.framework.api.PathAndBytesable;
 import org.apache.curator.framework.api.SetDataBackgroundVersionable;
 import org.apache.curator.framework.api.SetDataBuilder;
-import org.apache.curator.framework.api.transaction.CuratorTransactionBridge;
 import org.apache.curator.framework.api.transaction.OperationType;
 import org.apache.curator.framework.api.transaction.TransactionSetDataBuilder;
 import org.apache.zookeeper.AsyncCallback;
 import org.apache.zookeeper.Op;
 import org.apache.zookeeper.data.Stat;
-
 import java.util.concurrent.Callable;
 import java.util.concurrent.Executor;
 
@@ -53,12 +50,12 @@ class SetDataBuilderImpl implements SetDataBuilder, BackgroundOperation<PathAndB
         compress = false;
     }
 
-    TransactionSetDataBuilder   asTransactionSetDataBuilder(final CuratorTransactionImpl curatorTransaction, final CuratorMultiTransactionRecord transaction)
+    <T> TransactionSetDataBuilder<T> asTransactionSetDataBuilder(final T context, final CuratorMultiTransactionRecord transaction)
     {
-        return new TransactionSetDataBuilder()
+        return new TransactionSetDataBuilder<T>()
         {
             @Override
-            public CuratorTransactionBridge forPath(String path, byte[] data) throws Exception
+            public T forPath(String path, byte[] data) throws Exception
             {
                 if ( compress )
                 {
@@ -67,26 +64,26 @@ class SetDataBuilderImpl implements SetDataBuilder, BackgroundOperation<PathAndB
                 
                 String      fixedPath = client.fixForNamespace(path);
                 transaction.add(Op.setData(fixedPath, data, version), OperationType.SET_DATA, path);
-                return curatorTransaction;
+                return context;
             }
 
             @Override
-            public CuratorTransactionBridge forPath(String path) throws Exception
+            public T forPath(String path) throws Exception
             {
                 return forPath(path, client.getDefaultData());
             }
 
             @Override
-            public PathAndBytesable<CuratorTransactionBridge> withVersion(int version)
+            public PathAndBytesable<T> withVersion(int version)
             {
                 SetDataBuilderImpl.this.withVersion(version);
                 return this;
             }
 
             @Override
-            public PathAndBytesable<CuratorTransactionBridge> compressed() {
+            public PathAndBytesable<T> compressed()
+            {
                 compress = true;
-                
                 return this;
             }
         };
@@ -219,7 +216,7 @@ class SetDataBuilderImpl implements SetDataBuilder, BackgroundOperation<PathAndB
                 public void processResult(int rc, String path, Object ctx, Stat stat)
                 {
                     trace.commit();
-                    CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.SET_DATA, rc, path, null, ctx, stat, null, null, null, null);
+                    CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.SET_DATA, rc, path, null, ctx, stat, null, null, null, null, null);
                     client.processBackgroundOperation(operationAndData, event);
                 }
             },
@@ -246,7 +243,7 @@ class SetDataBuilderImpl implements SetDataBuilder, BackgroundOperation<PathAndB
         Stat        resultStat = null;
         if ( backgrounding.inBackground()  )
         {
-            client.processBackgroundOperation(new OperationAndData<PathAndBytes>(this, new PathAndBytes(path, data), backgrounding.getCallback(), null, backgrounding.getContext()), null);
+            client.processBackgroundOperation(new OperationAndData<>(this, new PathAndBytes(path, data), backgrounding.getCallback(), null, backgrounding.getContext()), null);
         }
         else
         {

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/imps/SyncBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/SyncBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/SyncBuilderImpl.java
index 2d3e9c0..cab31ae 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/SyncBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/SyncBuilderImpl.java
@@ -93,7 +93,7 @@ public class SyncBuilderImpl implements SyncBuilder, BackgroundOperation<String>
             public void processResult(int rc, String path, Object ctx)
             {
                 trace.commit();
-                CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.SYNC, rc, path, path, ctx, null, null, null, null, null);
+                CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.SYNC, rc, path, path, ctx, null, null, null, null, null, null);
                 client.processBackgroundOperation(operationAndData, event);
             }
         };

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/main/java/org/apache/curator/framework/imps/TransactionOpImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/TransactionOpImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/TransactionOpImpl.java
new file mode 100644
index 0000000..e0ada17
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/TransactionOpImpl.java
@@ -0,0 +1,65 @@
+/**
+ * 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.curator.framework.imps;
+
+import org.apache.curator.framework.api.transaction.CuratorOp;
+import org.apache.curator.framework.api.transaction.TransactionCheckBuilder;
+import org.apache.curator.framework.api.transaction.TransactionCreateBuilder;
+import org.apache.curator.framework.api.transaction.TransactionDeleteBuilder;
+import org.apache.curator.framework.api.transaction.TransactionOp;
+import org.apache.curator.framework.api.transaction.TransactionSetDataBuilder;
+
+public class TransactionOpImpl implements TransactionOp
+{
+    private final CuratorFrameworkImpl client;
+
+    public TransactionOpImpl(CuratorFrameworkImpl client)
+    {
+        this.client = client;
+    }
+
+    @Override
+    public TransactionCreateBuilder<CuratorOp> create()
+    {
+        ExtractingCuratorOp op = new ExtractingCuratorOp();
+        return new CreateBuilderImpl(client).asTransactionCreateBuilder(op.asCuratorOp(), op.getRecord());
+    }
+
+    @Override
+    public TransactionDeleteBuilder<CuratorOp> delete()
+    {
+        ExtractingCuratorOp op = new ExtractingCuratorOp();
+        return new DeleteBuilderImpl(client).asTransactionDeleteBuilder(op.asCuratorOp(), op.getRecord());
+    }
+
+    @Override
+    public TransactionSetDataBuilder<CuratorOp> setData()
+    {
+        ExtractingCuratorOp op = new ExtractingCuratorOp();
+        return new SetDataBuilderImpl(client).asTransactionSetDataBuilder(op.asCuratorOp(), op.getRecord());
+    }
+
+    @Override
+    public TransactionCheckBuilder<CuratorOp> check()
+    {
+        ExtractingCuratorOp op = new ExtractingCuratorOp();
+        return CuratorTransactionImpl.makeTransactionCheckBuilder(client, op.asCuratorOp(), op.getRecord());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/7df5ab38/curator-framework/src/test/java/org/apache/curator/framework/imps/TestTransactions.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestTransactions.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestTransactions.java
deleted file mode 100644
index ae2cf1d..0000000
--- a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestTransactions.java
+++ /dev/null
@@ -1,139 +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.curator.framework.imps;
-
-import com.google.common.collect.Iterables;
-import org.apache.curator.framework.CuratorFramework;
-import org.apache.curator.framework.CuratorFrameworkFactory;
-import org.apache.curator.framework.api.transaction.CuratorTransactionResult;
-import org.apache.curator.framework.api.transaction.OperationType;
-import org.apache.curator.retry.RetryOneTime;
-import org.apache.curator.test.BaseClassForTests;
-import org.apache.zookeeper.CreateMode;
-import org.apache.zookeeper.KeeperException;
-import org.apache.zookeeper.data.Stat;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-import java.util.Collection;
-
-public class TestTransactions extends BaseClassForTests
-{
-    @Test
-    public void     testCheckVersion() throws Exception
-    {
-        CuratorFramework        client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
-        client.start();
-        try
-        {
-            client.create().forPath("/foo");
-            Stat        stat = client.setData().forPath("/foo", "new".getBytes());  // up the version
-
-            try
-            {
-                client.inTransaction()
-                    .check().withVersion(stat.getVersion() + 1).forPath("/foo") // force a bad version
-                .and()
-                    .create().forPath("/bar")
-                .and()
-                    .commit();
-
-                Assert.fail();
-            }
-            catch ( KeeperException.BadVersionException correct )
-            {
-                // correct
-            }
-            
-            Assert.assertNull(client.checkExists().forPath("/bar"));
-        }
-        finally
-        {
-            client.close();
-        }
-    }
-
-    @Test
-    public void     testWithNamespace() throws Exception
-    {
-        CuratorFramework        client = CuratorFrameworkFactory.builder().connectString(server.getConnectString()).retryPolicy(new RetryOneTime(1)).namespace("galt").build();
-        client.start();
-        try
-        {
-            Collection<CuratorTransactionResult>    results =
-                client.inTransaction()
-                    .create().forPath("/foo", "one".getBytes())
-                .and()
-                    .create().withMode(CreateMode.PERSISTENT_SEQUENTIAL).forPath("/test-", "one".getBytes())
-                .and()
-                    .setData().forPath("/foo", "two".getBytes())
-                .and()
-                    .create().forPath("/foo/bar")
-                .and()
-                    .delete().forPath("/foo/bar")
-                .and()
-                    .commit();
-
-            Assert.assertTrue(client.checkExists().forPath("/foo") != null);
-            Assert.assertTrue(client.usingNamespace(null).checkExists().forPath("/galt/foo") != null);
-            Assert.assertEquals(client.getData().forPath("/foo"), "two".getBytes());
-            Assert.assertTrue(client.checkExists().forPath("/foo/bar") == null);
-
-            CuratorTransactionResult    ephemeralResult = Iterables.find(results, CuratorTransactionResult.ofTypeAndPath(OperationType.CREATE, "/test-"));
-            Assert.assertNotNull(ephemeralResult);
-            Assert.assertNotEquals(ephemeralResult.getResultPath(), "/test-");
-            Assert.assertTrue(ephemeralResult.getResultPath().startsWith("/test-"));
-        }
-        finally
-        {
-            client.close();
-        }
-    }
-
-    @Test
-    public void     testBasic() throws Exception
-    {
-        CuratorFramework        client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
-        client.start();
-        try
-        {
-            Collection<CuratorTransactionResult>    results =
-                client.inTransaction()
-                    .create().forPath("/foo")
-                .and()
-                    .create().forPath("/foo/bar", "snafu".getBytes())
-                .and()
-                    .commit();
-
-            Assert.assertTrue(client.checkExists().forPath("/foo/bar") != null);
-            Assert.assertEquals(client.getData().forPath("/foo/bar"), "snafu".getBytes());
-
-            CuratorTransactionResult    fooResult = Iterables.find(results, CuratorTransactionResult.ofTypeAndPath(OperationType.CREATE, "/foo"));
-            CuratorTransactionResult    fooBarResult = Iterables.find(results, CuratorTransactionResult.ofTypeAndPath(OperationType.CREATE, "/foo/bar"));
-            Assert.assertNotNull(fooResult);
-            Assert.assertNotNull(fooBarResult);
-            Assert.assertNotSame(fooResult, fooBarResult);
-            Assert.assertEquals(fooResult.getResultPath(), "/foo");
-            Assert.assertEquals(fooBarResult.getResultPath(), "/foo/bar");
-        }
-        finally
-        {
-            client.close();
-        }
-    }
-}


[24/27] curator git commit: Initial work on updated transaction APIs

Posted by dr...@apache.org.
Initial work on updated transaction APIs


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

Branch: refs/heads/CURATOR-215
Commit: d1e17eb2adeceb632a5b7e08159a864b4827c1f7
Parents: 0d6d82a
Author: randgalt <ra...@apache.org>
Authored: Sat May 9 12:39:14 2015 -0500
Committer: Scott Blum <dr...@apache.org>
Committed: Wed Aug 12 17:29:42 2015 -0400

----------------------------------------------------------------------
 .../curator/framework/CuratorFramework.java     |   8 ++
 .../transaction/CuratorMultiTransaction.java    |  26 ++++
 .../CuratorMultiTransactionMain.java            |  30 ++++
 .../imps/CuratorMultiTransactionImpl.java       | 139 +++++++++++++++++++
 4 files changed, 203 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/d1e17eb2/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java b/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
index 7de49ce..f14253f 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
@@ -21,6 +21,7 @@ package org.apache.curator.framework;
 
 import org.apache.curator.CuratorZookeeperClient;
 import org.apache.curator.framework.api.*;
+import org.apache.curator.framework.api.transaction.CuratorMultiTransaction;
 import org.apache.curator.framework.api.transaction.CuratorTransaction;
 import org.apache.curator.framework.imps.CuratorFrameworkState;
 import org.apache.curator.framework.listen.Listenable;
@@ -143,6 +144,13 @@ public interface CuratorFramework extends Closeable
     public CuratorTransaction inTransaction();
 
     /**
+     * Start a transaction builder
+     *
+     * @return builder object
+     */
+    public CuratorMultiTransaction transaction();
+
+    /**
      * Perform a sync on the given path - syncs are always in the background
      *
      * @param path                    the path

http://git-wip-us.apache.org/repos/asf/curator/blob/d1e17eb2/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorMultiTransaction.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorMultiTransaction.java b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorMultiTransaction.java
new file mode 100644
index 0000000..605ad2e
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorMultiTransaction.java
@@ -0,0 +1,26 @@
+/**
+ * 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.curator.framework.api.transaction;
+
+import org.apache.curator.framework.api.Backgroundable;
+
+public interface CuratorMultiTransaction
+    extends Backgroundable<CuratorMultiTransactionMain>
+{
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/d1e17eb2/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorMultiTransactionMain.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorMultiTransactionMain.java b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorMultiTransactionMain.java
new file mode 100644
index 0000000..02c59af
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorMultiTransactionMain.java
@@ -0,0 +1,30 @@
+/**
+ * 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.curator.framework.api.transaction;
+
+import org.apache.zookeeper.Op;
+import org.apache.zookeeper.OpResult;
+import java.util.List;
+
+public interface CuratorMultiTransactionMain
+{
+    List<OpResult> forOperations(Op... operations) throws Exception;
+
+    List<OpResult> forOperations(List<Op> operations) throws Exception;
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/d1e17eb2/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorMultiTransactionImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorMultiTransactionImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorMultiTransactionImpl.java
new file mode 100644
index 0000000..0ba3dc7
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorMultiTransactionImpl.java
@@ -0,0 +1,139 @@
+/**
+ * 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.curator.framework.imps;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import org.apache.curator.RetryLoop;
+import org.apache.curator.TimeTrace;
+import org.apache.curator.framework.api.BackgroundCallback;
+import org.apache.curator.framework.api.transaction.CuratorMultiTransaction;
+import org.apache.curator.framework.api.transaction.CuratorMultiTransactionMain;
+import org.apache.zookeeper.Op;
+import org.apache.zookeeper.OpResult;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executor;
+
+public class CuratorMultiTransactionImpl implements
+    CuratorMultiTransaction,
+    CuratorMultiTransactionMain,
+    BackgroundOperation<Void>
+{
+    private final CuratorFrameworkImpl client;
+    private Backgrounding backgrounding = new Backgrounding();
+
+    public CuratorMultiTransactionImpl(CuratorFrameworkImpl client)
+    {
+        this.client = client;
+    }
+
+    @Override
+    public CuratorMultiTransactionMain inBackground()
+    {
+        backgrounding = new Backgrounding(true);
+        return this;
+    }
+
+    @Override
+    public CuratorMultiTransactionMain inBackground(Object context)
+    {
+        backgrounding = new Backgrounding(context);
+        return this;
+    }
+
+    @Override
+    public CuratorMultiTransactionMain inBackground(BackgroundCallback callback)
+    {
+        backgrounding = new Backgrounding(callback);
+        return this;
+    }
+
+    @Override
+    public CuratorMultiTransactionMain inBackground(BackgroundCallback callback, Object context)
+    {
+        backgrounding = new Backgrounding(callback, context);
+        return this;
+    }
+
+    @Override
+    public CuratorMultiTransactionMain inBackground(BackgroundCallback callback, Executor executor)
+    {
+        backgrounding = new Backgrounding(callback, executor);
+        return this;
+    }
+
+    @Override
+    public CuratorMultiTransactionMain inBackground(BackgroundCallback callback, Object context, Executor executor)
+    {
+        backgrounding = new Backgrounding(client, callback, context, executor);
+        return this;
+    }
+
+    @Override
+    public List<OpResult> forOperations(Op... operations) throws Exception
+    {
+        List<Op> ops = (operations != null) ? Arrays.asList(operations) : Lists.<Op>newArrayList();
+        return forOperations(ops);
+    }
+
+    @Override
+    public List<OpResult> forOperations(List<Op> operations) throws Exception
+    {
+        operations = Preconditions.checkNotNull(operations, "operations cannot be null");
+        Preconditions.checkArgument(!operations.isEmpty(), "operations list cannot be empty");
+
+        if ( backgrounding.inBackground() )
+        {
+            client.processBackgroundOperation(new OperationAndData<>(this, null, backgrounding.getCallback(), null, backgrounding.getContext()), null);
+            return null;
+        }
+        else
+        {
+            return forOperationsInForeground(operations);
+        }
+    }
+
+    @Override
+    public void performBackgroundOperation(OperationAndData<Void> data) throws Exception
+    {
+
+    }
+
+    private List<OpResult> forOperationsInForeground(final List<Op> operations) throws Exception
+    {
+        TimeTrace trace = client.getZookeeperClient().startTracer("CuratorMultiTransactionImpl-Foreground");
+        List<OpResult> responseData = RetryLoop.callWithRetry
+        (
+            client.getZookeeperClient(),
+            new Callable<List<OpResult>>()
+            {
+                @Override
+                public List<OpResult> call() throws Exception
+                {
+                    return client.getZooKeeper().multi(operations);
+                }
+            }
+        );
+        trace.commit();
+
+        return responseData;
+    }
+}


[17/27] curator git commit: Updated CuratorEvent doc

Posted by dr...@apache.org.
Updated CuratorEvent doc


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

Branch: refs/heads/CURATOR-215
Commit: e558c4bcb1a861a34fd5dc1758f2302d76ff8986
Parents: 2eec9ea
Author: randgalt <ra...@apache.org>
Authored: Sat May 9 10:47:30 2015 -0500
Committer: Scott Blum <dr...@apache.org>
Committed: Wed Aug 12 17:28:42 2015 -0400

----------------------------------------------------------------------
 curator-framework/src/site/confluence/index.confluence | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/e558c4bc/curator-framework/src/site/confluence/index.confluence
----------------------------------------------------------------------
diff --git a/curator-framework/src/site/confluence/index.confluence b/curator-framework/src/site/confluence/index.confluence
index cf92514..bb1807e 100644
--- a/curator-framework/src/site/confluence/index.confluence
+++ b/curator-framework/src/site/confluence/index.confluence
@@ -55,9 +55,9 @@ CuratorFramework instance using the addListener() method. The listener implement
 |eventReceived()|A background operation has completed or a watch has triggered. Examine the given event for details|
 <td>clientClosedDueToError()|An unrecoverable error has occurred. The CuratorFramework instance has been shut down|
 
-h3. ClientEvent
-The ClientEvent object is a super\-set POJO that can hold every type of background notification and triggered watch. The useful fields of
-ClientEvent depend on the type of event which is exposed via the getType() method.
+h3. CuratorEvent
+The CuratorEvent object is a super\-set POJO that can hold every type of background notification and triggered watch. The useful fields of
+CuratorEvent depend on the type of event which is exposed via the getType() method.
 
 ||Event Type||Event Methods||
 |CREATE|getResultCode() and getPath()|
@@ -66,7 +66,12 @@ ClientEvent depend on the type of event which is exposed via the getType() metho
 |GET_DATA|getResultCode(), getPath(), getStat() and getData()|
 |SET_DATA|getResultCode(), getPath() and getStat()|
 |CHILDREN|getResultCode(), getPath(), getStat(), getChildren()|
+|SYNC|getResultCode(), getStat()|
+|GET_ACL|getResultCode(), getACLList()|
+|SET_ACL|getResultCode()|
 |WATCHED|getWatchedEvent()|
+|GET_CONFIG|getResultCode(), getData()|
+|RECONFIG|getResultCode(), getData()|
 
 h2. Namespaces
 Because a ZooKeeper cluster is a shared environment, it's vital that a namespace convention is


[04/27] curator git commit: [CURATOR-160] Add builders and dsl for ZooKeeper's config and reconfig methods.

Posted by dr...@apache.org.
[CURATOR-160] Add builders and dsl for ZooKeeper's config and reconfig methods.


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/2bd53fc2
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/2bd53fc2
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/2bd53fc2

Branch: refs/heads/CURATOR-215
Commit: 2bd53fc28fbaa70ed380af0579853db83b63a663
Parents: 143044b
Author: Ioannis Canellos <io...@gmail.com>
Authored: Thu Nov 6 17:34:47 2014 +0200
Committer: Scott Blum <dr...@apache.org>
Committed: Wed Aug 12 16:17:19 2015 -0400

----------------------------------------------------------------------
 .../curator/framework/CuratorFramework.java     |  12 +
 .../framework/api/AsyncReconfigurable.java      |  29 ++
 .../curator/framework/api/DataCallbackable.java |  32 ++
 .../curator/framework/api/GetConfigBuilder.java |  27 ++
 .../api/IncrementalReconfigBuilder.java         |  33 ++
 .../apache/curator/framework/api/Joinable.java  |  40 +++
 .../apache/curator/framework/api/Leaveable.java |  38 +++
 .../curator/framework/api/Memberable.java       |  40 +++
 .../api/NonIncrementalReconfigBuilder.java      |  32 ++
 .../curator/framework/api/ReconfigBuilder.java  |  26 ++
 .../framework/api/SyncReconfigurable.java       |  30 ++
 .../framework/imps/CuratorFrameworkImpl.java    |  10 +
 .../framework/imps/GetConfigBuilderImpl.java    |  80 +++++
 .../framework/imps/ReconfigBuilderImpl.java     | 182 +++++++++++
 .../framework/imps/TestReconfiguration.java     | 303 +++++++++++++++++++
 15 files changed, 914 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/2bd53fc2/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java b/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
index 9c23ddb..181e4e8 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java
@@ -122,6 +122,18 @@ public interface CuratorFramework extends Closeable
     public SetACLBuilder setACL();
 
     /**
+     * Start a reconfig builder
+     * @return builder object
+     */
+    public ReconfigBuilder reconfig();
+
+    /**
+     * Start a getConfig builder
+     * @return
+     */
+    public GetConfigBuilder getConfig();
+
+    /**
      * Start a transaction builder
      *
      * @return builder object

http://git-wip-us.apache.org/repos/asf/curator/blob/2bd53fc2/curator-framework/src/main/java/org/apache/curator/framework/api/AsyncReconfigurable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/AsyncReconfigurable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/AsyncReconfigurable.java
new file mode 100644
index 0000000..fc7fd57
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/AsyncReconfigurable.java
@@ -0,0 +1,29 @@
+/**
+ * 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.curator.framework.api;
+
+public interface AsyncReconfigurable  {
+
+    /**
+     * Sets the configuration version to use.
+     * @param config The version of the configuration.
+     * @throws Exception
+     */
+    void fromConfig(long config) throws Exception;
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/2bd53fc2/curator-framework/src/main/java/org/apache/curator/framework/api/DataCallbackable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/DataCallbackable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/DataCallbackable.java
new file mode 100644
index 0000000..75ded65
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/DataCallbackable.java
@@ -0,0 +1,32 @@
+/**
+ * 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.curator.framework.api;
+
+import org.apache.zookeeper.AsyncCallback.DataCallback;
+
+public interface DataCallbackable<T> {
+
+    /**
+     * Passes a callback and a context object to the config/reconfig command.
+     * @param callback  The async callback to use.
+     * @param ctx       An object that will be passed to the callback.
+     * @return this
+     */
+    T usingDataCallback(DataCallback callback, Object ctx);
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/2bd53fc2/curator-framework/src/main/java/org/apache/curator/framework/api/GetConfigBuilder.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/GetConfigBuilder.java b/curator-framework/src/main/java/org/apache/curator/framework/api/GetConfigBuilder.java
new file mode 100644
index 0000000..c7c013b
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/GetConfigBuilder.java
@@ -0,0 +1,27 @@
+/**
+ * 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.curator.framework.api;
+
+public interface GetConfigBuilder extends
+        Watchable<GetConfigBuilder>,
+        DataCallbackable<Void>,
+        Statable<byte[]> {
+}
+
+

http://git-wip-us.apache.org/repos/asf/curator/blob/2bd53fc2/curator-framework/src/main/java/org/apache/curator/framework/api/IncrementalReconfigBuilder.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/IncrementalReconfigBuilder.java b/curator-framework/src/main/java/org/apache/curator/framework/api/IncrementalReconfigBuilder.java
new file mode 100644
index 0000000..0ad6426
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/IncrementalReconfigBuilder.java
@@ -0,0 +1,33 @@
+/**
+ * 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.curator.framework.api;
+
+/**
+ * An incremental reconfiguration builder.
+ * This builder has access only to the incremental reconfiguration methods join and leave, so that we prevent
+ * mixing concepts that can't be used together.
+ * @param <T>
+ */
+public interface IncrementalReconfigBuilder<T> extends
+        Joinable<IncrementalReconfigBuilder<T>>,
+        Leaveable<IncrementalReconfigBuilder<T>>,
+        DataCallbackable<AsyncReconfigurable>,
+        Statable<SyncReconfigurable> {
+
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/2bd53fc2/curator-framework/src/main/java/org/apache/curator/framework/api/Joinable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/Joinable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/Joinable.java
new file mode 100644
index 0000000..ff1b3c5
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/Joinable.java
@@ -0,0 +1,40 @@
+/**
+ * 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.curator.framework.api;
+
+import java.util.Collection;
+
+public interface Joinable<T> {
+
+    /**
+     * Adds a server to join the ensemble.
+     * The expected format is server.[id]=[hostname]:[peer port]:[election port]:[type];[client port]
+     * @param server The server to join.
+     * @return this.
+     */
+    T join(String server);
+
+    /**
+     * Adds a collection of servers to the ensemble.
+     * The expected format is server.[id]=[hostname]:[peer port]:[election port]:[type];[client port]
+     * @param servers The collection of servers to join
+     * @return this
+     */
+    T join(Collection<String> servers);
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/2bd53fc2/curator-framework/src/main/java/org/apache/curator/framework/api/Leaveable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/Leaveable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/Leaveable.java
new file mode 100644
index 0000000..8560d65
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/Leaveable.java
@@ -0,0 +1,38 @@
+/**
+ * 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.curator.framework.api;
+
+import java.util.Collection;
+
+public interface Leaveable<T> {
+
+    /**
+     * Sets a server to leave the ensemble.
+     * @param server The server id.
+     * @return this
+     */
+    T leave(String server);
+
+    /**
+     * Sets a collection of servers to leave the ensemble.
+     * @param servers The collection of server ids.
+     * @return this.
+     */
+    T leave(Collection<String> servers);
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/2bd53fc2/curator-framework/src/main/java/org/apache/curator/framework/api/Memberable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/Memberable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/Memberable.java
new file mode 100644
index 0000000..5b62dba
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/Memberable.java
@@ -0,0 +1,40 @@
+/**
+ * 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.curator.framework.api;
+
+import java.util.Collection;
+
+public interface Memberable<T> {
+
+    /**
+     * Sets a member that is meant to be part of the ensemble.
+     * The expected format is server.[id]=[hostname]:[peer port]:[election port]:[type];[client port]
+     * @param server The server to add as a member of the ensemble.
+     * @return this.
+     */
+    T withMember(String server);
+
+    /**
+     * Sets a collection of members member that is meant to be part of the ensemble.
+     * The expected format is server.[id]=[hostname]:[peer port]:[election port]:[type];[client port]
+     * @param servers The collection of server to set as a members of the ensemble.
+     * @return this.
+     */
+    T withMembers(Collection<String> servers);
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/2bd53fc2/curator-framework/src/main/java/org/apache/curator/framework/api/NonIncrementalReconfigBuilder.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/NonIncrementalReconfigBuilder.java b/curator-framework/src/main/java/org/apache/curator/framework/api/NonIncrementalReconfigBuilder.java
new file mode 100644
index 0000000..2f6a9c6
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/NonIncrementalReconfigBuilder.java
@@ -0,0 +1,32 @@
+/**
+ * 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.curator.framework.api;
+
+/**
+ * An non-incremental reconfiguration builder.
+ * This builder has access only to the non-incremental reconfiguration methods withMembers, so that we prevent
+ * mixing concepts that can't be used together.
+ * @param <T>
+ */
+public interface NonIncrementalReconfigBuilder<T> extends
+        Memberable<NonIncrementalReconfigBuilder<T>>,
+        DataCallbackable<AsyncReconfigurable>,
+        Statable<SyncReconfigurable> {
+
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/2bd53fc2/curator-framework/src/main/java/org/apache/curator/framework/api/ReconfigBuilder.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/ReconfigBuilder.java b/curator-framework/src/main/java/org/apache/curator/framework/api/ReconfigBuilder.java
new file mode 100644
index 0000000..0e420a1
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/ReconfigBuilder.java
@@ -0,0 +1,26 @@
+/**
+ * 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.curator.framework.api;
+
+public interface ReconfigBuilder extends
+        Joinable<IncrementalReconfigBuilder<byte[]>>,
+        Leaveable<IncrementalReconfigBuilder<byte[]>>,
+        Memberable<NonIncrementalReconfigBuilder<byte[]>> {
+
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/2bd53fc2/curator-framework/src/main/java/org/apache/curator/framework/api/SyncReconfigurable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/SyncReconfigurable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/SyncReconfigurable.java
new file mode 100644
index 0000000..bd7b96b
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/SyncReconfigurable.java
@@ -0,0 +1,30 @@
+/**
+ * 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.curator.framework.api;
+
+public interface SyncReconfigurable  {
+
+    /**
+     * Sets the configuration version to use.
+     * @param config    The version of the configuration.
+     * @return The configuration data.
+     * @throws Exception
+     */
+    byte[] fromConfig(long config) throws Exception;
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/2bd53fc2/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
index 5034ed9..b9b9c31 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java
@@ -398,6 +398,16 @@ public class CuratorFrameworkImpl implements CuratorFramework
     }
 
     @Override
+    public ReconfigBuilder reconfig() {
+        return new ReconfigBuilderImpl(this);
+    }
+
+    @Override
+    public GetConfigBuilder getConfig() {
+        return new GetConfigBuilderImpl(this);
+    }
+
+    @Override
     public CuratorTransaction inTransaction()
     {
         Preconditions.checkState(getState() == CuratorFrameworkState.STARTED, "instance must be started before calling this method");

http://git-wip-us.apache.org/repos/asf/curator/blob/2bd53fc2/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
new file mode 100644
index 0000000..a56894d
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
@@ -0,0 +1,80 @@
+/**
+ * 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.curator.framework.imps;
+
+import org.apache.curator.framework.api.CuratorWatcher;
+import org.apache.curator.framework.api.GetConfigBuilder;
+import org.apache.zookeeper.AsyncCallback;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.data.Stat;
+
+public class GetConfigBuilderImpl implements GetConfigBuilder {
+
+    private final CuratorFrameworkImpl client;
+    private boolean watched;
+    private Watcher watcher;
+
+    public GetConfigBuilderImpl(CuratorFrameworkImpl client) {
+        this.client = client;
+    }
+
+    @Override
+    public Void usingDataCallback(AsyncCallback.DataCallback callback, Object ctx) {
+        try {
+            if (watcher != null) {
+                client.getZooKeeper().getConfig(watcher, callback, ctx);
+            } else {
+                client.getZooKeeper().getConfig(watched, callback, ctx);
+            }
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        return null;
+    }
+
+    @Override
+    public byte[] storingStatIn(Stat stat) {
+        try {
+            if (watcher != null) {
+               return client.getZooKeeper().getConfig(watcher, stat);
+            } else {
+                return client.getZooKeeper().getConfig(watched, stat);
+            }
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public GetConfigBuilder watched() {
+        this.watched = true;
+        return this;
+    }
+
+    @Override
+    public GetConfigBuilder usingWatcher(Watcher watcher) {
+        this.watcher = watcher;
+        return null;
+    }
+
+    @Override
+    public GetConfigBuilder usingWatcher(final CuratorWatcher watcher) {
+        throw new UnsupportedOperationException("GetConfigBuilder doesn't support CuratorWatcher, please use Watcher instead.");
+    }
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/2bd53fc2/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java
new file mode 100644
index 0000000..7b39be6
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java
@@ -0,0 +1,182 @@
+/**
+ * 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.curator.framework.imps;
+
+import org.apache.curator.framework.api.AsyncReconfigurable;
+import org.apache.curator.framework.api.IncrementalReconfigBuilder;
+import org.apache.curator.framework.api.NonIncrementalReconfigBuilder;
+import org.apache.curator.framework.api.ReconfigBuilder;
+import org.apache.curator.framework.api.SyncReconfigurable;
+import org.apache.zookeeper.AsyncCallback.DataCallback;
+import org.apache.zookeeper.data.Stat;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+public class ReconfigBuilderImpl implements ReconfigBuilder {
+
+    private final CuratorFrameworkImpl client;
+
+    private static class IncrementalReconfigBuilderImpl<T> implements IncrementalReconfigBuilder<T> {
+
+        private final CuratorFrameworkImpl client;
+        private List<String> joiningServers = new LinkedList<String>();
+        private List<String> leavingServers = new LinkedList<String>();
+
+        private IncrementalReconfigBuilderImpl(CuratorFrameworkImpl client) {
+            this.client = client;
+        }
+
+        @Override
+        public IncrementalReconfigBuilderImpl<T> join(String server) {
+            joiningServers.add(server);
+            return this;
+        }
+
+        @Override
+        public IncrementalReconfigBuilder<T> join(Collection<String> servers) {
+            joiningServers.addAll(servers);
+            return this;
+        }
+
+        @Override
+        public IncrementalReconfigBuilderImpl<T> leave(String server) {
+            leavingServers.add(server);
+            return this;
+        }
+
+        @Override
+        public IncrementalReconfigBuilder<T> leave(Collection<String> servers) {
+            leavingServers.addAll(servers);
+            return this;
+        }
+
+        @Override
+        public SyncReconfigurable storingStatIn(final Stat stat) {
+            return new SyncReconfigurable() {
+                @Override
+                public byte[] fromConfig(long config) throws Exception {
+                    return client
+                            .getZooKeeper()
+                            .reconfig(joiningServers.isEmpty() ? null : joiningServers,
+                                      leavingServers.isEmpty() ? null : leavingServers,
+                                      null,
+                                      config, stat);
+                }
+            };
+        }
+
+        @Override
+        public AsyncReconfigurable usingDataCallback(final DataCallback callback, final Object ctx) {
+            return new AsyncReconfigurable() {
+                @Override
+                public void fromConfig(long config) throws Exception {
+                     client.getZooKeeper()
+                           .reconfig(joiningServers.isEmpty() ? null : joiningServers,
+                                     leavingServers.isEmpty() ? null : leavingServers,
+                                     null,
+                                     config, callback, ctx);
+                }
+            };
+        }
+    }
+
+    private static class NonIncrementalReconfigBuilderImpl<T> implements NonIncrementalReconfigBuilder<T> {
+
+        private final CuratorFrameworkImpl client;
+        private List<String> newMembers = new LinkedList<String>();
+
+        private NonIncrementalReconfigBuilderImpl(CuratorFrameworkImpl client) {
+            this.client = client;
+        }
+
+        private NonIncrementalReconfigBuilderImpl(CuratorFrameworkImpl client, List<String> newMembers) {
+            this.client = client;
+            this.newMembers = newMembers;
+        }
+
+        @Override
+        public NonIncrementalReconfigBuilder<T> withMember(String server) {
+            newMembers.add(server);
+            return this;
+        }
+
+        @Override
+        public NonIncrementalReconfigBuilder<T> withMembers(Collection servers) {
+            newMembers.addAll(servers);
+            return this;
+        }
+
+        @Override
+        public SyncReconfigurable storingStatIn(final Stat stat) {
+            return new SyncReconfigurable() {
+                @Override
+                public byte[] fromConfig(long config) throws Exception {
+                    return client.getZooKeeper().reconfig(null, null, newMembers, config, stat);
+                }
+            };
+        }
+
+        @Override
+        public AsyncReconfigurable usingDataCallback(final DataCallback callback, final Object ctx) {
+            return new AsyncReconfigurable() {
+                @Override
+                public void fromConfig(long config) throws Exception {
+                    client.getZooKeeper().reconfig(null, null, newMembers, config, callback, ctx);
+                }
+            };
+        }
+    }
+
+
+    public ReconfigBuilderImpl(CuratorFrameworkImpl client) {
+        this.client = client;
+    }
+
+    @Override
+    public IncrementalReconfigBuilder<byte[]> join(String server) {
+        return new IncrementalReconfigBuilderImpl(client).join(server);
+    }
+
+    @Override
+    public IncrementalReconfigBuilder<byte[]> join(Collection<String> servers) {
+        return new IncrementalReconfigBuilderImpl(client).join(servers);
+    }
+
+    @Override
+    public IncrementalReconfigBuilder<byte[]> leave(String server) {
+        return new IncrementalReconfigBuilderImpl(client).leave(server);
+    }
+
+    @Override
+    public IncrementalReconfigBuilder<byte[]> leave(Collection<String> servers) {
+        return new IncrementalReconfigBuilderImpl(client).leave(servers);
+    }
+
+    @Override
+    public NonIncrementalReconfigBuilder<byte[]> withMember(String server) {
+        return new NonIncrementalReconfigBuilderImpl(client).withMember(server);
+    }
+
+    @Override
+    public NonIncrementalReconfigBuilder<byte[]> withMembers(Collection<String> servers) {
+        return new NonIncrementalReconfigBuilderImpl<byte[]>(client).withMembers(servers);
+    }
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/2bd53fc2/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java
new file mode 100644
index 0000000..6918825
--- /dev/null
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java
@@ -0,0 +1,303 @@
+/**
+ * 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.curator.framework.imps;
+
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.retry.RetryOneTime;
+import org.apache.curator.test.InstanceSpec;
+import org.apache.curator.test.TestingCluster;
+import org.apache.zookeeper.AsyncCallback;
+import org.apache.zookeeper.data.Stat;
+import org.apache.zookeeper.server.quorum.flexible.QuorumMaj;
+import org.apache.zookeeper.server.quorum.flexible.QuorumVerifier;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.Properties;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+public class TestReconfiguration {
+
+    static TestingCluster cluster;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        cluster = new TestingCluster(5);
+        cluster.start();
+    }
+
+    @AfterClass
+    public void tearDown() throws IOException {
+        cluster.close();
+    }
+
+    @Test
+    public void testSyncIncremental() throws Exception {
+        CuratorFramework client = CuratorFrameworkFactory.newClient(cluster.getConnectString(), new RetryOneTime(1));
+        client.start();
+        client.blockUntilConnected();
+        try {
+            Stat stat = new Stat();
+            byte[] bytes = client.getConfig().storingStatIn(stat);
+            Assert.assertNotNull(bytes);
+            QuorumVerifier qv = getQuorumVerifier(bytes);
+            Assert.assertEquals(5, qv.getAllMembers().size());
+            String server1 = getServerString(qv, cluster, 1L);
+            String server2 = getServerString(qv, cluster, 2L);
+
+            //Remove Servers
+            bytes = client.reconfig().leave("1").storingStatIn(stat).fromConfig(qv.getVersion());
+            qv = getQuorumVerifier(bytes);
+            Assert.assertEquals(4, qv.getAllMembers().size());
+            bytes = client.reconfig().leave("2").storingStatIn(stat).fromConfig(qv.getVersion());
+            qv = getQuorumVerifier(bytes);
+            Assert.assertEquals(3, qv.getAllMembers().size());
+
+            //Add Servers
+            bytes = client.reconfig().join("server.1=" + server1).storingStatIn(stat).fromConfig(qv.getVersion());
+            qv = getQuorumVerifier(bytes);
+            Assert.assertEquals(4, qv.getAllMembers().size());
+            bytes = client.reconfig().join("server.2=" + server2).storingStatIn(stat).fromConfig(qv.getVersion());
+            qv = getQuorumVerifier(bytes);
+            Assert.assertEquals(5, qv.getAllMembers().size());
+        } finally {
+            client.close();
+        }
+    }
+
+    @Test
+    public void testAsyncIncremental() throws Exception {
+        CuratorFramework client = CuratorFrameworkFactory.newClient(cluster.getConnectString(), new RetryOneTime(1));
+        client.start();
+        client.blockUntilConnected();
+        try {
+            final AtomicReference<byte[]> bytes = new AtomicReference<byte[]>();
+            final AsyncCallback.DataCallback callback = new AsyncCallback.DataCallback() {
+                @Override
+                public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat) {
+                    bytes.set(data);
+                    ((CountDownLatch)ctx).countDown();
+                }
+            };
+
+            CountDownLatch latch = new CountDownLatch(1);
+            client.getConfig().usingDataCallback(callback, latch);
+            latch.await(5, TimeUnit.SECONDS);
+            Assert.assertNotNull(bytes.get());
+            QuorumVerifier qv = getQuorumVerifier(bytes.get());
+            Assert.assertEquals(5, qv.getAllMembers().size());
+            String server1 = getServerString(qv, cluster, 1L);
+            String server2 = getServerString(qv, cluster, 2L);
+
+
+            //Remove Servers
+            latch = new CountDownLatch(1);
+            client.reconfig().leave("1").usingDataCallback(callback, latch).fromConfig(qv.getVersion());
+            latch.await(5, TimeUnit.SECONDS);
+            qv = getQuorumVerifier(bytes.get());
+            Assert.assertEquals(4, qv.getAllMembers().size());
+            latch = new CountDownLatch(1);
+            client.reconfig().leave("2").usingDataCallback(callback, latch).fromConfig(qv.getVersion());
+            latch.await(5, TimeUnit.SECONDS);
+            qv = getQuorumVerifier(bytes.get());
+            Assert.assertEquals(3, qv.getAllMembers().size());
+
+            //Add Servers
+            latch = new CountDownLatch(1);
+            client.reconfig().join("server.1=" + server1).usingDataCallback(callback, latch).fromConfig(qv.getVersion());
+            latch.await(5, TimeUnit.SECONDS);
+            qv = getQuorumVerifier(bytes.get());
+            Assert.assertEquals(4, qv.getAllMembers().size());
+            latch = new CountDownLatch(1);
+            client.reconfig().join("server.2=" + server2).usingDataCallback(callback, latch).fromConfig(qv.getVersion());
+            latch.await(5, TimeUnit.SECONDS);
+            qv = getQuorumVerifier(bytes.get());
+            Assert.assertEquals(5, qv.getAllMembers().size());
+        } finally {
+            client.close();
+        }
+    }
+
+    @Test
+    public void testSyncNonIncremental() throws Exception {
+        CuratorFramework client = CuratorFrameworkFactory.newClient(cluster.getConnectString(), new RetryOneTime(1));
+        client.start();
+        client.blockUntilConnected();
+        try {
+            Stat stat = new Stat();
+            byte[] bytes = client.getConfig().storingStatIn(stat);
+            Assert.assertNotNull(bytes);
+            QuorumVerifier qv = getQuorumVerifier(bytes);
+            Assert.assertEquals(5, qv.getAllMembers().size());
+            String server1 = getServerString(qv, cluster, 1L);
+            String server2 = getServerString(qv, cluster, 2L);
+            String server3 = getServerString(qv, cluster, 3L);
+            String server4 = getServerString(qv, cluster, 4L);
+            String server5 = getServerString(qv, cluster, 5L);
+
+            //Remove Servers
+            bytes = client.reconfig()
+                    .withMember("server.2="+server2)
+                    .withMember("server.3="+server3)
+                    .withMember("server.4="+server4)
+                    .withMember("server.5="+server5)
+                    .storingStatIn(stat).fromConfig(qv.getVersion());
+            qv = getQuorumVerifier(bytes);
+            Assert.assertEquals(4, qv.getAllMembers().size());
+            bytes = client.reconfig()
+                    .withMember("server.3=" + server3)
+                    .withMember("server.4=" + server4)
+                    .withMember("server.5=" + server5)
+                    .storingStatIn(stat).fromConfig(qv.getVersion());
+
+            qv = getQuorumVerifier(bytes);
+            Assert.assertEquals(3, qv.getAllMembers().size());
+
+            //Add Servers
+            bytes = client.reconfig()
+                    .withMember("server.1="+server1)
+                    .withMember("server.3=" + server3)
+                    .withMember("server.4="+server4)
+                    .withMember("server.5="+server5)
+                    .storingStatIn(stat).fromConfig(qv.getVersion());
+            qv = getQuorumVerifier(bytes);
+            Assert.assertEquals(4, qv.getAllMembers().size());
+            bytes = client.reconfig()
+                    .withMember("server.1="+server1)
+                    .withMember("server.2="+server2)
+                    .withMember("server.3=" + server3)
+                    .withMember("server.4="+server4)
+                    .withMember("server.5="+server5)
+                    .storingStatIn(stat).fromConfig(qv.getVersion());
+            qv = getQuorumVerifier(bytes);
+            Assert.assertEquals(5, qv.getAllMembers().size());
+        } finally {
+            client.close();
+        }
+    }
+
+    @Test
+    public void testAsyncNonIncremental() throws Exception {
+        CuratorFramework client = CuratorFrameworkFactory.newClient(cluster.getConnectString(), new RetryOneTime(1));
+        client.start();
+        client.blockUntilConnected();
+        try {
+            final AtomicReference<byte[]> bytes = new AtomicReference<byte[]>();
+            final AsyncCallback.DataCallback callback = new AsyncCallback.DataCallback() {
+                @Override
+                public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat) {
+                    bytes.set(data);
+                    ((CountDownLatch)ctx).countDown();
+                }
+            };
+
+            CountDownLatch latch = new CountDownLatch(1);
+            client.getConfig().usingDataCallback(callback, latch);
+            latch.await(5, TimeUnit.SECONDS);
+            Assert.assertNotNull(bytes.get());
+            QuorumVerifier qv = getQuorumVerifier(bytes.get());
+            Assert.assertEquals(5, qv.getAllMembers().size());
+            String server1 = getServerString(qv, cluster, 1L);
+            String server2 = getServerString(qv, cluster, 2L);
+            String server3 = getServerString(qv, cluster, 3L);
+            String server4 = getServerString(qv, cluster, 4L);
+            String server5 = getServerString(qv, cluster, 5L);
+
+
+            //Remove Servers
+            latch = new CountDownLatch(1);
+            client.reconfig()
+                    .withMember("server.2=" + server2)
+                    .withMember("server.3="+server3)
+                    .withMember("server.4="+server4)
+                    .withMember("server.5="+server5)
+            .usingDataCallback(callback, latch).fromConfig(qv.getVersion());
+            latch.await(5, TimeUnit.SECONDS);
+            qv = getQuorumVerifier(bytes.get());
+            Assert.assertEquals(4, qv.getAllMembers().size());
+            latch = new CountDownLatch(1);
+            client.reconfig()
+                    .withMember("server.3="+server3)
+                    .withMember("server.4=" + server4)
+                    .withMember("server.5=" + server5)
+                    .usingDataCallback(callback, latch).fromConfig(qv.getVersion());
+            latch.await(5, TimeUnit.SECONDS);
+            qv = getQuorumVerifier(bytes.get());
+            Assert.assertEquals(3, qv.getAllMembers().size());
+
+            //Add Servers
+            latch = new CountDownLatch(1);
+            client.reconfig()
+                    .withMember("server.1="+server1)
+                    .withMember("server.3=" + server3)
+                    .withMember("server.4=" + server4)
+                    .withMember("server.5=" + server5)
+                    .usingDataCallback(callback, latch).fromConfig(qv.getVersion());
+            latch.await(5, TimeUnit.SECONDS);
+            qv = getQuorumVerifier(bytes.get());
+            Assert.assertEquals(4, qv.getAllMembers().size());
+            latch = new CountDownLatch(1);
+            client.reconfig()
+                    .withMember("server.1="+server1)
+                    .withMember("server.2="+server2)
+                    .withMember("server.3="+server3)
+                    .withMember("server.4=" + server4)
+                    .withMember("server.5=" + server5)
+                    .usingDataCallback(callback, latch).fromConfig(qv.getVersion());
+            latch.await(5, TimeUnit.SECONDS);
+            qv = getQuorumVerifier(bytes.get());
+            Assert.assertEquals(5, qv.getAllMembers().size());
+        } finally {
+            client.close();
+        }
+    }
+
+
+    static QuorumVerifier getQuorumVerifier(byte[] bytes) throws Exception {
+        Properties properties = new Properties();
+        properties.load(new StringReader(new String(bytes)));
+        return new QuorumMaj(properties);
+    }
+
+    static InstanceSpec getInstance(TestingCluster cluster, int id) {
+        for (InstanceSpec spec : cluster.getInstances()) {
+            if (spec.getServerId() == id) {
+                return spec;
+            }
+        }
+        throw new IllegalStateException("InstanceSpec with id:" + id + " not found");
+    }
+
+    static String getServerString(QuorumVerifier qv, TestingCluster cluster, long id) throws Exception {
+        String str = qv.getAllMembers().get(id).toString();
+        //check if connection string is already there.
+        if (str.contains(";")) {
+            return str;
+        } else {
+            return str + ";" + getInstance(cluster, (int) id).getConnectString();
+        }
+    }
+}
\ No newline at end of file


[26/27] curator git commit: Updated example and some other wip

Posted by dr...@apache.org.
Updated example and some other wip


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/4275b3c6
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/4275b3c6
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/4275b3c6

Branch: refs/heads/CURATOR-215
Commit: 4275b3c60c9350a2c0cd3d7297643db03ba3304d
Parents: bf0649a
Author: randgalt <ra...@apache.org>
Authored: Tue May 12 14:46:06 2015 -0500
Committer: Scott Blum <dr...@apache.org>
Committed: Wed Aug 12 17:29:43 2015 -0400

----------------------------------------------------------------------
 .../java/framework/TransactionExamples.java     | 50 ++++----------------
 .../framework/imps/ExtractingCuratorOp.java     |  5 --
 .../framework/imps/TransactionOpImpl.java       |  8 ++--
 3 files changed, 14 insertions(+), 49 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/4275b3c6/curator-examples/src/main/java/framework/TransactionExamples.java
----------------------------------------------------------------------
diff --git a/curator-examples/src/main/java/framework/TransactionExamples.java b/curator-examples/src/main/java/framework/TransactionExamples.java
index f559b5a..7ff8064 100644
--- a/curator-examples/src/main/java/framework/TransactionExamples.java
+++ b/curator-examples/src/main/java/framework/TransactionExamples.java
@@ -19,25 +19,24 @@
 package framework;
 
 import org.apache.curator.framework.CuratorFramework;
-import org.apache.curator.framework.api.transaction.CuratorTransaction;
-import org.apache.curator.framework.api.transaction.CuratorTransactionFinal;
+import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.framework.api.transaction.CuratorOp;
 import org.apache.curator.framework.api.transaction.CuratorTransactionResult;
+import org.apache.curator.retry.RetryOneTime;
+import org.apache.curator.test.TestingServer;
 import java.util.Collection;
 
 public class TransactionExamples
 {
     public static Collection<CuratorTransactionResult>      transaction(CuratorFramework client) throws Exception
     {
-        // this example shows how to use ZooKeeper's new transactions
+        // this example shows how to use ZooKeeper's transactions
 
-        Collection<CuratorTransactionResult>    results = client.inTransaction()
-                .create().forPath("/a/path", "some data".getBytes())
-            .and()
-                .setData().forPath("/another/path", "other data".getBytes())
-            .and()
-                .delete().forPath("/yet/another/path")
-            .and()
-                .commit();  // IMPORTANT! The transaction is not submitted until commit() is called
+        CuratorOp createOp = client.transactionOp().create().forPath("/a/path", "some data".getBytes());
+        CuratorOp setDataOp = client.transactionOp().setData().forPath("/another/path", "other data".getBytes());
+        CuratorOp deleteOp = client.transactionOp().delete().forPath("/yet/another/path");
+
+        Collection<CuratorTransactionResult>    results = client.transaction().forOperations(createOp, setDataOp, deleteOp);
 
         for ( CuratorTransactionResult result : results )
         {
@@ -46,33 +45,4 @@ public class TransactionExamples
 
         return results;
     }
-
-    /*
-            These next four methods show how to use Curator's transaction APIs in a more
-            traditional - one-at-a-time - manner
-     */
-
-    public static CuratorTransaction        startTransaction(CuratorFramework client)
-    {
-        // start the transaction builder
-        return client.inTransaction();
-    }
-
-    public static CuratorTransactionFinal   addCreateToTransaction(CuratorTransaction transaction) throws Exception
-    {
-        // add a create operation
-        return transaction.create().forPath("/a/path", "some data".getBytes()).and();
-    }
-
-    public static CuratorTransactionFinal   addDeleteToTransaction(CuratorTransaction transaction) throws Exception
-    {
-        // add a delete operation
-        return transaction.delete().forPath("/another/path").and();
-    }
-
-    public static void                      commitTransaction(CuratorTransactionFinal transaction) throws Exception
-    {
-        // commit the transaction
-        transaction.commit();
-    }
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/4275b3c6/curator-framework/src/main/java/org/apache/curator/framework/imps/ExtractingCuratorOp.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/ExtractingCuratorOp.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/ExtractingCuratorOp.java
index 40bd8c8..7a5db69 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/ExtractingCuratorOp.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/ExtractingCuratorOp.java
@@ -32,11 +32,6 @@ class ExtractingCuratorOp implements CuratorOp
         return record;
     }
 
-    CuratorOp asCuratorOp()
-    {
-        return this;
-    }
-
     @Override
     public TypeAndPath getTypeAndPath()
     {

http://git-wip-us.apache.org/repos/asf/curator/blob/4275b3c6/curator-framework/src/main/java/org/apache/curator/framework/imps/TransactionOpImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/TransactionOpImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/TransactionOpImpl.java
index e0ada17..381842b 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/TransactionOpImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/TransactionOpImpl.java
@@ -38,28 +38,28 @@ public class TransactionOpImpl implements TransactionOp
     public TransactionCreateBuilder<CuratorOp> create()
     {
         ExtractingCuratorOp op = new ExtractingCuratorOp();
-        return new CreateBuilderImpl(client).asTransactionCreateBuilder(op.asCuratorOp(), op.getRecord());
+        return new CreateBuilderImpl(client).<CuratorOp>asTransactionCreateBuilder(op, op.getRecord());
     }
 
     @Override
     public TransactionDeleteBuilder<CuratorOp> delete()
     {
         ExtractingCuratorOp op = new ExtractingCuratorOp();
-        return new DeleteBuilderImpl(client).asTransactionDeleteBuilder(op.asCuratorOp(), op.getRecord());
+        return new DeleteBuilderImpl(client).<CuratorOp>asTransactionDeleteBuilder(op, op.getRecord());
     }
 
     @Override
     public TransactionSetDataBuilder<CuratorOp> setData()
     {
         ExtractingCuratorOp op = new ExtractingCuratorOp();
-        return new SetDataBuilderImpl(client).asTransactionSetDataBuilder(op.asCuratorOp(), op.getRecord());
+        return new SetDataBuilderImpl(client).<CuratorOp>asTransactionSetDataBuilder(op, op.getRecord());
     }
 
     @Override
     public TransactionCheckBuilder<CuratorOp> check()
     {
         ExtractingCuratorOp op = new ExtractingCuratorOp();
-        return CuratorTransactionImpl.makeTransactionCheckBuilder(client, op.asCuratorOp(), op.getRecord());
+        return CuratorTransactionImpl.<CuratorOp>makeTransactionCheckBuilder(client, op, op.getRecord());
     }
 
 }


[03/27] curator git commit: JDK version should be 1.7

Posted by dr...@apache.org.
JDK version should be 1.7


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/143044bb
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/143044bb
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/143044bb

Branch: refs/heads/CURATOR-215
Commit: 143044bb7586718aee5cca1a30983b876a5f304b
Parents: c026df7
Author: randgalt <ra...@apache.org>
Authored: Tue May 5 23:13:21 2015 -0500
Committer: Scott Blum <dr...@apache.org>
Committed: Wed Aug 12 14:31:49 2015 -0400

----------------------------------------------------------------------
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/143044bb/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index bcb9caf..0319c8d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -56,7 +56,7 @@
         <project.build.resourceEncoding>UTF-8</project.build.resourceEncoding>
         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
 
-        <jdk-version>1.6</jdk-version>
+        <jdk-version>1.7</jdk-version>
 
         <surefire-forkcount>1</surefire-forkcount>
 


[02/27] curator git commit: Update project version to 3.0.0-SNAPSHOT.

Posted by dr...@apache.org.
Update project version to 3.0.0-SNAPSHOT.


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

Branch: refs/heads/CURATOR-215
Commit: c026df787ab6a547d1eeeafd5785e2859d3e7963
Parents: 227aaf3
Author: Ioannis Canellos <io...@gmail.com>
Authored: Thu Nov 6 17:30:29 2014 +0200
Committer: Scott Blum <dr...@apache.org>
Committed: Wed Aug 12 14:31:21 2015 -0400

----------------------------------------------------------------------
 curator-client/pom.xml             | 4 ++--
 curator-examples/pom.xml           | 2 +-
 curator-framework/pom.xml          | 4 ++--
 curator-recipes/pom.xml            | 4 ++--
 curator-test/pom.xml               | 4 ++--
 curator-x-discovery-server/pom.xml | 4 ++--
 curator-x-discovery/pom.xml        | 4 ++--
 curator-x-rpc/pom.xml              | 4 ++--
 pom.xml                            | 2 +-
 9 files changed, 16 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/c026df78/curator-client/pom.xml
----------------------------------------------------------------------
diff --git a/curator-client/pom.xml b/curator-client/pom.xml
index 50b950f..0f3955b 100644
--- a/curator-client/pom.xml
+++ b/curator-client/pom.xml
@@ -24,11 +24,11 @@
     <parent>
         <groupId>org.apache.curator</groupId>
         <artifactId>apache-curator</artifactId>
-        <version>2.8.1-SNAPSHOT</version>
+        <version>3.0.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>curator-client</artifactId>
-    <version>2.8.1-SNAPSHOT</version>
+    <version>3.0.0-SNAPSHOT</version>
     <packaging>bundle</packaging>
 
     <name>Curator Client</name>

http://git-wip-us.apache.org/repos/asf/curator/blob/c026df78/curator-examples/pom.xml
----------------------------------------------------------------------
diff --git a/curator-examples/pom.xml b/curator-examples/pom.xml
index 85eaaf7..825ca16 100644
--- a/curator-examples/pom.xml
+++ b/curator-examples/pom.xml
@@ -24,7 +24,7 @@
     <parent>
         <groupId>org.apache.curator</groupId>
         <artifactId>apache-curator</artifactId>
-        <version>2.8.1-SNAPSHOT</version>
+        <version>3.0.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>curator-examples</artifactId>

http://git-wip-us.apache.org/repos/asf/curator/blob/c026df78/curator-framework/pom.xml
----------------------------------------------------------------------
diff --git a/curator-framework/pom.xml b/curator-framework/pom.xml
index 3b3e346..a45ce77 100644
--- a/curator-framework/pom.xml
+++ b/curator-framework/pom.xml
@@ -24,11 +24,11 @@
     <parent>
         <groupId>org.apache.curator</groupId>
         <artifactId>apache-curator</artifactId>
-        <version>2.8.1-SNAPSHOT</version>
+        <version>3.0.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>curator-framework</artifactId>
-    <version>2.8.1-SNAPSHOT</version>
+    <version>3.0.0-SNAPSHOT</version>
     <packaging>bundle</packaging>
 
     <name>Curator Framework</name>

http://git-wip-us.apache.org/repos/asf/curator/blob/c026df78/curator-recipes/pom.xml
----------------------------------------------------------------------
diff --git a/curator-recipes/pom.xml b/curator-recipes/pom.xml
index 8913b6f..9d1d081 100644
--- a/curator-recipes/pom.xml
+++ b/curator-recipes/pom.xml
@@ -24,11 +24,11 @@
     <parent>
         <groupId>org.apache.curator</groupId>
         <artifactId>apache-curator</artifactId>
-        <version>2.8.1-SNAPSHOT</version>
+        <version>3.0.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>curator-recipes</artifactId>
-    <version>2.8.1-SNAPSHOT</version>
+    <version>3.0.0-SNAPSHOT</version>
     <packaging>bundle</packaging>
 
     <name>Curator Recipes</name>

http://git-wip-us.apache.org/repos/asf/curator/blob/c026df78/curator-test/pom.xml
----------------------------------------------------------------------
diff --git a/curator-test/pom.xml b/curator-test/pom.xml
index d3301ca..1cbd93c 100644
--- a/curator-test/pom.xml
+++ b/curator-test/pom.xml
@@ -24,11 +24,11 @@
     <parent>
         <groupId>org.apache.curator</groupId>
         <artifactId>apache-curator</artifactId>
-        <version>2.8.1-SNAPSHOT</version>
+        <version>3.0.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>curator-test</artifactId>
-    <version>2.8.1-SNAPSHOT</version>
+    <version>3.0.0-SNAPSHOT</version>
 
     <name>Curator Testing</name>
     <description>Unit testing utilities.</description>

http://git-wip-us.apache.org/repos/asf/curator/blob/c026df78/curator-x-discovery-server/pom.xml
----------------------------------------------------------------------
diff --git a/curator-x-discovery-server/pom.xml b/curator-x-discovery-server/pom.xml
index 451f46c..352310f 100644
--- a/curator-x-discovery-server/pom.xml
+++ b/curator-x-discovery-server/pom.xml
@@ -24,11 +24,11 @@
     <parent>
         <groupId>org.apache.curator</groupId>
         <artifactId>apache-curator</artifactId>
-        <version>2.8.1-SNAPSHOT</version>
+        <version>3.0.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>curator-x-discovery-server</artifactId>
-    <version>2.8.1-SNAPSHOT</version>
+    <version>3.0.0-SNAPSHOT</version>
     <packaging>bundle</packaging>
 
     <name>Curator Service Discovery Server</name>

http://git-wip-us.apache.org/repos/asf/curator/blob/c026df78/curator-x-discovery/pom.xml
----------------------------------------------------------------------
diff --git a/curator-x-discovery/pom.xml b/curator-x-discovery/pom.xml
index 8c08a10..e211d89 100644
--- a/curator-x-discovery/pom.xml
+++ b/curator-x-discovery/pom.xml
@@ -24,11 +24,11 @@
     <parent>
         <groupId>org.apache.curator</groupId>
         <artifactId>apache-curator</artifactId>
-        <version>2.8.1-SNAPSHOT</version>
+        <version>3.0.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>curator-x-discovery</artifactId>
-    <version>2.8.1-SNAPSHOT</version>
+    <version>3.0.0-SNAPSHOT</version>
     <packaging>bundle</packaging>
 
     <name>Curator Service Discovery</name>

http://git-wip-us.apache.org/repos/asf/curator/blob/c026df78/curator-x-rpc/pom.xml
----------------------------------------------------------------------
diff --git a/curator-x-rpc/pom.xml b/curator-x-rpc/pom.xml
index 222310b..6f56f6f 100644
--- a/curator-x-rpc/pom.xml
+++ b/curator-x-rpc/pom.xml
@@ -22,12 +22,12 @@
     <parent>
         <artifactId>apache-curator</artifactId>
         <groupId>org.apache.curator</groupId>
-        <version>2.8.1-SNAPSHOT</version>
+        <version>3.0.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>curator-x-rpc</artifactId>
-    <version>2.8.1-SNAPSHOT</version>
+    <version>3.0.0-SNAPSHOT</version>
 
     <name>Curator RPC Proxy</name>
     <description>A proxy that bridges non-java environments with the Curator framework and recipes</description>

http://git-wip-us.apache.org/repos/asf/curator/blob/c026df78/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 21eefbf..bcb9caf 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,7 +28,7 @@
 
     <groupId>org.apache.curator</groupId>
     <artifactId>apache-curator</artifactId>
-    <version>2.8.1-SNAPSHOT</version>
+    <version>3.0.0-SNAPSHOT</version>
     <packaging>pom</packaging>
 
     <name>Apache Curator</name>


[07/27] curator git commit: [CURATOR-160] Add EnsembleListener and EnsembleTracker. Implement a DynamicEnsembleProvider. TestReconfiguration now also tests the DynamicEnsembleProvider.

Posted by dr...@apache.org.
[CURATOR-160] Add EnsembleListener and EnsembleTracker. Implement a DynamicEnsembleProvider. TestReconfiguration now also tests the DynamicEnsembleProvider.


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/4ec5ffe3
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/4ec5ffe3
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/4ec5ffe3

Branch: refs/heads/CURATOR-215
Commit: 4ec5ffe3a9d1c14a0a5acbe1ebb5552a284a8908
Parents: ec4083f
Author: Ioannis Canellos <io...@gmail.com>
Authored: Tue Nov 11 16:35:57 2014 +0200
Committer: Scott Blum <dr...@apache.org>
Committed: Wed Aug 12 17:08:33 2015 -0400

----------------------------------------------------------------------
 .../curator/ensemble/EnsembleListener.java      |  24 +
 .../dynamic/DynamicEnsembleProvider.java        |  61 +++
 .../curator/framework/imps/EnsembleTracker.java | 167 +++++++
 .../framework/imps/TestReconfiguration.java     | 489 +++++++++++--------
 4 files changed, 538 insertions(+), 203 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/4ec5ffe3/curator-client/src/main/java/org/apache/curator/ensemble/EnsembleListener.java
----------------------------------------------------------------------
diff --git a/curator-client/src/main/java/org/apache/curator/ensemble/EnsembleListener.java b/curator-client/src/main/java/org/apache/curator/ensemble/EnsembleListener.java
new file mode 100644
index 0000000..8f963cd
--- /dev/null
+++ b/curator-client/src/main/java/org/apache/curator/ensemble/EnsembleListener.java
@@ -0,0 +1,24 @@
+/**
+ * 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.curator.ensemble;
+
+public interface EnsembleListener {
+
+    void connectionStringUpdated(String connectionString);
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/4ec5ffe3/curator-client/src/main/java/org/apache/curator/ensemble/dynamic/DynamicEnsembleProvider.java
----------------------------------------------------------------------
diff --git a/curator-client/src/main/java/org/apache/curator/ensemble/dynamic/DynamicEnsembleProvider.java b/curator-client/src/main/java/org/apache/curator/ensemble/dynamic/DynamicEnsembleProvider.java
new file mode 100644
index 0000000..70b755f
--- /dev/null
+++ b/curator-client/src/main/java/org/apache/curator/ensemble/dynamic/DynamicEnsembleProvider.java
@@ -0,0 +1,61 @@
+/**
+ * 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.curator.ensemble.dynamic;
+
+import com.google.common.base.Preconditions;
+import org.apache.curator.ensemble.EnsembleListener;
+import org.apache.curator.ensemble.EnsembleProvider;
+
+import java.io.IOException;
+import java.util.concurrent.atomic.AtomicReference;
+
+public class DynamicEnsembleProvider implements EnsembleProvider, EnsembleListener {
+
+    private final AtomicReference<String> connectionString = new AtomicReference<String>();
+
+    /**
+     * The connection string to use
+     *
+     * @param connectionString connection string
+     */
+    public DynamicEnsembleProvider(String connectionString)
+    {
+        this.connectionString.set(Preconditions.checkNotNull(connectionString, "connectionString cannot be null"));
+    }
+
+    @Override
+    public void start() throws Exception {
+        // NOP
+    }
+
+    @Override
+    public String getConnectionString() {
+        return connectionString.get();
+    }
+
+    @Override
+    public void close() throws IOException {
+        // NOP
+    }
+
+    @Override
+    public void connectionStringUpdated(String connectionString) {
+        this.connectionString.set(connectionString);
+    }
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/4ec5ffe3/curator-framework/src/main/java/org/apache/curator/framework/imps/EnsembleTracker.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/EnsembleTracker.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/EnsembleTracker.java
new file mode 100644
index 0000000..a789e42
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/EnsembleTracker.java
@@ -0,0 +1,167 @@
+/**
+ * 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.curator.framework.imps;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import org.apache.curator.ensemble.EnsembleListener;
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.api.BackgroundCallback;
+import org.apache.curator.framework.api.CuratorEvent;
+import org.apache.curator.framework.api.CuratorWatcher;
+import org.apache.curator.framework.listen.ListenerContainer;
+import org.apache.curator.framework.state.ConnectionState;
+import org.apache.curator.framework.state.ConnectionStateListener;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.server.quorum.QuorumPeer;
+import org.apache.zookeeper.server.quorum.flexible.QuorumMaj;
+import org.apache.zookeeper.server.quorum.flexible.QuorumVerifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.ByteArrayInputStream;
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Tracks changes to the ensemble and notifies registered {@link org.apache.curator.ensemble.EnsembleListener} instances.
+ */
+public class EnsembleTracker implements Closeable {
+
+    private final Logger log = LoggerFactory.getLogger(getClass());
+    private final CuratorFramework client;
+    private final AtomicReference<State> state = new AtomicReference<State>(State.LATENT);
+    private final ListenerContainer<EnsembleListener> listeners = new ListenerContainer<EnsembleListener>();
+    private final AtomicBoolean isConnected = new AtomicBoolean(true);
+    private final ConnectionStateListener connectionStateListener = new ConnectionStateListener() {
+        @Override
+        public void stateChanged(CuratorFramework client, ConnectionState newState) {
+            if ((newState == ConnectionState.CONNECTED) || (newState == ConnectionState.RECONNECTED)) {
+                if (isConnected.compareAndSet(false, true)) {
+                    try {
+                        reset();
+                    } catch (Exception e) {
+                        log.error("Trying to reset after reconnection", e);
+                    }
+                }
+            } else {
+                isConnected.set(false);
+            }
+        }
+    };
+
+    private final CuratorWatcher watcher = new CuratorWatcher() {
+        @Override
+        public void process(WatchedEvent event) throws Exception {
+            reset();
+        }
+    };
+
+
+    private enum State {
+        LATENT,
+        STARTED,
+        CLOSED
+    }
+
+    private final BackgroundCallback backgroundCallback = new BackgroundCallback() {
+        @Override
+        public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
+            processBackgroundResult(event);
+        }
+    };
+
+
+    public EnsembleTracker(CuratorFramework client) {
+        this.client = client;
+    }
+
+    public void start() throws Exception {
+        Preconditions.checkState(state.compareAndSet(State.LATENT, State.STARTED), "Cannot be started more than once");
+        client.getConnectionStateListenable().addListener(connectionStateListener);
+        reset();
+    }
+
+    @Override
+    public void close() throws IOException {
+        if (state.compareAndSet(State.STARTED, State.CLOSED)) {
+            listeners.clear();
+        }
+        client.getConnectionStateListenable().removeListener(connectionStateListener);
+    }
+
+    /**
+     * Return the ensemble listenable
+     *
+     * @return listenable
+     */
+    public ListenerContainer<EnsembleListener> getListenable()
+    {
+        Preconditions.checkState(state.get() != State.CLOSED, "Closed");
+
+        return listeners;
+    }
+
+    private void reset() throws Exception {
+        client.getConfig().usingWatcher(watcher).inBackground(backgroundCallback).forEnsemble();
+    }
+
+    private void processBackgroundResult(CuratorEvent event) throws Exception {
+        switch (event.getType()) {
+            case GET_CONFIG: {
+                if (event.getResultCode() == KeeperException.Code.OK.intValue()) {
+                    processConfigData(event.getData());
+                }
+            }
+        }
+    }
+
+    private void processConfigData(byte[] data) throws Exception {
+        Properties properties = new Properties();
+        properties.load(new ByteArrayInputStream(data));
+        QuorumVerifier qv = new QuorumMaj(properties);
+        StringBuilder sb = new StringBuilder();
+        for (QuorumPeer.QuorumServer server : qv.getAllMembers().values()) {
+            if (sb.length() != 0) {
+                sb.append(",");
+            }
+            sb.append(server.clientAddr.getAddress().getHostAddress()).append(":").append(server.clientAddr.getPort());
+        }
+
+        final String connectionString = sb.toString();
+        listeners.forEach
+                (
+                        new Function<EnsembleListener, Void>() {
+                            @Override
+                            public Void apply(EnsembleListener listener) {
+                                try {
+                                    listener.connectionStringUpdated(connectionString);
+                                } catch (Exception e) {
+                                    log.error("Calling listener", e);
+                                }
+                                return null;
+                            }
+                        }
+                );
+    }
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/4ec5ffe3/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java
index e8896ae..faec551 100644
--- a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java
@@ -18,6 +18,8 @@
  */
 package org.apache.curator.framework.imps;
 
+import org.apache.curator.ensemble.EnsembleListener;
+import org.apache.curator.ensemble.dynamic.DynamicEnsembleProvider;
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
 import org.apache.curator.framework.api.BackgroundCallback;
@@ -35,246 +37,287 @@ import org.testng.annotations.Test;
 
 import java.io.IOException;
 import java.io.StringReader;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Properties;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicReference;
 
 public class TestReconfiguration {
 
     TestingCluster cluster;
+    DynamicEnsembleProvider dynamicEnsembleProvider;
+    WaitOnDelegateListener waitOnDelegateListener;
+    EnsembleTracker ensembleTracker;
+    CuratorFramework client;
+
+    String connectionString1to5;
+    String connectionString2to5;
+    String connectionString3to5;
 
     @BeforeMethod
     public void setup() throws Exception {
         cluster = new TestingCluster(5);
         cluster.start();
+
+        connectionString1to5 = cluster.getConnectString();
+        connectionString2to5 = getConnectionString(cluster, 2,3,4,5);
+        connectionString3to5 = getConnectionString(cluster, 3,4,5);
+
+        dynamicEnsembleProvider = new DynamicEnsembleProvider(connectionString1to5);
+        client = CuratorFrameworkFactory.builder()
+                .ensembleProvider(dynamicEnsembleProvider)
+                .retryPolicy(new RetryOneTime(1))
+                .build();
+        client.start();
+        client.blockUntilConnected();
+
+        //Wrap around the dynamic ensemble provider, so that we can wait until it has received the event.
+        waitOnDelegateListener = new WaitOnDelegateListener(dynamicEnsembleProvider);
+        ensembleTracker = new EnsembleTracker(client);
+        ensembleTracker.getListenable().addListener(waitOnDelegateListener);
+        ensembleTracker.start();
+        //Wait for the initial event.
+        waitOnDelegateListener.waitForEvent();
     }
 
     @AfterMethod
     public void tearDown() throws IOException {
+        ensembleTracker.close();
+        client.close();
         cluster.close();
     }
 
     @Test
     public void testSyncIncremental() throws Exception {
-        CuratorFramework client = CuratorFrameworkFactory.newClient(cluster.getConnectString(), new RetryOneTime(1));
-        client.start();
-        client.blockUntilConnected();
-        try {
-            Stat stat = new Stat();
-            byte[] bytes = client.getConfig().storingStatIn(stat).forEnsemble();
-            Assert.assertNotNull(bytes);
-            QuorumVerifier qv = getQuorumVerifier(bytes);
-            Assert.assertEquals(qv.getAllMembers().size(), 5);
-            String server1 = getServerString(qv, cluster, 1L);
-            String server2 = getServerString(qv, cluster, 2L);
-
-            //Remove Servers
-            bytes = client.reconfig().leaving("1").storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
-            qv = getQuorumVerifier(bytes);
-            Assert.assertEquals(qv.getAllMembers().size(), 4);
-            bytes = client.reconfig().leaving("2").storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
-            qv = getQuorumVerifier(bytes);
-            Assert.assertEquals(qv.getAllMembers().size(), 3);
-
-            //Add Servers
-            bytes = client.reconfig().joining("server.1=" + server1).storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
-            qv = getQuorumVerifier(bytes);
-            Assert.assertEquals(qv.getAllMembers().size(), 4);
-            bytes = client.reconfig().joining("server.2=" + server2).storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
-            qv = getQuorumVerifier(bytes);
-            Assert.assertEquals(qv.getAllMembers().size(), 5);
-        } finally {
-            client.close();
-        }
+        Stat stat = new Stat();
+        byte[] bytes = client.getConfig().storingStatIn(stat).forEnsemble();
+        Assert.assertNotNull(bytes);
+        QuorumVerifier qv = getQuorumVerifier(bytes);
+        Assert.assertEquals(qv.getAllMembers().size(), 5);
+        String server1 = getServerString(qv, cluster, 1L);
+        String server2 = getServerString(qv, cluster, 2L);
+
+        //Remove Servers
+        bytes = client.reconfig().leaving("1").storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
+        qv = getQuorumVerifier(bytes);
+        Assert.assertEquals(qv.getAllMembers().size(), 4);
+
+        waitOnDelegateListener.waitForEvent();
+        Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString2to5);
+
+        bytes = client.reconfig().leaving("2").storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
+        qv = getQuorumVerifier(bytes);
+        Assert.assertEquals(qv.getAllMembers().size(), 3);
+
+        waitOnDelegateListener.waitForEvent();
+        Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString3to5);
+
+        //Add Servers
+        bytes = client.reconfig().joining("server.2=" + server2).storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
+        qv = getQuorumVerifier(bytes);
+        Assert.assertEquals(qv.getAllMembers().size(), 4);
+
+        waitOnDelegateListener.waitForEvent();
+        Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString2to5);
+
+        bytes = client.reconfig().joining("server.1=" + server1).storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
+        qv = getQuorumVerifier(bytes);
+        Assert.assertEquals(qv.getAllMembers().size(), 5);
+
+        waitOnDelegateListener.waitForEvent();
+        Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString1to5);
     }
 
     @Test
     public void testAsyncIncremental() throws Exception {
-        CuratorFramework client = CuratorFrameworkFactory.newClient(cluster.getConnectString(), new RetryOneTime(1));
-        client.start();
-        client.blockUntilConnected();
-        try {
-            final AtomicReference<byte[]> bytes = new AtomicReference<byte[]>();
-            final BackgroundCallback callback = new BackgroundCallback() {
-                @Override
-                public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
-                    bytes.set(event.getData());
-                    ((CountDownLatch)event.getContext()).countDown();
+        final AtomicReference<byte[]> bytes = new AtomicReference<byte[]>();
+        final BackgroundCallback callback = new BackgroundCallback() {
+            @Override
+            public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
+                bytes.set(event.getData());
+                //We only need the latch on getConfig.
+                if (event.getContext() != null) {
+                    ((CountDownLatch) event.getContext()).countDown();
                 }
+            }
 
-            };
-
-            CountDownLatch latch = new CountDownLatch(1);
-            client.getConfig().inBackground(callback, latch).forEnsemble();
-            latch.await(5, TimeUnit.SECONDS);
-            Assert.assertNotNull(bytes.get());
-            QuorumVerifier qv = getQuorumVerifier(bytes.get());
-            Assert.assertEquals(qv.getAllMembers().size(), 5);
-            String server1 = getServerString(qv, cluster, 1L);
-            String server2 = getServerString(qv, cluster, 2L);
-
-
-            //Remove Servers
-            latch = new CountDownLatch(1);
-            client.reconfig().leaving("1").inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
-            latch.await(5, TimeUnit.SECONDS);
-            qv = getQuorumVerifier(bytes.get());
-            Assert.assertEquals(qv.getAllMembers().size(), 4);
-            latch = new CountDownLatch(1);
-            client.reconfig().leaving("2").inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
-            latch.await(5, TimeUnit.SECONDS);
-            qv = getQuorumVerifier(bytes.get());
-            Assert.assertEquals(qv.getAllMembers().size(), 3);
-
-            //Add Servers
-            latch = new CountDownLatch(1);
-            client.reconfig().joining("server.1=" + server1).inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
-            latch.await(5, TimeUnit.SECONDS);
-            qv = getQuorumVerifier(bytes.get());
-            Assert.assertEquals(qv.getAllMembers().size(), 4);
-            latch = new CountDownLatch(1);
-            client.reconfig().joining("server.2=" + server2).inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
-            latch.await(5, TimeUnit.SECONDS);
-            qv = getQuorumVerifier(bytes.get());
-            Assert.assertEquals(qv.getAllMembers().size(), 5);
-        } finally {
-            client.close();
-        }
+        };
+
+        CountDownLatch latch = new CountDownLatch(1);
+        client.getConfig().inBackground(callback, latch).forEnsemble();
+        latch.await(5, TimeUnit.SECONDS);
+        Assert.assertNotNull(bytes.get());
+        QuorumVerifier qv = getQuorumVerifier(bytes.get());
+        Assert.assertEquals(qv.getAllMembers().size(), 5);
+        String server1 = getServerString(qv, cluster, 1L);
+        String server2 = getServerString(qv, cluster, 2L);
+
+
+        //Remove Servers
+        client.reconfig().leaving("1").inBackground(callback).fromConfig(qv.getVersion()).forEnsemble();
+        waitOnDelegateListener.waitForEvent();
+        Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString2to5);
+        qv = getQuorumVerifier(bytes.get());
+        Assert.assertEquals(qv.getAllMembers().size(), 4);
+
+        client.reconfig().leaving("2").inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
+        waitOnDelegateListener.waitForEvent();
+        Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString3to5);
+        qv = getQuorumVerifier(bytes.get());
+        Assert.assertEquals(qv.getAllMembers().size(), 3);
+
+        //Add Servers
+        client.reconfig().joining("server.2=" + server2).inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
+        waitOnDelegateListener.waitForEvent();
+        Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString2to5);
+        qv = getQuorumVerifier(bytes.get());
+        Assert.assertEquals(qv.getAllMembers().size(), 4);
+
+
+        client.reconfig().joining("server.1=" + server1).inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
+        waitOnDelegateListener.waitForEvent();
+        Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString1to5);
+        qv = getQuorumVerifier(bytes.get());
+        Assert.assertEquals(qv.getAllMembers().size(), 5);
     }
 
     @Test
     public void testSyncNonIncremental() throws Exception {
-        CuratorFramework client = CuratorFrameworkFactory.newClient(cluster.getConnectString(), new RetryOneTime(1));
-        client.start();
-        client.blockUntilConnected();
-        try {
-            Stat stat = new Stat();
-            byte[] bytes = client.getConfig().storingStatIn(stat).forEnsemble();
-            Assert.assertNotNull(bytes);
-            QuorumVerifier qv = getQuorumVerifier(bytes);
-            Assert.assertEquals(qv.getAllMembers().size(), 5);
-            String server1 = getServerString(qv, cluster, 1L);
-            String server2 = getServerString(qv, cluster, 2L);
-            String server3 = getServerString(qv, cluster, 3L);
-            String server4 = getServerString(qv, cluster, 4L);
-            String server5 = getServerString(qv, cluster, 5L);
-
-            //Remove Servers
-            bytes = client.reconfig()
-                    .withMembers("server.2=" + server2,
-                            "server.3=" + server3,
-                            "server.4=" + server4,
-                            "server.5=" + server5)
-                    .storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
-            qv = getQuorumVerifier(bytes);
-            Assert.assertEquals(qv.getAllMembers().size(), 4);
-            bytes = client.reconfig()
-                    .withMembers("server.3=" + server3,
-                            "server.4=" + server4,
-                            "server.5=" + server5)
-                    .storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
-
-            qv = getQuorumVerifier(bytes);
-            Assert.assertEquals(qv.getAllMembers().size(), 3);
-
-            //Add Servers
-            bytes = client.reconfig()
-                    .withMembers("server.1=" + server1,
-                            "server.3=" + server3,
-                            "server.4=" + server4,
-                            "server.5=" + server5)
-                    .storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
-            qv = getQuorumVerifier(bytes);
-            Assert.assertEquals(qv.getAllMembers().size(), 4);
-            bytes = client.reconfig()
-                    .withMembers("server.1=" + server1,
-                            "server.2=" + server2,
-                            "server.3=" + server3,
-                            "server.4=" + server4,
-                            "server.5=" + server5)
-                    .storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
-            qv = getQuorumVerifier(bytes);
-            Assert.assertEquals(qv.getAllMembers().size(), 5);
-        } finally {
-            client.close();
-        }
+        Stat stat = new Stat();
+        byte[] bytes = client.getConfig().storingStatIn(stat).forEnsemble();
+        Assert.assertNotNull(bytes);
+        QuorumVerifier qv = getQuorumVerifier(bytes);
+        Assert.assertEquals(qv.getAllMembers().size(), 5);
+        String server1 = getServerString(qv, cluster, 1L);
+        String server2 = getServerString(qv, cluster, 2L);
+        String server3 = getServerString(qv, cluster, 3L);
+        String server4 = getServerString(qv, cluster, 4L);
+        String server5 = getServerString(qv, cluster, 5L);
+
+        //Remove Servers
+        bytes = client.reconfig()
+                .withMembers("server.2=" + server2,
+                        "server.3=" + server3,
+                        "server.4=" + server4,
+                        "server.5=" + server5)
+                .storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
+        qv = getQuorumVerifier(bytes);
+        Assert.assertEquals(qv.getAllMembers().size(), 4);
+
+        waitOnDelegateListener.waitForEvent();
+        Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString2to5);
+
+        bytes = client.reconfig()
+                .withMembers("server.3=" + server3,
+                        "server.4=" + server4,
+                        "server.5=" + server5)
+                .storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
+
+        qv = getQuorumVerifier(bytes);
+        Assert.assertEquals(qv.getAllMembers().size(), 3);
+
+        waitOnDelegateListener.waitForEvent();
+        Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString3to5);
+
+        //Add Servers
+        bytes = client.reconfig()
+                .withMembers("server.2=" + server2,
+                        "server.3=" + server3,
+                        "server.4=" + server4,
+                        "server.5=" + server5)
+                .storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
+        qv = getQuorumVerifier(bytes);
+        Assert.assertEquals(qv.getAllMembers().size(), 4);
+
+        waitOnDelegateListener.waitForEvent();
+        Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString2to5);
+
+        bytes = client.reconfig()
+                .withMembers("server.1=" + server1,
+                        "server.2=" + server2,
+                        "server.3=" + server3,
+                        "server.4=" + server4,
+                        "server.5=" + server5)
+                .storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
+        qv = getQuorumVerifier(bytes);
+        Assert.assertEquals(qv.getAllMembers().size(), 5);
+
+        waitOnDelegateListener.waitForEvent();
+        Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString1to5);
     }
 
     @Test
     public void testAsyncNonIncremental() throws Exception {
-        CuratorFramework client = CuratorFrameworkFactory.newClient(cluster.getConnectString(), new RetryOneTime(1));
-        client.start();
-        client.blockUntilConnected();
-        try {
-            final AtomicReference<byte[]> bytes = new AtomicReference<byte[]>();
-            final BackgroundCallback callback = new BackgroundCallback() {
-                @Override
-                public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
-                    bytes.set(event.getData());
-                    ((CountDownLatch)event.getContext()).countDown();
-                }
+        final AtomicReference<byte[]> bytes = new AtomicReference<byte[]>();
+        final BackgroundCallback callback = new BackgroundCallback() {
+            @Override
+            public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
+                bytes.set(event.getData());
+                ((CountDownLatch) event.getContext()).countDown();
+            }
 
-            };
-
-            CountDownLatch latch = new CountDownLatch(1);
-            client.getConfig().inBackground(callback, latch).forEnsemble();
-            latch.await(5, TimeUnit.SECONDS);
-            Assert.assertNotNull(bytes.get());
-            QuorumVerifier qv = getQuorumVerifier(bytes.get());
-            Assert.assertEquals(qv.getAllMembers().size(), 5);
-            String server1 = getServerString(qv, cluster, 1L);
-            String server2 = getServerString(qv, cluster, 2L);
-            String server3 = getServerString(qv, cluster, 3L);
-            String server4 = getServerString(qv, cluster, 4L);
-            String server5 = getServerString(qv, cluster, 5L);
-
-            //Remove Servers
-            latch = new CountDownLatch(1);
-            client.reconfig()
-                    .withMembers("server.2=" + server2,
-                            "server.3=" + server3,
-                            "server.4=" + server4,
-                            "server.5=" + server5)
-            .inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
-            latch.await(5, TimeUnit.SECONDS);
-            qv = getQuorumVerifier(bytes.get());
-            Assert.assertEquals(qv.getAllMembers().size(), 4);
-            latch = new CountDownLatch(1);
-            client.reconfig()
-                    .withMembers("server.3=" + server3,
-                            "server.4=" + server4,
-                            "server.5=" + server5)
-                    .inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
-            latch.await(5, TimeUnit.SECONDS);
-            qv = getQuorumVerifier(bytes.get());
-            Assert.assertEquals(qv.getAllMembers().size(), 3);
-
-            //Add Servers
-            latch = new CountDownLatch(1);
-            client.reconfig()
-                    .withMembers("server.1=" + server1,
-                            "server.3=" + server3,
-                            "server.4=" + server4,
-                            "server.5=" + server5)
-                    .inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
-            latch.await(5, TimeUnit.SECONDS);
-            qv = getQuorumVerifier(bytes.get());
-            Assert.assertEquals(qv.getAllMembers().size(), 4);
-            latch = new CountDownLatch(1);
-            client.reconfig()
-                    .withMembers("server.1=" + server1,
-                            "server.2=" + server2,
-                            "server.3=" + server3,
-                            "server.4=" + server4,
-                            "server.5=" + server5)
-                    .inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
-            latch.await(5, TimeUnit.SECONDS);
-            qv = getQuorumVerifier(bytes.get());
-            Assert.assertEquals(qv.getAllMembers().size(), 5);
-        } finally {
-            client.close();
-        }
+        };
+
+        CountDownLatch latch = new CountDownLatch(1);
+        client.getConfig().inBackground(callback, latch).forEnsemble();
+        latch.await(5, TimeUnit.SECONDS);
+        Assert.assertNotNull(bytes.get());
+        QuorumVerifier qv = getQuorumVerifier(bytes.get());
+        Assert.assertEquals(qv.getAllMembers().size(), 5);
+        String server1 = getServerString(qv, cluster, 1L);
+        String server2 = getServerString(qv, cluster, 2L);
+        String server3 = getServerString(qv, cluster, 3L);
+        String server4 = getServerString(qv, cluster, 4L);
+        String server5 = getServerString(qv, cluster, 5L);
+
+        //Remove Servers
+        client.reconfig()
+                .withMembers("server.2=" + server2,
+                        "server.3=" + server3,
+                        "server.4=" + server4,
+                        "server.5=" + server5)
+                .inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
+        waitOnDelegateListener.waitForEvent();
+        Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString2to5);
+        qv = getQuorumVerifier(bytes.get());
+        Assert.assertEquals(qv.getAllMembers().size(), 4);
+
+        client.reconfig()
+                .withMembers("server.3=" + server3,
+                        "server.4=" + server4,
+                        "server.5=" + server5)
+                .inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
+        waitOnDelegateListener.waitForEvent();
+        Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString3to5);
+        qv = getQuorumVerifier(bytes.get());
+        Assert.assertEquals(qv.getAllMembers().size(), 3);
+
+        //Add Servers
+        client.reconfig()
+                .withMembers("server.2=" + server2,
+                        "server.3=" + server3,
+                        "server.4=" + server4,
+                        "server.5=" + server5)
+                .inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
+        waitOnDelegateListener.waitForEvent();
+        Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString2to5);
+        qv = getQuorumVerifier(bytes.get());
+        Assert.assertEquals(qv.getAllMembers().size(), 4);
+
+        client.reconfig()
+                .withMembers("server.1=" + server1,
+                        "server.2=" + server2,
+                        "server.3=" + server3,
+                        "server.4=" + server4,
+                        "server.5=" + server5)
+                .inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
+        waitOnDelegateListener.waitForEvent();
+        Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString1to5);
+        qv = getQuorumVerifier(bytes.get());
+        Assert.assertEquals(qv.getAllMembers().size(), 5);
     }
 
 
@@ -302,4 +345,44 @@ public class TestReconfiguration {
             return str + ";" + getInstance(cluster, (int) id).getConnectString();
         }
     }
+
+    static String getConnectionString(TestingCluster cluster, long... ids) throws Exception {
+        StringBuilder sb = new StringBuilder();
+        Map<Long, InstanceSpec> specs = new HashMap<Long, InstanceSpec>();
+        for (InstanceSpec spec : cluster.getInstances()) {
+            specs.put(new Long(spec.getServerId()), spec);
+        }
+        for (long id : ids) {
+            if (sb.length() != 0) {
+                sb.append(",");
+            }
+            sb.append(specs.get(id).getConnectString());
+        }
+        return sb.toString();
+    }
+
+    //Simple EnsembleListener that can wait until the delegate handles the event.
+    private static class WaitOnDelegateListener implements EnsembleListener {
+        private CountDownLatch latch = new CountDownLatch(1);
+
+        private final EnsembleListener delegate;
+
+        private WaitOnDelegateListener(EnsembleListener delegate) {
+            this.delegate = delegate;
+        }
+
+        @Override
+        public void connectionStringUpdated(String connectionString) {
+            delegate.connectionStringUpdated(connectionString);
+            latch.countDown();
+        }
+
+        public void waitForEvent() throws InterruptedException, TimeoutException {
+            if (latch.await(5, TimeUnit.SECONDS)) {
+                latch = new CountDownLatch(1);
+            } else {
+                throw new TimeoutException("Failed to receive event in time.");
+            }
+        }
+    };
 }
\ No newline at end of file


[06/27] curator git commit: [CURATOR-160] Made Configurable optional. Fix storingStatIn in GetConfigBuilderImpl.

Posted by dr...@apache.org.
[CURATOR-160] Made Configurable optional. Fix storingStatIn in GetConfigBuilderImpl.


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

Branch: refs/heads/CURATOR-215
Commit: dbdcf2f1cd2eae8d91d78619dd039c154b4aa52a
Parents: 4ec5ffe
Author: Ioannis Canellos <io...@gmail.com>
Authored: Fri Apr 17 12:57:28 2015 +0300
Committer: Scott Blum <dr...@apache.org>
Committed: Wed Aug 12 17:08:33 2015 -0400

----------------------------------------------------------------------
 .../api/BackgroundStatConfigEnsembleable.java   | 24 ++++++++++
 .../api/BackgroundStatConfigurable.java         | 24 ----------
 .../api/BackgroundStatEnsembleable.java         | 24 ++++++++++
 .../curator/framework/api/Configurable.java     |  2 +-
 .../JoinBackgroundStatConfigEnsembleable.java   | 30 ++++++++++++
 .../api/JoinBackgroundStatConfigurable.java     | 30 ------------
 .../LeaveBackgroundStatConfigEnsembleable.java  | 30 ++++++++++++
 .../api/LeaveBackgroundStatConfigurable.java    | 30 ------------
 .../curator/framework/api/ReconfigBuilder.java  |  6 +--
 .../framework/imps/GetConfigBuilderImpl.java    |  2 +-
 .../framework/imps/ReconfigBuilderImpl.java     | 48 ++++++++++----------
 .../framework/imps/TestReconfiguration.java     | 32 ++++++-------
 12 files changed, 153 insertions(+), 129 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/dbdcf2f1/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundStatConfigEnsembleable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundStatConfigEnsembleable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundStatConfigEnsembleable.java
new file mode 100644
index 0000000..f109b0f
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundStatConfigEnsembleable.java
@@ -0,0 +1,24 @@
+/**
+ * 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.curator.framework.api;
+
+public interface BackgroundStatConfigEnsembleable<T> extends
+        Configurable<BackgroundStatEnsembleable<T>>,
+        BackgroundStatEnsembleable<T> {
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/dbdcf2f1/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundStatConfigurable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundStatConfigurable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundStatConfigurable.java
deleted file mode 100644
index e46ba89..0000000
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundStatConfigurable.java
+++ /dev/null
@@ -1,24 +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.curator.framework.api;
-
-public interface BackgroundStatConfigurable<T> extends
-    BackgroundStatable<Configurable<T>>,
-    Configurable<T> {
-}

http://git-wip-us.apache.org/repos/asf/curator/blob/dbdcf2f1/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundStatEnsembleable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundStatEnsembleable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundStatEnsembleable.java
new file mode 100644
index 0000000..62f666d
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/BackgroundStatEnsembleable.java
@@ -0,0 +1,24 @@
+/**
+ * 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.curator.framework.api;
+
+public interface BackgroundStatEnsembleable<T> extends
+    BackgroundStatable<Ensembleable<T>>,
+    Ensembleable<T> {
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/dbdcf2f1/curator-framework/src/main/java/org/apache/curator/framework/api/Configurable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/Configurable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/Configurable.java
index a47f9d0..39e2c0c 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/Configurable.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/Configurable.java
@@ -25,5 +25,5 @@ public interface Configurable<T> {
      * @param config The version of the configuration.
      * @throws Exception
      */
-    Ensembleable<T> fromConfig(long config) throws Exception;
+    BackgroundStatEnsembleable<byte[]> fromConfig(long config) throws Exception;
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/dbdcf2f1/curator-framework/src/main/java/org/apache/curator/framework/api/JoinBackgroundStatConfigEnsembleable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/JoinBackgroundStatConfigEnsembleable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/JoinBackgroundStatConfigEnsembleable.java
new file mode 100644
index 0000000..ba45efd
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/JoinBackgroundStatConfigEnsembleable.java
@@ -0,0 +1,30 @@
+/**
+ * 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.curator.framework.api;
+
+/**
+ * An incremental reconfiguration builder.
+ * This builder has access only to the incremental reconfiguration methods joining and leaving, so that we prevent
+ * mixing concepts that can't be used together.
+ */
+public interface JoinBackgroundStatConfigEnsembleable extends
+        Joinable<BackgroundStatConfigEnsembleable<byte[]>>,
+        BackgroundStatConfigEnsembleable<byte[]> {
+
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/dbdcf2f1/curator-framework/src/main/java/org/apache/curator/framework/api/JoinBackgroundStatConfigurable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/JoinBackgroundStatConfigurable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/JoinBackgroundStatConfigurable.java
deleted file mode 100644
index fb18c0c..0000000
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/JoinBackgroundStatConfigurable.java
+++ /dev/null
@@ -1,30 +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.curator.framework.api;
-
-/**
- * An incremental reconfiguration builder.
- * This builder has access only to the incremental reconfiguration methods joining and leaving, so that we prevent
- * mixing concepts that can't be used together.
- */
-public interface JoinBackgroundStatConfigurable extends
-        Joinable<BackgroundStatConfigurable<byte[]>>,
-        BackgroundStatConfigurable<byte[]> {
-
-}

http://git-wip-us.apache.org/repos/asf/curator/blob/dbdcf2f1/curator-framework/src/main/java/org/apache/curator/framework/api/LeaveBackgroundStatConfigEnsembleable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/LeaveBackgroundStatConfigEnsembleable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/LeaveBackgroundStatConfigEnsembleable.java
new file mode 100644
index 0000000..a6316c1
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/LeaveBackgroundStatConfigEnsembleable.java
@@ -0,0 +1,30 @@
+/**
+ * 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.curator.framework.api;
+
+/**
+ * An non-incremental reconfiguration builder.
+ * This builder has access only to the non-incremental reconfiguration methods withMembers, so that we prevent
+ * mixing concepts that can't be used together.
+ */
+public interface LeaveBackgroundStatConfigEnsembleable extends
+        Leaveable<BackgroundStatConfigEnsembleable<byte[]>>,
+        BackgroundStatConfigEnsembleable<byte[]> {
+
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/dbdcf2f1/curator-framework/src/main/java/org/apache/curator/framework/api/LeaveBackgroundStatConfigurable.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/LeaveBackgroundStatConfigurable.java b/curator-framework/src/main/java/org/apache/curator/framework/api/LeaveBackgroundStatConfigurable.java
deleted file mode 100644
index 196ffca..0000000
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/LeaveBackgroundStatConfigurable.java
+++ /dev/null
@@ -1,30 +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.curator.framework.api;
-
-/**
- * An non-incremental reconfiguration builder.
- * This builder has access only to the non-incremental reconfiguration methods withMembers, so that we prevent
- * mixing concepts that can't be used together.
- */
-public interface LeaveBackgroundStatConfigurable extends
-        Leaveable<BackgroundStatConfigurable<byte[]>>,
-        BackgroundStatConfigurable<byte[]> {
-
-}

http://git-wip-us.apache.org/repos/asf/curator/blob/dbdcf2f1/curator-framework/src/main/java/org/apache/curator/framework/api/ReconfigBuilder.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/ReconfigBuilder.java b/curator-framework/src/main/java/org/apache/curator/framework/api/ReconfigBuilder.java
index 96ebdf7..f05b99e 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/ReconfigBuilder.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/ReconfigBuilder.java
@@ -19,8 +19,8 @@
 package org.apache.curator.framework.api;
 
 public interface ReconfigBuilder extends
-        Joinable<LeaveBackgroundStatConfigurable>,
-        Leaveable<JoinBackgroundStatConfigurable>,
-        Memberable<BackgroundStatConfigurable<byte[]>> {
+        Joinable<LeaveBackgroundStatConfigEnsembleable>,
+        Leaveable<JoinBackgroundStatConfigEnsembleable>,
+        Memberable<BackgroundStatConfigEnsembleable<byte[]>> {
 
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/dbdcf2f1/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
index 59a621a..d331a0a 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
@@ -50,7 +50,7 @@ public class GetConfigBuilderImpl implements GetConfigBuilder, BackgroundOperati
 
     @Override
     public Ensembleable<byte[]> storingStatIn(Stat stat) {
-        this.stat = new Stat();
+        this.stat = stat;
         return this;
     }
 

http://git-wip-us.apache.org/repos/asf/curator/blob/dbdcf2f1/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java
index 7a33297..5489691 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java
@@ -21,13 +21,13 @@ package org.apache.curator.framework.imps;
 import org.apache.curator.RetryLoop;
 import org.apache.curator.TimeTrace;
 import org.apache.curator.framework.api.BackgroundCallback;
-import org.apache.curator.framework.api.BackgroundStatConfigurable;
-import org.apache.curator.framework.api.Configurable;
+import org.apache.curator.framework.api.BackgroundStatConfigEnsembleable;
+import org.apache.curator.framework.api.BackgroundStatEnsembleable;
 import org.apache.curator.framework.api.CuratorEvent;
 import org.apache.curator.framework.api.CuratorEventType;
 import org.apache.curator.framework.api.Ensembleable;
-import org.apache.curator.framework.api.JoinBackgroundStatConfigurable;
-import org.apache.curator.framework.api.LeaveBackgroundStatConfigurable;
+import org.apache.curator.framework.api.JoinBackgroundStatConfigEnsembleable;
+import org.apache.curator.framework.api.LeaveBackgroundStatConfigEnsembleable;
 import org.apache.curator.framework.api.ReconfigBuilder;
 import org.apache.zookeeper.AsyncCallback;
 import org.apache.zookeeper.data.Stat;
@@ -46,7 +46,7 @@ public class ReconfigBuilderImpl implements ReconfigBuilder {
         this.client = client;
     }
 
-    private static class ReconfigBuilderBase implements BackgroundStatConfigurable<byte[]>, Ensembleable<byte[]>, BackgroundOperation<EnsembleServersAndConfig> {
+    private static class ReconfigBuilderBase implements BackgroundStatConfigEnsembleable<byte[]>, Ensembleable<byte[]>, BackgroundOperation<EnsembleServersAndConfig> {
 
         final CuratorFrameworkImpl client;
         final List<String> joiningServers = new LinkedList<String>();
@@ -62,49 +62,49 @@ public class ReconfigBuilderImpl implements ReconfigBuilder {
         }
 
         @Override
-        public Configurable<byte[]> inBackground() {
+        public Ensembleable<byte[]> inBackground() {
             backgrounding = new Backgrounding();
             return this;
         }
 
         @Override
-        public Configurable<byte[]> inBackground(Object context) {
+        public Ensembleable<byte[]> inBackground(Object context) {
             backgrounding = new Backgrounding(context);
             return this;
         }
 
         @Override
-        public Configurable<byte[]> inBackground(BackgroundCallback callback) {
+        public Ensembleable<byte[]> inBackground(BackgroundCallback callback) {
             backgrounding = new Backgrounding(callback);
             return this;
         }
 
         @Override
-        public Configurable<byte[]> inBackground(BackgroundCallback callback, Object context) {
+        public Ensembleable<byte[]> inBackground(BackgroundCallback callback, Object context) {
             backgrounding = new Backgrounding(callback, context);
             return this;
         }
 
         @Override
-        public Configurable<byte[]> inBackground(BackgroundCallback callback, Executor executor) {
+        public Ensembleable<byte[]> inBackground(BackgroundCallback callback, Executor executor) {
             backgrounding = new Backgrounding(callback, executor);
             return this;
         }
 
         @Override
-        public Configurable<byte[]> inBackground(BackgroundCallback callback, Object context, Executor executor) {
+        public Ensembleable<byte[]> inBackground(BackgroundCallback callback, Object context, Executor executor) {
             backgrounding = new Backgrounding(client, callback, context, executor);
             return this;
         }
 
         @Override
-        public Ensembleable<byte[]> fromConfig(long config) throws Exception {
+        public BackgroundStatEnsembleable<byte[]> fromConfig(long config) throws Exception {
             this.config = config;
             return this;
         }
 
         @Override
-        public Configurable<byte[]> storingStatIn(Stat stat) {
+        public Ensembleable<byte[]> storingStatIn(Stat stat) {
             this.stat = stat;
             return this;
         }
@@ -166,27 +166,27 @@ public class ReconfigBuilderImpl implements ReconfigBuilder {
         }
     }
 
-    private static class JoinReconfigBuilder extends ReconfigBuilderBase implements JoinBackgroundStatConfigurable {
+    private static class JoinReconfigBuilderConfig extends ReconfigBuilderBase implements JoinBackgroundStatConfigEnsembleable {
 
-        private JoinReconfigBuilder(CuratorFrameworkImpl client) {
+        private JoinReconfigBuilderConfig(CuratorFrameworkImpl client) {
             super(client);
         }
 
         @Override
-        public BackgroundStatConfigurable<byte[]> joining(String... servers) {
+        public BackgroundStatConfigEnsembleable<byte[]> joining(String... servers) {
             joiningServers.addAll(Arrays.asList(servers));
             return this;
         }
     }
 
-    private static class LeaveReconfigBuilder extends ReconfigBuilderBase implements LeaveBackgroundStatConfigurable {
+    private static class LeaveReconfigBuilderConfig extends ReconfigBuilderBase implements LeaveBackgroundStatConfigEnsembleable {
 
-        private LeaveReconfigBuilder(CuratorFrameworkImpl client) {
+        private LeaveReconfigBuilderConfig(CuratorFrameworkImpl client) {
             super(client);
         }
 
         @Override
-        public BackgroundStatConfigurable<byte[]> leaving(String... servers) {
+        public BackgroundStatConfigEnsembleable<byte[]> leaving(String... servers) {
             leavingServers.addAll(Arrays.asList(servers));
             return this;
         }
@@ -194,21 +194,21 @@ public class ReconfigBuilderImpl implements ReconfigBuilder {
 
 
     @Override
-    public LeaveBackgroundStatConfigurable joining(String... servers) {
-        LeaveReconfigBuilder builder = new LeaveReconfigBuilder(client);
+    public LeaveBackgroundStatConfigEnsembleable joining(String... servers) {
+        LeaveReconfigBuilderConfig builder = new LeaveReconfigBuilderConfig(client);
         builder.joiningServers.addAll(Arrays.asList(servers));
         return builder;
     }
 
     @Override
-    public JoinBackgroundStatConfigurable leaving(String... servers) {
-        JoinReconfigBuilder builder = new JoinReconfigBuilder(client);
+    public JoinBackgroundStatConfigEnsembleable leaving(String... servers) {
+        JoinReconfigBuilderConfig builder = new JoinReconfigBuilderConfig(client);
         builder.leavingServers.addAll(Arrays.asList(servers));
         return builder;
     }
 
     @Override
-    public BackgroundStatConfigurable<byte[]> withMembers(String... servers) {
+    public BackgroundStatConfigEnsembleable<byte[]> withMembers(String... servers) {
         ReconfigBuilderBase builder = new ReconfigBuilderBase(client);
         builder.members.addAll(Arrays.asList(servers));
         return builder;

http://git-wip-us.apache.org/repos/asf/curator/blob/dbdcf2f1/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java
index faec551..44f9d00 100644
--- a/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java
@@ -101,14 +101,14 @@ public class TestReconfiguration {
         String server2 = getServerString(qv, cluster, 2L);
 
         //Remove Servers
-        bytes = client.reconfig().leaving("1").storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
+        bytes = client.reconfig().leaving("1").fromConfig(qv.getVersion()).storingStatIn(stat).forEnsemble();
         qv = getQuorumVerifier(bytes);
         Assert.assertEquals(qv.getAllMembers().size(), 4);
 
         waitOnDelegateListener.waitForEvent();
         Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString2to5);
 
-        bytes = client.reconfig().leaving("2").storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
+        bytes = client.reconfig().leaving("2").fromConfig(qv.getVersion()).storingStatIn(stat).forEnsemble();
         qv = getQuorumVerifier(bytes);
         Assert.assertEquals(qv.getAllMembers().size(), 3);
 
@@ -116,14 +116,14 @@ public class TestReconfiguration {
         Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString3to5);
 
         //Add Servers
-        bytes = client.reconfig().joining("server.2=" + server2).storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
+        bytes = client.reconfig().joining("server.2=" + server2).fromConfig(qv.getVersion()).storingStatIn(stat).forEnsemble();
         qv = getQuorumVerifier(bytes);
         Assert.assertEquals(qv.getAllMembers().size(), 4);
 
         waitOnDelegateListener.waitForEvent();
         Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString2to5);
 
-        bytes = client.reconfig().joining("server.1=" + server1).storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
+        bytes = client.reconfig().joining("server.1=" + server1).fromConfig(qv.getVersion()).storingStatIn(stat).forEnsemble();
         qv = getQuorumVerifier(bytes);
         Assert.assertEquals(qv.getAllMembers().size(), 5);
 
@@ -157,27 +157,27 @@ public class TestReconfiguration {
 
 
         //Remove Servers
-        client.reconfig().leaving("1").inBackground(callback).fromConfig(qv.getVersion()).forEnsemble();
+        client.reconfig().leaving("1").fromConfig(qv.getVersion()).inBackground(callback).forEnsemble();
         waitOnDelegateListener.waitForEvent();
         Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString2to5);
         qv = getQuorumVerifier(bytes.get());
         Assert.assertEquals(qv.getAllMembers().size(), 4);
 
-        client.reconfig().leaving("2").inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
+        client.reconfig().leaving("2").fromConfig(qv.getVersion()).inBackground(callback, latch).forEnsemble();
         waitOnDelegateListener.waitForEvent();
         Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString3to5);
         qv = getQuorumVerifier(bytes.get());
         Assert.assertEquals(qv.getAllMembers().size(), 3);
 
         //Add Servers
-        client.reconfig().joining("server.2=" + server2).inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
+        client.reconfig().joining("server.2=" + server2).fromConfig(qv.getVersion()).inBackground(callback, latch).forEnsemble();
         waitOnDelegateListener.waitForEvent();
         Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString2to5);
         qv = getQuorumVerifier(bytes.get());
         Assert.assertEquals(qv.getAllMembers().size(), 4);
 
 
-        client.reconfig().joining("server.1=" + server1).inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
+        client.reconfig().joining("server.1=" + server1).fromConfig(qv.getVersion()).inBackground(callback, latch).forEnsemble();
         waitOnDelegateListener.waitForEvent();
         Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString1to5);
         qv = getQuorumVerifier(bytes.get());
@@ -203,7 +203,7 @@ public class TestReconfiguration {
                         "server.3=" + server3,
                         "server.4=" + server4,
                         "server.5=" + server5)
-                .storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
+                .fromConfig(qv.getVersion()).storingStatIn(stat).forEnsemble();
         qv = getQuorumVerifier(bytes);
         Assert.assertEquals(qv.getAllMembers().size(), 4);
 
@@ -214,7 +214,7 @@ public class TestReconfiguration {
                 .withMembers("server.3=" + server3,
                         "server.4=" + server4,
                         "server.5=" + server5)
-                .storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
+                .fromConfig(qv.getVersion()).storingStatIn(stat).forEnsemble();
 
         qv = getQuorumVerifier(bytes);
         Assert.assertEquals(qv.getAllMembers().size(), 3);
@@ -228,7 +228,7 @@ public class TestReconfiguration {
                         "server.3=" + server3,
                         "server.4=" + server4,
                         "server.5=" + server5)
-                .storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
+                .fromConfig(qv.getVersion()).storingStatIn(stat).forEnsemble();
         qv = getQuorumVerifier(bytes);
         Assert.assertEquals(qv.getAllMembers().size(), 4);
 
@@ -241,7 +241,7 @@ public class TestReconfiguration {
                         "server.3=" + server3,
                         "server.4=" + server4,
                         "server.5=" + server5)
-                .storingStatIn(stat).fromConfig(qv.getVersion()).forEnsemble();
+                .fromConfig(qv.getVersion()).storingStatIn(stat).forEnsemble();
         qv = getQuorumVerifier(bytes);
         Assert.assertEquals(qv.getAllMembers().size(), 5);
 
@@ -279,7 +279,7 @@ public class TestReconfiguration {
                         "server.3=" + server3,
                         "server.4=" + server4,
                         "server.5=" + server5)
-                .inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
+                .fromConfig(qv.getVersion()).inBackground(callback, latch).forEnsemble();
         waitOnDelegateListener.waitForEvent();
         Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString2to5);
         qv = getQuorumVerifier(bytes.get());
@@ -289,7 +289,7 @@ public class TestReconfiguration {
                 .withMembers("server.3=" + server3,
                         "server.4=" + server4,
                         "server.5=" + server5)
-                .inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
+                .fromConfig(qv.getVersion()).inBackground(callback, latch).forEnsemble();
         waitOnDelegateListener.waitForEvent();
         Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString3to5);
         qv = getQuorumVerifier(bytes.get());
@@ -301,7 +301,7 @@ public class TestReconfiguration {
                         "server.3=" + server3,
                         "server.4=" + server4,
                         "server.5=" + server5)
-                .inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
+                .fromConfig(qv.getVersion()).inBackground(callback, latch).forEnsemble();
         waitOnDelegateListener.waitForEvent();
         Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString2to5);
         qv = getQuorumVerifier(bytes.get());
@@ -313,7 +313,7 @@ public class TestReconfiguration {
                         "server.3=" + server3,
                         "server.4=" + server4,
                         "server.5=" + server5)
-                .inBackground(callback, latch).fromConfig(qv.getVersion()).forEnsemble();
+                .fromConfig(qv.getVersion()).inBackground(callback, latch).forEnsemble();
         waitOnDelegateListener.waitForEvent();
         Assert.assertEquals(dynamicEnsembleProvider.getConnectionString(), connectionString1to5);
         qv = getQuorumVerifier(bytes.get());


[08/27] curator git commit: [CURATOR-160] Fix watcher support in GetConfigBuilderImpl.

Posted by dr...@apache.org.
[CURATOR-160] Fix watcher support in GetConfigBuilderImpl.


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/0e876c84
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/0e876c84
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/0e876c84

Branch: refs/heads/CURATOR-215
Commit: 0e876c842cb0cb357997b2e914d627bebc78130b
Parents: b00cecf
Author: Ioannis Canellos <io...@gmail.com>
Authored: Tue Nov 11 12:28:10 2014 +0200
Committer: Scott Blum <dr...@apache.org>
Committed: Wed Aug 12 17:08:33 2015 -0400

----------------------------------------------------------------------
 .../org/apache/curator/framework/imps/GetConfigBuilderImpl.java  | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/0e876c84/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
index 54b1862..59a621a 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
@@ -158,11 +158,11 @@ public class GetConfigBuilderImpl implements GetConfigBuilder, BackgroundOperati
         };
         if ( watching.isWatched() )
         {
-            client.getZooKeeper().getConfig(watching.getWatcher(), callback, backgrounding.getContext());
+            client.getZooKeeper().getConfig(false, callback, backgrounding.getContext());
         }
         else
         {
-            client.getZooKeeper().getConfig(false, callback, backgrounding.getContext());
+            client.getZooKeeper().getConfig(watching.getWatcher(), callback, backgrounding.getContext());
         }
     }
 


[15/27] curator git commit: fixed inBackground() calls

Posted by dr...@apache.org.
fixed inBackground() calls


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/0d6d82a4
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/0d6d82a4
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/0d6d82a4

Branch: refs/heads/CURATOR-215
Commit: 0d6d82a4d47d7ac56118fbf19d51b5db2e67232e
Parents: d9c394e
Author: randgalt <ra...@apache.org>
Authored: Sat May 9 12:40:08 2015 -0500
Committer: Scott Blum <dr...@apache.org>
Committed: Wed Aug 12 17:28:42 2015 -0400

----------------------------------------------------------------------
 .../org/apache/curator/framework/imps/GetConfigBuilderImpl.java    | 2 +-
 .../org/apache/curator/framework/imps/ReconfigBuilderImpl.java     | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/0d6d82a4/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
index b65f863..c9bbbf6 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
@@ -80,7 +80,7 @@ public class GetConfigBuilderImpl implements GetConfigBuilder, BackgroundOperati
     @Override
     public Ensembleable<byte[]> inBackground()
     {
-        backgrounding = new Backgrounding();
+        backgrounding = new Backgrounding(true);
         return this;
     }
 

http://git-wip-us.apache.org/repos/asf/curator/blob/0d6d82a4/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java
index 761c8ad..f4dba90 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java
@@ -203,7 +203,7 @@ public class ReconfigBuilderImpl implements
     @Override
     public ReconfigBuilderMain inBackground()
     {
-        backgrounding = new Backgrounding();
+        backgrounding = new Backgrounding(true);
         return this;
     }
 


[21/27] curator git commit: added doc

Posted by dr...@apache.org.
added doc


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

Branch: refs/heads/CURATOR-215
Commit: eacb0ba1e392267648c004f81455573bbc586a87
Parents: 7df5ab3
Author: randgalt <ra...@apache.org>
Authored: Sat May 9 15:01:20 2015 -0500
Committer: Scott Blum <dr...@apache.org>
Committed: Wed Aug 12 17:29:42 2015 -0400

----------------------------------------------------------------------
 .../CuratorMultiTransactionMain.java            | 17 +++++++++++++
 .../framework/api/transaction/CuratorOp.java    |  3 +++
 .../api/transaction/CuratorTransaction.java     |  2 +-
 .../api/transaction/TransactionOp.java          | 26 ++++++++++++++++++++
 4 files changed, 47 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/eacb0ba1/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorMultiTransactionMain.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorMultiTransactionMain.java b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorMultiTransactionMain.java
index 6b4910d..77dae61 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorMultiTransactionMain.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorMultiTransactionMain.java
@@ -18,11 +18,28 @@
  */
 package org.apache.curator.framework.api.transaction;
 
+import org.apache.curator.framework.CuratorFramework;
 import java.util.List;
 
 public interface CuratorMultiTransactionMain
 {
+    /**
+     * Commit the given operations as a single transaction. Create the
+     * operation instances via {@link CuratorFramework#transactionOp()}
+     *
+     * @param operations operations that make up the transaction.
+     * @return result details
+     * @throws Exception errors
+     */
     List<CuratorTransactionResult> forOperations(CuratorOp... operations) throws Exception;
 
+    /**
+     * Commit the given operations as a single transaction. Create the
+     * operation instances via {@link CuratorFramework#transactionOp()}
+     *
+     * @param operations operations that make up the transaction.
+     * @return result details
+     * @throws Exception errors
+     */
     List<CuratorTransactionResult> forOperations(List<CuratorOp> operations) throws Exception;
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/eacb0ba1/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorOp.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorOp.java b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorOp.java
index 533226b..23bc76c 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorOp.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorOp.java
@@ -20,6 +20,9 @@ package org.apache.curator.framework.api.transaction;
 
 import org.apache.zookeeper.Op;
 
+/**
+ * Internal representation of a transaction operation
+ */
 public interface CuratorOp
 {
     Op get();

http://git-wip-us.apache.org/repos/asf/curator/blob/eacb0ba1/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorTransaction.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorTransaction.java b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorTransaction.java
index 4f2fb02..5d60b5c 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorTransaction.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/CuratorTransaction.java
@@ -78,7 +78,7 @@ public interface CuratorTransaction
 
     /**
      * Start a check builder in the transaction
-     *ChildData
+     *
      * @return builder object
      */
     public TransactionCheckBuilder<CuratorTransactionBridge> check();

http://git-wip-us.apache.org/repos/asf/curator/blob/eacb0ba1/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionOp.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionOp.java b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionOp.java
index 742ac1f..84808a1 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionOp.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/transaction/TransactionOp.java
@@ -18,13 +18,39 @@
  */
 package org.apache.curator.framework.api.transaction;
 
+import org.apache.curator.framework.CuratorFramework;
+
+/**
+ * Builds operations that can be committed as a transaction
+ * via {@link CuratorFramework#transaction()}
+ */
 public interface TransactionOp
 {
+    /**
+     * Start a create builder in the transaction
+     *
+     * @return builder object
+     */
     TransactionCreateBuilder<CuratorOp> create();
 
+    /**
+     * Start a delete builder in the transaction
+     *
+     * @return builder object
+     */
     TransactionDeleteBuilder<CuratorOp> delete();
 
+    /**
+     * Start a setData builder in the transaction
+     *
+     * @return builder object
+     */
     TransactionSetDataBuilder<CuratorOp> setData();
 
+    /**
+     * Start a check builder in the transaction
+     *
+     * @return builder object
+     */
     TransactionCheckBuilder<CuratorOp> check();
 }


[13/27] curator git commit: Added doc for reconfig

Posted by dr...@apache.org.
Added doc for reconfig


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/2eec9eaf
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/2eec9eaf
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/2eec9eaf

Branch: refs/heads/CURATOR-215
Commit: 2eec9eafad5bdc92c893c1cac7cd853222bba847
Parents: d86f51f
Author: randgalt <ra...@apache.org>
Authored: Sat May 9 10:19:41 2015 -0500
Committer: Scott Blum <dr...@apache.org>
Committed: Wed Aug 12 17:28:42 2015 -0400

----------------------------------------------------------------------
 curator-framework/src/site/confluence/index.confluence | 4 ++++
 src/site/confluence/utilities.confluence               | 5 +++++
 2 files changed, 9 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/2eec9eaf/curator-framework/src/site/confluence/index.confluence
----------------------------------------------------------------------
diff --git a/curator-framework/src/site/confluence/index.confluence b/curator-framework/src/site/confluence/index.confluence
index 84f794f..cf92514 100644
--- a/curator-framework/src/site/confluence/index.confluence
+++ b/curator-framework/src/site/confluence/index.confluence
@@ -43,6 +43,10 @@ h3. Methods
 |setData()|Begins an operation to set a ZNode's data. Call additional methods (version or background) and finalize the operation by calling forPath()|
 |getChildren()|Begins an operation to get a ZNode's list of children ZNodes. Call additional methods (watch, background or get stat) and finalize the operation by calling forPath()|
 |inTransaction()|Begins an atomic ZooKeeper transaction. Combine create, setData, check, and/or delete operations and then commit() as a unit.|
+|getACL()|Begins an operation to return a ZNode's ACL settings. Call additional methods and finalize the operation by calling forPath()|
+|setACL()|Begins an operation to set a ZNode's ACL settings. Call additional methods and finalize the operation by calling forPath()|
+|getConfig()|Begins an operation to return the last committed configuration. Call additional methods and finalize the operation by calling forEnsemble()|
+|reconfig()|Begins an operation to change the configuration. Call additional methods and finalize the operation by calling forEnsemble()|
 
 h3. Notifications
 Notifications for background operations and watches are published via the ClientListener interface. You register listeners with the

http://git-wip-us.apache.org/repos/asf/curator/blob/2eec9eaf/src/site/confluence/utilities.confluence
----------------------------------------------------------------------
diff --git a/src/site/confluence/utilities.confluence b/src/site/confluence/utilities.confluence
index 7a8e95f..2ec5c6b 100644
--- a/src/site/confluence/utilities.confluence
+++ b/src/site/confluence/utilities.confluence
@@ -57,3 +57,8 @@ _ChildReaper_
 Utility to reap the empty child nodes in a parent node. Periodically calls getChildren() on the node and adds empty nodes to an internally managed Reaper.
 
 *NOTE:* You should consider using LeaderSelector to run the Reapers as they don't need to run in every client.
+
+h2. EnsembleTracker
+
+Utility to listen for ensemble/configuration changes via registered EnsembleListeners. Allocate a EnsembleTracker, add one or more listeners
+and start it.


[14/27] curator git commit: Some more refactoring, etc.

Posted by dr...@apache.org.
Some more refactoring, etc.


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/299a2022
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/299a2022
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/299a2022

Branch: refs/heads/CURATOR-215
Commit: 299a2022647e6982e674882053ed47ef4fd9b95b
Parents: 57dbf2e
Author: randgalt <ra...@apache.org>
Authored: Sat May 9 09:22:47 2015 -0500
Committer: Scott Blum <dr...@apache.org>
Committed: Wed Aug 12 17:28:42 2015 -0400

----------------------------------------------------------------------
 .../curator/framework/api/GetConfigBuilder.java |   8 +-
 .../framework/imps/GetConfigBuilderImpl.java    | 108 +++++++++----------
 .../framework/imps/ReconfigBuilderImpl.java     |   4 +-
 3 files changed, 61 insertions(+), 59 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/299a2022/curator-framework/src/main/java/org/apache/curator/framework/api/GetConfigBuilder.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/api/GetConfigBuilder.java b/curator-framework/src/main/java/org/apache/curator/framework/api/GetConfigBuilder.java
index c2fdf6c..c42e4cb 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/api/GetConfigBuilder.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/GetConfigBuilder.java
@@ -16,12 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
 package org.apache.curator.framework.api;
 
 public interface GetConfigBuilder extends
-        Watchable<BackgroundStatable<Ensembleable<byte[]>>>,
-        BackgroundStatable<Ensembleable<byte[]>>,
-        Ensembleable<byte[]> {
+    Watchable<BackgroundStatable<Ensembleable<byte[]>>>,
+    BackgroundStatable<Ensembleable<byte[]>>,
+    Ensembleable<byte[]>
+{
 }
 
 

http://git-wip-us.apache.org/repos/asf/curator/blob/299a2022/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
index d331a0a..b65f863 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
@@ -16,6 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
 package org.apache.curator.framework.imps;
 
 import org.apache.curator.RetryLoop;
@@ -30,122 +31,112 @@ import org.apache.curator.framework.api.GetConfigBuilder;
 import org.apache.zookeeper.AsyncCallback;
 import org.apache.zookeeper.Watcher;
 import org.apache.zookeeper.data.Stat;
-
 import java.util.concurrent.Callable;
 import java.util.concurrent.Executor;
 
-public class GetConfigBuilderImpl implements GetConfigBuilder, BackgroundOperation<Void> {
-
+public class GetConfigBuilderImpl implements GetConfigBuilder, BackgroundOperation<Void>
+{
     private final CuratorFrameworkImpl client;
 
     private Backgrounding backgrounding;
     private Watching watching;
     private Stat stat;
 
-    public GetConfigBuilderImpl(CuratorFrameworkImpl client) {
+    public GetConfigBuilderImpl(CuratorFrameworkImpl client)
+    {
         this.client = client;
         backgrounding = new Backgrounding();
         watching = new Watching();
     }
 
     @Override
-    public Ensembleable<byte[]> storingStatIn(Stat stat) {
+    public Ensembleable<byte[]> storingStatIn(Stat stat)
+    {
         this.stat = stat;
         return this;
     }
 
     @Override
-    public BackgroundStatable<Ensembleable<byte[]>> watched() {
+    public BackgroundStatable<Ensembleable<byte[]>> watched()
+    {
         watching = new Watching(true);
         return this;
     }
 
     @Override
-    public GetConfigBuilder usingWatcher(Watcher watcher) {
+    public GetConfigBuilder usingWatcher(Watcher watcher)
+    {
         watching = new Watching(client, watcher);
         return this;
     }
 
     @Override
-    public GetConfigBuilder usingWatcher(final CuratorWatcher watcher) {
+    public GetConfigBuilder usingWatcher(final CuratorWatcher watcher)
+    {
         watching = new Watching(client, watcher);
         return this;
     }
 
     @Override
-    public Ensembleable<byte[]> inBackground() {
+    public Ensembleable<byte[]> inBackground()
+    {
         backgrounding = new Backgrounding();
         return this;
     }
 
     @Override
-    public Ensembleable<byte[]> inBackground(Object context) {
+    public Ensembleable<byte[]> inBackground(Object context)
+    {
         backgrounding = new Backgrounding(context);
         return this;
     }
 
     @Override
-    public Ensembleable<byte[]> inBackground(BackgroundCallback callback) {
+    public Ensembleable<byte[]> inBackground(BackgroundCallback callback)
+    {
         backgrounding = new Backgrounding(callback);
         return this;
     }
 
     @Override
-    public Ensembleable<byte[]> inBackground(BackgroundCallback callback, Object context) {
+    public Ensembleable<byte[]> inBackground(BackgroundCallback callback, Object context)
+    {
         backgrounding = new Backgrounding(callback, context);
         return this;
     }
 
     @Override
-    public Ensembleable<byte[]> inBackground(BackgroundCallback callback, Executor executor) {
+    public Ensembleable<byte[]> inBackground(BackgroundCallback callback, Executor executor)
+    {
         backgrounding = new Backgrounding(callback, executor);
         return this;
     }
 
     @Override
-    public Ensembleable<byte[]> inBackground(BackgroundCallback callback, Object context, Executor executor) {
+    public Ensembleable<byte[]> inBackground(BackgroundCallback callback, Object context, Executor executor)
+    {
         backgrounding = new Backgrounding(client, callback, context, executor);
         return this;
     }
 
-    private void performBackgroundOperation() {
-        try {
-            client.getZooKeeper().getConfig(watching.getWatcher(),
-                    new AsyncCallback.DataCallback() {
-                        @Override
-                        public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat) {
-                            try {
-                                CuratorEvent event = new CuratorEventImpl(client, CuratorEventType.GET_CONFIG,
-                                        rc, path, null, ctx, stat, data, null, null, null);
-                                backgrounding.getCallback().processResult(client, event);
-                            } catch (Exception e) {
-                                throw new RuntimeException(e);
-                            }
-                        }
-                    }, backgrounding.getContext());
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
     @Override
-    public byte[] forEnsemble() throws Exception {
-        byte[] responseData = null;
+    public byte[] forEnsemble() throws Exception
+    {
         if ( backgrounding.inBackground() )
         {
             client.processBackgroundOperation(new OperationAndData<Void>(this, null, backgrounding.getCallback(), null, backgrounding.getContext()), null);
+            return null;
         }
         else
         {
-            responseData = configInForeground();
+            return configInForeground();
         }
-        return responseData;
     }
 
     @Override
     public void performBackgroundOperation(final OperationAndData<Void> operationAndData) throws Exception
     {
-        final TimeTrace   trace = client.getZookeeperClient().startTracer("GetDataBuilderImpl-Background");
+        final TimeTrace trace = client.getZookeeperClient().startTracer("GetDataBuilderImpl-Background");
         AsyncCallback.DataCallback callback = new AsyncCallback.DataCallback()
         {
             @Override
@@ -158,7 +149,7 @@ public class GetConfigBuilderImpl implements GetConfigBuilder, BackgroundOperati
         };
         if ( watching.isWatched() )
         {
-            client.getZooKeeper().getConfig(false, callback, backgrounding.getContext());
+            client.getZooKeeper().getConfig(true, callback, backgrounding.getContext());
         }
         else
         {
@@ -166,21 +157,30 @@ public class GetConfigBuilderImpl implements GetConfigBuilder, BackgroundOperati
         }
     }
 
-
-    private byte[] configInForeground() throws Exception {
-        TimeTrace   trace = client.getZookeeperClient().startTracer("GetConfigBuilderImpl-Foreground");
-        try {
+    private byte[] configInForeground() throws Exception
+    {
+        TimeTrace trace = client.getZookeeperClient().startTracer("GetConfigBuilderImpl-Foreground");
+        try
+        {
             return RetryLoop.callWithRetry
-                    (
-                            client.getZookeeperClient(),
-                            new Callable<byte[]>() {
-                                @Override
-                                public byte[] call() throws Exception {
-                                    return client.getZooKeeper().getConfig(watching.getWatcher(), stat);
-                                }
-                            }
-                    );
-        } finally {
+            (
+                client.getZookeeperClient(),
+                new Callable<byte[]>()
+                {
+                    @Override
+                    public byte[] call() throws Exception
+                    {
+                        if ( watching.isWatched() )
+                        {
+                            return client.getZooKeeper().getConfig(true, stat);
+                        }
+                        return client.getZooKeeper().getConfig(watching.getWatcher(), stat);
+                    }
+                }
+            );
+        }
+        finally
+        {
             trace.commit();
         }
     }

http://git-wip-us.apache.org/repos/asf/curator/blob/299a2022/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java
index 15ed13e..761c8ad 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java
@@ -41,7 +41,7 @@ public class ReconfigBuilderImpl implements
 {
     private final CuratorFrameworkImpl client;
 
-    private Backgrounding backgrounding;
+    private Backgrounding backgrounding = new Backgrounding();
     private Stat responseStat;
     private long fromConfig = -1;
     private List<String> adding;
@@ -56,7 +56,7 @@ public class ReconfigBuilderImpl implements
     @Override
     public byte[] forEnsemble() throws Exception
     {
-        if ( backgrounding != null )
+        if ( backgrounding.inBackground() )
         {
             client.processBackgroundOperation(new OperationAndData<>(this, null, backgrounding.getCallback(), null, backgrounding.getContext()), null);
             return new byte[0];


[22/27] curator git commit: Added doc for transactions

Posted by dr...@apache.org.
Added doc for transactions


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/7f27225b
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/7f27225b
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/7f27225b

Branch: refs/heads/CURATOR-215
Commit: 7f27225b3144a4d5b43ee50b4fd93f20d413a8a0
Parents: eacb0ba
Author: randgalt <ra...@apache.org>
Authored: Sat May 9 15:22:08 2015 -0500
Committer: Scott Blum <dr...@apache.org>
Committed: Wed Aug 12 17:29:42 2015 -0400

----------------------------------------------------------------------
 curator-framework/src/site/confluence/index.confluence | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/7f27225b/curator-framework/src/site/confluence/index.confluence
----------------------------------------------------------------------
diff --git a/curator-framework/src/site/confluence/index.confluence b/curator-framework/src/site/confluence/index.confluence
index c41b244..b79ece4 100644
--- a/curator-framework/src/site/confluence/index.confluence
+++ b/curator-framework/src/site/confluence/index.confluence
@@ -42,7 +42,8 @@ h3. Methods
 |getData()|Begins an operation to get a ZNode's data. Call additional methods (watch, background or get stat) and finalize the operation by calling forPath()|
 |setData()|Begins an operation to set a ZNode's data. Call additional methods (version or background) and finalize the operation by calling forPath()|
 |getChildren()|Begins an operation to get a ZNode's list of children ZNodes. Call additional methods (watch, background or get stat) and finalize the operation by calling forPath()|
-|inTransaction()|Begins an atomic ZooKeeper transaction. Combine create, setData, check, and/or delete operations and then commit() as a unit.|
+|transactionOp()|Used to allocate operations to be used with transaction().|
+|transaction()|Atomically submit a set of operations as a transaction.|
 |getACL()|Begins an operation to return a ZNode's ACL settings. Call additional methods and finalize the operation by calling forPath()|
 |setACL()|Begins an operation to set a ZNode's ACL settings. Call additional methods and finalize the operation by calling forPath()|
 |getConfig()|Begins an operation to return the last committed configuration. Call additional methods and finalize the operation by calling forEnsemble()|
@@ -69,6 +70,7 @@ CuratorEvent depend on the type of event which is exposed via the getType() meth
 |SYNC|getResultCode(), getStat()|
 |GET\_ACL|getResultCode(), getACLList()|
 |SET\_ACL|getResultCode()|
+|TRANSACTION|getResultCode(), getOpResults()|
 |WATCHED|getWatchedEvent()|
 |GET\_CONFIG|getResultCode(), getData()|
 |RECONFIG|getResultCode(), getData()|