HHH-10943 - Driver Manager Connection Pool should close leaked connections upon shutting down

This commit is contained in:
Vlad Mihalcea 2016-07-11 13:12:45 +03:00
parent 9abe775708
commit 799ab91cf5
6 changed files with 47 additions and 20 deletions

View File

@ -52,7 +52,6 @@ public class DriverManagerConnectionProviderImpl
private boolean active = true; private boolean active = true;
private ConnectionCreator connectionCreator;
private ScheduledExecutorService executorService; private ScheduledExecutorService executorService;
private PooledConnections pool; private PooledConnections pool;
@ -70,7 +69,6 @@ public class DriverManagerConnectionProviderImpl
public void configure(Map configurationValues) { public void configure(Map configurationValues) {
log.usingHibernateBuiltInConnectionPool(); log.usingHibernateBuiltInConnectionPool();
connectionCreator = buildCreator( configurationValues );
pool = buildPool( configurationValues ); pool = buildPool( configurationValues );
final long validationInterval = ConfigurationHelper.getLong( VALIDATION_INTERVAL, configurationValues, 30 ); final long validationInterval = ConfigurationHelper.getLong( VALIDATION_INTERVAL, configurationValues, 30 );
@ -99,6 +97,7 @@ public class DriverManagerConnectionProviderImpl
final int maxSize = ConfigurationHelper.getInt( AvailableSettings.POOL_SIZE, configurationValues, 20 ); final int maxSize = ConfigurationHelper.getInt( AvailableSettings.POOL_SIZE, configurationValues, 20 );
final int initialSize = ConfigurationHelper.getInt( INITIAL_SIZE, configurationValues, minSize ); final int initialSize = ConfigurationHelper.getInt( INITIAL_SIZE, configurationValues, minSize );
ConnectionCreator connectionCreator = buildCreator( configurationValues );
PooledConnections.Builder pooledConnectionBuilder = new PooledConnections.Builder( PooledConnections.Builder pooledConnectionBuilder = new PooledConnections.Builder(
connectionCreator, connectionCreator,
autoCommit autoCommit
@ -184,11 +183,7 @@ public class DriverManagerConnectionProviderImpl
throw new HibernateException( "Connection pool is no longer active" ); throw new HibernateException( "Connection pool is no longer active" );
} }
Connection conn = pool.poll(); return pool.poll();
if ( conn == null ) {
conn = connectionCreator.createConnection();
}
return conn;
} }
@Override @Override
@ -232,7 +227,7 @@ public class DriverManagerConnectionProviderImpl
return; return;
} }
log.cleaningUpConnectionPool( connectionCreator.getUrl() ); log.cleaningUpConnectionPool( pool.getUrl() );
active = false; active = false;

View File

