[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