From 4ac821d582465e5f0bd27372fd8871ad2271bd9a Mon Sep 17 00:00:00 2001 From: Jan Bartel Date: Thu, 18 Aug 2016 11:20:45 +1000 Subject: [PATCH] Updates to session javadoc --- .../jetty/server/SessionIdManager.java | 1 + .../server/session/AbstractSessionCache.java | 13 +- .../session/DefaultSessionIdManager.java | 6 +- .../eclipse/jetty/server/session/Session.java | 66 ++++-- .../jetty/server/session/SessionCache.java | 201 +++++++++++++++--- .../jetty/server/session/SessionHandler.java | 5 +- 6 files changed, 242 insertions(+), 50 deletions(-) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/SessionIdManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/SessionIdManager.java index 2d87a19062c..2fd4739c18f 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/SessionIdManager.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/SessionIdManager.java @@ -27,6 +27,7 @@ import org.eclipse.jetty.util.component.LifeCycle; /** * Session ID Manager. + * * Manages session IDs across multiple contexts. */ public interface SessionIdManager extends LifeCycle diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionCache.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionCache.java index 7f9194d96aa..fd7c2b7ee76 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionCache.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionCache.java @@ -33,22 +33,21 @@ import org.eclipse.jetty.util.thread.Locker.Lock; /** * AbstractSessionCache * - * A base implementation of the SessionCache interface for managing a set of + * A base implementation of the {@link SessionCache} interface for managing a set of * Session objects pertaining to a context in memory. * * This implementation ensures that multiple requests for the same session id * always return the same Session object. * * It will delay writing out a session to the SessionDataStore until the - * last request exists the session. If the SessionDataStore supports passivation + * last request exits the session. If the SessionDataStore supports passivation * then the session passivation and activation listeners are called appropriately as - * the session is written. Additionally the session can be evicted from the - * AbstractSessionCache after passivation on write. + * the session is written. * * This implementation also supports evicting idle Session objects. An idle Session * is one that is still valid, has not expired, but has not been accessed by a * request for a configurable amount of time. An idle session will be first - * passivated before eviction from the cache. + * passivated before it is evicted from the cache. * */ public abstract class AbstractSessionCache extends ContainerLifeCycle implements SessionCache @@ -89,6 +88,10 @@ public abstract class AbstractSessionCache extends ContainerLifeCycle implements protected boolean _saveOnInactiveEviction; + /** + * If true, a Session whose data cannot be read will be + * deleted from the SessionDataStore. + */ protected boolean _removeUnloadableSessions; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/DefaultSessionIdManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/DefaultSessionIdManager.java index deabc4b3a69..de986c5b41a 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/DefaultSessionIdManager.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/DefaultSessionIdManager.java @@ -37,12 +37,16 @@ import org.eclipse.jetty.util.log.Logger; /** - * AbstractSessionIdManager + * DefaultSessionIdManager * * Manages session ids to ensure each session id within a context is unique, and that * session ids can be shared across contexts (but not session contents). * * There is only 1 session id manager per Server instance. + * + * Runs a HouseKeeper thread to periodically check for expired Sessions. + * + * @See HouseKeeper */ public class DefaultSessionIdManager extends AbstractLifeCycle implements SessionIdManager { diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/Session.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/Session.java index 919edb7c394..ade960d850c 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/Session.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/Session.java @@ -47,7 +47,18 @@ import org.eclipse.jetty.util.thread.Locker.Lock; /** * Session * - * + * A heavy-weight Session object representing a HttpSession. Session objects + * relating to a context are kept in a {@link SessionCache}. The purpose of + * the SessionCache is to keep the working set of Session objects in memory + * so that they may be accessed quickly, and facilitate the sharing of a + * Session object amongst multiple simultaneous requests referring to the + * same session id. + * + * The {@link SessionHandler} coordinates + * the lifecycle of Session objects with the help of the SessionCache. + * + * @see SessionHandler + * @see org.eclipse.jetty.server.SessionIdManager */ public class Session implements SessionHandler.SessionIf { @@ -87,13 +98,16 @@ public class Session implements SessionHandler.SessionIf /* ------------------------------------------------------------- */ /** * SessionInactivityTimeout - * + * + * Each Session has a timer associated with it that fires whenever + * it has been idle (ie not referenced by a request) for a + * configurable amount of time, or the Session expires. + * + * @see SessionCache * */ public class SessionInactivityTimeout extends IdleTimeout { - - /** * */ @@ -146,7 +160,7 @@ public class Session implements SessionHandler.SessionIf /* ------------------------------------------------------------- */ /** * Create a new session - * @param handler TODO + * @param handler the SessionHandler that manages this session * @param request the request the session should be based on * @param data the session data */ @@ -162,8 +176,9 @@ public class Session implements SessionHandler.SessionIf /* ------------------------------------------------------------- */ /** - * Re-create an existing session - * @param handler TODO + * Re-inflate an existing session from some eg persistent store. + * + * @param handler the SessionHandler managing the session * @param data the session data */ public Session (SessionHandler handler, SessionData data) @@ -175,9 +190,9 @@ public class Session implements SessionHandler.SessionIf /* ------------------------------------------------------------- */ /** - * Should call this method with a lock held if you want to - * make decision on what to do with the session - * + * Returns the current number of requests that are active in the + * Session. + * * @return the number of active requests for this session */ public long getRequests() @@ -242,7 +257,8 @@ public class Session implements SessionHandler.SessionIf /* ------------------------------------------------------------- */ /** Check to see if session has expired as at the time given. - * @param time the time in milliseconds + * + * @param time the time since the epoch in ms * @return true if expired */ protected boolean isExpiredAt(long time) @@ -254,6 +270,12 @@ public class Session implements SessionHandler.SessionIf } + /* ------------------------------------------------------------- */ + /** Check if the Session has been idle longer than a number of seconds. + * + * @param sec the number of seconds + * @return true if the session has been idle longer than the interval + */ protected boolean isIdleLongerThan (int sec) { long now = System.currentTimeMillis(); @@ -320,7 +342,7 @@ public class Session implements SessionHandler.SessionIf /* ------------------------------------------------------------- */ /** * Call the activation listeners. This must be called holding the - * _lock. + * lock. */ public void didActivate() { @@ -340,7 +362,7 @@ public class Session implements SessionHandler.SessionIf /* ------------------------------------------------------------- */ /** * Call the passivation listeners. This must be called holding the - * _lock + * lock */ public void willPassivate() { @@ -573,7 +595,8 @@ public class Session implements SessionHandler.SessionIf /* ------------------------------------------------------------- */ /** - * asserts that the session is valid + * Check that the session can be modified. + * * @throws IllegalStateException if the session is invalid */ protected void checkValidForWrite() throws IllegalStateException @@ -590,7 +613,8 @@ public class Session implements SessionHandler.SessionIf /* ------------------------------------------------------------- */ /** - * asserts that the session is valid + * Chech that the session data can be read. + * * @throws IllegalStateException if the session is invalid */ protected void checkValidForRead () throws IllegalStateException @@ -764,6 +788,10 @@ public class Session implements SessionHandler.SessionIf } /* ------------------------------------------------------------ */ + /** Force a change to the id of a session. + * + * @param request the Request associated with the call to change id. + */ public void renewId(HttpServletRequest request) { if (_handler == null) @@ -846,6 +874,11 @@ public class Session implements SessionHandler.SessionIf } /* ------------------------------------------------------------- */ + /** Call HttpSessionAttributeListeners as part of invalidating + * a Session. + * + * @throws IllegalStateException + */ protected void doInvalidate() throws IllegalStateException { try (Lock lock = _lock.lockIfNotHeld()) @@ -928,12 +961,13 @@ public class Session implements SessionHandler.SessionIf return _sessionData; } - + /* ------------------------------------------------------------- */ public void setResident (boolean resident) { _resident = resident; } + /* ------------------------------------------------------------- */ public boolean isResident () { return _resident; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionCache.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionCache.java index 7d864ac2711..5b3c5eab75c 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionCache.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionCache.java @@ -28,28 +28,31 @@ import org.eclipse.jetty.util.component.LifeCycle; /** * SessionCache * - * A set of Session objects for a context that are actively being - * managed by this context instance. + * A working set of {@link Session} objects for a context. * - * Multiple requests for the same session id on the same context should always - * share the same Session object from the SessionCache. + * Ideally, multiple requests for the same session id in the same context will always + * share the same Session object from the SessionCache, but it would be possible + * for implementations of SessionCache to create a fresh object for each request. * - * The data for the Session objects is obtained from, and written to a SessionDataStore. - * It is assumed that the SessionDataStore is the authoritative source of session data: + * The SessionData pertaining to the Session objects is obtained from/written to a SessionDataStore. + * The SessionDataStore is the authoritative source of session data: * * - * Examples of SessionDataStores are relational or nosql databases, filesystems, or other - * distributed mechanisms. + * A SessionCache can passivate a valid Session to the SessionDataStore and + * evict it from the cache according to various strategies: + * . * - * A SessionCache is optionally able to passivate a managed Session to the SessionDataStore and - * evict it from the cache if it has been in memory, but not accessed for a configurable amount of time. + * Eviction can save memory, and can also help mitigate + * some of the problems of a non-sticky load balancer by forcing the session data to + * be re-read from the SessionDataStore more frequently. * - * Implementations of the SessionCache may also implement different strategies for writing out - * Session data to the SessionDataStore. */ public interface SessionCache extends LifeCycle { @@ -59,27 +62,177 @@ public interface SessionCache extends LifeCycle + /** + * @param context + */ void initialize(SessionContext context); - SessionHandler getSessionHandler(); - Session newSession (HttpServletRequest request, String id, long time, long maxInactiveMs); - Session newSession (SessionData data); - Session renewSessionId (String oldId, String newId) throws Exception; - Session get(String id) throws Exception; - void put(String id, Session session) throws Exception; - boolean contains (String id) throws Exception; - boolean exists (String id) throws Exception; - Session delete (String id) throws Exception; + void shutdown (); + + + SessionHandler getSessionHandler(); + + + /** + * Create an entirely new Session. + * + * @param request + * @param id + * @param time + * @param maxInactiveMs + * @return + */ + Session newSession (HttpServletRequest request, String id, long time, long maxInactiveMs); + + /** + * Re-inflate a Session that has previously existed. + * @param data + * @return + */ + Session newSession (SessionData data); + + + /** + * Change the id of a Session. + * + * @param oldId + * @param newId + * @return + * @throws Exception + */ + Session renewSessionId (String oldId, String newId) throws Exception; + + + /** + * Get an existing Session. If necessary, the cache will load the data for + * the session from the configured SessionDataStore. + * + * @param id + * @return + * @throws Exception + */ + Session get(String id) throws Exception; + + + /** + * Finish using a Session. This is called by the SessionHandler + * once a request is finished with a Session. SessionCache + * implementations may want to delay writing out Session contents + * until the last request exits a Session. + * + * @param id + * @param session + * @throws Exception + */ + void put(String id, Session session) throws Exception; + + + /** + * Check to see if a Session is in the cache. Does NOT consult + * the SessionDataStore. + * + * @param id + * @return true if a Session object matching the id is present + * in the cache, false otherwise + * @throws Exception + */ + boolean contains (String id) throws Exception; + + + /** + * Check to see if a session exists: WILL consult the + * SessionDataStore. + * + * @param id + * @return + * @throws Exception + */ + boolean exists (String id) throws Exception; + + + /** + * Remove a Session completely: from both this + * cache and the SessionDataStore. + * + * @param id + * @return + * @throws Exception + */ + Session delete (String id) throws Exception; + + + /** + * Check a list of session ids that belong to potentially expired + * sessions. The Session in the cache should be checked, + * but also the SessionDataStore, as that is the authoritative + * source of all session information. + * + * @param candidates the session ids to check + * @return the set of session ids that have actually expired: this can + * be a superset of the original candidate list. + */ Set checkExpiration (Set candidates); - SessionDataStore getSessionDataStore(); - void setSessionDataStore(SessionDataStore sds); + + /** + * Check a Session to see if it might be appropriate to + * evict or expire. + * + * @param session + */ void checkInactiveSession(Session session); + + + /** + * A SessionDataStore that is the authoritative source + * of session information. + * @param sds + */ + void setSessionDataStore(SessionDataStore sds); + SessionDataStore getSessionDataStore(); + + + /** + * Sessions in this cache can be: + *
    + *
  • never evicted
  • + *
  • evicted once the last request exits
  • + *
  • evicted after a configurable period of inactivity
  • + *
+ * + * @param -1 is never evict; 0 is evict-on-exit; and any other positive + * value is the time in seconds that a session can be idle before it can + * be evicted. + */ void setEvictionPolicy (int policy); int getEvictionPolicy (); + + /** + * Whether or not a a session that is about to be evicted should + * be saved before being evicted. + * + * @param saveOnEvict + */ void setSaveOnInactiveEviction (boolean saveOnEvict); boolean isSaveOnInactiveEviction (); + + + /** + * Whether or not a session that is newly created should be + * immediately saved. If false, a session that is created and + * invalidated within a single request is never persisted. + * + * @param saveOnCreate + */ void setSaveOnCreate(boolean saveOnCreate); boolean isSaveOnCreate(); + + + /** + * If the data for a session exists but is unreadable, + * the SessionCache can instruct the SessionDataStore to delete it. + * + * @param removeUnloadableSessions + */ void setRemoveUnloadableSessions(boolean removeUnloadableSessions); boolean isRemoveUnloadableSessions(); } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java index 869797aae3a..2322927938a 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java @@ -1285,10 +1285,7 @@ public class SessionHandler extends ScopedHandler * when either the session has not been accessed for a * configurable amount of time, or the session itself * has passed its expiry. - *
    - *
  • for being expired
  • - *
  • for being idle
  • - *
+ * * @param session */ public void sessionInactivityTimerExpired (Session session)