Implement uniform expiry testing for all datastores, FileDataStore still todo.

This commit is contained in:
Jan Bartel 2016-03-05 16:00:34 +01:00
parent 5fa6bf4c10
commit 303aea96a3
12 changed files with 358 additions and 145 deletions

View File

@ -30,6 +30,7 @@ import org.eclipse.jetty.server.session.AbstractSessionDataStore;
import org.eclipse.jetty.server.session.SessionContext;
import org.eclipse.jetty.server.session.SessionData;
import org.eclipse.jetty.util.ClassLoadingObjectInputStream;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -78,11 +79,6 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
private KeyFactory _keyFactory;
private int _maxResults = DEFAULT_MAX_QUERY_RESULTS;
@ -189,57 +185,90 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
* @see org.eclipse.jetty.server.session.SessionDataStore#getExpired(java.util.Set)
*/
@Override
public Set<String> getExpired(Set<String> candidates)
public Set<String> doGetExpired(Set<String> candidates, int expiryTimeoutSec)
{
long now = System.currentTimeMillis();
Set<String> expired = new HashSet<String>();
//get up to maxResult number of sessions that have expired
ProjectionEntityQueryBuilder pbuilder = Query.projectionEntityQueryBuilder();
pbuilder.addProjection(Projection.property(ID));
pbuilder.filter(CompositeFilter.and(PropertyFilter.gt(EXPIRY, 0), PropertyFilter.le(EXPIRY, now)));
pbuilder.limit(_maxResults);
pbuilder.kind(KIND);
StructuredQuery<ProjectionEntity> pquery = pbuilder.build();
QueryResults<ProjectionEntity> presults = _datastore.run(pquery);
while (presults.hasNext())
{
ProjectionEntity pe = presults.next();
String id = pe.getString(ID);
expired.add(id);
}
//reconcile against ids that the SessionStore thinks are expired
Set<String> tmp = new HashSet<String>(candidates);
tmp.removeAll(expired);
if (!tmp.isEmpty())
{
//sessionstore thinks these are expired, but they are either no
//longer in the db or not expired in the db, or we exceeded the
//number of records retrieved by the expiry query, so check them
//individually
for (String s:tmp)
{
try
{
KeyQueryBuilder kbuilder = Query.keyQueryBuilder();
kbuilder.filter(PropertyFilter.eq(ID, s));
kbuilder.kind(KIND);
StructuredQuery<Key> kq = kbuilder.build();
QueryResults<Key> kresults = _datastore.run(kq);
if (!kresults.hasNext())
expired.add(s); //not in db, can be expired
}
catch (Exception e)
{
LOG.warn(e);
}
}
}
return expired;
long now = System.currentTimeMillis();
Set<String> expired = new HashSet<String>();
try
{
//get up to maxResult number of sessions that have expired
ProjectionEntityQueryBuilder pbuilder = Query.projectionEntityQueryBuilder();
pbuilder.addProjection(Projection.property(ID), Projection.property(LASTNODE), Projection.property(EXPIRY));
pbuilder.filter(CompositeFilter.and(PropertyFilter.gt(EXPIRY, 0), PropertyFilter.le(EXPIRY, now)));
pbuilder.limit(_maxResults);
pbuilder.kind(KIND);
StructuredQuery<ProjectionEntity> pquery = pbuilder.build();
QueryResults<ProjectionEntity> presults = _datastore.run(pquery);
while (presults.hasNext())
{
ProjectionEntity pe = presults.next();
String id = pe.getString(ID);
String lastNode = pe.getString(LASTNODE);
long expiry = pe.getLong(EXPIRY);
if (StringUtil.isBlank(lastNode))
expired.add(id); //nobody managing it
else
{
if (_context.getWorkerName().equals(lastNode))
expired.add(id); //we're managing it, we can expire it
else
{
if (_lastExpiryCheckTime <= 0)
{
//our first check, just look for sessions that we managed by another node that
//expired at least 3 graceperiods ago
if (expiry < (now - (1000L * (3 * _gracePeriodSec))))
expired.add(id);
}
else
{
//another node was last managing it, only expire it if it expired a graceperiod ago
if (expiry < (now - (1000L * _gracePeriodSec)))
expired.add(id);
}
}
}
}
//reconcile against ids that the SessionStore thinks are expired
Set<String> tmp = new HashSet<String>(candidates);
tmp.removeAll(expired);
if (!tmp.isEmpty())
{
//sessionstore thinks these are expired, but they are either no
//longer in the db or not expired in the db, or we exceeded the
//number of records retrieved by the expiry query, so check them
//individually
for (String s:tmp)
{
try
{
KeyQueryBuilder kbuilder = Query.keyQueryBuilder();
kbuilder.filter(PropertyFilter.eq(ID, s));
kbuilder.kind(KIND);
StructuredQuery<Key> kq = kbuilder.build();
QueryResults<Key> kresults = _datastore.run(kq);
if (!kresults.hasNext())
expired.add(s); //not in db, can be expired
}
catch (Exception e)
{
LOG.warn(e);
}
}
}
return expired;
}
catch (Exception e)
{
LOG.warn(e);
return expired; //return what we got
}
}
@ -297,6 +326,8 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
oos.writeObject(session.getAllAttributes());
oos.flush();
try
{
//turn a session into an entity
entity = Entity.builder(key)
.set(ID, session.getId())
@ -310,6 +341,12 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
.set(EXPIRY, session.getExpiry())
.set(MAXINACTIVE, session.getMaxInactiveMs())
.set(ATTRIBUTES, Blob.copyFrom(baos.toByteArray())).build();
}
catch (Exception e)
{
e.printStackTrace();
throw e;
}
return entity;
}

