Merge pull request #458 from brettwooldridge/experimental
Fixes #452 fixed race condition in the add-connection pathpull/445/merge
commit
a6f2534f4a
@ -1,83 +1,83 @@
|
||||
package com.zaxxer.hikari.pool;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import com.zaxxer.hikari.util.ConcurrentBag;
|
||||
|
||||
/**
|
||||
* @author Matthew Tambara (matthew.tambara@liferay.com)
|
||||
*/
|
||||
public class AddConnectionRaceConditionTest
|
||||
public class ConnectionRaceConditionTest
|
||||
{
|
||||
private HikariPool _hikariPool;
|
||||
|
||||
// @Test
|
||||
@Test
|
||||
public void testRaceCondition() throws Exception
|
||||
{
|
||||
HikariConfig config = new HikariConfig();
|
||||
config.setMinimumIdle(0);
|
||||
config.setMaximumPoolSize(10);
|
||||
config.setInitializationFailFast(false);
|
||||
config.setConnectionTimeout(2500);
|
||||
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
|
||||
|
||||
TestElf.setSlf4jLogLevel(ConcurrentBag.class, Level.INFO);
|
||||
|
||||
final AtomicReference<Exception> ref = new AtomicReference<Exception>(null);
|
||||
|
||||
// Initialize HikariPool with no initial connections and room to grow
|
||||
try (final HikariDataSource ds = new HikariDataSource(config)) {
|
||||
_hikariPool = TestElf.getPool(ds);
|
||||
|
||||
ExecutorService threadPool = Executors.newFixedThreadPool(2);
|
||||
for (int i = 0; i < 100000; i++) {
|
||||
Future<Exception> submit1 = threadPool.submit(new Callable<Exception>() {
|
||||
for (int i = 0; i < 500_000; i++) {
|
||||
threadPool.submit(new Callable<Exception>() {
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public Exception call() throws Exception
|
||||
{
|
||||
Connection c2;
|
||||
try {
|
||||
c2 = _hikariPool.getConnection(5000);
|
||||
c2 = ds.getConnection();
|
||||
ds.evictConnection(c2);
|
||||
}
|
||||
catch (SQLException e) {
|
||||
return e;
|
||||
catch (Exception e) {
|
||||
ref.set(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<Exception> submit2 = threadPool.submit(new Callable<Exception>() {
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public Exception call() throws Exception
|
||||
{
|
||||
Connection c2;
|
||||
try {
|
||||
c2 = _hikariPool.getConnection(5000);
|
||||
ds.evictConnection(c2);
|
||||
}
|
||||
catch (SQLException e) {
|
||||
return e;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
threadPool.shutdown();
|
||||
threadPool.awaitTermination(30, TimeUnit.SECONDS);
|
||||
|
||||
if (submit1.get() != null) {
|
||||
throw submit1.get();
|
||||
}
|
||||
if (submit2.get() != null) {
|
||||
throw submit2.get();
|
||||
}
|
||||
if (ref.get() != null) {
|
||||
ref.get().fillInStackTrace();
|
||||
LoggerFactory.getLogger(ConnectionRaceConditionTest.class).error("Submit1 task failed", ref.get());
|
||||
Assert.fail("Task failed");
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
public void after()
|
||||
{
|
||||
System.getProperties().remove("com.zaxxer.hikari.housekeeping.periodMs");
|
||||
|
||||
TestElf.setSlf4jLogLevel(HikariPool.class, Level.WARN);
|
||||
TestElf.setSlf4jLogLevel(ConcurrentBag.class, Level.WARN);
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration status="OFF">
|
||||
<appenders>
|
||||
<Console name="Console" target="SYSTEM_ERR">
|
||||
<PatternLayout pattern="%6sn [%-26.26t] %-5level %-20c{1} - %msg%n" />
|
||||
</Console>
|
||||
</appenders>
|
||||
<Loggers>
|
||||
<Root level="info">
|
||||
<AppenderRef ref="Console" />
|
||||
</Root>
|
||||
</Loggers>
|
||||
</configuration>
|
Loading…
Reference in New Issue