Add validationTimeout.

pull/253/head
Brett Wooldridge 10 years ago
parent f498dfa608
commit b544c21cf3

@ -39,6 +39,7 @@ public abstract class AbstractHikariConfig implements HikariConfigMBean
private static final Logger LOGGER = LoggerFactory.getLogger(HikariConfig.class); private static final Logger LOGGER = LoggerFactory.getLogger(HikariConfig.class);
private static final long CONNECTION_TIMEOUT = TimeUnit.SECONDS.toMillis(30); private static final long CONNECTION_TIMEOUT = TimeUnit.SECONDS.toMillis(30);
private static final long VALIDATION_TIMEOUT = TimeUnit.SECONDS.toMillis(5);
private static final long IDLE_TIMEOUT = TimeUnit.MINUTES.toMillis(10); private static final long IDLE_TIMEOUT = TimeUnit.MINUTES.toMillis(10);
private static final long MAX_LIFETIME = TimeUnit.MINUTES.toMillis(30); private static final long MAX_LIFETIME = TimeUnit.MINUTES.toMillis(30);
@ -48,6 +49,7 @@ public abstract class AbstractHikariConfig implements HikariConfigMBean
// Properties changeable at runtime through the MBean // Properties changeable at runtime through the MBean
// //
private volatile long connectionTimeout; private volatile long connectionTimeout;
private volatile long validationTimeout;
private volatile long idleTimeout; private volatile long idleTimeout;
private volatile long leakDetectionThreshold; private volatile long leakDetectionThreshold;
private volatile long maxLifetime; private volatile long maxLifetime;
@ -88,6 +90,7 @@ public abstract class AbstractHikariConfig implements HikariConfigMBean
dataSourceProperties = new Properties(); dataSourceProperties = new Properties();
connectionTimeout = CONNECTION_TIMEOUT; connectionTimeout = CONNECTION_TIMEOUT;
validationTimeout = VALIDATION_TIMEOUT;
idleTimeout = IDLE_TIMEOUT; idleTimeout = IDLE_TIMEOUT;
isAutoCommit = true; isAutoCommit = true;
isInitializationFailFast = true; isInitializationFailFast = true;
@ -263,14 +266,33 @@ public abstract class AbstractHikariConfig implements HikariConfigMBean
if (connectionTimeoutMs == 0) { if (connectionTimeoutMs == 0) {
this.connectionTimeout = Integer.MAX_VALUE; this.connectionTimeout = Integer.MAX_VALUE;
} }
else if (connectionTimeoutMs < 100) { else if (connectionTimeoutMs < 1000) {
throw new IllegalArgumentException("connectionTimeout cannot be less than 100ms"); throw new IllegalArgumentException("connectionTimeout cannot be less than 1000ms");
} }
else { else {
this.connectionTimeout = connectionTimeoutMs; this.connectionTimeout = connectionTimeoutMs;
} }
} }
/** {@inheritDoc} */
@Override
public long getValidationTimeout()
{
return validationTimeout;
}
/** {@inheritDoc} */
@Override
public void setValidationTimeout(long validationTimeoutMs)
{
if (validationTimeoutMs < 1000) {
throw new IllegalArgumentException("connectionTimeout cannot be less than 1000ms");
}
else {
this.validationTimeout = validationTimeoutMs;
}
}
/** /**
* Get the {@link DataSource} that has been explicitly specified to be wrapped by the * Get the {@link DataSource} that has been explicitly specified to be wrapped by the
* pool. * pool.
@ -708,6 +730,11 @@ public abstract class AbstractHikariConfig implements HikariConfigMBean
logger.warn("No connection wait timeout is set, this might cause an infinite wait."); logger.warn("No connection wait timeout is set, this might cause an infinite wait.");
} }
if (validationTimeout > connectionTimeout) {
logger.warn("validationTimeout is greater than connectionTimeout, setting validationTimeout to connectionTimeout.");
validationTimeout = connectionTimeout;
}
if (minIdle < 0 || minIdle > maxPoolSize) { if (minIdle < 0 || minIdle > maxPoolSize) {
minIdle = maxPoolSize; minIdle = maxPoolSize;
} }

@ -41,6 +41,22 @@ public interface HikariConfigMBean
*/ */
void setConnectionTimeout(long connectionTimeoutMs); void setConnectionTimeout(long connectionTimeoutMs);
/**
* Get the maximum number of milliseconds that the pool will wait for a connection to be validated as
* alive.
*
* @return the validation timeout in milliseconds
*/
long getValidationTimeout();
/**
* Sets the maximum number of milliseconds that the pool will wait for a connection to be validated as
* alive.
*
* @param validationTimeoutMs the validation timeout in milliseconds
*/
void setValidationTimeout(long validationTimeoutMs);
/** /**
* This property controls the maximum amount of time (in milliseconds) that a connection is allowed to sit * This property controls the maximum amount of time (in milliseconds) that a connection is allowed to sit
* idle in the pool. Whether a connection is retired as idle or not is subject to a maximum variation of +30 * idle in the pool. Whether a connection is retired as idle or not is subject to a maximum variation of +30

@ -89,6 +89,7 @@ public abstract class BaseHikariPool implements HikariPoolMBean, IBagStateListen
protected volatile int poolState; protected volatile int poolState;
protected volatile long connectionTimeout; protected volatile long connectionTimeout;
protected volatile long validationTimeout;
private final LeakTask leakTask; private final LeakTask leakTask;
private final DataSource dataSource; private final DataSource dataSource;
@ -129,6 +130,7 @@ public abstract class BaseHikariPool implements HikariPoolMBean, IBagStateListen
this.connectionBag = createConcurrentBag(this); this.connectionBag = createConcurrentBag(this);
this.totalConnections = new AtomicInteger(); this.totalConnections = new AtomicInteger();
this.connectionTimeout = configuration.getConnectionTimeout(); this.connectionTimeout = configuration.getConnectionTimeout();
this.validationTimeout = configuration.getValidationTimeout();
this.lastConnectionFailure = new AtomicReference<Throwable>(); this.lastConnectionFailure = new AtomicReference<Throwable>();
this.isReadOnly = configuration.isReadOnly(); this.isReadOnly = configuration.isReadOnly();
@ -183,7 +185,7 @@ public abstract class BaseHikariPool implements HikariPoolMBean, IBagStateListen
} }
final long now = System.currentTimeMillis(); final long now = System.currentTimeMillis();
if (bagEntry.evicted || (now - bagEntry.lastAccess > ALIVE_BYPASS_WINDOW && !isConnectionAlive(bagEntry.connection, timeout))) { if (bagEntry.evicted || (now - bagEntry.lastAccess > ALIVE_BYPASS_WINDOW && !isConnectionAlive(bagEntry.connection))) {
closeConnection(bagEntry); // Throw away the dead connection and try again closeConnection(bagEntry); // Throw away the dead connection and try again
timeout = connectionTimeout - elapsedTimeMs(start); timeout = connectionTimeout - elapsedTimeMs(start);
} }
@ -378,14 +380,14 @@ public abstract class BaseHikariPool implements HikariPoolMBean, IBagStateListen
final boolean timeoutEnabled = (connectionTimeout != Integer.MAX_VALUE); final boolean timeoutEnabled = (connectionTimeout != Integer.MAX_VALUE);
final long timeoutMs = timeoutEnabled ? Math.max(250L, connectionTimeout) : 0L; final long timeoutMs = timeoutEnabled ? Math.max(250L, connectionTimeout) : 0L;
final int originalTimeout = poolUtils.getAndSetNetworkTimeout(connection, timeoutMs, timeoutEnabled); final int originalTimeout = poolUtils.getAndSetNetworkTimeout(connection, timeoutMs);
transactionIsolation = (transactionIsolation < 0 ? connection.getTransactionIsolation() : transactionIsolation); transactionIsolation = (transactionIsolation < 0 ? connection.getTransactionIsolation() : transactionIsolation);
poolUtils.setupConnection(connection, isAutoCommit, isReadOnly, transactionIsolation, catalog); poolUtils.setupConnection(connection, isAutoCommit, isReadOnly, transactionIsolation, catalog);
connectionCustomizer.customize(connection); connectionCustomizer.customize(connection);
poolUtils.executeSql(connection, configuration.getConnectionInitSql(), isAutoCommit); poolUtils.executeSql(connection, configuration.getConnectionInitSql(), isAutoCommit);
poolUtils.setNetworkTimeout(connection, originalTimeout, timeoutEnabled); poolUtils.setNetworkTimeout(connection, originalTimeout);
connectionBag.add(new PoolBagEntry(connection, this)); connectionBag.add(new PoolBagEntry(connection, this));
lastConnectionFailure.set(null); lastConnectionFailure.set(null);
@ -431,7 +433,7 @@ public abstract class BaseHikariPool implements HikariPoolMBean, IBagStateListen
* @param timeoutMs the timeout before we consider the test a failure * @param timeoutMs the timeout before we consider the test a failure
* @return true if the connection is alive, false if it is not alive or we timed out * @return true if the connection is alive, false if it is not alive or we timed out
*/ */
protected abstract boolean isConnectionAlive(final Connection connection, final long timeoutMs); protected abstract boolean isConnectionAlive(final Connection connection);
/** /**
* Attempt to abort() active connections on Java7+, or close() them on Java6. * Attempt to abort() active connections on Java7+, or close() them on Java6.

@ -49,7 +49,7 @@ public final class PoolUtilities
{ {
if (connection != null) { if (connection != null) {
try { try {
setNetworkTimeout(connection, TimeUnit.SECONDS.toMillis(30), true); setNetworkTimeout(connection, TimeUnit.SECONDS.toMillis(30));
connection.close(); connection.close();
} }
catch (Throwable e) { catch (Throwable e) {
@ -177,12 +177,11 @@ public final class PoolUtilities
* *
* @param connection the connection to set the network timeout on * @param connection the connection to set the network timeout on
* @param timeoutMs the number of milliseconds before timeout * @param timeoutMs the number of milliseconds before timeout
* @param isUseNetworkTimeout true if the network timeout should be set, false otherwise
* @return the pre-existing network timeout value * @return the pre-existing network timeout value
*/ */
public int getAndSetNetworkTimeout(final Connection connection, final long timeoutMs, final boolean isUseNetworkTimeout) public int getAndSetNetworkTimeout(final Connection connection, final long timeoutMs)
{ {
if (isUseNetworkTimeout && isNetworkTimeoutSupported) { if (isNetworkTimeoutSupported) {
try { try {
final int networkTimeout = connection.getNetworkTimeout(); final int networkTimeout = connection.getNetworkTimeout();
connection.setNetworkTimeout(executorService, (int) timeoutMs); connection.setNetworkTimeout(executorService, (int) timeoutMs);
@ -203,11 +202,10 @@ public final class PoolUtilities
* *
* @param connection the connection to set the network timeout on * @param connection the connection to set the network timeout on
* @param timeoutMs the number of milliseconds before timeout * @param timeoutMs the number of milliseconds before timeout
* @param isUseNetworkTimeout true if the network timeout should be set, false otherwise
*/ */
public void setNetworkTimeout(final Connection connection, final long timeoutMs, final boolean isUseNetworkTimeout) public void setNetworkTimeout(final Connection connection, final long timeoutMs)
{ {
if (isUseNetworkTimeout && isNetworkTimeoutSupported) { if (isNetworkTimeoutSupported) {
try { try {
connection.setNetworkTimeout(executorService, (int) timeoutMs); connection.setNetworkTimeout(executorService, (int) timeoutMs);
} }

@ -139,17 +139,16 @@ public final class HikariPool extends BaseHikariPool
* @return true if the connection is alive, false if it is not alive or we timed out * @return true if the connection is alive, false if it is not alive or we timed out
*/ */
@Override @Override
protected boolean isConnectionAlive(final Connection connection, final long timeoutMs) protected boolean isConnectionAlive(final Connection connection)
{ {
try { try {
final boolean timeoutEnabled = (connectionTimeout != Integer.MAX_VALUE); final int timeoutSec = (int) TimeUnit.MILLISECONDS.toSeconds(validationTimeout);
int timeoutSec = timeoutEnabled ? (int) Math.max(1L, TimeUnit.MILLISECONDS.toSeconds(timeoutMs)) : 0;
if (isUseJdbc4Validation) { if (isUseJdbc4Validation) {
return connection.isValid(timeoutSec); return connection.isValid(timeoutSec);
} }
final int originalTimeout = poolUtils.getAndSetNetworkTimeout(connection, Math.max(1000, (int) timeoutMs), timeoutEnabled); final int originalTimeout = poolUtils.getAndSetNetworkTimeout(connection, validationTimeout);
Statement statement = connection.createStatement(); Statement statement = connection.createStatement();
try { try {
@ -164,7 +163,7 @@ public final class HikariPool extends BaseHikariPool
connection.rollback(); connection.rollback();
} }
poolUtils.setNetworkTimeout(connection, originalTimeout, timeoutEnabled); poolUtils.setNetworkTimeout(connection, originalTimeout);
return true; return true;
} }

@ -118,21 +118,19 @@ public final class HikariPool extends BaseHikariPool
* Check whether the connection is alive or not. * Check whether the connection is alive or not.
* *
* @param connection the connection to test * @param connection the connection to test
* @param timeoutMs the timeout before we consider the test a failure
* @return true if the connection is alive, false if it is not alive or we timed out * @return true if the connection is alive, false if it is not alive or we timed out
*/ */
@Override @Override
protected boolean isConnectionAlive(final Connection connection, final long timeoutMs) protected boolean isConnectionAlive(final Connection connection)
{ {
try { try {
final boolean timeoutEnabled = (connectionTimeout != Integer.MAX_VALUE); final int timeoutSec = (int) TimeUnit.MILLISECONDS.toSeconds(validationTimeout);
int timeoutSec = timeoutEnabled ? (int) Math.max(1L, TimeUnit.MILLISECONDS.toSeconds(timeoutMs)) : 0;
if (isUseJdbc4Validation) { if (isUseJdbc4Validation) {
return connection.isValid(timeoutSec); return connection.isValid(timeoutSec);
} }
final int originalTimeout = poolUtils.getAndSetNetworkTimeout(connection, Math.max(1000, (int) timeoutMs), timeoutEnabled); final int originalTimeout = poolUtils.getAndSetNetworkTimeout(connection, validationTimeout);
try (Statement statement = connection.createStatement()) { try (Statement statement = connection.createStatement()) {
poolUtils.setQueryTimeout(statement, timeoutSec); poolUtils.setQueryTimeout(statement, timeoutSec);
@ -143,7 +141,7 @@ public final class HikariPool extends BaseHikariPool
connection.rollback(); connection.rollback();
} }
poolUtils.setNetworkTimeout(connection, originalTimeout, timeoutEnabled); poolUtils.setNetworkTimeout(connection, originalTimeout);
return true; return true;
} }
@ -206,6 +204,7 @@ public final class HikariPool extends BaseHikariPool
logPoolState("Before cleanup "); logPoolState("Before cleanup ");
connectionTimeout = configuration.getConnectionTimeout(); // refresh member in case it changed connectionTimeout = configuration.getConnectionTimeout(); // refresh member in case it changed
validationTimeout = configuration.getValidationTimeout(); // refresh member in case it changed
final long now = System.currentTimeMillis(); final long now = System.currentTimeMillis();
final long idleTimeout = configuration.getIdleTimeout(); final long idleTimeout = configuration.getIdleTimeout();

Loading…
Cancel
Save