org.mortbay.terracotta.servlet
Class TerracottaSessionManager

java.lang.Object
  extended by org.mortbay.component.AbstractLifeCycle
      extended by org.mortbay.jetty.servlet.AbstractSessionManager
          extended by org.mortbay.terracotta.servlet.TerracottaSessionManager
All Implemented Interfaces:
Runnable, LifeCycle, SessionManager

public class TerracottaSessionManager
extends AbstractSessionManager
implements Runnable

A specialized SessionManager to be used with Terracotta.

IMPLEMENTATION NOTES

Requirements

This implementation of the session management requires J2SE 5 or superior.

Use of Hashtable

In Terracotta, collections classes are logically managed and we need two levels of locking: a local locking to handle concurrent requests on the same node and a distributed locking to handle concurrent requests on different nodes. Natively synchronized classes such as Hashtable fit better than synchronized wrappers obtained via, for example, Collections.synchronizedMap(Map). This is because Terracotta may replay the method call on the inner unsynchronized collection without invoking the external wrapper, so the synchronization will be lost. Natively synchronized collections does not have this problem.

Use of Hashtable as a Set

There is no natively synchronized Set implementation, so we use Hashtable instead, see TerracottaSessionIdManager. However, we don't map the session id to itself, because Strings are treated specially by Terracotta, causing more traffic to the Terracotta server. Instead we use the same pattern used in the implementation of java.util.HashSet: use a single shared object to indicate the presence of a key. This is necessary since Hashtable does not allow null values.

Sessions expiration map

In order to scavenge expired sessions, we need a way to know if they are expired. This information is normally held in the session itself via the lastAccessedTime property. However, we would need to iterate over all sessions to check if each one is expired, and this migrates all sessions to the node, causing a lot of unneeded traffic between nodes and the Terracotta server. To avoid this, we keep a separate map from session id to expiration time, so we only need to migrate all the expirations times to see if a session is expired or not.

Update of lastAccessedTime

As a performance improvement, the lastAccessedTime is updated only periodically, and not every time a request enters a node. This optimization allows applications that have frequent requests but less frequent accesses to the session to perform better, because the traffic between the node and the Terracotta server is reduced. The update period is the scavenger period, see Session#access(long).

Terracotta lock id

The Terracotta lock id is based on the session id, but this alone is not sufficient, as there may be two sessions with the same id for two different contexts. So we need session id and context path. However, this also is not enough, as we may have the rare case of the same webapp mapped to two different virtual hosts, and each virtual host must have a different session object. Therefore the lock id we need to use is a combination of session id, context path and virtual host, see newLockId(String).

See Also:
TerracottaSessionIdManager

Nested Class Summary
protected static class TerracottaSessionManager.Lock
           
static class TerracottaSessionManager.SessionData
          The session data that is distributed to cluster nodes via Terracotta.
 
Nested classes/interfaces inherited from class org.mortbay.jetty.servlet.AbstractSessionManager
AbstractSessionManager.NullSessionContext, AbstractSessionManager.SessionIf
 
Nested classes/interfaces inherited from interface org.mortbay.component.LifeCycle
LifeCycle.Listener
 
Field Summary
 
Fields inherited from class org.mortbay.jetty.servlet.AbstractSessionManager
__distantFuture, _context, _dftMaxIdleSecs, _httpOnly, _loader, _maxCookieAge, _maxSessions, _minSessions, _nodeIdInSessionId, _refreshCookieAge, _secureCookies, _sessionAttributeListeners, _sessionCookie, _sessionDomain, _sessionHandler, _sessionIdManager, _sessionListeners, _sessionPath, _sessionURL, _sessionURLPrefix
 
Fields inherited from class org.mortbay.component.AbstractLifeCycle
_listeners
 
Fields inherited from interface org.mortbay.jetty.SessionManager
__DefaultSessionCookie, __DefaultSessionDomain, __DefaultSessionURL, __MaxAgeProperty, __SessionCookieProperty, __SessionDomainProperty, __SessionPathProperty, __SessionURLProperty
 
Constructor Summary
TerracottaSessionManager()
           
 
Method Summary
 Cookie access(HttpSession session, boolean secure)
          Called by the SessionHandler when a session is access by a request
protected  void addSession(AbstractSessionManager.Session session)
           
 void complete(HttpSession session)
          Called by the SessionHandler when a reqeuest is not longer handling a session.
 void doStart()
           
 void doStop()
           
 void enter(Request request)
           
protected  void enter(String clusterId)
           
 void exit(Request request)
           
