Repository: curator Updated Branches: refs/heads/CURATOR-299 ea643a2fd -> d192209df
CURATOR-302: fix TestTreeCache.testKilledSession() Project: http://git-wip-us.apache.org/repos/asf/curator/repo Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/82289084 Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/82289084 Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/82289084 Branch: refs/heads/CURATOR-299 Commit: 822890844a608caae20a7c7ce8b2b7aaa2b0f964 Parents: 4e4072b Author: Scott Blum <[email protected]> Authored: Mon Feb 8 12:16:41 2016 -0500 Committer: Scott Blum <[email protected]> Committed: Mon Feb 8 12:17:04 2016 -0500 ---------------------------------------------------------------------- .../framework/recipes/cache/TestTreeCache.java | 4 +- .../apache/curator/test/KillServerSession.java | 122 +++++++++++++++++++ 2 files changed, 125 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/curator/blob/82289084/curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestTreeCache.java ---------------------------------------------------------------------- diff --git a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestTreeCache.java b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestTreeCache.java index e984c03..9f00035 100644 --- a/curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestTreeCache.java +++ b/curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestTreeCache.java @@ -21,6 +21,7 @@ package org.apache.curator.framework.recipes.cache; import com.google.common.collect.ImmutableSet; import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.test.KillServerSession; import org.apache.curator.test.KillSession; import org.apache.curator.utils.CloseableUtils; import org.apache.zookeeper.CreateMode; @@ -423,7 +424,8 @@ public class TestTreeCache extends BaseTestTreeCache client.create().withMode(CreateMode.EPHEMERAL).forPath("/test/me", "data".getBytes()); assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test/me"); - KillSession.kill(client.getZookeeperClient().getZooKeeper(), server.getConnectString()); + KillServerSession.kill(client.getZookeeperClient().getZooKeeper(), server.getConnectString()); + assertEvent(TreeCacheEvent.Type.CONNECTION_SUSPENDED); assertEvent(TreeCacheEvent.Type.CONNECTION_LOST); assertEvent(TreeCacheEvent.Type.CONNECTION_RECONNECTED); assertEvent(TreeCacheEvent.Type.NODE_REMOVED, "/test/me", "data".getBytes()); http://git-wip-us.apache.org/repos/asf/curator/blob/82289084/curator-test/src/main/java/org/apache/curator/test/KillServerSession.java ---------------------------------------------------------------------- diff --git a/curator-test/src/main/java/org/apache/curator/test/KillServerSession.java b/curator-test/src/main/java/org/apache/curator/test/KillServerSession.java new file mode 100644 index 0000000..ab5fa32 --- /dev/null +++ b/curator-test/src/main/java/org/apache/curator/test/KillServerSession.java @@ -0,0 +1,122 @@ +/** + * 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.test; + +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.ZooKeeper; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/** + * <p> + * Utility to simulate a ZK session dying. See: <a href="http://wiki.apache.org/hadoop/ZooKeeper/FAQ#A4">ZooKeeper FAQ</a> + * </p> + * + * <blockquote> + * In the case of testing we want to cause a problem, so to explicitly expire a session an + * application connects to ZooKeeper, saves the session id and password, creates another + * ZooKeeper handle with that id and password, and then closes the new handle. Since both + * handles reference the same session, the close on second handle will invalidate the session + * causing a SESSION_EXPIRED on the first handle. + * </blockquote> + */ +public class KillServerSession +{ + /** + * Kill the given ZK session + * + * @param client the client to kill + * @param connectString server connection string + * @throws Exception errors + */ + public static void kill(ZooKeeper client, String connectString) throws Exception + { + kill(client, connectString, new Timing().forWaiting().milliseconds()); + } + + /** + * Kill the given ZK session + * + * @param client the client to kill + * @param connectString server connection string + * @param maxMs max time ms to wait for kill + * @throws Exception errors + */ + public static void kill(ZooKeeper client, String connectString, int maxMs) throws Exception + { + long startTicks = System.currentTimeMillis(); + + final CountDownLatch sessionLostLatch = new CountDownLatch(1); + Watcher sessionLostWatch = new Watcher() + { + @Override + public void process(WatchedEvent event) + { + sessionLostLatch.countDown(); + } + }; + client.exists("/___CURATOR_KILL_SESSION___" + System.nanoTime(), sessionLostWatch); + + final CountDownLatch connectionLatch = new CountDownLatch(1); + Watcher connectionWatcher = new Watcher() + { + @Override + public void process(WatchedEvent event) + { + if ( event.getState() == Event.KeeperState.SyncConnected ) + { + connectionLatch.countDown(); + } + } + }; + ZooKeeper zk = new ZooKeeper(connectString, maxMs, connectionWatcher, client.getSessionId(), client.getSessionPasswd()); + try + { + if ( !connectionLatch.await(maxMs, TimeUnit.MILLISECONDS) ) + { + throw new Exception("KillSession could not establish duplicate session"); + } + try + { + zk.close(); + } + finally + { + zk = null; + } + + while ( client.getState().isConnected() && !sessionLostLatch.await(100, TimeUnit.MILLISECONDS) ) + { + long elapsed = System.currentTimeMillis() - startTicks; + if ( elapsed > maxMs ) + { + throw new Exception("KillSession timed out waiting for session to expire"); + } + } + } + finally + { + if ( zk != null ) + { + zk.close(); + } + } + } +}
