diff --git a/src/main/java/com/zaxxer/hikari/pool/HikariPool.java b/src/main/java/com/zaxxer/hikari/pool/HikariPool.java index bc815496..df465258 100644 --- a/src/main/java/com/zaxxer/hikari/pool/HikariPool.java +++ b/src/main/java/com/zaxxer/hikari/pool/HikariPool.java @@ -106,9 +106,6 @@ public class HikariPool implements HikariPoolMBean, IBagStateListener private final SuspendResumeLock suspendResumeLock; private final AtomicReference lastConnectionFailure; - private final String username; - private final String password; - private volatile MetricsTracker metricsTracker; private volatile boolean isRecordMetrics; @@ -120,8 +117,6 @@ public class HikariPool implements HikariPoolMBean, IBagStateListener public HikariPool(HikariConfig config) { this.configuration = config; - this.username = config.getUsername(); - this.password = config.getPassword(); this.poolUtils = new PoolUtilities(config); this.dataSource = poolUtils.initializeDataSource(); @@ -147,8 +142,8 @@ public class HikariPool implements HikariPoolMBean, IBagStateListener this.addConnectionExecutor = createThreadPoolExecutor(config.getMaximumPoolSize(), "Hikari connection filler (pool " + config.getPoolName() + ")", config.getThreadFactory(), new ThreadPoolExecutor.DiscardPolicy()); this.closeConnectionExecutor = createThreadPoolExecutor(4, "Hikari connection closer (pool " + config.getPoolName() + ")", config.getThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy()); - ThreadFactory threadFactory = config.getThreadFactory() != null ? config.getThreadFactory() : new DefaultThreadFactory("Hikari housekeeper (pool " + config.getPoolName() + ")", true); if (config.getScheduledExecutorService() == null) { + ThreadFactory threadFactory = config.getThreadFactory() != null ? config.getThreadFactory() : new DefaultThreadFactory("Hikari housekeeper (pool " + config.getPoolName() + ")", true); this.houseKeepingExecutorService = new ScheduledThreadPoolExecutor(1, threadFactory, new ThreadPoolExecutor.DiscardPolicy()); this.houseKeepingExecutorService.scheduleAtFixedRate(new HouseKeeper(), HOUSEKEEPING_PERIOD_MS, HOUSEKEEPING_PERIOD_MS, TimeUnit.MILLISECONDS); this.houseKeepingExecutorService.setExecuteExistingDelayedTasksAfterShutdownPolicy(false); @@ -490,38 +485,43 @@ public class HikariPool implements HikariPoolMBean, IBagStateListener */ private boolean addConnection() { + final HikariConfig config = configuration; + // Speculative increment of totalConnections with expectation of success - if (totalConnections.incrementAndGet() > configuration.getMaximumPoolSize()) { + if (totalConnections.incrementAndGet() > config.getMaximumPoolSize()) { totalConnections.decrementAndGet(); // Pool is maxed out, so undo speculative increment of totalConnections - lastConnectionFailure.set(new SQLException("HikariCP pool " + configuration.getPoolName() +" is at maximum capacity")); + lastConnectionFailure.set(new SQLException("Hikari pool " + config.getPoolName() +" is at maximum capacity")); return true; } Connection connection = null; try { + String username = config.getUsername(); + String password = config.getPassword(); + connection = (username == null && password == null) ? dataSource.getConnection() : dataSource.getConnection(username, password); if (isUseJdbc4Validation && !poolUtils.isJdbc4ValidationSupported(connection)) { throw new SQLException("JDBC4 Connection.isValid() method not supported, connection test query must be configured"); } - + final int originalTimeout = poolUtils.getAndSetNetworkTimeout(connection, connectionTimeout); - + transactionIsolation = (transactionIsolation < 0 ? connection.getTransactionIsolation() : transactionIsolation); - - poolUtils.setupConnection(connection, configuration.getConnectionInitSql(), isAutoCommit, isReadOnly, transactionIsolation, catalog); + poolUtils.setupConnection(connection, config.getConnectionInitSql(), isAutoCommit, isReadOnly, transactionIsolation, catalog); + poolUtils.setNetworkTimeout(connection, originalTimeout); connectionBag.add(new PoolBagEntry(connection, this)); lastConnectionFailure.set(null); - LOGGER.debug("Connection {} added to pool {} ", connection, configuration.getPoolName()); + LOGGER.debug("Connection {} added to pool {} ", connection, config.getPoolName()); return true; } catch (Exception e) { totalConnections.decrementAndGet(); // We failed, so undo speculative increment of totalConnections lastConnectionFailure.set(e); if (poolState == POOL_NORMAL) { - LOGGER.debug("Connection attempt to database in pool {} failed: {}", configuration.getPoolName(), e.getMessage(), e); + LOGGER.debug("Connection attempt to database in pool {} failed: {}", config.getPoolName(), e.getMessage(), e); } poolUtils.quietlyCloseConnection(connection, "exception during connection creation"); return false; diff --git a/src/main/java/com/zaxxer/hikari/pool/PoolUtilities.java b/src/main/java/com/zaxxer/hikari/pool/PoolUtilities.java index f074a38f..41733f90 100644 --- a/src/main/java/com/zaxxer/hikari/pool/PoolUtilities.java +++ b/src/main/java/com/zaxxer/hikari/pool/PoolUtilities.java @@ -8,6 +8,7 @@ import java.sql.Statement; import java.util.Properties; import java.util.concurrent.Executor; import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -98,7 +99,7 @@ public final class PoolUtilities if (dataSource != null) { setLoginTimeout(dataSource, config.getConnectionTimeout()); - createNetworkTimeoutExecutor(dataSource, dsClassName, jdbcUrl); + createNetworkTimeoutExecutor(dataSource, dsClassName, jdbcUrl, Math.min(config.getValidationTimeout(), TimeUnit.SECONDS.toMillis(5))); } return dataSource; @@ -234,7 +235,7 @@ public final class PoolUtilities } // Temporary hack for MySQL issue: http://bugs.mysql.com/bug.php?id=75615 - private void createNetworkTimeoutExecutor(final DataSource dataSource, final String dsClassName, final String jdbcUrl) + private void createNetworkTimeoutExecutor(final DataSource dataSource, final String dsClassName, final String jdbcUrl, final long keepAliveMs) { if ((dsClassName != null && dsClassName.contains("Mysql")) || (jdbcUrl != null && jdbcUrl.contains("mysql")) || @@ -242,8 +243,11 @@ public final class PoolUtilities netTimeoutExecutor = new SynchronousExecutor(); } else { - netTimeoutExecutor = Executors.newCachedThreadPool(new DefaultThreadFactory("Hikari JDBC-timeout executor", true)); - ((ThreadPoolExecutor) netTimeoutExecutor).allowCoreThreadTimeOut(true); + ThreadFactory threadFactory = config.getThreadFactory() != null ? config.getThreadFactory() : new DefaultThreadFactory("Hikari JDBC-timeout executor", true); + ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newCachedThreadPool(threadFactory); + executor.allowCoreThreadTimeOut(true); + executor.setKeepAliveTime(keepAliveMs, TimeUnit.MILLISECONDS); + netTimeoutExecutor = executor; } }