Repository: curator Updated Branches: refs/heads/217-merged [created] d5d12c88b
Merge 'CURATOR-217' 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/d5d12c88 Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/d5d12c88 Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/d5d12c88 Branch: refs/heads/217-merged Commit: d5d12c88b075fd1fc51a29412b3c08918cceb983 Parents: 44ee854 f0a09db Author: Scott Blum <[email protected]> Authored: Mon Aug 17 22:13:37 2015 -0400 Committer: Scott Blum <[email protected]> Committed: Mon Aug 17 22:13:37 2015 -0400 ---------------------------------------------------------------------- .../org/apache/curator/utils/DebugUtils.java | 1 + .../curator/framework/CuratorFramework.java | 19 + .../WatcherRemoveCuratorFramework.java | 30 + .../api/BackgroundPathableQuietly.java | 23 + .../api/BackgroundPathableQuietlyable.java | 5 + .../curator/framework/api/CuratorEventType.java | 5 + .../curator/framework/api/DeleteBuilder.java | 2 +- .../curator/framework/api/Guaranteeable.java | 20 +- .../framework/api/GuaranteeableDeletable.java | 39 ++ .../apache/curator/framework/api/Quietly.java | 24 + .../framework/api/RemoveWatchesBuilder.java | 47 ++ .../framework/api/RemoveWatchesLocal.java | 35 + .../framework/api/RemoveWatchesType.java | 37 ++ .../framework/imps/CuratorFrameworkImpl.java | 28 +- .../framework/imps/DeleteBuilderImpl.java | 4 +- .../framework/imps/ExistsBuilderImpl.java | 4 +- .../framework/imps/FailedDeleteManager.java | 39 +- .../framework/imps/FailedOperationManager.java | 68 ++ .../imps/FailedRemoveWatchManager.java | 56 ++ .../framework/imps/GetChildrenBuilderImpl.java | 4 +- .../framework/imps/GetConfigBuilderImpl.java | 5 +- .../framework/imps/GetDataBuilderImpl.java | 4 +- .../framework/imps/OperationAndData.java | 16 +- .../imps/RemoveWatchesBuilderImpl.java | 315 +++++++++ .../framework/imps/WatcherRemovalFacade.java | 176 +++++ .../framework/imps/WatcherRemovalManager.java | 137 ++++ .../apache/curator/framework/imps/Watching.java | 6 +- .../framework/imps/TestFailedDeleteManager.java | 9 +- .../framework/imps/TestRemoveWatches.java | 655 +++++++++++++++++++ .../imps/TestWatcherRemovalManager.java | 257 ++++++++ .../framework/recipes/cache/NodeCache.java | 6 +- .../recipes/cache/PathChildrenCache.java | 13 +- .../framework/recipes/cache/TreeCache.java | 6 +- .../framework/recipes/leader/LeaderLatch.java | 6 +- .../locks/InterProcessSemaphoreMutex.java | 6 +- .../recipes/locks/InterProcessSemaphoreV2.java | 60 +- .../framework/recipes/locks/LockInternals.java | 9 +- .../recipes/nodes/PersistentEphemeralNode.java | 7 +- .../framework/recipes/queue/ChildrenCache.java | 6 +- .../framework/recipes/shared/SharedValue.java | 8 +- .../curator/framework/imps/TestCleanState.java | 68 ++ .../recipes/cache/BaseTestTreeCache.java | 3 +- .../framework/recipes/cache/TestNodeCache.java | 9 +- .../recipes/cache/TestPathChildrenCache.java | 58 +- .../recipes/leader/TestLeaderLatch.java | 26 +- .../locks/TestInterProcessMultiMutex.java | 7 +- .../recipes/locks/TestInterProcessMutex.java | 5 +- .../locks/TestInterProcessMutexBase.java | 19 +- .../locks/TestInterProcessReadWriteLock.java | 223 ++++--- .../locks/TestInterProcessSemaphore.java | 27 +- .../locks/TestInterProcessSemaphoreCluster.java | 3 +- .../framework/recipes/locks/TestLockACLs.java | 3 +- .../locks/TestLockCleanlinessWithFaults.java | 3 +- .../nodes/TestPersistentEphemeralNode.java | 18 +- .../recipes/shared/TestSharedCount.java | 11 +- .../apache/curator/test/BaseClassForTests.java | 14 + .../org/apache/curator/test/WatchersDebug.java | 92 +++ 57 files changed, 2491 insertions(+), 295 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-client/src/main/java/org/apache/curator/utils/DebugUtils.java ---------------------------------------------------------------------- diff --cc curator-client/src/main/java/org/apache/curator/utils/DebugUtils.java index b098989,e84e06b..383bc13 --- a/curator-client/src/main/java/org/apache/curator/utils/DebugUtils.java +++ b/curator-client/src/main/java/org/apache/curator/utils/DebugUtils.java @@@ -23,7 -23,7 +23,8 @@@ public class DebugUtil public static final String PROPERTY_LOG_EVENTS = "curator-log-events"; public static final String PROPERTY_DONT_LOG_CONNECTION_ISSUES = "curator-dont-log-connection-problems"; public static final String PROPERTY_LOG_ONLY_FIRST_CONNECTION_ISSUE_AS_ERROR_LEVEL = "curator-log-only-first-connection-issue-as-error-level"; + public static final String PROPERTY_REMOVE_WATCHERS_IN_FOREGROUND = "curator-remove-watchers-in-foreground"; + public static final String PROPERTY_RETRY_FAILED_TESTS = "curator-retry-failed-tests"; private DebugUtils() { http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java ---------------------------------------------------------------------- diff --cc curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java index 9239ac4,7de6308..58c5bf5 --- a/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java +++ b/curator-framework/src/main/java/org/apache/curator/framework/CuratorFramework.java @@@ -1,281 -1,251 +1,300 @@@ -/** - * 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; - -import org.apache.curator.CuratorZookeeperClient; -import org.apache.curator.framework.api.*; -import org.apache.curator.framework.api.transaction.CuratorTransaction; -import org.apache.curator.framework.imps.CuratorFrameworkState; -import org.apache.curator.framework.listen.Listenable; -import org.apache.curator.framework.state.ConnectionStateListener; -import org.apache.curator.utils.EnsurePath; -import org.apache.zookeeper.Watcher; - -import java.io.Closeable; -import java.util.concurrent.TimeUnit; - -/** - * Zookeeper framework-style client - */ -public interface CuratorFramework extends Closeable -{ - /** - * Start the client. Most mutator methods will not work until the client is started - */ - public void start(); - - /** - * Stop the client - */ - public void close(); - - /** - * Returns the state of this instance - * - * @return state - */ - public CuratorFrameworkState getState(); - - /** - * Return true if the client is started, not closed, etc. - * - * @return true/false - * @deprecated use {@link #getState()} instead - */ - public boolean isStarted(); - - /** - * Start a create builder - * - * @return builder object - */ - public CreateBuilder create(); - - /** - * Start a delete builder - * - * @return builder object - */ - public DeleteBuilder delete(); - - /** - * Start an exists builder - * <p> - * The builder will return a Stat object as if org.apache.zookeeper.ZooKeeper.exists() were called. Thus, a null - * means that it does not exist and an actual Stat object means it does exist. - * - * @return builder object - */ - public ExistsBuilder checkExists(); - - /** - * Start a get data builder - * - * @return builder object - */ - public GetDataBuilder getData(); - - /** - * Start a set data builder - * - * @return builder object - */ - public SetDataBuilder setData(); - - /** - * Start a get children builder - * - * @return builder object - */ - public GetChildrenBuilder getChildren(); - - /** - * Start a get ACL builder - * - * @return builder object - */ - public GetACLBuilder getACL(); - - /** - * Start a set ACL builder - * - * @return builder object - */ - public SetACLBuilder setACL(); - - /** - * Start a transaction builder - * - * @return builder object - */ - public CuratorTransaction inTransaction(); - - /** - * Perform a sync on the given path - syncs are always in the background - * - * @param path the path - * @param backgroundContextObject optional context - * @deprecated use {@link #sync()} instead - */ - public void sync(String path, Object backgroundContextObject); - - /** - * Start a sync builder. Note: sync is ALWAYS in the background even - * if you don't use one of the background() methods - * - * @return builder object - */ - public SyncBuilder sync(); - - /** - * Start a remove watches builder. - * @return builder object - */ - public RemoveWatchesBuilder watches(); - - /** - * Returns the listenable interface for the Connect State - * - * @return listenable - */ - public Listenable<ConnectionStateListener> getConnectionStateListenable(); - - /** - * Returns the listenable interface for events - * - * @return listenable - */ - public Listenable<CuratorListener> getCuratorListenable(); - - /** - * Returns the listenable interface for unhandled errors - * - * @return listenable - */ - public Listenable<UnhandledErrorListener> getUnhandledErrorListenable(); - - /** - * Returns a facade of the current instance that does _not_ automatically - * pre-pend the namespace to all paths - * - * @return facade - * @deprecated use {@link #usingNamespace} passing <code>null</code> - */ - public CuratorFramework nonNamespaceView(); - - /** - * Returns a facade of the current instance that uses the specified namespace - * or no namespace if <code>newNamespace</code> is <code>null</code>. - * - * @param newNamespace the new namespace or null for none - * @return facade - */ - public CuratorFramework usingNamespace(String newNamespace); - - /** - * Return the current namespace or "" if none - * - * @return namespace - */ - public String getNamespace(); - - /** - * Return the managed zookeeper client - * - * @return client - */ - public CuratorZookeeperClient getZookeeperClient(); - - /** - * Allocates an ensure path instance that is namespace aware - * - * @param path path to ensure - * @return new EnsurePath instance - */ - public EnsurePath newNamespaceAwareEnsurePath(String path); - - /** - * Curator can hold internal references to watchers that may inhibit garbage collection. - * Call this method on watchers you are no longer interested in. - * - * @param watcher the watcher - * - * @deprecated As of ZooKeeper 3.5 Curators recipes will handle removing watcher references - * when they are no longer used. - */ - @Deprecated - public void clearWatcherReferences(Watcher watcher); - - /** - * Block until a connection to ZooKeeper is available or the maxWaitTime has been exceeded - * @param maxWaitTime The maximum wait time. Specify a value <= 0 to wait indefinitely - * @param units The time units for the maximum wait time. - * @return True if connection has been established, false otherwise. - * @throws InterruptedException If interrupted while waiting - */ - public boolean blockUntilConnected(int maxWaitTime, TimeUnit units) throws InterruptedException; - - /** - * Block until a connection to ZooKeeper is available. This method will not return until a - * connection is available or it is interrupted, in which case an InterruptedException will - * be thrown - * @throws InterruptedException If interrupted while waiting - */ - public void blockUntilConnected() throws InterruptedException; - - /** - * Returns a facade of the current instance that tracks - * watchers created and allows a one-shot removal of all watchers - * via {@link WatcherRemoveCuratorFramework#removeWatchers()} - * - * @return facade - */ - public WatcherRemoveCuratorFramework newWatcherRemoveCuratorFramework(); -} +/** + * 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; + +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; +import org.apache.curator.framework.listen.Listenable; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.EnsurePath; +import org.apache.zookeeper.Watcher; + +import java.io.Closeable; +import java.util.concurrent.TimeUnit; + +/** + * Zookeeper framework-style client + */ +public interface CuratorFramework extends Closeable +{ + /** + * Start the client. Most mutator methods will not work until the client is started + */ + public void start(); + + /** + * Stop the client + */ + public void close(); + + /** + * Returns the state of this instance + * + * @return state + */ + public CuratorFrameworkState getState(); + + /** + * Return true if the client is started, not closed, etc. + * + * @return true/false + * @deprecated use {@link #getState()} instead + */ + @Deprecated + public boolean isStarted(); + + /** + * Start a create builder + * + * @return builder object + */ + public CreateBuilder create(); + + /** + * Start a delete builder + * + * @return builder object + */ + public DeleteBuilder delete(); + + /** + * Start an exists builder + * <p> + * The builder will return a Stat object as if org.apache.zookeeper.ZooKeeper.exists() were called. Thus, a null + * means that it does not exist and an actual Stat object means it does exist. + * + * @return builder object + */ + public ExistsBuilder checkExists(); + + /** + * Start a get data builder + * + * @return builder object + */ + public GetDataBuilder getData(); + + /** + * Start a set data builder + * + * @return builder object + */ + public SetDataBuilder setData(); + + /** + * Start a get children builder + * + * @return builder object + */ + public GetChildrenBuilder getChildren(); + + /** + * Start a get ACL builder + * + * @return builder object + */ + public GetACLBuilder getACL(); + + /** + * Start a set ACL builder + * + * @return builder object + */ + public SetACLBuilder setACL(); + + /** + * Start a reconfig builder + * + * @return builder object + */ + public ReconfigBuilder reconfig(); + + /** + * Start a getConfig builder + * + * @return builder object + */ + public GetConfigBuilder getConfig(); + + /** + * Start a transaction builder + * + * @return builder object + * @deprecated use {@link #transaction()} instead + */ + public CuratorTransaction inTransaction(); + + /** + * Start a transaction builder + * + * @return builder object + */ + public CuratorMultiTransaction transaction(); + + /** + * Allocate an operation that can be used with {@link #transaction()}. + * NOTE: {@link CuratorOp} instances created by this builder are + * reusable. + * + * @return operation builder + */ + public TransactionOp transactionOp(); + + /** + * Perform a sync on the given path - syncs are always in the background + * + * @param path the path + * @param backgroundContextObject optional context + * @deprecated use {@link #sync()} instead + */ + @Deprecated + public void sync(String path, Object backgroundContextObject); + + /** + * Create all nodes in the specified path as containers if they don't + * already exist + * + * @param path path to create + * @throws Exception errors + */ + public void createContainers(String path) throws Exception; + + /** + * Start a sync builder. Note: sync is ALWAYS in the background even + * if you don't use one of the background() methods + * + * @return builder object + */ + public SyncBuilder sync(); + + /** ++ * Start a remove watches builder. ++ * @return builder object ++ */ ++ public RemoveWatchesBuilder watches(); ++ ++ /** + * Returns the listenable interface for the Connect State + * + * @return listenable + */ + public Listenable<ConnectionStateListener> getConnectionStateListenable(); + + /** + * Returns the listenable interface for events + * + * @return listenable + */ + public Listenable<CuratorListener> getCuratorListenable(); + + /** + * Returns the listenable interface for unhandled errors + * + * @return listenable + */ + public Listenable<UnhandledErrorListener> getUnhandledErrorListenable(); + + /** + * Returns a facade of the current instance that does _not_ automatically + * pre-pend the namespace to all paths + * + * @return facade + * @deprecated Since 2.9.0 - use {@link #usingNamespace} passing <code>null</code> + */ + @Deprecated + public CuratorFramework nonNamespaceView(); + + /** + * Returns a facade of the current instance that uses the specified namespace + * or no namespace if <code>newNamespace</code> is <code>null</code>. + * + * @param newNamespace the new namespace or null for none + * @return facade + */ + public CuratorFramework usingNamespace(String newNamespace); + + /** + * Return the current namespace or "" if none + * + * @return namespace + */ + public String getNamespace(); + + /** + * Return the managed zookeeper client + * + * @return client + */ + public CuratorZookeeperClient getZookeeperClient(); + + /** + * Allocates an ensure path instance that is namespace aware + * + * @param path path to ensure + * @return new EnsurePath instance + * @deprecated Since 2.9.0 - prefer {@link CreateBuilder#creatingParentContainersIfNeeded()}, {@link ExistsBuilder#creatingParentContainersIfNeeded()} + * or {@link CuratorFramework#createContainers(String)} + */ + @Deprecated + public EnsurePath newNamespaceAwareEnsurePath(String path); + + /** + * Curator can hold internal references to watchers that may inhibit garbage collection. + * Call this method on watchers you are no longer interested in. + * + * @param watcher the watcher ++ * ++ * @deprecated As of ZooKeeper 3.5 Curators recipes will handle removing watcher references ++ * when they are no longer used. + */ ++ @Deprecated + public void clearWatcherReferences(Watcher watcher); + + /** + * Block until a connection to ZooKeeper is available or the maxWaitTime has been exceeded + * @param maxWaitTime The maximum wait time. Specify a value <= 0 to wait indefinitely + * @param units The time units for the maximum wait time. + * @return True if connection has been established, false otherwise. + * @throws InterruptedException If interrupted while waiting + */ + public boolean blockUntilConnected(int maxWaitTime, TimeUnit units) throws InterruptedException; + + /** + * Block until a connection to ZooKeeper is available. This method will not return until a + * connection is available or it is interrupted, in which case an InterruptedException will + * be thrown + * @throws InterruptedException If interrupted while waiting + */ + public void blockUntilConnected() throws InterruptedException; ++ ++ /** ++ * Returns a facade of the current instance that tracks ++ * watchers created and allows a one-shot removal of all watchers ++ * via {@link WatcherRemoveCuratorFramework#removeWatchers()} ++ * ++ * @return facade ++ */ ++ public WatcherRemoveCuratorFramework newWatcherRemoveCuratorFramework(); +} http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-framework/src/main/java/org/apache/curator/framework/api/CuratorEventType.java ---------------------------------------------------------------------- diff --cc curator-framework/src/main/java/org/apache/curator/framework/api/CuratorEventType.java index 5a2dc56,480d5ec..5dea211 --- 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 @@@ -1,95 -1,85 +1,100 @@@ -/** - * 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.curator.framework.CuratorFramework; -import org.apache.zookeeper.Watcher; - -public enum CuratorEventType -{ - /** - * Corresponds to {@link CuratorFramework#create()} - */ - CREATE, - - /** - * Corresponds to {@link CuratorFramework#delete()} - */ - DELETE, - - /** - * Corresponds to {@link CuratorFramework#checkExists()} - */ - EXISTS, - - /** - * Corresponds to {@link CuratorFramework#getData()} - */ - GET_DATA, - - /** - * Corresponds to {@link CuratorFramework#setData()} - */ - SET_DATA, - - /** - * Corresponds to {@link CuratorFramework#getChildren()} - */ - CHILDREN, - - /** - * Corresponds to {@link CuratorFramework#sync(String, Object)} - */ - SYNC, - - /** - * Corresponds to {@link CuratorFramework#getACL()} - */ - GET_ACL, - - /** - * Corresponds to {@link CuratorFramework#setACL()} - */ - SET_ACL, - - /** - * Corresponds to {@link Watchable#usingWatcher(Watcher)} or {@link Watchable#watched()} - */ - WATCHED, - - /** - * Corresponds to {@link CuratorFramework#removeWatches()} - */ - REMOVE_WATCHES, - - /** - * Event sent when client is being closed - */ - CLOSING -} +/** + * 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.curator.framework.CuratorFramework; +import org.apache.zookeeper.Watcher; + +public enum CuratorEventType +{ + /** + * Corresponds to {@link CuratorFramework#create()} + */ + CREATE, + + /** + * Corresponds to {@link CuratorFramework#delete()} + */ + DELETE, + + /** + * Corresponds to {@link CuratorFramework#checkExists()} + */ + EXISTS, + + /** + * Corresponds to {@link CuratorFramework#getData()} + */ + GET_DATA, + + /** + * Corresponds to {@link CuratorFramework#setData()} + */ + SET_DATA, + + /** + * Corresponds to {@link CuratorFramework#getChildren()} + */ + CHILDREN, + + /** + * Corresponds to {@link CuratorFramework#sync(String, Object)} + */ + SYNC, + + /** + * Corresponds to {@link CuratorFramework#getACL()} + */ + GET_ACL, + + /** + * Corresponds to {@link CuratorFramework#setACL()} + */ + SET_ACL, + + /** + * Corresponds to {@link CuratorFramework#transaction()} + */ + TRANSACTION, + + /** + * Corresponds to {@link CuratorFramework#getConfig()} + */ + GET_CONFIG, + + /** + * Corresponds to {@link CuratorFramework#reconfig()} + */ + RECONFIG, + + /** + * Corresponds to {@link Watchable#usingWatcher(Watcher)} or {@link Watchable#watched()} + */ + WATCHED, + + /** ++ * Corresponds to {@link CuratorFramework#watches()} ()} ++ */ ++ REMOVE_WATCHES, ++ ++ /** + * Event sent when client is being closed + */ + CLOSING +} http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java ---------------------------------------------------------------------- diff --cc curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorFrameworkImpl.java index 900374b,b078768..41bb7cd --- 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 @@@ -27,13 -27,11 +27,14 @@@ import org.apache.curator.CuratorConnec import org.apache.curator.CuratorZookeeperClient; import org.apache.curator.RetryLoop; import org.apache.curator.TimeTrace; +import org.apache.curator.framework.AuthInfo; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFrameworkFactory; + import org.apache.curator.framework.WatcherRemoveCuratorFramework; 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; @@@ -73,9 -70,10 +74,10 @@@ public class CuratorFrameworkImpl imple private final BlockingQueue<OperationAndData<?>> backgroundOperations; private final NamespaceImpl namespace; private final ConnectionStateManager connectionStateManager; - private final AtomicReference<AuthInfo> authInfo = new AtomicReference<AuthInfo>(); + private final List<AuthInfo> authInfos; private final byte[] defaultData; private final FailedDeleteManager failedDeleteManager; + private final FailedRemoveWatchManager failedRemoveWatcherManager; private final CompressionProvider compressionProvider; private final ACLProvider aclProvider; private final NamespaceFacadeCache namespaceFacadeCache; @@@ -125,22 -142,23 +127,29 @@@ byte[] builderDefaultData = builder.getDefaultData(); defaultData = (builderDefaultData != null) ? Arrays.copyOf(builderDefaultData, builderDefaultData.length) : new byte[0]; - - if ( builder.getAuthScheme() != null ) - { - authInfo.set(new AuthInfo(builder.getAuthScheme(), builder.getAuthValue())); - } + authInfos = buildAuths(builder); failedDeleteManager = new FailedDeleteManager(this); + failedRemoveWatcherManager = new FailedRemoveWatchManager(this); namespaceFacadeCache = new NamespaceFacadeCache(this); } + private List<AuthInfo> buildAuths(CuratorFrameworkFactory.Builder builder) + { + ImmutableList.Builder<AuthInfo> builder1 = ImmutableList.builder(); + if ( builder.getAuthInfos() != null ) + { + builder1.addAll(builder.getAuthInfos()); + } + return builder1.build(); + } + + @Override + public WatcherRemoveCuratorFramework newWatcherRemoveCuratorFramework() + { + return new WatcherRemovalFacade(this); + } + private ZookeeperFactory makeZookeeperFactory(final ZookeeperFactory actualZookeeperFactory) { return new ZookeeperFactory() @@@ -478,7 -463,13 +488,13 @@@ { return new SyncBuilderImpl(this); } - + + @Override + public RemoveWatchesBuilder watches() + { + return new RemoveWatchesBuilderImpl(this); + } + protected void internalSync(CuratorFrameworkImpl impl, String path, Object context) { BackgroundOperation<String> operation = new BackgroundSyncImpl(impl, context); @@@ -506,7 -497,12 +522,12 @@@ { return failedDeleteManager; } - + + FailedRemoveWatchManager getFailedRemoveWatcherManager() + { + return failedRemoveWatcherManager; - } ++ } + RetryLoop newRetryLoop() { return client.newRetryLoop(); http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-framework/src/main/java/org/apache/curator/framework/imps/DeleteBuilderImpl.java ---------------------------------------------------------------------- diff --cc curator-framework/src/main/java/org/apache/curator/framework/imps/DeleteBuilderImpl.java index 51641b8,51691dd..2a98f56 --- 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 @@@ -259,9 -251,9 +259,9 @@@ class DeleteBuilderImpl implements Dele catch ( Exception e ) { //Only retry a guaranteed delete if it's a retryable error - if( RetryLoop.isRetryException(e) && guaranteed ) + if( (RetryLoop.isRetryException(e) || (e instanceof InterruptedException)) && guaranteed ) { - client.getFailedDeleteManager().addFailedDelete(unfixedPath); + client.getFailedDeleteManager().addFailedOperation(unfixedPath); } throw e; } http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-framework/src/main/java/org/apache/curator/framework/imps/ExistsBuilderImpl.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-framework/src/main/java/org/apache/curator/framework/imps/GetChildrenBuilderImpl.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java ---------------------------------------------------------------------- diff --cc curator-framework/src/main/java/org/apache/curator/framework/imps/GetConfigBuilderImpl.java index a837809,0000000..5468bd4 mode 100644,000000..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 @@@ -1,187 -1,0 +1,188 @@@ +/** + * 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.ZooDefs; +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 = 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(true); + 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; + } + + @Override + public byte[] forEnsemble() throws Exception + { + if ( backgrounding.inBackground() ) + { + client.processBackgroundOperation(new OperationAndData<Void>(this, null, backgrounding.getCallback(), null, backgrounding.getContext()), null); + return null; + } + else + { + return configInForeground(); + } + } + + @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, null); + client.processBackgroundOperation(operationAndData, event); + } + }; + if ( watching.isWatched() ) + { + client.getZooKeeper().getConfig(true, callback, backgrounding.getContext()); + } + else + { - client.getZooKeeper().getConfig(watching.getWatcher(), callback, backgrounding.getContext()); ++ client.getZooKeeper().getConfig(watching.getWatcher(client, ZooDefs.CONFIG_NODE), 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 + { + if ( watching.isWatched() ) + { + return client.getZooKeeper().getConfig(true, stat); + } - return client.getZooKeeper().getConfig(watching.getWatcher(), stat); ++ return client.getZooKeeper().getConfig(watching.getWatcher(client, ZooDefs.CONFIG_NODE), stat); + } + } + ); + } + finally + { + trace.commit(); + } + } +} http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-framework/src/main/java/org/apache/curator/framework/imps/GetDataBuilderImpl.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/NodeCache.java ---------------------------------------------------------------------- diff --cc curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/NodeCache.java index 72ee5ff,4d87732..49b9a3f --- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/NodeCache.java +++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/NodeCache.java @@@ -53,9 -55,10 +54,9 @@@ import java.util.concurrent.atomic.Atom public class NodeCache implements Closeable { private final Logger log = LoggerFactory.getLogger(getClass()); - private final CuratorFramework client; + private final WatcherRemoveCuratorFramework client; private final String path; private final boolean dataIsCompressed; - private final EnsurePath ensurePath; private final AtomicReference<ChildData> data = new AtomicReference<ChildData>(null); private final AtomicReference<State> state = new AtomicReference<State>(State.LATENT); private final ListenerContainer<NodeCacheListener> listeners = new ListenerContainer<NodeCacheListener>(); @@@ -127,9 -130,10 +128,9 @@@ */ public NodeCache(CuratorFramework client, String path, boolean dataIsCompressed) { - this.client = client; + this.client = client.newWatcherRemoveCuratorFramework(); this.path = PathUtils.validatePath(path); this.dataIsCompressed = dataIsCompressed; - ensurePath = client.newNamespaceAwareEnsurePath(path).excludingLast(); } /** http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/PathChildrenCache.java ---------------------------------------------------------------------- diff --cc curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/PathChildrenCache.java index b5d912c,5c413b6..99a652d --- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/PathChildrenCache.java +++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/PathChildrenCache.java @@@ -42,16 -44,16 +43,13 @@@ import org.apache.zookeeper.Watcher import org.apache.zookeeper.data.Stat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; ++ import java.io.Closeable; import java.io.IOException; import java.util.List; import java.util.Map; import java.util.Set; --import java.util.concurrent.ConcurrentMap; --import java.util.concurrent.Exchanger; --import java.util.concurrent.ExecutorService; --import java.util.concurrent.Executors; --import java.util.concurrent.ThreadFactory; ++import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicReference; /** http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java ---------------------------------------------------------------------- diff --cc curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java index 4f3ffb6,c3958aa..bda00bf --- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java +++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java @@@ -524,13 -510,11 +525,13 @@@ public class TreeCache implements Close * @param cacheData if true, node contents are cached in addition to the stat * @param dataIsCompressed if true, data in the path is compressed * @param executorService Closeable ExecutorService to use for the TreeCache's background thread + * @param createParentNodes true to create parent nodes as containers */ - TreeCache(CuratorFramework client, String path, boolean cacheData, boolean dataIsCompressed, int maxDepth, final CloseableExecutorService executorService) + TreeCache(CuratorFramework client, String path, boolean cacheData, boolean dataIsCompressed, int maxDepth, final CloseableExecutorService executorService, boolean createParentNodes) { + this.createParentNodes = createParentNodes; this.root = new TreeNode(validatePath(path), null); - this.client = client; + this.client = client.newWatcherRemoveCuratorFramework(); this.cacheData = cacheData; this.dataIsCompressed = dataIsCompressed; this.maxDepth = maxDepth; http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-recipes/src/main/java/org/apache/curator/framework/recipes/leader/LeaderLatch.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/InterProcessSemaphoreV2.java ---------------------------------------------------------------------- diff --cc curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/InterProcessSemaphoreV2.java index f4af39b,2a55107..3bf2ec3 --- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/InterProcessSemaphoreV2.java +++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/locks/InterProcessSemaphoreV2.java @@@ -21,16 -21,15 +21,17 @@@ package org.apache.curator.framework.re import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; -import org.apache.curator.framework.WatcherRemoveCuratorFramework; -import org.apache.curator.utils.CloseableUtils; +import com.google.common.collect.Sets; - - import org.apache.curator.utils.CloseableUtils; import org.apache.curator.RetryLoop; import org.apache.curator.framework.CuratorFramework; ++import org.apache.curator.framework.WatcherRemoveCuratorFramework; import org.apache.curator.framework.api.PathAndBytesable; import org.apache.curator.framework.imps.CuratorFrameworkState; import org.apache.curator.framework.recipes.shared.SharedCountListener; import org.apache.curator.framework.recipes.shared.SharedCountReader; import org.apache.curator.framework.state.ConnectionState; ++import org.apache.curator.utils.CloseableUtils; ++import org.apache.curator.utils.PathUtils; import org.apache.curator.utils.ZKPaths; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; @@@ -38,13 -37,12 +39,13 @@@ import org.apache.zookeeper.WatchedEven import org.apache.zookeeper.Watcher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; ++ import java.io.IOException; import java.util.Arrays; import java.util.Collection; import java.util.List; +import java.util.Set; import java.util.concurrent.TimeUnit; --import org.apache.curator.utils.PathUtils; /** * <p> http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-recipes/src/main/java/org/apache/curator/framework/recipes/nodes/PersistentEphemeralNode.java ---------------------------------------------------------------------- diff --cc curator-recipes/src/main/java/org/apache/curator/framework/recipes/nodes/PersistentEphemeralNode.java index 0d963e0,98b09c9..0b482ef --- a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/nodes/PersistentEphemeralNode.java +++ b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/nodes/PersistentEphemeralNode.java @@@ -20,8 -20,8 +20,9 @@@ package org.apache.curator.framework.recipes.nodes; import com.google.common.base.Preconditions; + import org.apache.curator.framework.CuratorFramework; + import org.apache.curator.framework.WatcherRemoveCuratorFramework; import org.apache.curator.framework.api.ACLBackgroundPathAndBytesable; import org.apache.curator.framework.api.BackgroundCallback; import org.apache.curator.framework.api.CreateModable; @@@ -210,12 -189,12 +211,12 @@@ public class PersistentEphemeralNode im * @param basePath the base path for the node * @param data data for the node */ - public PersistentEphemeralNode(CuratorFramework client, Mode mode, String basePath, byte[] data) + public PersistentEphemeralNode(CuratorFramework client, Mode mode, String basePath, byte[] initData) { - this.client = Preconditions.checkNotNull(client, "client cannot be null"); + this.client = Preconditions.checkNotNull(client, "client cannot be null").newWatcherRemoveCuratorFramework(); this.basePath = PathUtils.validatePath(basePath); this.mode = Preconditions.checkNotNull(mode, "mode cannot be null"); - data = Preconditions.checkNotNull(data, "data cannot be null"); + final byte[] data = Preconditions.checkNotNull(initData, "data cannot be null"); backgroundCallback = new BackgroundCallback() { http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-recipes/src/main/java/org/apache/curator/framework/recipes/shared/SharedValue.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestPathChildrenCache.java ---------------------------------------------------------------------- diff --cc curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestPathChildrenCache.java index 14d061f,ffcf251..3571ca7 --- a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestPathChildrenCache.java +++ b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestPathChildrenCache.java @@@ -28,10 -28,9 +28,10 @@@ import org.apache.curator.framework.api import org.apache.curator.framework.api.CuratorEvent; import org.apache.curator.framework.api.Pathable; import org.apache.curator.framework.api.UnhandledErrorListener; - import org.apache.curator.framework.imps.CuratorFrameworkImpl; + import org.apache.curator.framework.imps.TestCleanState; import org.apache.curator.retry.RetryOneTime; import org.apache.curator.test.BaseClassForTests; +import org.apache.curator.test.ExecuteCalledWatchingExecutorService; import org.apache.curator.test.KillSession; import org.apache.curator.test.Timing; import org.apache.curator.utils.CloseableUtils; @@@ -957,9 -1041,133 +966,10 @@@ public class TestPathChildrenCache exte latch.await(5, TimeUnit.SECONDS); Assert.assertTrue(latch.getCount() == 1, "Unexpected exception occurred"); - } finally + } + finally { - CloseableUtils.closeQuietly(client); + TestCleanState.closeAndTestClean(client); } } - - public static class ExecuteCalledWatchingExecutorService extends DelegatingExecutorService - { - boolean executeCalled = false; - - public ExecuteCalledWatchingExecutorService(ExecutorService delegate) - { - super(delegate); - } - - @Override - public synchronized void execute(Runnable command) - { - executeCalled = true; - super.execute(command); - } - - public synchronized boolean isExecuteCalled() - { - return executeCalled; - } - - public synchronized void setExecuteCalled(boolean executeCalled) - { - this.executeCalled = executeCalled; - } - } - - public static class DelegatingExecutorService implements ExecutorService - { - private final ExecutorService delegate; - - public DelegatingExecutorService( - ExecutorService delegate - ) - { - this.delegate = delegate; - } - - - @Override - public void shutdown() - { - delegate.shutdown(); - } - - @Override - public List<Runnable> shutdownNow() - { - return delegate.shutdownNow(); - } - - @Override - public boolean isShutdown() - { - return delegate.isShutdown(); - } - - @Override - public boolean isTerminated() - { - return delegate.isTerminated(); - } - - @Override - public boolean awaitTermination(long timeout, TimeUnit unit) - throws InterruptedException - { - return delegate.awaitTermination(timeout, unit); - } - - @Override - public <T> Future<T> submit(Callable<T> task) - { - return delegate.submit(task); - } - - @Override - public <T> Future<T> submit(Runnable task, T result) - { - return delegate.submit(task, result); - } - - @Override - public Future<?> submit(Runnable task) - { - return delegate.submit(task); - } - - @Override - public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) - throws InterruptedException - { - return delegate.invokeAll(tasks); - } - - @Override - public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) - throws InterruptedException - { - return delegate.invokeAll(tasks, timeout, unit); - } - - @Override - public <T> T invokeAny(Collection<? extends Callable<T>> tasks) - throws InterruptedException, ExecutionException - { - return delegate.invokeAny(tasks); - } - - @Override - public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, TimeoutException - { - return delegate.invokeAny(tasks, timeout, unit); - } - - @Override - public void execute(Runnable command) - { - delegate.execute(command); - } - } } http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessMultiMutex.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessMutex.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessMutexBase.java ---------------------------------------------------------------------- diff --cc curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessMutexBase.java index 99ea11f,49e5d19..f44d238 --- a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessMutexBase.java +++ b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessMutexBase.java @@@ -27,11 -28,7 +28,10 @@@ import org.apache.curator.framework.sta import org.apache.curator.retry.ExponentialBackoffRetry; import org.apache.curator.test.BaseClassForTests; import org.apache.curator.test.KillSession; - import org.apache.curator.test.TestingServer; import org.apache.curator.test.Timing; +import org.apache.curator.utils.CloseableUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.CreateMode; import org.testng.Assert; import org.testng.annotations.Test; import java.util.List; http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessSemaphore.java ---------------------------------------------------------------------- diff --cc curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessSemaphore.java index 631b7c7,2797b5f..3ba75d8 --- a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessSemaphore.java +++ b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/locks/TestInterProcessSemaphore.java @@@ -528,47 -531,7 +531,47 @@@ public class TestInterProcessSemaphore { CloseableUtils.closeQuietly(l); } - CloseableUtils.closeQuietly(client); + TestCleanState.closeAndTestClean(client); } } + + @Test + public void testChildReaperCleansUpLockNodes() throws Exception + { + Timing timing = new Timing(); + CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), timing.session(), timing.connection(), new RetryOneTime(1)); + client.start(); + + ChildReaper childReaper = null; + try + { + InterProcessSemaphoreV2 semaphore = new InterProcessSemaphoreV2(client, "/test/lock", 1); + semaphore.returnLease(semaphore.acquire(timing.forWaiting().seconds(), TimeUnit.SECONDS)); + + Assert.assertTrue(client.getChildren().forPath("/test").size() > 0); + + childReaper = new ChildReaper( + client, + "/test", + Reaper.Mode.REAP_UNTIL_GONE, + ChildReaper.newExecutorService(), + 1, + "/test-leader", + InterProcessSemaphoreV2.LOCK_SCHEMA + ); + childReaper.start(); + + timing.forWaiting().sleepABit(); + + List<String> children = client.getChildren().forPath("/test"); + + Assert.assertEquals(children.size(), 0, "All children of /test should have been reaped"); + } + finally + { + CloseableUtils.closeQuietly(childReaper); + CloseableUtils.closeQuietly(client); + } + + } } http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-recipes/src/test/java/org/apache/curator/framework/recipes/nodes/TestPersistentEphemeralNode.java ---------------------------------------------------------------------- diff --cc curator-recipes/src/test/java/org/apache/curator/framework/recipes/nodes/TestPersistentEphemeralNode.java index 9f5907a,5a58b2a..c81cc65 --- a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/nodes/TestPersistentEphemeralNode.java +++ b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/nodes/TestPersistentEphemeralNode.java @@@ -20,17 -20,15 +20,16 @@@ package org.apache.curator.framework.re import com.google.common.base.Throwables; import com.google.common.collect.Lists; - 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.imps.TestCleanState; import org.apache.curator.framework.state.ConnectionState; import org.apache.curator.framework.state.ConnectionStateListener; import org.apache.curator.retry.RetryOneTime; import org.apache.curator.test.BaseClassForTests; import org.apache.curator.test.KillSession; --import org.apache.curator.test.TestingServer; import org.apache.curator.test.Timing; import org.apache.curator.utils.CloseableUtils; import org.apache.curator.utils.ZKPaths; @@@ -129,9 -123,10 +127,10 @@@ public class TestPersistentEphemeralNod @Test public void testNoServerAtStart() throws Exception { - server.close(); + server.stop(); CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), timing.session(), timing.connection(), new RetryOneTime(1)); + PersistentEphemeralNode node = null; try { client.start(); http://git-wip-us.apache.org/repos/asf/curator/blob/d5d12c88/curator-test/src/main/java/org/apache/curator/test/BaseClassForTests.java ---------------------------------------------------------------------- diff --cc curator-test/src/main/java/org/apache/curator/test/BaseClassForTests.java index 13c3138,d5c434f..6ef3bb0 --- a/curator-test/src/main/java/org/apache/curator/test/BaseClassForTests.java +++ b/curator-test/src/main/java/org/apache/curator/test/BaseClassForTests.java @@@ -35,11 -34,10 +35,12 @@@ public class BaseClassForTest private static final int RETRY_WAIT_MS = 5000; private static final String INTERNAL_PROPERTY_DONT_LOG_CONNECTION_ISSUES; + private static final String INTERNAL_PROPERTY_REMOVE_WATCHERS_IN_FOREGROUND; + private static final String INTERNAL_RETRY_FAILED_TESTS; static { - String s = null; + String logConnectionIssues = null; + String retryFailedTests = null; try { // use reflection to avoid adding a circular dependency in the pom @@@ -51,8 -47,18 +52,19 @@@ { e.printStackTrace(); } - INTERNAL_PROPERTY_DONT_LOG_CONNECTION_ISSUES = s; - + INTERNAL_PROPERTY_DONT_LOG_CONNECTION_ISSUES = logConnectionIssues; + INTERNAL_RETRY_FAILED_TESTS = retryFailedTests; ++ String s = null; + try + { + // use reflection to avoid adding a circular dependency in the pom + s = (String)Class.forName("org.apache.curator.utils.DebugUtils").getField("PROPERTY_REMOVE_WATCHERS_IN_FOREGROUND").get(null); + } + catch ( Exception e ) + { + e.printStackTrace(); + } + INTERNAL_PROPERTY_REMOVE_WATCHERS_IN_FOREGROUND = s; } @BeforeSuite(alwaysRun = true) @@@ -89,18 -96,9 +102,19 @@@ @AfterMethod public void teardown() throws Exception { + System.clearProperty(INTERNAL_PROPERTY_REMOVE_WATCHERS_IN_FOREGROUND); - server.close(); - server = null; + if ( server != null ) + { + try + { + server.close(); + } + catch ( IOException e ) + { + e.printStackTrace(); + } + server = null; + } } private static class RetryTest implements IRetryAnalyzer
