[jboss-cvs] JBossAS SVN: r80304 - in projects/ejb3/trunk/core/src: test/java/org/jboss/ejb3/core/test/ejbthree1549 and 1 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Fri Oct 31 03:30:36 EDT 2008


Author: ALRubinger
Date: 2008-10-31 03:30:36 -0400 (Fri, 31 Oct 2008)
New Revision: 80304

Modified:
   projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/cache/simple/SimpleStatefulCache.java
   projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/BlockingPersistenceManager.java
   projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/ForcePassivationCache.java
   projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/unit/PassivationDoesNotPreventNewActivityUnitTestCase.java
Log:
[EJBTHREE-1549] Replace Thread.sleep() in tests with more reliable locks/barriers for blocking

Modified: projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/cache/simple/SimpleStatefulCache.java
===================================================================
--- projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/cache/simple/SimpleStatefulCache.java	2008-10-31 04:57:33 UTC (rev 80303)
+++ projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/cache/simple/SimpleStatefulCache.java	2008-10-31 07:30:36 UTC (rev 80304)
@@ -54,7 +54,7 @@
    protected CacheMap cacheMap;
    private int maxSize = 1000;
    private StatefulSessionPersistenceManager pm;
-   private long sessionTimeout = 300; // 5 minutes
+   protected long sessionTimeout = 300; // 5 minutes
    private long removalTimeout = 0; 
    private Thread timeoutTask;
    private RemovalTimeoutTask removalTask = null;
@@ -182,6 +182,14 @@
       {
          Thread.sleep(sessionTimeout * 1000);
       }
+      
+      /**
+       * Just provides a hook
+       */
+      public void passivationCompleted()
+      {
+         
+      }
 
       public void run()
       {
@@ -276,6 +284,9 @@
                         assert removed == centry : "Removed " + removed
                               + " from internal cacheMap did not match the object we were expecting: " + centry;
 
+                        // Make internal callback that we're done
+                        this.passivationCompleted();
+                        
                         /*
                          * End EJBTHREE-1549
                          */

Modified: projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/BlockingPersistenceManager.java
===================================================================
--- projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/BlockingPersistenceManager.java	2008-10-31 04:57:33 UTC (rev 80303)
+++ projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/BlockingPersistenceManager.java	2008-10-31 07:30:36 UTC (rev 80304)
@@ -21,6 +21,8 @@
  */
 package org.jboss.ejb3.core.test.ejbthree1549;
 
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.CyclicBarrier;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 
@@ -47,10 +49,20 @@
    private static final Logger log = Logger.getLogger(BlockingPersistenceManager.class);
 
    /**
-    * Publicly-accessible lock to allow tests to block passivation
+    * Publicly-accessible lock
+    * 
+    * Used by the test to block the act of passivation
     */
-   public static final Lock LOCK = new ReentrantLock();
+   public static final Lock PASSIVATION_LOCK = new ReentrantLock();
 
+   /**
+    * Publicly-accessible barrier
+    * 
+    * Will block until both the test and the PM agree that passivation 
+    * should take place
+    */
+   public static final CyclicBarrier BARRIER = new CyclicBarrier(2);
+
    // --------------------------------------------------------------------------------||
    // Required Implementations -------------------------------------------------------||
    // --------------------------------------------------------------------------------||
@@ -58,21 +70,46 @@
    @Override
    public void passivateSession(StatefulBeanContext ctx)
    {
-      // Block until the lock may be acquired, 
-      // may currently be held by the test Thread
-      LOCK.lock();
 
       try
       {
-         // Mock Passivate
-         log.info("Mock Passivation on " + ctx);
+         /*
+          * Block until the lock may be acquired,
+          * may currently be held by the test Thread until the test is ready.
+          * So here both the test and passivation will block until this barrier
+          * is agreed by both Threads to be released
+          */
+         log.info("Waiting until the test is ready for passivation to start...");
+         BARRIER.await();
+
+         // Block until the test releases this lock
+         log.info("Blocking until the test tells us that the act of passivation may continue...");
+         PASSIVATION_LOCK.lock();
+
+         try
+         {
+            // Mock Passivate
+            log.info("Mock Passivation on " + ctx);
+         }
+         finally
+         {
+            // Release the passivation lock
+            log.info("We're done with passivation, letting the lock go.");
+            PASSIVATION_LOCK.unlock();
+         }
       }
+      catch (InterruptedException e)
+      {
+         throw new RuntimeException("Barrier was interrupted prematurely", e);
+      }
+      catch (BrokenBarrierException e)
+      {
+         throw new RuntimeException("Barrier was broken prematurely", e);
+      }
       finally
       {
-         // Release the lock
-         LOCK.unlock();
+         // Reset the Barrier
+         BARRIER.reset();
       }
-
    }
-
 }

