/* * JBoss, Home of Professional Open Source. * Copyright 2008, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.test.jca.test; import javax.resource.ResourceException; import javax.resource.spi.ConnectionRequestInfo; import javax.resource.spi.ManagedConnectionFactory; import javax.security.auth.Subject; import org.jboss.logging.Logger; import org.jboss.resource.connectionmanager.BaseConnectionManager2; import org.jboss.resource.connectionmanager.CachedConnectionManager; import org.jboss.resource.connectionmanager.ConnectionListener; import org.jboss.resource.connectionmanager.InternalManagedConnectionPool; import org.jboss.resource.connectionmanager.JBossManagedConnectionPool; import org.jboss.resource.connectionmanager.ManagedConnectionPool; import org.jboss.resource.connectionmanager.NoTxConnectionManager; import org.jboss.test.jca.adapter.TestConnectionRequestInfo; import org.jboss.test.jca.adapter.TestManagedConnectionFactory; import org.jboss.test.JBossTestCase; /** * Unit Test for class ManagedConnectionPool * * * Created: Wed Jan 2 00:06:35 2002 * * @author <a href="mailto:d_jencks@users.sourceforge.net">David Jencks</a> * @version */ public class BaseConnectionManagerStressTestCase extends JBossTestCase { Logger log = Logger.getLogger(getClass()); boolean failed; ResourceException error; int startedThreadCount; final Object startedLock = new Object(); int finishedThreadCount; final Object finishedLock = new Object(); int connectionCount; int errorCount; float elapsed = 0; float held = 0; float getConnection = 0; float returnConnection = 0; Subject subject = new Subject(); ConnectionRequestInfo cri = new TestConnectionRequestInfo(); CachedConnectionManager ccm = new CachedConnectionManager(); /** * Creates a new <code>BaseConnectionManagerStressTestCase</code> instance. * * @param name test name */ public BaseConnectionManagerStressTestCase (String name) { super(name); } private BaseConnectionManager2 getCM( InternalManagedConnectionPool.PoolParams pp) throws Exception { ManagedConnectionFactory mcf = new TestManagedConnectionFactory(); ManagedConnectionPool poolingStrategy = new TestPool(mcf, pp, false, log); BaseConnectionManager2 cm = new NoTxConnectionManager(ccm, poolingStrategy); poolingStrategy.setConnectionListenerFactory(cm); return cm; } private void shutdown(BaseConnectionManager2 cm) { TestPool pool = (TestPool) cm.getPoolingStrategy(); pool.shutdown(); } public void testShortBlockingNoFill() throws Exception { doShortBlocking(20, 0, 5000); } public void testShortBlockingFill() throws Exception { doShortBlocking(20, getBeanCount(), 5000); } public void testShortBlockingPartFill() throws Exception { doShortBlocking(20, getBeanCount()/2, 5000); } public void testShortBlockingNearlyFill() throws Exception { doShortBlocking(20, getBeanCount() - 1, 5000); } public void testShortBlockingAggressiveRemoval() throws Exception { doShortBlocking(20, 0, 10); } public void testShortBlockingAggressiveRemovalAndFill() throws Exception { doShortBlocking(20, getBeanCount(), 10); } /** * The testShortBlocking test tries to simulate extremely high load on the pool, * with a short blocking timeout. It tests fairness in scheduling servicing * requests. The work time is modeled by sleepTime. Allowing overhead of * 15 ms/pool request, the blocking is calculated at * (worktime + overhead) * (threadsPerConnection) * * @exception Exception if an error occurs */ public void doShortBlocking(long sleep, int min, long idle) throws Exception { startedThreadCount = 0; finishedThreadCount = 0; connectionCount = 0; errorCount = 0; final int reps = getIterationCount(); final int threadsPerConnection = getThreadCount(); final long sleepTime = sleep; failed = false; InternalManagedConnectionPool.PoolParams pp = new InternalManagedConnectionPool.PoolParams(); pp.minSize = min; pp.maxSize = getBeanCount(); pp.blockingTimeout = (threadsPerConnection) * ((int)sleepTime + 15); if (pp.blockingTimeout < 1000) pp.blockingTimeout = 1000; pp.idleTimeout = idle; final BaseConnectionManager2 cm = getCM(pp); try { int totalThreads = pp.maxSize * threadsPerConnection; log.info("ShortBlocking test with connections: " + pp.maxSize + " totalThreads: " + totalThreads + " reps: " + reps); for (int i = 0; i < totalThreads; i++) { Runnable t = new Runnable() { int id; public void run() { synchronized (startedLock) { id = startedThreadCount; startedThreadCount++; startedLock.notify(); } long duration = 0; long getConnection = 0; long returnConnection = 0; long heldConnection = 0; for (int j = 0; j < reps; j++) { try { long startGetConnection = System.currentTimeMillis(); ConnectionListener cl = cm.getManagedConnection(null, null); long endGetConnection = System.currentTimeMillis(); //maybe should be synchronized BaseConnectionManagerStressTestCase.this.connectionCount++; Thread.sleep(sleepTime); long startReturnConnection = System.currentTimeMillis(); cm.returnManagedConnection(cl, false); long endReturnConnection = System.currentTimeMillis(); duration += (endReturnConnection - startGetConnection); getConnection += (endGetConnection - startGetConnection); returnConnection += (endReturnConnection - startReturnConnection); heldConnection += (startReturnConnection - endGetConnection); } catch (ResourceException re) { BaseConnectionManagerStressTestCase.this.log.info("error: iterationCount: " + j + ", connectionCount: " + BaseConnectionManagerStressTestCase.this.connectionCount + " " + re.getMessage()); BaseConnectionManagerStressTestCase.this.errorCount++; BaseConnectionManagerStressTestCase.this.error = re; BaseConnectionManagerStressTestCase.this.failed = true; } // end of try-catch catch (InterruptedException ie) { break; } // end of catch } synchronized (BaseConnectionManagerStressTestCase.this) { BaseConnectionManagerStressTestCase.this.elapsed += duration; BaseConnectionManagerStressTestCase.this.getConnection += getConnection; BaseConnectionManagerStressTestCase.this.returnConnection += returnConnection; BaseConnectionManagerStressTestCase.this.held += heldConnection; } synchronized (finishedLock) { finishedThreadCount++; finishedLock.notify(); } } }; new Thread(t).start(); synchronized (startedLock) { while (startedThreadCount < i + 1) { startedLock.wait(); } // end of while () } } // end of for () synchronized (finishedLock) { while (finishedThreadCount < totalThreads) { finishedLock.wait(); } // end of while () } // Stop the pool/idle remover, otherwise the following checks will be random TestPool pool = (TestPool) cm.getPoolingStrategy(); pool.shutdownWithoutClear(); float expected = totalThreads * reps; float lessWaiting = getConnection - (threadsPerConnection - 1) * held; log.info("completed " + getName() + " with connectionCount: " + connectionCount + ", expected : " + expected); log.info("errorCount: " + errorCount + " %error=" + ((100 * errorCount) / expected)); log.info("Total time elapsed: " + elapsed + ", perRequest: " + (elapsed / connectionCount)); log.info("Total time held : " + held + ", perRequest: " + (held / connectionCount)); log.info("Time getConnection: " + getConnection + ", perRequest: " + (getConnection / connectionCount)); log.info(" lessWaiting : " + lessWaiting + ", perRequest: " + (lessWaiting / connectionCount)); log.info("Time retConnection: " + returnConnection + ", perRequest: " + (returnConnection / connectionCount)); int available = (int) pool.getAvailableConnectionCount(); assertTrue("Wrong number of connections counted: " + available, available == pp.maxSize); assertTrue("Blocking Timeout occurred in ShortBlocking test: " + error, !failed); } finally { shutdown(cm); } } public class TestPool extends JBossManagedConnectionPool.OnePool { public TestPool(final ManagedConnectionFactory mcf, final InternalManagedConnectionPool.PoolParams poolParams, final boolean noTxSeparatePools, final Logger log) { super(mcf, poolParams, noTxSeparatePools, log); } public void shutdownWithoutClear() { super.shutdownWithoutClear(); } } }//