-
Notifications
You must be signed in to change notification settings - Fork 3.5k
/
PooledConnections.java
164 lines (140 loc) · 4.58 KB
/
PooledConnections.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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<Connection> allConnections = new ConcurrentLinkedQueue<Connection>();
private final ConcurrentLinkedQueue<Connection> availableConnections = new ConcurrentLinkedQueue<Connection>();
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( "Connection 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 );
}
}
}