void internalBlockUntilConnectedOrTimedOut() throws InterruptedException {
    long waitTimeMs = connectionTimeoutMs;
    while (!state.isConnected() && (waitTimeMs > 0)) {
      final AtomicReference<Watcher> previousWatcher = new AtomicReference<Watcher>(null);
      final CountDownLatch latch = new CountDownLatch(1);
      Watcher tempWatcher =
          new Watcher() {
            @Override
            public void process(WatchedEvent event) {
              Watcher localPreviousWatcher = previousWatcher.get();
              if (localPreviousWatcher != null) {
                localPreviousWatcher.process(event);
              }
              latch.countDown();
            }
          };

      previousWatcher.set(state.substituteParentWatcher(tempWatcher));
      long startTimeMs = System.currentTimeMillis();
      try {
        latch.await(1, TimeUnit.SECONDS);
      } finally {
        state.substituteParentWatcher(previousWatcher.get());
      }
      long elapsed = Math.max(1, System.currentTimeMillis() - startTimeMs);
      waitTimeMs -= elapsed;
    }
  }
  /**
   * This method blocks until the connection to ZK succeeds. Use with caution. The block will
   * timeout after the connection timeout (as passed to the constructor) has elapsed
   *
   * @return true if the connection succeeded, false if not
   * @throws InterruptedException interrupted while waiting
   */
  public boolean blockUntilConnectedOrTimedOut() throws InterruptedException {
    Preconditions.checkArgument(started.get());

    log.debug("blockUntilConnectedOrTimedOut() start");
    TimeTrace trace = startTracer("blockUntilConnectedOrTimedOut");

    internalBlockUntilConnectedOrTimedOut();

    trace.commit();

    boolean localIsConnected = state.isConnected();
    log.debug("blockUntilConnectedOrTimedOut() end. isConnected: " + localIsConnected);

    return localIsConnected;
  }
 /**
  * Returns true if the client is current connected
  *
  * @return true/false
  */
 public boolean isConnected() {
   return state.isConnected();
 }