From 012899d9d75aef65642014f1f4cc7f12f4c7dc4a Mon Sep 17 00:00:00 2001 From: wenshao Date: Sat, 25 Aug 2012 08:34:13 +0800 Subject: [PATCH] add testcase & bug fixed --- .../alibaba/druid/pool/DruidDataSource.java | 35 ++++--- .../DruidDataSourceTest_notEmptyWait.java | 2 + .../DruidDataSourceTest_notEmptyWait2.java | 92 +++++++++++++++++++ 3 files changed, 117 insertions(+), 12 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_notEmptyWait2.java diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index e9d7e799e4..5d4205ec11 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -32,6 +32,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; import javax.management.JMException; import javax.management.ObjectName; @@ -148,7 +149,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat if (LOG.isInfoEnabled()) { LOG.info("{dataSource-" + this.getID() + "} restart"); } - + this.close(); this.resetStat(); this.inited = false; @@ -347,7 +348,8 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } if (getInitialSize() > maxActive) { - throw new IllegalArgumentException("illegal initialSize " + this.initialSize + ", maxActieve " + maxActive); + throw new IllegalArgumentException("illegal initialSize " + this.initialSize + ", maxActieve " + + maxActive); } if (this.driverClass != null) { @@ -590,15 +592,6 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } public DruidPooledConnection getConnectionDirect(long maxWaitMillis) throws SQLException { - final int maxWaitThreadCount = getMaxWaitThreadCount(); - if (maxWaitThreadCount > 0) { - if (notEmptyWaitThreadCount > maxWaitThreadCount) { - connectErrorCount.incrementAndGet(); - throw new SQLException("maxWaitThreadCount " + maxWaitThreadCount + ", current wait Thread count " - + lock.getQueueLength()); - } - } - for (;;) { DruidPooledConnection poolalbeConnection = getConnectionInternal(maxWaitMillis); @@ -692,6 +685,15 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat throw new DataSourceDisableException(); } + final int maxWaitThreadCount = getMaxWaitThreadCount(); + if (maxWaitThreadCount > 0) { + if (notEmptyWaitThreadCount >= maxWaitThreadCount) { + connectErrorCount.incrementAndGet(); + throw new SQLException("maxWaitThreadCount " + maxWaitThreadCount + ", current wait Thread count " + + lock.getQueueLength()); + } + } + connectCount++; DruidConnectionHolder holder; @@ -1441,7 +1443,12 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } public int getNotEmptyWaitThreadCount() { - return notEmptyWaitThreadCount; + lock.lock(); + try { + return notEmptyWaitThreadCount; + } finally { + lock.unlock(); + } } public int getNotEmptyWaitThreadPeak() { @@ -1814,4 +1821,8 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat public Map getSqlStatMap() { return this.getDataSourceStat().getSqlStatMap(); } + + public Lock getLock() { + return lock; + } } diff --git a/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_notEmptyWait.java b/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_notEmptyWait.java index 55a3dc10bf..8abfb98341 100644 --- a/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_notEmptyWait.java +++ b/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_notEmptyWait.java @@ -56,6 +56,7 @@ public class DruidDataSourceTest_notEmptyWait extends TestCase { startLatch.countDown(); try { Connection conn = dataSource.getConnection(); + Thread.sleep(1); conn.close(); } catch (Exception e) { //e.printStackTrace(); @@ -75,6 +76,7 @@ public class DruidDataSourceTest_notEmptyWait extends TestCase { conn.close(); endLatch.await(100, TimeUnit.MILLISECONDS); + Assert.assertEquals(0, dataSource.getNotEmptyWaitThreadCount()); Assert.assertEquals(10, dataSource.getNotEmptyWaitThreadPeak()); } diff --git a/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_notEmptyWait2.java b/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_notEmptyWait2.java new file mode 100644 index 0000000000..2405413fe2 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_notEmptyWait2.java @@ -0,0 +1,92 @@ +package com.alibaba.druid.bvt.pool; + +import java.sql.Connection; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.alibaba.druid.pool.DruidDataSource; + +public class DruidDataSourceTest_notEmptyWait2 extends TestCase { + + private DruidDataSource dataSource; + + protected void setUp() throws Exception { + dataSource = new DruidDataSource(); + dataSource.setUrl("jdbc:mock:xxx"); + dataSource.setTestOnBorrow(false); + dataSource.setMaxActive(1); + + dataSource.setMaxWaitThreadCount(10); + } + + protected void tearDown() throws Exception { + dataSource.close(); + } + + public void test_maxWaitThread() throws Exception { + { + Connection conn = dataSource.getConnection(); + conn.close(); + } + + Connection conn = dataSource.getConnection(); + final AtomicLong errorCount = new AtomicLong(); + + final int THREAD_COUNT = 10; + final CountDownLatch startLatch = new CountDownLatch(THREAD_COUNT); + final CountDownLatch endLatch = new CountDownLatch(THREAD_COUNT); + Thread[] threads = new Thread[THREAD_COUNT]; + for (int i = 0; i < THREAD_COUNT; ++i) { + threads[i] = new Thread("thread-" + i) { + + public void run() { + startLatch.countDown(); + try { + Connection conn = dataSource.getConnection(); + Thread.sleep(1); + conn.close(); + } catch (Exception e) { + // e.printStackTrace(); + errorCount.incrementAndGet(); + } finally { + endLatch.countDown(); + } + } + }; + threads[i].start(); + } + + startLatch.await(100, TimeUnit.MILLISECONDS); + + final CountDownLatch errorThreadEndLatch = new CountDownLatch(THREAD_COUNT); + final AtomicLong maxWaitErrorCount = new AtomicLong(); + Thread errorThread = new Thread() { + public void run() { + try { + Connection conn = dataSource.getConnection(); + Thread.sleep(1); + conn.close(); + } catch (Exception e) { + maxWaitErrorCount.incrementAndGet(); + } finally { + errorThreadEndLatch.countDown(); + } + } + }; + errorThread.start(); + + errorThreadEndLatch.await(100, TimeUnit.MILLISECONDS); + + Assert.assertEquals(1, maxWaitErrorCount.get()); + + conn.close(); + + endLatch.await(100, TimeUnit.MILLISECONDS); + Assert.assertEquals(0, errorCount.get()); + + } +}