public HostConnectionPool(Host host, HostDistance hostDistance, Session.Manager manager)
      throws ConnectionException {
    assert hostDistance != HostDistance.IGNORED;
    this.host = host;
    this.hostDistance = hostDistance;
    this.manager = manager;

    this.newConnectionTask =
        new Runnable() {
          @Override
          public void run() {
            addConnectionIfUnderMaximum();
            scheduledForCreation.decrementAndGet();
          }
        };

    // Create initial core connections
    List<Connection> l =
        new ArrayList<Connection>(options().getCoreConnectionsPerHost(hostDistance));
    try {
      for (int i = 0; i < options().getCoreConnectionsPerHost(hostDistance); i++)
        l.add(manager.connectionFactory().open(host));
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
      // If asked to interrupt, we can skip opening core connections, the pool will still work.
      // But we ignore otherwise cause I'm not sure we can do much better currently.
    }
    this.connections = new CopyOnWriteArrayList<Connection>(l);
    this.open = new AtomicInteger(connections.size());

    logger.trace("Created connection pool to host {}", host);
  }
  private boolean addConnectionIfUnderMaximum() {

    // First, make sure we don't cross the allowed limit of open connections
    for (; ; ) {
      int opened = open.get();
      if (opened >= options().getMaxConnectionsPerHost(hostDistance)) return false;

      if (open.compareAndSet(opened, opened + 1)) break;
    }

    if (isShutdown()) {
      open.decrementAndGet();
      return false;
    }

    // Now really open the connection
    try {
      connections.add(manager.connectionFactory().open(host));
      signalAvailableConnection();
      return true;
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
      // Skip the open but ignore otherwise
      open.decrementAndGet();
      return false;
    } catch (ConnectionException e) {
      open.decrementAndGet();
      logger.debug("Connection error to {} while creating additional connection", host);
      if (host.getMonitor().signalConnectionFailure(e)) shutdown();
      return false;
    } catch (AuthenticationException e) {
      // This shouldn't really happen in theory
      open.decrementAndGet();
      logger.error(
          "Authentication error while creating additional connection (error is: {})",
          e.getMessage());
      shutdown();
      return false;
    }
  }