Merge branch 'experimental' into dev

* experimental:
  Add retrograde time motion detection, with soft-eviction.
  Fix unit test breakage and warnings.
  FastList reuse and other minor optimizations.
pull/316/merge
Brett Wooldridge 10 years ago
commit cb37a6d730

@ -102,7 +102,7 @@ public final class CodaHaleMetricsTracker extends MetricsTracker
@Override
public void recordConnectionUsage(final PoolBagEntry bagEntry)
{
connectionUsage.update(elapsedTimeMs(bagEntry.lastOpenNano));
connectionUsage.update(elapsedTimeMs(bagEntry.lastOpenTime));
}
public Timer getConnectionAcquisitionTimer()
@ -132,9 +132,9 @@ public final class CodaHaleMetricsTracker extends MetricsTracker
/** {@inheritDoc} */
@Override
public void setConnectionLastOpen(final PoolBagEntry bagEntry, final long nowNanos)
public void setConnectionLastOpen(final PoolBagEntry bagEntry, final long nowMillis)
{
bagEntry.lastOpenNano = nowNanos;
bagEntry.lastOpenTime = nowMillis;
}
}
}

@ -23,9 +23,8 @@ import static com.zaxxer.hikari.util.IConcurrentBagEntry.STATE_NOT_IN_USE;
import static com.zaxxer.hikari.util.IConcurrentBagEntry.STATE_REMOVED;
import static com.zaxxer.hikari.util.UtilityElf.createThreadPoolExecutor;
import static com.zaxxer.hikari.util.UtilityElf.elapsedTimeMs;
import static com.zaxxer.hikari.util.UtilityElf.elapsedNanos;
import static com.zaxxer.hikari.util.UtilityElf.getTransactionIsolation;
import static com.zaxxer.hikari.util.UtilityElf.quietlySleepMs;
import static com.zaxxer.hikari.util.UtilityElf.quietlySleep;
import java.sql.Connection;
import java.sql.SQLException;
@ -69,7 +68,8 @@ import com.zaxxer.hikari.util.IBagStateListener;
public class HikariPool implements HikariPoolMBean, IBagStateListener
{
protected final Logger LOGGER = LoggerFactory.getLogger(getClass());
private static final long ALIVE_BYPASS_WINDOW = Long.getLong("com.zaxxer.hikari.aliveBypassWindowNs", TimeUnit.SECONDS.toNanos(1));
private 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));
protected static final int POOL_NORMAL = 0;
protected static final int POOL_SUSPENDED = 1;
@ -92,7 +92,7 @@ public class HikariPool implements HikariPoolMBean, IBagStateListener
protected final boolean isIsolateInternalQueries;
protected volatile int poolState;
protected volatile long connectionTimeoutNanos;
protected volatile long connectionTimeout;
protected volatile long validationTimeout;
private final LeakTask leakTask;
@ -122,7 +122,7 @@ public class HikariPool implements HikariPoolMBean, IBagStateListener
this.connectionBag = new ConcurrentBag<PoolBagEntry>(this);
this.totalConnections = new AtomicInteger();
this.connectionTimeoutNanos = TimeUnit.MILLISECONDS.toNanos(config.getConnectionTimeout());
this.connectionTimeout = config.getConnectionTimeout();
this.validationTimeout = config.getValidationTimeout();
this.lastConnectionFailure = new AtomicReference<Throwable>();
@ -142,15 +142,14 @@ public class HikariPool implements HikariPoolMBean, IBagStateListener
this.addConnectionExecutor = createThreadPoolExecutor(config.getMaximumPoolSize(), "HikariCP connection filler (pool " + config.getPoolName() + ")", config.getThreadFactory(), new ThreadPoolExecutor.DiscardPolicy());
this.closeConnectionExecutor = createThreadPoolExecutor(4, "HikariCP connection closer (pool " + config.getPoolName() + ")", config.getThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());
long delayPeriod = Long.getLong("com.zaxxer.hikari.housekeeping.periodMs", TimeUnit.SECONDS.toMillis(30L));
ThreadFactory threadFactory = config.getThreadFactory() != null ? config.getThreadFactory() : new DefaultThreadFactory("Hikari Housekeeping Timer (pool " + config.getPoolName() + ")", true);
this.houseKeepingExecutorService = new ScheduledThreadPoolExecutor(1, threadFactory, new ThreadPoolExecutor.DiscardPolicy());
this.houseKeepingExecutorService.scheduleAtFixedRate(new HouseKeeper(), delayPeriod, delayPeriod, TimeUnit.MILLISECONDS);
this.houseKeepingExecutorService.scheduleAtFixedRate(new HouseKeeper(), HOUSEKEEPING_PERIOD_MS, HOUSEKEEPING_PERIOD_MS, TimeUnit.MILLISECONDS);
this.houseKeepingExecutorService.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
this.houseKeepingExecutorService.setRemoveOnCancelPolicy(true);
this.leakTask = (config.getLeakDetectionThreshold() == 0) ? LeakTask.NO_LEAK : new LeakTask(config.getLeakDetectionThreshold(), houseKeepingExecutorService);
poolUtils.setLoginTimeout(dataSource, config.getConnectionTimeout());
poolUtils.setLoginTimeout(dataSource, connectionTimeout);
registerMBeans(config, this);
initializeConnections();
}
@ -163,39 +162,39 @@ public class HikariPool implements HikariPoolMBean, IBagStateListener
*/
public final Connection getConnection() throws SQLException
{
return getConnection(connectionTimeoutNanos);
return getConnection(connectionTimeout);
}
/**
* Get a connection from the pool, or timeout after the specified number of nanoseconds.
* Get a connection from the pool, or timeout after the specified number of milliseconds.
*
* @param hardTimeoutNanos the maximum time to wait for a connection from the pool
* @param hardTimeout the maximum time to wait for a connection from the pool
* @return a java.sql.Connection instance
* @throws SQLException thrown if a timeout occurs trying to obtain a connection
*/
public final Connection getConnection(final long hardTimeoutNanos) throws SQLException
public final Connection getConnection(final long hardTimeout) throws SQLException
{
suspendResumeLock.acquire();
long timeout = hardTimeoutNanos;
final long startNano = System.nanoTime();
final MetricsContext metricsContext = (isRecordMetrics ? metricsTracker.recordConnectionRequest(startNano) : MetricsTracker.NO_CONTEXT);
long timeout = hardTimeout;
final long start = System.currentTimeMillis();
final MetricsContext metricsContext = (isRecordMetrics ? metricsTracker.recordConnectionRequest(start) : MetricsTracker.NO_CONTEXT);
try {
do {
final PoolBagEntry bagEntry = connectionBag.borrow(timeout);
final PoolBagEntry bagEntry = connectionBag.borrow(timeout, TimeUnit.MILLISECONDS);
if (bagEntry == null) {
break; // We timed out... break and throw exception
}
final long nowNano = System.nanoTime();
if (bagEntry.evicted || (nowNano - bagEntry.lastAccessNano > ALIVE_BYPASS_WINDOW && !isConnectionAlive(bagEntry.connection))) {
final long now = System.currentTimeMillis();
if (bagEntry.evicted || (now - bagEntry.lastAccess > ALIVE_BYPASS_WINDOW_MS && !isConnectionAlive(bagEntry.connection))) {
closeConnection(bagEntry, "connection evicted or dead"); // Throw away the dead connection and try again
timeout = hardTimeoutNanos - elapsedNanos(startNano);
timeout = hardTimeout - elapsedTimeMs(start);
}
else {
metricsContext.setConnectionLastOpen(bagEntry, nowNano);
metricsContext.setConnectionLastOpen(bagEntry, now);
metricsContext.stop();
return ProxyFactory.getProxyConnection(this, bagEntry, leakTask.start(bagEntry));
return ProxyFactory.getProxyConnection(bagEntry, leakTask.start(bagEntry), now);
}
}
while (timeout > 0L);
@ -208,7 +207,7 @@ public class HikariPool implements HikariPoolMBean, IBagStateListener
}
logPoolState("Timeout failure ");
throw new SQLTimeoutException(String.format("Timeout after %dms of waiting for a connection.", elapsedTimeMs(startNano)), lastConnectionFailure.getAndSet(null));
throw new SQLTimeoutException(String.format("Timeout after %dms of waiting for a connection.", elapsedTimeMs(start)), lastConnectionFailure.getAndSet(null));
}
/**
@ -254,12 +253,12 @@ public class HikariPool implements HikariPoolMBean, IBagStateListener
final ExecutorService assassinExecutor = createThreadPoolExecutor(configuration.getMaximumPoolSize(), "HikariCP connection assassin",
configuration.getThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());
try {
final long startNano = System.nanoTime();
final long start = System.currentTimeMillis();
do {
softEvictConnections();
abortActiveConnections(assassinExecutor);
}
while (getTotalConnections() > 0 && elapsedNanos(startNano) < TimeUnit.SECONDS.toNanos(5));
while (getTotalConnections() > 0 && elapsedTimeMs(start) < TimeUnit.SECONDS.toMillis(5));
} finally {
assassinExecutor.shutdown();
assassinExecutor.awaitTermination(5L, TimeUnit.SECONDS);
@ -359,13 +358,13 @@ public class HikariPool implements HikariPoolMBean, IBagStateListener
@Override
public void run()
{
long sleepBackoffMs = 200L;
long sleepBackoff = 200L;
final int minimumIdle = configuration.getMinimumIdle();
final int maxPoolSize = configuration.getMaximumPoolSize();
while (poolState == POOL_NORMAL && totalConnections.get() < maxPoolSize && getIdleConnections() <= minimumIdle && !addConnection()) {
// If we got into the loop, addConnection() failed, so we sleep and retry
quietlySleepMs(sleepBackoffMs);
sleepBackoffMs = Math.min(TimeUnit.NANOSECONDS.toMillis(connectionTimeoutNanos / 2), (long) ((double) sleepBackoffMs * 1.5));
quietlySleep(sleepBackoff);
sleepBackoff = Math.min(connectionTimeout / 2, (long) ((double) sleepBackoff * 1.5));
}
}
}, true);
@ -498,7 +497,7 @@ public class HikariPool implements HikariPoolMBean, IBagStateListener
throw new SQLException("JDBC4 Connection.isValid() method not supported, connection test query must be configured");
}
final int originalTimeout = poolUtils.getAndSetNetworkTimeout(connection, TimeUnit.NANOSECONDS.toMillis(connectionTimeoutNanos));
final int originalTimeout = poolUtils.getAndSetNetworkTimeout(connection, connectionTimeout);
transactionIsolation = (transactionIsolation < 0 ? connection.getTransactionIsolation() : transactionIsolation);
@ -636,22 +635,33 @@ public class HikariPool implements HikariPoolMBean, IBagStateListener
*/
private class HouseKeeper implements Runnable
{
private volatile long previous = System.currentTimeMillis();
@Override
public void run()
{
logPoolState("Before cleanup ");
connectionTimeout = configuration.getConnectionTimeout(); // refresh member in case it changed
connectionTimeoutNanos = TimeUnit.MILLISECONDS.toNanos(configuration.getConnectionTimeout()); // refresh member in case it changed
final long now = System.currentTimeMillis();
final long idleTimeout = configuration.getIdleTimeout();
final long nowNanos = System.nanoTime();
final long idleTimeout = TimeUnit.MILLISECONDS.toNanos(configuration.getIdleTimeout());
// Detect retrograde time as well as forward leaps of unacceptable duration
if (now < previous || now > previous + (2 * HOUSEKEEPING_PERIOD_MS)) {
LOGGER.warn("Unusual system clock change detected, soft-evicting connections from pool.");
softEvictConnections();
fillPool();
return;
}
previous = now;
logPoolState("Before cleanup ");
for (PoolBagEntry bagEntry : connectionBag.values(STATE_NOT_IN_USE)) {
if (connectionBag.reserve(bagEntry)) {
if (bagEntry.evicted) {
closeConnection(bagEntry, "connection evicted");
}
else if (idleTimeout > 0L && nowNanos - bagEntry.lastAccessNano > idleTimeout) {
else if (idleTimeout > 0L && now - bagEntry.lastAccess > idleTimeout) {
closeConnection(bagEntry, "connection passed idleTimeout");
}
else {

@ -16,11 +16,13 @@
package com.zaxxer.hikari.pool;
import java.sql.Connection;
import java.sql.Statement;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import com.zaxxer.hikari.util.FastList;
import com.zaxxer.hikari.util.IConcurrentBagEntry;
/**
@ -31,10 +33,12 @@ import com.zaxxer.hikari.util.IConcurrentBagEntry;
public final class PoolBagEntry implements IConcurrentBagEntry
{
public final AtomicInteger state = new AtomicInteger();
public final FastList<Statement> openStatements;
public final HikariPool parentPool;
public Connection connection;
public long lastAccessNano;
public long lastOpenNano;
public long lastAccess;
public long lastOpenTime;
public volatile boolean evicted;
public volatile boolean aborted;
@ -43,9 +47,11 @@ public final class PoolBagEntry implements IConcurrentBagEntry
public PoolBagEntry(final Connection connection, final HikariPool pool) {
this.connection = connection;
this.lastAccessNano = System.nanoTime();
this.parentPool = pool;
this.lastAccess = System.currentTimeMillis();
this.openStatements = new FastList<Statement>(Statement.class, 16);
final long variance = pool.configuration.getMaxLifetime() > 300_000 ? ThreadLocalRandom.current().nextLong(100_000) : 0;
final long variance = pool.configuration.getMaxLifetime() > 60_000 ? ThreadLocalRandom.current().nextLong(10_000) : 0;
final long maxLifetime = pool.configuration.getMaxLifetime() - variance;
if (maxLifetime > 0) {
endOfLife = pool.houseKeepingExecutorService.schedule(new Runnable() {
@ -84,8 +90,8 @@ public final class PoolBagEntry implements IConcurrentBagEntry
public String toString()
{
return "Connection......" + connection + "\n"
+ " Last access.." + lastAccessNano + "\n"
+ " Last open....." + lastOpenNano + "\n"
+ " Last access.." + lastAccess + "\n"
+ " Last open....." + lastOpenTime + "\n"
+ " State........." + stateToString();
}

@ -49,6 +49,10 @@ public final class PoolUtilities
*/
public void quietlyCloseConnection(final Connection connection, final String closureReason)
{
if (connection == null) {
return;
}
final String addendum = closureReason != null ? " (" + closureReason + ")" : "";
try {
LOGGER.debug("Closing connection {} in pool {}{}", connection, poolName, addendum);

@ -29,7 +29,6 @@ import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.zaxxer.hikari.pool.HikariPool;
import com.zaxxer.hikari.pool.LeakTask;
import com.zaxxer.hikari.pool.PoolBagEntry;
import com.zaxxer.hikari.util.FastList;
@ -47,11 +46,10 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
protected Connection delegate;
private final LeakTask leakTask;
private final HikariPool parentPool;
private final PoolBagEntry bagEntry;
private final FastList<Statement> openStatements;
private long lastAccessNano;
private long lastAccess;
private boolean isCommitStateDirty;
private boolean isConnectionStateDirty;
private boolean isAutoCommitDirty;
@ -72,13 +70,13 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
SQL_ERRORS.add("JZ0C1"); // Sybase disconnect error
}
protected ConnectionProxy(final HikariPool pool, final PoolBagEntry bagEntry, final LeakTask leakTask) {
this.parentPool = pool;
protected ConnectionProxy(final PoolBagEntry bagEntry, final LeakTask leakTask, final long now) {
this.bagEntry = bagEntry;
this.delegate = bagEntry.connection;
this.leakTask = leakTask;
this.lastAccess = now;
this.openStatements = new FastList<Statement>(Statement.class, 16);
this.delegate = bagEntry.connection;
this.openStatements = bagEntry.openStatements;
}
/** {@inheritDoc} */
@ -111,8 +109,8 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
boolean isForceClose = sqlState.startsWith("08") | SQL_ERRORS.contains(sqlState);
if (isForceClose) {
bagEntry.evicted = true;
LOGGER.warn("Connection {} ({}) marked as broken because of SQLSTATE({}), ErrorCode({}).", delegate,
parentPool, sqlState, sqle.getErrorCode(), sqle);
LOGGER.warn("Connection {} ({}) marked as broken because of SQLSTATE({}), ErrorCode({}).",
delegate, bagEntry.parentPool, sqlState, sqle.getErrorCode(), sqle);
}
else {
SQLException nse = sqle.getNextException();
@ -136,7 +134,6 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
public final void markCommitStateDirty()
{
isCommitStateDirty = true;
lastAccessNano = System.nanoTime();
}
// ***********************************************************************
@ -153,20 +150,22 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
private final void resetConnectionState() throws SQLException
{
if (isReadOnlyDirty) {
delegate.setReadOnly(parentPool.isReadOnly);
delegate.setReadOnly(bagEntry.parentPool.isReadOnly);
}
if (isAutoCommitDirty) {
delegate.setAutoCommit(parentPool.isAutoCommit);
delegate.setAutoCommit(bagEntry.parentPool.isAutoCommit);
}
if (isTransactionIsolationDirty) {
delegate.setTransactionIsolation(parentPool.transactionIsolation);
delegate.setTransactionIsolation(bagEntry.parentPool.transactionIsolation);
}
if (isCatalogDirty && parentPool.catalog != null) {
delegate.setCatalog(parentPool.catalog);
if (isCatalogDirty && bagEntry.parentPool.catalog != null) {
delegate.setCatalog(bagEntry.parentPool.catalog);
}
lastAccess = System.currentTimeMillis();
}
// **********************************************************************
@ -193,8 +192,12 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
}
try {
if (isCommitStateDirty && !delegate.getAutoCommit()) {
delegate.rollback();
if (isCommitStateDirty) {
lastAccess = System.currentTimeMillis();
if (!delegate.getAutoCommit()) {
delegate.rollback();
}
}
if (isConnectionStateDirty) {
@ -210,11 +213,9 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
}
}
finally {
if (lastAccessNano != 0) {
bagEntry.lastAccessNano = lastAccessNano;
}
delegate = ClosedConnection.CLOSED_CONNECTION;
parentPool.releaseConnection(bagEntry);
bagEntry.lastAccess = this.lastAccess;
bagEntry.parentPool.releaseConnection(bagEntry);
}
}
}
@ -316,6 +317,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
{
delegate.commit();
isCommitStateDirty = false;
lastAccess = System.currentTimeMillis();
}
/** {@inheritDoc} */
@ -324,6 +326,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
{
delegate.rollback();
isCommitStateDirty = false;
lastAccess = System.currentTimeMillis();
}
/** {@inheritDoc} */
@ -332,6 +335,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
{
delegate.rollback(savepoint);
isCommitStateDirty = false;
lastAccess = System.currentTimeMillis();
}
/** {@inheritDoc} */
@ -340,7 +344,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
{
delegate.setAutoCommit(autoCommit);
isConnectionStateDirty = true;
isAutoCommitDirty = (autoCommit != parentPool.isAutoCommit);
isAutoCommitDirty = (autoCommit != bagEntry.parentPool.isAutoCommit);
}
/** {@inheritDoc} */
@ -349,7 +353,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
{
delegate.setReadOnly(readOnly);
isConnectionStateDirty = true;
isReadOnlyDirty = (readOnly != parentPool.isReadOnly);
isReadOnlyDirty = (readOnly != bagEntry.parentPool.isReadOnly);
}
/** {@inheritDoc} */
@ -358,7 +362,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
{
delegate.setTransactionIsolation(level);
isConnectionStateDirty = true;
isTransactionIsolationDirty = (level != parentPool.transactionIsolation);
isTransactionIsolationDirty = (level != bagEntry.parentPool.transactionIsolation);
}
/** {@inheritDoc} */
@ -367,7 +371,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
{
delegate.setCatalog(catalog);
isConnectionStateDirty = true;
isCatalogDirty = (catalog != null && !catalog.equals(parentPool.catalog)) || (catalog == null && parentPool.catalog != null);
isCatalogDirty = (catalog != null && !catalog.equals(bagEntry.parentPool.catalog)) || (catalog == null && bagEntry.parentPool.catalog != null);
}
/** {@inheritDoc} */

@ -22,7 +22,6 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import com.zaxxer.hikari.pool.HikariPool;
import com.zaxxer.hikari.pool.LeakTask;
import com.zaxxer.hikari.pool.PoolBagEntry;
@ -42,12 +41,12 @@ public final class ProxyFactory
/**
* Create a proxy for the specified {@link Connection} instance.
*
* @param pool the {@link HikariPool} that will own this proxy
* @param bagEntry the PoolBagEntry entry for this proxy
* @param leakTask a leak detetection task
* @param now current timestamp in milliseconds
* @return a proxy that wraps the specified {@link Connection}
*/
public static IHikariConnectionProxy getProxyConnection(final HikariPool pool, final PoolBagEntry bagEntry, final LeakTask leakTask)
public static IHikariConnectionProxy getProxyConnection(final PoolBagEntry bagEntry, final LeakTask leakTask, final long now)
{
// Body is injected by JavassistProxyFactory
return null;

@ -25,6 +25,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedLongSynchronizer;
import org.slf4j.Logger;
@ -81,12 +82,13 @@ public class ConcurrentBag<T extends IConcurrentBagEntry> implements AutoCloseab
* The method will borrow a BagEntry from the bag, blocking for the
* specified timeout if none are available.
*
* @param timeoutNanos how long to wait before giving up, in units of unit
* @param timeout how long to wait before giving up, in units of unit
* @param timeUnit a <code>TimeUnit</code> determining how to interpret the timeout parameter
* @return a borrowed instance from the bag or null if a timeout occurs
* @throws InterruptedException if interrupted while waiting
*/
@SuppressWarnings("unchecked")
public T borrow(long timeoutNanos) throws InterruptedException
public T borrow(long timeout, final TimeUnit timeUnit) throws InterruptedException
{
// Try the thread-local list first, if there are no blocked threads waiting already
if (!synchronizer.hasQueuedThreads()) {
@ -105,12 +107,13 @@ 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 originTimeout = timeoutNanos;
final long originTimeout = timeout;
long startSeq = 0; // 0 intentionally causes tryAcquireSharedNanos() to fall-thru in the first iteration
try {
while (timeoutNanos > 1000L && synchronizer.tryAcquireSharedNanos(startSeq, timeoutNanos)) {
while (timeout > 1000L && synchronizer.tryAcquireSharedNanos(startSeq, timeout)) {
do {
startSeq = sequence.sum();
for (final T bagEntry : sharedList) {
@ -124,7 +127,7 @@ public class ConcurrentBag<T extends IConcurrentBagEntry> implements AutoCloseab
addItemFuture = listener.addBagItem();
}
timeoutNanos = originTimeout - (System.nanoTime() - startScan);
timeout = originTimeout - (System.nanoTime() - startScan);
}
}
finally {
@ -168,7 +171,7 @@ public class ConcurrentBag<T extends IConcurrentBagEntry> implements AutoCloseab
{
if (closed) {
LOGGER.info("ConcurrentBag has been closed, ignoring add()");
return;
throw new IllegalStateException("ConcurrentBag has been closed, ignoring add()");
}
sharedList.add(bagEntry);

@ -58,26 +58,16 @@ public final class UtilityElf
*
* @param millis the number of milliseconds to sleep
*/
public static void quietlySleep(final long ticks, final TimeUnit unit)
public static void quietlySleep(final long ticks)
{
try {
unit.sleep(ticks);
Thread.sleep(ticks);
}
catch (InterruptedException e) {
// I said be quiet!
}
}
/**
* Sleep and transform an InterruptedException into a RuntimeException.
*
* @param millis the number of milliseconds to sleep
*/
public static void quietlySleepMs(final long millis)
{
quietlySleep(millis, TimeUnit.MILLISECONDS);
}
/**
* Create and instance of the specified class using the constructor matching the specified
* arguments.

@ -108,9 +108,9 @@ public class MiscTest
TestElf.getPool(ds).logPoolState();
Connection connection = ds.getConnection();
UtilityElf.quietlySleepMs(TimeUnit.SECONDS.toMillis(4));
UtilityElf.quietlySleep(TimeUnit.SECONDS.toMillis(4));
connection.close();
UtilityElf.quietlySleepMs(TimeUnit.SECONDS.toMillis(1));
UtilityElf.quietlySleep(TimeUnit.SECONDS.toMillis(1));
ps.close();
String s = new String(baos.toByteArray());
Assert.assertNotNull("Exception string was null", s);

@ -58,7 +58,7 @@ public class PostgresTest
public void run() {
try (Connection connection = ds.getConnection()) {
System.err.println("Obtained connection " + connection);
UtilityElf.quietlySleepMs(TimeUnit.SECONDS.toMillis((long)(10 + (Math.random() * 20))));
UtilityElf.quietlySleep(TimeUnit.SECONDS.toMillis((long)(10 + (Math.random() * 20))));
}
catch (SQLException e) {
e.printStackTrace();
@ -68,7 +68,7 @@ public class PostgresTest
t.setDaemon(true);
t.start();
UtilityElf.quietlySleepMs(TimeUnit.SECONDS.toMillis((long)((Math.random() * 20))));
UtilityElf.quietlySleep(TimeUnit.SECONDS.toMillis((long)((Math.random() * 20))));
} while (UtilityElf.elapsedTimeMs(start) < TimeUnit.MINUTES.toMillis(15));
}
}
@ -92,7 +92,7 @@ public class PostgresTest
}
TestElf.getPool(ds).logPoolState();
UtilityElf.quietlySleepMs(5000L);
UtilityElf.quietlySleep(5000L);
System.err.println("\nNow attempting another getConnection(), expecting a timeout...");
@ -107,7 +107,7 @@ public class PostgresTest
}
System.err.println("\nOk, so far so good. Now, disable the firewall again. Attempting connection in 5 seconds...");
UtilityElf.quietlySleepMs(5000L);
UtilityElf.quietlySleep(5000L);
TestElf.getPool(ds).logPoolState();
try (Connection conn = ds.getConnection()) {
@ -144,10 +144,10 @@ public class PostgresTest
}.start();
}
UtilityElf.quietlySleepMs(5000L);
UtilityElf.quietlySleep(5000L);
System.err.println("Now, bring the DB online. Checking pool in 15 seconds.");
UtilityElf.quietlySleepMs(15000L);
UtilityElf.quietlySleep(15000L);
TestElf.getPool(ds).logPoolState();
}
@ -174,21 +174,21 @@ public class PostgresTest
for (int i = 0; i < 20; i++) {
threads.add(new Thread() {
public void run() {
UtilityElf.quietlySleepMs((long)(Math.random() * 2500L));
UtilityElf.quietlySleep((long)(Math.random() * 2500L));
final long start = System.currentTimeMillis();
do {
try (Connection conn = ds.getConnection(); Statement stmt = conn.createStatement()) {
try (ResultSet rs = stmt.executeQuery("SELECT * FROM device WHERE device_id=0 ORDER BY device_id LIMIT 1 OFFSET 0")) {
rs.next();
}
UtilityElf.quietlySleepMs(100L); //Math.max(50L, (long)(Math.random() * 250L)));
UtilityElf.quietlySleep(100L); //Math.max(50L, (long)(Math.random() * 250L)));
}
catch (SQLException e) {
e.printStackTrace();
// throw new RuntimeException(e);
}
// UtilityElf.quietlySleepMs(10L); //Math.max(50L, (long)(Math.random() * 250L)));
// UtilityElf.quietlySleep(10L); //Math.max(50L, (long)(Math.random() * 250L)));
} while (UtilityElf.elapsedTimeMs(start) < TimeUnit.MINUTES.toMillis(5));
};
});
@ -210,11 +210,11 @@ public class PostgresTest
do {
System.out.printf("Starting in %d seconds...\n", seconds);
if (seconds > 10) {
UtilityElf.quietlySleepMs(TimeUnit.SECONDS.toMillis(10));
UtilityElf.quietlySleep(TimeUnit.SECONDS.toMillis(10));
seconds -= 10;
}
else {
UtilityElf.quietlySleepMs(TimeUnit.SECONDS.toMillis(1));
UtilityElf.quietlySleep(TimeUnit.SECONDS.toMillis(1));
seconds -= 1;
}
} while (seconds > 0);

@ -72,7 +72,7 @@ public class ShutdownTest
{
try {
if (ds.getConnection() != null) {
UtilityElf.quietlySleepMs(TimeUnit.SECONDS.toMillis(1));
UtilityElf.quietlySleep(TimeUnit.SECONDS.toMillis(1));
}
}
catch (SQLException e) {
@ -83,7 +83,7 @@ public class ShutdownTest
threads[i].start();
}
UtilityElf.quietlySleepMs(1200L);
UtilityElf.quietlySleep(1200L);
Assert.assertTrue("Totals connection count not as expected, ", pool.getTotalConnections() > 0);
@ -112,7 +112,7 @@ public class ShutdownTest
HikariDataSource ds = new HikariDataSource(config);
HikariPool pool = TestElf.getPool(ds);
UtilityElf.quietlySleepMs(1200L);
UtilityElf.quietlySleep(1200L);
Assert.assertTrue("Totals connection count not as expected, ", pool.getTotalConnections() > 0);
@ -141,7 +141,7 @@ public class ShutdownTest
HikariDataSource ds = new HikariDataSource(config);
HikariPool pool = TestElf.getPool(ds);
UtilityElf.quietlySleepMs(1200L);
UtilityElf.quietlySleep(1200L);
Assert.assertTrue("Totals connection count not as expected, ", pool.getTotalConnections() == 5);
@ -166,13 +166,13 @@ public class ShutdownTest
HikariDataSource ds = new HikariDataSource(config);
UtilityElf.quietlySleepMs(500L);
UtilityElf.quietlySleep(500L);
ds.close();
long startNanos = System.nanoTime();
while (UtilityElf.elapsedTimeMs(startNanos) < TimeUnit.SECONDS.toMillis(5) && threadCount() > 0) {
UtilityElf.quietlySleepMs(250);
UtilityElf.quietlySleep(250);
}
Assert.assertSame("Unreleased connections after shutdown", 0, TestElf.getPool(ds).getTotalConnections());
@ -251,7 +251,7 @@ public class ShutdownTest
try {
connection2 = ds.getConnection();
PreparedStatement stmt = connection2.prepareStatement("SOMETHING");
UtilityElf.quietlySleepMs(20);
UtilityElf.quietlySleep(20);
stmt.getMaxFieldSize();
}
catch (SQLException e) {
@ -281,7 +281,7 @@ public class ShutdownTest
Thread t2 = new Thread() {
public void run() {
UtilityElf.quietlySleepMs(100);
UtilityElf.quietlySleep(100);
try {
ds.close();
}

@ -78,7 +78,7 @@ public class TestConcurrentBag
PoolBagEntry inuse = new PoolBagEntry(null, pool);
bag.add(inuse);
bag.borrow(TimeUnit.SECONDS.toNanos(2)); // in use
bag.borrow(2, TimeUnit.MILLISECONDS); // in use
PoolBagEntry notinuse = new PoolBagEntry(null, pool);
bag.add(notinuse); // not in use
@ -106,7 +106,7 @@ public class TestConcurrentBag
try {
PoolBagEntry bagEntry = new PoolBagEntry(null, pool);
bag.add(bagEntry);
Assert.assertNotEquals(bagEntry, bag.borrow(TimeUnit.MILLISECONDS.toNanos(100)));
Assert.assertNotEquals(bagEntry, bag.borrow(100, TimeUnit.MILLISECONDS));
}
catch (IllegalStateException e) {
Assert.assertTrue(new String(baos.toByteArray()).contains("ignoring add()"));

@ -44,7 +44,7 @@ public class TestConnectionCloseBlocking {
connection.close();
// Hikari only checks for validity for connections with lastAccess > 1000 ms so we sleep for 1001 ms to force
// Hikari to do a connection validation which will fail and will trigger the connection to be closed
UtilityElf.quietlySleepMs(1001);
UtilityElf.quietlySleep(1001);
startNanos = System.nanoTime();
connection = ds.getConnection(); // on physical connection close we sleep 2 seconds
Assert.assertTrue("Waited longer than timeout",

@ -21,27 +21,24 @@ public class TestConnectionTimeoutRetry
config.setMinimumIdle(0);
config.setMaximumPoolSize(1);
config.setConnectionTimeout(2800);
config.setValidationTimeout(2800);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
HikariDataSource ds = new HikariDataSource(config);
StubDataSource stubDataSource = ds.unwrap(StubDataSource.class);
stubDataSource.setThrowException(new SQLException("Connection refused"));
long start = System.currentTimeMillis();
try {
Connection connection = ds.getConnection();
connection.close();
Assert.fail("Should not have been able to get a connection.");
}
catch (SQLException e) {
long elapsed = System.currentTimeMillis() - start;
long timeout = config.getConnectionTimeout();
Assert.assertTrue("Didn't wait long enough for timeout", (elapsed >= timeout));
}
finally {
ds.close();
try (HikariDataSource ds = new HikariDataSource(config)) {
StubDataSource stubDataSource = ds.unwrap(StubDataSource.class);
stubDataSource.setThrowException(new SQLException("Connection refused"));
long start = System.currentTimeMillis();
try (Connection connection = ds.getConnection()) {
connection.close();
Assert.fail("Should not have been able to get a connection.");
}
catch (SQLException e) {
long elapsed = System.currentTimeMillis() - start;
long timeout = config.getConnectionTimeout();
Assert.assertTrue("Didn't wait long enough for timeout", (elapsed >= timeout));
}
}
}
@ -52,38 +49,38 @@ public class TestConnectionTimeoutRetry
config.setMinimumIdle(0);
config.setMaximumPoolSize(1);
config.setConnectionTimeout(2800);
config.setValidationTimeout(2800);
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
HikariDataSource ds = new HikariDataSource(config);
final StubDataSource stubDataSource = ds.unwrap(StubDataSource.class);
stubDataSource.setThrowException(new SQLException("Connection refused"));
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.schedule(new Runnable() {
public void run()
{
stubDataSource.setThrowException(null);
try (HikariDataSource ds = new HikariDataSource(config)) {
final StubDataSource stubDataSource = ds.unwrap(StubDataSource.class);
stubDataSource.setThrowException(new SQLException("Connection refused"));
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.schedule(new Runnable() {
public void run()
{
stubDataSource.setThrowException(null);
}
}, 300, TimeUnit.MILLISECONDS);
long start = System.currentTimeMillis();
try {
Connection connection = ds.getConnection();
connection.close();
long elapsed = System.currentTimeMillis() - start;
Assert.assertTrue("Connection returned too quickly, something is wrong.", elapsed > 250);
Assert.assertTrue("Waited too long to get a connection.", elapsed < config.getConnectionTimeout());
}
catch (SQLException e) {
Assert.fail("Should not have timed out: " + e.getMessage());
}
finally {
scheduler.shutdownNow();
}
}, 300, TimeUnit.MILLISECONDS);
long start = System.currentTimeMillis();
try {
Connection connection = ds.getConnection();
connection.close();
long elapsed = System.currentTimeMillis() - start;
Assert.assertTrue("Connection returned too quickly, something is wrong.", elapsed > 250);
Assert.assertTrue("Waited too long to get a connection.", elapsed < config.getConnectionTimeout());
}
catch (SQLException e) {
Assert.fail("Should not have timed out: " + e.getMessage());
}
finally {
scheduler.shutdownNow();
ds.close();
}
}
@ -94,43 +91,43 @@ public class TestConnectionTimeoutRetry
config.setMinimumIdle(0);
config.setMaximumPoolSize(2);
config.setConnectionTimeout(2800);
config.setValidationTimeout(2800);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
HikariDataSource ds = new HikariDataSource(config);
final Connection connection1 = ds.getConnection();
final Connection connection2 = ds.getConnection();
Assert.assertNotNull(connection1);
Assert.assertNotNull(connection2);
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
scheduler.schedule(new Runnable() {
public void run()
{
try {
connection1.close();
}
catch (Exception e) {
e.printStackTrace(System.err);
try (HikariDataSource ds = new HikariDataSource(config)) {
final Connection connection1 = ds.getConnection();
final Connection connection2 = ds.getConnection();
Assert.assertNotNull(connection1);
Assert.assertNotNull(connection2);
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
scheduler.schedule(new Runnable() {
public void run()
{
try {
connection1.close();
}
catch (Exception e) {
e.printStackTrace(System.err);
}
}
}, 800, TimeUnit.MILLISECONDS);
long start = System.currentTimeMillis();
try {
Connection connection3 = ds.getConnection();
connection3.close();
long elapsed = System.currentTimeMillis() - start;
Assert.assertTrue("Waited too long to get a connection.", (elapsed >= 700) && (elapsed < 950));
}
catch (SQLException e) {
Assert.fail("Should not have timed out.");
}
finally {
scheduler.shutdownNow();
}
}, 800, TimeUnit.MILLISECONDS);
long start = System.currentTimeMillis();
try {
Connection connection3 = ds.getConnection();
connection3.close();
long elapsed = System.currentTimeMillis() - start;
Assert.assertTrue("Waited too long to get a connection.", (elapsed >= 700) && (elapsed < 950));
}
catch (SQLException e) {
Assert.fail("Should not have timed out.");
}
finally {
scheduler.shutdownNow();
ds.close();
}
}
@ -141,26 +138,24 @@ public class TestConnectionTimeoutRetry
config.setMinimumIdle(0);
config.setMaximumPoolSize(1);
config.setConnectionTimeout(1000);
config.setValidationTimeout(1000);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
HikariDataSource ds = new HikariDataSource(config);
StubDataSource stubDataSource = ds.unwrap(StubDataSource.class);
stubDataSource.setThrowException(new SQLException("Connection refused"));
long start = System.currentTimeMillis();
try {
Connection connection = ds.getConnection();
connection.close();
Assert.fail("Should not have been able to get a connection.");
}
catch (SQLException e) {
long elapsed = System.currentTimeMillis() - start;
Assert.assertTrue("Didn't wait long enough for timeout", (elapsed >= config.getConnectionTimeout()));
}
finally {
ds.close();
try (HikariDataSource ds = new HikariDataSource(config)) {
StubDataSource stubDataSource = ds.unwrap(StubDataSource.class);
stubDataSource.setThrowException(new SQLException("Connection refused"));
long start = System.currentTimeMillis();
try {
Connection connection = ds.getConnection();
connection.close();
Assert.fail("Should not have been able to get a connection.");
}
catch (SQLException e) {
long elapsed = System.currentTimeMillis() - start;
Assert.assertTrue("Didn't wait long enough for timeout", (elapsed >= config.getConnectionTimeout()));
}
}
}
@ -171,44 +166,44 @@ public class TestConnectionTimeoutRetry
config.setMinimumIdle(0);
config.setMaximumPoolSize(2);
config.setConnectionTimeout(1000);
config.setValidationTimeout(1000);
config.setConnectionTestQuery("VALUES 1");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
HikariDataSource ds = new HikariDataSource(config);
final Connection connection1 = ds.getConnection();
long start = System.currentTimeMillis();
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
scheduler.schedule(new Runnable() {
public void run()
{
try {
connection1.close();
}
catch (Exception e) {
e.printStackTrace(System.err);
try (HikariDataSource ds = new HikariDataSource(config)) {
final Connection connection1 = ds.getConnection();
long start = System.currentTimeMillis();
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
scheduler.schedule(new Runnable() {
public void run()
{
try {
connection1.close();
}
catch (Exception e) {
e.printStackTrace(System.err);
}
}
}, 250, TimeUnit.MILLISECONDS);
StubDataSource stubDataSource = ds.unwrap(StubDataSource.class);
stubDataSource.setThrowException(new SQLException("Connection refused"));
try {
Connection connection2 = ds.getConnection();
connection2.close();
long elapsed = System.currentTimeMillis() - start;
Assert.assertTrue("Waited too long to get a connection.", (elapsed >= 250) && (elapsed < config.getConnectionTimeout()));
}
catch (SQLException e) {
Assert.fail("Should not have timed out.");
}
finally {
scheduler.shutdownNow();
}
}, 250, TimeUnit.MILLISECONDS);
StubDataSource stubDataSource = ds.unwrap(StubDataSource.class);
stubDataSource.setThrowException(new SQLException("Connection refused"));
try {
Connection connection2 = ds.getConnection();
connection2.close();
long elapsed = System.currentTimeMillis() - start;
Assert.assertTrue("Waited too long to get a connection.", (elapsed >= 250) && (elapsed < config.getConnectionTimeout()));
}
catch (SQLException e) {
Assert.fail("Should not have timed out.");
}
finally {
scheduler.shutdownNow();
ds.close();
}
}
@ -221,14 +216,13 @@ public class TestConnectionTimeoutRetry
config.setMinimumIdle(5);
config.setMaximumPoolSize(10);
config.setConnectionTimeout(1000);
config.setValidationTimeout(1000);
config.setConnectionTestQuery("VALUES 2");
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
System.setProperty("com.zaxxer.hikari.housekeeping.periodMs", "500");
HikariDataSource ds = new HikariDataSource(config);
try {
try (HikariDataSource ds = new HikariDataSource(config)) {
Connection connection1 = ds.getConnection();
Connection connection2 = ds.getConnection();
Connection connection3 = ds.getConnection();
@ -255,7 +249,6 @@ public class TestConnectionTimeoutRetry
}
finally {
System.getProperties().remove("com.zaxxer.hikari.housekeeping.periodMs");
ds.close();
}
}
}

@ -129,7 +129,7 @@ public class TestConnections
System.err.println("Closing " + connection2);
connection2.close();
quietlySleep(2, TimeUnit.SECONDS);
quietlySleep(TimeUnit.SECONDS.toMillis(2));
System.err.println(">>>>>>>>>>>>>> getConnection() ");
@ -181,7 +181,7 @@ public class TestConnections
Assert.assertSame("Second idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
connection2.close();
quietlySleep(800, TimeUnit.MILLISECONDS);
quietlySleep(800);
connection2 = ds.getConnection();
Assert.assertNotSame("Expected a different connection", connection, connection2);
@ -237,7 +237,7 @@ public class TestConnections
try {
Connection connection = ds.getConnection();
quietlySleep(1, TimeUnit.SECONDS);
quietlySleep(1000);
Assert.assertEquals(1, TestElf.getPool(ds).getTotalConnections());
ds.evictConnection(connection);
@ -261,7 +261,7 @@ public class TestConnections
HikariDataSource ds = new HikariDataSource(config);
try {
UtilityElf.quietlySleepMs(1200L);
UtilityElf.quietlySleep(1200L);
Assert.assertSame("Totals connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections());
@ -270,7 +270,7 @@ public class TestConnections
Connection connection = ds.getConnection();
Assert.assertNotNull(connection);
quietlySleep(500, TimeUnit.MILLISECONDS);
quietlySleep(500);
Assert.assertSame("Totals connections not as expected", 1, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
@ -292,7 +292,7 @@ public class TestConnections
// The connection will be ejected from the pool here
connection.close();
quietlySleep(500, TimeUnit.MILLISECONDS);
quietlySleep(500);
Assert.assertSame("Totals connections not as expected", 0, TestElf.getPool(ds).getTotalConnections());
Assert.assertSame("Idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections());
@ -331,7 +331,7 @@ public class TestConnections
{
try {
Connection connection = ds.getConnection();
quietlySleep(500, TimeUnit.MILLISECONDS);
quietlySleep(500);
connection.close();
}
catch (Exception e) {
@ -369,12 +369,12 @@ public class TestConnections
StubStatement.oldDriver = true;
HikariDataSource ds = new HikariDataSource(config);
try {
quietlySleep(1001, TimeUnit.MILLISECONDS);
quietlySleep(1001);
Connection connection = ds.getConnection();
connection.close();
quietlySleep(1001, TimeUnit.MILLISECONDS);
quietlySleep(1001);
connection = ds.getConnection();
}
finally {
@ -398,7 +398,7 @@ public class TestConnections
try {
HikariPool pool = TestElf.getPool(ds);
while (pool.getTotalConnections() < 3) {
quietlySleep(50, TimeUnit.MILLISECONDS);
quietlySleep(50);
}
Thread t = new Thread(new Runnable() {
@ -420,12 +420,12 @@ public class TestConnections
pool.suspendPool();
t.start();
quietlySleep(500, TimeUnit.MILLISECONDS);
quietlySleep(500);
Assert.assertEquals(2, pool.getIdleConnections());
c3.close();
Assert.assertEquals(3, pool.getIdleConnections());
pool.resumePool();
quietlySleep(500, TimeUnit.MILLISECONDS);
quietlySleep(500);
Assert.assertEquals(1, pool.getIdleConnections());
}
finally {

@ -86,7 +86,6 @@ public class TestJNDI
}
}
@SuppressWarnings("unchecked")
private class BogusContext extends AbstractContext
{
@Override

@ -90,7 +90,7 @@ public class TestMetrics
HikariDataSource ds = new HikariDataSource(config);
try {
Connection connection = ds.getConnection();
UtilityElf.quietlySleepMs(250L);
UtilityElf.quietlySleep(250L);
connection.close();
Histogram histo = metricRegistry.getHistograms(new MetricFilter() {
@ -128,7 +128,7 @@ public class TestMetrics
HikariDataSource ds = new HikariDataSource(config);
try {
UtilityElf.quietlySleepMs(TimeUnit.SECONDS.toMillis(2));
UtilityElf.quietlySleep(TimeUnit.SECONDS.toMillis(2));
Connection connection = ds.getConnection();
connection.close();

@ -34,7 +34,6 @@ import java.sql.Struct;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import com.zaxxer.hikari.util.UtilityElf;
@ -61,7 +60,7 @@ public class StubConnection extends StubBaseConnection implements Connection
public StubConnection() {
count.incrementAndGet();
if (slowCreate) {
UtilityElf.quietlySleep(1, TimeUnit.SECONDS);
UtilityElf.quietlySleep(1000);
}
}

Loading…
Cancel
Save