mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Matthew Swift
15.11.2012 4f425a29d8c7115f8014f7548db560400c850e41
Fix OPENDJ-590: ConnectionPool may return already closed/disconnected connections

Fix bug and enable unit test.


2 files modified
60 ■■■■■ changed files
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/FixedConnectionPool.java 58 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/ConnectionPoolTestCase.java 2 ●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/FixedConnectionPool.java
@@ -575,36 +575,44 @@
    @Override
    public FutureResult<Connection> getConnectionAsync(
            final ResultHandler<? super Connection> handler) {
        QueueElement holder;
        synchronized (queue) {
            if (isClosed) {
                throw new IllegalStateException("FixedConnectionPool is already closed");
        // Loop while iterating through stale connections (see OPENDJ-590).
        for (;;) {
            final QueueElement holder;
            synchronized (queue) {
                if (isClosed) {
                    throw new IllegalStateException("FixedConnectionPool is already closed");
                }
                if (queue.isEmpty() || queue.getFirst().isWaitingFuture()) {
                    holder = new QueueElement(handler);
                    queue.add(holder);
                } else {
                    holder = queue.removeFirst();
                }
            }
            if (queue.isEmpty() || queue.getFirst().isWaitingFuture()) {
                holder = new QueueElement(handler);
                queue.add(holder);
            if (!holder.isWaitingFuture()) {
                // There was a completed connection attempt.
                final Connection connection = holder.getWaitingConnection();
                if (connection.isValid()) {
                    final PooledConnection pooledConnection = new PooledConnection(connection);
                    if (handler != null) {
                        handler.handleResult(pooledConnection);
                    }
                    return new CompletedFutureResult<Connection>(pooledConnection);
                } else {
                    // Close the stale connection and try again.
                    connection.close();
                }
            } else {
                holder = queue.removeFirst();
                // Grow the pool if needed.
                final FutureResult<Connection> future = holder.getWaitingFuture();
                if (!future.isDone() && currentPoolSize.tryAcquire()) {
                    factory.getConnectionAsync(connectionResultHandler);
                }
                return future;
            }
        }
        if (!holder.isWaitingFuture()) {
            // There was a completed connection attempt.
            final Connection connection = holder.getWaitingConnection();
            final PooledConnection pooledConnection = new PooledConnection(connection);
            if (handler != null) {
                handler.handleResult(pooledConnection);
            }
            return new CompletedFutureResult<Connection>(pooledConnection);
        } else {
            // Grow the pool if needed.
            final FutureResult<Connection> future = holder.getWaitingFuture();
            if (!future.isDone() && currentPoolSize.tryAcquire()) {
                factory.getConnectionAsync(connectionResultHandler);
            }
            return future;
        }
    }
    /**
opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/ConnectionPoolTestCase.java
@@ -273,7 +273,7 @@
     * @throws Exception
     *             If an unexpected error occurred.
     */
    @Test(enabled = false)
    @Test
    public void testSkipStaleConnectionsOnGet() throws Exception {
        // Setup.
        final Connection connection1 = mock(Connection.class);