@@ -158,8 +158,24 @@ void returnPooledConnection(PooledConnection c, boolean forceClose) {
158158 }
159159 }
160160
161- private PooledConnection extractFromFreeList (Object affinitiyId ) {
161+ /**
162+ * Tries to extract the best matching connection from the freeList.
163+ * If there is none, it tries to create one or steal one from other affinity slot.
164+ */
165+ private PooledConnection extractFromFreeList (Object affinitiyId , boolean create ) throws SQLException {
166+ PooledConnection c = extractFromFreeList (affinitiyId );
167+ if (c == null && create ) {
168+ c = createConnection ();
169+ }
170+ if (c == null && buffer .isAffinitySupported ()) {
171+ // TODO: This "stealing" stragegy could be optimized.
172+ // we might build a heurestic, which one would be the best candidate
173+ c = extractFromFreeList (ConnectionBuffer .GET_LAST );
174+ }
175+ return c ;
176+ }
162177
178+ private PooledConnection extractFromFreeList (Object affinitiyId ) {
163179 PooledConnection c = buffer .removeFree (affinitiyId );
164180 if (c == null ) {
165181 return null ;
@@ -182,6 +198,21 @@ private boolean staleEviction(PooledConnection c) {
182198 return pool .invalidConnection (c );
183199 }
184200
201+
202+ private PooledConnection createConnection () throws SQLException {
203+ if (totalConnections () < maxSize ) {
204+ // grow the connection pool
205+ PooledConnection c = pool .createConnectionForQueue (connectionId ++);
206+ int busySize = registerBusyConnection (c );
207+ if (Log .isLoggable (DEBUG )) {
208+ Log .debug ("DataSource [{0}] grow; id[{1}] busy[{2}] max[{3}]" , name , c .name (), busySize , maxSize );
209+ }
210+ return c ;
211+ } else {
212+ return null ;
213+ }
214+ }
215+
185216 private boolean stale (PooledConnection c ) {
186217 return c .lastUsedTime () < System .currentTimeMillis () - validateStaleMillis ;
187218 }
@@ -225,13 +256,9 @@ private PooledConnection _obtainConnection(Object affinitiyId) throws Interrupte
225256 hitCount ++;
226257 // are other threads already waiting? (they get priority)
227258 if (waitingThreads == 0 ) {
228- PooledConnection connection = extractFromFreeList (affinitiyId );
229- if (connection != null ) {
230- return connection ;
231- }
232- connection = createConnection ();
233- if (connection != null ) {
234- return connection ;
259+ PooledConnection c = this .extractFromFreeList (affinitiyId , true );
260+ if (c != null ) {
261+ return c ;
235262 }
236263 }
237264 try {
@@ -251,20 +278,6 @@ private PooledConnection _obtainConnection(Object affinitiyId) throws Interrupte
251278 }
252279 }
253280
254- private PooledConnection createConnection () throws SQLException {
255- if (totalConnections () < maxSize ) {
256- // grow the connection pool
257- PooledConnection c = pool .createConnectionForQueue (connectionId ++);
258- int busySize = registerBusyConnection (c );
259- if (Log .isLoggable (DEBUG )) {
260- Log .debug ("DataSource [{0}] grow; id[{1}] busy[{2}] max[{3}]" , name , c .name (), busySize , maxSize );
261- }
262- return c ;
263- } else {
264- return null ;
265- }
266- }
267-
268281 /**
269282 * Got into a loop waiting for connections to be returned to the pool.
270283 */
@@ -277,13 +290,6 @@ private PooledConnection _obtainConnectionWaitLoop(Object affinitiyId) throws SQ
277290 if (conn != null ) {
278291 return conn ;
279292 }
280- // we could not create new connection, so we take the last one and change the affinity id
281- if (buffer .isAffinitySupported ()) {
282- conn = extractFromFreeList (ConnectionBuffer .GET_LAST );
283- }
284- if (conn != null ) {
285- return conn ;
286- }
287293 String msg = "Unsuccessfully waited [" + waitTimeoutMillis + "] millis for a connection to be returned."
288294 + " No connections are free. You need to Increase the max connections of [" + maxSize + "]"
289295 + " or look for a connection pool leak using datasource.xxx.capturestacktrace=true" ;
@@ -296,8 +302,7 @@ private PooledConnection _obtainConnectionWaitLoop(Object affinitiyId) throws SQ
296302
297303 try {
298304 nanos = notEmpty .awaitNanos (nanos );
299- PooledConnection c = extractFromFreeList (affinitiyId );
300-
305+ PooledConnection c = this .extractFromFreeList (affinitiyId , false );
301306 if (c != null ) {
302307 // successfully waited
303308 return c ;
0 commit comments