[jboss-cvs] JBossAS SVN: r79302 - in projects/ejb3/trunk/testsuite/src/test/java/org/jboss/ejb3/test/singleton: pool and 1 other directories.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Thu Oct 9 10:46:40 EDT 2008
Author: alex.loubyansky at jboss.com
Date: 2008-10-09 10:46:40 -0400 (Thu, 09 Oct 2008)
New Revision: 79302
Modified:
projects/ejb3/trunk/testsuite/src/test/java/org/jboss/ejb3/test/singleton/SingletonBean.java
projects/ejb3/trunk/testsuite/src/test/java/org/jboss/ejb3/test/singleton/SingletonLockInterceptor.java
projects/ejb3/trunk/testsuite/src/test/java/org/jboss/ejb3/test/singleton/SingletonRemote.java
projects/ejb3/trunk/testsuite/src/test/java/org/jboss/ejb3/test/singleton/pool/SingletonPool.java
projects/ejb3/trunk/testsuite/src/test/java/org/jboss/ejb3/test/singleton/unit/SingletonUnitTestCase.java
Log:
EJBTHREE-1518 basic pool impl and basic tests for read and write concurrency
Modified: projects/ejb3/trunk/testsuite/src/test/java/org/jboss/ejb3/test/singleton/SingletonBean.java
===================================================================
--- projects/ejb3/trunk/testsuite/src/test/java/org/jboss/ejb3/test/singleton/SingletonBean.java 2008-10-09 12:37:20 UTC (rev 79301)
+++ projects/ejb3/trunk/testsuite/src/test/java/org/jboss/ejb3/test/singleton/SingletonBean.java 2008-10-09 14:46:40 UTC (rev 79302)
@@ -47,6 +47,9 @@
private static Object instanceLock = new Object();
private static Thread lockerThread;
+ // some instance variable
+ private int value;
+
// instance initialization
{
synchronized(instanceCount)
@@ -60,7 +63,11 @@
return instanceCount;
}
- public void testWriteLock(long pause)
+ /**
+ * This method demonstrates that once one thread is entered an instance method
+ * no other thread can enter any method of the same instance in case of write concurrency.
+ */
+ public void writeLock(long pause)
{
Thread currentThread = Thread.currentThread();
synchronized(instanceLock)
@@ -69,7 +76,6 @@
lockerThread = currentThread;
else if(!lockerThread.equals(currentThread))
{
- //System.out.println("Another thread is active in the instance: " + lockerThread + ", current thread: " + currentThread);
throw new IllegalStateException("Another thread is active in the instance: " + lockerThread + ", current thread: " + currentThread);
}
}
@@ -86,10 +92,70 @@
{
if(!currentThread.equals(lockerThread))
{
- //System.out.println("Another thread is active in the instance: " + lockerThread + ", current thread: " + currentThread);
throw new IllegalStateException("Another thread is/was active in the instance: " + lockerThread + ", current thread: " + currentThread);
}
lockerThread = null;
}
}
+
+ /**
+ * This method demonstrates that two threads can be active in the same session bean instance in case of read concurrency.
+ *
+ * 1. check that the value (instance variable) is equal to the expectedCurrentValue.
+ * If it's not then wait for the other thread to set it to the expectedCurrentValue.
+ * 2. increase the value
+ * 3. if the expectedCurrentValue != 0 then just return the current value.
+ * Otherwise wait for the other thread to change the value and return the current value.
+ *
+ * if waiting takes longer than timeout then throw an exception.
+ */
+ public int getReadLock(int expectedCurrentValue, long timeout)
+ {
+ long startTime = System.currentTimeMillis();
+ synchronized(instanceLock)
+ {
+ // make sure value has the expected value
+ while(expectedCurrentValue != this.value)
+ {
+ if (System.currentTimeMillis() - startTime > timeout)
+ throw new IllegalStateException("The method took too long.");
+ try
+ {
+ instanceLock.wait(timeout);
+ }
+ catch (InterruptedException e)
+ {
+ }
+ }
+
+ // at this point value == expectedCurrentValue
+ if(expectedCurrentValue != this.value)
+ throw new IllegalStateException("Unexpected instance variable value. Expected " + expectedCurrentValue + " but was " + this.value);
+
+ // increase the value
+ ++this.value;
+ instanceLock.notify();
+
+ if(expectedCurrentValue == 0)
+ {
+ // wait until the other thread increases the current value
+ startTime = System.currentTimeMillis();
+ while (this.value == expectedCurrentValue + 1)
+ {
+ if (System.currentTimeMillis() - startTime > timeout)
+ throw new IllegalStateException("The method took too long.");
+
+ try
+ {
+ instanceLock.wait(timeout);
+ }
+ catch (InterruptedException e)
+ {
+ }
+ }
+ }
+ }
+
+ return this.value;
+ }
}
Modified: projects/ejb3/trunk/testsuite/src/test/java/org/jboss/ejb3/test/singleton/SingletonLockInterceptor.java
===================================================================
--- projects/ejb3/trunk/testsuite/src/test/java/org/jboss/ejb3/test/singleton/SingletonLockInterceptor.java 2008-10-09 12:37:20 UTC (rev 79301)
+++ projects/ejb3/trunk/testsuite/src/test/java/org/jboss/ejb3/test/singleton/SingletonLockInterceptor.java 2008-10-09 14:46:40 UTC (rev 79302)
@@ -23,6 +23,7 @@
import org.jboss.aop.joinpoint.Invocation;
import org.jboss.aop.joinpoint.MethodInvocation;
+import org.jboss.ejb3.EJBContainer;
import org.jboss.ejb3.aop.AbstractInterceptor;
import org.jboss.logging.Logger;
@@ -46,8 +47,8 @@
public Object invoke(Invocation invocation) throws Throwable
{
+ EJBContainer container = getEJBContainer(invocation);
/* way to get to the metadata and determine whether the method has READ or WRITE lock
- EJBContainer container = getEJBContainer(invocation);
JBossEnterpriseBeanMetaData xml = container.getXml();
if(xml != null)
log.info("metadata is available");
@@ -57,7 +58,11 @@
boolean isReadMethod = false;
MethodInvocation mi = (MethodInvocation) invocation;
if(mi.getMethod() != null)
- isReadMethod = mi.getMethod().getName().startsWith("get");
+ {
+ String methodName = mi.getMethod().getName();
+ isReadMethod = methodName.startsWith("get") || methodName.startsWith("is");
+ log.info(container.getEjbName() + '.' + methodName + " is read concurrency: " + isReadMethod);
+ }
lock.sync();
try
Modified: projects/ejb3/trunk/testsuite/src/test/java/org/jboss/ejb3/test/singleton/SingletonRemote.java
===================================================================
--- projects/ejb3/trunk/testsuite/src/test/java/org/jboss/ejb3/test/singleton/SingletonRemote.java 2008-10-09 12:37:20 UTC (rev 79301)
+++ projects/ejb3/trunk/testsuite/src/test/java/org/jboss/ejb3/test/singleton/SingletonRemote.java 2008-10-09 14:46:40 UTC (rev 79302)
@@ -29,7 +29,19 @@
*/
public interface SingletonRemote
{
+ /**
+ * @return current number of created instances (must always be 1)
+ */
int getInstanceCount();
- void testWriteLock(long pause);
+ /**
+ * This method demonstrates that once one thread is entered an instance method
+ * no other thread can enter any method of the same instance in case of write concurrency.
+ */
+ void writeLock(long pause);
+
+ /**
+ * This method demonstrates that two threads can be active in the same session bean instance in case of read concurrency.
+ */
+ int getReadLock(int expectedCurrentValue, long timeout);
}
Modified: projects/ejb3/trunk/testsuite/src/test/java/org/jboss/ejb3/test/singleton/pool/SingletonPool.java
===================================================================
--- projects/ejb3/trunk/testsuite/src/test/java/org/jboss/ejb3/test/singleton/pool/SingletonPool.java 2008-10-09 12:37:20 UTC (rev 79301)
+++ projects/ejb3/trunk/testsuite/src/test/java/org/jboss/ejb3/test/singleton/pool/SingletonPool.java 2008-10-09 14:46:40 UTC (rev 79302)
@@ -21,8 +21,9 @@
*/
package org.jboss.ejb3.test.singleton.pool;
+import org.jboss.ejb3.BeanContext;
import org.jboss.ejb3.Container;
-import org.jboss.ejb3.pool.StrictMaxPool;
+import org.jboss.ejb3.pool.AbstractPool;
/**
* A SingletonPool.
@@ -30,11 +31,57 @@
* @author <a href="alex at jboss.com">Alexey Loubyansky</a>
* @version $Revision: 1.1 $
*/
-public class SingletonPool extends StrictMaxPool
+public class SingletonPool extends AbstractPool
{
+ private BeanContext<?> instance;
+
@Override
public void initialize(Container container, int maxSize, long timeout)
{
- super.initialize(container, 1, 11000);
+ super.initialize(container, 1, timeout);
+ instance = create(null, null);
+ System.out.println("SingletonPool.initialize: maxSize=" + maxSize);
}
+
+ @Override
+ public void setMaxSize(int maxSize)
+ {
+ if(maxSize != 1)
+ throw new IllegalArgumentException("Maximum size for this pool must be 1: " + maxSize);
+ }
+
+ public void destroy()
+ {
+ if(instance != null)
+ discard(instance);
+ }
+
+ public BeanContext<?> get()
+ {
+ return instance;
+ }
+
+ public BeanContext<?> get(Class<?>[] initTypes, Object[] initValues)
+ {
+ return instance;
+ }
+
+ public int getAvailableCount()
+ {
+ return 1;
+ }
+
+ public int getCurrentSize()
+ {
+ return getCreateCount() - getRemoveCount();
+ }
+
+ public int getMaxSize()
+ {
+ return 1;
+ }
+
+ public void release(BeanContext<?> obj)
+ {
+ }
}
Modified: projects/ejb3/trunk/testsuite/src/test/java/org/jboss/ejb3/test/singleton/unit/SingletonUnitTestCase.java
===================================================================
--- projects/ejb3/trunk/testsuite/src/test/java/org/jboss/ejb3/test/singleton/unit/SingletonUnitTestCase.java 2008-10-09 12:37:20 UTC (rev 79301)
+++ projects/ejb3/trunk/testsuite/src/test/java/org/jboss/ejb3/test/singleton/unit/SingletonUnitTestCase.java 2008-10-09 14:46:40 UTC (rev 79302)
@@ -66,7 +66,11 @@
undeploy("singleton-test.jar");
}
- public void testWriteLock() throws Exception
+ /**
+ * This method demonstrates that once one thread is entered an instance method
+ * no other thread can enter any method of the same instance in case of write concurrency.
+ */
+ public void testWriteConcurrency() throws Exception
{
final SingletonRemote remote = (SingletonRemote) getInitialContext().lookup("SingletonBean/remote");
@@ -81,7 +85,7 @@
{
try
{
- remote.testWriteLock((long) (1000*Math.random()));
+ remote.writeLock((long) (1000*Math.random()));
}
catch(Throwable t)
{
@@ -123,4 +127,66 @@
assertNull("One of the threads failed: " + sawFailedThread[0], sawFailedThread[0]);
assertEquals(1, remote.getInstanceCount());
}
+
+ /**
+ * This method demonstrates that two threads can be active in the same session bean instance in case of read concurrency.
+ */
+ public void testReadConcurrency() throws Throwable
+ {
+ final SingletonRemote remote = (SingletonRemote) getInitialContext().lookup("SingletonBean/remote");
+
+ final Throwable error[] = new Throwable[1];
+ final int[] results = new int[2];
+ final Thread[] threads = new Thread[2];
+ for(int i = 0; i < threads.length; ++i)
+ {
+ final int threadIndex = i;
+ threads[i] = new Thread(new Runnable()
+ {
+ public void run()
+ {
+ try
+ {
+ results[threadIndex] = remote.getReadLock(threadIndex, 1000);
+ }
+ catch(Throwable t)
+ {
+ log.error(t);
+ error[0] = t;
+ }
+ finally
+ {
+ synchronized (results)
+ {
+ results.notify();
+ }
+ }
+ }
+ });
+ }
+
+ for(int i = 0; i < threads.length; ++i)
+ threads[i].start();
+
+ synchronized(results)
+ {
+ while((results[0] == 0 || results[1] == 0) && error[0] == null)
+ {
+ try
+ {
+ results.wait();
+ }
+ catch(InterruptedException e)
+ {
+ }
+ }
+ }
+
+ if(error[0] != null)
+ throw error[0];
+
+ assertEquals(2, results[0]);
+ assertEquals(2, results[1]);
+ assertEquals(1, remote.getInstanceCount());
+ }
}
More information about the jboss-cvs-commits
mailing list