public Session findSession(String id) throws IOException {
Session session = super.findSession(id);
+ // OK, at this point, we're not sure if another thread is trying to
+ // remove the session or not so the only way around this is to lock it
+ // (or attempt to) and then try to get it by this session id again. If
+ // the other code ran swapOut, then we should get a null back during
+ // this run, and if not, we lock it out so we can access the session
+ // safely.
+ if(session != null) {
+ synchronized(session){
+ session = super.findSession(session.getIdInternal());
+ if(session != null){
+ // To keep any external calling code from messing up the
+ // concurrency.
+ session.access();
+ session.endAccess();
+ }
+ }
+ }
if (session != null)
return (session);
long timeNow = System.currentTimeMillis();
// Swap out all sessions idle longer than maxIdleSwap
- // FIXME: What's preventing us from mangling a session during
- // a request?
if (maxIdleSwap >= 0) {
for (int i = 0; i < sessions.length; i++) {
StandardSession session = (StandardSession) sessions[i];
- if (!session.isValid())
- continue;
- int timeIdle = // Truncate, do not round up
- (int) ((timeNow - session.getLastAccessedTime()) / 1000L);
- if (timeIdle > maxIdleSwap && timeIdle > minIdleSwap) {
- if (log.isDebugEnabled())
- log.debug(sm.getString
- ("persistentManager.swapMaxIdle",
- session.getIdInternal(), new Integer(timeIdle)));
- try {
- swapOut(session);
- } catch (IOException e) {
- ; // This is logged in writeSession()
+ synchronized (session) {
+ if (!session.isValid())
+ continue;
+ int timeIdle = // Truncate, do not round up
+ (int) ((timeNow - session.getLastAccessedTime()) / 1000L);
+ if (timeIdle > maxIdleSwap && timeIdle > minIdleSwap) {
+ if (log.isDebugEnabled())
+ log.debug(sm.getString
+ ("persistentManager.swapMaxIdle",
+ session.getIdInternal(), new Integer(timeIdle)));
+ try {
+ swapOut(session);
+ } catch (IOException e) {
+ ; // This is logged in writeSession()
+ }
}
}
}
long timeNow = System.currentTimeMillis();
for (int i = 0; i < sessions.length && toswap > 0; i++) {
- int timeIdle = // Truncate, do not round up
- (int) ((timeNow - sessions[i].getLastAccessedTime()) / 1000L);
- if (timeIdle > minIdleSwap) {
- if(log.isDebugEnabled())
- log.debug(sm.getString
- ("persistentManager.swapTooManyActive",
- sessions[i].getIdInternal(), new Integer(timeIdle)));
- try {
- swapOut(sessions[i]);
- } catch (IOException e) {
- ; // This is logged in writeSession()
+ synchronized (sessions[i]) {
+ int timeIdle = // Truncate, do not round up
+ (int) ((timeNow - sessions[i].getLastAccessedTime()) / 1000L);
+ if (timeIdle > minIdleSwap) {
+ if(log.isDebugEnabled())
+ log.debug(sm.getString
+ ("persistentManager.swapTooManyActive",
+ sessions[i].getIdInternal(), new Integer(timeIdle)));
+ try {
+ swapOut(sessions[i]);
+ } catch (IOException e) {
+ ; // This is logged in writeSession()
+ }
+ toswap--;
}
- toswap--;
}
}
if (maxIdleBackup >= 0) {
for (int i = 0; i < sessions.length; i++) {
StandardSession session = (StandardSession) sessions[i];
- if (!session.isValid())
- continue;
- int timeIdle = // Truncate, do not round up
- (int) ((timeNow - session.getLastAccessedTime()) / 1000L);
- if (timeIdle > maxIdleBackup) {
- if (log.isDebugEnabled())
- log.debug(sm.getString
- ("persistentManager.backupMaxIdle",
- session.getIdInternal(), new Integer(timeIdle)));
-
- try {
- writeSession(session);
- } catch (IOException e) {
- ; // This is logged in writeSession()
+ synchronized (session) {
+ if (!session.isValid())
+ continue;
+ int timeIdle = // Truncate, do not round up
+ (int) ((timeNow - session.getLastAccessedTime()) / 1000L);
+ if (timeIdle > maxIdleBackup) {
+ if (log.isDebugEnabled())
+ log.debug(sm.getString
+ ("persistentManager.backupMaxIdle",
+ session.getIdInternal(), new Integer(timeIdle)));
+
+ try {
+ writeSession(session);
+ } catch (IOException e) {
+ ; // This is logged in writeSession()
+ }
}
}
}
import org.apache.catalina.Store;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
-import org.apache.catalina.core.StandardHost;
import org.apache.catalina.session.PersistentManager;
import org.apache.catalina.util.StringManager;
/**
- * Valve that implements the default basic behavior for the
- * <code>StandardHost</code> container implementation.
+ * Valve that implements per-request session persistence. It is intended to be
+ * used with non-sticky load-balancers.
* <p>
* <b>USAGE CONSTRAINT</b>: To work correctly it requires a PersistentManager.
+ * <p>
+ * <b>USAGE CONSTRAINT</b>: To work correctly it assumes only one request exists
+ * per session at any one time.
*
* @author Jean-Frederic Clere
* @version $Revision$ $Date$
throws IOException, ServletException {
// Select the Context to be used for this Request
- StandardHost host = (StandardHost) getContainer();
Context context = request.getContext();
if (context == null) {
response.sendError