diff --git a/core/src/main/java/com/zaxxer/hikari/HikariPool.java b/core/src/main/java/com/zaxxer/hikari/HikariPool.java index 91979590..315dc04a 100644 --- a/core/src/main/java/com/zaxxer/hikari/HikariPool.java +++ b/core/src/main/java/com/zaxxer/hikari/HikariPool.java @@ -101,7 +101,8 @@ public final class HikariPool implements HikariPoolMBean long idleTimeout = configuration.getIdleTimeout(); if (idleTimeout > 0 || configuration.getMaxLifetime() > 0) { - houseKeepingTimer.scheduleAtFixedRate(new HouseKeeper(), TimeUnit.SECONDS.toMillis(30), TimeUnit.SECONDS.toMillis(30)); + long delayPeriod = Long.getLong("com.zaxxer.hikari.housekeeping.period", TimeUnit.SECONDS.toMillis(30)); + houseKeepingTimer.scheduleAtFixedRate(new HouseKeeper(), delayPeriod * 2, delayPeriod); } fillPool(); @@ -126,24 +127,15 @@ public final class HikariPool implements HikariPoolMBean IHikariConnectionProxy connectionProxy = idleConnections.poll(timeout, TimeUnit.MILLISECONDS); if (connectionProxy == null) { + // We timed out... break and throw exception break; } idleConnectionCount.decrementAndGet(); - final long maxLifetime = configuration.getMaxLifetime(); - if (maxLifetime > 0 && start - connectionProxy.getCreationTime() > maxLifetime) - { - // Throw away the connection that has passed its lifetime, try again - closeConnection(connectionProxy); - timeout -= (System.currentTimeMillis() - start); - continue; - } - connectionProxy.unclose(); - Connection connection = (Connection) connectionProxy; - if (!isConnectionAlive(connection, timeout)) + if (!isConnectionAlive(connectionProxy, timeout)) { // Throw away the dead connection, try again closeConnection(connectionProxy); @@ -156,9 +148,9 @@ public final class HikariPool implements HikariPoolMBean connectionProxy.captureStack(leakDetectionThreshold, houseKeepingTimer); } - connection.clearWarnings(); + connectionProxy.clearWarnings(); - return connection; + return connectionProxy; } while (timeout > 0); @@ -189,8 +181,6 @@ public final class HikariPool implements HikariPoolMBean { if (!connectionProxy.isBrokenConnection()) { - connectionProxy.markLastAccess(); - idleConnectionCount.incrementAndGet(); idleConnections.put(connectionProxy); } @@ -335,7 +325,7 @@ public final class HikariPool implements HikariPoolMBean transactionIsolation = connection.getTransactionIsolation(); } - boolean alive = isConnectionAlive((Connection) proxyConnection, configuration.getConnectionTimeout()); + boolean alive = isConnectionAlive(proxyConnection, configuration.getConnectionTimeout()); if (!alive) { // This will be caught below... diff --git a/core/src/main/java/com/zaxxer/hikari/proxy/ConnectionProxy.java b/core/src/main/java/com/zaxxer/hikari/proxy/ConnectionProxy.java index 7487219f..20a155e4 100644 --- a/core/src/main/java/com/zaxxer/hikari/proxy/ConnectionProxy.java +++ b/core/src/main/java/com/zaxxer/hikari/proxy/ConnectionProxy.java @@ -45,13 +45,13 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy private final ArrayList openStatements; private final HikariPool parentPool; - private volatile boolean isClosed; + private boolean isClosed; + private boolean forceClose; private final long creationTime; - private boolean forceClose; - private long lastAccess; + private volatile long lastAccess; - private StackTraceElement[] stackTrace; + private StackTraceElement[] leakTrace; private TimerTask leakTask; // static initializer @@ -73,7 +73,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy this.delegate = connection; creationTime = lastAccess = System.currentTimeMillis(); - openStatements = new ArrayList(64); + openStatements = new ArrayList(); } public final void unregisterStatement(Object statement) @@ -97,11 +97,6 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy return lastAccess; } - public final void markLastAccess() - { - this.lastAccess = System.currentTimeMillis(); - } - public final void unclose() { isClosed = false; @@ -115,10 +110,10 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy public final void captureStack(long leakDetectionThreshold, Timer scheduler) { StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - stackTrace = new StackTraceElement[trace.length - 4]; - System.arraycopy(trace, 4, stackTrace, 0, stackTrace.length); + leakTrace = new StackTraceElement[trace.length - 4]; + System.arraycopy(trace, 4, leakTrace, 0, leakTrace.length); - leakTask = new LeakTask(stackTrace, leakDetectionThreshold); + leakTask = new LeakTask(leakTrace, leakDetectionThreshold); scheduler.schedule(leakTask, leakDetectionThreshold); } @@ -196,6 +191,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy { isClosed = true; openStatements.clear(); + lastAccess = System.currentTimeMillis(); parentPool.releaseConnection(this); } } diff --git a/core/src/main/java/com/zaxxer/hikari/proxy/IHikariConnectionProxy.java b/core/src/main/java/com/zaxxer/hikari/proxy/IHikariConnectionProxy.java index 2074ca3d..8f15e0e6 100644 --- a/core/src/main/java/com/zaxxer/hikari/proxy/IHikariConnectionProxy.java +++ b/core/src/main/java/com/zaxxer/hikari/proxy/IHikariConnectionProxy.java @@ -40,8 +40,6 @@ public interface IHikariConnectionProxy extends Connection long getLastAccess(); - void markLastAccess(); - /* Leak Detection API */ void captureStack(long leakThreshold, Timer houseKeepingTimer); } diff --git a/core/src/test/java/com/zaxxer/hikari/CreationTest.java b/core/src/test/java/com/zaxxer/hikari/CreationTest.java index f400d93d..d1610cac 100644 --- a/core/src/test/java/com/zaxxer/hikari/CreationTest.java +++ b/core/src/test/java/com/zaxxer/hikari/CreationTest.java @@ -95,8 +95,12 @@ public class CreationTest config.setConnectionTestQuery("VALUES 1"); config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); + System.setProperty("com.zaxxer.hikari.housekeeping.period", "350"); + HikariDataSource ds = new HikariDataSource(config); + System.clearProperty("com.zaxxer.hikari.housekeeping.period"); + config.setMaxLifetime(500); Assert.assertSame("Totals connections not as expected", 1, ds.pool.getTotalConnections()); @@ -115,7 +119,7 @@ public class CreationTest Assert.assertSame("Expected the same connection", connection, connection2); connection2.close(); - Thread.sleep(501); + Thread.sleep(800); connection2 = ds.getConnection(); Assert.assertNotSame("Expected a different connection", connection, connection2);