View File

@ -134,7 +134,7 @@ public class InfinispanSessionDataStore extends AbstractSessionDataStore
* @see org.eclipse.jetty.server.session.SessionDataStore#getExpired(java.util.Set)
*/
@Override
public Set<String> getExpired(Set<String> candidates)
public Set<String> doGetExpired(Set<String> candidates, int expiryTimeoutSec)
{
if (candidates == null || candidates.isEmpty())
return candidates;
@ -143,6 +143,9 @@ public class InfinispanSessionDataStore extends AbstractSessionDataStore
Set<String> expired = new HashSet<String>();
//TODO if there is NOT an idle timeout set, need to check other sessions that
//might have expired
for (String candidate:candidates)
{
if (LOG.isDebugEnabled())
@ -151,12 +154,43 @@ public class InfinispanSessionDataStore extends AbstractSessionDataStore
{
SessionData sd = load(candidate);
if (sd == null || sd.isExpiredAt(now))
//if the session no longer exists
if (sd == null)
{
expired.add(candidate);
if (LOG.isDebugEnabled())
LOG.debug("Is null {} is expired {}", (sd==null), (sd !=null));
}
LOG.debug("Session {} does not exist in infinispan", candidate);
}
else
{
if (_context.getWorkerName().equals(sd.getLastNode()))
{
//we are its manager, add it to the expired set if it is expired now
if ((sd.getExpiry() > 0 ) && sd.getExpiry() <= now)
{
expired.add(candidate);
if (LOG.isDebugEnabled())
LOG.debug("Session {} managed by {} is expired", candidate, _context.getWorkerName());
}
}
else
{
//if we are not the session's manager, only expire it iff:
// this is our first expiryCheck and the session expired a long time ago
//or
//the session expired at least one graceperiod ago
if (_lastExpiryCheckTime <=0)
{
if ((sd.getExpiry() > 0 ) && sd.getExpiry() < (now - (1000L * (3 * _gracePeriodSec))))
expired.add(candidate);
}
else
{
if ((sd.getExpiry() > 0 ) && sd.getExpiry() < (now - (1000L * _gracePeriodSec)))
expired.add(candidate);
}
}
}
}
catch (Exception e)
{
@ -193,6 +227,11 @@ public class InfinispanSessionDataStore extends AbstractSessionDataStore
}
/**
* @param id
* @param context
* @return
*/
public static String getCacheKey (String id, SessionContext context)
{
return context.getCanonicalContextPath()+"_"+context.getVhost()+"_"+id;
@ -224,11 +263,17 @@ public class InfinispanSessionDataStore extends AbstractSessionDataStore
/**
* @param sec the infinispan-specific idle timeout in sec or 0 if not set
*/
public void setInfinispanIdleTimeoutSec (int sec)
{
_infinispanIdleTimeoutSec = sec;
}
/**
* @return
*/
public int getInfinispanIdleTimeoutSec ()
{
return _infinispanIdleTimeoutSec;

View File

@ -153,8 +153,6 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
private DBCollection _dbSessions;
private long _gracePeriodMs = 1000L * 60 * 60; //default grace period is 1hr
public void setDBCollection (DBCollection collection)
{
_dbSessions = collection;
@ -169,24 +167,7 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
return _dbSessions;
}
/**
* @return
*/
public int getGracePeriodSec ()
{
return (int)(_gracePeriodMs == 0L? 0 : _gracePeriodMs/1000L);
}
/**
* @param sec
*/
public void setGracePeriodSec (int sec)
{
if (sec < 0)
_gracePeriodMs = 0;
else
_gracePeriodMs = sec * 1000L;
}
/**
* @see org.eclipse.jetty.server.session.SessionDataStore#load(org.eclipse.jetty.server.session.SessionKey)
@ -342,12 +323,14 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
* @see org.eclipse.jetty.server.session.SessionDataStore#getExpired(java.util.Set)
*/
@Override
public Set<String> getExpired(Set<String> candidates)
public Set<String> doGetExpired(Set<String> candidates, int expiryTimeoutSec)
{
long upperBound = System.currentTimeMillis();
long now = System.currentTimeMillis();
long upperBound = now;
Set<String> expiredSessions = new HashSet<>();
//firstly ask mongo to verify if these candidate ids have expired
//firstly ask mongo to verify if these candidate ids have expired - all of
//these candidates will be for our node
BasicDBObject query = new BasicDBObject();
query.put(__ID,new BasicDBObject("$in", candidates));
query.put(__EXPIRY, new BasicDBObject("$gt", 0));
@ -369,9 +352,13 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
if (verifiedExpiredSessions != null) verifiedExpiredSessions.close();
}
//now ask mongo to find sessions that expired a while ago
upperBound = upperBound - (3 * _gracePeriodMs);
//now ask mongo to find sessions last managed by other nodes that expired a while ago
//if this is our first expiry check, make sure that we only grab really old sessions
if (_lastExpiryCheckTime <= 0)
upperBound = (now - (3*(1000L * _gracePeriodSec)));
else
upperBound = _lastExpiryCheckTime - (1000L * _gracePeriodSec);
query.clear();
query.put(__EXPIRY, new BasicDBObject("$gt", 0));
query.put(__EXPIRY, new BasicDBObject("$lt", upperBound));

View File

@ -20,6 +20,8 @@
package org.eclipse.jetty.server.session;
import java.util.Set;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
/**
@ -30,6 +32,8 @@ import org.eclipse.jetty.util.component.AbstractLifeCycle;
public abstract class AbstractSessionDataStore extends AbstractLifeCycle implements SessionDataStore
{
protected SessionContext _context; //context associated with this session data store
protected int _gracePeriodSec = 60 * 60; //default of 1hr
protected long _lastExpiryCheckTime = 0; //last time in ms that getExpired was called
/**
@ -43,6 +47,16 @@ public abstract class AbstractSessionDataStore extends AbstractLifeCycle impleme
public abstract void doStore(String id, SessionData data, long lastSaveTime) throws Exception;
/**
* Implemented by subclasses to resolve which sessions this node
* should attempt to expire.
*
* @param candidates the ids of sessions the SessionStore thinks has expired
* @param scavengePeriodSec the period in sec of the scavenge cycle checks
* @return the reconciled set of session ids that this node should attempt to expire
* @throws Exception
*/
public abstract Set<String> doGetExpired (Set<String> candidates, int scavengePeriodSec);
/**
@ -81,6 +95,25 @@ public abstract class AbstractSessionDataStore extends AbstractLifeCycle impleme
/**
* @see org.eclipse.jetty.server.session.SessionDataStore#getExpired(java.util.Set, int)
*/
@Override
public Set<String> getExpired(Set<String> candidates, int scavengePeriodSec)
{
try
{
return doGetExpired (candidates, scavengePeriodSec);
}
finally
{
_lastExpiryCheckTime = System.currentTimeMillis();
}
}
/**
* @see org.eclipse.jetty.server.session.SessionDataStore#newSessionData(java.lang.String, long, long, long, long)
*/
@ -110,7 +143,29 @@ public abstract class AbstractSessionDataStore extends AbstractLifeCycle impleme
super.doStart();
}
/**
* @return
*/
public int getGracePeriodSec()
{
return _gracePeriodSec;
}
/**
* @param sec
*/
public void setGracePeriodSec(int sec)
{
_gracePeriodSec = sec;
}
}

View File

@ -565,7 +565,7 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
if (LOG.isDebugEnabled())
LOG.debug("SessionStore checking expiration on {}", candidates);
return _sessionDataStore.getExpired(candidates);
return _sessionDataStore.getExpired(candidates, _expiryTimeoutSec);
}

