Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
* dev: (22 commits)
  Javadoc, renaming, and cleanup.
  Fix FastStatementList unit test failure.
  Slightly cleaner fix for issue #35
  javadoc.
  Change default size from 16 to 32, and change growth factor from 4x to 2x.
  Add a pool state log at timeout failure.
  Synchronization fixes.
  Minor cleanup and javadoc.
  Refactored SpecializedConcurrentBag for efficiency, moved to util.
  Initialize the concurrent bag with an initial size.
  Cache the hashCode.
  Merged changed from fwbrasil
  Add license header and class-level javadoc.
  Even more detailed log for broken connections
  New concurrent connection container (moved away from LinkedBlockingQueue and LinkedTransferQueue).
  Adjust version number in the benchmark script.
  fix fast statement list overflow inconsistency
  Start of experimental implementation of a concurrent bag.
  Readability improvement.
  Added logging for broken connections.
  ...
  • Loading branch information
brettwooldridge committed Feb 18, 2014
2 parents 5bed7c4 + b81c24d commit 0b73a2b
Show file tree
Hide file tree
Showing 9 changed files with 345 additions and 44 deletions.
2 changes: 1 addition & 1 deletion benchmark.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ CLASSPATH=$CLASSPATH:~/.m2/repository/commons-logging/commons-logging/1.1.3/comm
CLASSPATH=$CLASSPATH:~/.m2/repository/commons-logging/commons-logging-api/1.1/commons-logging-api-1.1.jar

CLASSPATH=$CLASSPATH:$JAVA_HOME/lib/tools.jar
CLASSPATH=$CLASSPATH:./target/HikariCP-1.2.9-SNAPSHOT.jar
CLASSPATH=$CLASSPATH:./target/HikariCP-1.3.0-SNAPSHOT.jar
CLASSPATH=$CLASSPATH:./target/test-classes

java -classpath $CLASSPATH \
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>1.2.10-SNAPSHOT</version>
<version>1.3.0-SNAPSHOT</version>
<packaging>bundle</packaging>

<name>HikariCP</name>
Expand Down
54 changes: 24 additions & 30 deletions src/main/java/com/zaxxer/hikari/HikariPool.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
Expand All @@ -34,6 +34,7 @@
import com.zaxxer.hikari.proxy.IHikariConnectionProxy;
import com.zaxxer.hikari.proxy.ProxyFactory;
import com.zaxxer.hikari.util.PropertyBeanSetter;
import com.zaxxer.hikari.util.ConcurrentBag;

