Merge pull request #423 from nitincchauhan/dev

removed redundant creationTime. lastAceess is initialized at creation as
pull/424/merge
Brett Wooldridge 10 years ago
commit 350a18e74f

@ -360,7 +360,6 @@ Here is a list of JDBC *DataSource* classes for popular databases:
| Apache Derby | Derby | org.apache.derby.jdbc.ClientDataSource | | Apache Derby | Derby | org.apache.derby.jdbc.ClientDataSource |
| Firebird | Jaybird | org.firebirdsql.pool.FBSimpleDataSource | | Firebird | Jaybird | org.firebirdsql.pool.FBSimpleDataSource |
| H2 | H2 | org.h2.jdbcx.JdbcDataSource | | H2 | H2 | org.h2.jdbcx.JdbcDataSource |
| IBM AS400 | IBM | com.ibm.as400.access.AS400JDBCDriver |
| HSQLDB | HSQLDB | org.hsqldb.jdbc.JDBCDataSource | | HSQLDB | HSQLDB | org.hsqldb.jdbc.JDBCDataSource |
| IBM AS400 | IBM | com.ibm.as400.access.AS400JDBCDriver | | IBM AS400 | IBM | com.ibm.as400.access.AS400JDBCDriver |
| IBM DB2 | DB2 | com.ibm.db2.jcc.DB2SimpleDataSource | | IBM DB2 | DB2 | com.ibm.db2.jcc.DB2SimpleDataSource |

@ -21,12 +21,9 @@ import com.codahale.metrics.Histogram;
import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Timer; import com.codahale.metrics.Timer;
import com.zaxxer.hikari.pool.PoolEntry; import com.zaxxer.hikari.pool.PoolEntry;
import com.zaxxer.hikari.util.ClockSource;
public final class CodaHaleMetricsTracker extends MetricsTracker public final class CodaHaleMetricsTracker extends MetricsTracker
{ {
private static final ClockSource clockSource = ClockSource.INSTANCE;
private final String poolName; private final String poolName;
private final Timer connectionObtainTimer; private final Timer connectionObtainTimer;
private final Histogram connectionUsage; private final Histogram connectionUsage;
@ -95,7 +92,7 @@ public final class CodaHaleMetricsTracker extends MetricsTracker
@Override @Override
public void recordConnectionUsage(final PoolEntry bagEntry) public void recordConnectionUsage(final PoolEntry bagEntry)
{ {
connectionUsage.update(clockSource.elapsedMillis(bagEntry.lastOpenTime)); connectionUsage.update(bagEntry.getElapsedLastBorrowed());
} }
public Timer getConnectionAcquisitionTimer() public Timer getConnectionAcquisitionTimer()
@ -122,12 +119,5 @@ public final class CodaHaleMetricsTracker extends MetricsTracker
{ {
innerContext.stop(); innerContext.stop();
} }
/** {@inheritDoc} */
@Override
public void setConnectionLastOpen(final PoolEntry bagEntry, final long now)
{
bagEntry.lastOpenTime = now;
}
} }
} }

@ -17,7 +17,6 @@
package com.zaxxer.hikari.metrics; package com.zaxxer.hikari.metrics;
import com.zaxxer.hikari.pool.PoolEntry; import com.zaxxer.hikari.pool.PoolEntry;
import com.zaxxer.hikari.util.ClockSource;
/** /**
* This class only supports realtime, not historical metrics. * This class only supports realtime, not historical metrics.
@ -59,16 +58,5 @@ public class MetricsTracker implements AutoCloseable
{ {
// do nothing // do nothing
} }
/**
* Set the lastOpenTime on the provided bag entry.
*
* @param bagEntry the bag entry
* @param now the last open timestamp from {@link ClockSource#currentTime()}
*/
public void setConnectionLastOpen(final PoolEntry bagEntry, final long now)
{
// do nothing
}
} }
} }

