[jboss-cvs] JBossAS SVN: r100315 - in branches/JBPAPP_5_0: testsuite/src/main/org/jboss/test/cluster/testutil and 3 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Tue Feb 2 23:12:57 EST 2010


Author: dereed
Date: 2010-02-02 23:12:56 -0500 (Tue, 02 Feb 2010)
New Revision: 100315

Added:
   branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/defaultcfg/simpleweb/test/ClusteredSessionUnitTestCase.java
   branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/defaultcfg/simpleweb/test/ConcurrentFailoverRequestsTestCase.java
   branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/testutil/JBossCacheUtil.java
   branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/web/mocks/ConcurrentRequestHandler.java
   branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/web/mocks/MockClusteredManager.java
   branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/web/mocks/MockDistributedCacheManager.java
   branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/web/mocks/MockDistributedCacheManagerFactory.java
Removed:
   branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/web/jvmroute/MockDistributedCacheManager.java
   branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/web/jvmroute/MockJBossManager.java
Modified:
   branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/defaultcfg/simpleweb/test/JvmRouteValveUnitTestCase.java
   branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/testutil/SessionTestUtil.java
   branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/web/jvmroute/MockSession.java
   branches/JBPAPP_5_0/tomcat/src/main/org/jboss/web/tomcat/service/session/ClusteredSession.java
   branches/JBPAPP_5_0/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheManager.java
Log:
[JBPAPP-2929] Port JBAS-7379 to EAP 5.0.1


Added: branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/defaultcfg/simpleweb/test/ClusteredSessionUnitTestCase.java
===================================================================
--- branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/defaultcfg/simpleweb/test/ClusteredSessionUnitTestCase.java	                        (rev 0)
+++ branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/defaultcfg/simpleweb/test/ClusteredSessionUnitTestCase.java	2010-02-03 04:12:56 UTC (rev 100315)
@@ -0,0 +1,88 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009 Red Hat Middleware, Inc. 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.cluster.defaultcfg.simpleweb.test;
+
+import junit.framework.TestCase;
+
+import org.jboss.metadata.web.jboss.ReplicationGranularity;
+import org.jboss.test.cluster.testutil.JGroupsSystemPropertySupport;
+import org.jboss.test.cluster.testutil.SessionTestUtil;
+import org.jboss.test.cluster.web.mocks.MockDistributedCacheManagerFactory;
+import org.jboss.web.tomcat.service.session.ClusteredSession;
+import org.jboss.web.tomcat.service.session.JBossCacheManager;
+
+/**
+ * Unit tests of {@link ClusteredSession}.
+ *
+ * @author Brian Stansberry
+ * 
+ * @version $Revision: $
+ */
+public class ClusteredSessionUnitTestCase extends TestCase
+{
+   /**
+    * Create a new ClusteredSessionUnitTestCase.
+    * 
+    * @param name
+    */
+   public ClusteredSessionUnitTestCase(String name)
+   {
+      super(name);
+   }
+   
+   /**
+    * Validates the behavior of isOutdated() with respect to returning
+    * true until a creation time is set.
+    * <p>
+    * Note: the use of creation time is a convenience; it's just a field that
+    * isn't set at construction but rather after the session is either loaded
+    * from the distributed cache or is added as a brand new session.
+    * 
+    * @throws Exception
+    */
+   public void testNewSessionIsOutdated() throws Exception
+   {
+      JBossCacheManager mgr = new JBossCacheManager(new MockDistributedCacheManagerFactory());
+      SessionTestUtil.setupContainer("test", null, mgr);
+      mgr.start();
+      
+      mgr.setReplicationGranularity(ReplicationGranularity.SESSION);
+      ClusteredSession sess = (ClusteredSession) mgr.createEmptySession();
+      assertTrue(sess.isOutdated());
+      sess.setCreationTime(System.currentTimeMillis());
+      assertFalse(sess.isOutdated());
+      
+      mgr.setReplicationGranularity(ReplicationGranularity.ATTRIBUTE);
+      sess = (ClusteredSession) mgr.createEmptySession();
+      assertTrue(sess.isOutdated());
+      sess.setCreationTime(System.currentTimeMillis());
+      assertFalse(sess.isOutdated());
+      
+      mgr.setReplicationGranularity(ReplicationGranularity.FIELD);
+      sess = (ClusteredSession) mgr.createEmptySession();
+      assertTrue(sess.isOutdated());
+      sess.setCreationTime(System.currentTimeMillis());
+      assertFalse(sess.isOutdated());
+   }
+
+}

