From 6256bc1e41b2b799336d44700083446ec83117ec Mon Sep 17 00:00:00 2001 From: Mukti Date: Tue, 9 Mar 2021 13:34:22 +0530 Subject: [PATCH] ZOOKEEPER-1871: Add an option to zkCli to wailt for connection before executing commands --- .../org/apache/zookeeper/ZooKeeperMain.java | 24 +++++++++++++++++++ .../org/apache/zookeeper/ZooKeeperTest.java | 22 +++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeperMain.java b/zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeperMain.java index ff8ce623286..ee363948236 100644 --- a/zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeperMain.java +++ b/zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeperMain.java @@ -32,6 +32,9 @@ import java.util.List; import java.util.Map; import java.util.NoSuchElementException; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Stream; @@ -68,6 +71,7 @@ public class ZooKeeperMain { protected ZooKeeper zk; protected String host = ""; + private CountDownLatch connectLatch = null; public boolean getPrintWatches() { return printWatches; @@ -106,6 +110,13 @@ public void process(WatchedEvent event) { ZooKeeperMain.printMessage("WATCHER::"); ZooKeeperMain.printMessage(event.toString()); } + if (connectLatch != null) { + // connection success + if ( event.getType() == Event.EventType.None + && event.getState() == Event.KeeperState.SyncConnected) { + connectLatch.countDown(); + } + } } } @@ -168,6 +179,8 @@ public boolean parseOptions(String[] args) { options.put("readonly", "true"); } else if (opt.equals("-client-configuration")) { options.put("client-configuration", it.next()); + } else if (opt.equals("-waitforconnection")) { + options.put("waitforconnection", "true"); } } catch (NoSuchElementException e) { System.err.println("Error: no argument found for option " + opt); @@ -249,6 +262,17 @@ protected void connectToZK(String newHost) throws InterruptedException, IOExcept System.setProperty(ZKClientConfig.SECURE_CLIENT, "true"); System.out.println("Secure connection is enabled"); } + if (cl.getOption("waitforconnection") != null) { + connectLatch = new CountDownLatch(1); + } + int timeout = Integer.parseInt(cl.getOption("timeout")); + zk = new ZooKeeperAdmin(host, timeout, new MyWatcher(),readOnly); + if (connectLatch != null) { + if (!connectLatch.await(timeout, TimeUnit.MILLISECONDS)) { + zk.close(); + throw new IOException(KeeperException.create(KeeperException.Code.CONNECTIONLOSS)); + } + } ZKClientConfig clientConfig = null; diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/ZooKeeperTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/ZooKeeperTest.java index b726c47da06..26ed112b582 100644 --- a/zookeeper-server/src/test/java/org/apache/zookeeper/ZooKeeperTest.java +++ b/zookeeper-server/src/test/java/org/apache/zookeeper/ZooKeeperTest.java @@ -50,6 +50,7 @@ import org.apache.zookeeper.data.Id; import org.apache.zookeeper.data.Stat; import org.apache.zookeeper.test.ClientBase; +import org.apache.zookeeper.PortAssignment; import org.junit.jupiter.api.Test; /** @@ -774,4 +775,25 @@ private void assertClientAuthInfo(List expected, String actual) { }); } + @Test + public void testWaitForConnection() throws Exception { + // get a wrong port number + int invalidPort = PortAssignment.unique(); + long timeout = 3000L; // millisecond + String[] args1 = {"-server", "localhost:" + invalidPort, "-timeout", + Long.toString(timeout), "-waitforconnection", "ls", "/"}; + long startTime = System.currentTimeMillis(); + // try to connect to a non-existing server so as to wait until wait_timeout + try { + ZooKeeperMain zkMain = new ZooKeeperMain(args1); + fail("IOException was expected"); + } catch (IOException e) { + // do nothing + } + long endTime = System.currentTimeMillis(); + assertTrue(endTime - startTime >= timeout, + "ZooKeeeperMain does not wait until the specified timeout"); + + } + }