All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hibernate.engine.jdbc.connections.internal.PooledConnections Maven / Gradle / Ivy

There is a newer version: 7.0.0.Alpha1
Show newest version
/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
 * See the lgpl.txt file in the root directory or .
 */
package org.hibernate.engine.jdbc.connections.internal;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.hibernate.HibernateException;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;

/**
 * @author Andrea Boriero
 */
public class PooledConnections {

	private final ConcurrentLinkedQueue allConnections = new ConcurrentLinkedQueue();
	private final ConcurrentLinkedQueue availableConnections = new ConcurrentLinkedQueue();

	private static final CoreMessageLogger log = CoreLogging.messageLogger( DriverManagerConnectionProviderImpl.class );

	private final ConnectionCreator connectionCreator;
	private final boolean autoCommit;
	private final int minSize;
	private final int maxSize;

	private boolean primed;

	private PooledConnections(
			Builder builder) {
		log.debugf( "Initializing Connection pool with %s Connections", builder.initialSize );
		connectionCreator = builder.connectionCreator;
		autoCommit = builder.autoCommit;
		maxSize = builder.maxSize;
		minSize = builder.minSize;
		log.hibernateConnectionPoolSize( maxSize, minSize );
		addConnections( builder.initialSize );
	}

	public void validate() {
		final int size = size();

		if ( !primed && size >= minSize ) {
			// IMPL NOTE : the purpose of primed is to allow the pool to lazily reach its
			// defined min-size.
			log.debug( "Connection pool now considered primed; min-size will be maintained" );
			primed = true;
		}

		if ( size < minSize && primed ) {
			int numberToBeAdded = minSize - size;
			log.debugf( "Adding %s Connections to the pool", numberToBeAdded );
			addConnections( numberToBeAdded );
		}
		else if ( size > maxSize ) {
			int numberToBeRemoved = size - maxSize;
			log.debugf( "Removing %s Connections from the pool", numberToBeRemoved );
			removeConnections( numberToBeRemoved );
		}
	}

	public void add(Connection conn) throws SQLException {
		conn.setAutoCommit( true );
		conn.clearWarnings();
		availableConnections.offer( conn );
	}

	public Connection poll() throws SQLException {
		Connection conn = availableConnections.poll();
		if ( conn == 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 );
		return conn;
	}

	public void close() throws SQLException {
		try {
			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() {
		return availableConnections.size();
	}

	protected void removeConnections(int numberToBeRemoved) {
		for ( int i = 0; i < numberToBeRemoved; i++ ) {
			Connection connection = availableConnections.poll();
			try {
				if ( connection != null ) {
					connection.close();
				}
				allConnections.remove( connection );
			}
			catch (SQLException e) {
				log.unableToCloseConnection( e );
			}
		}
	}

	protected void addConnections(int numberOfConnections) {
		for ( int i = 0; i < numberOfConnections; i++ ) {
			Connection connection = connectionCreator.createConnection();
			allConnections.add( connection );
			availableConnections.add( connection );
		}
	}

	public String getUrl() {
		return connectionCreator.getUrl();
	}

	public static class Builder {
		private final ConnectionCreator connectionCreator;
		private boolean autoCommit;
		private int initialSize = 1;
		private int minSize = 1;
		private int maxSize = 20;

		public Builder(ConnectionCreator connectionCreator, boolean autoCommit) {
			this.connectionCreator = connectionCreator;
			this.autoCommit = autoCommit;
		}

		public Builder initialSize(int initialSize) {
			this.initialSize = initialSize;
			return this;
		}

		public Builder minSize(int minSize) {
			this.minSize = minSize;
			return this;
		}

		public Builder maxSize(int maxSize) {
			this.maxSize = maxSize;
			return this;
		}

		public PooledConnections build() {
			return new PooledConnections( this );
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy