Skip to content

Commit 905f878

Browse files
committed
Optimized locking access
1 parent 0410531 commit 905f878

File tree

2 files changed

+36
-37
lines changed

2 files changed

+36
-37
lines changed

ebean-datasource/src/main/java/io/ebean/datasource/pool/ConnectionPool.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ public SQLException dataSourceDownReason() {
302302

303303
private void notifyDataSourceIsDown(SQLException reason) {
304304
if (dataSourceUp.get()) {
305-
reset();
305+
reset(false);
306306
notifyDown(reason);
307307
}
308308
}
@@ -326,7 +326,7 @@ private void notifyDown(SQLException reason) {
326326

327327
private void notifyDataSourceIsUp() {
328328
if (!dataSourceUp.get()) {
329-
reset();
329+
reset(true);
330330
notifyUp();
331331
}
332332
}
@@ -583,7 +583,7 @@ private void returnTheConnection(PooledConnection pooledConnection, boolean forc
583583
void returnConnectionReset(PooledConnection pooledConnection) {
584584
queue.returnPooledConnection(pooledConnection, true);
585585
Log.warn("Resetting DataSource on read-only failure [{0}]", name);
586-
reset();
586+
reset(false);
587587
}
588588

589589
/**
@@ -612,9 +612,9 @@ PooledConnection createConnectionForQueue(int connId) throws SQLException {
612612
* <li>Busy connections are closed when they are returned to the pool.</li>
613613
* </ul>
614614
*/
615-
private void reset() {
615+
private void reset(boolean logErrors) {
616616
heartbeatPoolExhaustedCount = 0;
617-
queue.reset(leakTimeMinutes);
617+
queue.reset(leakTimeMinutes, logErrors);
618618
}
619619

620620
/**

ebean-datasource/src/main/java/io/ebean/datasource/pool/PooledConnectionQueue.java

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -310,11 +310,12 @@ private PooledConnection _obtainConnectionWaitLoop(Object affinitiyId) throws SQ
310310
}
311311

312312
PoolStatus shutdown(boolean closeBusyConnections) {
313+
313314
lock.lock();
314315
try {
315316
doingShutdown = true;
316317
PoolStatus status = createStatus();
317-
closeFreeConnections(true);
318+
doCloseFreeConnections(buffer.clearFreeList(), true);
318319

319320
if (!closeBusyConnections) {
320321
// connections close on return to pool
@@ -323,7 +324,7 @@ PoolStatus shutdown(boolean closeBusyConnections) {
323324
if (buffer.busySize() > 0) {
324325
Log.warn("Closing busy connections on shutdown size: {0}", buffer.busySize());
325326
dumpBusyConnectionInformation();
326-
closeBusyConnections(0);
327+
doCloseBusyConnections(buffer.cleanupBusyList(0), true);
327328
}
328329
}
329330
return status;
@@ -339,24 +340,28 @@ PoolStatus shutdown(boolean closeBusyConnections) {
339340
* <p>
340341
* This is typically done when a database down event occurs.
341342
*/
342-
void reset(long leakTimeMinutes) {
343+
void reset(long leakTimeMinutes, boolean logErrors) {
344+
List<PooledConnection> busyConnections;
345+
List<PooledConnection> freeConnections;
343346
lock.lock();
344347
try {
345348
PoolStatus status = createStatus();
346349
Log.info("Resetting DataSource [{0}] {1}", name, status);
347350
lastResetTime = System.currentTimeMillis();
348351

349-
closeFreeConnections(false);
350-
closeBusyConnections(leakTimeMinutes);
351-
352-
String busyInfo = getBusyConnectionInformation();
353-
if (!busyInfo.isEmpty()) {
354-
Log.info("Busy Connections:\n {0}", busyInfo);
355-
}
352+
freeConnections = buffer.clearFreeList();
353+
busyConnections = buffer.cleanupBusyList(leakTimeMinutes);
356354

357355
} finally {
358356
lock.unlock();
359357
}
358+
// we are closing the connections outside the lock
359+
doCloseFreeConnections(freeConnections, logErrors);
360+
doCloseBusyConnections(busyConnections, logErrors);
361+
String busyInfo = getBusyConnectionInformation();
362+
if (!busyInfo.isEmpty()) {
363+
Log.info("Busy Connections:\n {0}", busyInfo);
364+
}
360365
}
361366

362367
void trim(long maxInactiveMillis, long maxAgeMillis) {
@@ -401,48 +406,42 @@ private boolean trimInactiveConnections(long maxInactiveMillis, long maxAgeMilli
401406
}
402407

403408
/**
404-
* Close all the connections that are in the free list.
409+
* Close all the connections that are from the free list.
405410
*/
406-
private void closeFreeConnections(boolean logErrors) {
407-
List<PooledConnection> tempList;
408-
lock.lock();
409-
try {
410-
tempList = buffer.clearFreeList();
411-
} finally {
412-
lock.unlock();
413-
}
414-
// closing the connections is done outside lock
411+
void doCloseFreeConnections(List<PooledConnection> connections, boolean logErrors) {
415412
if (Log.isLoggable(System.Logger.Level.TRACE)) {
416-
Log.trace("... closing all {0} connections from the free list with logErrors: {1}", tempList.size(), logErrors);
413+
Log.trace("... closing all {0} connections from the free list with logErrors: {1}", connections.size(), logErrors);
417414
}
418-
for (PooledConnection connection : tempList) {
419-
connection.closeConnectionFully(logErrors);
415+
for (PooledConnection pc : connections) {
416+
try {
417+
pc.closeConnectionFully(logErrors);
418+
} catch (Throwable ex) {
419+
Log.error("Error when closing potentially leaked connection " + pc.description(), ex);
420+
}
420421
}
421422
}
422423

423424
/**
424425
* Close any busy connections that have not been used for some time.
425426
* <p>
427+
* The connections are removed with buffer.cleanupBusyList(leakTimeout)
428+
* from the buffer and are normally closed outside the lock.
426429
* These connections are considered to have leaked from the connection pool.
427430
* <p>
428431
* Connection leaks occur when code doesn't ensure that connections are
429432
* closed() after they have been finished with. There should be an
430433
* appropriate try catch finally block to ensure connections are always
431434
* closed and put back into the pool.
432435
*/
433-
void closeBusyConnections(long leakTimeMinutes) {
434-
List<PooledConnection> tempList;
435-
lock.lock();
436-
try {
437-
tempList = buffer.cleanupBusyList(leakTimeMinutes);
438-
} finally {
439-
lock.unlock();
436+
void doCloseBusyConnections(List<PooledConnection> connections, boolean logErrors) {
437+
if (Log.isLoggable(System.Logger.Level.TRACE)) {
438+
Log.trace("... closing all {0} connections from the busy list with logErrors: {1}", connections.size(), logErrors);
440439
}
441-
for (PooledConnection pc : tempList) {
440+
for (PooledConnection pc : connections) {
442441
try {
443442
Log.warn("DataSource closing busy connection? {0}", pc.fullDescription());
444443
System.out.println("CLOSING busy connection: " + pc.fullDescription());
445-
pc.closeConnectionFully(false);
444+
pc.closeConnectionFully(logErrors);
446445
} catch (Exception ex) {
447446
Log.error("Error when closing potentially leaked connection " + pc.description(), ex);
448447
}

0 commit comments

Comments
 (0)