@ -10,6 +10,7 @@ import java.sql.Connection;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import org.hibernate.HibernateException;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
@ -18,7 +19,8 @@ import org.hibernate.internal.CoreMessageLogger;
*/ */
public class PooledConnections { public class PooledConnections {
private ConcurrentLinkedQueue<Connection> connections = new ConcurrentLinkedQueue<Connection>(); private final ConcurrentLinkedQueue<Connection> allConnections = new ConcurrentLinkedQueue<Connection>();
private final ConcurrentLinkedQueue<Connection> availableConnections = new ConcurrentLinkedQueue<Connection>();
private static final CoreMessageLogger log = CoreLogging.messageLogger( DriverManagerConnectionProviderImpl.class ); private static final CoreMessageLogger log = CoreLogging.messageLogger( DriverManagerConnectionProviderImpl.class );
@ -65,35 +67,50 @@ public class PooledConnections {
public void add(Connection conn) throws SQLException { public void add(Connection conn) throws SQLException {
conn.setAutoCommit( true ); conn.setAutoCommit( true );
conn.clearWarnings(); conn.clearWarnings();
connections.offer( conn ); availableConnections.offer( conn );
} }
public Connection poll() throws SQLException { public Connection poll() throws SQLException {
Connection conn = connections.poll(); Connection conn = availableConnections.poll();
if ( conn == null ) { if ( conn == null ) {
return null; synchronized (allConnections) {
if(allConnections.size() < maxSize) {
addConnections( 1 );
return poll();
}
}
throw new HibernateException( "The internal connection pool has reached its maximum size and no connection is currently available!" );
} }
conn.setAutoCommit( autoCommit ); conn.setAutoCommit( autoCommit );
return conn; return conn;
} }
public void close() throws SQLException { public void close() throws SQLException {
for ( Connection connection : connections ) { try {
connection.close(); int allocationCount = allConnections.size() - availableConnections.size();
if(allocationCount > 0) {
log.error( "Collection leak detected: there are " + allocationCount + " unclosed connections upon shutting down pool " + getUrl());
}
}
finally {
for ( Connection connection : allConnections ) {
connection.close();
}
} }
} }
public int size() { public int size() {
return connections.size(); return availableConnections.size();
} }
protected void removeConnections(int numberToBeRemoved) { protected void removeConnections(int numberToBeRemoved) {
for ( int i = 0; i < numberToBeRemoved; i++ ) { for ( int i = 0; i < numberToBeRemoved; i++ ) {
Connection connection = connections.poll(); Connection connection = availableConnections.poll();
try { try {
if ( connection != null ) { if ( connection != null ) {
connection.close(); connection.close();
} }
allConnections.remove( connection );
} }
catch (SQLException e) { catch (SQLException e) {
log.unableToCloseConnection( e ); log.unableToCloseConnection( e );
@ -103,10 +120,16 @@ public class PooledConnections {
protected void addConnections(int numberOfConnections) { protected void addConnections(int numberOfConnections) {
for ( int i = 0; i < numberOfConnections; i++ ) { for ( int i = 0; i < numberOfConnections; i++ ) {
connections.add( connectionCreator.createConnection() ); Connection connection = connectionCreator.createConnection();
allConnections.add( connection );
availableConnections.add( connection );
} }
} }
public String getUrl() {
return connectionCreator.getUrl();
}
public static class Builder { public static class Builder {
private final ConnectionCreator connectionCreator; private final ConnectionCreator connectionCreator;
private boolean autoCommit; private boolean autoCommit;

View File

@ -521,5 +521,9 @@ public class CMTTest extends BaseNonConfigCoreFunctionalTestCase {
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit();
} }
protected boolean rebuildSessionFactoryOnError() {
return false;
}
} }

View File

@ -23,7 +23,7 @@
<property name="connection.password"></property> <property name="connection.password"></property>
<!-- JDBC connection pool (use the built-in) --> <!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property> <property name="connection.pool_size">5</property>
<!-- SQL dialect --> <!-- SQL dialect -->
<property name="dialect"> <property name="dialect">

View File

@ -23,7 +23,7 @@
<property name="connection.password"></property> <property name="connection.password"></property>
<!-- JDBC connection pool (use the built-in) --> <!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property> <property name="connection.pool_size">5</property>
<!-- SQL dialect --> <!-- SQL dialect -->
<property name="dialect"> <property name="dialect">

View File

@ -148,7 +148,12 @@ public class JtaAwareConnectionProviderImpl implements ConnectionProvider, Confi
private void delist(Connection connection) { private void delist(Connection connection) {
// todo : verify the incoming connection is the currently enlisted one? // todo : verify the incoming connection is the currently enlisted one?
TestingJtaPlatformImpl.synchronizationRegistry().putResource( CONNECTION_KEY, null ); try {
TestingJtaPlatformImpl.synchronizationRegistry().putResource( CONNECTION_KEY, null );
}
catch ( Exception e ) {
System.err.println( "!!!Error trying to reset synchronization registry!!!" );
}
try { try {
delegate.closeConnection( connection ); delegate.closeConnection( connection );
} }