Modified: projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/ForcePassivationCache.java
===================================================================
--- projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/ForcePassivationCache.java	2008-10-31 04:57:33 UTC (rev 80303)
+++ projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/ForcePassivationCache.java	2008-10-31 07:30:36 UTC (rev 80304)
@@ -22,8 +22,11 @@
 package org.jboss.ejb3.core.test.ejbthree1549;
 
 import java.io.Serializable;
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.CyclicBarrier;
 
 import org.jboss.ejb3.cache.simple.SimpleStatefulCache;
+import org.jboss.ejb3.stateful.StatefulBeanContext;
 import org.jboss.logging.Logger;
 
 /**
@@ -43,8 +46,17 @@
 
    private static final Logger log = Logger.getLogger(ForcePassivationCache.class);
 
-   private static final Object PASSIVATION_LOCK = new Object();
+   /**
+    * Shared barrier between the Cache and the test so that 
+    * the test may block until passivation is completed
+    */
+   public static final CyclicBarrier POST_PASSIVATE_BARRIER = new CyclicBarrier(2);
 
+   /**
+    * Internal lock used to manually block the passivation task from running
+    */
+   private static final Object START_PASSIVATION_LOCK = new Object();
+
    // --------------------------------------------------------------------------------||
    // Functional Methods -------------------------------------------------------------||
    // --------------------------------------------------------------------------------||
@@ -56,15 +68,44 @@
    {
       // Get a lock
       log.info("Awaiting lock to force passivation");
-      synchronized (PASSIVATION_LOCK)
+      synchronized (START_PASSIVATION_LOCK)
       {
          // Notify that passivation should run
          log.info("Notifying passivation via manual force...");
-         PASSIVATION_LOCK.notify();
+         START_PASSIVATION_LOCK.notify();
       }
    }
 
    /**
+    * Manually sets the session with the specified sessionId
+    * past expiry for passivation
+    * 
+    * @param sessionId
+    */
+   public void makeSessionEligibleForPassivation(Serializable sessionId)
+   {
+      // Get the cacheMap
+      CacheMap cm = this.cacheMap;
+
+      // Synchronize on it
+      synchronized (cm)
+      {
+         // Find the session
+         StatefulBeanContext session = (StatefulBeanContext) cm.get(sessionId);
+
+         // Synchronize on the session
+         synchronized (session)
+         {
+            // Get now
+            long now = System.currentTimeMillis();
+
+            // Manually set past expiry
+            session.lastUsed = (now - (sessionTimeout * 1000)) - 1;
+         }
+      }
+   }
+
+   /**
     * Exposed for testing only
     * 
     * Returns whether or not the internal cacheMap contains
@@ -76,9 +117,9 @@
    {
       // Get the cacheMap
       CacheMap cm = this.cacheMap;
-      
+
       // Synchronize on it
-      synchronized(cm)
+      synchronized (cm)
       {
          // Return whether the specified key was found
          return cm.containsKey(sessionId);
@@ -112,24 +153,54 @@
     */
    private class BlockingPassivationTask extends SessionTimeoutTask
    {
+
       public BlockingPassivationTask(String name)
       {
          super(name);
       }
 
+      @Override
       public void block() throws InterruptedException
       {
          // Get a lock on our monitor
-         synchronized (PASSIVATION_LOCK)
+         synchronized (START_PASSIVATION_LOCK)
          {
             // Wait until we're signaled
             log.info("Waiting to be notified to run passivation...");
-            PASSIVATION_LOCK.wait();
+            START_PASSIVATION_LOCK.wait();
          }
 
          // Log that we've been notified
          log.info("Notified to run passivation");
       }
+
+      @Override
+      public void passivationCompleted()
+      {
+         // Call super
+         super.passivationCompleted();
+
+         // Tell the barrier we've arrived
+         try
+         {
+            log.info("Waiting on the post-passivate barrier...");
+            POST_PASSIVATE_BARRIER.await();
+         }
+         catch (InterruptedException e)
+         {
+            throw new RuntimeException("Post Passivate prematurely interrupted", e);
+         }
+         catch (BrokenBarrierException e)
+         {
+            throw new RuntimeException("Post Passivate prematurely broken", e);
+         }
+         finally
+         {
+            // Reset the barrier
+            log.info("Post-passivate of PM is done, resetting the barrier");
+            POST_PASSIVATE_BARRIER.reset();
+         }
+      }
    }
 
 }
\ No newline at end of file

Modified: projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/unit/PassivationDoesNotPreventNewActivityUnitTestCase.java
===================================================================
--- projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/unit/PassivationDoesNotPreventNewActivityUnitTestCase.java	2008-10-31 04:57:33 UTC (rev 80303)
+++ projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/unit/PassivationDoesNotPreventNewActivityUnitTestCase.java	2008-10-31 07:30:36 UTC (rev 80304)
@@ -39,7 +39,6 @@
 import org.jboss.ejb3.core.test.ejbthree1549.MyStatefulBean;
 import org.jboss.ejb3.core.test.ejbthree1549.MyStatefulLocal;
 import org.jboss.ejb3.proxy.handler.session.stateful.StatefulLocalProxyInvocationHandler;
