diff --git a/src/main/java/com/alibaba/druid/pool/ConnectionHolder.java b/src/main/java/com/alibaba/druid/pool/ConnectionHolder.java index b44a4ab851..2c9246b4e2 100644 --- a/src/main/java/com/alibaba/druid/pool/ConnectionHolder.java +++ b/src/main/java/com/alibaba/druid/pool/ConnectionHolder.java @@ -43,7 +43,7 @@ public final class ConnectionHolder { private final List statementTrace = new ArrayList(); - public ConnectionHolder(DruidDataSource dataSource, Connection conn){ + public ConnectionHolder(DruidAbstractDataSource dataSource, Connection conn){ this.dataSource = dataSource; this.conn = conn; this.poolPreparedStatements = dataSource.isPoolPreparedStatements(); diff --git a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java index e7d18d41d1..a445f3a89f 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java @@ -44,7 +44,7 @@ import com.alibaba.druid.util.DruidLoaderUtils; /** * @author wenshao */ -public abstract class DruidAbstractDataSource implements DataSource, DataSourceProxy, Serializable { +public abstract class DruidAbstractDataSource implements DruidAbstractDataSourceMBean, DataSource, DataSourceProxy, Serializable { private static final long serialVersionUID = 1L; diff --git a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSourceMBean.java b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSourceMBean.java new file mode 100644 index 0000000000..320e2db38e --- /dev/null +++ b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSourceMBean.java @@ -0,0 +1,86 @@ +package com.alibaba.druid.pool; + +import java.util.List; + +public interface DruidAbstractDataSourceMBean { + + String getDbType(); + + String getName(); + + int getInitialSize(); + + String getUsername(); + + String getPassword(); + + String getUrl(); + + String getDriverClassName(); + + long getConnectCount(); + + long getCloseCount(); + + long getConnectErrorCount(); + + int getPoolingCount(); + + long getRecycleCount(); + + int getActiveCount(); + + long getCreateCount(); + + long getDestroyCount(); + + long getCreateTimespanMillis(); + + int getQueryTimeout(); + + String getValidationQuery(); + + int getValidationQueryTimeout(); + + int getMaxWaitThreadCount(); + + long getTimeBetweenEvictionRunsMillis(); + + long getMinEvictableIdleTimeMillis(); + + boolean isActiveConnectionTraceEnable(); + + void setActiveConnectionTraceEnable(boolean connectStackTraceEnable); + + List getActiveConnectionStackTrace(); + + List getFilterClassNames(); + + boolean isTestOnBorrow(); + + boolean isTestOnReturn(); + + boolean isDefaultAutoCommit(); + + Boolean getDefaultReadOnly(); + + Integer getDefaultTransactionIsolation(); + + String getDefaultCatalog(); + + boolean isPoolPreparedStatements(); + + long getMaxWait(); + + int getMinIdle(); + + int getMaxIdle(); + + long getCreateErrorCount(); + + int getMaxActive(); + + long getTimeBetweenConnectErrorMillis(); + + int getMaxOpenPreparedStatements(); +} diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource2.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource2.java index f17ac20d57..4436f2c242 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource2.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource2.java @@ -1,35 +1,242 @@ package com.alibaba.druid.pool; import java.sql.Connection; +import java.sql.Driver; import java.sql.SQLException; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.locks.ReentrantLock; + +import com.alibaba.druid.filter.Filter; +import com.alibaba.druid.util.JdbcUtils; +import com.alibaba.druid.util.LinkedTransferQueue; +import com.alibaba.druid.util.TransferQueue; public class DruidDataSource2 extends DruidAbstractDataSource { - private static final long serialVersionUID = 1L; + private final ReentrantLock lock = new ReentrantLock(); + private final TransferQueue connections = new LinkedTransferQueue(); + + private static final long serialVersionUID = 1L; + + private final CountDownLatch initedLatch = new CountDownLatch(1); + private CreateConnectionThread createConnectionThread; @Override public Connection getConnection() throws SQLException { - // TODO Auto-generated method stub + init(); + return null; } + private void init() throws SQLException { + if (inited) { + return; + } + + try { + lock.lockInterruptibly(); + + if (inited) { + return; + } + + if (maxActive <= 0) { + throw new IllegalArgumentException("illegal maxActive " + maxActive); + } + + if (maxIdle <= 0 || maxIdle < minIdle) { + throw new IllegalArgumentException("illegal maxPoolSize"); + } + + if (this.driverClass != null) { + this.driverClass = driverClass.trim(); + } + + if (this.jdbcUrl != null) { + this.jdbcUrl = this.jdbcUrl.trim(); + } + + if (this.driver == null) { + if (this.driverClass == null || this.driverClass.isEmpty()) { + this.driverClass = JdbcUtils.getDriverClassName(this.jdbcUrl); + } + + try { + driver = (Driver) Class.forName(this.driverClass).newInstance(); + } catch (IllegalAccessException e) { + throw new SQLException(e.getMessage(), e); + } catch (InstantiationException e) { + throw new SQLException(e.getMessage(), e); + } catch (ClassNotFoundException e) { + throw new SQLException(e.getMessage(), e); + } + } else { + if (this.driverClass == null) { + this.driverClass = driver.getClass().getName(); + } + } + + this.dbType = JdbcUtils.getDbType(jdbcUrl, driverClass.getClass().getName()); + + for (Filter filter : filters) { + filter.init(this); + } + + initConnectionFactory(); + + int capacity = maxIdle + maxActive; + + if (capacity < getInitialSize()) { + capacity = getInitialSize(); + } + + // pool = new ConnectionPool(this, this.minIdle, this.maxIdle, + // this.maxActive, this.maxIdleTimeMillis); + + for (int i = 0, size = getInitialSize(); i < size; ++i) { + Connection conn = connectionFactory.createConnection(); + conn.setAutoCommit(true); + connections.add(new ConnectionHolder(this, conn)); + } + + createConnectionThread = new CreateConnectionThread("Druid-ConnectionPool-Create"); + + createConnectionThread.start(); + + initedLatch.await(); + inited = true; + + } catch (InterruptedException e) { + throw new SQLException(e.getMessage(), e); + } finally { + lock.unlock(); + } + } + @Override public Connection getConnection(String username, String password) throws SQLException { - // TODO Auto-generated method stub return null; } @Override void incrementCreateCount() { + + } + + @Override + protected void recycle(PoolableConnection pooledConnection) throws SQLException { + } + + public class CreateConnectionThread extends Thread { + + public CreateConnectionThread(String name){ + super(name); + } + + public void run() { + initedLatch.countDown(); + + for (;;) { + // addLast + lock.lock(); + try { + Connection connection = connectionFactory.createConnection(); + ConnectionHolder poolableConnection = new ConnectionHolder(DruidDataSource2.this, connection); + connections.transfer(poolableConnection); + } catch (InterruptedException e) { + break; + } catch (SQLException e) { + printStackTrace(e); + + if (timeBetweenConnectErrorMillis > 0) { + try { + Thread.sleep(timeBetweenConnectErrorMillis); + } catch (InterruptedException e1) { + break; + } + } + } catch (RuntimeException e) { + printStackTrace(e); + } catch (Error e) { + printStackTrace(e); + break; + } finally { + lock.unlock(); + } + } + } + } + + @Override + public long getConnectCount() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public long getCloseCount() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public long getConnectErrorCount() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public int getPoolingCount() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public long getRecycleCount() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public int getActiveCount() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public long getCreateCount() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public long getDestroyCount() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public boolean isActiveConnectionTraceEnable() { + // TODO Auto-generated method stub + return false; + } + + @Override + public void setActiveConnectionTraceEnable(boolean connectStackTraceEnable) { // TODO Auto-generated method stub } @Override - protected void recycle(PoolableConnection pooledConnection) throws SQLException { + public List getActiveConnectionStackTrace() { // TODO Auto-generated method stub - + return null; } - + @Override + public List getFilterClassNames() { + // TODO Auto-generated method stub + return null; + } } diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSourceMBean.java b/src/main/java/com/alibaba/druid/pool/DruidDataSourceMBean.java index ea3d7f2f75..fe0d272e4a 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSourceMBean.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSourceMBean.java @@ -15,60 +15,10 @@ */ package com.alibaba.druid.pool; -import java.util.List; /** * @author wenshao */ -public interface DruidDataSourceMBean { - - String getName(); +public interface DruidDataSourceMBean extends DruidAbstractDataSourceMBean { - int getInitialSize(); - - String getUsername(); - - String getPassword(); - - String getUrl(); - - String getDriverClassName(); - - long getConnectCount(); - - long getCloseCount(); - - long getConnectErrorCount(); - - int getPoolingCount(); - - long getRecycleCount(); - - int getActiveCount(); - - long getCreateCount(); - - long getDestroyCount(); - - long getCreateTimespanMillis(); - - int getQueryTimeout(); - - String getValidationQuery(); - - int getValidationQueryTimeout(); - - int getMaxWaitThreadCount(); - - long getTimeBetweenEvictionRunsMillis(); - - long getMinEvictableIdleTimeMillis(); - - boolean isActiveConnectionTraceEnable(); - - void setActiveConnectionTraceEnable(boolean connectStackTraceEnable); - - List getActiveConnectionStackTrace(); - - List getFilterClassNames(); } diff --git a/src/main/java/com/alibaba/druid/util/LinkedTransferQueue.java b/src/main/java/com/alibaba/druid/util/LinkedTransferQueue.java index 709e68e29a..4c10809e5d 100644 --- a/src/main/java/com/alibaba/druid/util/LinkedTransferQueue.java +++ b/src/main/java/com/alibaba/druid/util/LinkedTransferQueue.java @@ -1352,24 +1352,24 @@ public class LinkedTransferQueue extends AbstractQueue } } - static sun.misc.Unsafe getUnsafe() { +static sun.misc.Unsafe getUnsafe() { + try { + return sun.misc.Unsafe.getUnsafe(); + } catch (SecurityException se) { try { - return sun.misc.Unsafe.getUnsafe(); - } catch (SecurityException se) { - try { - return java.security.AccessController.doPrivileged - (new java.security - .PrivilegedExceptionAction() { - public sun.misc.Unsafe run() throws Exception { - java.lang.reflect.Field f = sun.misc - .Unsafe.class.getDeclaredField("theUnsafe"); - f.setAccessible(true); - return (sun.misc.Unsafe) f.get(null); - }}); - } catch (java.security.PrivilegedActionException e) { - throw new RuntimeException("Could not initialize intrinsics", - e.getCause()); - } + return java.security.AccessController.doPrivileged + (new java.security + .PrivilegedExceptionAction() { + public sun.misc.Unsafe run() throws Exception { + java.lang.reflect.Field f = sun.misc + .Unsafe.class.getDeclaredField("theUnsafe"); + f.setAccessible(true); + return (sun.misc.Unsafe) f.get(null); + }}); + } catch (java.security.PrivilegedActionException e) { + throw new RuntimeException("Could not initialize intrinsics", + e.getCause()); } } } +} diff --git a/src/test/java/com/alibaba/druid/TestLinkedTransferQueue.java b/src/test/java/com/alibaba/druid/TestLinkedTransferQueue.java index 2d1988f85a..05976b9fbc 100644 --- a/src/test/java/com/alibaba/druid/TestLinkedTransferQueue.java +++ b/src/test/java/com/alibaba/druid/TestLinkedTransferQueue.java @@ -1,5 +1,8 @@ package com.alibaba.druid; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + import junit.framework.TestCase; import com.alibaba.druid.util.LinkedTransferQueue; @@ -7,6 +10,10 @@ import com.alibaba.druid.util.LinkedTransferQueue; public class TestLinkedTransferQueue extends TestCase { public void test_0() throws Exception { + final Lock lock = new ReentrantLock(); + + lock.lock(); + final LinkedTransferQueue q = new LinkedTransferQueue(); Thread takeThread = new Thread("Take Thread") { @@ -24,6 +31,11 @@ public class TestLinkedTransferQueue extends TestCase { takeThread.start(); // q.take(); + for (int i = 0; i < 10; ++i) { + Object value = i; + q.transfer(value); + } + q.put(1); q.put(2); System.out.println(q.size()); diff --git a/src/test/java/com/alibaba/druid/pool/benckmark/Case1.java b/src/test/java/com/alibaba/druid/pool/benckmark/Case1.java index a5bc3113e1..13ead18473 100644 --- a/src/test/java/com/alibaba/druid/pool/benckmark/Case1.java +++ b/src/test/java/com/alibaba/druid/pool/benckmark/Case1.java @@ -45,9 +45,9 @@ public class Case1 extends TestCase { private int maxPoolSize = 50; private int maxActive = 50; private String validationQuery = "SELECT 1"; - private int threadCount = 10; + private int threadCount = 40; private int loopCount = 4; - final int LOOP_COUNT = 1000 * 100; + final int LOOP_COUNT = 1000 * 10; protected void setUp() throws Exception { jdbcUrl = "jdbc:fake:dragoon_v25masterdb"; @@ -78,7 +78,7 @@ public class Case1 extends TestCase { System.out.println(); } - public void test_1() throws Exception { + public void ftest_1() throws Exception { final BasicDataSource dataSource = new BasicDataSource(); dataSource.setInitialSize(initialSize);