[jboss-cvs] JBossAS SVN: r108681 - branches/infinispan-int/tomcat/src/main/java/org/jboss/web/tomcat/service/session.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Wed Oct 20 00:05:59 EDT 2010


Author: pferraro
Date: 2010-10-20 00:05:58 -0400 (Wed, 20 Oct 2010)
New Revision: 108681

Modified:
   branches/infinispan-int/tomcat/src/main/java/org/jboss/web/tomcat/service/session/ClusteredSession.java
Log:
JBAS-7844, JBAS-7852 Session ownership support

Modified: branches/infinispan-int/tomcat/src/main/java/org/jboss/web/tomcat/service/session/ClusteredSession.java
===================================================================
--- branches/infinispan-int/tomcat/src/main/java/org/jboss/web/tomcat/service/session/ClusteredSession.java	2010-10-20 03:56:32 UTC (rev 108680)
+++ branches/infinispan-int/tomcat/src/main/java/org/jboss/web/tomcat/service/session/ClusteredSession.java	2010-10-20 04:05:58 UTC (rev 108681)
@@ -40,6 +40,8 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpSession;
@@ -61,12 +63,14 @@
 import org.apache.catalina.session.StandardSessionFacade;
 import org.apache.catalina.util.Enumerator;
 import org.apache.catalina.util.StringManager;
+import org.jboss.ha.framework.server.lock.TimeoutException;
 import org.jboss.logging.Logger;
 import org.jboss.metadata.web.jboss.ReplicationTrigger;
 import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributableSessionMetadata;
 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;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.SessionOwnershipSupport;
 import org.jboss.web.tomcat.service.session.notification.ClusteredSessionManagementStatus;
 import org.jboss.web.tomcat.service.session.notification.ClusteredSessionNotificationCause;
 import org.jboss.web.tomcat.service.session.notification.ClusteredSessionNotificationPolicy;