Added: branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/defaultcfg/simpleweb/test/ConcurrentFailoverRequestsTestCase.java
===================================================================
--- branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/defaultcfg/simpleweb/test/ConcurrentFailoverRequestsTestCase.java	                        (rev 0)
+++ branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/defaultcfg/simpleweb/test/ConcurrentFailoverRequestsTestCase.java	2010-02-03 04:12:56 UTC (rev 100315)
@@ -0,0 +1,279 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009 Red Hat, Inc. 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.cluster.defaultcfg.simpleweb.test;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import junit.framework.TestCase;
+
+import org.apache.catalina.Manager;
+import org.apache.catalina.Session;
+import org.apache.catalina.Valve;
+import org.apache.catalina.connector.Request;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.pojo.PojoCache;
+import org.jboss.logging.Logger;
+import org.jboss.metadata.web.jboss.JBossWebMetaData;
+import org.jboss.test.cluster.testutil.JBossCacheUtil;
+import org.jboss.test.cluster.testutil.JGroupsSystemPropertySupport;
+import org.jboss.test.cluster.testutil.SessionTestUtil;
+import org.jboss.test.cluster.web.mocks.BasicRequestHandler;
+import org.jboss.test.cluster.web.mocks.ConcurrentRequestHandler;
+import org.jboss.test.cluster.web.mocks.SetAttributesRequestHandler;
+import org.jboss.web.tomcat.service.session.JBossCacheManager;
+
+/**
+ * JBAS-7379. Tests that multiple concurrent failover requests for
+ * the same session are handled properly.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 85945 $
+ */
+public class ConcurrentFailoverRequestsTestCase extends TestCase
+{
+   private static final Logger log = Logger.getLogger(ConcurrentFailoverRequestsTestCase.class);
+   
+   private static long testCount = System.currentTimeMillis();
+   
+   private final JGroupsSystemPropertySupport jgSupport = new JGroupsSystemPropertySupport();
+   private Set<PojoCache> caches = new HashSet<PojoCache>();
+   
+   private ExecutorService threadPool;
+   
+   /**
+    * Create a new ConcurrentFailoverRequestsTestCase.
+    * 
+    * @param name
+    */
+   public ConcurrentFailoverRequestsTestCase(String name)
+   {
+      super(name);
+   } 
+
+   @Override
+   protected void setUp() throws Exception
+   {
+      super.setUp();
+      
+      jgSupport.setUpProperties();
+   }
+
+   @Override
+   protected void tearDown() throws Exception
+   {
+      try
+      {
+         super.tearDown();
+      }
+      finally
+      {      
+         jgSupport.restoreProperties();
+         
+         if (threadPool != null)
+         {
+            threadPool.shutdownNow();
+         }
+         
+         SessionTestUtil.clearDistributedCacheManagerFactory();
+         
+         for (PojoCache cache : caches)
+         { 
+            // Try to clean up so we avoid loading sessions 
+            // from storage in later tests
+            try
+            {
+               log.info("Removing /JSESSION from " + cache.getCache().getLocalAddress());
+               cache.getCache().removeNode(Fqn.fromString("/JSESSION"));
+            }
+            catch (Exception e)
+            {
+               log.error("Cache " + cache.getCache().getLocalAddress() + ": " + e.getMessage(), e);
+            }
+            
+            try
+            {
+               cache.stop();
+               cache.destroy();
+            }
+            catch (Exception e)
+            {
+               log.error("Cache " + cache.getCache().getLocalAddress() + ": " + e.getMessage(), e);
+            }
+            
+         }
+         
+         caches.clear();
+      }
+   }
+
+   public void testConcurrentFailoverRequests() throws Exception
+   {
+      ++testCount;
+      
+      JBossWebMetaData webMetaData = SessionTestUtil.createWebMetaData(100);
+      String warName = "test" + testCount;
+      JBossCacheManager jbcm0 = SessionTestUtil.createManager(warName, 30, false, null, false, false, null, caches);
+      jbcm0.init(warName, webMetaData);      
+      jbcm0.start();
+      
+      JBossCacheManager jbcm1 = SessionTestUtil.createManager(warName, 30, false, null, false, false, null, caches);
+      jbcm1.init(warName, webMetaData);      
+      jbcm1.start();
+      
+      Cache[] array = new Cache[caches.size()];
+      int index = 0;
+      for (PojoCache c : caches)
+      {
+         array[index] = c.getCache();
+         index++;
+      }
+      JBossCacheUtil.blockUntilViewsReceived(array, 10000);
+      
+      Object value = "0";
+      Map<String, Object> attrs = Collections.unmodifiableMap(Collections.singletonMap("count", value));
+      SetAttributesRequestHandler setHandler = new SetAttributesRequestHandler(attrs, false);
+      SessionTestUtil.invokeRequest(jbcm0, setHandler, null);
+      
+      String id1 = setHandler.getSessionId();
+      assertNotNull(id1);
+      
+      // Add a second session that we can check for replication; this is a proxy
+      // for checking that first session has replicated
+      setHandler = new SetAttributesRequestHandler(attrs, false);
+      SessionTestUtil.invokeRequest(jbcm0, setHandler, null);
+      
+      String id2 = setHandler.getSessionId();
+      assertNotNull(id1);
+      
+      assertFalse(id1.equals(id2));
+      
+      // Ensure replication of session 2 has occurred
+      boolean found = false;
+      for (int i = 0; i < 10; i++)
+      {
+         BasicRequestHandler getHandler = new BasicRequestHandler(attrs.keySet(), false);
+         SessionTestUtil.invokeRequest(jbcm1, getHandler, id2);
+         if (getHandler.getCheckedAttributes() != null && value.equals(getHandler.getCheckedAttributes().get("count")))
+         {
+            found = true;
+            break;
+         }
+         Thread.sleep(50);            
+      }
+      assertTrue("sessions replicated", found);
+      
+      jbcm0.stop();
+      
+      int THREADS = 10;
+      threadPool = Executors.newFixedThreadPool(THREADS);
+      
+      CountDownLatch startingGun = new CountDownLatch(THREADS + 1);
+      CountDownLatch finishedSignal = new CountDownLatch(THREADS);
+      ConcurrentRequestHandler concurrentHandler = new ConcurrentRequestHandler();
+      Valve pipelineHead = SessionTestUtil.setupPipeline(jbcm1, concurrentHandler);
+      Loader[] loaders = new Loader[THREADS];
+      
+      for (int i = 0; i < loaders.length; i++)
+      {
+         loaders[i] = new Loader(pipelineHead, concurrentHandler, jbcm1, id1, attrs.keySet(), startingGun, finishedSignal);
+         threadPool.execute(loaders[i]);
+      }
+      
+      startingGun.countDown();
+      
+      assertTrue("loaders completed on time", finishedSignal.await(45, TimeUnit.SECONDS));     
+      
+      for (int i = 0; i < loaders.length; i++)
+      {         
+         assertNotNull("got checked attributes for " + i, loaders[i].checkedAttributes);
+         assertTrue("checked 'count' attribute for " + i, loaders[i].checkedAttributes.containsKey("count"));
+         assertEquals("correct value for " + i, value, loaders[i].checkedAttributes.get("count"));
+      }
+   }
+   
+   private static class Loader implements Runnable
+   {
+      private final Valve pipelineHead;
+      private final ConcurrentRequestHandler concurrentHandler;
+      private final Manager manager;
+      private final String sessionId;
+      private final Set<String> attributeKeys;
+      private final CountDownLatch startingGun;
+      private final CountDownLatch finishedSignal;
+      
+      private Map<String, Object> checkedAttributes;
+
+      private Loader(Valve pipelineHead, ConcurrentRequestHandler concurrentHandler,
+            Manager manager, String sessionId, Set<String> attributeKeys, 
+            CountDownLatch startingGun, CountDownLatch finishedSignal)
+      {
+         this.pipelineHead = pipelineHead;
+         this.concurrentHandler = concurrentHandler;
+         this.manager = manager;
+         this.sessionId = sessionId;
+         this.attributeKeys = attributeKeys;
+         this.startingGun = startingGun;
+         this.finishedSignal = finishedSignal;
+      }
+      
+      public void run()
+      {
+         try
+         {
+            BasicRequestHandler getHandler = new BasicRequestHandler(attributeKeys, false);
+            concurrentHandler.registerHandler(getHandler);
+            Request request = SessionTestUtil.setupRequest(manager, sessionId);
+            startingGun.countDown();
+            startingGun.await();
+            System.out.println("started");
+            
+            SessionTestUtil.invokeRequest(pipelineHead, request);
+            this.checkedAttributes = getHandler.getCheckedAttributes();
+            if (this.checkedAttributes != null)
+            {
+               System.out.println(this.checkedAttributes.keySet());
+            }
+         }
+         catch (Exception e)
+         {
+            e.printStackTrace(System.out);
+         }
+         finally
+         {
+            finishedSignal.countDown();
+            
+            concurrentHandler.unregisterHandler();
+         }
+         
+      }
+      
+   }
+}

Modified: branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/defaultcfg/simpleweb/test/JvmRouteValveUnitTestCase.java
===================================================================
--- branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/defaultcfg/simpleweb/test/JvmRouteValveUnitTestCase.java	2010-02-03 02:29:36 UTC (rev 100314)
+++ branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/defaultcfg/simpleweb/test/JvmRouteValveUnitTestCase.java	2010-02-03 04:12:56 UTC (rev 100315)
@@ -27,8 +27,8 @@
 import org.apache.catalina.Session;
 import org.apache.catalina.connector.Response;
 import org.jboss.logging.Logger;
-import org.jboss.test.cluster.web.jvmroute.MockJBossManager;
 import org.jboss.test.cluster.web.jvmroute.MockRequest;
