[Jboss-cvs] JBossAS SVN: r55057 - branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/session

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Wed Aug 2 18:46:03 EDT 2006


Author: bstansberry at jboss.com
Date: 2006-08-02 18:46:02 -0400 (Wed, 02 Aug 2006)
New Revision: 55057

Modified:
   branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/session/ClusteredSessionValve.java
   branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/session/InstantSnapshotManager.java
   branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/session/IntervalSnapshotManager.java
   branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/session/JBossCacheManager.java
   branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/session/JBossManager.java
   branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/session/SnapshotManager.java
Log:
[JBAS-3318] Replicate all sessions affected by a cross-context call

Modified: branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/session/ClusteredSessionValve.java
===================================================================
--- branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/session/ClusteredSessionValve.java	2006-08-02 22:44:10 UTC (rev 55056)
+++ branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/session/ClusteredSessionValve.java	2006-08-02 22:46:02 UTC (rev 55057)
@@ -22,7 +22,6 @@
 package org.jboss.web.tomcat.tc5.session;
 
 import java.io.IOException;
-import javax.servlet.http.HttpSession;
 import javax.servlet.ServletException;
 
 import org.apache.catalina.*;
@@ -39,6 +38,7 @@
  * Lifecycle interface.
  *
  * @author Thomas Peuss <jboss at peuss.de>
+ * @author Brian Stansberry
  * @version $Revision$
  */
 public class ClusteredSessionValve extends ValveBase implements Lifecycle
@@ -46,28 +46,15 @@
    // The info string for this Valve
    private static final String info = "ClusteredSessionValve/1.0";
 
-   // The SnapshotManager that is associated with this Valve
-   protected SnapshotManager snapshot;
-
    // Valve-lifecycle_ helper object
    protected LifecycleSupport support = new LifecycleSupport(this);
 
-   // store the request and response object for parts of the clustering code that
-   // have no direct access to this objects
-   protected static final ThreadLocal requestThreadLocal = new ThreadLocal();
-   protected static final ThreadLocal responseThreadLocal = new ThreadLocal();
-   // Manager may store a ref to session id's it has handled here
-   protected static final ThreadLocal sessionIdThreadLocal = new ThreadLocal();
-
    /**
     * Create a new Valve.
-    *
-    * @param snapshot The SnapshotManager associated with this Valve
     */
