/** Removes a connection */
  void removeItem(ManagedPoolItem item, ManagedConnection mConn) {
    synchronized (_connectionPool) {
      _idlePool.remove(mConn);

      _connectionPool.remove(item);
      _connectionPool.notifyAll();
    }

    try {
      item.destroy();
    } catch (Exception e) {
      log.log(Level.WARNING, e.toString(), e);
    }
  }
  /** Adds a connection to the idle pool. */
  void toIdle(ManagedPoolItem item) {
    try {
      if (_maxConnections < _connectionPool.size() || item.isConnectionError()) {
        return;
      }

      ManagedConnection mConn = item.getManagedConnection();

      if (mConn == null) {
        return;
      }

      mConn.cleanup();

      long now = CurrentTime.getCurrentTime();

      if (_idlePool.size() == 0) _idlePoolExpire = now + _idleTimeout;

      if (_idlePoolExpire < now) {
        // shrink the idle pool when non-empty for idleTimeout
        _idlePoolExpire = now + _idleTimeout;
      } else if (_idlePool.add(mConn)) {
        item = null;
        return;
      }
    } catch (Exception e) {
      log.log(Level.FINE, e.toString(), e);
    } finally {
      notifyConnectionAvailable();

      if (item != null) item.destroy();
    }
  }
  /** Clears the idle connections in the pool. */
  @Override
  public void clear() {
    ArrayList<ManagedPoolItem> pool = _connectionPool;

    if (pool == null) return;

    ArrayList<ManagedPoolItem> clearItems = new ArrayList<ManagedPoolItem>();

    synchronized (_connectionPool) {
      _idlePool.clear();

      clearItems.addAll(pool);

      pool.clear();
    }

    for (int i = 0; i < clearItems.size(); i++) {
      ManagedPoolItem poolItem = clearItems.get(i);

      try {
        poolItem.destroy();
      } catch (Throwable e) {
        log.log(Level.WARNING, e.toString(), e);
      }
    }
  }
  /** Destroys the manager. */
  public void destroy() {
    stop();

    if (!_lifecycle.toDestroy()) return;

    ArrayList<ManagedPoolItem> pool;

    synchronized (_connectionPool) {
      pool = new ArrayList<ManagedPoolItem>(_connectionPool);
      _connectionPool.clear();

      if (_idlePool != null) _idlePool.clear();
    }

    for (int i = 0; i < pool.size(); i++) {
      ManagedPoolItem poolItem = pool.get(i);

      try {
        poolItem.destroy();
      } catch (Throwable e) {
        log.log(Level.WARNING, e.toString(), e);
      }
    }
  }
 /** True if idlePool has an available connection. */
 private boolean isIdleAvailable() {
   return _idlePool.size() > 0;
 }
  /** Allocates a connection from the idle pool. */
  private UserPoolItem allocateIdleConnection(
      ManagedConnectionFactory mcf,
      Subject subject,
      ConnectionRequestInfo info,
      UserPoolItem oldPoolItem)
      throws ResourceException {
    while (_lifecycle.isActive()) {
      ManagedConnection mConn;

      long now = CurrentTime.getCurrentTime();

      if (_lastValidCheckTime + 15000L < now) {
        _lastValidCheckTime = now;

        if (mcf instanceof ValidatingManagedConnectionFactory) {
          ValidatingManagedConnectionFactory vmcf;
          vmcf = (ValidatingManagedConnectionFactory) mcf;

          validate(vmcf);
        }
      }

      ManagedPoolItem poolItem = null;

      while (true) {
        // asks the Driver's ManagedConnectionFactory to match an
        // idle connection
        synchronized (_connectionPool) {
          mConn = mcf.matchManagedConnections(_idlePool, subject, info);

          // If there are no more idle connections, return null
          if (mConn == null) return null;

          // remove can fail for threading reasons, so only succeed if it works.
          if (!_idlePool.remove(mConn)) {
            mConn = null;
          }
        }

        if (mConn != null) {
          poolItem = findPoolItem(mConn);

          if (poolItem == null)
            throw new IllegalStateException(
                L.l("Unexpected non-matching PoolItem found for {0}", mConn));

          break;
        }
      }

      try {
        // Ensure the connection is still valid
        UserPoolItem userPoolItem;
        userPoolItem = poolItem.toActive(subject, info, oldPoolItem);

        if (userPoolItem != null) {
          poolItem = null;
          return userPoolItem;
        }
      } finally {
        if (poolItem != null) poolItem.destroy();
      }
    }

    return null;
  }
 /** Returns the active connections. */
 @Override
 public int getConnectionActiveCount() {
   return _connectionPool.size() - _idlePool.size();
 }
 /** Returns the idle connections. */
 @Override
 public int getConnectionIdleCount() {
   return _idlePool.size();
 }