Skip to content

Commit 0b352a1

Browse files
committed
add listeners to control max connections
ADD: forceTrim zwischencommit test erweitert + fix revert logback revert pool as parameter fix test
1 parent d982e5c commit 0b352a1

File tree

8 files changed

+253
-11
lines changed

8 files changed

+253
-11
lines changed

ebean-datasource-api/src/main/java/io/ebean/datasource/DataSourcePool.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ static DataSourceBuilder builder() {
102102
*/
103103
SQLException dataSourceDownReason();
104104

105+
int forceTrim(int trimCount);
106+
105107
/**
106108
* Set a new maximum size.
107109
* <p>

ebean-datasource-api/src/main/java/io/ebean/datasource/DataSourcePoolListener.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,53 @@
1414
*/
1515
public interface DataSourcePoolListener {
1616

17+
/**
18+
* Called before a connection has been created
19+
*/
20+
default void onBeforeCreateConnection(DataSourcePool pool) {}
21+
22+
/**
23+
* Called after a connection has been created
24+
*/
25+
default void onAfterCreateConnection(DataSourcePool pool, Connection connection) {}
26+
27+
/**
28+
* Called before a connection has been retrieved from the connection pool
29+
*/
30+
default void onBeforeBorrowConnection(DataSourcePool pool) {}
31+
1732
/**
1833
* Called after a connection has been retrieved from the connection pool
1934
*/
35+
default void onAfterBorrowConnection(DataSourcePool pool, Connection connection) {onAfterBorrowConnection(connection);}
36+
37+
/**
38+
* Called after a connection has been retrieved from the connection pool.
39+
*
40+
* Migrate to <code>onAfterBorrowConnection(DataSourcePool pool, Connection connection)</code>
41+
*/
42+
@Deprecated
2043
default void onAfterBorrowConnection(Connection connection) {}
2144

2245
/**
2346
* Called before a connection will be put back to the connection pool
2447
*/
48+
default void onBeforeReturnConnection(DataSourcePool pool, Connection connection) {onBeforeReturnConnection(connection);}
49+
50+
/**
51+
* Called before a connection will be put back to the connection pool.
52+
*
53+
* Migrate to <code>onBeforeReturnConnection(DataSourcePool pool, Connection connection)</code>
54+
*/
55+
@Deprecated
2556
default void onBeforeReturnConnection(Connection connection) {}
2657

58+
/**
59+
* Called after a connection will be put back to the connection pool
60+
*/
61+
default void onAfterReturnConnection(DataSourcePool pool) {}
62+
63+
default void onBeforeCloseConnection(DataSourcePool pool, Connection connection) {}
2764

65+
default void onAfterCloseConnection(DataSourcePool pool) {}
2866
}

ebean-datasource/pom.xml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
<dependency>
3030
<groupId>io.ebean</groupId>
3131
<artifactId>ebean-test-containers</artifactId>
32-
<version>7.3</version>
32+
<version>7.6</version>
3333
<scope>test</scope>
3434
</dependency>
3535

@@ -83,6 +83,13 @@
8383
<scope>test</scope>
8484
</dependency>
8585

86+
<dependency>
87+
<groupId>org.mariadb.jdbc</groupId>
88+
<artifactId>mariadb-java-client</artifactId>
89+
<version>3.5.1</version>
90+
<scope>test</scope>
91+
</dependency>
92+
8693
</dependencies>
8794

8895
</project>

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

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ void pstmtCacheMetrics(PstmtCache pstmtCache) {
157157
pscRem.add(pstmtCache.removeCount());
158158
}
159159

160+
161+
160162
final class HeartBeatRunnable extends TimerTask {
161163
@Override
162164
public void run() {
@@ -446,7 +448,20 @@ private Connection initConnection(Connection conn) throws SQLException {
446448
}
447449

448450
private Connection createConnection() throws SQLException {
449-
return initConnection(source.getConnection());
451+
452+
if (poolListener != null) {
453+
poolListener.onBeforeCreateConnection(this);
454+
}
455+
Connection connection = initConnection(source.getConnection());
456+
if (poolListener != null) {
457+
poolListener.onAfterCreateConnection(this, connection);
458+
}
459+
return connection;
460+
}
461+
462+
@Override
463+
public int forceTrim(int trimCount) {
464+
return queue.forceTrim(trimCount);
450465
}
451466

452467
@Override
@@ -559,9 +574,12 @@ void removeClosedConnection(PooledConnection pooledConnection) {
559574
*/
560575
private void returnTheConnection(PooledConnection pooledConnection, boolean forceClose) {
561576
if (poolListener != null && !forceClose) {
562-
poolListener.onBeforeReturnConnection(pooledConnection);
577+
poolListener.onBeforeReturnConnection(this, pooledConnection);
563578
}
564579
queue.returnPooledConnection(pooledConnection, forceClose);
580+
if (poolListener != null && !forceClose) {
581+
poolListener.onAfterReturnConnection(this);
582+
}
565583
}
566584

567585
void returnConnectionReset(PooledConnection pooledConnection) {
@@ -570,6 +588,17 @@ void returnConnectionReset(PooledConnection pooledConnection) {
570588
reset();
571589
}
572590

591+
void onBeforeCloseConnection(PooledConnection pooledConnection) {
592+
if (poolListener != null) {
593+
poolListener.onBeforeCloseConnection(this, pooledConnection);
594+
}
595+
}
596+
597+
void onAfterCloseConnection() {
598+
if (poolListener != null) {
599+
poolListener.onAfterCloseConnection(this);
600+
}
601+
}
573602
/**
574603
* Grow the pool by creating a new connection. The connection can either be
575604
* added to the available list, or returned.
@@ -608,7 +637,14 @@ private void reset() {
608637
*/
609638
@Override
610639
public Connection getConnection(String username, String password) throws SQLException {
611-
return initConnection(source.getConnection(username, password));
640+
if (poolListener != null) {
641+
poolListener.onBeforeCreateConnection(this);
642+
}
643+
Connection connection = initConnection(source.getConnection(username, password));
644+
if (poolListener != null) {
645+
poolListener.onAfterCreateConnection(this, connection);
646+
}
647+
return connection;
612648
}
613649

614650
/**
@@ -626,12 +662,15 @@ public Connection getConnection() throws SQLException {
626662
* will go into a wait if the pool has hit its maximum size.
627663
*/
628664
private PooledConnection getPooledConnection() throws SQLException {
665+
if (poolListener != null) {
666+
poolListener.onBeforeBorrowConnection(this);
667+
}
629668
PooledConnection c = queue.obtainConnection();
630669
if (captureStackTrace) {
631670
c.setStackTrace(Thread.currentThread().getStackTrace());
632671
}
633672
if (poolListener != null) {
634-
poolListener.onAfterBorrowConnection(c);
673+
poolListener.onAfterBorrowConnection(this, c);
635674
}
636675
return c;
637676
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,12 @@ void closeAll(boolean logErrors) {
6363
/**
6464
* Trim any inactive connections that have not been used since usedSince.
6565
*/
66-
int trim(int minSize, long usedSince, long createdSince) {
66+
int trim(int minSize, long usedSince, long createdSince, boolean forced) {
6767
int trimCount = 0;
6868
ListIterator<PooledConnection> iterator = freeBuffer.listIterator(minSize);
6969
while (iterator.hasNext()) {
7070
PooledConnection pooledConnection = iterator.next();
71-
if (pooledConnection.shouldTrim(usedSince, createdSince)) {
71+
if (pooledConnection.shouldTrim(usedSince, createdSince, forced)) {
7272
iterator.remove();
7373
pooledConnection.closeConnectionFully(true);
7474
trimCount++;

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ final class PooledConnection extends ConnectionDelegator {
3737
*/
3838
private static final String REASON_RESET = "reset";
3939

40+
/**
41+
* Marker for when connection is closed due a forced trim.
42+
*/
43+
private static final String REASON_FORCED = "forced";
44+
4045
/**
4146
* Set when connection is idle in the pool. In general when in the pool the
4247
* connection should not be modified.
@@ -237,6 +242,7 @@ void closeConnectionFully(boolean logErrors) {
237242
}
238243
if (pool != null) {
239244
pool.pstmtCacheMetrics(pstmtCache);
245+
pool.onBeforeCloseConnection(this);
240246
}
241247
try {
242248
if (connection.isClosed()) {
@@ -276,6 +282,7 @@ void closeConnectionFully(boolean logErrors) {
276282
try {
277283
connection.close();
278284
pool.dec();
285+
pool.onAfterCloseConnection();
279286
} catch (SQLException ex) {
280287
if (logErrors || Log.isLoggable(System.Logger.Level.DEBUG)) {
281288
Log.error("Error when fully closing connection [" + fullDescription() + "]", ex);
@@ -363,7 +370,7 @@ private PreparedStatement prepareStatement(String sql, boolean useFlag, int flag
363370
lastStatement = sql;
364371
// try to get a matching cached PStmt from the cache.
365372
ExtendedPreparedStatement pstmt = pstmtCache.remove(cacheKey);
366-
if (pstmt != null) {
373+
if (pstmt != null && !pstmt.isClosed()) {
367374
return pstmt.reset();
368375
}
369376

@@ -543,7 +550,7 @@ boolean shouldTrimOnReturn(long lastResetTime, long maxAgeMillis) {
543550
/**
544551
* Return true if the connection has been idle for too long or is too old.
545552
*/
546-
boolean shouldTrim(long usedSince, long createdSince) {
553+
boolean shouldTrim(long usedSince, long createdSince, boolean forced) {
547554
if (lastUseTime < usedSince) {
548555
// been idle for too long so trim it
549556
this.closeReason = REASON_IDLE;
@@ -554,6 +561,10 @@ boolean shouldTrim(long usedSince, long createdSince) {
554561
this.closeReason = REASON_MAXAGE;
555562
return true;
556563
}
564+
if (forced) {
565+
this.closeReason = REASON_FORCED;
566+
return true;
567+
}
557568
return false;
558569
}
559570

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

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import io.ebean.datasource.pool.ConnectionPool.Status;
66

77
import java.sql.SQLException;
8+
import java.util.List;
89
import java.util.concurrent.TimeUnit;
910
import java.util.concurrent.locks.Condition;
1011
import java.util.concurrent.locks.ReentrantLock;
@@ -376,10 +377,10 @@ private boolean trimInactiveConnections(long maxInactiveMillis, long maxAgeMilli
376377
if (freeList.size() > minSize) {
377378
// trim on maxInactive and maxAge
378379
long usedSince = System.currentTimeMillis() - maxInactiveMillis;
379-
trimmedCount = freeList.trim(minSize, usedSince, createdSince);
380+
trimmedCount = freeList.trim(minSize, usedSince, createdSince, false);
380381
} else if (createdSince > 0) {
381382
// trim only on maxAge
382-
trimmedCount = freeList.trim(0, createdSince, createdSince);
383+
trimmedCount = freeList.trim(0, createdSince, createdSince, false);
383384
} else {
384385
trimmedCount = 0;
385386
}
@@ -401,6 +402,27 @@ private void closeFreeConnections(boolean logErrors) {
401402
}
402403
}
403404

405+
int forceTrim(int trimCount) {
406+
int trimmedCount = 0;
407+
lock.lock();
408+
try {
409+
int trimStart = freeList.size() - trimCount;
410+
trimStart = Math.max(trimStart, 0);
411+
412+
if (freeList.size() > trimStart) {
413+
trimmedCount = freeList.trim(trimStart, 0, 0, true);
414+
}
415+
} finally {
416+
lock.unlock();
417+
}
418+
if (trimmedCount != 0) {
419+
if (Log.isLoggable(DEBUG)) {
420+
Log.debug("DataSource [{0}] forced trimmed [{1}] connections. New size[{2}]", name, trimmedCount, totalConnections());
421+
}
422+
}
423+
return trimmedCount;
424+
}
425+
404426
/**
405427
* Close any busy connections that have not been used for some time.
406428
* <p>

0 commit comments

Comments
 (0)