private void maybeSpawnNewConnection() {
    while (true) {
      int inCreation = scheduledForCreation.get();
      if (inCreation >= MAX_SIMULTANEOUS_CREATION) return;
      if (scheduledForCreation.compareAndSet(inCreation, inCreation + 1)) break;
    }

    logger.debug("Creating new connection on busy pool to {}", host);
    manager.executor().submit(newConnectionTask);
  }
 private void close(final Connection connection) {
   manager
       .executor()
       .submit(
           new Runnable() {
             @Override
             public void run() {
               connection.close();
             }
           });
 }
  private void replace(final Connection connection) {
    connections.remove(connection);

    manager
        .executor()
        .submit(
            new Runnable() {
              @Override
              public void run() {
                connection.close();
                addConnectionIfUnderMaximum();
              }
            });
  }
  // This creates connections if we have less than core connections (if we
  // have more than core, connection will just get trash when we can).
  public void ensureCoreConnections() {
    if (isShutdown()) return;

    // Note: this process is a bit racy, but it doesn't matter since we're still guaranteed to not
    // create
    // more connection than maximum (and if we create more than core connection due to a race but
    // this isn't
    // justified by the load, the connection in excess will be quickly trashed anyway)
    int opened = open.get();
    for (int i = opened; i < options().getCoreConnectionsPerHost(hostDistance); i++) {
      // We don't respect MAX_SIMULTANEOUS_CREATION here because it's only to
      // protect against creating connection in excess of core too quickly
      scheduledForCreation.incrementAndGet();
      manager.executor().submit(newConnectionTask);
    }
  }
  public Connection borrowConnection(long timeout, TimeUnit unit)
      throws ConnectionException, TimeoutException {
    if (isShutdown.get())
      // Note: throwing a ConnectionException is probably fine in practice as it will trigger the
      // creation of a new host.
      // That being said, maybe having a specific exception could be cleaner.
      throw new ConnectionException(host.getAddress(), "Pool is shutdown");

    if (connections.isEmpty()) {
      for (int i = 0; i < options().getCoreConnectionsPerHost(hostDistance); i++) {
        // We don't respect MAX_SIMULTANEOUS_CREATION here because it's  only to
        // protect against creating connection in excess of core too quickly
        scheduledForCreation.incrementAndGet();
        manager.executor().submit(newConnectionTask);
      }
      Connection c = waitForConnection(timeout, unit);
      c.setKeyspace(manager.poolsState.keyspace);
      return c;
    }

    int minInFlight = Integer.MAX_VALUE;
    Connection leastBusy = null;
    for (Connection connection : connections) {
      int inFlight = connection.inFlight.get();
      if (inFlight < minInFlight) {
        minInFlight = inFlight;
        leastBusy = connection;
      }
    }

    if (minInFlight >= options().getMaxSimultaneousRequestsPerConnectionThreshold(hostDistance)
        && connections.size() < options().getMaxConnectionsPerHost(hostDistance))
      maybeSpawnNewConnection();

    while (true) {
      int inFlight = leastBusy.inFlight.get();

      if (inFlight >= Connection.MAX_STREAM_PER_CONNECTION) {
        leastBusy = waitForConnection(timeout, unit);
        break;
      }

      if (leastBusy.inFlight.compareAndSet(inFlight, inFlight + 1)) break;
    }
    leastBusy.setKeyspace(manager.poolsState.keyspace);
    return leastBusy;
  }