HHH-10943 - Driver Manager Connection Pool should close leaked connections upon shutting down
This commit is contained in:
parent
9abe775708
commit
799ab91cf5
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -521,5 +521,9 @@ public class CMTTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit();
|
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean rebuildSessionFactoryOnError() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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 );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue