examples/tomcat6/apache-tomcat-6.0.35-src/libs/commons-dbcp-1.3-src/src/test/org/apache/commons/dbcp/TestConnectionPool.java
Merged with mercurial revision 4f3cc813be4 (8 changesets total)
Merged changesets:
- f14cd4bbd33f: Jan Vrany, 2015-03-11 11:41 +0000: Zulu support: added Zulu7 and Zulu8 JavaReleases
- f8bc54a17beb: Jan Vrany, 2015-03-11 12:38 +0000: Java release: On UNIX, prefer OpenJDK over Zulu, on Windows, prefer Zulu over Oracle JDK
- 5dd55aa7d949: Jan Vrany, 2015-03-12 14:50 +0000: Zulu support: move natives from OracleJDK7 to OpenJDK7 as they are used by OpenJDK7 on Windows
- 2127b5057d60: Jan Vrany, 2015-03-13 09:40 +0000: testing: improved run-all.rb script to run tests with different configurations.
- a6d8f5c2ad73: Jan Vrany, 2015-03-13 13:33 +0000: Updated .hgignore
- e18d5c89221d: Jan Vrany, 2015-03-13 16:09 +0000: Java release: consult 64bit registry entries as well as 32 bit when searching for installed JDKs
- 183e4567bda7: Jan Vrany, 2015-03-17 20:56 +0000: Java release: added #is32bit & #is64bit testing methods
- 4f3cc813be4b: Jan Vrany, 2015-03-19 17:27 +0000: settings: JavaCodeLibrary validation refactored and improved
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.dbcp;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Hashtable;
import java.util.Stack;
import junit.framework.TestCase;
// XXX FIX ME XXX
// this class still needs some cleanup, but at least
// this consolidates most of the relevant test code
// in a fairly re-usable fashion
// XXX FIX ME XXX
/**
* Base test suite for DBCP pools.
*
* @author Rodney Waldhoff
* @author Sean C. Sullivan
* @author John McNally
* @author Dirk Verbeeck
* @version $Revision: 1.5 $ $Date: 2015-03-20 12:08:10 $
*/
public abstract class TestConnectionPool extends TestCase {
public TestConnectionPool(String testName) {
super(testName);
}
public void tearDown() throws Exception {
super.tearDown();
// Close any connections opened by the test
while (!connections.isEmpty()) {
Connection conn = (Connection) connections.pop();
try {
conn.close();
} catch (Exception ex) {
// ignore
} finally {
conn = null;
}
}
}
protected abstract Connection getConnection() throws Exception;
protected int getMaxActive() {
return 10;
}
protected long getMaxWait() {
return 100L;
}
/** Connections opened during the course of a test */
protected Stack connections = new Stack();
/** Acquire a connection and push it onto the connections stack */
protected Connection newConnection() throws Exception {
Connection connection = getConnection();
connections.push(connection);
return connection;
}
// ----------- Utility Methods ---------------------------------
protected String getUsername(Connection conn) throws SQLException {
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select username");
if (rs.next()) {
return rs.getString(1);
}
return null;
}
// ----------- tests ---------------------------------
public void testClearWarnings() throws Exception {
Connection[] c = new Connection[getMaxActive()];
for (int i = 0; i < c.length; i++) {
c[i] = newConnection();
assertTrue(c[i] != null);
// generate SQLWarning on connection
c[i].prepareCall("warning");
}
for (int i = 0; i < c.length; i++) {
assertNotNull(c[i].getWarnings());
}
for (int i = 0; i < c.length; i++) {
c[i].close();
}
for (int i = 0; i < c.length; i++) {
c[i] = newConnection();
}
for (int i = 0; i < c.length; i++) {
// warnings should have been cleared by putting the connection back in the pool
assertNull(c[i].getWarnings());
}
for (int i = 0; i < c.length; i++) {
c[i].close();
}
}
public void testIsClosed() throws Exception {
for(int i=0;i<getMaxActive();i++) {
Connection conn = newConnection();
assertNotNull(conn);
assertTrue(!conn.isClosed());
PreparedStatement stmt = conn.prepareStatement("select * from dual");
assertNotNull(stmt);
ResultSet rset = stmt.executeQuery();
assertNotNull(rset);
assertTrue(rset.next());
rset.close();
stmt.close();
conn.close();
assertTrue(conn.isClosed());
}
}
/**
* Verify the close method can be called multiple times on a single connection without
* an exception being thrown.
*/
public void testCanCloseConnectionTwice() throws Exception {
for (int i = 0; i < getMaxActive(); i++) { // loop to show we *can* close again once we've borrowed it from the pool again
Connection conn = newConnection();
assertNotNull(conn);
assertTrue(!conn.isClosed());
conn.close();
assertTrue(conn.isClosed());
conn.close();
assertTrue(conn.isClosed());
}
}
public void testCanCloseStatementTwice() throws Exception {
Connection conn = newConnection();
assertNotNull(conn);
assertTrue(!conn.isClosed());
for(int i=0;i<2;i++) { // loop to show we *can* close again once we've borrowed it from the pool again
Statement stmt = conn.createStatement();
assertNotNull(stmt);
assertFalse(isClosed(stmt));
stmt.close();
assertTrue(isClosed(stmt));
stmt.close();
assertTrue(isClosed(stmt));
stmt.close();
assertTrue(isClosed(stmt));
}
conn.close();
}
public void testCanClosePreparedStatementTwice() throws Exception {
Connection conn = newConnection();
assertNotNull(conn);
assertTrue(!conn.isClosed());
for(int i=0;i<2;i++) { // loop to show we *can* close again once we've borrowed it from the pool again
PreparedStatement stmt = conn.prepareStatement("select * from dual");
assertNotNull(stmt);
assertFalse(isClosed(stmt));
stmt.close();
assertTrue(isClosed(stmt));
stmt.close();
assertTrue(isClosed(stmt));
stmt.close();
assertTrue(isClosed(stmt));
}
conn.close();
}
public void testCanCloseCallableStatementTwice() throws Exception {
Connection conn = newConnection();
assertNotNull(conn);
assertTrue(!conn.isClosed());
for(int i=0;i<2;i++) { // loop to show we *can* close again once we've borrowed it from the pool again
PreparedStatement stmt = conn.prepareCall("select * from dual");
assertNotNull(stmt);
assertFalse(isClosed(stmt));
stmt.close();
assertTrue(isClosed(stmt));
stmt.close();
assertTrue(isClosed(stmt));
stmt.close();
assertTrue(isClosed(stmt));
}
conn.close();
}
public void testCanCloseResultSetTwice() throws Exception {
Connection conn = newConnection();
assertNotNull(conn);
assertTrue(!conn.isClosed());
for(int i=0;i<2;i++) { // loop to show we *can* close again once we've borrowed it from the pool again
PreparedStatement stmt = conn.prepareStatement("select * from dual");
assertNotNull(stmt);
ResultSet rset = stmt.executeQuery();
assertNotNull(rset);
assertFalse(isClosed(rset));
rset.close();
assertTrue(isClosed(rset));
rset.close();
assertTrue(isClosed(rset));
rset.close();
assertTrue(isClosed(rset));
}
conn.close();
}
public void testBackPointers() throws Exception {
// normal statement
Connection conn = newConnection();
assertBackPointers(conn, conn.createStatement());
conn = newConnection();
assertBackPointers(conn, conn.createStatement(0, 0));
conn = newConnection();
assertBackPointers(conn, conn.createStatement(0, 0, 0));
// prepared statement
conn = newConnection();
assertBackPointers(conn, conn.prepareStatement("select * from dual"));
conn = newConnection();
assertBackPointers(conn, conn.prepareStatement("select * from dual", 0));
conn = newConnection();
assertBackPointers(conn, conn.prepareStatement("select * from dual", 0, 0));
conn = newConnection();
assertBackPointers(conn, conn.prepareStatement("select * from dual", 0, 0, 0));
conn = newConnection();
assertBackPointers(conn, conn.prepareStatement("select * from dual", new int[0]));
conn = newConnection();
assertBackPointers(conn, conn.prepareStatement("select * from dual", new String[0]));
// callable statement
conn = newConnection();
assertBackPointers(conn, conn.prepareCall("select * from dual"));
conn = newConnection();
assertBackPointers(conn, conn.prepareCall("select * from dual", 0, 0));
conn = newConnection();
assertBackPointers(conn, conn.prepareCall("select * from dual", 0, 0, 0));
}
protected void assertBackPointers(Connection conn, Statement statement) throws SQLException {
assertFalse(conn.isClosed());
assertFalse(isClosed(statement));
assertSame("statement.getConnection() should return the exact same connection instance that was used to create the statement",
conn, statement.getConnection());
ResultSet resultSet = statement.getResultSet();
assertFalse(isClosed(resultSet));
assertSame("resultSet.getStatement() should return the exact same statement instance that was used to create the result set",
statement, resultSet.getStatement());
ResultSet executeResultSet = statement.executeQuery("select * from dual");
assertFalse(isClosed(executeResultSet));
assertSame("resultSet.getStatement() should return the exact same statement instance that was used to create the result set",
statement, executeResultSet.getStatement());
ResultSet keysResultSet = statement.getGeneratedKeys();
assertFalse(isClosed(keysResultSet));
assertSame("resultSet.getStatement() should return the exact same statement instance that was used to create the result set",
statement, keysResultSet.getStatement());
ResultSet preparedResultSet = null;
if (statement instanceof PreparedStatement) {
PreparedStatement preparedStatement = (PreparedStatement) statement;
preparedResultSet = preparedStatement.executeQuery();
assertFalse(isClosed(preparedResultSet));
assertSame("resultSet.getStatement() should return the exact same statement instance that was used to create the result set",
statement, preparedResultSet.getStatement());
}
resultSet.getStatement().getConnection().close();
assertTrue(conn.isClosed());
assertTrue(isClosed(statement));
assertTrue(isClosed(resultSet));
assertTrue(isClosed(executeResultSet));
assertTrue(isClosed(keysResultSet));
if (preparedResultSet != null) {
assertTrue(isClosed(preparedResultSet));
}
}
public void testSimple() throws Exception {
Connection conn = newConnection();
assertNotNull(conn);
PreparedStatement stmt = conn.prepareStatement("select * from dual");
assertNotNull(stmt);
ResultSet rset = stmt.executeQuery();
assertNotNull(rset);
assertTrue(rset.next());
rset.close();
stmt.close();
conn.close();
}
public void testRepeatedBorrowAndReturn() throws Exception {
for(int i=0;i<100;i++) {
Connection conn = newConnection();
assertNotNull(conn);
PreparedStatement stmt = conn.prepareStatement("select * from dual");
assertNotNull(stmt);
ResultSet rset = stmt.executeQuery();
assertNotNull(rset);
assertTrue(rset.next());
rset.close();
stmt.close();
conn.close();
}
}
public void testSimple2() throws Exception {
Connection conn = newConnection();
assertNotNull(conn);
{
PreparedStatement stmt = conn.prepareStatement("select * from dual");
assertNotNull(stmt);
ResultSet rset = stmt.executeQuery();
assertNotNull(rset);
assertTrue(rset.next());
rset.close();
stmt.close();
}
{
PreparedStatement stmt = conn.prepareStatement("select * from dual");
assertNotNull(stmt);
ResultSet rset = stmt.executeQuery();
assertNotNull(rset);
assertTrue(rset.next());
rset.close();
stmt.close();
}
conn.close();
try {
conn.createStatement();
fail("Can't use closed connections");
} catch(SQLException e) {
// expected
}
conn = newConnection();
assertNotNull(conn);
{
PreparedStatement stmt = conn.prepareStatement("select * from dual");
assertNotNull(stmt);
ResultSet rset = stmt.executeQuery();
assertNotNull(rset);
assertTrue(rset.next());
rset.close();
stmt.close();
}
{
PreparedStatement stmt = conn.prepareStatement("select * from dual");
assertNotNull(stmt);
ResultSet rset = stmt.executeQuery();
assertNotNull(rset);
assertTrue(rset.next());
rset.close();
stmt.close();
}
conn.close();
conn = null;
}
public void testPooling() throws Exception {
// Grab a maximal set of open connections from the pool
Connection[] c = new Connection[getMaxActive()];
Connection[] u = new Connection[getMaxActive()];
for (int i = 0; i < c.length; i++) {
c[i] = newConnection();
if (c[i] instanceof DelegatingConnection) {
u[i] = ((DelegatingConnection) c[i]).getInnermostDelegate();
} else {
for (int j = 0; j <= i; j++) {
c[j].close();
}
return; // skip this test
}
}
// Close connections one at a time and get new ones, making sure
// the new ones come from the pool
for (int i = 0; i < c.length; i++) {
c[i].close();
Connection con = newConnection();
Connection underCon =
((DelegatingConnection) con).getInnermostDelegate();
assertTrue("Failed to get connection", underCon != null);
boolean found = false;
for (int j = 0; j < c.length; j++) {
if (underCon == u[j]) {
found = true;
break;
}
}
assertTrue("New connection not from pool", found);
con.close();
}
}
public void testAutoCommitBehavior() throws Exception {
Connection conn = newConnection();
assertNotNull(conn);
assertTrue(conn.getAutoCommit());
conn.setAutoCommit(false);
conn.close();
Connection conn2 = newConnection();
assertTrue( conn2.getAutoCommit() );
Connection conn3 = newConnection();
assertTrue( conn3.getAutoCommit() );
conn2.close();
conn3.close();
}
/** @see "http://issues.apache.org/bugzilla/show_bug.cgi?id=12400" */
public void testConnectionsAreDistinct() throws Exception {
Connection[] conn = new Connection[getMaxActive()];
for(int i=0;i<conn.length;i++) {
conn[i] = newConnection();
for(int j=0;j<i;j++) {
assertTrue(conn[j] != conn[i]);
assertTrue(!conn[j].equals(conn[i]));
}
}
for(int i=0;i<conn.length;i++) {
conn[i].close();
}
}
public void testOpening() throws Exception {
Connection[] c = new Connection[getMaxActive()];
// test that opening new connections is not closing previous
for (int i = 0; i < c.length; i++) {
c[i] = newConnection();
assertTrue(c[i] != null);
for (int j = 0; j <= i; j++) {
assertTrue(!c[j].isClosed());
}
}
for (int i = 0; i < c.length; i++) {
c[i].close();
}
}
public void testClosing() throws Exception {
Connection[] c = new Connection[getMaxActive()];
// open the maximum connections
for (int i = 0; i < c.length; i++) {
c[i] = newConnection();
}
// close one of the connections
c[0].close();
assertTrue(c[0].isClosed());
// get a new connection
c[0] = newConnection();
for (int i = 0; i < c.length; i++) {
c[i].close();
}
}
public void testMaxActive() throws Exception {
Connection[] c = new Connection[getMaxActive()];
for (int i = 0; i < c.length; i++) {
c[i] = newConnection();
assertTrue(c[i] != null);
}
try {
newConnection();
fail("Allowed to open more than DefaultMaxActive connections.");
} catch (java.sql.SQLException e) {
// should only be able to open 10 connections, so this test should
// throw an exception
}
for (int i = 0; i < c.length; i++) {
c[i].close();
}
}
/**
* DBCP-128: BasicDataSource.getConnection()
* Connections don't work as hashtable keys
*/
public void testHashing() throws Exception {
Connection con = getConnection();
Hashtable hash = new Hashtable();
hash.put(con, "test");
assertEquals("test", hash.get(con));
assertTrue(hash.containsKey(con));
assertTrue(hash.contains("test"));
hash.clear();
con.close();
}
public void testThreaded() {
TestThread[] threads = new TestThread[getMaxActive()];
for(int i=0;i<threads.length;i++) {
threads[i] = new TestThread(50,50);
Thread t = new Thread(threads[i]);
t.start();
}
for(int i=0;i<threads.length;i++) {
while(!(threads[i]).complete()) {
try {
Thread.sleep(100L);
} catch(Exception e) {
// ignored
}
}
if(threads[i].failed()) {
fail();
}
}
}
class TestThread implements Runnable {
java.util.Random _random = new java.util.Random();
boolean _complete = false;
boolean _failed = false;
int _iter = 100;
int _delay = 50;
public TestThread() {
}
public TestThread(int iter) {
_iter = iter;
}
public TestThread(int iter, int delay) {
_iter = iter;
_delay = delay;
}
public boolean complete() {
return _complete;
}
public boolean failed() {
return _failed;
}
public void run() {
for(int i=0;i<_iter;i++) {
try {
Thread.sleep(_random.nextInt(_delay));
} catch(Exception e) {
// ignored
}
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rset = null;
try {
conn = newConnection();
stmt = conn.prepareStatement("select 'literal', SYSDATE from dual");
rset = stmt.executeQuery();
try {
Thread.sleep(_random.nextInt(_delay));
} catch(Exception e) {
// ignored
}
} catch(Exception e) {
e.printStackTrace();
_failed = true;
_complete = true;
break;
} finally {
try { if (rset != null) rset.close(); } catch(Exception e) { }
try { if (stmt != null) stmt.close(); } catch(Exception e) { }
try { if (conn != null) conn.close(); } catch(Exception e) { }
}
}
_complete = true;
}
}
// Bugzilla Bug 24328: PooledConnectionImpl ignores resultsetType
// and Concurrency if statement pooling is not enabled
// http://issues.apache.org/bugzilla/show_bug.cgi?id=24328
public void testPrepareStatementOptions() throws Exception
{
Connection conn = newConnection();
assertNotNull(conn);
PreparedStatement stmt = conn.prepareStatement("select * from dual",
ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
assertNotNull(stmt);
ResultSet rset = stmt.executeQuery();
assertNotNull(rset);
assertTrue(rset.next());
assertEquals(ResultSet.TYPE_SCROLL_SENSITIVE, rset.getType());
assertEquals(ResultSet.CONCUR_UPDATABLE, rset.getConcurrency());
rset.close();
stmt.close();
conn.close();
}
// Bugzilla Bug 24966: NullPointer with Oracle 9 driver
// wrong order of passivate/close when a rset isn't closed
public void testNoRsetClose() throws Exception {
Connection conn = newConnection();
assertNotNull(conn);
PreparedStatement stmt = conn.prepareStatement("test");
assertNotNull(stmt);
ResultSet rset = stmt.getResultSet();
assertNotNull(rset);
// forget to close the resultset: rset.close();
stmt.close();
conn.close();
}
// Bugzilla Bug 26966: Connectionpool's connections always returns same
public void testHashCode() throws Exception {
Connection conn1 = newConnection();
assertNotNull(conn1);
Connection conn2 = newConnection();
assertNotNull(conn2);
assertTrue(conn1.hashCode() != conn2.hashCode());
}
protected boolean isClosed(Statement statement) {
try {
statement.getWarnings();
return false;
} catch (SQLException e) {
// getWarnings throws an exception if the statement is
// closed, but could throw an exception for other reasons
// in this case it is good enought to assume the statement
// is closed
return true;
}
}
protected boolean isClosed(ResultSet resultSet) {
try {
resultSet.getWarnings();
return false;
} catch (SQLException e) {
// getWarnings throws an exception if the statement is
// closed, but could throw an exception for other reasons
// in this case it is good enought to assume the result set
// is closed
return true;
}
}
private static final boolean DISPLAY_THREAD_DETAILS=
Boolean.valueOf(System.getProperty("TestConnectionPool.display.thread.details", "false")).booleanValue();
// To pass this to a Maven test, use:
// mvn test -DargLine="-DTestConnectionPool.display.thread.details=true"
// @see http://jira.codehaus.org/browse/SUREFIRE-121
/**
* Launches a group of 2 * getMaxActive() threads, each of which will attempt to obtain a connection
* from the pool, hold it for <holdTime> ms, and then return it to the pool. If <loopOnce> is false,
* threads will continue this process indefinitely. If <expectError> is true, exactly 1/2 of the
* threads are expected to either throw exceptions or fail to complete. If <expectError> is false,
* all threads are expected to complete successfully.
*
* @param holdTime time in ms that a thread holds a connection before returning it to the pool
* @param expectError whether or not an error is expected
* @param loopOnce whether threads should complete the borrow - hold - return cycle only once, or loop indefinitely
* @param maxWait passed in by client - has no impact on the test itself, but does get reported
*
* @throws Exception
*/
protected void multipleThreads(final int holdTime, final boolean expectError, final boolean loopOnce, final long maxWait)
throws Exception {
long startTime = timeStamp();
final PoolTest[] pts = new PoolTest[2 * getMaxActive()];
// Catch Exception so we can stop all threads if one fails
ThreadGroup threadGroup = new ThreadGroup("foo") {
public void uncaughtException(Thread t, Throwable e) {
for (int i = 0; i < pts.length; i++) {
pts[i].stop();
}
}
};
// Create all the threads
for (int i = 0; i < pts.length; i++) {
pts[i] = new PoolTest(threadGroup, holdTime, expectError, loopOnce);
}
// Start all the threads
for (int i = 0; i < pts.length; i++) {
pts[i].start();
}
// Give all threads a chance to start and succeed
Thread.sleep(300L);
// Stop threads
for (int i = 0; i < pts.length; i++) {
pts[i].stop();
}
/*
* Wait for all threads to terminate.
* This is essential to ensure that all threads have a chance to update success[0]
* and to ensure that the variable is published correctly.
*/
int done=0;
int failed=0;
int didNotRun = 0;
int loops=0;
for (int i = 0; i < pts.length; i++) {
final PoolTest poolTest = pts[i];
poolTest.thread.join();
loops += poolTest.loops;
final String state = poolTest.state;
if (DONE.equals(state)){
done++;
}
if (poolTest.loops == 0){
didNotRun++;
}
final Throwable thrown = poolTest.thrown;
if (thrown != null) {
failed++;
if (!expectError || !(thrown instanceof SQLException)){
System.out.println("Unexpected error: "+thrown.getMessage());
}
}
}
long time = timeStamp() - startTime;
System.out.println("Multithread test time = " + time
+ " ms. Threads: " + pts.length
+ ". Loops: " + loops
+ ". Hold time: " + holdTime
+ ". Maxwait: " + maxWait
+ ". Done: " + done
+ ". Did not run: " + didNotRun
+ ". Failed: " + failed
+ ". expectError: " + expectError
);
if (expectError) {
if (DISPLAY_THREAD_DETAILS || (pts.length/2 != failed)){
long offset = pts[0].created - 1000; // To reduce size of output numbers, but ensure they have 4 digits
System.out.println("Offset: "+offset);
for (int i = 0; i < pts.length; i++) {
PoolTest pt = pts[i];
System.out.println(
"Pre: " + (pt.preconnected-offset) // First, so can sort on this easily
+ ". Post: " + (pt.postconnected != 0 ? Long.toString(pt.postconnected-offset): "-")
+ ". Hash: " + pt.connHash
+ ". Startup: " + (pt.started-pt.created)
+ ". getConn(): " + (pt.connected != 0 ? Long.toString(pt.connected-pt.preconnected) : "-")
+ ". Runtime: " + (pt.ended-pt.started)
+ ". IDX: " + i
+ ". Loops: " + pt.loops
+ ". State: " + pt.state
+ ". thrown: "+ pt.thrown
+ "."
);
}
}
if (didNotRun > 0){
System.out.println("NOTE: some threads did not run the code: "+didNotRun);
}
// Perform initial sanity check:
assertTrue("Expected some of the threads to fail",failed > 0);
// Assume that threads that did not run would have timed out.
assertEquals("WARNING: Expected half the threads to fail",pts.length/2,failed+didNotRun);
} else {
assertEquals("Did not expect any threads to fail",0,failed);
}
}
private static int currentThreadCount = 0;
private static final String DONE = "Done";
protected class PoolTest implements Runnable {
/**
* The number of milliseconds to hold onto a database connection
*/
private final int connHoldTime;
private volatile boolean isRun;
private String state; // No need to be volatile if it is read after the thread finishes
private final Thread thread;
private Throwable thrown;
// Debug for DBCP-318
private final long created; // When object was created
private long started; // when thread started
private long ended; // when thread ended
private long preconnected; // just before connect
private long connected; // when thread last connected
private long postconnected; // when thread released connection
private int loops = 0;
private int connHash = 0; // Connection identity hashCode (to see which one is reused)
private final boolean stopOnException; // If true, don't rethrow Exception
private final boolean loopOnce; // If true, don't repeat loop
public PoolTest(ThreadGroup threadGroup, int connHoldTime, boolean isStopOnException) {
this(threadGroup, connHoldTime, isStopOnException, false);
}
private PoolTest(ThreadGroup threadGroup, int connHoldTime, boolean isStopOnException, boolean once) {
this.loopOnce = once;
this.connHoldTime = connHoldTime;
stopOnException = isStopOnException;
isRun = true; // Must be done here so main thread is guaranteed to be able to set it false
thrown = null;
thread =
new Thread(threadGroup, this, "Thread+" + currentThreadCount++);
thread.setDaemon(false);
created = timeStamp();
}
public void start(){
thread.start();
}
public void run() {
started = timeStamp();
try {
while (isRun) {
loops++;
state = "Getting Connection";
preconnected = timeStamp();
Connection conn = getConnection();
connHash = System.identityHashCode(((DelegatingConnection)conn).getInnermostDelegate());
connected = timeStamp();
state = "Using Connection";
assertNotNull(conn);
PreparedStatement stmt =
conn.prepareStatement("select * from dual");
assertNotNull(stmt);
ResultSet rset = stmt.executeQuery();
assertNotNull(rset);
assertTrue(rset.next());
state = "Holding Connection";
Thread.sleep(connHoldTime);
state = "Closing ResultSet";
rset.close();
state = "Closing Statement";
stmt.close();
state = "Closing Connection";
conn.close();
postconnected = timeStamp();
state = "Closed";
if (loopOnce){
break; // Or could set isRun=false
}
}
state = DONE;
} catch (Throwable t) {
thrown = t;
if (!stopOnException) {
throw new RuntimeException();
}
} finally {
ended = timeStamp();
}
}
public void stop() {
isRun = false;
}
public Thread getThread() {
return thread;
}
}
long timeStamp() {
return System.currentTimeMillis();// JVM 1.5+ System.nanoTime() / 1000000;
}
}