/**
* All the information about the connection pool
*/
- protected PoolProperties poolProperties;
+ private PoolProperties poolProperties;
/**
* Contains all the connections that are in use
* TODO - this shouldn't be a blocking queue, simply a list to hold our objects
*/
- protected BlockingQueue<PooledConnection> busy;
+ private BlockingQueue<PooledConnection> busy;
/**
* Contains all the idle connections
*/
- protected BlockingQueue<PooledConnection> idle;
+ private BlockingQueue<PooledConnection> idle;
/**
* The thread that is responsible for checking abandoned and idle threads
*/
- protected PoolCleaner poolCleaner;
+ private PoolCleaner poolCleaner;
/**
* Pool closed flag
*/
- protected boolean closed = false;
+ private boolean closed = false;
/**
* Since newProxyInstance performs the same operation, over and over
* again, it is much more optimized if we simply store the constructor ourselves.
*/
- protected Constructor proxyClassConstructor;
+ private Constructor proxyClassConstructor;
/**
* Executor service used to cancel Futures
*/
- protected ThreadPoolExecutor cancellator = new ThreadPoolExecutor(0,1,1000,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
+ private ThreadPoolExecutor cancellator = new ThreadPoolExecutor(0,1,1000,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
/**
* reference to mbean
/**
* counter to track how many threads are waiting for a connection
*/
- protected AtomicInteger waitcount = new AtomicInteger(0);
+ private AtomicInteger waitcount = new AtomicInteger(0);
//===============================================================================
// PUBLIC METHODS
return;
try {
con.lock();
- con.release();
+ if (con.release()) {
+ size.addAndGet(-1);
+ }
} finally {
- size.addAndGet(-1);
+
con.unlock();
}
}
* @return PooledConnection
* @throws SQLException
*/
- protected PooledConnection borrowConnection(int wait) throws SQLException {
+ private PooledConnection borrowConnection(int wait) throws SQLException {
if (isClosed()) {
throw new SQLException("Connection pool closed.");
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
/**
*/
private WeakReference<JdbcInterceptor> handler = null;
+ private AtomicBoolean released = new AtomicBoolean(false);
+
public PooledConnection(PoolProperties prop, ConnectionPool parent) {
instanceCount = counter.addAndGet(1);
}
public void connect() throws SQLException {
+ if (released.get()) throw new SQLException("A connection once released, can't be reestablished.");
if (connection != null) {
try {
this.disconnect(false);
/**
* This method is called if (Now - timeCheckedIn > getReleaseTime())
*/
- public void release() {
+ public boolean release() {
try {
disconnect(true);
} catch (Exception x) {
log.debug("Unable to close SQL connection",x);
}
}
+ return released.compareAndSet(false, true);
}
public class DefaultTestCase extends TestCase {
protected org.apache.tomcat.jdbc.pool.DataSource datasource;
protected BasicDataSource tDatasource;
- protected DataSource c3p0Datasource;
+ protected ComboPooledDataSource c3p0Datasource;
protected int threadcount = 10;
protected int iterations = 100000;
public DefaultTestCase(String name) {
protected long complete = Long.getLong("complete",20000);
protected boolean printthread = Boolean.getBoolean("printthread");
CountDownLatch latch = null;
- protected void printThreadResults(TestThread[] threads, String name) {
+ protected void printThreadResults(TestThread[] threads, String name, int active, int expected) {
long minfetch = Long.MAX_VALUE, maxfetch = Long.MIN_VALUE, totalfetch = 0;
long maxwait = 0, minwait = Long.MAX_VALUE, averagewait = 0, totalwait = 0;
float avgfetch = 0;
System.out.println("["+name+"] Max fetch:"+(maxfetch)+" Min fetch:"+(minfetch)+" Average fetch:"+
(((float)totalfetch))/(float)threads.length);
System.out.println("["+name+"] Max wait:"+(((float)maxwait)/1000000f)+"ms. Min wait:"+(((float)minwait)/1000000f)+"ms. Average wait:"+(((((float)totalwait))/(float)totalfetch)/1000000f)+" ms.");
+ System.out.println("["+name+"] Max active:"+active+" Expected Active:"+expected);
}
}
this.run = false;
long delta = System.currentTimeMillis() - start;
- printThreadResults(threads,"testDBCPThreads20Connections10");
+ printThreadResults(threads,"testDBCPThreads20Connections10",this.tDatasource.getNumActive(),10);
tearDown();
}
}
this.run = false;
long delta = System.currentTimeMillis() - start;
- printThreadResults(threads,"testPoolThreads20Connections10");
+ printThreadResults(threads,"testPoolThreads20Connections10",this.datasource.getSize(),10);
tearDown();
}
}
this.run = false;
long delta = System.currentTimeMillis() - start;
- printThreadResults(threads,"testPoolThreads20Connections10Fair");
+ printThreadResults(threads,"testPoolThreads20Connections10Fair",this.datasource.getSize(),10);
tearDown();
}
}
this.run = false;
long delta = System.currentTimeMillis() - start;
- printThreadResults(threads,"testPoolThreads20Connections10FairAsync");
+ printThreadResults(threads,"testPoolThreads20Connections10FairAsync",this.datasource.getSize(),10);
tearDown();
}
}
this.run = false;
long delta = System.currentTimeMillis() - start;
- printThreadResults(threads,"testC3P0Threads20Connections10");
+ printThreadResults(threads,"testC3P0Threads20Connections10",c3p0Datasource.getNumConnectionsAllUsers(),10);
tearDown();
}