diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/jdbc/CachedConnection.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/jdbc/CachedConnection.java index 188f7ba2fb..3c2dbcac38 100644 --- a/opendj-server-legacy/src/main/java/org/opends/server/backends/jdbc/CachedConnection.java +++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/jdbc/CachedConnection.java @@ -23,9 +23,21 @@ import java.sql.*; import java.time.Duration; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Deque; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Properties; +import java.util.Set; import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicLong; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class CachedConnection implements Connection { private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); @@ -33,6 +45,71 @@ public class CachedConnection implements Connection { static final String TTL_PROPERTY = "org.openidentityplatform.opendj.jdbc.ttl"; static final long DEFAULT_TTL_MS = 15000; + /** + * Bounds the connect and the login of one attempt to establish a connection, in seconds; 0 for + * no bound of its own - the deadline of {@value #POOL_TIMEOUT_PROPERTY} still bounds the + * attempt, since it stands for the whole borrow. Setting both to 0 is what leaves a connect + * unbounded. + */ + static final String CONNECT_TIMEOUT_PROPERTY = "org.openidentityplatform.opendj.jdbc.connect.timeout"; + static final long DEFAULT_CONNECT_TIMEOUT_SECONDS = 30; + + /** + * Bounds a whole borrow - every connect attempt and every wait for a pooled connection - in + * seconds; 0 for no bound. Not to the millisecond: the connection in hand is validated + * whatever the deadline says, and an attempt is never given less than a second, so a borrow + * can return a validation and a last attempt past it. + */ + static final String POOL_TIMEOUT_PROPERTY = "org.openidentityplatform.opendj.jdbc.pool.timeout"; + static final long DEFAULT_POOL_TIMEOUT_SECONDS = 60; + + /** Bound of the validation of a pooled connection: isValid(0) means "no timeout" in the JDBC contract. */ + static final int VALIDATION_TIMEOUT_SECONDS = 5; + + /** 08001, sqlclient_unable_to_establish_sqlconnection: the state of a connect that did not happen. */ + private static final String CONNECT_FAILED_SQL_STATE = "08001"; + /** 53300, too_many_connections: how the standard - and postgresql - reports a server taking no further connection. */ + private static final String CONNECTION_LIMIT_SQL_STATE = "53300"; + /** 57P03, cannot_connect_now: postgresql starting up, shutting down or in recovery. */ + private static final String NOT_ACCEPTING_YET_SQL_STATE = "57P03"; + + static final long MAX_BACKOFF_MS = 1000; + static final long STALL_WARNING_AFTER_MS = 1000; + static final long STALL_WARNING_INTERVAL_MS = 10000; + + /** How many links of the cause and getNextException() chains of a failure are looked at. */ + private static final int MAX_CHAIN_LENGTH = 32; + + /** What a connection string is cut down to where this cannot tell its credentials from the rest of it. */ + static final String CREDENTIALS_HIDDEN = "