protected  void exit(String clusterId)
           
 long getScavengePeriodMs()
           
 AbstractSessionManager.Session getSession(String clusterId)
          Get a known existingsession
 Map getSessionMap()
           
 int getSessions()
           
protected  void invalidateSessions()
           
protected  String newLockId(String clusterId)
           
protected  org.mortbay.terracotta.servlet.TerracottaSessionManager.Session newSession(HttpServletRequest request)
          Create a new session instance
protected  void removeSession(String clusterId)
           
 void run()
           
 void setScavengePeriodMs(long ms)
           
protected  boolean tryEnter(String clusterId)
           
 
Methods inherited from class org.mortbay.jetty.servlet.AbstractSessionManager
addEventListener, addSession, clearEventListeners, getClusterId, getHttpOnly, getHttpSession, getIdManager, getMaxCookieAge, getMaxInactiveInterval, getMaxSessions, getMetaManager, getMinSessions, getNodeId, getRefreshCookieAge, getSecureCookies, getSessionCookie, getSessionCookie, getSessionDomain, getSessionHandler, getSessionPath, getSessionURL, getSessionURLPrefix, isNodeIdInSessionId, isUsingCookies, isValid, newHttpSession, removeEventListener, removeSession, removeSession, resetStats, setHttpOnly, setIdManager, setMaxCookieAge, setMaxInactiveInterval, setMetaManager, setNodeIdInSessionId, setRefreshCookieAge, setSecureCookies, setSessionCookie, setSessionDomain, setSessionHandler, setSessionPath, setSessionURL, setUsingCookies
 
Methods inherited from class org.mortbay.component.AbstractLifeCycle
addLifeCycleListener, isFailed, isRunning, isStarted, isStarting, isStopped, isStopping, removeLifeCycleListener, start, stop
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 
Methods inherited from interface org.mortbay.component.LifeCycle
addLifeCycleListener, isFailed, isRunning, isStarted, isStarting, isStopped, isStopping, removeLifeCycleListener, start, stop
 

Constructor Detail

TerracottaSessionManager

public TerracottaSessionManager()
Method Detail

doStart

public void doStart()
             throws Exception
Overrides:
doStart in class AbstractSessionManager
Throws:
Exception

doStop

public void doStop()
            throws Exception
Overrides:
doStop in class AbstractSessionManager
Throws:
Exception

run

public void run()
Specified by:
run in interface Runnable

enter

public void enter(Request request)

enter

protected void enter(String clusterId)

tryEnter

protected boolean tryEnter(String clusterId)

exit

public void exit(Request request)

exit

protected void exit(String clusterId)

addSession

protected void addSession(AbstractSessionManager.Session session)
Specified by:
addSession in class AbstractSessionManager

access

public Cookie access(HttpSession session,
                     boolean secure)
Description copied from interface: SessionManager
Called by the SessionHandler when a session is access by a request

Specified by:
access in interface SessionManager
Overrides:
access in class AbstractSessionManager
Returns:
Cookie If non null, this cookie should be set on the response to either migrate the session or to refresh a cookie that may expire.

complete

public void complete(HttpSession session)
Description copied from interface: SessionManager
Called by the SessionHandler when a reqeuest is not longer handling a session. Not this includes new sessions, so there may not be a matching call to #access(HttpSession).

Specified by:
complete in interface SessionManager
Overrides:
complete in class AbstractSessionManager

removeSession

protected void removeSession(String clusterId)
Specified by:
removeSession in class AbstractSessionManager

setScavengePeriodMs

public void setScavengePeriodMs(long ms)

getScavengePeriodMs

public long getScavengePeriodMs()

getSession

public AbstractSessionManager.Session getSession(String clusterId)
Description copied from class: AbstractSessionManager
Get a known existingsession

Specified by:
getSession in class AbstractSessionManager
Parameters:
clusterId - The session ID in the cluster, stripped of any worker name.
Returns:
A Session or null if none exists.

newLockId

protected String newLockId(String clusterId)

getSessionMap

public Map getSessionMap()
Specified by:
getSessionMap in class AbstractSessionManager

getSessions

public int getSessions()
Specified by:
getSessions in class AbstractSessionManager

newSession

protected org.mortbay.terracotta.servlet.TerracottaSessionManager.Session newSession(HttpServletRequest request)
Description copied from class: AbstractSessionManager
Create a new session instance

Specified by:
newSession in class AbstractSessionManager
Returns:

invalidateSessions

protected void invalidateSessions()
Specified by:
invalidateSessions in class AbstractSessionManager


Copyright © 1995-2009 Mort Bay Consulting. All Rights Reserved.