Merge commit '953b0be06d7517e63eebb6ef61c6d734621eae1e' into dev

pull/688/head
Brett Wooldridge 9 years ago
commit e6ece36c32

@ -131,7 +131,7 @@ It is a boolean value.
&#8986;``connectionTimeout``<br/>
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)*
&#8986;``idleTimeout``<br/>
@ -254,14 +254,13 @@ class such as ``TRANSACTION_READ_COMMITTED``, ``TRANSACTION_REPEATABLE_READ``, e
&#8986;``validationTimeout``<br/>
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*
&#8986;``leakDetectionThreshold``<br/>
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*
&#10145;``dataSource``<br/>

@ -16,6 +16,9 @@
package com.zaxxer.hikari.pool;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLTransientConnectionException;
@ -44,11 +47,8 @@ import com.zaxxer.hikari.metrics.dropwizard.CodahaleMetricsTrackerFactory;
import com.zaxxer.hikari.util.ClockSource;
import com.zaxxer.hikari.util.ConcurrentBag;
import com.zaxxer.hikari.util.ConcurrentBag.IBagStateListener;
import com.zaxxer.hikari.util.UtilityElf.DefaultThreadFactory;
import com.zaxxer.hikari.util.SuspendResumeLock;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import com.zaxxer.hikari.util.UtilityElf.DefaultThreadFactory;
import static com.zaxxer.hikari.pool.PoolEntry.LASTACCESS_COMPARABLE;
import static com.zaxxer.hikari.util.ConcurrentBag.IConcurrentBagEntry.STATE_IN_USE;
@ -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());
@ -199,16 +199,19 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL
try {
poolState = POOL_SHUTDOWN;
if (addConnectionExecutor == null) {
return;
}
LOGGER.info("{} - Close initiated...", poolName);
logPoolState("Before closing ");
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 +233,8 @@ 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,12 +384,12 @@ 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);
@ -423,7 +424,7 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL
// ***********************************************************************
/**
* Create and add a single connection to the pool.
* Creating new poolEntry.
*/
private PoolEntry createPoolEntry()
{
@ -476,7 +477,7 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL
}
/**
* Attempt to abort() active connections, or close() them.
* Attempt to abort or close active connections.
*/
private void abortActiveConnections(final ExecutorService assassinExecutor)
{
@ -497,7 +498,9 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL
}
/**
* Fill the pool up to the minimum size.
* If initializationFailFast is configured, check that we have DB connectivity.
*
* @throws PoolInitializationException if fails to create or validate connection
*/
private void checkFailFast()
{
@ -506,13 +509,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 +516,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()
@ -564,6 +557,9 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL
// Non-anonymous Inner-classes
// ***********************************************************************
/**
* Creating and adding poolEntries (connections) to the pool.
*/
private class PoolEntryCreator implements Callable<Boolean>
{
@Override
@ -588,7 +584,7 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL
}
/**
* The house keeping task to retire idle connections.
* The house keeping task to retire and maintain minimum idle connections.
*/
private class HouseKeeper implements Runnable
{
@ -609,7 +605,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();

@ -1,11 +1,5 @@
package com.zaxxer.hikari.pool;
import static com.zaxxer.hikari.pool.ProxyConnection.DIRTY_BIT_AUTOCOMMIT;
import static com.zaxxer.hikari.pool.ProxyConnection.DIRTY_BIT_CATALOG;
import static com.zaxxer.hikari.pool.ProxyConnection.DIRTY_BIT_ISOLATION;
import static com.zaxxer.hikari.pool.ProxyConnection.DIRTY_BIT_NETTIMEOUT;
import static com.zaxxer.hikari.pool.ProxyConnection.DIRTY_BIT_READONLY;
import static com.zaxxer.hikari.util.UtilityElf.createInstance;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
@ -36,6 +30,13 @@ import com.zaxxer.hikari.util.PropertyElf;
import com.zaxxer.hikari.util.UtilityElf;
import com.zaxxer.hikari.util.UtilityElf.DefaultThreadFactory;
import static com.zaxxer.hikari.pool.ProxyConnection.DIRTY_BIT_AUTOCOMMIT;
import static com.zaxxer.hikari.pool.ProxyConnection.DIRTY_BIT_CATALOG;
import static com.zaxxer.hikari.pool.ProxyConnection.DIRTY_BIT_ISOLATION;
import static com.zaxxer.hikari.pool.ProxyConnection.DIRTY_BIT_NETTIMEOUT;
import static com.zaxxer.hikari.pool.ProxyConnection.DIRTY_BIT_READONLY;
import static com.zaxxer.hikari.util.UtilityElf.createInstance;
abstract class PoolBase
{
private final Logger LOGGER = LoggerFactory.getLogger(PoolBase.class);
@ -98,7 +99,7 @@ abstract class PoolBase
return poolName;
}
abstract void releaseConnection(final PoolEntry poolEntry);
abstract void recycle(final PoolEntry poolEntry);
// ***********************************************************************
// JDBC methods
@ -239,7 +240,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("{} - JMX name ({}) is already registered.", poolName, poolName);
}
}
catch (Exception e) {
@ -299,13 +300,18 @@ abstract class PoolBase
}
if (dataSource != null) {
setLoginTimeout(dataSource, connectionTimeout);
setLoginTimeout(dataSource);
createNetworkTimeoutExecutor(dataSource, dsClassName, jdbcUrl);
}
this.dataSource = dataSource;
}
/**
* Obtain connection from data source.
*
* @return a Connection connection
*/
Connection newConnection() throws Exception
{
Connection connection = null;
@ -370,23 +376,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();
@ -519,9 +519,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 {

@ -84,7 +84,7 @@ final class PoolEntry implements IConcurrentBagEntry
{
if (connection != null) {
this.lastAccessed = lastAccessed;
hikariPool.releaseConnection(this);
hikariPool.recycle(this);
}
}

@ -140,7 +140,7 @@ public class ConcurrentBag<T extends IConcurrentBagEntry> implements AutoCloseab
// Otherwise, scan the shared list ... for maximum of timeout
timeout = timeUnit.toNanos(timeout);
Future<Boolean> 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<T extends IConcurrentBagEntry> implements AutoCloseab
addItemFuture = listener.addBagItem();
}
timeout = originTimeout - (System.nanoTime() - startScan);
timeout = originTimeout - (System.nanoTime() - startTime);
} while (timeout > 10_000L && synchronizer.waitUntilSequenceExceeded(startSeq, timeout));
}
finally {
@ -182,7 +182,7 @@ public class ConcurrentBag<T extends IConcurrentBagEntry> implements AutoCloseab
*
* @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)
{

@ -507,6 +507,14 @@ public class TestConnections
catch (SQLException e) {
Assert.assertSame("Bad query or something.", e.getNextException().getMessage());
}
config.setInitializationFailFast(true);
try (HikariDataSource ds = new HikariDataSource(config)) {
Assert.fail("Initialization should have failed");
}
catch (PoolInitializationException e) {
// passed
}
}
@Test

Loading…
Cancel
Save