@ -128,12 +128,12 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
this . leakDetectionThreshold = configuration . getLeakDetectionThreshold ( ) ;
this . transactionIsolation = configuration . getTransactionIsolation ( ) ;
this . isRecordMetrics = configuration . isRecordMetrics ( ) ;
this . metricsTracker = MetricsFactory . createMetricsTracker ( ( isRecordMetrics ? configuration . getMetricsTrackerClassName ( ) : "com.zaxxer.hikari.metrics.MetricsTracker" ) , configuration . getPoolName ( ) ) ;
this . metricsTracker = MetricsFactory . createMetricsTracker ( ( isRecordMetrics ? configuration . getMetricsTrackerClassName ( )
: "com.zaxxer.hikari.metrics.MetricsTracker" ) , configuration . getPoolName ( ) ) ;
this . dataSource = initializeDataSource ( ) ;
if ( isRegisteredMbeans )
{
if ( isRegisteredMbeans ) {
HikariMBeanElf . registerMBeans ( configuration , this ) ;
}
@ -158,27 +158,22 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
final MetricsContext context = ( isRecordMetrics ? metricsTracker . recordConnectionRequest ( start ) : MetricsTracker . NO_CONTEXT ) ;
long timeout = connectionTimeout ;
try
{
do
{
try {
do {
IHikariConnectionProxy connection = connectionBag . borrow ( timeout , TimeUnit . MILLISECONDS ) ;
if ( connection = = null )
{
if ( connection = = null ) {
break ; // We timed out... break and throw exception
}
final long now = System . currentTimeMillis ( ) ;
connection . unclose ( now ) ;
if ( now > connection . getExpirationTime ( ) | | ( now - connection . getLastAccess ( ) > 1000L & & ! isConnectionAlive ( connection , timeout ) ) )
{
if ( now > connection . getExpirationTime ( ) | | ( now - connection . getLastAccess ( ) > 1000L & & ! isConnectionAlive ( connection , timeout ) ) ) {
closeConnection ( connection ) ; // Throw away the dead connection and try again
timeout - = elapsedTimeMs ( start ) ;
continue ;
}
else if ( leakDetectionThreshold ! = 0 )
{
else if ( leakDetectionThreshold ! = 0 ) {
connection . captureStack ( leakDetectionThreshold , houseKeepingTimer ) ;
}
@ -186,18 +181,16 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
}
while ( timeout > 0 L ) ;
}
catch ( InterruptedException e )
{
catch ( InterruptedException e ) {
throw new SQLException ( "Interrupted during connection acquisition" , e ) ;
}
finally
{
finally {
context . stop ( ) ;
}
logPoolState ( "Timeout failure " ) ;
throw new SQLException ( String . format ( "Timeout of %dms encountered waiting for connection." ,
configuration . getConnectionTimeout ( ) ) , lastConnectionFailure . getAndSet ( null ) ) ;
throw new SQLException ( String . format ( "Timeout of %dms encountered waiting for connection." , configuration . getConnectionTimeout ( ) ) ,
lastConnectionFailure . getAndSet ( null ) ) ;
}
/ * *
@ -208,13 +201,11 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
* /
public void releaseConnection ( final IHikariConnectionProxy connectionProxy , final boolean isBroken )
{
if ( isRecordMetrics )
{
if ( isRecordMetrics ) {
metricsTracker . recordConnectionUsage ( elapsedTimeMs ( connectionProxy . getLastOpenTime ( ) ) ) ;
}
if ( isBroken | | isShutdown )
{
if ( isBroken | | isShutdown ) {
LOGGER . debug ( "Connection returned to pool {} is broken, or the pool is shutting down. Closing connection." , configuration . getPoolName ( ) ) ;
closeConnection ( connectionProxy ) ;
return ;
@ -231,8 +222,7 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
* /
public void shutdown ( ) throws InterruptedException
{
if ( ! isShutdown )
{
if ( ! isShutdown ) {
isShutdown = true ;
LOGGER . info ( "HikariCP pool {} is shutting down." , configuration . getPoolName ( ) ) ;
@ -241,8 +231,7 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
addConnectionExecutor . shutdownNow ( ) ;
final long start = System . currentTimeMillis ( ) ;
do
{
do {
closeIdleConnections ( ) ;
abortActiveConnections ( ) ;
}
@ -250,8 +239,7 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
logPoolState ( "After shutdown " ) ;
if ( isRegisteredMbeans )
{
if ( isRegisteredMbeans ) {
HikariMBeanElf . unregisterMBeans ( configuration , this ) ;
}
}
@ -274,21 +262,17 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
* /
public void closeConnection ( final IHikariConnectionProxy connectionProxy )
{
try
{
try {
int tc = totalConnections . decrementAndGet ( ) ;
if ( tc < 0 )
{
if ( tc < 0 ) {
LOGGER . warn ( "Internal accounting inconsistency, totalConnections={}" , tc , new Exception ( ) ) ;
}
connectionProxy . realClose ( ) ;
}
catch ( SQLException e )
{
catch ( SQLException e ) {
return ;
}
finally
{
finally {
connectionBag . remove ( connectionProxy ) ;
}
}
@ -307,23 +291,21 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
@Override
public void addBagItem ( )
{
class AddConnection implements Runnable {
class AddConnection implements Runnable
{
public void run ( )
{
long sleepBackoff = 200L ;
final int maxPoolSize = configuration . getMaximumPoolSize ( ) ;
final int minIdle = configuration . getMinimumIdle ( ) ;
while ( ! isShutdown & & totalConnections . get ( ) < maxPoolSize & & ( minIdle = = 0 | | getIdleConnections ( ) < minIdle ) )
{
if ( ! addConnection ( ) )
{
while ( ! isShutdown & & totalConnections . get ( ) < maxPoolSize & & ( minIdle = = 0 | | getIdleConnections ( ) < minIdle ) ) {
if ( ! addConnection ( ) ) {
quietlySleep ( sleepBackoff ) ;
sleepBackoff = Math . min ( 1000L , ( long ) ( ( double ) sleepBackoff * 1.5 ) ) ;
continue ;
}
if ( minIdle = = 0 )
{
if ( minIdle = = 0 ) {
break ; // This break is here so we only add one connection when there is no min. idle
}
}
@ -369,10 +351,8 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
@Override
public void closeIdleConnections ( )
{
for ( IHikariConnectionProxy connectionProxy : connectionBag . values ( ConcurrentBag . STATE_NOT_IN_USE ) )
{
if ( connectionBag . reserve ( connectionProxy ) )
{
for ( IHikariConnectionProxy connectionProxy : connectionBag . values ( ConcurrentBag . STATE_NOT_IN_USE ) ) {
if ( connectionBag . reserve ( connectionProxy ) ) {
closeConnection ( connectionProxy ) ;
}
}
@ -388,11 +368,9 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
private boolean addConnection ( )
{
Connection connection = null ;
try
{
try {
// Speculative increment of totalConnections with expectation of success
if ( totalConnections . incrementAndGet ( ) > configuration . getMaximumPoolSize ( ) | | isShutdown )
{
if ( totalConnections . incrementAndGet ( ) > configuration . getMaximumPoolSize ( ) | | isShutdown ) {
totalConnections . decrementAndGet ( ) ;
return true ;
}
@ -403,15 +381,14 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
executeSqlAutoCommit ( connection , configuration . getConnectionInitSql ( ) ) ;
IHikariConnectionProxy proxyConnection = ProxyFactory . getProxyConnection ( this , connection , configuration . getMaxLifetime ( ) ,
transactionIsolation , isAutoCommit , isReadOnly , catalog ) ;
IHikariConnectionProxy proxyConnection = ProxyFactory . getProxyConnection ( this , connection , configuration . getMaxLifetime ( ) , transactionIsolation ,
isAutoCommit , isReadOnly , catalog ) ;
proxyConnection . resetConnectionState ( ) ;
connectionBag . add ( proxyConnection ) ;
lastConnectionFailure . set ( null ) ;
return true ;
}
catch ( Exception e )
{
catch ( Exception e ) {
// We failed, so undo speculative increment of totalConnections
totalConnections . decrementAndGet ( ) ;
@ -431,34 +408,28 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
* /
private boolean isConnectionAlive ( final IHikariConnectionProxy connection , long timeoutMs )
{
try
{
try {
final boolean timeoutEnabled = ( configuration . getConnectionTimeout ( ) ! = Integer . MAX_VALUE ) ;
timeoutMs = timeoutEnabled ? Math . max ( 1000L , timeoutMs ) : 0 ;
if ( isJdbc4ConnectionTest )
{
if ( isJdbc4ConnectionTest ) {
return connection . isValid ( ( int ) TimeUnit . MILLISECONDS . toSeconds ( timeoutMs ) ) ;
}
Statement statement = connection . createStatement ( ) ;
try
{
try {
statement . setQueryTimeout ( ( int ) TimeUnit . MILLISECONDS . toSeconds ( timeoutMs ) ) ;
statement . executeQuery ( configuration . getConnectionTestQuery ( ) ) ;
return true ;
}
finally
{
finally {
statement . close ( ) ;
if ( isIsolateInternalQueries & & ! isAutoCommit )
{
if ( isIsolateInternalQueries & & ! isAutoCommit ) {
connection . rollback ( ) ;
}
}
}
catch ( SQLException e )
{
catch ( SQLException e ) {
LOGGER . warn ( "Exception during keep alive check, that means the connection must be dead." , e ) ;
return false ;
}
@ -469,18 +440,14 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
* /
private void fillPool ( )
{
if ( configuration . isInitializationFailFast ( ) )
{
for ( int maxIters = configuration . getMinimumIdle ( ) ; maxIters > 0 ; maxIters - - )
{
if ( ! addConnection ( ) )
{
if ( configuration . isInitializationFailFast ( ) ) {
for ( int maxIters = configuration . getMinimumIdle ( ) ; maxIters > 0 ; maxIters - - ) {
if ( ! addConnection ( ) ) {
throw new RuntimeException ( "Fail-fast during pool initialization" , lastConnectionFailure . getAndSet ( null ) ) ;
}
}
}
else if ( configuration . getMinimumIdle ( ) > 0 )
{
else if ( configuration . getMinimumIdle ( ) > 0 ) {
addBagItem ( ) ;
}
}
@ -493,31 +460,24 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
private void abortActiveConnections ( ) throws InterruptedException
{
ThreadPoolExecutor assassinExecutor = createThreadPoolExecutor ( configuration . getMaximumPoolSize ( ) , "HikariCP connection assassin" ) ;
for ( IHikariConnectionProxy connectionProxy : connectionBag . values ( ConcurrentBag . STATE_IN_USE ) )
{
try
{
if ( IS_JAVA7 )
{
for ( IHikariConnectionProxy connectionProxy : connectionBag . values ( ConcurrentBag . STATE_IN_USE ) ) {
try {
if ( IS_JAVA7 ) {
connectionProxy . abort ( assassinExecutor ) ;
continue ;
}
connectionProxy . close ( ) ;
}
catch ( SQLException e )
{
catch ( SQLException e ) {
continue ;
}
finally
{
finally {
totalConnections . decrementAndGet ( ) ;
try
{
try {
connectionBag . remove ( connectionProxy ) ;
}
catch ( IllegalStateException ise )
{
catch ( IllegalStateException ise ) {
continue ;
}
}
@ -535,14 +495,12 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
private DataSource initializeDataSource ( )
{
String dsClassName = configuration . getDataSourceClassName ( ) ;
if ( configuration . getDataSource ( ) = = null & & dsClassName ! = null )
{
if ( configuration . getDataSource ( ) = = null & & dsClassName ! = null ) {
DataSource dataSource = createInstance ( dsClassName , DataSource . class ) ;
PropertyBeanSetter . setTargetFromProperties ( dataSource , configuration . getDataSourceProperties ( ) ) ;
return dataSource ;
}
else if ( configuration . getJdbcUrl ( ) ! = null )
{
else if ( configuration . getJdbcUrl ( ) ! = null ) {
return new DriverDataSource ( configuration . getJdbcUrl ( ) , configuration . getDataSourceProperties ( ) , username , password ) ;
}
@ -551,8 +509,7 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
private IConnectionCustomizer initializeCustomizer ( )
{
if ( configuration . getConnectionCustomizerClassName ( ) ! = null )
{
if ( configuration . getConnectionCustomizerClassName ( ) ! = null ) {
return createInstance ( configuration . getConnectionCustomizerClassName ( ) , IConnectionCustomizer . class ) ;
}
@ -563,8 +520,8 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
{
int total = totalConnections . get ( ) ;
int idle = getIdleConnections ( ) ;
LOGGER . debug ( "{}pool stats {} (total={}, inUse={}, avail={}, waiting={})" , ( prefix . length > 0 ? prefix [ 0 ] : "" ) ,
configuration . getPoolName ( ) , total , total - idle , idle , getThreadsAwaitingConnection ( ) ) ;
LOGGER . debug ( "{}pool stats {} (total={}, inUse={}, avail={}, waiting={})" , ( prefix . length > 0 ? prefix [ 0 ] : "" ) , configuration . getPoolName ( ) , total ,
total - idle , idle , getThreadsAwaitingConnection ( ) ) ;
}
/ * *
@ -583,14 +540,9 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
final long now = System . currentTimeMillis ( ) ;
final long idleTimeout = configuration . getIdleTimeout ( ) ;
for ( IHikariConnectionProxy connectionProxy : connectionBag . values ( ConcurrentBag . STATE_NOT_IN_USE ) )
{
if ( connectionBag . reserve ( connectionProxy ) )
{
if ( ( idleTimeout > 0 L & & now > connectionProxy . getLastAccess ( ) + idleTimeout )
| |
( now > connectionProxy . getExpirationTime ( ) ) )
{
for ( IHikariConnectionProxy connectionProxy : connectionBag . values ( ConcurrentBag . STATE_NOT_IN_USE ) ) {
if ( connectionBag . reserve ( connectionProxy ) ) {
if ( ( idleTimeout > 0 L & & now > connectionProxy . getLastAccess ( ) + idleTimeout ) | | ( now > connectionProxy . getExpirationTime ( ) ) ) {
closeConnection ( connectionProxy ) ;
continue ;
}