@ -67,23 +67,22 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL
private static final ClockSource clockSource = ClockSource.INSTANCE; private static final ClockSource clockSource = ClockSource.INSTANCE;
private final long ALIVE_BYPASS_WINDOW_MS = Long.getLong("com.zaxxer.hikari.aliveBypassWindow", TimeUnit.SECONDS.toMillis(1)); private static final long ALIVE_BYPASS_WINDOW_MS = Long.getLong("com.zaxxer.hikari.aliveBypassWindow", TimeUnit.SECONDS.toMillis(1));
private final long HOUSEKEEPING_PERIOD_MS = Long.getLong("com.zaxxer.hikari.housekeeping.periodMs", TimeUnit.SECONDS.toMillis(30)); private static final long HOUSEKEEPING_PERIOD_MS = Long.getLong("com.zaxxer.hikari.housekeeping.periodMs", TimeUnit.SECONDS.toMillis(30));
private static final int POOL_NORMAL = 0; private static final int POOL_NORMAL = 0;
private static final int POOL_SUSPENDED = 1; private static final int POOL_SUSPENDED = 1;
private static final int POOL_SHUTDOWN = 2; private static final int POOL_SHUTDOWN = 2;
final ConcurrentBag<PoolEntry> connectionBag; private volatile int poolState;
final ScheduledThreadPoolExecutor houseKeepingExecutorService;
private final AtomicInteger totalConnections; private final AtomicInteger totalConnections;
private final ThreadPoolExecutor addConnectionExecutor; private final ThreadPoolExecutor addConnectionExecutor;
private final ThreadPoolExecutor closeConnectionExecutor; private final ThreadPoolExecutor closeConnectionExecutor;
private final ScheduledThreadPoolExecutor houseKeepingExecutorService;
private volatile int poolState; private final ConcurrentBag<PoolEntry> connectionBag;
private final String poolName;
private final ProxyLeakTask leakTask; private final ProxyLeakTask leakTask;
private final SuspendResumeLock suspendResumeLock; private final SuspendResumeLock suspendResumeLock;
@ -99,7 +98,6 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL
{ {
super(config); super(config);
this.poolName = config.getPoolName();
this.connectionBag = new ConcurrentBag<>(this); this.connectionBag = new ConcurrentBag<>(this);
this.totalConnections = new AtomicInteger(); this.totalConnections = new AtomicInteger();
this.suspendResumeLock = config.isAllowPoolSuspension() ? new SuspendResumeLock() : SuspendResumeLock.FAUX_LOCK; this.suspendResumeLock = config.isAllowPoolSuspension() ? new SuspendResumeLock() : SuspendResumeLock.FAUX_LOCK;
@ -168,12 +166,12 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL
} }
final long now = clockSource.currentTime(); final long now = clockSource.currentTime();
if (poolEntry.evict || (clockSource.elapsedMillis(poolEntry.lastAccess, now) > ALIVE_BYPASS_WINDOW_MS && !isConnectionAlive(poolEntry.connection))) { if (poolEntry.evict || (clockSource.elapsedMillis(poolEntry.lastAccessed, now) > ALIVE_BYPASS_WINDOW_MS && !isConnectionAlive(poolEntry.connection))) {
closeConnection(poolEntry, "(connection evicted or dead)"); // Throw away the dead connection and try again closeConnection(poolEntry, "(connection evicted or dead)"); // Throw away the dead connection and try again
timeout = hardTimeout - clockSource.elapsedMillis(startTime, now); timeout = hardTimeout - clockSource.elapsedMillis(startTime, now);
} }
else { else {
metricsContext.setConnectionLastOpen(poolEntry, now); poolEntry.lastBorrowed = now;
metricsContext.stop(); metricsContext.stop();
return poolEntry.createProxyConnection(leakTask.start(poolEntry), now); return poolEntry.createProxyConnection(leakTask.start(poolEntry), now);
} }
@ -627,7 +625,7 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL
if (removable <= 0) { if (removable <= 0) {
break; break;
} }
if (clockSource.elapsedMillis(poolEntry.lastAccess, now) > idleTimeout) { if (clockSource.elapsedMillis(poolEntry.lastAccessed, now) > idleTimeout) {
if (connectionBag.reserve(poolEntry)) { if (connectionBag.reserve(poolEntry)) {
closeConnection(poolEntry, "(connection passed idleTimeout)"); closeConnection(poolEntry, "(connection passed idleTimeout)");
removable--; removable--;

@ -29,8 +29,9 @@ import com.zaxxer.hikari.util.UtilityElf;
abstract class PoolBase abstract class PoolBase
{ {
protected final Logger LOGGER = LoggerFactory.getLogger(getClass()); private final Logger LOGGER = LoggerFactory.getLogger(PoolBase.class);
protected final HikariConfig config; protected final HikariConfig config;
protected final String poolName;
protected long connectionTimeout; protected long connectionTimeout;
private static final String[] RESET_STATES = {"readOnly", "autoCommit", "isolation", "catalog", "netTimeout"}; private static final String[] RESET_STATES = {"readOnly", "autoCommit", "isolation", "catalog", "netTimeout"};
@ -45,8 +46,6 @@ abstract class PoolBase
private Executor netTimeoutExecutor; private Executor netTimeoutExecutor;
private DataSource dataSource; private DataSource dataSource;
// private final HikariPool hikariPool;
private final String poolName;
private final String catalog; private final String catalog;
private final boolean isReadOnly; private final boolean isReadOnly;
private final boolean isAutoCommit; private final boolean isAutoCommit;
@ -78,7 +77,7 @@ abstract class PoolBase
initializeDataSource(); initializeDataSource();
} }
public String getPoolName() String getPoolName()
{ {
return poolName; return poolName;
} }
@ -89,7 +88,7 @@ abstract class PoolBase
// JDBC methods // JDBC methods
// *********************************************************************** // ***********************************************************************
public void quietlyCloseConnection(final Connection connection, final String closureReason) void quietlyCloseConnection(final Connection connection, final String closureReason)
{ {
try { try {
if (connection == null || connection.isClosed()) { if (connection == null || connection.isClosed()) {
@ -110,7 +109,7 @@ abstract class PoolBase
} }
} }
public boolean isConnectionAlive(final Connection connection) boolean isConnectionAlive(final Connection connection)
{ {
try { try {
final long validationTimeout = config.getValidationTimeout(); final long validationTimeout = config.getValidationTimeout();
@ -144,17 +143,16 @@ abstract class PoolBase
} }
} }
public DataSource getUnwrappedDataSource() Throwable getLastConnectionFailure()
{ {
return dataSource; return lastConnectionFailure.getAndSet(null);
} }
public Throwable getLastConnectionFailure() public DataSource getUnwrappedDataSource()
{ {
return lastConnectionFailure.getAndSet(null); return dataSource;
} }
// *********************************************************************** // ***********************************************************************
// PoolEntry methods // PoolEntry methods
// *********************************************************************** // ***********************************************************************
@ -164,7 +162,7 @@ abstract class PoolBase
return new PoolEntry(newConnection(), this); return new PoolEntry(newConnection(), this);
} }
public void resetConnectionState(final Connection connection, final ProxyConnection proxyConnection, final int dirtyBits) throws SQLException void resetConnectionState(final Connection connection, final ProxyConnection proxyConnection, final int dirtyBits) throws SQLException
{ {
int resetBits = 0; int resetBits = 0;
@ -201,9 +199,15 @@ abstract class PoolBase
} }
} }
void shutdownNetworkTimeoutExecutor()
{
if (netTimeoutExecutor != null && netTimeoutExecutor instanceof ThreadPoolExecutor) {
((ThreadPoolExecutor) netTimeoutExecutor).shutdownNow();
}
}
// *********************************************************************** // ***********************************************************************
// PoolMediator methods // JMX methods
// *********************************************************************** // ***********************************************************************
/** /**
@ -259,13 +263,6 @@ abstract class PoolBase
} }
} }
public void shutdownNetworkTimeoutExecutor()
{
if (netTimeoutExecutor != null && netTimeoutExecutor instanceof ThreadPoolExecutor) {
((ThreadPoolExecutor) netTimeoutExecutor).shutdownNow();
}
}
// *********************************************************************** // ***********************************************************************
// Private methods // Private methods
// *********************************************************************** // ***********************************************************************

@ -18,8 +18,6 @@ package com.zaxxer.hikari.pool;
import java.sql.Connection; import java.sql.Connection;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ -37,16 +35,12 @@ import com.zaxxer.hikari.util.FastList;
*/ */
public final class PoolEntry implements IConcurrentBagEntry public final class PoolEntry implements IConcurrentBagEntry
{ {
private static final Logger LOGGER; private static final Logger LOGGER = LoggerFactory.getLogger(PoolEntry.class);
private static final SimpleDateFormat DATE_FORMAT;
public final long creationTime; Connection connection;
long lastAccessed;
public Connection connection; long lastBorrowed;
public long lastAccess; volatile boolean evict;
public volatile long lastOpenTime;
public volatile boolean evict;
private final FastList<Statement> openStatements; private final FastList<Statement> openStatements;
private final PoolBase poolBase; private final PoolBase poolBase;
@ -54,37 +48,30 @@ public final class PoolEntry implements IConcurrentBagEntry
private volatile ScheduledFuture<?> endOfLife; private volatile ScheduledFuture<?> endOfLife;
static
{
LOGGER = LoggerFactory.getLogger(PoolEntry.class);
DATE_FORMAT = new SimpleDateFormat("MMM dd, HH:mm:ss.SSS");
}
PoolEntry(final Connection connection, final PoolBase pool) PoolEntry(final Connection connection, final PoolBase pool)
{ {
this.connection = connection; this.connection = connection;
this.poolBase = pool; this.poolBase = pool;
this.creationTime = System.currentTimeMillis();
this.state = new AtomicInteger(STATE_NOT_IN_USE); this.state = new AtomicInteger(STATE_NOT_IN_USE);
this.lastAccess = ClockSource.INSTANCE.currentTime(); this.lastAccessed = ClockSource.INSTANCE.currentTime();
this.openStatements = new FastList<>(Statement.class, 16); this.openStatements = new FastList<>(Statement.class, 16);
} }
/** /**
* Release this entry back to the pool. * Release this entry back to the pool.
* *
* @param lastAccess last access time-stamp * @param lastAccessed last access time-stamp
*/ */
public void recycle(final long lastAccess) void recycle(final long lastAccessed)
{ {
this.lastAccess = lastAccess; this.lastAccessed = lastAccessed;
poolBase.releaseConnection(this); poolBase.releaseConnection(this);
} }
/** /**
* @param endOfLife * @param endOfLife
*/ */
public void setFutureEol(final ScheduledFuture<?> endOfLife) void setFutureEol(final ScheduledFuture<?> endOfLife)
{ {
this.endOfLife = endOfLife; this.endOfLife = endOfLife;
} }
@ -94,41 +81,42 @@ public final class PoolEntry implements IConcurrentBagEntry
return ProxyFactory.getProxyConnection(this, connection, openStatements, leakTask, now); return ProxyFactory.getProxyConnection(this, connection, openStatements, leakTask, now);
} }
public void resetConnectionState(final ProxyConnection proxyConnection, final int dirtyBits) throws SQLException void resetConnectionState(final ProxyConnection proxyConnection, final int dirtyBits) throws SQLException
{ {
poolBase.resetConnectionState(connection, proxyConnection, dirtyBits); poolBase.resetConnectionState(connection, proxyConnection, dirtyBits);
} }
public String getPoolName() String getPoolName()
{ {
return poolBase.getPoolName(); return poolBase.getPoolName();
} }
public Connection getConnection() Connection getConnection()
{ {
return connection; return connection;
} }
public long getLastAccess() boolean isEvicted()
{
return lastAccess;
}
public boolean isEvicted()
{ {
return evict; return evict;
} }
public void evict() void evict()
{ {
this.evict = true; this.evict = true;
} }
public FastList<Statement> getStatementsList() FastList<Statement> getStatementsList()
{ {
return openStatements; return openStatements;
} }
/** Returns millis since lastBorrowed */
public long getElapsedLastBorrowed()
{
return ClockSource.INSTANCE.elapsedMillis(lastBorrowed);
}
// *********************************************************************** // ***********************************************************************
// IConcurrentBagEntry methods // IConcurrentBagEntry methods
// *********************************************************************** // ***********************************************************************
@ -158,9 +146,10 @@ public final class PoolEntry implements IConcurrentBagEntry
@Override @Override
public String toString() public String toString()
{ {
final long now = ClockSource.INSTANCE.currentTime();
return connection return connection
+ ", created " + formatDateTime(creationTime) + ", borrowed " + ClockSource.INSTANCE.elapsedMillis(lastBorrowed, now) + "ms ago, "
+ ", last release " + ClockSource.INSTANCE.elapsedMillis(lastAccess) + "ms ago, " + ", accessed " + ClockSource.INSTANCE.elapsedMillis(lastAccessed, now) + "ms ago, "
+ stateToString(); + stateToString();
} }
@ -174,11 +163,6 @@ public final class PoolEntry implements IConcurrentBagEntry
connection = null; connection = null;
} }
private static synchronized String formatDateTime(final long timestamp)
{
return DATE_FORMAT.format(new Date(timestamp));
}
private String stateToString() private String stateToString()
{ {
switch (state.get()) { switch (state.get()) {

@ -96,30 +96,30 @@ public abstract class ProxyConnection implements Connection
} }
// *********************************************************************** // ***********************************************************************
// Live Connection State accessors // Connection State Accessors
// *********************************************************************** // ***********************************************************************
public final boolean getAutoCommitState() final boolean getAutoCommitState()
{ {
return isAutoCommit; return isAutoCommit;
} }
public final String getCatalogState() final String getCatalogState()
{ {
return dbcatalog; return dbcatalog;
} }
public final int getTransactionIsolationState() final int getTransactionIsolationState()
{ {
return transactionIsolation; return transactionIsolation;
} }
public final boolean getReadOnlyState() final boolean getReadOnlyState()
{ {
return isReadOnly; return isReadOnly;
} }
public final int getNetworkTimeoutState() final int getNetworkTimeoutState()
{ {
return networkTimeout; return networkTimeout;
} }
@ -129,13 +129,13 @@ public abstract class ProxyConnection implements Connection
// *********************************************************************** // ***********************************************************************
/** {@inheritDoc} */ /** {@inheritDoc} */
public final PoolEntry getPoolEntry() final PoolEntry getPoolEntry()
{ {
return poolEntry; return poolEntry;
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
public final SQLException checkException(final SQLException sqle) final SQLException checkException(final SQLException sqle)
{ {
String sqlState = sqle.getSQLState(); String sqlState = sqle.getSQLState();
if (sqlState != null) { if (sqlState != null) {
@ -156,13 +156,13 @@ public abstract class ProxyConnection implements Connection
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
public final void untrackStatement(final Statement statement) final void untrackStatement(final Statement statement)
{ {
openStatements.remove(statement); openStatements.remove(statement);
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
public final void markCommitStateDirty() final void markCommitStateDirty()
{ {
if (isAutoCommit) { if (isAutoCommit) {
lastAccess = clockSource.currentTime(); lastAccess = clockSource.currentTime();

@ -87,7 +87,7 @@ class ProxyLeakTask implements Runnable
LOGGER.warn("Connection leak detection triggered for connection {}, stack trace follows", connectionName, exception); LOGGER.warn("Connection leak detection triggered for connection {}, stack trace follows", connectionName, exception);
} }
public void cancel() void cancel()
{ {
scheduledFuture.cancel(false); scheduledFuture.cancel(false);
} }

@ -39,7 +39,7 @@ public abstract class ProxyResultSet implements ResultSet
this.delegate = resultSet; this.delegate = resultSet;
} }
protected final SQLException checkException(SQLException e) final SQLException checkException(SQLException e)
{ {
return connection.checkException(e); return connection.checkException(e);
} }

@ -40,7 +40,7 @@ public abstract class ProxyStatement implements Statement
this.delegate = statement; this.delegate = statement;
} }
protected final SQLException checkException(SQLException e) final SQLException checkException(SQLException e)
{ {
return connection.checkException(e); return connection.checkException(e);
} }

@ -244,9 +244,9 @@ public class ConcurrentBag<T extends IConcurrentBagEntry> implements AutoCloseab
public List<T> values(final int state) public List<T> values(final int state)
{ {
final ArrayList<T> list = new ArrayList<>(sharedList.size()); final ArrayList<T> list = new ArrayList<>(sharedList.size());
for (final T reference : sharedList) { for (final T entry : sharedList) {
if (reference.getState() == state) { if (entry.getState() == state) {
list.add(reference); list.add(entry);
} }
} }
@ -320,8 +320,8 @@ public class ConcurrentBag<T extends IConcurrentBagEntry> implements AutoCloseab
public int getCount(final int state) public int getCount(final int state)
{ {
int count = 0; int count = 0;
for (final T reference : sharedList) { for (final T entry : sharedList) {
if (reference.getState() == state) { if (entry.getState() == state) {
count++; count++;
} }
} }

@ -291,7 +291,7 @@ public class ShutdownTest
Assert.fail(e.getMessage()); Assert.fail(e.getMessage());
} }
finally { finally {
TestElf.getPool(ds).quietlyCloseConnection(connection, "(because this is a test)"); try { connection.close(); } catch (SQLException e) { e.printStackTrace(); }
ds.close(); ds.close();
} }
}; };

Loading…
Cancel
Save