From 0116673e66af4905ee25476b9905b73e5dba0cf3 Mon Sep 17 00:00:00 2001
From: Valery Kharseko <vharseko@3a-systems.ru>
Date: Tue, 22 Sep 2026 09:09:23 +0000
Subject: [PATCH] [#932] Hand the bounds of a catalog connect in, so its cases stop setting them for the whole jvm (#1006)

---
 opendj-server-legacy/src/main/java/org/opends/server/backends/jdbc/JDBCStorage.java |   31 +++++++++++++++++++++++++++++--
 1 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/jdbc/JDBCStorage.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/jdbc/JDBCStorage.java
index 55cb13c..fad5fa3 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/jdbc/JDBCStorage.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/jdbc/JDBCStorage.java
@@ -1734,6 +1734,35 @@
 	 *        CachedConnection#deadlineOf}, so that the shorter of the two is a plain {@code min}.
 	 */
 	Connection newCatalogConnection(long budgetDeadline) throws SQLException {
+		// the one place this connect reads the two settings, and it reads them on every connect the way
+		// the pool reads them on every borrow: an operator may change either on a running server
+		return newCatalogConnection(budgetDeadline, CachedConnection.getConnectTimeoutSeconds(),
+			CachedConnection.getPoolTimeoutSeconds());
+	}
+
+	/**
+	 * The same connect with its two bounds handed in, for the cases of this connect that are not about
+	 * where the bounds come from.
+	 * <p>
+	 * Both are read from system properties, here and on every borrow of the pool, so a case pinning
+	 * them by setting the properties holds them for the whole jvm while it runs - and a borrow made
+	 * anywhere else in that window computes a deadline it was never meant to have (#932). The cases
+	 * about the reading itself go on setting the properties, that being the thing they assert; every
+	 * other one hands its values in here, and the jvm hears nothing about it.
+	 * <p>
+	 * Not a seam for the product: {@link #newCatalogConnection(long)} is what every caller uses, and
+	 * the pair it reads is the pair a borrow of the pool reads beside it - one property, one meaning,
+	 * whichever of the two is asking.
+	 *
+	 * @param budgetDeadline as {@link #newCatalogConnection(long)} takes it.
+	 * @param connectTimeoutSeconds the bound of one attempt, the way {@link
+	 *        CachedConnection#getConnectTimeoutSeconds()} reads it; 0 for an attempt with no bound of
+	 *        its own.
+	 * @param poolTimeoutSeconds the deadline of the whole wait, the way {@link
+	 *        CachedConnection#getPoolTimeoutSeconds()} reads it; 0 for no deadline of its own.
+	 */
+	Connection newCatalogConnection(long budgetDeadline, long connectTimeoutSeconds, long poolTimeoutSeconds)
+			throws SQLException {
 		// poolKey() rather than the configuration as it stands, for the reason newStampConnection()
 		// gives: this connection is not pooled, but it is a connection to the database of this
 		// storage, and db-directory may be changed on a running backend. Reading it again here would
@@ -1742,8 +1771,6 @@
 		// rows in one database and tables in another, which is #888 again by another route (#878)
 		final String connectionString=poolKey();
 		final CachedConnection.ConnectDialect dialect=CachedConnection.ConnectDialect.of(connectionString);
-		final long connectTimeoutSeconds=CachedConnection.getConnectTimeoutSeconds();
-		final long poolTimeoutSeconds=CachedConnection.getPoolTimeoutSeconds();
 		final long startedAt=System.currentTimeMillis();
 		final long poolDeadline=CachedConnection.deadlineOf(startedAt, poolTimeoutSeconds);
 		// the deadline of the whole wait, which is the shorter of the pool's own and what is left of

--
Gitblit v1.10.0