curator-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From randg...@apache.org
Subject [12/25] curator git commit: [CURATOR-160] Add builders and dsl for ZooKeeper's config and reconfig methods.
Date Tue, 12 May 2015 13:54:13 GMT
[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/0e92b562
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/0e92b562
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/0e92b562

Branch: refs/heads/CURATOR-3.0
Commit: 0e92b562dfb3ac0ec6bfae82b5690473f5ca7594
Parents: e11ef78
Author: Ioannis Canellos <iocanel@gmail.com>
Authored: Thu Nov 6 17:34:47 2014 +0200
Committer: Ioannis Canellos <iocanel@gmail.com>
Committed: Fri Apr 17 13:00:30 2015 +0300

----------------------------------------------------------------------
 .../main/java/org/apache/curator/RetryLoop.java |   3 +-
 .../curator/framework/CuratorFramework.java     |  12 +
 .../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 |  27 ++
 .../api/JoinBackgroundStatConfigurable.java     |  30 ++
 .../apache/curator/framework/api/Joinable.java  |  31 ++
 .../api/LeaveBackgroundStatConfigurable.java    |  30 ++
 .../apache/curator/framework/api/Leaveable.java |  30 ++
 .../curator/framework/api/Memberable.java       |  31 ++
 .../curator/framework/api/ReconfigBuilder.java  |  26 ++
 .../framework/imps/CuratorFrameworkImpl.java    |  10 +
 .../imps/EnsembleServersAndConfig.java          |  52 ++++
 .../framework/imps/GetConfigBuilderImpl.java    | 187 ++++++++++++
 .../framework/imps/ReconfigBuilderImpl.java     | 216 +++++++++++++
 .../framework/imps/TestReconfiguration.java     | 305 +++++++++++++++++++
 .../org/apache/curator/test/InstanceSpec.java   |   4 +
 .../org/apache/curator/test/TestingCluster.java |   1 +
 21 files changed, 1105 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/0e92b562/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/0e92b562/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/0e92b562/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/0e92b562/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/0e92b562/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/0e92b562/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/0e92b562/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/0e92b562/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..c2fdf6c
--- /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<BackgroundStatable<Ensembleable<byte[]>>>,
+        BackgroundStatable<Ensembleable<byte[]>>,
+        Ensembleable<byte[]> {
+}
+
+

http://git-wip-us.apache.org/repos/asf/curator/blob/0e92b562/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/0e92b562/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..dde5b1c
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/Joinable.java
@@ -0,0 +1,31 @@
+/**
+ * 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 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.
+     */
+    T joining(String... server);
+
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/0e92b562/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/0e92b562/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..a3c3358
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/Leaveable.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 Leaveable<T> {
+
+    /**
+     * Sets one or more servers to leaving the ensemble.
+     * @param server The server ids.
+     * @return this
+     */
+    T leaving(String... server);
+
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/0e92b562/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..6ef54c1
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/api/Memberable.java
@@ -0,0 +1,31 @@
+/**
+ * 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/0e92b562/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..96ebdf7
--- /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<LeaveBackgroundStatConfigurable>,
+        Leaveable<JoinBackgroundStatConfigurable>,
+        Memberable<BackgroundStatConfigurable<byte[]>> {
+
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/0e92b562/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/0e92b562/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/0e92b562/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..54b1862
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java
@@ -0,0 +1,187 @@
+/**
+ * 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.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;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executor;
+
+public class GetConfigBuilderImpl implements GetConfigBuilder, BackgroundOperation<Void> {
+
+    private final CuratorFrameworkImpl client;
+
+    private Backgrounding backgrounding;
+    private Watching watching;
+    private Stat stat;
+
+    public GetConfigBuilderImpl(CuratorFrameworkImpl client) {
+        this.client = client;
+        backgrounding = new Backgrounding();
+        watching = new Watching();
+    }
+
+    @Override
+    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 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 {
+            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;
+        if ( backgrounding.inBackground() )
+        {
+            client.processBackgroundOperation(new OperationAndData<Void>(this, null, backgrounding.getCallback(), null, backgrounding.getContext()), null);
+        }
+        else
+        {
+            responseData = configInForeground();
+        }
+        return responseData;
+    }
+
+    @Override
+    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());
+        }
+    }
+
+
+    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/0e92b562/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..7a33297
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/ReconfigBuilderImpl.java
@@ -0,0 +1,216 @@
+/**
+ * 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.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.zookeeper.AsyncCallback;
+import org.apache.zookeeper.data.Stat;
+
+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;
+
+    public ReconfigBuilderImpl(CuratorFrameworkImpl client) {
+        this.client = client;
+    }
+
+    private static class ReconfigBuilderBase implements BackgroundStatConfigurable<byte[]>, Ensembleable<byte[]>, BackgroundOperation<EnsembleServersAndConfig> {
+
+        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 Configurable<byte[]> inBackground() {
+            backgrounding = new Backgrounding();
+            return this;
+        }
+
+        @Override
+        public Configurable<byte[]> inBackground(Object context) {
+            backgrounding = new Backgrounding(context);
+            return this;
+        }
+
+        @Override
+        public Configurable<byte[]> inBackground(BackgroundCallback callback) {
+            backgrounding = new Backgrounding(callback);
+            return this;
+        }
+
+        @Override
+        public Configurable<byte[]> inBackground(BackgroundCallback callback, Object context) {
+            backgrounding = new Backgrounding(callback, context);
+            return this;
+        }
+
+        @Override
+        public Configurable<byte[]> inBackground(BackgroundCallback callback, Executor executor) {
+            backgrounding = new Backgrounding(callback, executor);
+            return this;
+        }
+
+        @Override
+        public Configurable<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 {
+            this.config = config;
+            return this;
+        }
+
+        @Override
+        public Configurable<byte[]> storingStatIn(Stat stat) {
+            this.stat = stat;
+            return this;
+        }
+
+        @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();
+            }
+        }
+
+        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 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()
+            );
+
+        }
+    }
+
+    private static class JoinReconfigBuilder extends ReconfigBuilderBase implements JoinBackgroundStatConfigurable {
+
+        private JoinReconfigBuilder(CuratorFrameworkImpl client) {
+            super(client);
+        }
+
+        @Override
+        public BackgroundStatConfigurable<byte[]> joining(String... servers) {
+            joiningServers.addAll(Arrays.asList(servers));
+            return this;
+        }
+    }
+
+    private static class LeaveReconfigBuilder extends ReconfigBuilderBase implements LeaveBackgroundStatConfigurable {
+
+        private LeaveReconfigBuilder(CuratorFrameworkImpl client) {
+            super(client);
+        }
+
+        @Override
+        public BackgroundStatConfigurable<byte[]> leaving(String... servers) {
+            leavingServers.addAll(Arrays.asList(servers));
+            return this;
+        }
+    }
+
+
+    @Override
+    public LeaveBackgroundStatConfigurable joining(String... servers) {
+        LeaveReconfigBuilder builder = new LeaveReconfigBuilder(client);
+        builder.joiningServers.addAll(Arrays.asList(servers));
+        return builder;
+    }
+
+    @Override
+    public JoinBackgroundStatConfigurable leaving(String... servers) {
+        JoinReconfigBuilder builder = new JoinReconfigBuilder(client);
+        builder.leavingServers.addAll(Arrays.asList(servers));
+        return builder;
+    }
+
+    @Override
+    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/0e92b562/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..e8896ae
--- /dev/null
+++ b/curator-framework/src/test/java/org/apache/curator/framework/imps/TestReconfiguration.java
@@ -0,0 +1,305 @@
+/**
+ * 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.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.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.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+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 {
+
+    TestingCluster cluster;
+
+    @BeforeMethod
+    public void setup() throws Exception {
+        cluster = new TestingCluster(5);
+        cluster.start();
+    }
+
+    @AfterMethod
+    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).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();
+        }
+    }
+
+    @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();
+                }
+
+            };
+
+            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();
+        }
+    }
+
+    @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();
+        }
+    }
+
+    @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();
+                }
+
+            };
+
+            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();
+        }
+    }
+
+
+    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

http://git-wip-us.apache.org/repos/asf/curator/blob/0e92b562/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/0e92b562/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 )
         {


Mime
View raw message