From 7bab1a8ccdd3fad2ed9a332e469f68ce9e5c4ec1 Mon Sep 17 00:00:00 2001 From: Brett Wooldridge Date: Tue, 29 Nov 2016 10:31:49 +0900 Subject: [PATCH] Fixes #770 by adding a new property initializationFailTimeout and deprecating initializationFailFast. --- .../com/zaxxer/hikari/pool/HikariPool.java | 14 ++-- .../java/com/zaxxer/hikari/pool/PoolBase.java | 68 ++++++++++++------- .../pool/ConnectionRaceConditionTest.java | 2 +- .../hikari/pool/HouseKeeperCleanupTest.java | 2 +- .../com/zaxxer/hikari/pool/RampUpDown.java | 2 +- .../com/zaxxer/hikari/pool/ShutdownTest.java | 16 ++--- .../zaxxer/hikari/pool/TestConcurrentBag.java | 2 +- .../pool/TestConnectionTimeoutRetry.java | 2 +- .../zaxxer/hikari/pool/TestConnections.java | 21 +++--- .../com/zaxxer/hikari/pool/TestMetrics.java | 4 +- .../com/zaxxer/hikari/pool/UnwrapTest.java | 4 +- 11 files changed, 80 insertions(+), 57 deletions(-) diff --git a/src/main/java/com/zaxxer/hikari/pool/HikariPool.java b/src/main/java/com/zaxxer/hikari/pool/HikariPool.java index c57b1c4e..b0aae455 100644 --- a/src/main/java/com/zaxxer/hikari/pool/HikariPool.java +++ b/src/main/java/com/zaxxer/hikari/pool/HikariPool.java @@ -455,7 +455,7 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL } catch (Exception e) { if (poolState == POOL_NORMAL) { - LOGGER.debug("{} - Cannot acquire connection from data source", poolName, e); + LOGGER.debug("{} - Cannot acquire connection from data source", poolName, (e instanceof ConnectionSetupException ? e.getCause() : e)); } return null; } @@ -508,26 +508,24 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL */ private void checkFailFast() { - if (config.getInitializationFailTimeout() == 0) { - return; - } - final long startTime = clockSource.currentTime(); - boolean acquired = false; Throwable throwable = new SQLTimeoutException("HikariCP was unable to initialize connections in pool " + poolName); do { try (Connection connection = newConnection()) { - acquired = true; if (!connection.getAutoCommit()) { connection.commit(); } return; } + catch (ConnectionSetupException e) { + throwable = e.getCause(); + break; + } catch (Throwable t) { throwable = t; quietlySleep(1000L); } - } while (!acquired && clockSource.elapsedMillis(startTime) < config.getInitializationFailTimeout()); + } while (clockSource.elapsedMillis(startTime) < config.getInitializationFailTimeout()); throw new PoolInitializationException(throwable); } diff --git a/src/main/java/com/zaxxer/hikari/pool/PoolBase.java b/src/main/java/com/zaxxer/hikari/pool/PoolBase.java index 21d3a8bb..f4e8c236 100644 --- a/src/main/java/com/zaxxer/hikari/pool/PoolBase.java +++ b/src/main/java/com/zaxxer/hikari/pool/PoolBase.java @@ -348,14 +348,19 @@ abstract class PoolBase return connection; } catch (Exception e) { + Exception cause = e; + if (e instanceof ConnectionSetupException) { + cause = (Exception) e.getCause(); + } + if (connection != null) { quietlyCloseConnection(connection, "(Failed to create/setup connection)"); } else if (getLastConnectionFailure() == null) { - LOGGER.debug("{} - Failed to create/setup connection: {}", poolName, e.getMessage()); + LOGGER.debug("{} - Failed to create/setup connection: {}", poolName, cause.getMessage()); } - lastConnectionFailure.set(e); + lastConnectionFailure.set(cause); throw e; } } @@ -366,31 +371,36 @@ abstract class PoolBase * @param connection a Connection * @throws SQLException thrown from driver */ - private void setupConnection(final Connection connection) throws SQLException + private void setupConnection(final Connection connection) throws ConnectionSetupException { - if (networkTimeout == UNINITIALIZED) { - networkTimeout = getAndSetNetworkTimeout(connection, validationTimeout); - } - else { - setNetworkTimeout(connection, validationTimeout); - } - - connection.setReadOnly(isReadOnly); - connection.setAutoCommit(isAutoCommit); - - checkDriverSupport(connection); - - if (transactionIsolation != defaultTransactionIsolation) { - connection.setTransactionIsolation(transactionIsolation); + try { + if (networkTimeout == UNINITIALIZED) { + networkTimeout = getAndSetNetworkTimeout(connection, validationTimeout); + } + else { + setNetworkTimeout(connection, validationTimeout); + } + + connection.setReadOnly(isReadOnly); + connection.setAutoCommit(isAutoCommit); + + checkDriverSupport(connection); + + if (transactionIsolation != defaultTransactionIsolation) { + connection.setTransactionIsolation(transactionIsolation); + } + + if (catalog != null) { + connection.setCatalog(catalog); + } + + executeSql(connection, config.getConnectionInitSql(), true); + + setNetworkTimeout(connection, networkTimeout); } - - if (catalog != null) { - connection.setCatalog(catalog); + catch (SQLException e) { + throw new ConnectionSetupException(e); } - - executeSql(connection, config.getConnectionInitSql(), true); - - setNetworkTimeout(connection, networkTimeout); } /** @@ -590,6 +600,16 @@ abstract class PoolBase // Private Static Classes // *********************************************************************** + static class ConnectionSetupException extends Exception + { + private static final long serialVersionUID = 929872118275916521L; + + public ConnectionSetupException(Throwable t) + { + super(t); + } + } + /** * Special executor used only to work around a MySQL issue that has not been addressed. * MySQL issue: http://bugs.mysql.com/bug.php?id=75615 diff --git a/src/test/java/com/zaxxer/hikari/pool/ConnectionRaceConditionTest.java b/src/test/java/com/zaxxer/hikari/pool/ConnectionRaceConditionTest.java index d1f2ec33..e0467c6b 100644 --- a/src/test/java/com/zaxxer/hikari/pool/ConnectionRaceConditionTest.java +++ b/src/test/java/com/zaxxer/hikari/pool/ConnectionRaceConditionTest.java @@ -44,7 +44,7 @@ public class ConnectionRaceConditionTest HikariConfig config = new HikariConfig(); config.setMinimumIdle(0); config.setMaximumPoolSize(10); - config.setInitializationFailFast(false); + config.setInitializationFailTimeout(Long.MAX_VALUE); config.setConnectionTimeout(2500); config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); diff --git a/src/test/java/com/zaxxer/hikari/pool/HouseKeeperCleanupTest.java b/src/test/java/com/zaxxer/hikari/pool/HouseKeeperCleanupTest.java index e079ca96..f6a1133d 100644 --- a/src/test/java/com/zaxxer/hikari/pool/HouseKeeperCleanupTest.java +++ b/src/test/java/com/zaxxer/hikari/pool/HouseKeeperCleanupTest.java @@ -53,7 +53,7 @@ public class HouseKeeperCleanupTest HikariConfig config = new HikariConfig(); config.setMinimumIdle(0); config.setMaximumPoolSize(10); - config.setInitializationFailFast(false); + config.setInitializationFailTimeout(Long.MAX_VALUE); config.setConnectionTimeout(2500); config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); config.setScheduledExecutorService(executor); diff --git a/src/test/java/com/zaxxer/hikari/pool/RampUpDown.java b/src/test/java/com/zaxxer/hikari/pool/RampUpDown.java index 654adfb4..789b23ca 100644 --- a/src/test/java/com/zaxxer/hikari/pool/RampUpDown.java +++ b/src/test/java/com/zaxxer/hikari/pool/RampUpDown.java @@ -33,7 +33,7 @@ public class RampUpDown HikariConfig config = new HikariConfig(); config.setMinimumIdle(5); config.setMaximumPoolSize(60); - config.setInitializationFailFast(true); + config.setInitializationFailTimeout(0); config.setConnectionTestQuery("VALUES 1"); config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); diff --git a/src/test/java/com/zaxxer/hikari/pool/ShutdownTest.java b/src/test/java/com/zaxxer/hikari/pool/ShutdownTest.java index bc91f03e..83ce34ea 100644 --- a/src/test/java/com/zaxxer/hikari/pool/ShutdownTest.java +++ b/src/test/java/com/zaxxer/hikari/pool/ShutdownTest.java @@ -64,7 +64,7 @@ public class ShutdownTest HikariConfig config = new HikariConfig(); config.setMinimumIdle(0); config.setMaximumPoolSize(10); - config.setInitializationFailFast(false); + config.setInitializationFailTimeout(Long.MAX_VALUE); config.setConnectionTestQuery("VALUES 1"); config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); @@ -115,7 +115,7 @@ public class ShutdownTest HikariConfig config = new HikariConfig(); config.setMinimumIdle(10); config.setMaximumPoolSize(10); - config.setInitializationFailFast(true); + config.setInitializationFailTimeout(0); config.setConnectionTestQuery("VALUES 1"); config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); @@ -145,7 +145,7 @@ public class ShutdownTest HikariConfig config = new HikariConfig(); config.setMinimumIdle(5); config.setMaximumPoolSize(5); - config.setInitializationFailFast(true); + config.setInitializationFailTimeout(0); config.setConnectionTestQuery("VALUES 1"); config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); @@ -172,7 +172,7 @@ public class ShutdownTest HikariConfig config = new HikariConfig(); config.setMinimumIdle(10); config.setMaximumPoolSize(10); - config.setInitializationFailFast(false); + config.setInitializationFailTimeout(Long.MAX_VALUE); config.setConnectionTestQuery("VALUES 1"); config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); @@ -198,7 +198,7 @@ public class ShutdownTest HikariConfig config = new HikariConfig(); config.setMinimumIdle(5); config.setMaximumPoolSize(5); - config.setInitializationFailFast(true); + config.setInitializationFailTimeout(0); config.setConnectionTestQuery("VALUES 1"); config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); @@ -226,7 +226,7 @@ public class ShutdownTest HikariConfig config = new HikariConfig(); config.setMinimumIdle(0); config.setMaximumPoolSize(5); - config.setInitializationFailFast(true); + config.setInitializationFailTimeout(0); config.setConnectionTestQuery("VALUES 1"); config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); @@ -249,7 +249,7 @@ public class ShutdownTest config.setMaximumPoolSize(5); config.setConnectionTimeout(1000); config.setValidationTimeout(1000); - config.setInitializationFailFast(true); + config.setInitializationFailTimeout(0); config.setConnectionTestQuery("VALUES 1"); config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); @@ -267,7 +267,7 @@ public class ShutdownTest config.setMaximumPoolSize(5); config.setConnectionTimeout(1000); config.setValidationTimeout(1000); - config.setInitializationFailFast(true); + config.setInitializationFailTimeout(0); config.setConnectionTestQuery("VALUES 1"); config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); diff --git a/src/test/java/com/zaxxer/hikari/pool/TestConcurrentBag.java b/src/test/java/com/zaxxer/hikari/pool/TestConcurrentBag.java index 6fa79f36..589b5463 100644 --- a/src/test/java/com/zaxxer/hikari/pool/TestConcurrentBag.java +++ b/src/test/java/com/zaxxer/hikari/pool/TestConcurrentBag.java @@ -46,7 +46,7 @@ public class TestConcurrentBag HikariConfig config = new HikariConfig(); config.setMinimumIdle(1); config.setMaximumPoolSize(2); - config.setInitializationFailFast(true); + config.setInitializationFailTimeout(0); config.setConnectionTestQuery("VALUES 1"); config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); diff --git a/src/test/java/com/zaxxer/hikari/pool/TestConnectionTimeoutRetry.java b/src/test/java/com/zaxxer/hikari/pool/TestConnectionTimeoutRetry.java index 3335ccc2..5e7b0bce 100644 --- a/src/test/java/com/zaxxer/hikari/pool/TestConnectionTimeoutRetry.java +++ b/src/test/java/com/zaxxer/hikari/pool/TestConnectionTimeoutRetry.java @@ -74,7 +74,7 @@ public class TestConnectionTimeoutRetry config.setMaximumPoolSize(1); config.setConnectionTimeout(2800); config.setValidationTimeout(2800); - config.setInitializationFailFast(true); + config.setInitializationFailTimeout(0); config.setConnectionTestQuery("VALUES 1"); config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); diff --git a/src/test/java/com/zaxxer/hikari/pool/TestConnections.java b/src/test/java/com/zaxxer/hikari/pool/TestConnections.java index f5bd4e4d..dc751694 100644 --- a/src/test/java/com/zaxxer/hikari/pool/TestConnections.java +++ b/src/test/java/com/zaxxer/hikari/pool/TestConnections.java @@ -114,7 +114,7 @@ public class TestConnections config.setMaximumPoolSize(1); config.setConnectionTimeout(2500); config.setConnectionTestQuery("VALUES 1"); - config.setInitializationFailFast(false); + config.setInitializationFailTimeout(Long.MAX_VALUE); config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); System.setProperty("com.zaxxer.hikari.housekeeping.periodMs", "100"); @@ -268,7 +268,7 @@ public class TestConnections config.setMinimumIdle(1); config.setMaximumPoolSize(4); config.setConnectionTimeout(1000); - config.setInitializationFailFast(false); + config.setInitializationFailTimeout(Long.MAX_VALUE); config.setConnectionTestQuery("VALUES 1"); config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); @@ -328,7 +328,7 @@ public class TestConnections config.setMinimumIdle(1); config.setMaximumPoolSize(4); config.setConnectionTimeout(20000); - config.setInitializationFailFast(true); + config.setInitializationFailTimeout(0); config.setConnectionTestQuery("VALUES 1"); config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); @@ -503,14 +503,19 @@ public class TestConnections config.setInitializationFailTimeout(TimeUnit.SECONDS.toMillis(2)); config.setDataSource(stubDataSource); - try (HikariDataSource ds = new HikariDataSource(config); Connection c = ds.getConnection()) { - Assert.fail("getConnection() should have failed"); + try (HikariDataSource ds = new HikariDataSource(config)) { + try (Connection c = ds.getConnection()) { + Assert.fail("getConnection() should have failed"); + } + catch (SQLException e) { + Assert.assertSame("Bad query or something.", e.getNextException().getMessage()); + } } - catch (SQLException e) { - Assert.assertSame("Bad query or something.", e.getNextException().getMessage()); + catch (PoolInitializationException e) { + Assert.assertSame("Bad query or something.", e.getCause().getMessage()); } - config.setInitializationFailFast(true); + config.setInitializationFailTimeout(0); try (HikariDataSource ds = new HikariDataSource(config)) { Assert.fail("Initialization should have failed"); } diff --git a/src/test/java/com/zaxxer/hikari/pool/TestMetrics.java b/src/test/java/com/zaxxer/hikari/pool/TestMetrics.java index 0cafd831..e9bee254 100644 --- a/src/test/java/com/zaxxer/hikari/pool/TestMetrics.java +++ b/src/test/java/com/zaxxer/hikari/pool/TestMetrics.java @@ -56,7 +56,7 @@ public class TestMetrics config.setMinimumIdle(1); config.setMaximumPoolSize(1); config.setMetricRegistry(metricRegistry); - config.setInitializationFailFast(false); + config.setInitializationFailTimeout(Long.MAX_VALUE); config.setPoolName("test"); config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); @@ -87,7 +87,7 @@ public class TestMetrics config.setMinimumIdle(1); config.setMaximumPoolSize(1); config.setMetricRegistry(metricRegistry); - config.setInitializationFailFast(false); + config.setInitializationFailTimeout(Long.MAX_VALUE); config.setPoolName("test"); config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); diff --git a/src/test/java/com/zaxxer/hikari/pool/UnwrapTest.java b/src/test/java/com/zaxxer/hikari/pool/UnwrapTest.java index 699e4572..ce114ca6 100644 --- a/src/test/java/com/zaxxer/hikari/pool/UnwrapTest.java +++ b/src/test/java/com/zaxxer/hikari/pool/UnwrapTest.java @@ -38,7 +38,7 @@ public class UnwrapTest HikariConfig config = new HikariConfig(); config.setMinimumIdle(1); config.setMaximumPoolSize(1); - config.setInitializationFailFast(true); + config.setInitializationFailTimeout(0); config.setConnectionTestQuery("VALUES 1"); config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); @@ -60,7 +60,7 @@ public class UnwrapTest HikariConfig config = new HikariConfig(); config.setMinimumIdle(1); config.setMaximumPoolSize(1); - config.setInitializationFailFast(true); + config.setInitializationFailTimeout(0); config.setConnectionTestQuery("VALUES 1"); config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");