You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by fh...@apache.org on 2011/11/29 01:05:44 UTC
svn commit: r1207712 - in /tomcat/trunk/modules/jdbc-pool: doc/jdbc-pool.xml
src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java
src/test/java/org/apache/tomcat/jdbc/test/PoolCleanerTest.java
Author: fhanik
Date: Tue Nov 29 00:05:43 2011
New Revision: 1207712
URL: http://svn.apache.org/viewvc?rev=1207712&view=rev
Log:
Conserve threads by allowing multiple pools in the same classloader to share a pool cleaner thread
Added:
tomcat/trunk/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/PoolCleanerTest.java (with props)
Modified:
tomcat/trunk/modules/jdbc-pool/doc/jdbc-pool.xml
tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java
Modified: tomcat/trunk/modules/jdbc-pool/doc/jdbc-pool.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/doc/jdbc-pool.xml?rev=1207712&r1=1207711&r2=1207712&view=diff
==============================================================================
--- tomcat/trunk/modules/jdbc-pool/doc/jdbc-pool.xml (original)
+++ tomcat/trunk/modules/jdbc-pool/doc/jdbc-pool.xml Tue Nov 29 00:05:43 2011
@@ -281,7 +281,8 @@
<p>(int) The number of milliseconds to sleep between runs of the idle connection validation/cleaner thread.
This value should not be set under 1 second. It dictates how often we check for idle, abandoned connections, and how often
we validate idle connections.
- The default value is <code>5000</code> (5 seconds).</p>
+ The default value is <code>5000</code> (5 seconds). <br/>
+ </p>
</attribute>
<attribute name="numTestsPerEvictionRun" required="false">
@@ -816,6 +817,9 @@
ant test (runs tests, expects a test database to be setup)
</source>
</p>
+ <p>
+ The system is structured for a Maven build, but does generate release artifacts. Just the library itself.
+ </p>
</subsection>
</section>
</body>
Modified: tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java?rev=1207712&r1=1207711&r2=1207712&view=diff
==============================================================================
--- tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java (original)
+++ tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java Tue Nov 29 00:05:43 2011
@@ -21,8 +21,14 @@ import java.lang.reflect.InvocationHandl
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.SQLException;
+import java.util.Collections;
import java.util.ConcurrentModificationException;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
+import java.util.Set;
+import java.util.Timer;
+import java.util.TimerTask;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
@@ -785,13 +791,12 @@ public class ConnectionPool {
protected boolean terminateTransaction(PooledConnection con) {
try {
if (con.getPoolProperties().getDefaultAutoCommit()==Boolean.FALSE) {
- boolean autocommit = con.getConnection().getAutoCommit();
- if (!autocommit) {
- if (this.getPoolProperties().getRollbackOnReturn()) {
- con.getConnection().rollback();
- } else if (this.getPoolProperties().getCommitOnReturn()) {
- con.getConnection().commit();
- }
+ if (this.getPoolProperties().getRollbackOnReturn()) {
+ boolean autocommit = con.getConnection().getAutoCommit();
+ if (!autocommit) con.getConnection().rollback();
+ } else if (this.getPoolProperties().getCommitOnReturn()) {
+ boolean autocommit = con.getConnection().getAutoCommit();
+ if (!autocommit) con.getConnection().commit();
}
}
return true;
@@ -1185,14 +1190,54 @@ public class ConnectionPool {
}
}
+
+
+
+ private static volatile Timer poolCleanTimer = null;
+ private static HashSet<PoolCleaner> cleaners = new HashSet<PoolCleaner>();
+
+ private static synchronized void registerCleaner(PoolCleaner cleaner) {
+ unregisterCleaner(cleaner);
+ cleaners.add(cleaner);
+ if (poolCleanTimer == null) {
+ poolCleanTimer = new Timer("PoolCleaner["
+ + System.identityHashCode(ConnectionPool.class
+ .getClassLoader()) + ":"
+ + System.currentTimeMillis() + "]", true);
+ }
+ poolCleanTimer.scheduleAtFixedRate(cleaner, cleaner.sleepTime,
+ cleaner.sleepTime);
+ }
+
+ private static synchronized void unregisterCleaner(PoolCleaner cleaner) {
+ boolean removed = cleaners.remove(cleaner);
+ if (removed) {
+ cleaner.cancel();
+ if (poolCleanTimer != null) {
+ poolCleanTimer.purge();
+ if (cleaners.size() == 0) {
+ poolCleanTimer.cancel();
+ poolCleanTimer = null;
+ }
+ }
+ }
+ }
+
+ public static Set<TimerTask> getPoolCleaners() {
+ return Collections.<TimerTask>unmodifiableSet(cleaners);
+ }
+
+ public static Timer getPoolTimer() {
+ return poolCleanTimer;
+ }
- protected class PoolCleaner extends Thread {
+ protected class PoolCleaner extends TimerTask {
protected ConnectionPool pool;
protected long sleepTime;
protected volatile boolean run = true;
+ protected volatile long lastRun = 0;
+
PoolCleaner(String name, ConnectionPool pool, long sleepTime) {
- super(name);
- this.setDaemon(true);
this.pool = pool;
this.sleepTime = sleepTime;
if (sleepTime <= 0) {
@@ -1205,37 +1250,32 @@ public class ConnectionPool {
@Override
public void run() {
- while (run) {
+ if (pool.isClosed()) {
+ if (pool.getSize() <= 0) {
+ run = false;
+ }
+ } else if ((System.currentTimeMillis() - lastRun) > sleepTime) {
+ lastRun = System.currentTimeMillis();
try {
- sleep(sleepTime);
- } catch (InterruptedException e) {
- // ignore it
- Thread.interrupted();
- continue;
- } //catch
+ if (pool.getPoolProperties().isRemoveAbandoned())
+ pool.checkAbandoned();
+ if (pool.getPoolProperties().getMinIdle() < pool.idle
+ .size())
+ pool.checkIdle();
+ if (pool.getPoolProperties().isTestWhileIdle())
+ pool.testAllIdle();
+ } catch (Exception x) {
+ log.error("", x);
+ } // catch
+ } // end if
+ } // run
- if (pool.isClosed()) {
- if (pool.getSize() <= 0) {
- run = false;
- }
- } else {
- try {
- if (pool.getPoolProperties().isRemoveAbandoned())
- pool.checkAbandoned();
- if (pool.getPoolProperties().getMinIdle()<pool.idle.size())
- pool.checkIdle();
- if (pool.getPoolProperties().isTestWhileIdle())
- pool.testAllIdle();
- } catch (Exception x) {
- log.error("", x);
- } //catch
- } //end if
- } //while
- } //run
+ public void start() {
+ registerCleaner(this);
+ }
public void stopRunning() {
- run = false;
- interrupt();
+ unregisterCleaner(this);
}
}
}
Added: tomcat/trunk/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/PoolCleanerTest.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/PoolCleanerTest.java?rev=1207712&view=auto
==============================================================================
--- tomcat/trunk/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/PoolCleanerTest.java (added)
+++ tomcat/trunk/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/PoolCleanerTest.java Tue Nov 29 00:05:43 2011
@@ -0,0 +1,66 @@
+package org.apache.tomcat.jdbc.test;
+
+import org.apache.tomcat.jdbc.pool.ConnectionPool;
+import org.apache.tomcat.jdbc.pool.DataSource;
+
+public class PoolCleanerTest extends DefaultTestCase {
+
+ public PoolCleanerTest(String name) {
+ super(name);
+ }
+
+ public void testPoolCleaner() throws Exception {
+ datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(2000);
+ datasource.getPoolProperties().setTestWhileIdle(true);
+ assertEquals("Pool cleaner should not be started yet.",0,ConnectionPool.getPoolCleaners().size() );
+ assertNull("Pool timer should be null", ConnectionPool.getPoolTimer());
+
+ datasource.getConnection().close();
+ assertEquals("Pool cleaner should have 1 cleaner.",1,ConnectionPool.getPoolCleaners().size() );
+ assertNotNull("Pool timer should not be null", ConnectionPool.getPoolTimer());
+
+ datasource.close();
+ assertEquals("Pool shutdown, no cleaners should be present.",0,ConnectionPool.getPoolCleaners().size() );
+ assertNull("Pool timer should be null after shutdown", ConnectionPool.getPoolTimer());
+ }
+
+ public void test2PoolCleaners() throws Exception {
+ datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(2000);
+ datasource.getPoolProperties().setTestWhileIdle(true);
+
+ DataSource ds2 = new DataSource(datasource.getPoolProperties());
+
+ assertEquals("Pool cleaner should not be started yet.",0,ConnectionPool.getPoolCleaners().size() );
+ assertNull("Pool timer should be null", ConnectionPool.getPoolTimer());
+
+ datasource.getConnection().close();
+ ds2.getConnection().close();
+ assertEquals("Pool cleaner should have 2 cleaner.",2,ConnectionPool.getPoolCleaners().size() );
+ assertNotNull("Pool timer should not be null", ConnectionPool.getPoolTimer());
+
+ datasource.close();
+ assertEquals("Pool cleaner should have 1 cleaner.",1,ConnectionPool.getPoolCleaners().size() );
+ assertNotNull("Pool timer should not be null", ConnectionPool.getPoolTimer());
+
+ ds2.close();
+ assertEquals("Pool shutdown, no cleaners should be present.",0,ConnectionPool.getPoolCleaners().size() );
+ assertNull("Pool timer should be null after shutdown", ConnectionPool.getPoolTimer());
+ }
+
+ public void testIdleTimeout() throws Exception {
+ datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(2000);
+ datasource.getPoolProperties().setTestWhileIdle(true);
+ datasource.getPoolProperties().setMaxIdle(0);
+ datasource.getPoolProperties().setInitialSize(0);
+ datasource.getPoolProperties().setMinIdle(0);
+ datasource.getPoolProperties().setMinEvictableIdleTimeMillis(1000);
+ datasource.getConnection().close();
+ assertEquals("Pool should have 1 idle.", 1, datasource.getIdle());
+ Thread.sleep(3000);
+ assertEquals("Pool should have 0 idle.", 0, datasource.getIdle());
+
+
+ }
+
+
+}
Propchange: tomcat/trunk/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/PoolCleanerTest.java
------------------------------------------------------------------------------
svn:eol-style = native
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org