From: fhanik Date: Fri, 10 Jul 2009 21:02:43 +0000 (+0000) Subject: Fix a concurrency issue with connections being released and then trying to be reconnected X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=03c22b8eff3ec3bfd5cf56ad96f6290fbdc8011e;p=tomcat7.0 Fix a concurrency issue with connections being released and then trying to be reconnected git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@793108 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java index a1eed8180..b02b06c85 100644 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java +++ b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java @@ -648,6 +648,11 @@ public class ConnectionPool { boolean setToNull = false; try { con.lock(); + + if (con.isReleased()) { + return null; + } + if (!con.isDiscarded() && !con.isInitialized()) { //attempt to connect con.connect(); diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolProperties.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolProperties.java index b28f411c3..9c7d29b5d 100644 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolProperties.java +++ b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolProperties.java @@ -72,7 +72,7 @@ public class PoolProperties { protected boolean useEquals = false; protected int abandonWhenPercentageFull = 0; protected long maxAge = 0; - + protected boolean useLock = true; private InterceptorDefinition[] interceptors = null; public void setAbandonWhenPercentageFull(int percentage) { @@ -531,7 +531,15 @@ public class PoolProperties { public void setMaxAge(long maxAge) { this.maxAge = maxAge; } + + public boolean getUseLock() { + return useLock; + } + + public void setUseLock(boolean useLock) { + this.useLock = useLock; + } - + } diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PooledConnection.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PooledConnection.java index 24c33772b..f01b2a03a 100644 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PooledConnection.java +++ b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PooledConnection.java @@ -112,7 +112,6 @@ public class PooledConnection { private AtomicBoolean released = new AtomicBoolean(false); - public PooledConnection(PoolProperties prop, ConnectionPool parent) { instanceCount = counter.addAndGet(1); poolProperties = prop; @@ -367,7 +366,7 @@ public class PooledConnection { * Otherwise this is a noop for performance */ public void lock() { - if (this.poolProperties.isPoolSweeperEnabled()) { + if (poolProperties.getUseLock() || this.poolProperties.isPoolSweeperEnabled()) { //optimized, only use a lock when there is concurrency lock.writeLock().lock(); } @@ -378,7 +377,7 @@ public class PooledConnection { * Otherwise this is a noop for performance */ public void unlock() { - if (this.poolProperties.isPoolSweeperEnabled()) { + if (poolProperties.getUseLock() || this.poolProperties.isPoolSweeperEnabled()) { //optimized, only use a lock when there is concurrency lock.writeLock().unlock(); } @@ -423,5 +422,9 @@ public class PooledConnection { public String toString() { return "PooledConnection["+(connection!=null?connection.toString():"null")+"]"; } + + public boolean isReleased() { + return released.get(); + } } diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/ConnectCountTest.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/ConnectCountTest.java index 61183293b..f0e8c103b 100644 --- a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/ConnectCountTest.java +++ b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/ConnectCountTest.java @@ -62,7 +62,7 @@ public class ConnectCountTest extends DefaultTestCase { @Override protected void tearDown() throws Exception { - Driver.connectCount.set(0); + Driver.reset(); super.tearDown(); } diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestConcurrency.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestConcurrency.java new file mode 100644 index 000000000..23b4ef027 --- /dev/null +++ b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestConcurrency.java @@ -0,0 +1,144 @@ +package org.apache.tomcat.jdbc.test; + +import java.sql.Connection; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.tomcat.jdbc.pool.DataSource; +import org.apache.tomcat.jdbc.test.driver.Driver; + +public class TestConcurrency extends DefaultTestCase { + + public static final boolean debug = Boolean.getBoolean("jdbc.debug"); + + protected volatile DataSource ds = null; + + public TestConcurrency(String name) { + super(name); + } + + @Override + public void setUp() { + // TODO Auto-generated method stub + ds = createDefaultDataSource(); + ds.getPoolProperties().setDriverClassName(Driver.class.getName()); + ds.getPoolProperties().setUrl(Driver.url); + ds.getPoolProperties().setInitialSize(0); + ds.getPoolProperties().setMaxIdle(0); + ds.getPoolProperties().setMinIdle(0); + ds.getPoolProperties().setMaxActive(10); + ds.getPoolProperties().setRemoveAbandoned(true); + ds.getPoolProperties().setLogAbandoned(true); + ds.getPoolProperties().setTestWhileIdle(true); + ds.getPoolProperties().setMinEvictableIdleTimeMillis(750); + ds.getPoolProperties().setTimeBetweenEvictionRunsMillis(25); + } + + @Override + protected void tearDown() throws Exception { + Driver.reset(); + super.tearDown(); + } + + public void testSimple() throws Exception { + ds.getConnection().close(); + final int iter = 1000 * 10; + final AtomicInteger loopcount = new AtomicInteger(0); + final Runnable run = new Runnable() { + public void run() { + try { + while (loopcount.incrementAndGet() < iter) { + Connection con = ds.getConnection(); + Thread.sleep(10); + con.close(); + } + }catch (Exception x) { + loopcount.set(iter); //stops the test + x.printStackTrace(); + } + } + }; + Thread[] threads = new Thread[20]; + for (int i=0; i