-   public ClusteredSessionValve(SnapshotManager snapshot)
+   public ClusteredSessionValve()
    {
       super();
-      this.snapshot = snapshot;
    }
 
    /**
@@ -90,29 +77,28 @@
    {
       // Store the request and response object for the clustering code that has no direct access to
       // this objects
-      requestThreadLocal.set(request);
-      responseThreadLocal.set(response);
-
-      // let the servlet invocation go through
-      getNext().invoke(request, response);
-
-      // --> We are now after the servlet invocation
-
-      // Get the session
-      HttpSession session = request.getSession(false);
-
-      if (session != null && session.getId() != null)
-      {
-         // tell the snapshot manager that this session was modified
-         snapshot.snapshot(session.getId());
-      }
-
-      // don't leak references to the request and response objects
-      requestThreadLocal.set(null);
-      responseThreadLocal.set(null);
+      SessionReplicationContext.initContext(request, response);
       
-      // If JBossCacheManager stored a ref to a session id, we need to clear it
-      sessionIdThreadLocal.set(null);
+      try
+      {  
+         
+         
+         // let the servlet invocation go through
+         getNext().invoke(request, response);
+   
+         // --> We are now after the servlet invocation
+   
+         SessionReplicationContext[] sessions = SessionReplicationContext.getActiveSessions();
+         
+         for (int i = 0; i < sessions.length; i++)
+         {
+            sessions[i].getSnapshot().snapshot(sessions[i].getSessionId());
+         }
+      }
+      finally
+      {         
+         SessionReplicationContext.clearContext();
+      }
    }
 
    // Lifecylce-interface
@@ -133,14 +119,12 @@
 
    public void start() throws LifecycleException
    {
-      snapshot.start();
       support.fireLifecycleEvent(START_EVENT, this);
    }
 
    public void stop() throws LifecycleException
    {
       support.fireLifecycleEvent(STOP_EVENT, this);
-      snapshot.stop();
    }
 
 }

Modified: branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/session/InstantSnapshotManager.java
===================================================================
--- branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/session/InstantSnapshotManager.java	2006-08-02 22:44:10 UTC (rev 55056)
+++ branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/session/InstantSnapshotManager.java	2006-08-02 22:46:02 UTC (rev 55057)
@@ -22,19 +22,17 @@
 package org.jboss.web.tomcat.tc5.session;
 
 import org.apache.catalina.Session;
-import org.jboss.logging.Logger;
 
 /**
  * A concrete implementation of the snapshot manager interface
  * that does instant replication of a modified session
  *
  * @author Thomas Peuss <jboss at peuss.de>
+ * @author Brian Stansberry
  * @version $Revision$
  */
 public class InstantSnapshotManager extends SnapshotManager
 {
-   static Logger log = Logger.getLogger(InstantSnapshotManager.class);
-
    public InstantSnapshotManager(AbstractJBossManager manager, String path)
    {
       super(manager, path);
@@ -48,12 +46,14 @@
       try
       {
          // find the session that has been modified
-         Session session = manager.findSession(id);
-         manager.storeSession(session);
+         AbstractJBossManager mgr = getManager();
+         Session session = mgr.findSession(id);
+         if (session != null)
+            mgr.storeSession(session);
       }
       catch (Exception e)
       {
-         log.warn("Failed to replicate sessionID:" + id, e);
+         getLog().warn("Failed to replicate sessionID:" + id, e);
       }
    }
 

Modified: branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/session/IntervalSnapshotManager.java
===================================================================
--- branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/session/IntervalSnapshotManager.java	2006-08-02 22:44:10 UTC (rev 55056)
+++ branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/session/IntervalSnapshotManager.java	2006-08-02 22:46:02 UTC (rev 55057)
@@ -21,10 +21,9 @@
 */
 package org.jboss.web.tomcat.tc5.session;
 
-import java.util.HashMap;
-import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Set;
 
-import org.apache.catalina.Context;
 import org.apache.catalina.Session;
 import org.jboss.logging.Logger;
 
@@ -33,6 +32,7 @@
  * period of time and distributes them en bloc.
  *
  * @author Thomas Peuss <jboss at peuss.de>
+ * @author Brian Stansberry
  * @version $Revision$
  */
 public class IntervalSnapshotManager extends SnapshotManager implements Runnable
@@ -43,7 +43,7 @@
    protected int interval = 1000;
 
    // the modified sessions
-   protected HashMap sessions = new HashMap();
+   protected Set sessions = new LinkedHashSet();
 
    // the distribute thread
    protected Thread thread = null;
@@ -68,11 +68,10 @@
    public void snapshot(String id)
    {
       try
-      {
-         Session session = (Session) manager.findSession(id);
+      {         
          synchronized (sessions)
          {
-            sessions.put(id, session);
+            sessions.add(id);
          }
       }
       catch (Exception e)
@@ -86,22 +85,28 @@
     */
    protected void processSessions()
    {
-      HashMap copy = new HashMap(sessions.size());
-
+      String[] ids = null;
       synchronized (sessions)
       {
-         copy.putAll(sessions);
+         ids = new String[sessions.size()];
+         ids = (String[]) sessions.toArray(ids);
          sessions.clear();
       }
-      Iterator iter = copy.values().iterator();
 
-      // distribute all modified sessions using default replication type
-      while (iter.hasNext())
+      AbstractJBossManager mgr = getManager();
+      for (int i = 0; i < ids.length; i++)
       {
-         Session session = (Session) iter.next();
-         manager.storeSession(session);
+         try
+         {
+            Session session = mgr.findSession(ids[i]);
+            if (session != null)
+               mgr.storeSession(session);
+         }
+         catch (Exception e)
+         {
+            getLog().error("Caught exception processing session " + ids[i], e);
+         }
       }
-      copy.clear();
    }
 
    /**
@@ -134,9 +139,9 @@
          return;
       }
 
-      thread = new Thread(this, "ClusteredSessionDistributor[" + contextPath + "]");
+      thread = new Thread(this, "ClusteredSessionDistributor[" + getContextPath() + "]");
       thread.setDaemon(true);
-      thread.setContextClassLoader(manager.getContainer().getLoader().getClassLoader());
+      thread.setContextClassLoader(getManager().getContainer().getLoader().getClassLoader());
       threadDone = false;
       thread.start();
    }
@@ -163,28 +168,26 @@
    }
 
    /**
-    * Little Thread - sleep awhile...
-    */
-   protected void threadSleep()
-   {
-      try
-      {
-         Thread.sleep(interval);
-      }
-      catch (InterruptedException e)
-      {
-      }
-   }
-
-   /**
     * Thread-loop
     */
    public void run()
    {
       while (!threadDone)
       {
-         threadSleep();
-         processSessions();
+         try
+         {
+            Thread.sleep(interval);
+            processSessions();
+         }
+         catch (InterruptedException ie)
+         {
+            if (!threadDone)
+               getLog().error("Caught exception processing sessions", ie);
+         }
+         catch (Exception e)
+         {
+            getLog().error("Caught exception processing sessions", e);
+         }
       }
    }
 }

Modified: branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/session/JBossCacheManager.java
===================================================================
--- branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/session/JBossCacheManager.java	2006-08-02 22:44:10 UTC (rev 55056)
+++ branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/session/JBossCacheManager.java	2006-08-02 22:46:02 UTC (rev 55057)
@@ -121,6 +121,11 @@
    
    /** Class loader for this web app. */
    private ClassLoader tcl_;
+   
+   /**
+    * The snapshot manager we are using.
+    */
+   private SnapshotManager snapshotManager_;
 
    //  ----------------------------------------------------------  Constructors
 
@@ -180,7 +185,7 @@
    {
       return cacheObjectNameString_;
    }
-   
+
    /**
     * Sets the JMX <code>ObjectName</code> under which our
     * <code>TreeCache</code> is registered.
@@ -483,6 +488,8 @@
       proxy_.stop();
       tm = null;
       
+      snapshotManager_.stop();
+      
       started_ = false;
       
       // Notify our interested LifecycleListeners
@@ -611,6 +618,12 @@
       }
 
       createdCounter_++;
+      
+      // Add this session to the set of those potentially needing replication
+      // We use the realId here
+      String realId = getRealId(sessionId);
+      SessionReplicationContext.addActiveSession(realId, snapshotManager_);
+      
       return session;
    }
 
@@ -770,7 +783,7 @@
       // session from the other nodes to be gravitated, thus resuscitating
       // the session.
       if (session == null 
-            && !realId.equals(ClusteredSessionValve.sessionIdThreadLocal.get()))
+            && !SessionReplicationContext.isSessionActive(realId, snapshotManager_))
       {
          session = loadSession(realId);
          if (session != null)
@@ -787,7 +800,10 @@
       }
 
       if (session != null)
-         ClusteredSessionValve.sessionIdThreadLocal.set(realId);
+      {
+         // Add this session to the set of those potentially needing replication
+         SessionReplicationContext.addActiveSession(realId, snapshotManager_);
+      }
 
       return session;
    }
@@ -1243,9 +1259,9 @@
          
          // Ensure the correct TCL is in place
          ClassLoader prevTcl = Thread.currentThread().getContextClassLoader();
-         Thread.currentThread().setContextClassLoader(tcl_);
          try
          {
+            Thread.currentThread().setContextClassLoader(tcl_);
             synchronized (session)
             {
                session.removeAttributeInternal(attrKey, localCall, localOnly, notify);
@@ -1369,7 +1385,10 @@
       try
       {
          initializeUnloadedSessions();
-      
+         
+         // Setup our SnapshotManager
+         initSnapshotManager();
+         
          // Add SnapshotValve and, if needed, JvmRouteValve and batch repl valve
          installValves();
 
@@ -1483,7 +1502,7 @@
       try
       {
          initializeUnloadedSessions();
-      
+
          // Add SnapshotValve and, if needed, JvmRouteValve and batch repl valve
          installValves();
 
@@ -1616,7 +1635,7 @@
     * 
     */
    private void installValves()
-   {       
+   {  
       if (useJK_)
       {
          log_.info("We are using mod_jk(2) for load-balancing. " +
@@ -1624,8 +1643,10 @@
          
          installContextValve(new JvmRouteValve(this));         
       }
-      
+         
       // Add batch replication valve if needed.
+      // TODO -- should we add this even if not FIELD in case a cross-context
+      // call traverses a field-based webapp?
       if (replicationGranularity_ == WebMetaData.REPLICATION_GRANULARITY_FIELD &&
           Boolean.TRUE.equals(replicationFieldBatchMode_))
       {
@@ -1633,29 +1654,35 @@
          log_.debug("Adding BatchReplicationClusteredSessionValve for batch replication.");
          installContextValve(batchValve);
       }
-      
-      // Choose the snapshot manager
+
+      // Add clustered session valve
+      ClusteredSessionValve valve = new ClusteredSessionValve();
+      installContextValve(valve);
+   }
+
+   /**
+    * Create and start a snapshot manager.
+    */
+   private void initSnapshotManager()
+   {
       String ctxPath = ((Context) container_).getPath();
-      SnapshotManager snap = null;
       if ("instant".equals(snapshotMode_) || replicationGranularity_
             == WebMetaData.REPLICATION_GRANULARITY_FIELD)
       {
-         snap = new InstantSnapshotManager(this, ctxPath);
+         snapshotManager_ = new InstantSnapshotManager(this, ctxPath);
       }
       else if ("interval".equals(snapshotMode_))
       {
-         snap = new IntervalSnapshotManager(this, ctxPath, snapshotInterval_);
+         snapshotManager_ = new IntervalSnapshotManager(this, ctxPath, snapshotInterval_);
       }
       else
       {
          log_.error("Snapshot mode must be 'instant' or 'interval' - " +
                     "using 'instant'");
-         snap = new InstantSnapshotManager(this, ctxPath);
+         snapshotManager_ = new InstantSnapshotManager(this, ctxPath);
       }
-
-      // Add the session snapshot valve to the Context
-      ClusteredSessionValve valve = new ClusteredSessionValve(snap);
-      installContextValve(valve);
+      
+      snapshotManager_.start();
    }
    
    private void installContextValve(Valve valve)
@@ -1714,7 +1741,7 @@
       {
             throw new ClusteringNotSupportedException("replication-granularity value is set to " +
                   "'FIELD' but is not supported by the cache service configuration. " +
-                  "Must set 'UseMarshalling' to 'true' in the tc5-cluster-service.xml");
+                  "Must set 'UseRegionBasedMarshalling' to 'true' in the tc6-cluster.sar jboss-service.xml");
       }
    }
    

Modified: branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/session/JBossManager.java
===================================================================
--- branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/session/JBossManager.java	2006-08-02 22:44:10 UTC (rev 55056)
+++ branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/session/JBossManager.java	2006-08-02 22:46:02 UTC (rev 55057)
@@ -249,7 +249,7 @@
     */
    public void setSessionCookie(String sessionId)
    {
-      HttpServletResponse response = (HttpServletResponse) ClusteredSessionValve.responseThreadLocal.get();
+      HttpServletResponse response = SessionReplicationContext.getOriginalResponse();
       setNewSessionCookie(sessionId, response);
    }
 
@@ -259,7 +259,6 @@
       {
          Context context = (Context) container_;
          Connector connector = ((Response)response).getConnector();
-
          if (context.getCookies())
          {
             // set a new session cookie

Modified: branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/session/SnapshotManager.java
===================================================================
--- branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/session/SnapshotManager.java	2006-08-02 22:44:10 UTC (rev 55056)
+++ branches/Branch_4_0/tomcat/src/main/org/jboss/web/tomcat/tc5/session/SnapshotManager.java	2006-08-02 22:46:02 UTC (rev 55057)
@@ -22,6 +22,7 @@
 package org.jboss.web.tomcat.tc5.session;
 
 import org.apache.catalina.Context;
+import org.jboss.logging.Logger;
 
 /**
  * Abstract base class for a session snapshot manager.
@@ -36,11 +37,18 @@
 
    // The context-path
    protected String contextPath;
+   
+   private Logger log;
 
    public SnapshotManager(AbstractJBossManager manager, String path)
    {
       this.manager = manager;
       contextPath = path;
+      
+      String suffix = path;
+      if (suffix == null || "".equals(suffix))
+         suffix = "ROOT";
+      log = Logger.getLogger(getClass().getName() + "." + suffix);
    }
 
    /**
@@ -58,4 +66,21 @@
     * Stop the snapshot manager
     */
    public abstract void stop();
+
+   protected String getContextPath()
+   {
+      return contextPath;
+   }
+
+   protected Logger getLog()
+   {
+      return log;
+   }
+
+   protected AbstractJBossManager getManager()
+   {
+      return manager;
+   }
+   
+   
 }




More information about the jboss-cvs-commits mailing list