/**
* This is the primary connection pool class that provides the basic
Expand All @@ -49,7 +50,7 @@ public final class HikariPool implements HikariPoolMBean

private final IConnectionCustomizer connectionCustomizer;
private final HikariConfig configuration;
private final LinkedBlockingQueue<IHikariConnectionProxy> idleConnections;
private final ConcurrentBag<IHikariConnectionProxy> idleConnectionBag;

private final Timer houseKeepingTimer;

Expand Down Expand Up @@ -79,7 +80,7 @@ public final class HikariPool implements HikariPoolMBean
this.idleConnectionCount = new AtomicInteger();
this.awaitingConnection = new AtomicInteger();
this.backgroundFillQueued = new AtomicBoolean();
this.idleConnections = new LinkedBlockingQueue<IHikariConnectionProxy>();
this.idleConnectionBag = new ConcurrentBag<IHikariConnectionProxy>();

this.jdbc4ConnectionTest = configuration.isJdbc4ConnectionTest();
this.leakDetectionThreshold = configuration.getLeakDetectionThreshold();
Expand Down Expand Up @@ -167,7 +168,7 @@ Connection getConnection() throws SQLException
{
addConnections(AddConnectionStrategy.ONLY_IF_EMPTY);

IHikariConnectionProxy connectionProxy = idleConnections.poll(timeout, TimeUnit.MILLISECONDS);
IHikariConnectionProxy connectionProxy = idleConnectionBag.borrow(timeout, TimeUnit.MILLISECONDS);
if (connectionProxy == null)
{
// We timed out... break and throw exception
Expand Down Expand Up @@ -201,6 +202,7 @@ Connection getConnection() throws SQLException

String msg = String.format("Timeout of %dms encountered waiting for connection.", configuration.getConnectionTimeout());
LOGGER.error(msg);
logPoolState("Timeout failure ");

throw new SQLException(msg);
}
Expand Down Expand Up @@ -230,10 +232,7 @@ public void releaseConnection(IHikariConnectionProxy connectionProxy)
if (!connectionProxy.isBrokenConnection() && !shutdown)
{
idleConnectionCount.incrementAndGet();
if (!idleConnections.offer(connectionProxy))
{
closeConnection(connectionProxy);
}
idleConnectionBag.requite(connectionProxy);
}
else
{
Expand All @@ -244,19 +243,13 @@ public void releaseConnection(IHikariConnectionProxy connectionProxy)

void shutdown()
{
LOGGER.info("HikariCP pool " + configuration.getPoolName() + " is being shutdown.");

shutdown = true;
houseKeepingTimer.cancel();

while (true)
{
IHikariConnectionProxy connection = idleConnections.poll();
if (connection == null)
{
break;
}
closeConnection(connection);
}

closeIdleConnections();

HikariMBeanElf.unregisterMBeans(configuration, this);
}

Expand Down Expand Up @@ -291,13 +284,12 @@ public int getThreadsAwaitingConnection()
/** {@inheritDoc} */
public void closeIdleConnections()
{
final int idleCount = idleConnectionCount.get();
for (int i = 0; i < idleCount; i++)
List<IHikariConnectionProxy> list = idleConnectionBag.values(ConcurrentBag.STATE_NOT_IN_USE);
for (IHikariConnectionProxy connectionProxy : list)
{
IHikariConnectionProxy connectionProxy = idleConnections.poll();
if (connectionProxy == null)
if (!idleConnectionBag.reserve(connectionProxy))
{
break;
continue;
}

idleConnectionCount.decrementAndGet();
Expand Down Expand Up @@ -415,7 +407,7 @@ private void addConnection()
{
idleConnectionCount.incrementAndGet();
totalConnections.incrementAndGet();
idleConnections.add(proxyConnection);
idleConnectionBag.add(proxyConnection);
}
break;
}
Expand Down Expand Up @@ -522,6 +514,10 @@ private void closeConnection(IHikariConnectionProxy connectionProxy)
{
return;
}
finally
{
idleConnectionBag.remove(connectionProxy);
}
}

private void logPoolState(String... prefix)
Expand All @@ -547,14 +543,12 @@ public void run()
final long now = System.currentTimeMillis();
final long idleTimeout = configuration.getIdleTimeout();
final long maxLifetime = configuration.getMaxLifetime();
final int idleCount = idleConnectionCount.get();

for (int i = 0; i < idleCount; i++)
for (IHikariConnectionProxy connectionProxy : idleConnectionBag.values(ConcurrentBag.STATE_NOT_IN_USE))
{
IHikariConnectionProxy connectionProxy = idleConnections.poll();
if (connectionProxy == null)
if (!idleConnectionBag.reserve(connectionProxy))
{
break;
continue;
}

idleConnectionCount.decrementAndGet();
Expand All @@ -568,7 +562,7 @@ public void run()
else
{
idleConnectionCount.incrementAndGet();
idleConnections.add(connectionProxy);
idleConnectionBag.unreserve(connectionProxy);
}
}

Expand Down
52 changes: 48 additions & 4 deletions src/main/java/com/zaxxer/hikari/proxy/ConnectionProxy.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicInteger;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.zaxxer.hikari.HikariPool;
import com.zaxxer.hikari.util.FastStatementList;
Expand All @@ -36,13 +40,16 @@
*/
public abstract class ConnectionProxy implements IHikariConnectionProxy
{
private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionProxy.class);

private static final Set<String> SQL_ERRORS;

protected final Connection delegate;

private final FastStatementList openStatements;
private final HikariPool parentPool;
private final int defaultIsolationLevel;
private final AtomicInteger state;

