Skip to content

Commit

Permalink
Update to getting pooled conn on HC failure
Browse files Browse the repository at this point in the history
Updated the LDAPConnectionPool behavior in the case that an attempt
to check out a connection from the pool first encounters an existing
connection that is deemed not valid by the configured health check.
Previously, it would close that connection as defunct and try to
create a new connection to replace it, but if that attempt was
successful, the newly created connection would be added to the end
of the pool's set of potentially available connections, and it would
continue iterating through the set of connections to try to find one
that is valid.  Now, if the pool is able to successfully create a
new connection to replace the existing defunct connection, it will
immediately return that new connection without checking any of the
other existing connections.  This should substantially improve
performance in the case that the pool has several connections that
are already established but have become invalid for some reason in a
way that does not prevent successfully establishing new connections.
  • Loading branch information
dirmgr committed Jan 19, 2024
1 parent 62aa718 commit 08d3cb2
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 5 deletions.
17 changes: 17 additions & 0 deletions docs/release-notes.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,23 @@ <h3>Version 7.0.0</h3>
<br><br>
</li>

<li>
Updated the LDAPConnectionPool behavior in the case that an attempt to check out
a connection from the pool first encounters an existing connection that is deemed
not valid by the configured health check. Previously, it would close that
connection as defunct and try to create a new connection to replace it, but if
that attempt was successful, the newly created connection would be added to the
end of the pool's set of potentially available connections, and it would continue
iterating through the set of connections to try to find one that is valid. Now,
if the pool is able to successfully create a new connection to replace the
existing defunct connection, it will immediately return that new connection
without checking any of the other existing connections. This should
substantially improve performance in the case that the pool has several
connections that are already established but have become invalid for some reason
in a way that does not prevent successfully establishing new connections.
<br><br>
</li>

<li>
Added a compare-ldap-schemas command-line tool that can be used to identify
differences between the schemas of two LDAP servers.
Expand Down
19 changes: 14 additions & 5 deletions src/com/unboundid/ldap/sdk/LDAPConnectionPool.java
Original file line number Diff line number Diff line change
Expand Up @@ -1812,11 +1812,20 @@ public LDAPConnection getConnection()
}
}

poolStatistics.incrementNumConnectionsClosedDefunct();
Debug.debugConnectionPool(Level.WARNING, this, conn,
"Closing a defunct connection encountered during checkout",
connException);
handleDefunctConnection(conn);
try
{
conn = replaceDefunctConnection(conn);
poolStatistics.incrementNumSuccessfulCheckoutsWithoutWaiting();
Debug.debugConnectionPool(Level.INFO, this, conn,
"Returning a newly created connection after a checked-out " +
"connection was found to be invalid", null);
return conn;
}
catch (final LDAPException e)
{
Debug.debugException(e);
}

for (int i=0; i < numConnections; i++)
{
conn = availableConnections.poll();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3277,4 +3277,51 @@ public void testReplaceDefunctConnectionWithCreateIfNecessaryFalse()
pool.close();
ds.shutDown(true);
}



/**
* Tests to ensure that it's possible to successfully obtain a connection to a
* pool when that pool is configured with a health check that will always
* result in a failure when trying to check out an existing connection. In
* that case, it will fall back to trying to create a new connection, and if
* that succeeds, then it will use that new connection.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testCheckOutHealthCheckFailure()
throws Exception
{
// Create an in-memory directory server to use for testing.
final InMemoryDirectoryServerConfig cfg =
new InMemoryDirectoryServerConfig("dc=example,dc=com");
cfg.addAdditionalBindCredentials("cn=Directory Manager", "password");
final InMemoryDirectoryServer ds = new InMemoryDirectoryServer(cfg);
ds.startListening();

// Create a connection pool to use for testing. Configure it with a
// health check that will always fail checkout attempts.
final LDAPConnectionPool pool = new LDAPConnectionPool(
new SingleServerSet("localhost", ds.getListenPort()),
new SimpleBindRequest("cn=Directory Manager", "password"), 1, 1);
pool.setHealthCheck(new TestLDAPConnectionPoolHealthCheck(null, null,
new LDAPException(ResultCode.SERVER_DOWN,
"The existing connection is no longer considered valid"),
null, null, null));


// Make sure that we can successfully process operations using the
// connection pool.
assertNotNull(pool.getRootDSE());
assertNotNull(pool.getRootDSE());

final LDAPConnection conn = pool.getConnection();
assertNotNull(conn);
assertNotNull(conn.getRootDSE());
pool.releaseConnection(conn);

pool.close();
ds.shutDown(true);
}
}

0 comments on commit 08d3cb2

Please sign in to comment.