@@ -129,15 +133,13 @@
    @SuppressWarnings("deprecation")
    protected static javax.servlet.http.HttpSessionContext sessionContext = new javax.servlet.http.HttpSessionContext()
    {
-      @SuppressWarnings("unchecked")
-      private final Map empty = Collections.EMPTY_MAP;
-
-      @SuppressWarnings("unchecked")
-      public Enumeration getIds()
+      @Override
+      public Enumeration<String> getIds()
       {
-         return new Enumerator(empty);
+         return Collections.enumeration(Collections.<String>emptyList());
       }
-
+      
+      @Override
       public HttpSession getSession(String sessionId)
       {
          return null;
@@ -385,8 +387,11 @@
    /** End of period when we do full replication */
    private transient long fullReplicationWindow = -1;
    
+   /** Coordinate updates from the cluster */
+   private transient Lock ownershipLock = new ReentrantLock();
+   
    // ------------------------------------------------------------ Constructors
-
+   
    /**
     * Creates a new ClusteredSession.
     * 
@@ -499,7 +504,7 @@
       if ((manager instanceof ClusteredManager<?>) == false)
          throw new IllegalArgumentException("manager must implement ClusteredManager");
       @SuppressWarnings("unchecked")
-      ClusteredManager<O> unchecked = (ClusteredManager) manager;
+      ClusteredManager<O> unchecked = (ClusteredManager<O>) manager;
       this.manager = unchecked;
 
       
@@ -558,6 +563,8 @@
 
    public void access()
    {
+      this.acquireSessionOwnership();
+      
       this.lastAccessedTime = this.thisAccessedTime;
       this.thisAccessedTime = System.currentTimeMillis();
       
@@ -573,12 +580,53 @@
       }      
    }
    
+   private void acquireSessionOwnership()
+   {
+      SessionOwnershipSupport support = this.distributedCacheManager.getSessionOwnershipSupport();
+      
+      if (support != null)
+      {
+         try
+         {
+            this.ownershipLock.lockInterruptibly();
+            
+            try
+            {
+               if (support.acquireSessionOwnership(this.realId, needNewLock()) == SessionOwnershipSupport.LockResult.ACQUIRED_FROM_CLUSTER)
+               {
+                  // We may be out of date re: the distributed cache
+                  update(this.distributedCacheManager.getSessionData(this.realId, false));
+               }
+            }
+            catch (TimeoutException e)
+            {
+               throw new RuntimeException("Caught " + e.getClass().getSimpleName() + " acquiring ownership of " + this.realId, e);
+            }
+            finally
+            {
+               this.ownershipLock.unlock();
+            }
+         }
+         catch (InterruptedException e)
+         {
+            Thread.currentThread().interrupt();
+            throw new RuntimeException("Interrupted while acquiring ownership of " + this.realId, e);
+         }
+      }
+   }
+   
+   private boolean needNewLock()
+   {
+      return firstAccess && isNew;
+   }
+
    public void endAccess()
    {
       isNew = false;
 
-      if (ACTIVITY_CHECK) {
-          accessCount.decrementAndGet();
+      if (ACTIVITY_CHECK)
+      {
+         accessCount.decrementAndGet();
       }
       
       this.lastAccessedTime = this.thisAccessedTime;
@@ -591,7 +639,19 @@
          // So, we fix that
          isNew = true;
       }
+      
+      this.relinquishSessionOwnership(false);
    }
+   
+   private void relinquishSessionOwnership(boolean remove)
+   {
+      SessionOwnershipSupport support = this.distributedCacheManager.getSessionOwnershipSupport();
+      
+      if (support != null)
+      {
+         support.relinquishSessionOwnership(this.realId, remove);
+      }
+   }
 
    public boolean isNew()
    {
@@ -732,8 +792,7 @@
       return (notes.get(name));
    }
 
-   @SuppressWarnings("unchecked")
-   public Iterator getNoteNames()
+   public Iterator<String> getNoteNames()
    {
       return (notes.keySet().iterator());
    }
@@ -791,10 +850,9 @@
          if (SecurityUtil.isPackageProtectionEnabled())
          {
             final HttpSession fsession = this;
-            @SuppressWarnings("unchecked")
-            StandardSessionFacade ssf = (StandardSessionFacade)AccessController.doPrivileged(new PrivilegedAction()
+            StandardSessionFacade ssf = AccessController.doPrivileged(new PrivilegedAction<StandardSessionFacade>()
             {
-               public Object run()
+               public StandardSessionFacade run()
                {
                   return new StandardSessionFacade(fsession);
                }
@@ -1416,107 +1474,117 @@
          
          // SRV.10.6 (2.5) 11.6 (3.0) Propagate listener exceptions
          RuntimeException listenerException = null;
+         
+         if (localCall)
+         {
+            this.acquireSessionOwnership();
+         }
+         
          try
          {
-	         // Notify interested application event listeners
-	         // FIXME - Assumes we call listeners in reverse order
-	         Context context = (Context) manager.getContainer();
-	         Object lifecycleListeners[] = context.getApplicationSessionLifecycleListeners();
-	         if (notify 
-	               && (lifecycleListeners != null) 
-	               && notificationPolicy.isHttpSessionListenerInvocationAllowed(this.clusterStatus, cause, localCall))
-	         {
-	            HttpSessionEvent event =
-	               new HttpSessionEvent(getSession());
-	            for (int i = 0; i < lifecycleListeners.length; i++)
-	            {
-	               int j = (lifecycleListeners.length - 1) - i;
-	               if (!(lifecycleListeners[j] instanceof HttpSessionListener))
-	                  continue;
-	               HttpSessionListener listener =
-	                  (HttpSessionListener) lifecycleListeners[j];
-	               try
-	               {
-	                  fireContainerEvent(context,
-	                     "beforeSessionDestroyed",
-	                     listener);
-	                  try
-	                  {
-	                     listener.sessionDestroyed(event);
-	                  }
-	                  catch (RuntimeException e)
-	                  {
-	                     if (listenerException == null)
-	                      {
-	                          listenerException = e;
-	                      }
-	                  }
-	                  fireContainerEvent(context,
-	                     "afterSessionDestroyed",
-	                     listener);
-	               }
-	               catch (Throwable t)
-	               {
-	                  try
-	                  {
-	                     fireContainerEvent(context,
-	                        "afterSessionDestroyed",
-	                        listener);
-	                  }
-	                  catch (Exception e)
-	                  {
-	                     ;
-	                  }
-	                  manager.getContainer().getLogger().error(sm.getString("clusteredSession.sessionEvent"), t);
-	               }
-	            }
-	         }
-	         
-	         if (ACTIVITY_CHECK) {
-	             accessCount.set(0);
-	         }
-	
-	         // Notify interested session event listeners. 
-	         if (notify)
-	         {
-	            fireSessionEvent(Session.SESSION_DESTROYED_EVENT, null);
-	         }
-	
-	         // JBAS-1360 -- Unbind any objects associated with this session
-	         String keys[] = keys();
-	         for (int i = 0; i < keys.length; i++)
-	         {
-	        	 try
-	        	 {
-	        		 removeAttributeInternal(keys[i], localCall, localOnly, notify, cause);
-	        	 }
-	        	 catch (RuntimeException e)
-	        	 {
-	        		 if (listenerException == null)
-	        		 {
-	        			 listenerException = e;
-	        		 }
-	        	 }
-	         }
-	
-	         // Remove this session from our manager's active sessions
-	         // If !localCall, this expire call came from the manager, 
-	         // so don't recurse
-	         if (localCall)
-	         {
-	            removeFromManager(localOnly);
-	         }
-	         
-	         if (listenerException != null)
-	         {
-	        	 throw listenerException;
-	         }
+            // Notify interested application event listeners
+            // FIXME - Assumes we call listeners in reverse order
+            Context context = (Context) manager.getContainer();
+            Object lifecycleListeners[] = context.getApplicationSessionLifecycleListeners();
+            if (notify 
+                  && (lifecycleListeners != null) 
+                  && notificationPolicy.isHttpSessionListenerInvocationAllowed(this.clusterStatus, cause, localCall))
+            {
+               HttpSessionEvent event =
+                  new HttpSessionEvent(getSession());
+               for (int i = 0; i < lifecycleListeners.length; i++)
+               {
+                  int j = (lifecycleListeners.length - 1) - i;
+                  if (!(lifecycleListeners[j] instanceof HttpSessionListener))
+                     continue;
+                  HttpSessionListener listener =
+                     (HttpSessionListener) lifecycleListeners[j];
+                  try
+                  {
+                     fireContainerEvent(context,
+                        "beforeSessionDestroyed",
+                        listener);
+                     try
+                     {
+                        listener.sessionDestroyed(event);
+                     }
+                     catch (RuntimeException e)
+                     {
+                        if (listenerException == null)
+                         {
+                             listenerException = e;
+                         }
+                     }
+                     fireContainerEvent(context,
+                        "afterSessionDestroyed",
+                        listener);
+                  }
+                  catch (Throwable t)
+                  {
+                     try
+                     {
+                        fireContainerEvent(context,
+                           "afterSessionDestroyed",
+                           listener);
+                     }
+                     catch (Exception e)
+                     {
+                        ;
+                     }
+                     manager.getContainer().getLogger().error(sm.getString("clusteredSession.sessionEvent"), t);
+                  }
+               }
+            }
+            
+            if (ACTIVITY_CHECK) {
+                accessCount.set(0);
+            }
+   
+            // Notify interested session event listeners. 
+            if (notify)
+            {
+               fireSessionEvent(Session.SESSION_DESTROYED_EVENT, null);
+            }
+   
+            // JBAS-1360 -- Unbind any objects associated with this session
+            String keys[] = keys();
+            for (int i = 0; i < keys.length; i++)
+            {
+               try
+               {
+                  removeAttributeInternal(keys[i], localCall, localOnly, notify, cause);
+               }
+               catch (RuntimeException e)
+               {
+                  if (listenerException == null)
+                  {
+                     listenerException = e;
+                  }
+               }
+            }
+   
+            // Remove this session from our manager's active sessions
+            // If !localCall, this expire call came from the manager, 
+            // so don't recurse
+            if (localCall)
+            {
+               removeFromManager(localOnly);
+            }
+            
+            if (listenerException != null)
+            {
+               throw listenerException;
+            }
          }
          finally
          {
              // We have completed expire of this session
              setValid(false);
-             expiring = false;        	 
+             expiring = false;
+             if (localCall)
+             {
+                this.relinquishSessionOwnership(true);
+             }
          }
       }
    }



More information about the jboss-cvs-commits mailing list