diff --git a/src/main/java/com/zaxxer/hikari/pool/HikariPool.java b/src/main/java/com/zaxxer/hikari/pool/HikariPool.java index c3fcd896..b8b7a32d 100644 --- a/src/main/java/com/zaxxer/hikari/pool/HikariPool.java +++ b/src/main/java/com/zaxxer/hikari/pool/HikariPool.java @@ -194,7 +194,7 @@ public class HikariPool implements HikariPoolMBean, IBagStateListener else { metricsContext.setConnectionLastOpen(bagEntry, now); metricsContext.stop(); - return ProxyFactory.getProxyConnection(this, bagEntry, leakTask.start(bagEntry), now); + return ProxyFactory.getProxyConnection(bagEntry, leakTask.start(bagEntry), now); } } while (timeout > 0L); diff --git a/src/main/java/com/zaxxer/hikari/pool/PoolBagEntry.java b/src/main/java/com/zaxxer/hikari/pool/PoolBagEntry.java index a54c696e..ca867202 100644 --- a/src/main/java/com/zaxxer/hikari/pool/PoolBagEntry.java +++ b/src/main/java/com/zaxxer/hikari/pool/PoolBagEntry.java @@ -16,11 +16,13 @@ package com.zaxxer.hikari.pool; import java.sql.Connection; +import java.sql.Statement; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import com.zaxxer.hikari.util.FastList; import com.zaxxer.hikari.util.IConcurrentBagEntry; /** @@ -31,6 +33,8 @@ import com.zaxxer.hikari.util.IConcurrentBagEntry; public final class PoolBagEntry implements IConcurrentBagEntry { public final AtomicInteger state = new AtomicInteger(); + public final FastList openStatements; + public final HikariPool parentPool; public Connection connection; public long lastAccess; @@ -43,9 +47,11 @@ public final class PoolBagEntry implements IConcurrentBagEntry public PoolBagEntry(final Connection connection, final HikariPool pool) { this.connection = connection; + this.parentPool = pool; this.lastAccess = System.currentTimeMillis(); + this.openStatements = new FastList(Statement.class, 16); - final long variance = pool.configuration.getMaxLifetime() > 300_000 ? ThreadLocalRandom.current().nextLong(100_000) : 0; + final long variance = pool.configuration.getMaxLifetime() > 60_000 ? ThreadLocalRandom.current().nextLong(10_000) : 0; final long maxLifetime = pool.configuration.getMaxLifetime() - variance; if (maxLifetime > 0) { endOfLife = pool.houseKeepingExecutorService.schedule(new Runnable() { diff --git a/src/main/java/com/zaxxer/hikari/proxy/ConnectionProxy.java b/src/main/java/com/zaxxer/hikari/proxy/ConnectionProxy.java index a94b478c..9f27ae9d 100644 --- a/src/main/java/com/zaxxer/hikari/proxy/ConnectionProxy.java +++ b/src/main/java/com/zaxxer/hikari/proxy/ConnectionProxy.java @@ -29,7 +29,6 @@ import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.zaxxer.hikari.pool.HikariPool; import com.zaxxer.hikari.pool.LeakTask; import com.zaxxer.hikari.pool.PoolBagEntry; import com.zaxxer.hikari.util.FastList; @@ -47,7 +46,6 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy protected Connection delegate; private final LeakTask leakTask; - private final HikariPool parentPool; private final PoolBagEntry bagEntry; private final FastList openStatements; @@ -72,14 +70,13 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy SQL_ERRORS.add("JZ0C1"); // Sybase disconnect error } - protected ConnectionProxy(final HikariPool pool, final PoolBagEntry bagEntry, final LeakTask leakTask, final long now) { - this.parentPool = pool; + protected ConnectionProxy(final PoolBagEntry bagEntry, final LeakTask leakTask, final long now) { this.bagEntry = bagEntry; - this.delegate = bagEntry.connection; this.leakTask = leakTask; - this.lastAccess = now; - this.openStatements = new FastList(Statement.class, 16); + + this.delegate = bagEntry.connection; + this.openStatements = bagEntry.openStatements; } /** {@inheritDoc} */ @@ -112,8 +109,8 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy boolean isForceClose = sqlState.startsWith("08") | SQL_ERRORS.contains(sqlState); if (isForceClose) { bagEntry.evicted = true; - LOGGER.warn("Connection {} ({}) marked as broken because of SQLSTATE({}), ErrorCode({}).", delegate, - parentPool, sqlState, sqle.getErrorCode(), sqle); + LOGGER.warn("Connection {} ({}) marked as broken because of SQLSTATE({}), ErrorCode({}).", + delegate, bagEntry.parentPool, sqlState, sqle.getErrorCode(), sqle); } else { SQLException nse = sqle.getNextException(); @@ -153,19 +150,19 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy private final void resetConnectionState() throws SQLException { if (isReadOnlyDirty) { - delegate.setReadOnly(parentPool.isReadOnly); + delegate.setReadOnly(bagEntry.parentPool.isReadOnly); } if (isAutoCommitDirty) { - delegate.setAutoCommit(parentPool.isAutoCommit); + delegate.setAutoCommit(bagEntry.parentPool.isAutoCommit); } if (isTransactionIsolationDirty) { - delegate.setTransactionIsolation(parentPool.transactionIsolation); + delegate.setTransactionIsolation(bagEntry.parentPool.transactionIsolation); } - if (isCatalogDirty && parentPool.catalog != null) { - delegate.setCatalog(parentPool.catalog); + if (isCatalogDirty && bagEntry.parentPool.catalog != null) { + delegate.setCatalog(bagEntry.parentPool.catalog); } lastAccess = System.currentTimeMillis(); @@ -218,7 +215,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy finally { delegate = ClosedConnection.CLOSED_CONNECTION; bagEntry.lastAccess = this.lastAccess; - parentPool.releaseConnection(bagEntry); + bagEntry.parentPool.releaseConnection(bagEntry); } } } @@ -347,7 +344,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy { delegate.setAutoCommit(autoCommit); isConnectionStateDirty = true; - isAutoCommitDirty = (autoCommit != parentPool.isAutoCommit); + isAutoCommitDirty = (autoCommit != bagEntry.parentPool.isAutoCommit); } /** {@inheritDoc} */ @@ -356,7 +353,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy { delegate.setReadOnly(readOnly); isConnectionStateDirty = true; - isReadOnlyDirty = (readOnly != parentPool.isReadOnly); + isReadOnlyDirty = (readOnly != bagEntry.parentPool.isReadOnly); } /** {@inheritDoc} */ @@ -365,7 +362,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy { delegate.setTransactionIsolation(level); isConnectionStateDirty = true; - isTransactionIsolationDirty = (level != parentPool.transactionIsolation); + isTransactionIsolationDirty = (level != bagEntry.parentPool.transactionIsolation); } /** {@inheritDoc} */ @@ -374,7 +371,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy { delegate.setCatalog(catalog); isConnectionStateDirty = true; - isCatalogDirty = (catalog != null && !catalog.equals(parentPool.catalog)) || (catalog == null && parentPool.catalog != null); + isCatalogDirty = (catalog != null && !catalog.equals(bagEntry.parentPool.catalog)) || (catalog == null && bagEntry.parentPool.catalog != null); } /** {@inheritDoc} */ diff --git a/src/main/java/com/zaxxer/hikari/proxy/ProxyFactory.java b/src/main/java/com/zaxxer/hikari/proxy/ProxyFactory.java index 8f62c2f5..6097b7ce 100644 --- a/src/main/java/com/zaxxer/hikari/proxy/ProxyFactory.java +++ b/src/main/java/com/zaxxer/hikari/proxy/ProxyFactory.java @@ -22,7 +22,6 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; -import com.zaxxer.hikari.pool.HikariPool; import com.zaxxer.hikari.pool.LeakTask; import com.zaxxer.hikari.pool.PoolBagEntry; @@ -42,12 +41,12 @@ public final class ProxyFactory /** * Create a proxy for the specified {@link Connection} instance. * - * @param pool the {@link HikariPool} that will own this proxy * @param bagEntry the PoolBagEntry entry for this proxy * @param leakTask a leak detetection task + * @param now current timestamp in milliseconds * @return a proxy that wraps the specified {@link Connection} */ - public static IHikariConnectionProxy getProxyConnection(final HikariPool pool, final PoolBagEntry bagEntry, final LeakTask leakTask, final long now) + public static IHikariConnectionProxy getProxyConnection(final PoolBagEntry bagEntry, final LeakTask leakTask, final long now) { // Body is injected by JavassistProxyFactory return null;