/** Starts creation of an overflow connection. */
  private boolean startCreateOverflow() throws ResourceException {
    int size = _connectionPool.size();
    int createCount = _createCount.incrementAndGet();

    if (createCount + size <= _maxConnections + _maxOverflowConnections) return true;

    _createCount.decrementAndGet();
    String message =
        L.l(
            "{0} cannot create overflow connection after {1}ms"
                + " (pool-size={2}"
                + ", max-connections={3}"
                + ", create-count={4}"
                + ", max-create-connections={5}"
                + ", max-overflow-connections={6})",
            this,
            _connectionWaitTimeout,
            _connectionPool.size(),
            _maxConnections,
            _createCount.get(),
            _maxCreateConnections,
            _maxOverflowConnections);

    HealthStatusService.updateCurrentHealthStatus(this, HealthStatus.WARNING, message);

    throw new ResourceException(message);
  }
  /**
   * Allocates the pool item for a connection, creating one if necessary.
   *
   * @param mcf the driver's ManagedConnectionFactory for creating pooled connections
   * @param subject the user's authentication credentials
   * @param info the user's extra connection information
   */
  UserPoolItem allocatePoolConnection(
      ManagedConnectionFactory mcf,
      Subject subject,
      ConnectionRequestInfo info,
      UserPoolItem oldPoolItem)
      throws ResourceException {
    long expireTime = CurrentTime.getCurrentTimeActual() + _connectionWaitTimeout;

    if (!_lifecycle.isActive()) {
      throw new IllegalStateException(
          L.l("{0}: Can't allocate connection because the connection pool is closed.", this));
    }

    do {
      UserPoolItem userPoolItem = allocateIdleConnection(mcf, subject, info, oldPoolItem);

      if (userPoolItem != null) return userPoolItem;

      // if no item in pool, try to create one
      if (startCreateConnection()) {
        try {
          return createConnection(mcf, subject, info, oldPoolItem);
        } finally {
          finishCreateConnection();
        }
      }
    } while (_lifecycle.isActive() && waitForAvailableConnection(expireTime));

    if (!_lifecycle.isActive())
      throw new IllegalStateException(
          L.l("{0}: Can't allocate connection because the connection pool is closed.", this));

    String message =
        (this
            + " pool throttled create timeout"
            + " (pool-size="
            + _connectionPool.size()
            + ", max-connections="
            + _maxConnections
            + ", create-count="
            + _createCount.get()
            + ", max-create-connections="
            + _maxCreateConnections
            + ")");

    HealthStatusService.updateCurrentHealthStatus(this, HealthStatus.WARNING, message);

    if (startCreateOverflow()) {
      try {
        return createConnection(mcf, subject, info, oldPoolItem);
      } finally {
        finishCreateConnection();
      }
    }

    message =
        (this
            + " pool overflow failed to create"
            + " (pool-size="
            + _connectionPool.size()
            + ", max-connections="
            + _maxConnections
            + ", create-count="
            + _createCount.get()
            + ", max-create-connections="
            + _maxCreateConnections
            + ")");

    HealthStatusService.updateCurrentHealthStatus(this, HealthStatus.CRITICAL, message);

    throw new ResourceException(
        L.l("Can't create overflow connection connection-max={0}", _maxConnections));
  }