package org.jboss.cache;
import EDU.oswego.cs.dl.util.concurrent.Sync;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.cache.lock.ReadWriteLockWithUpgrade;
/**
* Stress test for RWLock with upgrade.
*/
public class ReadWriteLockWithUpgradeStressTest extends TestCase
{
static final ReadWriteLockWithUpgrade lock_ = new ReadWriteLockWithUpgrade();
static final long SLEEP_MSECS = 50;
static final int LOOPS = 200;
static int SEED = 1;
static Log log_=LogFactory.getLog("ReadWriteLockWithUpgrade");
int counter;
public ReadWriteLockWithUpgradeStressTest(String name)
{
super(name);
}
public static void main(String[] args) throws Exception
{
log("\nBeginning ReadWriteLockWithUpgrade automated testing ...\n");
junit.textui.TestRunner.run(suite());
}
// Needed for JUnit.
public static Test suite()
{
TestSuite suite = new TestSuite();
// Adding test cases here ...
suite.addTestSuite(ReadWriteLockWithUpgradeStressTest.class);
return suite;
}
public void setUp() throws Exception {
super.setUp();
log("Setting up stress test case ...");
counter = 0;
}
public void tearDown() throws Exception {
super.tearDown();
log("Tearing down stress test case ...");
}
public void testTimedWriteLocks() throws InterruptedException {
ReadWriteLockWithUpgrade l = new ReadWriteLockWithUpgrade();
final int NUM=1000000;
for(int i=0; i < NUM; i++) {
l.writeLock().attempt(2000);
l.writeLock().release();
if(i % 10000 == 0)
System.out.println(i);
}
}
protected Thread readAttemptThread(String name, final long msecs)
{
return new Thread(name)
{
public void run()
{
java.util.Random rand = new java.util.Random(++SEED);
for (int i = 0; i < LOOPS; i++) {
int duration = rand.nextInt((int) SLEEP_MSECS);
_sleep(SLEEP_MSECS);
Sync rlock = null;
try {
rlock = lock_.readLock();
if (!rlock.attempt(msecs)) {
log("Read lock attempt failed.");
// fail("Read lock attempt failed.");
counter++;
continue;
}
log("acquired read lock");
_sleep(duration);
log("released read lock");
} catch (Exception ex) {
}
finally {
rlock.release();
}
}
}
};
}
protected Thread writeAttemptThread(String name, final long msecs)
{
return new Thread(name)
{
public void run()
{
java.util.Random rand = new java.util.Random(++SEED);
for (int i = 0; i < LOOPS; i++) {
int duration = rand.nextInt((int) SLEEP_MSECS);
_sleep(SLEEP_MSECS + duration);
Sync wlock = null;
try {
wlock = lock_.writeLock();
if (!wlock.attempt(msecs)) {
log("Write lock attempt failed.");
// fail("Write lock attempt failed.");
counter++;
continue;
}
log("acquired write lock");
_sleep(duration);
log("released write lock");
} catch (Exception ex) {
}
finally {
wlock.release();
}
}
}
};
}
protected Thread upgradeAttemptThread(String name, final long msecs)
{
return new Thread(name)
{
public void run()
{
java.util.Random rand = new java.util.Random(++SEED);
for (int i = 0; i < LOOPS; i++) {
int duration = rand.nextInt((int) SLEEP_MSECS);
_sleep(SLEEP_MSECS);
Sync rlock = null;
Sync wlock = null;
try {
rlock = lock_.readLock();
if (!wlock.attempt(msecs)) {
log("Read lock attempt failed.");
// fail("Read lock attempt failed.");
counter++;
continue;
}
log("Acquired read lock for upgrade later");
_sleep(duration / 2);
// upgrade lock. Note that read lock will be released
// and write lock be acquired automatically.
wlock = lock_.upgradeLockAttempt(msecs);
if (wlock == null) {
log("upgrade lock attempt failed");
// fail("upgrade lock attempt failed");
rlock.release();
counter++;
}
log("Upgraded write lock");
_sleep(duration);
log("released write lock");
} catch (Exception ex) {
}
finally {
if(wlock != null)
wlock.release();
}
}
}
};
}
private void _sleep(long l) {
try {
Thread.sleep(l);
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
public void testWriteWriteAttempt() throws Exception
{
log("testWriteWriteAttempt() ...");
final long msecs = 1000;
Thread t1 = writeAttemptThread("t1-write", msecs);
Thread t2 = writeAttemptThread("t2-write", msecs);
Thread t3 = writeAttemptThread("t3-write", msecs);
Thread t4 = writeAttemptThread("t4-write", msecs);
t1.start();
t2.start();
t3.start();
t4.start();
long timeout = 0;
t1.join(timeout);
t2.join(timeout);
t3.join(timeout);
t4.join(timeout);
checkCounter();
}
public void testReadWriteAttempt1() throws Exception
{
log("testReadWriteAttemp1() ...");
final long msecs = 2000;
Thread t1 = readAttemptThread("t1-read", msecs);
Thread t2 = readAttemptThread("t2-read", msecs);
Thread t3 = writeAttemptThread("t3-write", msecs);
Thread t4 = writeAttemptThread("t4-write", msecs);
Thread t5 = upgradeAttemptThread("t5-upgrade", msecs);
Thread t6 = upgradeAttemptThread("t6-upgrade", msecs);
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
long timeout = 0;
t1.join(timeout);
t2.join(timeout);
t3.join(timeout);
t4.join(timeout);
t5.join(timeout);
t6.join(timeout);
checkCounter();
}
public void testReadWriteAttempt2() throws Exception
{
log("**************");
log("testReadWriteAttemp2() ...");
log("**************");
SEED++;
final long msecs = 1000;
Thread t1 = readAttemptThread("t1-read", msecs);
// Thread t2 = readAttemptThread("t2-read", msecs);
Thread t3 = writeAttemptThread("t3-write", msecs);
// Thread t4 = writeAttemptThread("t4-write", msecs);
Thread t5 = upgradeAttemptThread("t5-upgrade", msecs);
Thread t6 = upgradeAttemptThread("t6-upgrade", msecs);
t1.start();
// t2.start();
t3.start();
// t4.start();
t5.start();
t6.start();
long timeout = 0;
t1.join(timeout);
// t2.join(timeout);
t3.join(timeout);
// t4.join(timeout);
t5.join(timeout);
t6.join(timeout);
checkCounter();
}
public void testReadWriteAttempt3() throws Exception
{
log("**************");
log("testReadWriteAttemp3() ...");
log("**************");
SEED++;
final long msecs = 1000;
Thread t1 = readAttemptThread("t1-read", msecs);
Thread t2 = readAttemptThread("t2-read", msecs);
Thread t3 = writeAttemptThread("t3-write", msecs);
Thread t4 = writeAttemptThread("t4-write", msecs);
// Thread t5 = upgradeAttemptThread("t5-upgrade", msecs);
Thread t6 = upgradeAttemptThread("t6-upgrade", msecs);
t1.start();
t2.start();
t3.start();
t4.start();
// t5.start();
t6.start();
long timeout = 0;
t1.join(timeout);
t2.join(timeout);
t3.join(timeout);
t4.join(timeout);
// t5.join(timeout);
t6.join(timeout);
checkCounter();
}
private void checkCounter() {
if(counter > (LOOPS) )
fail("Failed lock attempt or upgrade exceeded warning. Counter: "+counter);
}
public static void log(String str)
{
// System.out.println(Thread.currentThread() + ": " + " StressTestCase " + " : "
// +" : "+java.util.Calendar.getInstance().getTime() + " : " +str);
log_.debug(Thread.currentThread() + ": "
+ " : " + str);
}
}