55import io .ebean .datasource .pool .ConnectionPool .Status ;
66
77import java .sql .SQLException ;
8+ import java .util .Collections ;
9+ import java .util .List ;
810import java .util .concurrent .TimeUnit ;
911import java .util .concurrent .locks .Condition ;
1012import java .util .concurrent .locks .ReentrantLock ;
@@ -107,15 +109,10 @@ PoolStatus status(boolean reset) {
107109 }
108110
109111 void setMaxSize (int maxSize ) {
110- lock .lock ();
111- try {
112- if (maxSize < this .minSize ) {
113- throw new IllegalArgumentException ("maxSize " + maxSize + " < minSize " + this .minSize );
114- }
115- this .maxSize = maxSize ;
116- } finally {
117- lock .unlock ();
112+ if (maxSize < this .minSize ) {
113+ throw new IllegalArgumentException ("maxSize " + maxSize + " < minSize " + this .minSize );
118114 }
115+ this .maxSize = maxSize ;
119116 }
120117
121118 private int totalConnections () {
@@ -141,20 +138,24 @@ void ensureMinimumConnections() throws SQLException {
141138 * Return a PooledConnection.
142139 */
143140 void returnPooledConnection (PooledConnection c , boolean forceClose ) {
141+ boolean closeConnection = false ;
144142 lock .lock ();
145143 try {
146144 if (!buffer .removeBusy (c )) {
147145 Log .error ("Connection [{0}] not found in BusyList?" , c );
148146 }
149147 if (forceClose || c .shouldTrimOnReturn (lastResetTime , maxAgeMillis )) {
150- c . closeConnectionFully ( false ) ;
148+ closeConnection = true ;
151149 } else {
152150 buffer .addFree (c );
153151 notEmpty .signal ();
154152 }
155153 } finally {
156154 lock .unlock ();
157155 }
156+ if (closeConnection ) {
157+ c .closeConnectionFully (false );
158+ }
158159 }
159160
160161 private PooledConnection extractFromFreeList (Object affinitiyId ) {
@@ -356,17 +357,12 @@ void reset(long leakTimeMinutes) {
356357 }
357358
358359 void trim (long maxInactiveMillis , long maxAgeMillis ) {
359- lock .lock ();
360- try {
361- if (trimInactiveConnections (maxInactiveMillis , maxAgeMillis )) {
362- try {
363- ensureMinimumConnections ();
364- } catch (SQLException e ) {
365- Log .error ("Error trying to ensure minimum connections" , e );
366- }
360+ if (trimInactiveConnections (maxInactiveMillis , maxAgeMillis )) {
361+ try {
362+ ensureMinimumConnections ();
363+ } catch (SQLException e ) {
364+ Log .error ("Error trying to ensure minimum connections" , e );
367365 }
368- } finally {
369- lock .unlock ();
370366 }
371367 }
372368
@@ -375,33 +371,50 @@ void trim(long maxInactiveMillis, long maxAgeMillis) {
375371 */
376372 private boolean trimInactiveConnections (long maxInactiveMillis , long maxAgeMillis ) {
377373 final long createdSince = (maxAgeMillis == 0 ) ? 0 : System .currentTimeMillis () - maxAgeMillis ;
378- final int trimmedCount ;
379- if (buffer .freeSize () > minSize ) {
380- // trim on maxInactive and maxAge
381- long usedSince = System .currentTimeMillis () - maxInactiveMillis ;
382- trimmedCount = buffer .trim (minSize , usedSince , createdSince );
383- } else if (createdSince > 0 ) {
384- // trim only on maxAge
385- trimmedCount = buffer .trim (0 , createdSince , createdSince );
386- } else {
387- trimmedCount = 0 ;
374+ final List <PooledConnection > toTrim ;
375+ lock .lock ();
376+ try {
377+ if (buffer .freeSize () > minSize ) {
378+ // trim on maxInactive and maxAge
379+ long usedSince = System .currentTimeMillis () - maxInactiveMillis ;
380+ toTrim = buffer .trim (minSize , usedSince , createdSince );
381+ } else if (createdSince > 0 ) {
382+ // trim only on maxAge
383+ toTrim = buffer .trim (0 , createdSince , createdSince );
384+ } else {
385+ toTrim = Collections .emptyList ();
386+ }
387+ } finally {
388+ lock .unlock ();
389+ }
390+ if (toTrim .isEmpty ()) {
391+ return false ;
388392 }
389- if (trimmedCount > 0 && Log .isLoggable (DEBUG )) {
390- Log .debug ("DataSource [{0}] trimmed [{1}] inactive connections. New size[{2}]" , name , trimmedCount , totalConnections ());
393+ toTrim .forEach (pc -> pc .closeConnectionFully (true ));
394+ if (Log .isLoggable (DEBUG )) {
395+ Log .debug ("DataSource [{0}] trimmed [{1}] inactive connections. New size[{2}]" , name , toTrim .size (), totalConnections ());
391396 }
392- return trimmedCount > 0 && buffer .freeSize () < minSize ;
397+ return buffer .freeSize () < minSize ;
393398 }
394399
395400 /**
396401 * Close all the connections that are in the free list.
397402 */
398403 private void closeFreeConnections (boolean logErrors ) {
404+ List <PooledConnection > tempList ;
399405 lock .lock ();
400406 try {
401- buffer .closeAllFree ( logErrors );
407+ tempList = buffer .clearFreeList ( );
402408 } finally {
403409 lock .unlock ();
404410 }
411+ // closing the connections is done outside lock
412+ if (Log .isLoggable (System .Logger .Level .TRACE )) {
413+ Log .trace ("... closing all {0} connections from the free list with logErrors: {1}" , tempList .size (), logErrors );
414+ }
415+ for (PooledConnection connection : tempList ) {
416+ connection .closeConnectionFully (logErrors );
417+ }
405418 }
406419
407420 /**
@@ -415,12 +428,22 @@ private void closeFreeConnections(boolean logErrors) {
415428 * closed and put back into the pool.
416429 */
417430 void closeBusyConnections (long leakTimeMinutes ) {
431+ List <PooledConnection > tempList ;
418432 lock .lock ();
419433 try {
420- buffer .closeBusyConnections (leakTimeMinutes );
434+ tempList = buffer .cleanupBusyList (leakTimeMinutes );
421435 } finally {
422436 lock .unlock ();
423437 }
438+ for (PooledConnection pc : tempList ) {
439+ try {
440+ Log .warn ("DataSource closing busy connection? {0}" , pc .fullDescription ());
441+ System .out .println ("CLOSING busy connection: " + pc .fullDescription ());
442+ pc .closeConnectionFully (false );
443+ } catch (Exception ex ) {
444+ Log .error ("Error when closing potentially leaked connection " + pc .description (), ex );
445+ }
446+ }
424447 }
425448
426449 String getBusyConnectionInformation () {
0 commit comments