From 8559ab6ce951a579855b560f7650b72f6c99ffa4 Mon Sep 17 00:00:00 2001 From: wenshao Date: Wed, 28 Nov 2012 20:25:57 +0800 Subject: [PATCH] bug fixed for discardConnection --- .../alibaba/druid/pool/DruidDataSource.java | 4 + .../bvt/hibernate/HibernateCRUDTest.java | 14 +- .../alibaba/druid/bvt/pool/DiscardTest.java | 129 ++++++++++++++++++ 3 files changed, 142 insertions(+), 5 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/pool/DiscardTest.java diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index f7830e468f..9de9fa994a 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -710,6 +710,10 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat try { activeCount--; discardCount++; + + if (activeCount <= 0) { + empty.signal(); + } } finally { lock.unlock(); } diff --git a/src/test/java/com/alibaba/druid/bvt/hibernate/HibernateCRUDTest.java b/src/test/java/com/alibaba/druid/bvt/hibernate/HibernateCRUDTest.java index cab0b5c9f5..6872027a9d 100644 --- a/src/test/java/com/alibaba/druid/bvt/hibernate/HibernateCRUDTest.java +++ b/src/test/java/com/alibaba/druid/bvt/hibernate/HibernateCRUDTest.java @@ -1,8 +1,11 @@ package com.alibaba.druid.bvt.hibernate; -import com.alibaba.druid.bvt.hibernate.entity.Sample; -import com.alibaba.druid.pool.DruidDataSource; +import java.io.IOException; +import java.util.Date; +import java.util.Properties; + import junit.framework.TestCase; + import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; @@ -10,9 +13,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.orm.hibernate4.LocalSessionFactoryBean; -import java.io.IOException; -import java.util.Date; -import java.util.Properties; +import com.alibaba.druid.bvt.hibernate.entity.Sample; +import com.alibaba.druid.pool.DruidDataSource; +import com.alibaba.druid.util.JdbcUtils; /** * @author yinheli @@ -59,6 +62,7 @@ public class HibernateCRUDTest extends TestCase { @Override public void tearDown() throws Exception { sessionFactory.close(); + JdbcUtils.close(dataSource); } private void doCreate(Session session) { diff --git a/src/test/java/com/alibaba/druid/bvt/pool/DiscardTest.java b/src/test/java/com/alibaba/druid/bvt/pool/DiscardTest.java new file mode 100644 index 0000000000..0f700c3f84 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/pool/DiscardTest.java @@ -0,0 +1,129 @@ +package com.alibaba.druid.bvt.pool; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Properties; +import java.util.concurrent.CountDownLatch; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.alibaba.druid.mock.MockDriver; +import com.alibaba.druid.mock.MockStatementBase; +import com.alibaba.druid.pool.DruidDataSource; +import com.alibaba.druid.pool.vendor.MySqlExceptionSorter; +import com.alibaba.druid.util.JdbcUtils; + +public class DiscardTest extends TestCase { + + private DruidDataSource dataSource; + + private MockDriver driver; + + private volatile boolean failed = false; + + protected void setUp() throws Exception { + driver = new MockDriver() { + + public ResultSet executeQuery(MockStatementBase stmt, String sql) throws SQLException { + if (failed) { + throw new SQLException("", "", 1040); + } + return super.executeQuery(stmt, sql); + } + + public Connection connect(String url, Properties info) throws SQLException { + while (failed) { + try { + Thread.sleep(1); + } catch (InterruptedException e) { + throw new SQLException(e.getMessage(), e); + } + } + + return super.connect(url, info); + } + }; + + dataSource = new DruidDataSource(); + dataSource.setUrl("jdbc:mock:xxx"); + dataSource.setTestOnBorrow(false); + dataSource.setDriver(driver); + dataSource.setDbType("mysql"); + dataSource.setMinIdle(1); + dataSource.setMaxActive(1); + dataSource.setFilters("log4j"); + dataSource.setExceptionSorter(new MySqlExceptionSorter()); + } + + protected void tearDown() throws Exception { + dataSource.close(); + } + + public void test_db_fail() throws Exception { + exec(); + + final int THREAD_COUNT = 10; + final CountDownLatch endLatch = new CountDownLatch(THREAD_COUNT); + + Thread[] threads = new Thread[THREAD_COUNT]; + + { + Exception error = null; + + Connection conn = dataSource.getConnection(); + Statement stmt = conn.createStatement(); + + for (int i = 0; i < THREAD_COUNT; ++i) { + threads[i] = new Thread() { + + public void run() { + try { + exec(); + } finally { + endLatch.countDown(); + } + } + }; + threads[i].start(); + } + + this.failed = true; + try { + ResultSet rs = stmt.executeQuery("select 1"); + rs.close(); + } catch (SQLException e) { + error = e; + } + + stmt.close(); + conn.close(); + + Assert.assertNotNull(error); + } + + this.failed = false; + + endLatch.await(); + } + + private void exec() { + Connection conn = null; + Statement stmt = null; + ResultSet rs = null; + + try { + conn = dataSource.getConnection(); + stmt = conn.createStatement(); + rs = stmt.executeQuery("select 1"); + } catch (Exception ex) { + ex.printStackTrace(); + } finally { + JdbcUtils.close(rs); + JdbcUtils.close(stmt); + JdbcUtils.close(conn); + } + } +}