View File

@ -119,7 +119,7 @@ public class CachingSessionDataStore extends AbstractSessionDataStore
* @see org.eclipse.jetty.server.session.SessionDataStore#getExpired(java.util.Set)
*/
@Override
public Set<String> getExpired(Set<String> candidates)
public Set<String> doGetExpired(Set<String> candidates, int expiryTimeoutSec)
{
// TODO Auto-generated method stub
return null;

View File

@ -114,7 +114,7 @@ public class FileSessionDataStore extends AbstractSessionDataStore
* @see org.eclipse.jetty.server.session.SessionDataStore#getExpired(java.util.Set)
*/
@Override
public Set<String> getExpired(Set<String> candidates)
public Set<String> doGetExpired(Set<String> candidates, int expiryTimeoutSec)
{
//we don't want to open up each file and check, so just leave it up to the SessionStore
//TODO as the session manager is likely to be a lazy loader, if a session is never requested, its

View File

@ -58,8 +58,7 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
private int _attempts = -1; // <= 0 means unlimited attempts to load a session
private boolean _deleteUnloadables = false; //true means if attempts exhausted delete the session
private long _gracePeriodMs = 1000L * 60 * 60; //default grace period is 1hr
/**
* SessionTableSchema
*
@ -285,7 +284,7 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
}
public PreparedStatement getMyExpiredSessionsStatement (Connection connection, String canonicalContextPath, String vhost, long expiry)
public PreparedStatement getExpiredSessionsStatement (Connection connection, String canonicalContextPath, String vhost, long expiry)
throws SQLException
{
if (_dbAdaptor == null)
@ -317,6 +316,42 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
return statement;
}
public PreparedStatement getMyExpiredSessionsStatement (Connection connection, SessionContext sessionContext, long expiry)
throws SQLException
{
if (_dbAdaptor == null)
throw new IllegalStateException("No DB adaptor");
if (sessionContext.getCanonicalContextPath() == null || "".equals(sessionContext.getCanonicalContextPath()))
{
if (_dbAdaptor.isEmptyStringNull())
{
PreparedStatement statement = connection.prepareStatement("select "+getIdColumn()+", "+getExpiryTimeColumn()+
" from "+getTableName()+" where "+
getLastNodeColumn() + " = ? and "+
getContextPathColumn()+" is null and "+
getVirtualHostColumn()+" = ? and "+getExpiryTimeColumn()+" >0 and "+getExpiryTimeColumn()+" <= ?");
statement.setString(1, sessionContext.getWorkerName());
statement.setString(2, sessionContext.getVhost());
statement.setLong(3, expiry);
return statement;
}
}
PreparedStatement statement = connection.prepareStatement("select "+getIdColumn()+", "+getExpiryTimeColumn()+
" from "+getTableName()+" where "+
getLastNodeColumn()+" = ? and "+
getContextPathColumn()+" = ? and "+
getVirtualHostColumn()+" = ? and "+
getExpiryTimeColumn()+" >0 and "+getExpiryTimeColumn()+" <= ?");
statement.setString(1, sessionContext.getWorkerName());
statement.setString(2, sessionContext.getCanonicalContextPath());
statement.setString(3, sessionContext.getVhost());
statement.setLong(4, expiry);
return statement;
}
public PreparedStatement getAllAncientExpiredSessionsStatement (Connection connection)
@ -804,6 +839,7 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
}
}
private void doUpdate (String id, SessionData data)
throws Exception
{
@ -854,27 +890,26 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
* @see org.eclipse.jetty.server.session.SessionDataStore#getExpired(java.util.Set)
*/
@Override
public Set<String> getExpired(Set<String> candidates)
public Set<String> doGetExpired(Set<String> candidates, int scavengeIntervalSec)
{
if (LOG.isDebugEnabled())
LOG.debug("Getting expired sessions "+System.currentTimeMillis());
long now = System.currentTimeMillis();
Set<String> expiredSessionKeys = new HashSet<>();
try (Connection connection = _dbAdaptor.getConnection())
{
connection.setAutoCommit(true);
/*
* 1. Select sessions for our context that have expired
* 1. Select sessions managed by this node for our context that have expired
*/
long upperBound = now;
if (LOG.isDebugEnabled())
LOG.debug ("{}- Pass 1: Searching for sessions for context {} expired before {}", _context.getWorkerName(), _context.getCanonicalContextPath(), upperBound);
LOG.debug ("{}- Pass 1: Searching for sessions for context {} managed by me {} and expired before {}", _context.getCanonicalContextPath(), _context.getWorkerName(), upperBound);
try (PreparedStatement statement = _sessionTableSchema.getMyExpiredSessionsStatement(connection, _context.getCanonicalContextPath(), _context.getVhost(), upperBound))
try (PreparedStatement statement = _sessionTableSchema.getExpiredSessionsStatement(connection, _context.getCanonicalContextPath(), _context.getVhost(), upperBound))
{
try (ResultSet result = statement.executeQuery())
{
@ -889,30 +924,33 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
}
/*
* 2. Select sessions for any node or context that have expired a long time ago (ie at least 3 grace periods ago)
* 2. Select sessions for any node or context that have expired
* at least 1 graceperiod since the last expiry check. If we haven't done previous expiry checks, then check
* those that have expired at least 3 graceperiod ago.
*/
try (PreparedStatement selectExpiredSessions = _sessionTableSchema.getAllAncientExpiredSessionsStatement(connection))
{
upperBound = now - (3 * _gracePeriodMs);
if (upperBound > 0)
{
if (LOG.isDebugEnabled()) LOG.debug("{}- Pass 2: Searching for sessions expired before {}",_context.getWorkerName(), upperBound);
if (_lastExpiryCheckTime <= 0)
upperBound = (now - (3*(1000L * _gracePeriodSec)));
else
upperBound = _lastExpiryCheckTime - (1000L * _gracePeriodSec);
selectExpiredSessions.setLong(1, upperBound);
try (ResultSet result = selectExpiredSessions.executeQuery())
if (LOG.isDebugEnabled()) LOG.debug("{}- Pass 2: Searching for sessions expired before {}",_context.getWorkerName(), upperBound);
selectExpiredSessions.setLong(1, upperBound);
try (ResultSet result = selectExpiredSessions.executeQuery())
{
while (result.next())
{
while (result.next())
{
String sessionId = result.getString(_sessionTableSchema.getIdColumn());
String ctxtpth = result.getString(_sessionTableSchema.getContextPathColumn());
String vh = result.getString(_sessionTableSchema.getVirtualHostColumn());
expiredSessionKeys.add(sessionId);
if (LOG.isDebugEnabled()) LOG.debug ("{}- Found expired sessionId=",_context.getWorkerName(), sessionId);
}
String sessionId = result.getString(_sessionTableSchema.getIdColumn());
String ctxtpth = result.getString(_sessionTableSchema.getContextPathColumn());
String vh = result.getString(_sessionTableSchema.getVirtualHostColumn());
expiredSessionKeys.add(sessionId);
if (LOG.isDebugEnabled()) LOG.debug ("{}- Found expired sessionId=",_context.getWorkerName(), sessionId);
}
}
}
Set<String> notExpiredInDB = new HashSet<>();
for (String k: candidates)
@ -958,44 +996,48 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
LOG.warn(e);
return expiredSessionKeys; //return whatever we got
}
}
public int getGracePeriodSec ()
{
return (int)(_gracePeriodMs == 0L? 0 : _gracePeriodMs/1000L);
}
public void setGracePeriodSec (int sec)
{
if (sec < 0)
_gracePeriodMs = 0;
else
_gracePeriodMs = sec * 1000L;
}
/**
* @param dbAdaptor
*/
public void setDatabaseAdaptor (DatabaseAdaptor dbAdaptor)
{
checkStarted();
_dbAdaptor = dbAdaptor;
}
/**
* @param schema
*/
public void setSessionTableSchema (SessionTableSchema schema)
{
checkStarted();
_sessionTableSchema = schema;
}
/**
* @param attempts
*/
public void setLoadAttempts (int attempts)
{
checkStarted();
_attempts = attempts;
}
/**
* @return
*/
public int getLoadAttempts ()
{
return _attempts;
}
/**
* @param id
* @return
*/
public boolean loadAttemptsExhausted (String id)
{
AtomicInteger i = _unloadables.get(id);
@ -1004,18 +1046,27 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
return (i.get() >= _attempts);
}
/**
* @param delete
*/
public void setDeleteUnloadableSessions (boolean delete)
{
checkStarted();
_deleteUnloadables = delete;
}
/**
* @return true if we should delete data for sessions that we cant reconstitute
*/
public boolean isDeleteUnloadableSessions ()
{
return _deleteUnloadables;
}
/**
* @param id
*/
protected void incLoadAttempt (String id)
{
AtomicInteger i = new AtomicInteger(0);
@ -1027,6 +1078,10 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
/**
* @param id
* @return number of attempts to load the given id
*/
public int getLoadAttempts (String id)
{
AtomicInteger i = _unloadables.get(id);
@ -1035,15 +1090,21 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
return i.get();
}
/**
* @return how many sessions we've failed to load
*/
public Set<String> getUnloadableSessions ()
{
return new HashSet<String>(_unloadables.keySet());
}
public void clearUnloadableSessions()
{
_unloadables.clear();
}
/**
*
*/
public void clearUnloadableSessions()
{
_unloadables.clear();
}

View File

@ -72,7 +72,7 @@ public class NullSessionDataStore extends AbstractSessionDataStore
* @see org.eclipse.jetty.server.session.SessionDataStore#getExpired(java.util.Set)
*/
@Override
public Set<String> getExpired(Set<String> candidates)
public Set<String> doGetExpired(Set<String> candidates, int expiryTimeoutSec)
{
return candidates; //whatever is suggested we accept
}

View File

@ -433,4 +433,23 @@ public class SessionData implements Serializable
return (getExpiry() < time);
}
/**
* @see java.lang.Object#toString()
*/
public String toString()
{
StringBuilder builder = new StringBuilder();
builder.append("id="+_id);
builder.append(", contextpath="+_contextPath);
builder.append(", vhost="+_vhost);
builder.append(", accessed="+_accessed);
builder.append(", lastaccessed="+_lastAccessed);
builder.append(", created="+_created);
builder.append(", cookieset="+_cookieSet);
builder.append(", lastnode="+_lastNode);
builder.append(", expiry="+_expiry);
builder.append(", maxinactive="+_maxInactiveMs);
return builder.toString();
}
}

View File

@ -95,7 +95,7 @@ public interface SessionDataStore extends LifeCycle
* SessionDataStore
* @return set of session ids
*/
public Set<String> getExpired (Set<String> candidates);
public Set<String> getExpired (Set<String> candidates, int scavengePeriodSec);

View File

@ -139,7 +139,7 @@ public abstract class AbstractSessionInvalidateAndCreateTest
assertTrue(listener.destroys.contains("session1"));
assertTrue(listener.destroys.contains("session2"));
//session2's HttpSessionBindingListener should have been called when it was scavenged
assertTrue(servlet.unbound);
assertTrue(servlet.listener.unbound);
}
finally
{
@ -151,24 +151,33 @@ public abstract class AbstractSessionInvalidateAndCreateTest
server.stop();
}
}
public static class Foo implements Serializable
{
public boolean bar = false;
public boolean getBar() { return bar;};
}
public static class TestServlet extends HttpServlet
public static class MySessionBindingListener implements HttpSessionBindingListener, Serializable
{
private boolean unbound = false;
public class MySessionBindingListener implements HttpSessionBindingListener, Serializable
public void valueUnbound(HttpSessionBindingEvent event)
{
unbound = true;
}
public void valueBound(HttpSessionBindingEvent event)
{
public void valueUnbound(HttpSessionBindingEvent event)
{
unbound = true;
}
public void valueBound(HttpSessionBindingEvent event)
{
}
}
}
public static class TestServlet extends HttpServlet
{
public MySessionBindingListener listener = new MySessionBindingListener();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse httpServletResponse) throws ServletException, IOException
@ -190,7 +199,7 @@ public abstract class AbstractSessionInvalidateAndCreateTest
//now make a new session
session = request.getSession(true);
session.setAttribute("identity", "session2");
session.setAttribute("listener", new MySessionBindingListener());
session.setAttribute("listener", listener);
}
else
fail("Session already missing");