private synchronized void checkTimeouts() throws Exception {
   long elapsed = System.currentTimeMillis() - connectionStartMs;
   if (elapsed >= Math.min(sessionTimeoutMs, connectionTimeoutMs)) {
     if (zooKeeper.hasNewConnectionString()) {
       handleNewConnectionString();
     } else if (elapsed > sessionTimeoutMs) {
       if (!Boolean.getBoolean(DebugUtils.PROPERTY_DONT_LOG_CONNECTION_ISSUES)) {
         log.warn(
             String.format(
                 "Connection attempt unsuccessful after %d (greater than session timeout of %d). Resetting connection and trying again with a new connection.",
                 elapsed, sessionTimeoutMs));
       }
       reset();
     } else {
       KeeperException.ConnectionLossException connectionLossException =
           new KeeperException.ConnectionLossException();
       if (!Boolean.getBoolean(DebugUtils.PROPERTY_DONT_LOG_CONNECTION_ISSUES)) {
         log.error(
             String.format(
                 "Connection timed out for connection string (%s) and timeout (%d) / elapsed (%d)",
                 zooKeeper.getConnectionString(), connectionTimeoutMs, elapsed),
             connectionLossException);
       }
       tracer.get().addCount("connections-timed-out", 1);
       throw connectionLossException;
     }
   }
 }
  private synchronized void reset() throws Exception {
    log.debug("reset");

    isConnected.set(false);
    connectionStartMs = System.currentTimeMillis();
    zooKeeper.closeAndReset();
    zooKeeper.getZooKeeper(); // initiate connection
  }
  @Override
  public void close() throws IOException {
    log.debug("Closing");

    Closeables.closeQuietly(ensembleProvider);
    try {
      zooKeeper.closeAndClear();
    } catch (Exception e) {
      throw new IOException(e);
    } finally {
      isConnected.set(false);
    }
  }
  private boolean checkState(Event.KeeperState state, boolean wasConnected) {
    boolean isConnected = wasConnected;
    boolean checkNewConnectionString = true;
    switch (state) {
      default:
      case Disconnected:
        {
          isConnected = false;
          break;
        }

      case SyncConnected:
      case ConnectedReadOnly:
        {
          isConnected = true;
          break;
        }

      case AuthFailed:
        {
          isConnected = false;
          log.error("Authentication failed");
          break;
        }

      case Expired:
        {
          isConnected = false;
          checkNewConnectionString = false;
          handleExpiredSession();
          break;
        }

      case SaslAuthenticated:
        {
          // NOP
          break;
        }
    }

    if (checkNewConnectionString && zooKeeper.hasNewConnectionString()) {
      handleNewConnectionString();
    }

    return isConnected;
  }
  ZooKeeper getZooKeeper() throws Exception {
    if (SessionFailRetryLoop.sessionForThreadHasFailed()) {
      throw new SessionFailRetryLoop.SessionFailedException();
    }

    Exception exception = backgroundExceptions.poll();
    if (exception != null) {
      log.error("Background exception caught", exception);
      tracer.get().addCount("background-exceptions", 1);
      throw exception;
    }

    boolean localIsConnected = isConnected.get();
    if (!localIsConnected) {
      checkTimeouts();
    }

    return zooKeeper.getZooKeeper();
  }