You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ps...@apache.org on 2024/02/15 23:07:05 UTC
(commons-dbcp) branch master updated: Make BDS actually implement usage tracking. JIRA: DBCP-590.
This is an automated email from the ASF dual-hosted git repository.
psteitz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-dbcp.git
The following commit(s) were added to refs/heads/master by this push:
new 4dd9df42 Make BDS actually implement usage tracking. JIRA: DBCP-590.
4dd9df42 is described below
commit 4dd9df42ffe0905c6fd74515017a22505ae863cf
Author: Phil Steitz <ph...@gmail.com>
AuthorDate: Thu Feb 15 16:06:54 2024 -0700
Make BDS actually implement usage tracking. JIRA: DBCP-590.
---
src/changes/changes.xml | 1 +
.../org/apache/commons/dbcp2/BasicDataSource.java | 4 +++
.../apache/commons/dbcp2/PoolableConnection.java | 12 +++++++
.../commons/dbcp2/PoolableConnectionFactory.java | 4 ++-
.../dbcp2/TestAbandonedBasicDataSource.java | 39 ++++++++++++++++++++++
5 files changed, 59 insertions(+), 1 deletion(-)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 020237e7..481b515b 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -64,6 +64,7 @@ The <action> type attribute can be add,update,fix,remove.
<body>
<release version="2.11.1" date="2024-MM-DD" description="This is a minor release, including bug fixes and enhancements.">
<!-- FIX -->
+ <action type="fix" issue="DBCP-590" dev="psteitz" due-to=" RĂ©da Housni Alaoui">BasicDataSource#setAbandonedUsageTracking has no effect.</action>
<action type="fix" issue="DBCP-596" dev="ggregory" due-to="Aapo Haapanen, Gary Gregory">PoolingConnection.toString() causes StackOverflowError.</action>
<!-- ADD -->
<action type="add" dev="ggregory" due-to="Gary Gregory">Add property project.build.outputTimestamp for build reproducibility.</action>
diff --git a/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java b/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java
index 1fb8dac8..48b2fedb 100644
--- a/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java
+++ b/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java
@@ -483,6 +483,10 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
updateJmxName(config);
// Disable JMX on the underlying pool if the DS is not registered:
config.setJmxEnabled(registeredJmxObjectName != null);
+ // Set up usage tracking if enabled
+ if (getAbandonedUsageTracking() && abandonedConfig != null) {
+ abandonedConfig.setUseUsageTracking(true);
+ }
final GenericObjectPool<PoolableConnection> gop = createObjectPool(factory, config, abandonedConfig);
gop.setMaxTotal(maxTotal);
gop.setMaxIdle(maxIdle);
diff --git a/src/main/java/org/apache/commons/dbcp2/PoolableConnection.java b/src/main/java/org/apache/commons/dbcp2/PoolableConnection.java
index 9bc4059a..c99e789a 100644
--- a/src/main/java/org/apache/commons/dbcp2/PoolableConnection.java
+++ b/src/main/java/org/apache/commons/dbcp2/PoolableConnection.java
@@ -34,6 +34,7 @@ import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import org.apache.commons.pool2.ObjectPool;
+import org.apache.commons.pool2.impl.GenericObjectPool;
/**
* A delegating connection that, rather than closing the underlying connection, returns itself to an {@link ObjectPool}
@@ -333,6 +334,17 @@ public class PoolableConnection extends DelegatingConnection<Connection> impleme
super.closeInternal();
}
+ @Override
+ public void setLastUsed() {
+ super.setLastUsed();
+ if (pool instanceof GenericObjectPool<?>) {
+ final GenericObjectPool<PoolableConnection> gop = (GenericObjectPool<PoolableConnection>) pool;
+ if (gop.isAbandonedConfig()) {
+ gop.use(this);
+ }
+ }
+ }
+
/**
* Validates the connection, using the following algorithm:
* <ol>
diff --git a/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java b/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java
index 297b4cba..51600251 100644
--- a/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java
+++ b/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java
@@ -467,7 +467,9 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo
final PoolableConnection pc = new PoolableConnection(conn, pool, connJmxName, disconnectionSqlCodes, fastFailValidation);
pc.setCacheState(cacheState);
- return new DefaultPooledObject<>(pc);
+ final DefaultPooledObject<PoolableConnection> pooledObject = new DefaultPooledObject<>(pc);
+ pooledObject.setRequireFullStackTrace(true);
+ return pooledObject;
}
@Override
diff --git a/src/test/java/org/apache/commons/dbcp2/TestAbandonedBasicDataSource.java b/src/test/java/org/apache/commons/dbcp2/TestAbandonedBasicDataSource.java
index 8b1d9287..dbd2b929 100644
--- a/src/test/java/org/apache/commons/dbcp2/TestAbandonedBasicDataSource.java
+++ b/src/test/java/org/apache/commons/dbcp2/TestAbandonedBasicDataSource.java
@@ -389,4 +389,43 @@ public class TestAbandonedBasicDataSource extends TestBasicDataSource {
checkLastUsedStatement(st, conn);
}
}
+
+ @Test
+ public void testAbandonedStackTraces() throws Exception {
+ // force abandoned
+ ds.setRemoveAbandonedTimeout(Duration.ZERO);
+ ds.setMaxTotal(1);
+ ds.setAccessToUnderlyingConnectionAllowed(true);
+ ds.setAbandonedUsageTracking(true);
+
+ try (Connection conn1 = getConnection()) {
+ assertNotNull(conn1);
+ assertEquals(1, ds.getNumActive());
+ // Use the connection
+ try (Statement stmt = conn1.createStatement()) {
+ assertNotNull(stmt);
+ stmt.execute("SELECT 1 FROM DUAL");
+ }
+
+ try (Connection conn2 = getConnection()) {
+ // Attempt to borrow object triggers abandoned cleanup
+ // conn1 should be closed by the pool to make room
+ assertNotNull(conn2);
+ assertEquals(1, ds.getNumActive());
+ // Verify that conn1 is closed
+ assertTrue(((DelegatingConnection<?>) conn1).getInnermostDelegate().isClosed());
+ // Verify that conn1 is aborted
+ final TesterConnection tCon = (TesterConnection) ((DelegatingConnection<?>) conn1)
+ .getInnermostDelegate();
+ assertTrue(tCon.isAborted());
+
+ }
+ assertEquals(0, ds.getNumActive());
+ }
+ assertEquals(0, ds.getNumActive());
+ final String stackTrace = sw.toString();
+ assertTrue(stackTrace.contains("testAbandonedStackTraces"), stackTrace);
+ assertTrue(stackTrace.contains("Pooled object created"), stackTrace);
+ assertTrue(stackTrace.contains("The last code to use this object was:"), stackTrace);
+ }
}