Index: src/java/org/apache/commons/dbcp/cpdsadapter/DriverAdapterCPDS.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/dbcp/src/java/org/apache/commons/dbcp/cpdsadapter/DriverAdapterCPDS.java,v retrieving revision 1.8 diff -u -r1.8 DriverAdapterCPDS.java --- src/java/org/apache/commons/dbcp/cpdsadapter/DriverAdapterCPDS.java 28 Feb 2004 12:18:17 -0000 1.8 +++ src/java/org/apache/commons/dbcp/cpdsadapter/DriverAdapterCPDS.java 29 Feb 2004 00:26:10 -0000 @@ -113,6 +113,7 @@ private int _timeBetweenEvictionRunsMillis = -1; private int _numTestsPerEvictionRun = -1; private int _minEvictableIdleTimeMillis = -1; + private int _maxPreparedStatements = -1; private boolean getConnectionCalled = false; @@ -147,13 +148,28 @@ */ KeyedObjectPool stmtPool = null; if (isPoolPreparedStatements()) { - stmtPool = new GenericKeyedObjectPool(null, - getMaxActive(), GenericKeyedObjectPool.WHEN_EXHAUSTED_GROW, 0, - getMaxIdle(), false, false, getTimeBetweenEvictionRunsMillis(), - getNumTestsPerEvictionRun(), - getMinEvictableIdleTimeMillis(), false); + if (getMaxPreparedStatements() == -1) + { + // since there is no limit, create a prepared statement pool with an eviction thread + // evictor settings are the same as the connection pool settings. + stmtPool = new GenericKeyedObjectPool(null, + getMaxActive(), GenericKeyedObjectPool.WHEN_EXHAUSTED_GROW, 0, + getMaxIdle(), false, false, + getTimeBetweenEvictionRunsMillis(),getNumTestsPerEvictionRun(),getMinEvictableIdleTimeMillis(), + false); + } + else + { + // since there is limit, create a prepared statement pool without an eviction thread + // pool has LRU functionality so when the limit is reached, 15% of the pool is cleared. + // see org.apache.commons.pool.impl.GenericKeyedObjectPool.clearOldest method + stmtPool = new GenericKeyedObjectPool(null, + getMaxActive(), GenericKeyedObjectPool.WHEN_EXHAUSTED_GROW, 0, + getMaxIdle(), getMaxPreparedStatements(), false, false, + -1,0,0, // -1 tells the pool that there should be no eviction thread. + false); + } } - // Workaround for buggy WebLogic 5.1 classloader - ignore the // exception upon first invocation. try { @@ -201,6 +217,8 @@ String.valueOf(getNumTestsPerEvictionRun()))); ref.add(new StringRefAddr("minEvictableIdleTimeMillis", String.valueOf(getMinEvictableIdleTimeMillis()))); + ref.add(new StringRefAddr("maxPreparedStatements", + String.valueOf(getMaxPreparedStatements()))); return ref; } @@ -275,6 +293,11 @@ setMinEvictableIdleTimeMillis( Integer.parseInt(ra.getContent().toString())); } + ra = ref.get("maxPreparedStatements"); + if (ra != null && ra.getContent() != null) { + setMaxPreparedStatements( + Integer.parseInt(ra.getContent().toString())); + } cpds = this; } @@ -552,5 +575,14 @@ public void setMinEvictableIdleTimeMillis(int minEvictableIdleTimeMillis) { assertInitializationAllowed(); _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; + } + public int getMaxPreparedStatements() + { + return _maxPreparedStatements; + } + + public void setMaxPreparedStatements(int maxPreparedStatements) + { + _maxPreparedStatements = maxPreparedStatements; } } Index: src/test/org/apache/commons/dbcp/datasources/TestSharedPoolDataSource.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/dbcp/src/test/org/apache/commons/dbcp/datasources/TestSharedPoolDataSource.java,v retrieving revision 1.7 diff -u -r1.7 TestSharedPoolDataSource.java --- src/test/org/apache/commons/dbcp/datasources/TestSharedPoolDataSource.java 28 Feb 2004 11:47:52 -0000 1.7 +++ src/test/org/apache/commons/dbcp/datasources/TestSharedPoolDataSource.java 29 Feb 2004 00:26:55 -0000 @@ -412,7 +412,6 @@ conn3.close(); } - // Bugzilla Bug 24136 ClassCastException in DriverAdapterCPDS // when setPoolPreparedStatements(true) public void testPoolPrepareStatement() throws Exception @@ -429,5 +428,80 @@ rset.close(); stmt.close(); conn.close(); + } + + public void testPoolPreparedStatements() throws Exception { + DriverAdapterCPDS mypcds = new DriverAdapterCPDS(); + DataSource myds = null; + mypcds.setDriver("org.apache.commons.dbcp.TesterDriver"); + mypcds.setUrl("jdbc:apache:commons:testdriver"); + mypcds.setUser("foo"); + mypcds.setPassword("bar"); + mypcds.setPoolPreparedStatements(true); + mypcds.setMaxPreparedStatements(10); + + SharedPoolDataSource tds = new SharedPoolDataSource(); + tds.setConnectionPoolDataSource(mypcds); + tds.setMaxActive(getMaxActive()); + tds.setMaxWait((int)(getMaxWait())); + tds.setDefaultTransactionIsolation( + Connection.TRANSACTION_READ_COMMITTED); + + myds = tds; + + Connection conn = ds.getConnection(); + PreparedStatement stmt = null; + ResultSet rset = null; + + assertTrue(null != conn); + + stmt = conn.prepareStatement("select * from dual"); + assertTrue(null != stmt); + long l1HashCode = stmt.hashCode(); + rset = stmt.executeQuery(); + assertTrue(null != rset); + assertTrue(rset.next()); + rset.close(); + stmt.close(); + + stmt = conn.prepareStatement("select * from dual"); + assertTrue(null != stmt); + long l2HashCode = stmt.hashCode(); + rset = stmt.executeQuery(); + assertTrue(null != rset); + assertTrue(rset.next()); + rset.close(); + stmt.close(); + + // statement pooling is not enabled, we should get different statements + assertTrue(l1HashCode != l2HashCode); + conn.close(); + conn = null; + + conn = myds.getConnection(); + + stmt = conn.prepareStatement("select * from dual"); + assertTrue(null != stmt); + long l3HashCode = stmt.hashCode(); + rset = stmt.executeQuery(); + assertTrue(null != rset); + assertTrue(rset.next()); + rset.close(); + stmt.close(); + + stmt = conn.prepareStatement("select * from dual"); + assertTrue(null != stmt); + long l4HashCode = stmt.hashCode(); + rset = stmt.executeQuery(); + assertTrue(null != rset); + assertTrue(rset.next()); + rset.close(); + stmt.close(); + + // prepared statement pooling is working + assertTrue(l3HashCode == l4HashCode); + conn.close(); + conn = null; + } }