private boolean isClosed;
private boolean forceClose;
Expand All @@ -54,14 +61,15 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy
private StackTraceElement[] leakTrace;
private TimerTask leakTask;

private final int hashCode;

// static initializer
static
{
SQL_ERRORS = new HashSet<String>();
SQL_ERRORS.add("57P01"); // ADMIN SHUTDOWN
SQL_ERRORS.add("57P02"); // CRASH SHUTDOWN
SQL_ERRORS.add("57P03"); // CANNOT CONNECT NOW
SQL_ERRORS.add("57P02"); // CRASH SHUTDOWN
SQL_ERRORS.add("01002"); // SQL92 disconnect error
}

Expand All @@ -70,11 +78,13 @@ protected ConnectionProxy(HikariPool pool, Connection connection, int defaultIso
this.parentPool = pool;
this.delegate = connection;
this.defaultIsolationLevel = defaultIsolationLevel;
this.state = new AtomicInteger();

creationTime = lastAccess = System.currentTimeMillis();
openStatements = new FastStatementList();
this.creationTime = lastAccess = System.currentTimeMillis();
this.openStatements = new FastStatementList();
this.hashCode = System.identityHashCode(this);
}

public final void untrackStatement(Object statement)
{
// If the connection is not closed. If it is closed, it means this is being
Expand Down Expand Up @@ -137,9 +147,25 @@ public final void checkException(SQLException sqle)
if (sqlState != null)
{
forceClose |= sqlState.startsWith("08") | SQL_ERRORS.contains(sqlState);
if (forceClose)
{
LOGGER.warn("Connection {} marked as broken because of SQLSTATE({}), ErrorCode({}): {}", delegate.toString(), sqlState, sqle.getErrorCode(), sqle.getNextException());
}
}
}

@Override
public boolean equals(Object other)
{
return this == other;
}

@Override
public int hashCode()
{
return hashCode;
}

protected final void checkClosed() throws SQLException
{
if (isClosed)
Expand All @@ -155,6 +181,24 @@ private final <T extends Statement> T trackStatement(T statement)
return statement;
}

// **********************************************************************
// IBagManagable Methods
// **********************************************************************

/** {@inheritDoc} */
@Override
public int getState()
{
return state.get();
}

/** {@inheritDoc} */
@Override
public boolean compareAndSetState(int expectedState, int newState)
{
return state.compareAndSet(expectedState, newState);
}

// **********************************************************************
// "Overridden" java.sql.Connection Methods
// **********************************************************************
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@
import java.sql.SQLException;
import java.util.Timer;

import com.zaxxer.hikari.util.ConcurrentBag.IBagManagable;

/**
*
* @author Brett Wooldridge
*/
public interface IHikariConnectionProxy extends Connection
public interface IHikariConnectionProxy extends Connection, IBagManagable
{
void unclose();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,20 +101,21 @@ private void modifyProxyFactory() throws Exception
CtClass proxyCt = classPool.getCtClass("com.zaxxer.hikari.proxy.ProxyFactory");
for (CtMethod method : proxyCt.getMethods())
{
String methodName = method.getName();
StringBuilder call = new StringBuilder("{");
if ("getProxyConnection".equals(method.getName()))
if ("getProxyConnection".equals(methodName))
{
call.append("return new ").append(packageName).append(".ConnectionJavassistProxy($$);");
}
else if ("getProxyStatement".equals(method.getName()))
else if ("getProxyStatement".equals(methodName))
{
call.append("return new ").append(packageName).append(".StatementJavassistProxy($$);");
}
else if ("getProxyPreparedStatement".equals(method.getName()))
else if ("getProxyPreparedStatement".equals(methodName))
{
call.append("return new ").append(packageName).append(".PreparedStatementJavassistProxy($$);");
}
else if ("getProxyCallableStatement".equals(method.getName()))
else if ("getProxyCallableStatement".equals(methodName))
{
call.append("return new ").append(packageName).append(".CallableStatementJavassistProxy($$);");
}
Expand Down
Loading

0 comments on commit 0b73a2b

Please sign in to comment.