+import org.jboss.test.cluster.web.mocks.MockClusteredManager;
 import org.jboss.test.cluster.web.mocks.MockValve;
 import org.jboss.web.tomcat.service.session.JvmRouteValve;
 
@@ -64,7 +64,7 @@
    {
       log.info("Enter testNonFailover");
       
-      MockJBossManager mgr = new MockJBossManager();
+      MockClusteredManager mgr = new MockClusteredManager();
       mgr.setJvmRoute(JVM_ROUTE);
        
       JvmRouteValve jvmRouteValve = new JvmRouteValve(mgr);
@@ -92,7 +92,7 @@
    {
       log.info("Enter testFailover");
       
-      MockJBossManager mgr = new MockJBossManager();
+      MockClusteredManager mgr = new MockClusteredManager();
       mgr.setJvmRoute(JVM_ROUTE);
        
       JvmRouteValve jvmRouteValve = new JvmRouteValve(mgr);
@@ -121,7 +121,7 @@
    {
       log.info("Enter testFailoverFromURL");
       
-      MockJBossManager mgr = new MockJBossManager();
+      MockClusteredManager mgr = new MockClusteredManager();
       mgr.setJvmRoute(JVM_ROUTE);
        
       JvmRouteValve jvmRouteValve = new JvmRouteValve(mgr);
@@ -150,7 +150,7 @@
    {
       log.info("Enter testFailoverMismatchBadReq");
       
-      MockJBossManager mgr = new MockJBossManager();
+      MockClusteredManager mgr = new MockClusteredManager();
       mgr.setJvmRoute(JVM_ROUTE);
        
       JvmRouteValve jvmRouteValve = new JvmRouteValve(mgr);
@@ -178,7 +178,7 @@
    {
       log.info("Enter testFailoverMismatchBadReqFromURL");
       
-      MockJBossManager mgr = new MockJBossManager();
+      MockClusteredManager mgr = new MockClusteredManager();
       mgr.setJvmRoute(JVM_ROUTE);
        
       JvmRouteValve jvmRouteValve = new JvmRouteValve(mgr);
@@ -207,7 +207,7 @@
    {
       log.info("Enter testFailoverMismatchBadSession");
       
-      MockJBossManager mgr = new MockJBossManager();
+      MockClusteredManager mgr = new MockClusteredManager();
       mgr.setJvmRoute(JVM_ROUTE);
        
       JvmRouteValve jvmRouteValve = new JvmRouteValve(mgr);
@@ -235,7 +235,7 @@
    {
       log.info("Enter testFailoverMismatchBadSessionFromURL");
       
-      MockJBossManager mgr = new MockJBossManager();
+      MockClusteredManager mgr = new MockClusteredManager();
       mgr.setJvmRoute(JVM_ROUTE);
        
       JvmRouteValve jvmRouteValve = new JvmRouteValve(mgr);
@@ -264,7 +264,7 @@
    {
       log.info("Enter testNoSession");
       
-      MockJBossManager mgr = new MockJBossManager();
+      MockClusteredManager mgr = new MockClusteredManager();
       mgr.setJvmRoute(JVM_ROUTE);
        
       JvmRouteValve jvmRouteValve = new JvmRouteValve(mgr);
@@ -290,7 +290,7 @@
    {
       log.info("Enter testNoSessionFromURL");
       
-      MockJBossManager mgr = new MockJBossManager();
+      MockClusteredManager mgr = new MockClusteredManager();
       mgr.setJvmRoute(JVM_ROUTE);
        
       JvmRouteValve jvmRouteValve = new JvmRouteValve(mgr);
@@ -317,7 +317,7 @@
    {
       log.info("Enter testFailoverNoSession");
       
-      MockJBossManager mgr = new MockJBossManager();
+      MockClusteredManager mgr = new MockClusteredManager();
       mgr.setJvmRoute(JVM_ROUTE);
        
       JvmRouteValve jvmRouteValve = new JvmRouteValve(mgr);
@@ -344,7 +344,7 @@
    {
       log.info("Enter testNoSessionNoRequestedSession");
       
-      MockJBossManager mgr = new MockJBossManager();
+      MockClusteredManager mgr = new MockClusteredManager();
       mgr.setJvmRoute(JVM_ROUTE);
        
       JvmRouteValve jvmRouteValve = new JvmRouteValve(mgr);
@@ -370,7 +370,7 @@
    {
       log.info("Enter testSessionNoRequestedSession");
       
-      MockJBossManager mgr = new MockJBossManager();
+      MockClusteredManager mgr = new MockClusteredManager();
       mgr.setJvmRoute(JVM_ROUTE);
        
       JvmRouteValve jvmRouteValve = new JvmRouteValve(mgr);
@@ -397,7 +397,7 @@
    {
       log.info("Enter testSessionNoRequestedSessionFromURL");
       
-      MockJBossManager mgr = new MockJBossManager();
+      MockClusteredManager mgr = new MockClusteredManager();
       mgr.setJvmRoute(JVM_ROUTE);
        
       JvmRouteValve jvmRouteValve = new JvmRouteValve(mgr);
@@ -425,7 +425,7 @@
    {
       log.info("Enter testFailoverSessionNoRequestedSession");
       
-      MockJBossManager mgr = new MockJBossManager();
+      MockClusteredManager mgr = new MockClusteredManager();
       mgr.setJvmRoute(JVM_ROUTE);
        
       JvmRouteValve jvmRouteValve = new JvmRouteValve(mgr);
@@ -452,7 +452,7 @@
    {
       log.info("Enter testFailoverSessionNoRequestedSessionFromURL");
       
-      MockJBossManager mgr = new MockJBossManager();
+      MockClusteredManager mgr = new MockClusteredManager();
       mgr.setJvmRoute(JVM_ROUTE);
        
       JvmRouteValve jvmRouteValve = new JvmRouteValve(mgr);
@@ -480,7 +480,7 @@
    {
       log.info("Enter testNoJvmRouteSession");
       
-      MockJBossManager mgr = new MockJBossManager();
+      MockClusteredManager mgr = new MockClusteredManager();
       mgr.setJvmRoute(JVM_ROUTE);
        
       JvmRouteValve jvmRouteValve = new JvmRouteValve(mgr);
@@ -508,7 +508,7 @@
    {
       log.info("Enter testNoJvmRouteSessionFromURL");
       
-      MockJBossManager mgr = new MockJBossManager();
+      MockClusteredManager mgr = new MockClusteredManager();
       mgr.setJvmRoute(JVM_ROUTE);
        
       JvmRouteValve jvmRouteValve = new JvmRouteValve(mgr);
@@ -537,7 +537,7 @@
    {
       log.info("Enter testNoJvmRouteRequest");
       
-      MockJBossManager mgr = new MockJBossManager();
+      MockClusteredManager mgr = new MockClusteredManager();
       mgr.setJvmRoute(JVM_ROUTE);
        
       JvmRouteValve jvmRouteValve = new JvmRouteValve(mgr);
@@ -565,7 +565,7 @@
    {
       log.info("Enter testNoJvmRouteRequest");
       
-      MockJBossManager mgr = new MockJBossManager();
+      MockClusteredManager mgr = new MockClusteredManager();
       mgr.setJvmRoute(JVM_ROUTE);
        
       JvmRouteValve jvmRouteValve = new JvmRouteValve(mgr);
@@ -594,7 +594,7 @@
    {
       log.info("Enter testJvmRouteIncludesDomain");
       
-      MockJBossManager mgr = new MockJBossManager();
+      MockClusteredManager mgr = new MockClusteredManager();
       mgr.setJvmRoute(DOMAIN_JVM_ROUTE);
        
       JvmRouteValve jvmRouteValve = new JvmRouteValve(mgr);

Added: branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/testutil/JBossCacheUtil.java
===================================================================
--- branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/testutil/JBossCacheUtil.java	                        (rev 0)
+++ branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/testutil/JBossCacheUtil.java	2010-02-03 04:12:56 UTC (rev 100315)
@@ -0,0 +1,175 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009 Red Hat, Inc. 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.cluster.testutil;
+
+import java.util.List;
+
+import org.jboss.cache.Cache;
+import org.jboss.cache.CacheSPI;
+
+/**
+ * Utilities related to dealing with JBoss Cache.
+ *
+ * @author Brian Stansberry
+ * 
+ * @version $Revision: $
+ */
+public class JBossCacheUtil
+{
+
+   /**
+    * Loops, continually calling {@link #areCacheViewsComplete(org.jboss.cache.Cache[])}
+    * until it either returns true or <code>timeout</code> ms have elapsed.
+    *
+    * @param caches  caches which must all have consistent views
+    * @param timeout max number of ms to loop
+    * @throws RuntimeException if <code>timeout</code> ms have elapse without
+    *                          all caches having the same number of members.
+    */
+   public static void blockUntilViewsReceived(Cache[] caches, long timeout)
+   {
+      long failTime = System.currentTimeMillis() + timeout;
+
+      while (System.currentTimeMillis() < failTime)
+      {
+         sleepThread(100);
+         if (areCacheViewsComplete(caches))
+         {
+            return;
+         }
+      }
+
+      throw new RuntimeException("timed out before caches had complete views" + views(caches));
+   }
+
+   /**
+    * Checks each cache to see if the number of elements in the array
+    * returned by {@link CacheSPI#getMembers()} matches the size of
+    * the <code>caches</code> parameter.
+    *
+    * @param caches caches that should form a View
+    * @return <code>true</code> if all caches have
+    *         <code>caches.length</code> members; false otherwise
+    * @throws IllegalStateException if any of the caches have MORE view
+    *                               members than caches.length
+    */
+   public static boolean areCacheViewsComplete(Cache[] caches)
+   {
+      return areCacheViewsComplete(caches, true);
+   }
+
+   public static boolean areCacheViewsComplete(Cache[] caches, boolean barfIfTooManyMembers)
+   {
+      int memberCount = caches.length;
+
+      for (int i = 0; i < memberCount; i++)
+      {
+         if (!isCacheViewComplete(caches[i], memberCount, barfIfTooManyMembers))
+         {
+            return false;
+         }
+      }
+
+      return true;
+   }
+
+   public static boolean isCacheViewComplete(Cache c, int memberCount)
+   {
+      return isCacheViewComplete(c, memberCount, true);
+   }
+
+   public static boolean isCacheViewComplete(Cache cache, int memberCount, boolean barfIfTooManyMembers)
+   {
+      List members = cache.getMembers();
+      if (members == null || memberCount > members.size())
+      {
+         return false;
+      }
+      else if (memberCount < members.size())
+      {
+         if (barfIfTooManyMembers)
+         {
+            // This is an exceptional condition
+            StringBuilder sb = new StringBuilder("Cache at address ");
+            sb.append(cache.getLocalAddress());
+            sb.append(" had ");
+            sb.append(members.size());
+            sb.append(" members; expecting ");
+            sb.append(memberCount);
+            sb.append(". Members were (");
+            for (int j = 0; j < members.size(); j++)
+            {
+               if (j > 0)
+               {
+                  sb.append(", ");
+               }
+               sb.append(members.get(j));
+            }
+            sb.append(')');
+
+            throw new IllegalStateException(sb.toString());
+         }
+         else return false;
+      }
+
+      return true;
+   }
+
+
+   /**
+    * Puts the current thread to sleep for the desired number of ms, suppressing
+    * any exceptions.
+    *
+    * @param sleeptime number of ms to sleep
+    */
+   public static void sleepThread(long sleeptime)
+   {
+      try
+      {
+         Thread.sleep(sleeptime);
+      }
+      catch (InterruptedException ie)
+      {
+      }
+   }
+
+   private static String views(Cache... caches)
+   {
+      StringBuilder builder = new StringBuilder("[\n");
+      for (Cache c:caches)
+      {
+         builder.append("   ").append(c.getLocalAddress()).append("->").append(c.getMembers()).append("\n");
+      }
+      builder.append("]");
+      return builder.toString();
+   }
+
+   /**
+    * Prevent instantiation 
+    */
+   private JBossCacheUtil()
+   {
+      // TODO Auto-generated constructor stub
+   }
+
+}

Modified: branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/testutil/SessionTestUtil.java
===================================================================
--- branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/testutil/SessionTestUtil.java	2010-02-03 02:29:36 UTC (rev 100314)
+++ branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/testutil/SessionTestUtil.java	2010-02-03 04:12:56 UTC (rev 100315)
@@ -34,6 +34,7 @@
 import org.apache.catalina.Manager;
 import org.apache.catalina.Pipeline;
 import org.apache.catalina.Valve;
+import org.apache.catalina.connector.Request;
 import org.apache.catalina.connector.Response;
 import org.apache.catalina.core.StandardContext;
 import org.apache.commons.httpclient.Cookie;
@@ -92,11 +93,22 @@
          e.printStackTrace();
       }
    }
+   
    public static JBossCacheManager createManager(String warName, int maxInactiveInterval, 
                                                  boolean local, String passivationDir, 
                                                  boolean totalReplication, boolean marshalling, 
                                                  String jvmRoute, Set<PojoCache> allCaches)
    {
+      return createManager(warName, maxInactiveInterval, local, passivationDir, 
+                           totalReplication, marshalling, false, jvmRoute, allCaches);
+   }
+   
+   public static JBossCacheManager createManager(String warName, int maxInactiveInterval, 
+                                                 boolean local, String passivationDir, 
+                                                 boolean totalReplication, boolean marshalling,
+                                                 boolean purgeCacheLoader,
+                                                 String jvmRoute, Set<PojoCache> allCaches)
+   {
       PojoCache cache = createCache(local, passivationDir, totalReplication, marshalling, allCaches);
       return createManager(warName, maxInactiveInterval, cache, jvmRoute);
    }
@@ -113,15 +125,7 @@
       JBossCacheManager jbcm = new JBossCacheManager(distributedManagerFactory);
       jbcm.setSnapshotMode(SnapshotMode.INSTANT);
       
-      MockEngine engine = new MockEngine();
-      engine.setJvmRoute(jvmRoute);
-      MockHost host = new MockHost();
-      engine.addChild(host);
-      host.setName("localhost");
-      StandardContext container = new StandardContext();
-      container.setName(warName);
-      host.addChild(container);
-      container.setManager(jbcm);
+      setupContainer(warName, jvmRoute, jbcm);
       
       // Do this after assigning the manager to the container, or else
       // the container's setting will override ours
@@ -134,7 +138,13 @@
    public static PojoCache createCache(boolean local, String passivationDir, 
          boolean totalReplication, boolean marshalling, Set<PojoCache> allCaches)
    {
-      Configuration cfg = getConfiguration(local, passivationDir, totalReplication, marshalling);
+      return createCache(local, passivationDir, totalReplication, marshalling, false, allCaches);
+   }
+   
+   public static PojoCache createCache(boolean local, String passivationDir, 
+         boolean totalReplication, boolean marshalling, boolean purgeCacheLoader, Set<PojoCache> allCaches)
+   {
+      Configuration cfg = getConfiguration(local, passivationDir, totalReplication, marshalling, purgeCacheLoader);
       PojoCache cache = PojoCacheFactory.createCache(cfg, true);
       
       if (allCaches != null)
@@ -143,7 +153,7 @@
    }
    
    public static Configuration getConfiguration(boolean local, String passivationDir, 
-         boolean totalReplication, boolean marshalling)
+         boolean totalReplication, boolean marshalling, boolean purgeCacheLoader)
    {
       PojoCache temp = PojoCacheFactory.createCache(CONFIG_LOCATION, false);
       Configuration config = temp.getCache().getConfiguration();
@@ -160,6 +170,7 @@
          fclc.setProperties(clc.getFirstCacheLoaderConfig().getProperties());
          fclc.setLocation(passivationDir);
          fclc.setFetchPersistentState(true);
+         fclc.setPurgeOnStartup(purgeCacheLoader);
          ArrayList<IndividualCacheLoaderConfig> iclcs = new ArrayList<IndividualCacheLoaderConfig>();
          iclcs.add(fclc);
          clc.setIndividualCacheLoaderConfigs(iclcs);
@@ -197,6 +208,19 @@
    {
       distributedManagerFactory.clearCaches();
    }
+
+   public static void setupContainer(String warName, String jvmRoute, Manager mgr)
+   {
+      MockEngine engine = new MockEngine();
+      engine.setJvmRoute(jvmRoute);
+      MockHost host = new MockHost();
+      engine.addChild(host);
+      host.setName("localhost");
+      StandardContext container = new StandardContext();
+      container.setName(warName);
+      host.addChild(container);
+      container.setManager(mgr);
+   }
    
    public static JBossWebMetaData createWebMetaData(int maxSessions)
    {
@@ -249,12 +273,14 @@
       throws ServletException, IOException
    {
       Valve valve = setupPipeline(manager, handler);
-      MockRequest request = new MockRequest();
-      request.setRequestedSessionId(sessionId);
-      request.setContext((Context) manager.getContainer());
-      Response response = new Response();
-      request.setResponse(response);
-      valve.invoke(request, response);
+      Request request = setupRequest(manager, sessionId);
+      invokeRequest(valve, request);
+   }
+   
+   public static void invokeRequest(Valve pipelineHead, Request request)
+      throws ServletException, IOException
+   {
+      pipelineHead.invoke(request, request.getResponse());
       // StandardHostValve calls request.getSession(false) on way out, so we will too
       request.getSession(false);
       request.recycle();
@@ -289,6 +315,17 @@
       return pipeline.getFirst();
    }
    
+   public static Request setupRequest(Manager manager, String sessionId)
+   {
+      MockRequest request = new MockRequest();
+      request.setRequestedSessionId(sessionId);
+      request.setContext((Context) manager.getContainer());
+      Response response = new Response();
+      request.setResponse(response);
+      return request;
+      
+   }
+   
    public static void cleanupPipeline(Manager manager)
    {
       Pipeline pipeline = manager.getContainer().getPipeline();
@@ -504,7 +541,7 @@
    {
       return Integer.valueOf(value);
    }
-   
+
    public static void cleanPassivationDir(File root)
    {
 	   if (root.exists())

Deleted: branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/web/jvmroute/MockDistributedCacheManager.java
===================================================================
--- branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/web/jvmroute/MockDistributedCacheManager.java	2010-02-03 02:29:36 UTC (rev 100314)
+++ branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/web/jvmroute/MockDistributedCacheManager.java	2010-02-03 04:12:56 UTC (rev 100315)
@@ -1,165 +0,0 @@
-/*
- * 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.cluster.web.jvmroute;
-
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
-
-import org.jboss.web.tomcat.service.session.distributedcache.spi.BatchingManager;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.IncomingDistributableSessionData;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingDistributableSessionData;
-
-/**
- * @author Brian Stansberry
- *
- */
-public class MockDistributedCacheManager implements DistributedCacheManager<OutgoingDistributableSessionData>
-{
-   public static final MockDistributedCacheManager INSTANCE = new MockDistributedCacheManager();
-   
-
-   public void evictSession(String realId)
-   {
-      // no-op
-   }
-
-   public void evictSession(String realId, String dataOwner)
-   {
-      // no-op
-   }
-
-   public Object getAttribute(String realId, String key)
-   {
-      return null;
-   }
-
-   public Set<String> getAttributeKeys(String realId)
-   {
-      return Collections.emptySet();
-   }
-
-   public Map<String, Object> getAttributes(String realId)
-   {
-      return Collections.emptyMap();
-   }
-
-   public BatchingManager getBatchingManager()
-   {
-      return null;
-   }
-
-   public IncomingDistributableSessionData getSessionData(String realId, boolean initialLoad)
-   {
-      return null;
-   }
-
-   public IncomingDistributableSessionData getSessionData(String realId, String dataOwner, boolean includeAttributes)
-   {
-      return null;
-   }
-
-   public Map<String, String> getSessionIds()
-   {
-      return Collections.emptyMap();
-   }
-
-   public boolean isPassivationEnabled()
-   {
-      return false;
-   }
-
-   public void putAttribute(String realId, Map<String, Object> map)
-   {
-      // no-op
-   }
-
-   public void putAttribute(String realId, String key, Object value)
-   {
-      // no-op
-   }
-   
-   
-
-   public Object removeAttribute(String realId, String key)
-   {
-      return null;
-   }
-
-   public void removeAttributeLocal(String realId, String key)
-   {
-   // no-op
-   }
-
-   public void removeAttributes(String realId)
-   {
-      // no-op
-   }
-
-   public void removeAttributesLocal(String realId)
-   {
-      // no-op
-   }
-
-   public void removeSession(String realId)
-   {
-      // no-op
-   }
-
-   public void removeSessionLocal(String realId)
-   {
-      // no-op
-   }
-
-   public void removeSessionLocal(String realId, String dataOwner)
-   {
-      // no-op
-   }
-
-   public void start()
-   {
-      // no-op
-   }
-
-   public void stop()
-   {
-      // no-op
-   }
-
-   public boolean getSupportsAttributeOperations()
-   {
-      return true;
-   }
-
-   public void sessionCreated(String realId)
-   {
-      // no-op
-   }
-
-   public void storeSessionData(OutgoingDistributableSessionData sessionData)
-   {
-      // no-op      
-   }
-
-}

Deleted: branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/web/jvmroute/MockJBossManager.java
===================================================================
--- branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/web/jvmroute/MockJBossManager.java	2010-02-03 02:29:36 UTC (rev 100314)
+++ branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/web/jvmroute/MockJBossManager.java	2010-02-03 04:12:56 UTC (rev 100315)
@@ -1,276 +0,0 @@
-/*
- * 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.cluster.web.jvmroute;
-
-import java.beans.PropertyChangeListener;
-import java.io.IOException;
-
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.catalina.Container;
-import org.apache.catalina.Session;
-import org.jboss.metadata.web.jboss.JBossWebMetaData;
-import org.jboss.metadata.web.jboss.ReplicationTrigger;
-import org.jboss.web.tomcat.service.session.ClusteredManager;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.ClusteringNotSupportedException;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingDistributableSessionData;
-import org.jboss.web.tomcat.service.session.notification.ClusteredSessionNotificationPolicy;
-import org.jboss.web.tomcat.service.session.notification.LegacyClusteredSessionNotificationPolicy;
-
-/**
- * @author Brian Stansberry
- *
- */
-public class MockJBossManager implements ClusteredManager<OutgoingDistributableSessionData>
-{
-   private String jvmRoute = null;
-   private String newCookieIdSession = null;
-   private Session session = null;
-   
-   /**
-    * Create a new MockJBossManager.
-    * 
-    */
-   public MockJBossManager()
-   {      
-   }
-
-   public String getJvmRoute()
-   {
-      return jvmRoute;
-   }
-   
-   public void setJvmRoute(String jvmRoute)
-   {
-      this.jvmRoute = jvmRoute;
-   }
-
-   public void setNewSessionCookie(String sessionId, HttpServletResponse response)
-   {
-      newCookieIdSession = sessionId;
-   }
-   
-   public String getNewCookieIdSession()
-   {
-      return newCookieIdSession;
-   }
-
-   public Session createSession(String s)
-   {
-      Session session = new MockSession(this);
-      session.setId(s);
-      return session;
-   }
-
-   public Session findSession(String s) throws IOException
-   {
-      return session;
-   }
-   
-   public void add(Session session)
-   {
-      this.session = session;
-   }
-
-   public ReplicationTrigger getReplicationTrigger()
-   {
-      return ReplicationTrigger.SET_AND_NON_PRIMITIVE_GET;
-   }
-
-   public void init(String name, JBossWebMetaData webMetaData) throws ClusteringNotSupportedException
-   {      
-
-   }
-
-   public void removeLocal(Session session)
-   {
-   }
-
-   public boolean storeSession(Session session)
-   {
-      return false;
-   }
-
-   public void addPropertyChangeListener(PropertyChangeListener propertychangelistener)
-   {
-   }
-
-   public void backgroundProcess()
-   {
-   }
-
-   public Session createEmptySession()
-   {
-      return null;
-   }
-
-   public Session createSession()
-   {
-      return null;
-   }
-
-   public Session[] findSessions()
-   {
-      return null;
-   }
-
-   public int getActiveSessions()
-   {
-      return 0;
-   }
-
-   public Container getContainer()
-   {
-      return null;
-   }
-
-   public boolean getDistributable()
-   {
-      return false;
-   }
-
-   public int getExpiredSessions()
-   {
-      return 0;
-   }
-
-   public String getInfo()
-   {
-      return null;
-   }
-
-   public int getMaxActive()
-   {
-      return 0;
-   }
-
-   public int getMaxInactiveInterval()
-   {
-      return 0;
-   }
-
-   public int getRejectedSessions()
-   {
-      return 0;
-   }
-
-   public int getSessionAverageAliveTime()
-   {
-      return 0;
-   }
-
-   public int getSessionCounter()
-   {
-      return 0;
-   }
-
-   public int getSessionIdLength()
-   {
-      return 0;
-   }
-
-   public int getSessionMaxAliveTime()
-   {
-      return 0;
-   }
-
-   public void load() throws ClassNotFoundException, IOException
-   {
-   }
-
-   public void remove(Session session)
-   {
-   }
-
-   public void removePropertyChangeListener(PropertyChangeListener propertychangelistener)
-   {
-   }
-
-   public void setContainer(Container container)
-   {
-   }
-
-   public void setDistributable(boolean flag)
-   {
-   }
-
-   public void setExpiredSessions(int i)
-   {
-   }
-
-   public void setMaxActive(int i)
-   {
-   }
-   
-   public void setMaxInactiveInterval(int i)
-   {
-   }
-
-   public void setRejectedSessions(int i)
-   {
-   }
-
-   public void setSessionAverageAliveTime(int i)
-   {
-   }
-
-   public void setSessionCounter(int i)
-   {
-   }
-
-   public void setSessionIdLength(int i)
-   {
-   }
-
-   public void setSessionMaxAliveTime(int i)
-   {
-   }
-
-   public void unload() throws IOException
-   {
-   }
-
-   public DistributedCacheManager getDistributedCacheManager()
-   {
-      return MockDistributedCacheManager.INSTANCE;
-   }
-
-   public int getMaxUnreplicatedInterval()
-   {
-      return -1;
-   }
-
-   public ClusteredSessionNotificationPolicy getNotificationPolicy()
-   {
-      return new LegacyClusteredSessionNotificationPolicy();
-   }
-
-   public boolean getUseJK()
-   {
-      return true;
-   }
-   
-   
-
-}

Modified: branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/web/jvmroute/MockSession.java
===================================================================
--- branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/web/jvmroute/MockSession.java	2010-02-03 02:29:36 UTC (rev 100314)
+++ branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/web/jvmroute/MockSession.java	2010-02-03 04:12:56 UTC (rev 100315)
@@ -25,6 +25,7 @@
 import javax.servlet.http.HttpSession;
 
 import org.apache.catalina.session.StandardSessionFacade;
+import org.jboss.test.cluster.web.mocks.MockClusteredManager;
 import org.jboss.web.tomcat.service.session.ClusteredSession;
 import org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingDistributableSessionData;
 import org.jboss.web.tomcat.service.session.notification.ClusteredSessionNotificationCause;
@@ -43,7 +44,7 @@
     * 
     * @param manager
     */
-   public MockSession(MockJBossManager manager)
+   public MockSession(MockClusteredManager manager)
    {
       super(manager);
    }

Added: branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/web/mocks/ConcurrentRequestHandler.java
===================================================================
--- branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/web/mocks/ConcurrentRequestHandler.java	                        (rev 0)
+++ branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/web/mocks/ConcurrentRequestHandler.java	2010-02-03 04:12:56 UTC (rev 100315)
@@ -0,0 +1,72 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009 Red Hat, Inc. 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.cluster.web.mocks;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+
+/**
+ * Uses a ThreadLocal to allow a single RequestHandlerValve to concurrently
+ * handle requests.
+ *
+ * @author Brian Stansberry
+ * 
+ * @version $Revision: $
+ */
+public class ConcurrentRequestHandler implements RequestHandler
+{
+   private final ThreadLocal<RequestHandler> threadHandler = new ThreadLocal<RequestHandler>();
+   private final Set<RequestHandler> handlers = new HashSet<RequestHandler>();
+   
+   public void registerHandler(RequestHandler handler)
+   {
+      threadHandler.set(handler);
+   }
+   
+   public void unregisterHandler()
+   {
+      threadHandler.remove();
+   }
+   
+   public void clear()
+   {
+      for (RequestHandler handler : handlers)
+      {
+         handler.clear();
+      }
+   }
+
+   public void handleRequest(Request request, Response response)
+   {
+      RequestHandler handler = threadHandler.get();
+      if (handler == null)
+      {
+         throw new IllegalStateException("No handler; call registerHandler before executing requet");
+      }
+      handler.handleRequest(request, response);      
+   }
+
+}

Added: branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/web/mocks/MockClusteredManager.java
===================================================================
--- branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/web/mocks/MockClusteredManager.java	                        (rev 0)
+++ branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/web/mocks/MockClusteredManager.java	2010-02-03 04:12:56 UTC (rev 100315)
@@ -0,0 +1,277 @@
+/*
+ * 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.cluster.web.mocks;
+
+import java.beans.PropertyChangeListener;
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.catalina.Container;
+import org.apache.catalina.Session;
+import org.jboss.metadata.web.jboss.JBossWebMetaData;
+import org.jboss.metadata.web.jboss.ReplicationTrigger;
+import org.jboss.test.cluster.web.jvmroute.MockSession;
+import org.jboss.web.tomcat.service.session.ClusteredManager;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.ClusteringNotSupportedException;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingDistributableSessionData;
+import org.jboss.web.tomcat.service.session.notification.ClusteredSessionNotificationPolicy;
+import org.jboss.web.tomcat.service.session.notification.LegacyClusteredSessionNotificationPolicy;
+
+/**
+ * @author Brian Stansberry
+ *
+ */
+public class MockClusteredManager implements ClusteredManager<OutgoingDistributableSessionData>
+{
+   private String jvmRoute = null;
+   private String newCookieIdSession = null;
+   private Session session = null;
+   
+   /**
+    * Create a new MockJBossManager.
+    * 
+    */
+   public MockClusteredManager()
+   {      
+   }
+
+   public String getJvmRoute()
+   {
+      return jvmRoute;
+   }
+   
+   public void setJvmRoute(String jvmRoute)
+   {
+      this.jvmRoute = jvmRoute;
+   }
+
+   public void setNewSessionCookie(String sessionId, HttpServletResponse response)
+   {
+      newCookieIdSession = sessionId;
+   }
+   
+   public String getNewCookieIdSession()
+   {
+      return newCookieIdSession;
+   }
+
+   public Session createSession(String s)
+   {
+      Session session = new MockSession(this);
+      session.setId(s);
+      return session;
+   }
+
+   public Session findSession(String s) throws IOException
+   {
+      return session;
+   }
+   
+   public void add(Session session)
+   {
+      this.session = session;
+   }
+
+   public ReplicationTrigger getReplicationTrigger()
+   {
+      return ReplicationTrigger.SET_AND_NON_PRIMITIVE_GET;
+   }
+
+   public void init(String name, JBossWebMetaData webMetaData) throws ClusteringNotSupportedException
+   {      
+
+   }
+
+   public void removeLocal(Session session)
+   {
+   }
+
+   public boolean storeSession(Session session)
+   {
+      return false;
+   }
+
+   public void addPropertyChangeListener(PropertyChangeListener propertychangelistener)
+   {
+   }
+
+   public void backgroundProcess()
+   {
+   }
+
+   public Session createEmptySession()
+   {
+      return null;
+   }
+
+   public Session createSession()
+   {
+      return null;
+   }
+
+   public Session[] findSessions()
+   {
+      return null;
+   }
+
+   public int getActiveSessions()
+   {
+      return 0;
+   }
+
+   public Container getContainer()
+   {
+      return null;
+   }
+
+   public boolean getDistributable()
+   {
+      return false;
+   }
+
+   public int getExpiredSessions()
+   {
+      return 0;
+   }
+
+   public String getInfo()
+   {
+      return null;
+   }
+
+   public int getMaxActive()
+   {
+      return 0;
+   }
+
+   public int getMaxInactiveInterval()
+   {
+      return 0;
+   }
+
+   public int getRejectedSessions()
+   {
+      return 0;
+   }
+
+   public int getSessionAverageAliveTime()
+   {
+      return 0;
+   }
+
+   public int getSessionCounter()
+   {
+      return 0;
+   }
+
+   public int getSessionIdLength()
+   {
+      return 0;
+   }
+
+   public int getSessionMaxAliveTime()
+   {
+      return 0;
+   }
+
+   public void load() throws ClassNotFoundException, IOException
+   {
+   }
+
+   public void remove(Session session)
+   {
+   }
+
+   public void removePropertyChangeListener(PropertyChangeListener propertychangelistener)
+   {
+   }
+
+   public void setContainer(Container container)
+   {
+   }
+
+   public void setDistributable(boolean flag)
+   {
+   }
+
+   public void setExpiredSessions(int i)
+   {
+   }
+
+   public void setMaxActive(int i)
+   {
+   }
+   
+   public void setMaxInactiveInterval(int i)
+   {
+   }
+
+   public void setRejectedSessions(int i)
+   {
+   }
+
+   public void setSessionAverageAliveTime(int i)
+   {
+   }
+
+   public void setSessionCounter(int i)
+   {
+   }
+
+   public void setSessionIdLength(int i)
+   {
+   }
+
+   public void setSessionMaxAliveTime(int i)
+   {
+   }
+
+   public void unload() throws IOException
+   {
+   }
+
+   public DistributedCacheManager getDistributedCacheManager()
+   {
+      return MockDistributedCacheManager.INSTANCE;
+   }
+
+   public int getMaxUnreplicatedInterval()
+   {
+      return -1;
+   }
+
+   public ClusteredSessionNotificationPolicy getNotificationPolicy()
+   {
+      return new LegacyClusteredSessionNotificationPolicy();
+   }
+
+   public boolean getUseJK()
+   {
+      return true;
+   }
+   
+   
+
+}

Added: branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/web/mocks/MockDistributedCacheManager.java
===================================================================
--- branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/web/mocks/MockDistributedCacheManager.java	                        (rev 0)
+++ branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/web/mocks/MockDistributedCacheManager.java	2010-02-03 04:12:56 UTC (rev 100315)
@@ -0,0 +1,195 @@
+/*
+ * 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.cluster.web.mocks;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import org.jboss.web.tomcat.service.session.distributedcache.spi.BatchingManager;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.IncomingDistributableSessionData;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingDistributableSessionData;
+
+/**
+ * @author Brian Stansberry
+ *
+ */
+public class MockDistributedCacheManager implements DistributedCacheManager<OutgoingDistributableSessionData>
+{
+   public static final MockDistributedCacheManager INSTANCE = new MockDistributedCacheManager();
+   
+
+   public void evictSession(String realId)
+   {
+      // no-op
+   }
+
+   public void evictSession(String realId, String dataOwner)
+   {
+      // no-op
+   }
+
+   public Object getAttribute(String realId, String key)
+   {
+      return null;
+   }
+
+   public Set<String> getAttributeKeys(String realId)
+   {
+      return Collections.emptySet();
+   }
+
+   public Map<String, Object> getAttributes(String realId)
+   {
+      return Collections.emptyMap();
+   }
+
+   public BatchingManager getBatchingManager()
+   {
+      return MockBatchingManager.INSTANCE;
+   }
+
+   public IncomingDistributableSessionData getSessionData(String realId, boolean initialLoad)
+   {
+      return null;
+   }
+
+   public IncomingDistributableSessionData getSessionData(String realId, String dataOwner, boolean includeAttributes)
+   {
+      return null;
+   }
+
+   public Map<String, String> getSessionIds()
+   {
+      return Collections.emptyMap();
+   }
+
+   public boolean isPassivationEnabled()
+   {
+      return false;
+   }
+
+   public void putAttribute(String realId, Map<String, Object> map)
+   {
+      // no-op
+   }
+
+   public void putAttribute(String realId, String key, Object value)
+   {
+      // no-op
+   }
+   
+   
+
+   public Object removeAttribute(String realId, String key)
+   {
+      return null;
+   }
+
+   public void removeAttributeLocal(String realId, String key)
+   {
+   // no-op
+   }
+
+   public void removeAttributes(String realId)
+   {
+      // no-op
+   }
+
+   public void removeAttributesLocal(String realId)
+   {
+      // no-op
+   }
+
+   public void removeSession(String realId)
+   {
+      // no-op
+   }
+
+   public void removeSessionLocal(String realId)
+   {
+      // no-op
+   }
+
+   public void removeSessionLocal(String realId, String dataOwner)
+   {
+      // no-op
+   }
+
+   public void start()
+   {
+      // no-op
+   }
+
+   public void stop()
+   {
+      // no-op
+   }
+
+   public boolean getSupportsAttributeOperations()
+   {
+      return true;
+   }
+
+   public void sessionCreated(String realId)
+   {
+      // no-op
+   }
+
+   public void storeSessionData(OutgoingDistributableSessionData sessionData)
+   {
+      // no-op      
+   }
+   
+   private static class MockBatchingManager implements BatchingManager
+   {
+      private static final MockBatchingManager INSTANCE = new MockBatchingManager();
+      
+      public void endBatch()
+      {
+         // TODO Auto-generated method stub
+         
+      }
+
+      public boolean isBatchInProgress() throws Exception
+      {
+         // TODO Auto-generated method stub
+         return false;
+      }
+
+      public void setBatchRollbackOnly() throws Exception
+      {
+         // TODO Auto-generated method stub
+         
+      }
+
+      public void startBatch() throws Exception
+      {
+         // TODO Auto-generated method stub
+         
+      }
+      
+   }
+
+}

Added: branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/web/mocks/MockDistributedCacheManagerFactory.java
===================================================================
--- branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/web/mocks/MockDistributedCacheManagerFactory.java	                        (rev 0)
+++ branches/JBPAPP_5_0/testsuite/src/main/org/jboss/test/cluster/web/mocks/MockDistributedCacheManagerFactory.java	2010-02-03 04:12:56 UTC (rev 100315)
@@ -0,0 +1,47 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009 Red Hat, Inc. 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.cluster.web.mocks;
+
+import org.jboss.web.tomcat.service.session.distributedcache.spi.ClusteringNotSupportedException;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManagerFactory;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.LocalDistributableSessionManager;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingDistributableSessionData;
+
+/**
+ *
+ *
+ * @author Brian Stansberry
+ * 
+ * @version $Revision: $
+ */
+public class MockDistributedCacheManagerFactory implements DistributedCacheManagerFactory
+{
+
+   public <T extends OutgoingDistributableSessionData> DistributedCacheManager<T> getDistributedCacheManager(
+         LocalDistributableSessionManager localManager) throws ClusteringNotSupportedException
+   {
+      return (DistributedCacheManager<T>) MockDistributedCacheManager.INSTANCE;
+   }
+
+}

Modified: branches/JBPAPP_5_0/tomcat/src/main/org/jboss/web/tomcat/service/session/ClusteredSession.java
===================================================================
--- branches/JBPAPP_5_0/tomcat/src/main/org/jboss/web/tomcat/service/session/ClusteredSession.java	2010-02-03 02:29:36 UTC (rev 100314)
+++ branches/JBPAPP_5_0/tomcat/src/main/org/jboss/web/tomcat/service/session/ClusteredSession.java	2010-02-03 04:12:56 UTC (rev 100315)
@@ -1310,7 +1310,9 @@
     */
    public boolean isOutdated()
    {
-      return thisAccessedTime < outdatedTime;
+      // if creationTime == 0 we've neither been synced with the
+      // distributed cache nor had creation time set (i.e. brand new session)
+      return thisAccessedTime < outdatedTime || this.creationTime == 0;
    } 
    
    public boolean isSessionDirty()

Modified: branches/JBPAPP_5_0/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheManager.java
===================================================================
--- branches/JBPAPP_5_0/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheManager.java	2010-02-03 02:29:36 UTC (rev 100314)
+++ branches/JBPAPP_5_0/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheManager.java	2010-02-03 04:12:56 UTC (rev 100315)
@@ -31,6 +31,7 @@
 import java.util.Set;
 import java.util.TreeSet;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -106,6 +107,13 @@
    /** Id/timestamp of sessions in distributedcache that we haven't loaded locally*/
    private Map<String, OwnedSessionUpdate> unloadedSessions_ = 
          new ConcurrentHashMap<String, OwnedSessionUpdate>();
+
+   /** 
+    * Sessions that have been created but not yet loaded. Used to ensure
+    * concurrent threads trying to load the same session
+    */
+   private final ConcurrentMap<String, ClusteredSession<? extends OutgoingDistributableSessionData>> embryonicSessions = 
+      new ConcurrentHashMap<String, ClusteredSession<? extends OutgoingDistributableSessionData>>();
    
    /** Number of passivated sessions */
    private AtomicInteger passivatedCount_ = new AtomicInteger();
@@ -2008,6 +2016,15 @@
                   // a replication message from another server
                   mustAdd = true;
                   session = createEmptyClusteredSession();
+
+                  // JBAS-7379 Ensure concurrent threads trying to load same session id
+                  // use the same session
+                  ClusteredSession<? extends OutgoingDistributableSessionData> embryo = 
+                     this.embryonicSessions.putIfAbsent(realId, session);
+                  if (embryo != null)
+                  {
+                     session = embryo;
+                  }
                   
                   OwnedSessionUpdate osu = unloadedSessions_.get(realId);
                   passivated = (osu != null && osu.isPassivated());
@@ -2015,6 +2032,14 @@
   
                synchronized (session)
                {
+                  // JBAS-7379 check if we lost the race to the sync block
+                  // and another thread has already loaded this session
+                  if (initialLoad && session.isOutdated() == false)
+                  {
+                     // some one else loaded this
+                     return session;
+                  }
+
                   ContextClassLoaderSwitcher.SwitchContext switcher = null; 
                   boolean doTx = false; 
                   boolean loadCompleted = false;




More information about the jboss-cvs-commits mailing list