Merge hikaricp changes into hikaricp-java6.

pull/134/head
Brett Wooldridge 11 years ago
parent b5967fc5a1
commit 2bca598c1b

@ -211,7 +211,7 @@ public class HikariDataSource extends HikariConfig implements DataSource, Closea
public void evictConnection(Connection connection)
{
if (!isShutdown && pool != null && connection instanceof IHikariConnectionProxy) {
pool.closeConnection((IHikariConnectionProxy) connection);
pool.evictConnection((IHikariConnectionProxy) connection);
}
}

@ -16,6 +16,9 @@
package com.zaxxer.hikari.pool;
import static com.zaxxer.hikari.util.ConcurrentBag.STATE_IN_USE;
import static com.zaxxer.hikari.util.ConcurrentBag.STATE_NOT_IN_USE;
import static com.zaxxer.hikari.util.PoolUtilities.IS_JAVA7;
import static com.zaxxer.hikari.util.PoolUtilities.createInstance;
import static com.zaxxer.hikari.util.PoolUtilities.createThreadPoolExecutor;
import static com.zaxxer.hikari.util.PoolUtilities.elapsedTimeMs;
@ -51,9 +54,6 @@ import com.zaxxer.hikari.util.ConcurrentBag.IBagStateListener;
import com.zaxxer.hikari.util.DefaultThreadFactory;
import com.zaxxer.hikari.util.DriverDataSource;
import com.zaxxer.hikari.util.PropertyBeanSetter;
import static com.zaxxer.hikari.util.PoolUtilities.IS_JAVA7;
import static com.zaxxer.hikari.util.ConcurrentBag.STATE_IN_USE;
import static com.zaxxer.hikari.util.ConcurrentBag.STATE_NOT_IN_USE;
/**
* This is the primary connection pool class that provides the basic
@ -65,11 +65,16 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
{
private static final Logger LOGGER = LoggerFactory.getLogger(HikariPool.class);
public int transactionIsolation;
public final String catalog;
public final boolean isAutoCommit;
public final boolean isReadOnly;
private final DataSource dataSource;
private final IConnectionCustomizer connectionCustomizer;
private final HikariConfig configuration;
private final ConcurrentBag<IHikariConnectionProxy> connectionBag;
private final ConcurrentBag<PoolBagEntry> connectionBag;
private final ThreadPoolExecutor addConnectionExecutor;
private final IMetricsTracker metricsTracker;
@ -77,20 +82,16 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
private final AtomicInteger totalConnections;
private final ScheduledThreadPoolExecutor houseKeepingExecutorService;
private final boolean isAutoCommit;
private final boolean isIsolateInternalQueries;
private final boolean isReadOnly;
private final boolean isRecordMetrics;
private final boolean isRegisteredMbeans;
private final boolean isJdbc4ConnectionTest;
private final long leakDetectionThreshold;
private final String catalog;
private final String username;
private final String password;
private volatile long connectionTimeout;
private volatile boolean isShutdown;
private int transactionIsolation;
/**
* Construct a HikariPool with the specified configuration.
@ -116,7 +117,7 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
this.password = password;
this.totalConnections = new AtomicInteger();
this.connectionBag = new ConcurrentBag<IHikariConnectionProxy>();
this.connectionBag = new ConcurrentBag<PoolBagEntry>();
this.connectionBag.addBagStateListener(this);
this.lastConnectionFailure = new AtomicReference<Throwable>();
this.connectionTimeout = configuration.getConnectionTimeout();
@ -166,32 +167,29 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
try {
do {
IHikariConnectionProxy connection = connectionBag.borrow(timeout, TimeUnit.MILLISECONDS);
if (connection == null) {
final PoolBagEntry bagEntry = connectionBag.borrow(timeout, TimeUnit.MILLISECONDS);
if (bagEntry == 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))) {
closeConnection(connection); // Throw away the dead connection and try again
if (now > bagEntry.expirationTime || (now - bagEntry.lastAccess > 1000L && !isConnectionAlive(bagEntry.connection, timeout))) {
closeConnection(bagEntry); // Throw away the dead connection and try again
timeout = connectionTimeout - elapsedTimeMs(start);
continue;
}
if (isIsolateInternalQueries) {
IHikariConnectionProxy newProxy = ProxyFactory.getProxyConnection(connection);
connectionBag.remove(connection);
connectionBag.add(newProxy);
connection = newProxy;
}
final IHikariConnectionProxy proxyConnection = ProxyFactory.getProxyConnection(this, bagEntry);
if (leakDetectionThreshold != 0) {
connection.captureStack(leakDetectionThreshold, houseKeepingExecutorService);
proxyConnection.captureStack(leakDetectionThreshold, houseKeepingExecutorService);
}
if (isRecordMetrics) {
bagEntry.lastOpenTime = now;
}
return connection;
return proxyConnection;
}
while (timeout > 0L);
}
@ -213,19 +211,20 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
* @param connectionProxy the connection to release back to the pool
* @param isBroken true if the connection was detected as broken
*/
public void releaseConnection(final IHikariConnectionProxy connectionProxy, final boolean isBroken)
public void releaseConnection(final PoolBagEntry bagEntry, final boolean isBroken)
{
if (isRecordMetrics) {
metricsTracker.recordConnectionUsage(elapsedTimeMs(connectionProxy.getLastOpenTime()));
metricsTracker.recordConnectionUsage(elapsedTimeMs(bagEntry.lastOpenTime));
}
if (isBroken || isShutdown) {
LOGGER.debug("Connection returned to pool {} is broken, or the pool is shutting down. Closing connection.", configuration.getPoolName());
closeConnection(connectionProxy);
closeConnection(bagEntry);
return;
}
connectionBag.requite(connectionProxy);
bagEntry.lastAccess = System.currentTimeMillis();
connectionBag.requite(bagEntry);
}
/**
@ -259,6 +258,10 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
}
}
public void evictConnection(IHikariConnectionProxy proxyConnection) {
closeConnection(proxyConnection.getPoolBagEntry());
}
/**
* Get the wrapped DataSource.
*
@ -269,28 +272,6 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
return dataSource;
}
/**
* Permanently close the real (underlying) connection (eat any exception).
*
* @param connectionProxy the connection to actually close
*/
public void closeConnection(final IHikariConnectionProxy connectionProxy)
{
try {
int tc = totalConnections.decrementAndGet();
if (tc < 0) {
LOGGER.warn("Internal accounting inconsistency, totalConnections={}", tc, new Exception());
}
connectionProxy.realClose();
}
catch (SQLException e) {
return;
}
finally {
connectionBag.remove(connectionProxy);
}
}
@Override
public String toString()
{
@ -365,9 +346,9 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
@Override
public void closeIdleConnections()
{
for (IHikariConnectionProxy connectionProxy : connectionBag.values(STATE_NOT_IN_USE)) {
if (connectionBag.reserve(connectionProxy)) {
closeConnection(connectionProxy);
for (PoolBagEntry bagEntry : connectionBag.values(STATE_NOT_IN_USE)) {
if (connectionBag.reserve(bagEntry)) {
closeConnection(bagEntry);
}
}
}
@ -383,6 +364,28 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
// Private methods
// ***********************************************************************
/**
* Permanently close the real (underlying) connection (eat any exception).
*
* @param connectionProxy the connection to actually close
*/
private void closeConnection(final PoolBagEntry bagEntry)
{
try {
int tc = totalConnections.decrementAndGet();
if (tc < 0) {
LOGGER.warn("Internal accounting inconsistency, totalConnections={}", tc, new Exception());
}
bagEntry.connection.close();
}
catch (SQLException e) {
return;
}
finally {
connectionBag.remove(bagEntry);
}
}
/**
* Create and add a single connection to the pool.
*/
@ -402,10 +405,16 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
executeSqlAutoCommit(connection, configuration.getConnectionInitSql());
IHikariConnectionProxy proxyConnection = ProxyFactory.getProxyConnection(this, connection, configuration.getMaxLifetime(), transactionIsolation,
isAutoCommit, isReadOnly, catalog);
proxyConnection.resetConnectionState();
connectionBag.add(proxyConnection);
connection.setAutoCommit(isAutoCommit);
connection.setTransactionIsolation(transactionIsolation);
connection.setReadOnly(isReadOnly);
if (catalog != null) {
connection.setCatalog(catalog);
}
PoolBagEntry bagEntry = new PoolBagEntry(connection, configuration.getMaxLifetime());
connectionBag.add(bagEntry);
lastConnectionFailure.set(null);
return true;
}
@ -427,7 +436,7 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
* @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
*/
private boolean isConnectionAlive(final IHikariConnectionProxy connection, long timeoutMs)
private boolean isConnectionAlive(final Connection connection, long timeoutMs)
{
try {
final boolean timeoutEnabled = (configuration.getConnectionTimeout() != Integer.MAX_VALUE);
@ -481,23 +490,23 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
private void abortActiveConnections() throws InterruptedException
{
ExecutorService assassinExecutor = createThreadPoolExecutor(configuration.getMaximumPoolSize(), "HikariCP connection assassin", configuration.getThreadFactory());
for (IHikariConnectionProxy connectionProxy : connectionBag.values(STATE_IN_USE)) {
for (PoolBagEntry bagEntry : connectionBag.values(STATE_IN_USE)) {
try {
connectionProxy.abort(assassinExecutor);
totalConnections.decrementAndGet();
bagEntry.connection.abort(assassinExecutor);
}
catch (AbstractMethodError e) {
quietlyCloseConnection(connectionProxy);
quietlyCloseConnection(bagEntry.connection);
}
catch (SQLException e) {
quietlyCloseConnection(connectionProxy);
quietlyCloseConnection(bagEntry.connection);
}
finally {
try {
connectionBag.remove(connectionProxy);
connectionBag.remove(bagEntry);
totalConnections.decrementAndGet();
}
catch (IllegalStateException ise) {
continue;
break;
}
}
}
@ -558,14 +567,14 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
final long now = System.currentTimeMillis();
final long idleTimeout = configuration.getIdleTimeout();
for (IHikariConnectionProxy connectionProxy : connectionBag.values(STATE_NOT_IN_USE)) {
if (connectionBag.reserve(connectionProxy)) {
if ((idleTimeout > 0L && now > connectionProxy.getLastAccess() + idleTimeout) || (now > connectionProxy.getExpirationTime())) {
closeConnection(connectionProxy);
for (PoolBagEntry bagEntry : connectionBag.values(STATE_NOT_IN_USE)) {
if (connectionBag.reserve(bagEntry)) {
if ((idleTimeout > 0L && now > bagEntry.lastAccess + idleTimeout) || (now > bagEntry.expirationTime)) {
closeConnection(bagEntry);
continue;
}
connectionBag.unreserve(connectionProxy);
connectionBag.unreserve(bagEntry);
}
}

@ -0,0 +1,40 @@
/*
* Copyright (C) 2013 Brett Wooldridge
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zaxxer.hikari.pool;
import java.sql.Connection;
import com.zaxxer.hikari.util.ConcurrentBag.BagEntry;
/**
*
* @author Brett Wooldridge
*/
public class PoolBagEntry extends BagEntry
{
public final Connection connection;
public final long expirationTime;
long lastOpenTime;
long lastAccess;
PoolBagEntry(final Connection connection, long maxLifetime) {
this.connection = connection;
expirationTime = (maxLifetime > 0 ? System.currentTimeMillis() + maxLifetime : Long.MAX_VALUE);
lastAccess = expirationTime;
}
}

@ -26,12 +26,12 @@ import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.zaxxer.hikari.pool.HikariPool;
import com.zaxxer.hikari.pool.PoolBagEntry;
import com.zaxxer.hikari.util.FastList;
/**
@ -47,14 +47,8 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
protected final Connection delegate;
private final FastList<Statement> openStatements;
private final HikariPool parentPool;
private final AtomicInteger state;
private final String defaultCatalog;
private final long expirationTime;
private final int defaultIsolationLevel;
private final boolean defaultAutoCommit;
private final boolean defaultReadOnly;
private final PoolBagEntry bagEntry;
private boolean forceClose;
private boolean isAutoCommitDirty;
@ -62,13 +56,10 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
private boolean isClosed;
private boolean isReadOnlyDirty;
private boolean isTransactionIsolationDirty;
private volatile long lastAccess;
private long uncloseTime;
private FastList<Statement> openStatements;
private LeakTask leakTask;
private final int hashCode;
// static initializer
static {
SQL_ERRORS = new HashSet<String>();
@ -80,64 +71,12 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
SQL_ERRORS.add("JZ0C1"); // Sybase disconnect error
}
protected ConnectionProxy(HikariPool pool, Connection connection, long maxLifetime, int defaultIsolationLevel, boolean defaultAutoCommit,
boolean defaultReadOnly, String defaultCatalog)
{
protected ConnectionProxy(final HikariPool pool, final PoolBagEntry bagEntry) {
this.parentPool = pool;
this.delegate = connection;
this.defaultIsolationLevel = defaultIsolationLevel;
this.defaultAutoCommit = defaultAutoCommit;
this.defaultReadOnly = defaultReadOnly;
this.defaultCatalog = defaultCatalog;
this.state = new AtomicInteger();
long now = System.currentTimeMillis();
this.expirationTime = (maxLifetime > 0 ? now + maxLifetime : Long.MAX_VALUE);
this.lastAccess = now;
this.openStatements = new FastList<Statement>(Statement.class);
this.hashCode = System.identityHashCode(this);
isCatalogDirty = true;
isReadOnlyDirty = defaultReadOnly;
isAutoCommitDirty = true;
isTransactionIsolationDirty = true;
}
protected ConnectionProxy(final IHikariConnectionProxy proxy)
{
final ConnectionProxy copyProxy = (ConnectionProxy) proxy;
this.parentPool = copyProxy.parentPool;
this.delegate = copyProxy.delegate;
this.defaultIsolationLevel = copyProxy.defaultIsolationLevel;
this.defaultAutoCommit = copyProxy.defaultAutoCommit;
this.defaultReadOnly = copyProxy.defaultReadOnly;
this.defaultCatalog = copyProxy.defaultCatalog;
this.state = new AtomicInteger(copyProxy.getState());
this.expirationTime = copyProxy.expirationTime;
this.lastAccess = this.uncloseTime = System.currentTimeMillis();
this.openStatements = new FastList<Statement>(Statement.class);
this.hashCode = System.identityHashCode(this);
this.isCatalogDirty = copyProxy.isCatalogDirty;
this.isReadOnlyDirty = copyProxy.isReadOnlyDirty;
this.isAutoCommitDirty = copyProxy.isAutoCommitDirty;
this.isTransactionIsolationDirty = copyProxy.isTransactionIsolationDirty;
}
this.bagEntry = bagEntry;
this.delegate = bagEntry.connection;
/** {@inheritDoc} */
@Override
public final boolean equals(Object other)
{
return this == other;
}
/** {@inheritDoc} */
@Override
public final int hashCode()
{
return hashCode;
this.openStatements = new FastList<Statement>(Statement.class, 16);
}
@Override
@ -150,6 +89,13 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
// IHikariConnectionProxy methods
// ***********************************************************************
/** {@inheritDoc} */
@Override
public PoolBagEntry getPoolBagEntry()
{
return bagEntry;
}
/** {@inheritDoc} */
@Override
public final void captureStack(long leakDetectionThreshold, ScheduledExecutorService executorService)
@ -179,27 +125,6 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
}
}
/** {@inheritDoc} */
@Override
public final long getExpirationTime()
{
return expirationTime;
}
/** {@inheritDoc} */
@Override
public final long getLastAccess()
{
return lastAccess;
}
/** {@inheritDoc} */
@Override
public long getLastOpenTime()
{
return uncloseTime;
}
/** {@inheritDoc} */
@Override
public final boolean isBrokenConnection()
@ -207,52 +132,6 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
return forceClose;
}
/** {@inheritDoc} */
@Override
public final void realClose() throws SQLException
{
delegate.close();
}
/** {@inheritDoc} */
@Override
public final void resetConnectionState() throws SQLException
{
if (!delegate.getAutoCommit()) {
delegate.rollback();
}
if (isReadOnlyDirty) {
delegate.setReadOnly(defaultReadOnly);
isReadOnlyDirty = false;
}
if (isAutoCommitDirty) {
delegate.setAutoCommit(defaultAutoCommit);
isAutoCommitDirty = false;
}
if (isTransactionIsolationDirty) {
delegate.setTransactionIsolation(defaultIsolationLevel);
isTransactionIsolationDirty = false;
}
if (isCatalogDirty && defaultCatalog != null) {
delegate.setCatalog(defaultCatalog);
isCatalogDirty = false;
}
delegate.clearWarnings();
}
/** {@inheritDoc} */
@Override
public final void unclose(final long now)
{
isClosed = false;
uncloseTime = now;
}
/** {@inheritDoc} */
@Override
public final void untrackStatement(Statement statement)
@ -283,22 +162,29 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
return statement;
}
// **********************************************************************
// IBagManagable Methods
// **********************************************************************
/** {@inheritDoc} */
@Override
public final int getState()
private final void resetConnectionState() throws SQLException
{
return state.get();
}
if (!delegate.getAutoCommit()) {
delegate.rollback();
}
/** {@inheritDoc} */
@Override
public final boolean compareAndSetState(int expectedState, int newState)
{
return state.compareAndSet(expectedState, newState);
if (isReadOnlyDirty) {
delegate.setReadOnly(parentPool.isReadOnly);
}
if (isAutoCommitDirty) {
delegate.setAutoCommit(parentPool.isAutoCommit);
}
if (isTransactionIsolationDirty) {
delegate.setTransactionIsolation(parentPool.transactionIsolation);
}
if (isCatalogDirty && parentPool.catalog != null) {
delegate.setCatalog(parentPool.catalog);
}
delegate.clearWarnings();
}
// **********************************************************************
@ -329,7 +215,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
}
}
openStatements.clear();
openStatements = null;
}
resetConnectionState();
@ -339,8 +225,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
throw e;
}
finally {
lastAccess = System.currentTimeMillis();
parentPool.releaseConnection(this, forceClose);
parentPool.releaseConnection(bagEntry, forceClose);
}
}
}
@ -560,7 +445,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
checkClosed();
try {
delegate.setAutoCommit(autoCommit);
isAutoCommitDirty = (autoCommit != defaultAutoCommit);
isAutoCommitDirty = (autoCommit != parentPool.isAutoCommit);
}
catch (SQLException e) {
checkException(e);
@ -575,7 +460,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
checkClosed();
try {
delegate.setReadOnly(readOnly);
isReadOnlyDirty = (readOnly != defaultReadOnly);
isReadOnlyDirty = (readOnly != parentPool.isReadOnly);
}
catch (SQLException e) {
checkException(e);
@ -590,7 +475,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
checkClosed();
try {
delegate.setTransactionIsolation(level);
isTransactionIsolationDirty = (level != defaultIsolationLevel);
isTransactionIsolationDirty = (level != parentPool.transactionIsolation);
}
catch (SQLException e) {
checkException(e);
@ -604,7 +489,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
checkClosed();
try {
delegate.setCatalog(catalog);
isCatalogDirty = !catalog.equals(defaultCatalog);
isCatalogDirty = !catalog.equals(parentPool.catalog);
}
catch (SQLException e) {
checkException(e);

@ -21,7 +21,7 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.util.concurrent.ScheduledExecutorService;
import com.zaxxer.hikari.util.ConcurrentBag.IBagManagable;
import com.zaxxer.hikari.pool.PoolBagEntry;
/**
* The interface used by the Connection proxy and through which all interaction
@ -29,8 +29,15 @@ import com.zaxxer.hikari.util.ConcurrentBag.IBagManagable;
*
* @author Brett Wooldridge
*/
public interface IHikariConnectionProxy extends Connection, IBagManagable
public interface IHikariConnectionProxy extends Connection
{
/**
* Get the ConcurrentBag entry that is associated in the pool with the underlying connection.
*
* @return the PoolBagEntry
*/
PoolBagEntry getPoolBagEntry();
/**
* Catpure the stack and start leak detection.
*
@ -76,26 +83,6 @@ public interface IHikariConnectionProxy extends Connection, IBagManagable
*/
boolean isBrokenConnection();
/**
* Actually close the underlying delegate Connection.
*
* @throws SQLException rethrown from the underlying delegate Connection
*/
void realClose() throws SQLException;
/**
* Reset the delegate Connection back to pristine state.
*
* @throws SQLException thrown if there is an error resetting any of the state
*/
void resetConnectionState() throws SQLException;
/**
* Make the Connection available for use again by marking it as not closed.
* @param now the current time in milliseconds
*/
void unclose(long now);
/**
* Called by Statement and its subclasses when they are closed to remove them
* from the tracking list.

@ -22,6 +22,7 @@ import java.sql.PreparedStatement;
import java.sql.Statement;
import com.zaxxer.hikari.pool.HikariPool;
import com.zaxxer.hikari.pool.PoolBagEntry;
/**
* A factory class that produces proxies around instances of the standard
@ -41,39 +42,32 @@ public final class ProxyFactory
*
* @param pool the {@link HikariPool} that will own this proxy
* @param connection the {@link Connection} that will be wrapped by this proxy
* @param maxLifeTime the lifetime of the connection
* @param bagManagable the IBagManagable entry for this proxy
* @param defaultIsolationLevel the default transaction isolation level of the underlying {@link Connection}
* @param defaultAutoCommit the default auto-commit state of the underlying {@link Connection}
* @param defaultIReadOnly the default readOnly state of the underlying {@link Connection}
* @param defaultCatalog the default catalog of the underlying {@link Connection}
* @return a proxy that wraps the specified {@link Connection}
*/
public static IHikariConnectionProxy getProxyConnection(HikariPool pool, Connection connection, long maxLifeTime, int defaultIsolationLevel,
boolean defaultAutoCommit, boolean defaultIReadOnly, String defaultCatalog)
public static IHikariConnectionProxy getProxyConnection(final HikariPool pool, final PoolBagEntry bagEntry)
{
// Body is injected by JavassistProxyFactory
return null;
}
public static IHikariConnectionProxy getProxyConnection(IHikariConnectionProxy copyProxy)
{
// Body is injected by JavassistProxyFactory
return null;
}
static Statement getProxyStatement(ConnectionProxy connection, Statement statement)
static Statement getProxyStatement(final ConnectionProxy connection, final Statement statement)
{
// Body is injected by JavassistProxyFactory
return null;
}
static CallableStatement getProxyCallableStatement(ConnectionProxy connection, CallableStatement statement)
static CallableStatement getProxyCallableStatement(final ConnectionProxy connection, final CallableStatement statement)
{
// Body is injected by JavassistProxyFactory
return null;
}
static PreparedStatement getProxyPreparedStatement(ConnectionProxy connection, PreparedStatement statement)
static PreparedStatement getProxyPreparedStatement(final ConnectionProxy connection, final PreparedStatement statement)
{
// Body is injected by JavassistProxyFactory
return null;

@ -22,12 +22,15 @@ import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.AbstractQueuedLongSynchronizer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.zaxxer.hikari.util.ConcurrentBag.BagEntry;
/**
* This is a specialized concurrent bag that achieves superior performance
* to LinkedBlockingQueue and LinkedTransferQueue for the purposes of a
@ -48,7 +51,7 @@ import org.slf4j.LoggerFactory;
*
* @param <T> the templated type to store in the bag
*/
public class ConcurrentBag<T extends com.zaxxer.hikari.util.ConcurrentBag.IBagManagable>
public final class ConcurrentBag<T extends BagEntry>
{
private static final Logger LOGGER = LoggerFactory.getLogger(ConcurrentBag.class);
@ -57,17 +60,9 @@ public class ConcurrentBag<T extends com.zaxxer.hikari.util.ConcurrentBag.IBagMa
private static final int STATE_REMOVED = -1;
private static final int STATE_RESERVED = -2;
/**
* This interface must be implemented by classes wishing to be managed by
* ConcurrentBag. All implementations must be atomic with respect to state.
* The suggested implementation is via AtomicInteger using the methods
* <code>get()</code> and <code>compareAndSet()</code>.
*/
public interface IBagManagable
public static abstract class BagEntry
{
int getState();
boolean compareAndSetState(int expectedState, int newState);
final AtomicInteger state = new AtomicInteger();
}
/**
@ -76,7 +71,7 @@ public class ConcurrentBag<T extends com.zaxxer.hikari.util.ConcurrentBag.IBagMa
* of action by the listener in this case is to attempt to add an item
* to the bag.
*/
public interface IBagStateListener
public static interface IBagStateListener
{
void addBagItem();
}
@ -116,10 +111,9 @@ public class ConcurrentBag<T extends com.zaxxer.hikari.util.ConcurrentBag.IBagMa
threadList.set(list);
}
else {
for (int i = list.size() - 1; i >= 0; i--) {
final WeakReference<T> reference = list.removeLast();
final T element = reference.get();
if (element != null && element.compareAndSetState(STATE_NOT_IN_USE, STATE_IN_USE)) {
for (int i = list.size(); i > 0; i--) {
final T element = list.removeLast().get();
if (element != null && element.state.compareAndSet(STATE_NOT_IN_USE, STATE_IN_USE)) {
return element;
}
}
@ -133,7 +127,7 @@ public class ConcurrentBag<T extends com.zaxxer.hikari.util.ConcurrentBag.IBagMa
do {
startSeq = sequence.longValue();
for (T reference : sharedList) {
if (reference.compareAndSetState(STATE_NOT_IN_USE, STATE_IN_USE)) {
if (reference.state.compareAndSet(STATE_NOT_IN_USE, STATE_IN_USE)) {
return reference;
}
}
@ -167,14 +161,16 @@ public class ConcurrentBag<T extends com.zaxxer.hikari.util.ConcurrentBag.IBagMa
throw new NullPointerException("Cannot return a null value to the bag");
}
if (value.compareAndSetState(STATE_IN_USE, STATE_NOT_IN_USE)) {
FastList<WeakReference<T>> list = threadList.get();
if (value.state.compareAndSet(STATE_IN_USE, STATE_NOT_IN_USE)) {
final FastList<WeakReference<T>> list = threadList.get();
if (list == null) {
list = new FastList<WeakReference<T>>(WeakReference.class);
threadList.set(list);
FastList<WeakReference<T>> newList = new FastList<WeakReference<T>>(WeakReference.class);
threadList.set(newList);
newList.add(new WeakReference<T>(value));
}
else {
list.add(new WeakReference<T>(value));
}
list.add(new WeakReference<T>(value));
synchronizer.releaseShared(sequence.incrementAndGet());
}
else {
@ -202,7 +198,7 @@ public class ConcurrentBag<T extends com.zaxxer.hikari.util.ConcurrentBag.IBagMa
*/
public void remove(final T value)
{
if (value.compareAndSetState(STATE_IN_USE, STATE_REMOVED) || value.compareAndSetState(STATE_RESERVED, STATE_REMOVED)) {
if (value.state.compareAndSet(STATE_IN_USE, STATE_REMOVED) || value.state.compareAndSet(STATE_RESERVED, STATE_REMOVED)) {
if (!sharedList.remove(value)) {
throw new IllegalStateException("Attempt to remove an object from the bag that does not exist");
}
@ -226,7 +222,7 @@ public class ConcurrentBag<T extends com.zaxxer.hikari.util.ConcurrentBag.IBagMa
ArrayList<T> list = new ArrayList<T>(sharedList.size());
if (state == STATE_IN_USE || state == STATE_NOT_IN_USE) {
for (T reference : sharedList) {
if (reference.getState() == state) {
if (reference.state.get() == state) {
list.add(reference);
}
}
@ -248,7 +244,7 @@ public class ConcurrentBag<T extends com.zaxxer.hikari.util.ConcurrentBag.IBagMa
*/
public boolean reserve(final T value)
{
return value.compareAndSetState(STATE_NOT_IN_USE, STATE_RESERVED);
return value.state.compareAndSet(STATE_NOT_IN_USE, STATE_RESERVED);
}
/**
@ -260,7 +256,7 @@ public class ConcurrentBag<T extends com.zaxxer.hikari.util.ConcurrentBag.IBagMa
public void unreserve(final T value)
{
final long checkInSeq = sequence.incrementAndGet();
if (!value.compareAndSetState(STATE_RESERVED, STATE_NOT_IN_USE)) {
if (!value.state.compareAndSet(STATE_RESERVED, STATE_NOT_IN_USE)) {
throw new IllegalStateException("Attempt to relinquish an object to the bag that was not reserved");
}
@ -293,7 +289,7 @@ public class ConcurrentBag<T extends com.zaxxer.hikari.util.ConcurrentBag.IBagMa
{
int count = 0;
for (T reference : sharedList) {
if (reference.getState() == state) {
if (reference.state.get() == state) {
count++;
}
}
@ -313,7 +309,7 @@ public class ConcurrentBag<T extends com.zaxxer.hikari.util.ConcurrentBag.IBagMa
public void dumpState()
{
for (T reference : sharedList) {
switch (reference.getState()) {
switch (reference.state.get()) {
case STATE_IN_USE:
LOGGER.info(reference.toString() + " state IN_USE");
break;

@ -29,7 +29,7 @@ public class ConnectionStateTest
connection.close();
Connection connection2 = ds.getConnection();
Assert.assertSame(connection, connection2);
Assert.assertSame(connection.unwrap(Connection.class), connection2.unwrap(Connection.class));
Assert.assertTrue(connection2.getAutoCommit());
connection2.close();
}
@ -56,7 +56,7 @@ public class ConnectionStateTest
connection.close();
Connection connection2 = ds.getConnection();
Assert.assertSame(connection, connection2);
Assert.assertSame(connection.unwrap(Connection.class), connection2.unwrap(Connection.class));
Assert.assertEquals(Connection.TRANSACTION_READ_COMMITTED, connection2.getTransactionIsolation());
connection2.close();
}
@ -95,7 +95,7 @@ public class ConnectionStateTest
connection.close();
Connection connection2 = ds.getConnection();
Assert.assertSame(connection, connection2);
Assert.assertSame(connection.unwrap(Connection.class), connection2.unwrap(Connection.class));
Assert.assertEquals("test", connection2.getCatalog());
connection2.close();
}

@ -51,7 +51,6 @@ public class IsolationTest
Connection connection2 = ds.getConnection();
connection2.close();
Assert.assertSame(connection, connection2);
Assert.assertSame(connection.unwrap(Connection.class), connection2.unwrap(Connection.class));
}
finally

@ -115,7 +115,7 @@ public class TestConnections
Assert.assertSame("Idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
Connection connection2 = ds.getConnection();
Assert.assertSame("Expected the same connection", connection, connection2);
Assert.assertSame(connection.unwrap(Connection.class), connection2.unwrap(Connection.class));
Assert.assertSame("Second total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Second idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
connection2.close();
@ -165,7 +165,7 @@ public class TestConnections
Assert.assertSame("Idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
Connection connection2 = ds.getConnection();
Assert.assertSame("Expected the same connection", connection, connection2);
Assert.assertSame(connection.unwrap(Connection.class), connection2.unwrap(Connection.class));
Assert.assertSame("Second total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Second idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
connection2.close();

@ -337,9 +337,9 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
@Override
public void closeIdleConnections()
{
connectionBag.values(STATE_NOT_IN_USE).forEach(connectionProxy -> {
if (connectionBag.reserve(connectionProxy)) {
closeConnection(connectionProxy);
connectionBag.values(STATE_NOT_IN_USE).forEach(bagEntry -> {
if (connectionBag.reserve(bagEntry)) {
closeConnection(bagEntry);
}
});
}

@ -501,7 +501,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
@Override
public final boolean isWrapperFor(Class<?> iface) throws SQLException
{
return iface.isInstance(delegate) || (delegate instanceof Wrapper && delegate.isWrapperFor(iface));
return iface.isInstance(delegate) || (delegate instanceof Wrapper && delegate.isWrapperFor(iface));
}
/** {@inheritDoc} */

@ -86,7 +86,7 @@ public class TestFastList
}
FastList<Base> list = new FastList<>(Base.class, 2);
FastList<Base> list = new FastList<Base>(Base.class, 2);
list.add(new Foo());
list.add(new Foo());
list.add(new Bar());

Loading…
Cancel
Save