Evict connection immediately upon broken state detection.

pull/437/head
Brett Wooldridge 10 years ago
parent 79386c6487
commit 31447dd1e2

@ -165,7 +165,7 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL
}
final long now = clockSource.currentTime();
if (poolEntry.evict || (clockSource.elapsedMillis(poolEntry.lastAccessed, now) > ALIVE_BYPASS_WINDOW_MS && !isConnectionAlive(poolEntry.connection))) {
if (poolEntry.isMarkedEvicted() || (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
timeout = hardTimeout - clockSource.elapsedMillis(startTime);
}
@ -206,12 +206,7 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL
{
metricsTracker.recordConnectionUsage(poolEntry);
if (poolEntry.evict) {
closeConnection(poolEntry, "(connection broken or evicted)");
}
else {
connectionBag.requite(poolEntry);
}
connectionBag.requite(poolEntry);
}
/**
@ -506,7 +501,7 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL
{
for (PoolEntry poolEntry : connectionBag.values(STATE_IN_USE)) {
try {
poolEntry.evict = true;
poolEntry.markEvicted();
poolEntry.connection.abort(assassinExecutor);
}
catch (Throwable e) {
@ -557,7 +552,7 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL
private void softEvictConnection(final PoolEntry poolEntry, final String reason, final boolean owner)
{
poolEntry.evict();
poolEntry.markEvicted();
if (connectionBag.reserve(poolEntry) || owner) {
closeConnection(poolEntry, reason);
}

@ -42,10 +42,10 @@ final class PoolEntry implements IConcurrentBagEntry
Connection connection;
long lastAccessed;
long lastBorrowed;
volatile boolean evict;
private volatile boolean evict;
private final FastList<Statement> openStatements;
private final PoolBase poolBase;
private final HikariPool hikariPool;
private final AtomicInteger state;
private volatile ScheduledFuture<?> endOfLife;
@ -63,7 +63,7 @@ final class PoolEntry implements IConcurrentBagEntry
PoolEntry(final Connection connection, final PoolBase pool)
{
this.connection = connection;
this.poolBase = pool;
this.hikariPool = (HikariPool) pool;
this.state = new AtomicInteger(STATE_NOT_IN_USE);
this.lastAccessed = ClockSource.INSTANCE.currentTime();
this.openStatements = new FastList<>(Statement.class, 16);
@ -77,7 +77,7 @@ final class PoolEntry implements IConcurrentBagEntry
void recycle(final long lastAccessed)
{
this.lastAccessed = lastAccessed;
poolBase.releaseConnection(this);
hikariPool.releaseConnection(this);
}
/**
@ -95,12 +95,12 @@ final class PoolEntry implements IConcurrentBagEntry
void resetConnectionState(final ProxyConnection proxyConnection, final int dirtyBits) throws SQLException
{
poolBase.resetConnectionState(connection, proxyConnection, dirtyBits);
hikariPool.resetConnectionState(connection, proxyConnection, dirtyBits);
}
String getPoolName()
{
return poolBase.toString();
return hikariPool.toString();
}
Connection getConnection()
@ -108,16 +108,21 @@ final class PoolEntry implements IConcurrentBagEntry
return connection;
}
boolean isEvicted()
boolean isMarkedEvicted()
{
return evict;
}
void evict()
void markEvicted()
{
this.evict = true;
}
void evict(final String closureReason)
{
hikariPool.closeConnection(this, closureReason);
}
FastList<Statement> getStatementsList()
{
return openStatements;

@ -140,10 +140,12 @@ public abstract class ProxyConnection implements Connection
String sqlState = sqle.getSQLState();
if (sqlState != null) {
boolean isForceClose = sqlState.startsWith("08") || SQL_ERRORS.contains(sqlState);
if (isForceClose) {
poolEntry.evict();
if (isForceClose && delegate != ClosedConnection.CLOSED_CONNECTION) {
LOGGER.warn("{} - Connection {} marked as broken because of SQLSTATE({}), ErrorCode({})",
poolEntry.getPoolName(), delegate, sqlState, sqle.getErrorCode(), sqle);
leakTask.cancel();
delegate = ClosedConnection.CLOSED_CONNECTION;
poolEntry.evict("(connection broken)");
}
else {
SQLException nse = sqle.getNextException();
@ -211,11 +213,13 @@ public abstract class ProxyConnection implements Connection
@Override
public final void close() throws SQLException
{
// Closing statements can cause connection eviction, so this must run before the conditional below
closeStatements();
if (delegate != ClosedConnection.CLOSED_CONNECTION) {
leakTask.cancel();
try {
closeStatements();
if (isCommitStateDirty && !isAutoCommit) {
delegate.rollback();
lastAccess = clockSource.currentTime();
@ -231,7 +235,7 @@ public abstract class ProxyConnection implements Connection
}
catch (SQLException e) {
// when connections are aborted, exceptions are often thrown that should not reach the application
if (!poolEntry.isEvicted()) {
if (!poolEntry.isMarkedEvicted()) {
throw checkException(e);
}
}

Loading…
Cancel
Save