src/main/java/org/vibur/dbcp/pool/PoolOperations.java
private ConnHolder getConnHolder(long timeoutMs) throws SQLException, ViburDBCPException {
        Hook.GetConnection[] onGet = ((ConnHooksAccessor) dataSource.getConnHooks()).onGet();
        ConnHolder connHolder = null;
        long[] waitedNanos = NO_WAIT;
        SQLException sqlException = null;
        ViburDBCPException viburException = null;

        try {
            if (onGet.length > 0) {
                waitedNanos = new long[1];
                connHolder = timeoutMs > 0 ? poolService.tryTake(timeoutMs, MILLISECONDS, waitedNanos) : poolService.take(waitedNanos);
            }
            else {
                connHolder = timeoutMs > 0 ? poolService.tryTake(timeoutMs, MILLISECONDS) : poolService.take();
            }

            if (connHolder == null) { // we were *not* able to obtain a connection from the pool
                sqlException = createSQLException(onGet.length > 0 ? waitedNanos[0] : MILLISECONDS.toNanos(timeoutMs));
            }
        } catch (ViburDBCPException e) { // thrown (indirectly) by the ConnectionFactory.create() methods
            viburException = e;
            sqlException = e.unwrapSQLException(); // currently all such errors are treated as recoverable, i.e., can be retried

        } finally {
            Connection rawConnection = connHolder != null ? connHolder.rawConnection() : null;
            try {
                for (Hook.GetConnection hook : onGet) {
                    hook.on(rawConnection, waitedNanos[0]);
                }
            } catch (SQLException e) {
                sqlException = chainSQLException(sqlException, e);
            }
        }

        if (viburException != null) {
            throw viburException; // a recoverable error
        }
        if (sqlException != null) {
            throw sqlException; // a non-recoverable error
        }

        return connHolder; // never null if we reach this point
    }
private ConnHolder getConnHolder(long timeoutMs) throws SQLException, ViburDBCPException {
        Hook.GetConnection[] onGet = ((ConnHooksAccessor) dataSource.getConnHooks()).onGet();
        ConnHolder connHolder = null;
        long[] waitedNanos = NO_WAIT;
        SQLException sqlException = null;
        ViburDBCPException viburException = null;

        try {
            if (onGet.length > 0) {
                waitedNanos = new long[1];
                connHolder = timeoutMs > 0 ? poolService.tryTake(timeoutMs, MILLISECONDS, waitedNanos) : poolService.take(waitedNanos);
            }
            else {
                connHolder = timeoutMs > 0 ? poolService.tryTake(timeoutMs, MILLISECONDS) : poolService.take();
            }

            if (connHolder == null) { // we were *not* able to obtain a connection from the pool
                sqlException = createSQLException(onGet.length > 0 ? waitedNanos[0] : MILLISECONDS.toNanos(timeoutMs));
            }
        } catch (ViburDBCPException e) { // thrown (indirectly) by the ConnectionFactory.create() methods
            viburException = e;
            sqlException = e.unwrapSQLException(); // currently all such errors are treated as recoverable, i.e., can be retried

        } finally {
            Connection rawConnection = connHolder != null ? connHolder.rawConnection() : null;
            try {
                for (Hook.GetConnection hook : onGet) {
                    hook.on(rawConnection, waitedNanos[0]);
                }
            } catch (SQLException e) {
                sqlException = chainSQLException(sqlException, e);
            }
        }

        if (viburException != null) {
            throw viburException; // a recoverable error
        }
        if (sqlException != null) {
            throw sqlException; // a non-recoverable error
        }

        return connHolder; // never null if we reach this point
    }
Tries to take a {@code ConnHolder} object from the underlying object pool. If successful, never returns
{@code null}.

@param timeoutMs timeout in millis to pass to the underlying object pool {@code take} methods
@throws SQLException to indicate a generic non-recoverable error that cannot be retried
@throws SQLTimeoutException to indicate a non-recoverable error due to timeout that cannot be retried
@throws ViburDBCPException to indicate a recoverable error that can be retried