diff --git a/README.md b/README.md index 3508562a..545a0179 100644 --- a/README.md +++ b/README.md @@ -131,7 +131,7 @@ It is a boolean value. ⌚``connectionTimeout``
This property controls the maximum number of milliseconds that a client (that's you) will wait for a connection from the pool. If this time is exceeded without a connection becoming -available, a SQLException will be thrown. 1000ms is the minimum value. +available, a SQLException will be thrown. Lowest acceptable connection timeout is 250 ms. *Default: 30000 (30 seconds)* ⌚``idleTimeout``
@@ -254,14 +254,13 @@ class such as ``TRANSACTION_READ_COMMITTED``, ``TRANSACTION_REPEATABLE_READ``, e ⌚``validationTimeout``
This property controls the maximum amount of time that a connection will be tested for aliveness. -This value must be less than the ``connectionTimeout``. The lowest accepted validation timeout is -1000ms (1 second). +This value must be less than the ``connectionTimeout``. Lowest acceptable validation timeout is 250 ms. *Default: 5000* ⌚``leakDetectionThreshold``
This property controls the amount of time that a connection can be out of the pool before a message is logged indicating a possible connection leak. A value of 0 means leak detection -is disabled. Lowest acceptable value for enabling leak detection is 2000 (2 secs). +is disabled. Lowest acceptable value for enabling leak detection is 2000 (2 seconds). *Default: 0* ➡``dataSource``
diff --git a/src/main/java/com/zaxxer/hikari/pool/HikariPool.java b/src/main/java/com/zaxxer/hikari/pool/HikariPool.java index 4df7f62f..51adefc9 100644 --- a/src/main/java/com/zaxxer/hikari/pool/HikariPool.java +++ b/src/main/java/com/zaxxer/hikari/pool/HikariPool.java @@ -104,6 +104,8 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL this.totalConnections = new AtomicInteger(); this.suspendResumeLock = config.isAllowPoolSuspension() ? new SuspendResumeLock() : SuspendResumeLock.FAUX_LOCK; + checkFailFast(); + if (config.getMetricsTrackerFactory() != null) { setMetricsTrackerFactory(config.getMetricsTrackerFactory()); } @@ -115,8 +117,6 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL registerMBeans(this); - checkFailFast(); - ThreadFactory threadFactory = config.getThreadFactory(); this.addConnectionExecutor = createThreadPoolExecutor(config.getMaximumPoolSize(), poolName + " connection adder", threadFactory, new ThreadPoolExecutor.DiscardPolicy()); this.closeConnectionExecutor = createThreadPoolExecutor(config.getMaximumPoolSize(), poolName + " connection closer", threadFactory, new ThreadPoolExecutor.CallerRunsPolicy()); @@ -204,11 +204,10 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL softEvictConnections(); - if (addConnectionExecutor != null) { - addConnectionExecutor.shutdown(); - addConnectionExecutor.awaitTermination(5L, SECONDS); - } - if (config.getScheduledExecutorService() == null && houseKeepingExecutorService != null) { + addConnectionExecutor.shutdown(); + addConnectionExecutor.awaitTermination(5L, SECONDS); + + if (config.getScheduledExecutorService() == null) { houseKeepingExecutorService.shutdown(); houseKeepingExecutorService.awaitTermination(5L, SECONDS); } @@ -230,10 +229,9 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL } shutdownNetworkTimeoutExecutor(); - if (closeConnectionExecutor != null) { - closeConnectionExecutor.shutdown(); - closeConnectionExecutor.awaitTermination(5L, SECONDS); - } + + closeConnectionExecutor.shutdown(); + closeConnectionExecutor.awaitTermination(5L, SECONDS); } finally { logPoolState("After closing "); @@ -383,16 +381,16 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL } /** - * Release a connection back to the pool, or permanently close it if it is broken. + * Recycle PoolEntry (add back to the pool) * - * @param poolEntry the PoolBagEntry to release back to the pool + * @param poolEntry the PoolEntry to recycle */ @Override - final void releaseConnection(final PoolEntry poolEntry) + final void recycle(final PoolEntry poolEntry) { metricsTracker.recordConnectionUsage(poolEntry); - connectionBag.requite(poolEntry); + connectionBag.recycle(poolEntry); } /** @@ -506,13 +504,6 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL newConnection().close(); } catch (Throwable e) { - try { - shutdown(); - } - catch (Throwable ex) { - e.addSuppressed(ex); - } - throw new PoolInitializationException(e); } } @@ -520,13 +511,10 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL private void softEvictConnection(final PoolEntry poolEntry, final String reason, final boolean owner) { + poolEntry.markEvicted(); if (owner || connectionBag.reserve(poolEntry)) { - poolEntry.markEvicted(); closeConnection(poolEntry, reason); } - else { - poolEntry.markEvicted(); - } } private PoolStats getPoolStats() @@ -609,7 +597,7 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL // Detect retrograde time, allowing +128ms as per NTP spec. if (clockSource.plusMillis(now, 128) < clockSource.plusMillis(previous, HOUSEKEEPING_PERIOD_MS)) { LOGGER.warn("{} - Retrograde clock change detected (housekeeper delta={}), soft-evicting connections from pool.", - clockSource.elapsedDisplayString(previous, now), poolName); + poolName, clockSource.elapsedDisplayString(previous, now)); previous = now; softEvictConnections(); fillPool(); @@ -617,7 +605,7 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL } else if (now > clockSource.plusMillis(previous, (3 * HOUSEKEEPING_PERIOD_MS) / 2)) { // No point evicting for forward clock motion, this merely accelerates connection retirement anyway - LOGGER.warn("{} - Thread starvation or clock leap detected (housekeeper delta={}).", clockSource.elapsedDisplayString(previous, now), poolName); + LOGGER.warn("{} - Thread starvation or clock leap detected (housekeeper delta={}).", poolName, clockSource.elapsedDisplayString(previous, now)); } previous = now; diff --git a/src/main/java/com/zaxxer/hikari/pool/PoolBase.java b/src/main/java/com/zaxxer/hikari/pool/PoolBase.java index 9a282588..2421c1a6 100644 --- a/src/main/java/com/zaxxer/hikari/pool/PoolBase.java +++ b/src/main/java/com/zaxxer/hikari/pool/PoolBase.java @@ -98,7 +98,7 @@ abstract class PoolBase return poolName; } - abstract void releaseConnection(final PoolEntry poolEntry); + abstract void recycle(final PoolEntry poolEntry); // *********************************************************************** // JDBC methods @@ -239,7 +239,7 @@ abstract class PoolBase mBeanServer.registerMBean(hikariPool, beanPoolName); } else { - LOGGER.error("{} - You cannot use the same pool name for separate pool instances.", poolName); + LOGGER.error("{} - is already registered.", poolName); } } catch (Exception e) { @@ -265,6 +265,9 @@ abstract class PoolBase mBeanServer.unregisterMBean(beanConfigName); mBeanServer.unregisterMBean(beanPoolName); } + else { + LOGGER.error("{} - is not registered.", poolName); + } } catch (Exception e) { LOGGER.warn("{} - Failed to unregister management beans.", poolName, e); @@ -299,7 +302,7 @@ abstract class PoolBase } if (dataSource != null) { - setLoginTimeout(dataSource, connectionTimeout); + setLoginTimeout(dataSource); createNetworkTimeoutExecutor(dataSource, dsClassName, jdbcUrl); } @@ -370,23 +373,17 @@ abstract class PoolBase private void checkDriverSupport(final Connection connection) throws SQLException { if (!isValidChecked) { - if (isUseJdbc4Validation) { - try { + try { + if (isUseJdbc4Validation) { connection.isValid(1); } - catch (Throwable e) { - LOGGER.error("{} - Failed to execute isValid() for connection, configure connection test query. ({})", poolName, e.getMessage()); - throw e; - } - } - else { - try { + else { executeSql(connection, config.getConnectionTestQuery(), false); } - catch (Throwable e) { - LOGGER.error("{} - Failed to execute connection test query. ({})", poolName, e.getMessage()); - throw e; - } + } + catch (Throwable e) { + LOGGER.error("{} - Failed to execute" + (isUseJdbc4Validation ? " isValid() for connection, configure" : "") + " connection test query. ({})", poolName, e.getMessage()); + throw e; } defaultTransactionIsolation = connection.getTransactionIsolation(); @@ -441,7 +438,7 @@ abstract class PoolBase if (isNetworkTimeoutSupported == UNINITIALIZED) { isNetworkTimeoutSupported = FALSE; - LOGGER.info("{} - Driver does not support get/set network timeout for connections. ({})", poolName, e.getMessage()); + LOGGER.info("{} - Failed to get/set network timeout for connection. ({})", poolName, e.getMessage()); if (validationTimeout < SECONDS.toMillis(1)) { LOGGER.warn("{} - A validationTimeout of less than 1 second cannot be honored on drivers without setNetworkTimeout() support.", poolName); } @@ -519,9 +516,8 @@ abstract class PoolBase * Set the loginTimeout on the specified DataSource. * * @param dataSource the DataSource - * @param connectionTimeout the timeout in milliseconds */ - private void setLoginTimeout(final DataSource dataSource, final long connectionTimeout) + private void setLoginTimeout(final DataSource dataSource) { if (connectionTimeout != Integer.MAX_VALUE) { try { diff --git a/src/main/java/com/zaxxer/hikari/pool/PoolEntry.java b/src/main/java/com/zaxxer/hikari/pool/PoolEntry.java index 8a82ec3b..e8af0f98 100644 --- a/src/main/java/com/zaxxer/hikari/pool/PoolEntry.java +++ b/src/main/java/com/zaxxer/hikari/pool/PoolEntry.java @@ -84,7 +84,7 @@ final class PoolEntry implements IConcurrentBagEntry { if (connection != null) { this.lastAccessed = lastAccessed; - hikariPool.releaseConnection(this); + hikariPool.recycle(this); } } diff --git a/src/main/java/com/zaxxer/hikari/util/ConcurrentBag.java b/src/main/java/com/zaxxer/hikari/util/ConcurrentBag.java index 88d9fd4f..c44000f1 100644 --- a/src/main/java/com/zaxxer/hikari/util/ConcurrentBag.java +++ b/src/main/java/com/zaxxer/hikari/util/ConcurrentBag.java @@ -140,7 +140,7 @@ public class ConcurrentBag implements AutoCloseab // Otherwise, scan the shared list ... for maximum of timeout timeout = timeUnit.toNanos(timeout); Future addItemFuture = null; - final long startScan = System.nanoTime(); + final long startTime = System.nanoTime(); final long originTimeout = timeout; long startSeq; waiters.incrementAndGet(); @@ -165,7 +165,7 @@ public class ConcurrentBag implements AutoCloseab addItemFuture = listener.addBagItem(); } - timeout = originTimeout - (System.nanoTime() - startScan); + timeout = originTimeout - (System.nanoTime() - startTime); } while (timeout > 10_000L && synchronizer.waitUntilSequenceExceeded(startSeq, timeout)); } finally { @@ -177,14 +177,14 @@ public class ConcurrentBag implements AutoCloseab /** * This method will return a borrowed object to the bag. Objects - * that are borrowed from the bag but never "requited" will result + * that are borrowed from the bag but never "recycled" will result * in a memory leak. * * @param bagEntry the value to return to the bag * @throws NullPointerException if value is null - * @throws IllegalStateException if the requited value was not borrowed from the bag + * @throws IllegalStateException if the bagEntry was not borrowed from the bag */ - public void requite(final T bagEntry) + public void recycle(final T bagEntry) { bagEntry.lazySet(STATE_NOT_IN_USE);