-import org.jboss.ejb3.session.SessionContainer;
 import org.jboss.ejb3.stateful.StatefulContainer;
 import org.jboss.logging.Logger;
 import org.junit.AfterClass;
@@ -61,7 +60,7 @@
    // Class Members ------------------------------------------------------------------||
    // --------------------------------------------------------------------------------||
 
-   private static SessionContainer container;
+   private static StatefulContainer container;
 
    private static final Logger log = Logger.getLogger(PassivationDoesNotPreventNewActivityUnitTestCase.class);
 
@@ -197,8 +196,16 @@
       log.info("Got counter from bean1 : " + next);
       TestCase.assertEquals("SFSB did not return expected next counter", 0, next);
 
+      // Get our bean's Session ID
+      StatefulLocalProxyInvocationHandler handler = (StatefulLocalProxyInvocationHandler) Proxy
+            .getInvocationHandler(bean1);
+      Serializable sessionId = handler.getSessionId();
+
+      // Get the Cache
+      ForcePassivationCache cache = (ForcePassivationCache) container.getCache();
+
       // Get the lock to block the PM, now
-      boolean gotLock = BlockingPersistenceManager.LOCK.tryLock();
+      boolean gotLock = BlockingPersistenceManager.PASSIVATION_LOCK.tryLock();
 
       // Once PM lock is acquired, everything is in "try" so we release in "finally"
       try
@@ -207,16 +214,25 @@
          TestCase.assertTrue("Test was not able to immediately get the lock to block the PersistenceManager", gotLock);
          log.info("Locked " + BlockingPersistenceManager.class.getSimpleName());
 
-         // Wait to allow bean to be eligible for passivation
-         long sleepTime = MyStatefulLocal.PASSIVATION_TIMEOUT * 1000 + 1000; // Add 1/2 a second to the configured passivation timeout
-         Thread.sleep(sleepTime);
+         /*
+          * Mark our session as expired
+          */
 
+         // Mark
+         cache.makeSessionEligibleForPassivation(sessionId);
+
+         /*
+          * Passivate
+          */
+
          // Trigger Passivation
          ForcePassivationCache.forcePassivation();
          log.info("Passivation forced, carrying out test");
 
-         // Wait to allow passivation to actually start
-         Thread.sleep(2000);
+         // Block until the PM is ready to passivate
+         log.info("Waiting on common barrier for PM to run...");
+         BlockingPersistenceManager.BARRIER.await();
+         log.info("PM and test have met barrier, passivation running (but will be blocked to complete by test)");
 
          /*
           * At this point, we've told the passivation Thread to start, and have 
@@ -259,23 +275,19 @@
       {
 
          // Allow the Persistence Manager to finish up
-         BlockingPersistenceManager.LOCK.unlock();
-         
-         // We need to allow time to let PM do its thing, so use the lock to block then release
-         Thread.sleep(150); // Just to make sure the PM gets the lock back first
-         BlockingPersistenceManager.LOCK.lock(); // Block until PM is done
-         BlockingPersistenceManager.LOCK.unlock(); // PM must be done, we don't really need the lock, release it
+         log.info("Letting the PM perform passivation...");
+         BlockingPersistenceManager.PASSIVATION_LOCK.unlock();
       }
-      
-      
+
+      // We need to allow time to let the Cache finish passivation, so block until it's done
+      log.info("Waiting on Cache to tell us passivation is completed...");
+      ForcePassivationCache.POST_PASSIVATE_BARRIER.await();
+      log.info("Test sees Cache reports passivation completed.");
+
       /*
        * Here we ensure that the session was removed from the internal cacheMap
        */
-      StatefulLocalProxyInvocationHandler handler = (StatefulLocalProxyInvocationHandler) Proxy
-            .getInvocationHandler(bean1);
-      Serializable sessionId = handler.getSessionId();
-      boolean beanIsInCache = ((ForcePassivationCache) ((StatefulContainer) container).getCache())
-            .doesCacheMapContainKey(sessionId);
+      boolean beanIsInCache = cache.doesCacheMapContainKey(sessionId);
       assertFalse("bean was not removed from cache", beanIsInCache);
 
       // Ensure we're good
@@ -339,7 +351,7 @@
       // Deploy the test SFSB
       Class<?> ejbImplClass = MyStatefulBean.class;
       log.info("Deploying SFSB: " + ejbImplClass.getName());
-      container = deploySessionEjb(ejbImplClass);
+      container = (StatefulContainer) deploySessionEjb(ejbImplClass);
    }
 
    @AfterClass




More information about the jboss-cvs-commits mailing list