Make jdbc session tests work

This commit is contained in:
Jan Bartel 2015-11-11 18:31:38 +11:00
parent 84239bc7f2
commit b0748c5865
31 changed files with 611 additions and 310 deletions

View File

@ -33,8 +33,8 @@ import org.eclipse.jetty.util.log.Logger;
public abstract class AbstractSessionIdManager extends AbstractLifeCycle implements SessionIdManager
{
private static final Logger LOG = Log.getLogger(AbstractSessionIdManager.class);
private final static Logger LOG = Log.getLogger("org.eclipse.jetty.server.session");
private final static String __NEW_SESSION_ID="org.eclipse.jetty.server.newSessionId";
protected Random _random;
@ -243,7 +243,6 @@ public abstract class AbstractSessionIdManager extends AbstractLifeCycle impleme
}
_scavenger.start();
System.err.println("Started scavenger "+_scavenger);
}
/* ------------------------------------------------------------ */
@ -345,6 +344,7 @@ public abstract class AbstractSessionIdManager extends AbstractLifeCycle impleme
{
//take the id out of the list of known sessionids for this node
removeId(id);
//tell all contexts that may have a session object with this id to
//get rid of them
Handler[] contexts = _server.getChildHandlersByClass(ContextHandler.class);

View File

@ -20,10 +20,14 @@
package org.eclipse.jetty.server.session;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.statistic.CounterStatistic;
/**
* AbstractSessionStore
@ -32,26 +36,75 @@ import org.eclipse.jetty.util.component.AbstractLifeCycle;
*/
public abstract class AbstractSessionStore extends AbstractLifeCycle implements SessionStore
{
final static Logger LOG = Log.getLogger("org.eclipse.jetty.server.session");
protected SessionDataStore _sessionDataStore;
protected StalenessStrategy _staleStrategy;
protected SessionManager _manager;
protected final CounterStatistic _sessionStats = new CounterStatistic();
/**
* Create a new Session object from session data
* @param data
* @return
*/
public abstract Session newSession (SessionData data);
/**
* Get the session matching the key
* @param key
* @return
*/
public abstract Session doGet(SessionKey key);
public abstract void doPut (SessionKey key, Session session);
/**
* Put the session into the map if it wasn't already there
*
* @param key the identity of the session
* @param session the session object
* @return null if the session wasn't already in the map, or the existing entry otherwise
*/
public abstract Session doPutIfAbsent (SessionKey key, Session session);
/**
* Check to see if the session exists in the store
* @param key
* @return
*/
public abstract boolean doExists (SessionKey key);
public abstract void doDelete (SessionKey key);
/**
* Remove the session with this identity from the store
* @param key
* @return the removed Session or null if no such key
*/
public abstract Session doDelete (SessionKey key);
/**
* Get a list of keys for sessions that the store thinks has expired
* @return
*/
public abstract Set<SessionKey> doGetExpiredCandidates();
/**
*
*/
public AbstractSessionStore ()
{
}
@ -126,11 +179,21 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
* @see org.eclipse.jetty.server.session.SessionStore#get(java.lang.String)
*/
@Override
public Session get(SessionKey key) throws Exception
public Session get(SessionKey key, boolean staleCheck) throws Exception
{
//look locally
Session session = doGet(key);
if (staleCheck && isStale(session))
{
//delete from memory so should reload
doDelete(key);
session = null;
_sessionStats.decrement();
}
//not in session store, load the data for the session if possible
if (session == null && _sessionDataStore != null)
{
@ -139,7 +202,15 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
{
session = newSession(data);
session.setSessionManager(_manager);
doPut(key, session);
Session existing = doPutIfAbsent(key, session);
if (existing != null)
{
//some other thread has got in first and added the session
//so use it
session = existing;
}
else
_sessionStats.increment();
}
}
return session;
@ -159,9 +230,20 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
throw new IllegalArgumentException ("Put key="+key+" session="+(session==null?"null":session.getId()));
session.setSessionManager(_manager);
//if the session is already in our cache, then we want to write through any changes
if (doExists(key))
Session existing = doPutIfAbsent(key,session);
if (existing == null)
{
//session not already in cache write through
if (_sessionDataStore != null)
{
session.willPassivate();
_sessionDataStore.store(SessionKey.getKey(session.getSessionData()), session.getSessionData());
session.didActivate();
}
_sessionStats.increment();
}
else
{
//if the session data has changed, or the cache is considered stale, write it to any backing store
if ((session.getSessionData().isDirty() || isStale(session)) && _sessionDataStore != null)
@ -171,18 +253,6 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
session.didActivate();
}
}
else
{
//session not already in cache, add it and write through
if (_sessionDataStore != null)
{
session.willPassivate();
_sessionDataStore.store(SessionKey.getKey(session.getSessionData()), session.getSessionData());
session.didActivate();
}
doPut(key,session);
}
}
/**
@ -207,11 +277,17 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
@Override
public boolean delete(SessionKey key) throws Exception
{
boolean deleted = true;
if (_sessionDataStore != null)
deleted = _sessionDataStore.delete(key);
doDelete(key);
return deleted;
{
boolean dsdel = _sessionDataStore.delete(key);
if (LOG.isDebugEnabled()) LOG.debug("Session {} deleted in db {}",key, dsdel);
}
if (doDelete(key) != null)
{
_sessionStats.decrement();
return true;
}
return false;
}
public boolean isStale (Session session)
@ -235,4 +311,46 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
return _sessionDataStore.getExpired(candidates);
}
@Override
public Session newSession(HttpServletRequest request, SessionKey key, long time, long maxInactiveMs)
{
return null;
}
@Override
public int getSessions()
{
return (int)_sessionStats.getCurrent();
}
@Override
public int getSessionsMax()
{
return (int)_sessionStats.getMax();
}
@Override
public int getSessionsTotal()
{
return (int)_sessionStats.getTotal();
}
@Override
public void resetStats()
{
_sessionStats.reset();
}
}

View File

@ -41,7 +41,7 @@ import org.eclipse.jetty.util.log.Logger;
/**
* FileSessionDataStore
*
*
* A file-based store of session data.
*/
public class FileSessionDataStore extends AbstractSessionDataStore
{

View File

@ -50,7 +50,6 @@ public class HashSessionIdManager extends AbstractSessionIdManager
public String newSessionId(long seedTerm)
{
String id = super.newSessionId(seedTerm);
useId(id);
return id;
}

View File

@ -25,12 +25,15 @@ import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@ -43,14 +46,13 @@ import org.eclipse.jetty.util.log.Logger;
/**
* JDBCSessionDataStore
*
*
* Session data stored in database
*/
public class JDBCSessionDataStore extends AbstractSessionDataStore
{
final static Logger LOG = Log.getLogger("org.eclipse.jetty.server.session");
protected boolean _initialized = false;
protected long _lastScavengeTime = 0;
protected Map<SessionKey, AtomicInteger> _unloadables = new ConcurrentHashMap<>();
private DatabaseAdaptor _dbAdaptor;
@ -58,6 +60,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
@ -69,7 +72,6 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
protected DatabaseAdaptor _dbAdaptor;
protected String _tableName = "JettySessions";
protected String _rowIdColumn = "rowId";
protected String _idColumn = "sessionId";
protected String _contextPathColumn = "contextPath";
protected String _virtualHostColumn = "virtualHost";
@ -100,23 +102,7 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
checkNotNull(tableName);
_tableName = tableName;
}
public String getRowIdColumn()
{
if ("rowId".equals(_rowIdColumn) && _dbAdaptor.isRowIdReserved())
_rowIdColumn = "srowId";
return _rowIdColumn;
}
public void setRowIdColumn(String rowIdColumn)
{
checkNotNull(rowIdColumn);
if (_dbAdaptor == null)
throw new IllegalStateException ("DbAdaptor is null");
if (_dbAdaptor.isRowIdReserved() && "rowId".equals(rowIdColumn))
throw new IllegalArgumentException("rowId is reserved word for Oracle");
_rowIdColumn = rowIdColumn;
}
public String getIdColumn()
{
return _idColumn;
@ -234,11 +220,11 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
String blobType = _dbAdaptor.getBlobType();
String longType = _dbAdaptor.getLongType();
return "create table "+_tableName+" ("+getRowIdColumn()+" varchar(120), "+_idColumn+" varchar(120), "+
return "create table "+_tableName+" ("+_idColumn+" varchar(120), "+
_contextPathColumn+" varchar(60), "+_virtualHostColumn+" varchar(60), "+_lastNodeColumn+" varchar(60), "+_accessTimeColumn+" "+longType+", "+
_lastAccessTimeColumn+" "+longType+", "+_createTimeColumn+" "+longType+", "+_cookieTimeColumn+" "+longType+", "+
_lastSavedTimeColumn+" "+longType+", "+_expiryTimeColumn+" "+longType+", "+_maxIntervalColumn+" "+longType+", "+
_mapColumn+" "+blobType+", primary key("+getRowIdColumn()+"))";
_mapColumn+" "+blobType+", primary key("+_idColumn+", "+_contextPathColumn+","+_virtualHostColumn+"))";
}
public String getCreateIndexOverExpiryStatementAsString (String indexName)
@ -277,44 +263,124 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
" values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
}
public String getUpdateSessionStatementAsString(SessionKey key)
public PreparedStatement getUpdateSessionStatement(Connection connection, String canonicalContextPath)
throws SQLException
{
String s = "update "+getTableName()+
" set "+getIdColumn()+" = ?, "+getLastNodeColumn()+" = ?, "+getAccessTimeColumn()+" = ?, "+
" set "+getLastNodeColumn()+" = ?, "+getAccessTimeColumn()+" = ?, "+
getLastAccessTimeColumn()+" = ?, "+getLastSavedTimeColumn()+" = ?, "+getExpiryTimeColumn()+" = ?, "+
getMaxIntervalColumn()+" = ?, "+getMapColumn()+" = ? where ";
if (key.getCanonicalContextPath() == null || "".equals(key.getCanonicalContextPath()))
if (canonicalContextPath == null || "".equals(canonicalContextPath))
{
if (_dbAdaptor.isEmptyStringNull())
{
return s+getIdColumn()+" = ? and "+
s = s+getIdColumn()+" = ? and "+
getContextPathColumn()+" is null and "+
getVirtualHostColumn()+" = ?";
return connection.prepareStatement(s);
}
}
return s+getIdColumn()+" = ? and "+getContextPathColumn()+
" = ? and "+getVirtualHostColumn()+" = ?";
return connection.prepareStatement(s+getIdColumn()+" = ? and "+getContextPathColumn()+
" = ? and "+getVirtualHostColumn()+" = ?");
}
public String getBoundedExpiredSessionsStatementAsString()
public PreparedStatement getMyExpiredSessionsStatement (Connection connection, String canonicalContextPath, String vhost, long expiry)
throws SQLException
{
return "select "+getIdColumn()+" from "+getTableName()+" where "+getContextPathColumn()+" = ? and "+getVirtualHostColumn()+" = ? and "+getExpiryTimeColumn()+" >= ? and "+getExpiryTimeColumn()+" <= ?";
if (_dbAdaptor == null)
throw new IllegalStateException("No DB adaptor");
if (canonicalContextPath == null || "".equals(canonicalContextPath))
{
if (_dbAdaptor.isEmptyStringNull())
{
PreparedStatement statement = connection.prepareStatement("select "+getIdColumn()+", "+getExpiryTimeColumn()+
" from "+getTableName()+" where "+
getContextPathColumn()+" is null and "+
getVirtualHostColumn()+" = ? and "+getExpiryTimeColumn()+" >0 and "+getExpiryTimeColumn()+" <= ?");
statement.setString(1, vhost);
statement.setLong(2, expiry);
return statement;
}
}
PreparedStatement statement = connection.prepareStatement("select "+getIdColumn()+", "+", "+getExpiryTimeColumn()+
" from "+getTableName()+" where "+getContextPathColumn()+" = ? and "+
getVirtualHostColumn()+" = ? and "+
getExpiryTimeColumn()+" >0 and "+getExpiryTimeColumn()+" <= ?");
statement.setString(1, canonicalContextPath);
statement.setString(2, vhost);
statement.setLong(3, expiry);
return statement;
}
public String getMyExpiredSessionsStatementAsString()
public PreparedStatement getAllAncientExpiredSessionsStatement (Connection connection)
throws SQLException
{
return "select "+getIdColumn()+" from "+getTableName()+" where "+getLastNodeColumn()+" = ? and "+getContextPathColumn()+" = and "+getExpiryTimeColumn()+" >0 and "+getExpiryTimeColumn()+" <= ?";
}
public String getAllAncientExpiredSessionsAsString()
{
return "select "+getIdColumn()+", "+getContextPathColumn()+", "+getVirtualHostColumn()+" from "+getTableName()+" where "+getExpiryTimeColumn()+" >0 and "+getExpiryTimeColumn()+" <= ?";
if (_dbAdaptor == null)
throw new IllegalStateException("No DB adaptor");
PreparedStatement statement = connection.prepareStatement("select "+getIdColumn()+", "+getContextPathColumn()+", "+getVirtualHostColumn()+
" from "+getTableName()+
" where "+getExpiryTimeColumn()+" >0 and "+getExpiryTimeColumn()+" <= ?");
return statement;
}
public PreparedStatement getCheckSessionExistsStatement (Connection connection, String canonicalContextPath)
throws SQLException
{
if (_dbAdaptor == null)
throw new IllegalStateException("No DB adaptor");
if (canonicalContextPath == null || "".equals(canonicalContextPath))
{
if (_dbAdaptor.isEmptyStringNull())
{
PreparedStatement statement = connection.prepareStatement("select "+getIdColumn()+", "+getExpiryTimeColumn()+
" from "+getTableName()+
" where "+getIdColumn()+" = ? and "+
getContextPathColumn()+" is null and "+
getVirtualHostColumn()+" = ?");
return statement;
}
}
PreparedStatement statement = connection.prepareStatement("select "+getIdColumn()+", "+getExpiryTimeColumn()+
" from "+getTableName()+
" where "+getIdColumn()+" = ? and "+
getContextPathColumn()+" = ? and "+
getVirtualHostColumn()+" = ?");
return statement;
}
public void fillCheckSessionExistsStatement (PreparedStatement statement, SessionKey key)
throws SQLException
{
statement.clearParameters();
ParameterMetaData metaData = statement.getParameterMetaData();
if (metaData.getParameterCount() < 3)
{
statement.setString(1, key.getId());
statement.setString(2, key.getVhost());
}
else
{
statement.setString(1, key.getId());
statement.setString(2, key.getCanonicalContextPath());
statement.setString(3, key.getVhost());
}
}
public PreparedStatement getLoadStatement (Connection connection, SessionKey key)
throws SQLException
{
@ -356,7 +422,7 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
throw new IllegalStateException("No DB adaptor");
String s = "update "+getTableName()+
" set "+getIdColumn()+" = ?, "+getLastNodeColumn()+" = ?, "+getAccessTimeColumn()+" = ?, "+
" set "+getLastNodeColumn()+" = ?, "+getAccessTimeColumn()+" = ?, "+
getLastAccessTimeColumn()+" = ?, "+getLastSavedTimeColumn()+" = ?, "+getExpiryTimeColumn()+" = ?, "+
getMaxIntervalColumn()+" = ?, "+getMapColumn()+" = ? where ";
@ -581,6 +647,9 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
@Override
public SessionData load(SessionKey key) throws Exception
{
if (getLoadAttempts() > 0 && loadAttemptsExhausted(key))
throw new UnreadableSessionDataException(key, true);
try (Connection connection = _dbAdaptor.getConnection();
PreparedStatement statement = _sessionTableSchema.getLoadStatement(connection, key);
ResultSet result = statement.executeQuery())
@ -614,7 +683,10 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
}
throw new UnreadableSessionDataException (key, e);
}
//if the session successfully loaded, remove failed attempts
_unloadables.remove(key);
if (LOG.isDebugEnabled())
LOG.debug("LOADED session {}", data);
}
@ -625,7 +697,7 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
}
catch (UnreadableSessionDataException e)
{
if (getLoadAttempts() > 0 && loadAttemptsExhausted(key))
if (getLoadAttempts() > 0 && loadAttemptsExhausted(key) && isDeleteUnloadableSessions())
{
try
{
@ -657,6 +729,7 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
int rows = statement.executeUpdate();
if (LOG.isDebugEnabled())
LOG.debug("Deleted Session {}:{}",key,(rows>0));
return rows > 0;
}
}
@ -733,11 +806,9 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
private void doUpdate (Connection connection, SessionKey key, SessionData data)
throws Exception
{
try (PreparedStatement statement = connection.prepareStatement(_sessionTableSchema.getUpdateSessionStatementAsString(key)))
try (PreparedStatement statement = _sessionTableSchema.getUpdateSessionStatement(connection, key.getCanonicalContextPath()))
{
long now = System.currentTimeMillis();
statement.setString(1, data.getLastNode());//should be my node id
statement.setLong(2, data.getAccessed());//accessTime
@ -745,7 +816,7 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
statement.setLong(4, now); //last saved time
statement.setLong(5, data.getExpiry());
statement.setLong(6, data.getMaxInactiveMs());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(data.getAllAttributes());
@ -782,21 +853,10 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
public Set<SessionKey> getExpired(Set<SessionKey> candidates)
{
if (LOG.isDebugEnabled())
LOG.debug("Scavenge sweep started at "+System.currentTimeMillis());
LOG.debug("Getting expired sessions "+System.currentTimeMillis());
long now = System.currentTimeMillis();
//first time we're called, don't scavenge
if (_lastScavengeTime == 0)
{
_lastScavengeTime = now;
return Collections.emptySet();
}
//we actually ignore the list of candidates as the database has the definitive list of sessions
long interval = now - _lastScavengeTime;
String cpath = SessionKey.getContextPath(_context);
String vhost = SessionKey.getVirtualHost(_context);
@ -808,21 +868,18 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
/*
* 1. Select sessions for our node and context that have expired since a grace interval
*/
long upperBound = _lastScavengeTime; //grace interval is 1 scavenge interval
long upperBound = now;
if (LOG.isDebugEnabled())
LOG.debug ("{}- Pass 1: Searching for sessions for node {} and context {} expired before {}", _node, _node, cpath, upperBound);
try (PreparedStatement statement = connection.prepareStatement(_sessionTableSchema.getMyExpiredSessionsStatementAsString()))
try (PreparedStatement statement = _sessionTableSchema.getMyExpiredSessionsStatement(connection, cpath, vhost, upperBound))
{
statement.setString(1, cpath);
statement.setString(2, vhost);
statement.setLong(3, upperBound);
try (ResultSet result = statement.executeQuery())
{
while (result.next())
{
String sessionId = result.getString(_sessionTableSchema.getIdColumn());
long exp = result.getLong(_sessionTableSchema.getExpiryTimeColumn());
expiredSessionKeys.add(SessionKey.getKey(sessionId, cpath, vhost));
if (LOG.isDebugEnabled()) LOG.debug (cpath+"- Found expired sessionId="+sessionId);
}
@ -830,15 +887,15 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
}
/*
* 2. Select sessions for any node or context that have expired a long time ago (ie at least 3 intervals ago)
* 2. Select sessions for any node or context that have expired a long time ago (ie at least 3 grace periods ago)
*/
try (PreparedStatement selectExpiredSessions = connection.prepareStatement(_sessionTableSchema.getAllAncientExpiredSessionsAsString()))
try (PreparedStatement selectExpiredSessions = _sessionTableSchema.getAllAncientExpiredSessionsStatement(connection))
{
upperBound = _lastScavengeTime - (3 * interval);
upperBound = now - (3 * _gracePeriodMs);
if (upperBound > 0)
{
if (LOG.isDebugEnabled()) LOG.debug("{}- Pass 2: Searching for sessions expired before {}",_node, upperBound);
selectExpiredSessions.setLong(1, upperBound);
try (ResultSet result = selectExpiredSessions.executeQuery())
{
@ -853,6 +910,44 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
}
}
}
Set<SessionKey> notExpiredInDB = new HashSet<SessionKey>();
for (SessionKey k: candidates)
{
//there are some keys that the session store thought had expired, but were not
//found in our sweep either because it is no longer in the db, or its
//expiry time was updated
if (!expiredSessionKeys.contains(k))
notExpiredInDB.add(k);
}
if (!notExpiredInDB.isEmpty())
{
//we have some sessions to check
try (PreparedStatement checkSessionExists = _sessionTableSchema.getCheckSessionExistsStatement(connection, cpath))
{
for (SessionKey k: notExpiredInDB)
{
_sessionTableSchema.fillCheckSessionExistsStatement (checkSessionExists, k);
try (ResultSet result = checkSessionExists.executeQuery())
{
if (!result.next())
{
//session doesn't exist any more, can be expired
expiredSessionKeys.add(k);
}
//else its expiry time has not been reached
}
catch (Exception e)
{
LOG.warn("Problem checking if potentially expired session {} exists in db", k,e);
}
}
}
}
return expiredSessionKeys;
}
@ -861,13 +956,20 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
LOG.warn(e);
return expiredSessionKeys; //return whatever we got
}
finally
{
_lastScavengeTime = now;
}
}
public int getGracePeriodSec ()
{
return (int)(_gracePeriodMs == 0L? 0 : _gracePeriodMs/1000L);
}
public void setGracePeriodSec (int sec)
{
if (sec < 0)
_gracePeriodMs = 0;
else
_gracePeriodMs = sec * 1000L;
}
public void setDatabaseAdaptor (DatabaseAdaptor dbAdaptor)
{
@ -906,6 +1008,12 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
_deleteUnloadables = delete;
}
public boolean isDeleteUnloadableSessions ()
{
return _deleteUnloadables;
}
protected void incLoadAttempt (SessionKey key)
{
AtomicInteger i = new AtomicInteger(0);
@ -920,6 +1028,25 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
if (isStarted())
throw new IllegalStateException("Already started");
}
public int getLoadAttempts (SessionKey key)
{
AtomicInteger i = _unloadables.get(key);
if (i == null)
return 0;
return i.get();
}
public Set<SessionKey> getUnloadableSessions ()
{
return new HashSet<SessionKey>(_unloadables.keySet());
}
public void clearUnloadableSessions()
{
_unloadables.clear();
}
}

View File

@ -179,7 +179,6 @@ public class JDBCSessionIdManager extends org.eclipse.jetty.server.session.Abstr
public String newSessionId(long seedTerm)
{
String id = super.newSessionId(seedTerm);
useId(id);
return id;
}

View File

@ -22,19 +22,22 @@ package org.eclipse.jetty.server.session;
/**
* JDBCSessionManager
*
*
*/
public class JDBCSessionManager extends SessionManager
{
protected DatabaseAdaptor _db = new DatabaseAdaptor();
protected JDBCSessionDataStore _sessionDataStore = new JDBCSessionDataStore();
public JDBCSessionManager()
{
_sessionStore = new MemorySessionStore();
}
@Override
public void doStart() throws Exception
{
_sessionStore = new MemorySessionStore();
_sessionDataStore.setDatabaseAdaptor(_db);
((AbstractSessionStore)_sessionStore).setSessionDataStore(_sessionDataStore);

View File

@ -31,15 +31,22 @@ import org.eclipse.jetty.util.log.Logger;
/**
* MemorySessionStore
*
*
* A session store that keeps its sessions in memory in a hashmap
*/
public class MemorySessionStore extends AbstractSessionStore
{
private static final Logger LOG = Log.getLogger(MemorySessionStore.class);
private final static Logger LOG = Log.getLogger("org.eclipse.jetty.server.session");
protected ConcurrentHashMap<String, Session> _sessions = new ConcurrentHashMap<String, Session>();
/**
* MemorySession
*
*
*/
public class MemorySession extends Session
{
@ -64,9 +71,6 @@ public class MemorySessionStore extends AbstractSessionStore
{
super(data);
}
}
@ -88,25 +92,18 @@ public class MemorySessionStore extends AbstractSessionStore
public Session doGet(SessionKey key)
{
Session session = _sessions.get(key.getId());
if (isStale(session))
{
//delete from memory so should reload
doDelete(key);
return null;
}
return session;
}
/**
* @see org.eclipse.jetty.server.session.AbstractSessionStore#doPut(java.lang.String, org.eclipse.jetty.server.session.Session)
* @see org.eclipse.jetty.server.session.AbstractSessionStore#doPutIfAbsent(java.lang.String, org.eclipse.jetty.server.session.Session)
*/
@Override
public void doPut(SessionKey key, Session session)
public Session doPutIfAbsent(SessionKey key, Session session)
{
_sessions.put(key.getId(), session);
return _sessions.putIfAbsent(key.getId(), session);
}
/**
@ -122,9 +119,9 @@ public class MemorySessionStore extends AbstractSessionStore
* @see org.eclipse.jetty.server.session.AbstractSessionStore#doDelete(java.lang.String)
*/
@Override
public void doDelete(SessionKey key)
public Session doDelete(SessionKey key)
{
_sessions.remove(key.getId());
return _sessions.remove(key.getId());
}
@ -139,7 +136,9 @@ public class MemorySessionStore extends AbstractSessionStore
for (Session s:_sessions.values())
{
if (s.isExpiredAt(now))
{
candidates.add(SessionKey.getKey(s.getId(), s.getContextPath(), s.getVHost()));
}
}
return candidates;
}
@ -197,10 +196,10 @@ public class MemorySessionStore extends AbstractSessionStore
* @see org.eclipse.jetty.server.session.SessionStore#newSession(java.lang.String)
*/
@Override
public Session newSession(SessionKey key, long created, long accessed, long lastAccessed, long maxInactiveMs)
public Session newSession(HttpServletRequest request, SessionKey key, long time, long maxInactiveMs)
{
//TODO - how to tell that the session is new?!
return new MemorySession(_sessionDataStore.newSessionData(key, created, accessed, lastAccessed, maxInactiveMs));
MemorySession s = new MemorySession(request, _sessionDataStore.newSessionData(key, time, time, time, maxInactiveMs));
return s;
}
@ -212,7 +211,8 @@ public class MemorySessionStore extends AbstractSessionStore
@Override
public Session newSession(SessionData data)
{
return new MemorySession (data);
MemorySession s = new MemorySession (data);
return s;
}

View File

@ -22,7 +22,8 @@ package org.eclipse.jetty.server.session;
/**
* NeverStale
*
*
* This strategy says that a session never needs to be refreshed by the cluster.
*
*/
public class NeverStaleStrategy implements StalenessStrategy
{

View File

@ -32,7 +32,6 @@ import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionContext;
import javax.servlet.http.HttpSessionEvent;
import org.eclipse.jetty.server.session.SessionManager.SessionIf;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -46,8 +45,9 @@ import org.eclipse.jetty.util.log.Logger;
*/
public class Session implements SessionManager.SessionIf
{
final static Logger LOG = Log.getLogger(Session.class); // TODO SessionHandler.LOG;
private final static Logger LOG = Log.getLogger("org.eclipse.jetty.server.session");
public final static String SESSION_CREATED_SECURE="org.eclipse.jetty.security.sessionCreatedSecure";
protected SessionData _sessionData;
@ -138,21 +138,7 @@ public class Session implements SessionManager.SessionIf
throw new IllegalStateException ("No session manager for session "+ _sessionData.getId());
_manager.removeSession(this,true);
// Notify listeners and unbind values
boolean do_invalidate=false;
synchronized (this)
{
if (!_sessionData.isInvalid())
{
if (_requests<=0)
do_invalidate=true;
else
_doInvalidate=true;
}
}
if (do_invalidate)
doInvalidate();
doInvalidate();
}
@ -366,7 +352,9 @@ public class Session implements SessionManager.SessionIf
@Override
public void setMaxInactiveInterval(int secs)
{
_sessionData.setMaxInactiveMs((long)secs*1000L);
_sessionData.setMaxInactiveMs((long)secs*1000L);
_sessionData.setExpiry(_sessionData.getMaxInactiveMs() <= 0 ? 0 : (System.currentTimeMillis() + _sessionData.getMaxInactiveMs()*1000L));
_sessionData.setDirty(true);
}
/**
@ -571,13 +559,6 @@ public class Session implements SessionManager.SessionIf
checkValid();
try
{
/* // remove session from context
_manager.removeSession(this,true);
//invalidate session
doInvalidate();
*/
//tell id mgr to remove session from all other contexts
((AbstractSessionIdManager)_manager.getSessionIdManager()).invalidateAll(_sessionData.getId());

View File

@ -30,7 +30,7 @@ import java.util.concurrent.ConcurrentHashMap;
/**
* SessionData
*
* The data associated with a session
* The data associated with a session.
*/
public class SessionData implements Serializable
{
@ -57,6 +57,15 @@ public class SessionData implements Serializable
protected long _lastSaved; //time in msec since last save
/**
* @param id
* @param cpath
* @param vhost
* @param created
* @param accessed
* @param lastAccessed
* @param maxInactiveMs
*/
public SessionData (String id, String cpath, String vhost, long created, long accessed, long lastAccessed, long maxInactiveMs)
{
_id = id;

View File

@ -243,6 +243,7 @@ public class SessionHandler extends ScopedHandler
if (requested_session_id != null && sessionManager != null)
{
HttpSession session = sessionManager.getHttpSession(requested_session_id);
if (session != null && sessionManager.isValid(session))
baseRequest.setSession(session);
return;
@ -273,7 +274,6 @@ public class SessionHandler extends ScopedHandler
if (requested_session_id != null)
{
session = sessionManager.getHttpSession(requested_session_id);
if (session != null && sessionManager.isValid(session))
{
break;

View File

@ -56,6 +56,8 @@ public class SessionKey
private SessionKey (String id, String path, String vhost)
{
if (id == null || path == null || vhost == null)
throw new IllegalArgumentException ("Bad values for key");
_id = id;
_canonicalContextPath = path;
_vhost = vhost;
@ -81,6 +83,24 @@ public class SessionKey
return _canonicalContextPath +"_"+_vhost+"_"+_id;
}
@Override
public boolean equals (Object o)
{
if (o == null)
return false;
SessionKey k = ((SessionKey)o);
if (k.getId().equals(getId()) && k.getCanonicalContextPath().equals(getCanonicalContextPath()) && k.getVhost().equals(getVhost()))
return true;
return false;
}
@Override
public int hashCode()
{
return java.util.Objects.hash(getId(), getCanonicalContextPath(), getVhost());
}
public static String getContextPath (Context context)
{
if (context == null)

View File

@ -29,7 +29,6 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import javax.servlet.SessionCookieConfig;
import javax.servlet.SessionTrackingMode;
@ -52,10 +51,7 @@ import org.eclipse.jetty.util.annotation.ManagedOperation;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.statistic.CounterStatistic;
import org.eclipse.jetty.util.statistic.SampleStatistic;
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
import org.eclipse.jetty.util.thread.Scheduler;
/**
* AbstractSessionManager
@ -92,7 +88,7 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je
}
};
private boolean _usingCookies=true;
/* ------------------------------------------------------------ */
// Setting of max inactive interval for new sessions
@ -120,47 +116,14 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je
protected boolean _nodeIdInSessionId;
protected boolean _checkingRemoteSessionIdEncoding;
protected String _sessionComment;
protected SessionStore _sessionStore;
protected final SampleStatistic _sessionTimeStats = new SampleStatistic();
public Set<SessionTrackingMode> _sessionTrackingModes;
private boolean _usingURLs;
protected SessionStore _sessionStore;
private boolean _usingCookies=true;
protected final CounterStatistic _sessionsStats = new CounterStatistic();
protected final SampleStatistic _sessionTimeStats = new SampleStatistic();
protected Scheduler _scheduler; //scheduler for scavenging
protected boolean _ownScheduler; //did we create our own scheduler or reuse common one
protected Scheduler.Task _task; //scavenge task
/**
* Scavenger
*
*/
protected class Scavenger implements Runnable
{
@Override
public void run()
{
try
{
scavenge();
}
finally
{
if (_scheduler != null && _scheduler.isRunning())
_task = _scheduler.schedule(this, _scavengeIntervalMs, TimeUnit.MILLISECONDS);
}
}
}
/* ------------------------------------------------------------ */
@ -397,7 +360,7 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je
* @return seconds
*/
@Override
@ManagedAttribute("defailt maximum time a session may be idle for (in s)")
@ManagedAttribute("default maximum time a session may be idle for (in s)")
public int getMaxInactiveInterval()
{
return _dftMaxIdleSecs;
@ -410,7 +373,7 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je
@ManagedAttribute("maximum number of simultaneous sessions")
public int getSessionsMax()
{
return (int)_sessionsStats.getMax();
return _sessionStore.getSessions();
}
/* ------------------------------------------------------------ */
@ -420,7 +383,7 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je
@ManagedAttribute("total number of sessions")
public int getSessionsTotal()
{
return (int)_sessionsStats.getTotal();
return _sessionStore.getSessionsTotal();
}
/* ------------------------------------------------------------ */
@ -556,7 +519,7 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je
@ManagedAttribute("number of currently active sessions")
public int getSessions()
{
return (int)_sessionsStats.getCurrent();
return _sessionStore.getSessions();
}
/* ------------------------------------------------------------ */
@ -618,10 +581,11 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je
long created=System.currentTimeMillis();
String id =_sessionIdManager.newSessionId(request,created);
SessionKey key = SessionKey.getKey(id, _context);
Session session = _sessionStore.newSession(key, created, created, created, (_dftMaxIdleSecs>0?_dftMaxIdleSecs*1000L:-1));
Session session = _sessionStore.newSession(request, key, created, (_dftMaxIdleSecs>0?_dftMaxIdleSecs*1000L:-1));
session.setExtendedId(_sessionIdManager.getExtendedId(id,request));
session.setSessionManager(this);
session.setLastNode(_sessionIdManager.getWorkerName());
session.getSessionData().setExpiry(_dftMaxIdleSecs <= 0 ? 0 : (created + _dftMaxIdleSecs*1000L));
if (request.isSecure())
session.setAttribute(Session.SESSION_CREATED_SECURE, Boolean.TRUE);
@ -629,21 +593,23 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je
try
{
_sessionStore.put(key, session);
_sessionIdManager.useId(id);
if (_sessionListeners!=null)
{
HttpSessionEvent event=new HttpSessionEvent(session);
for (HttpSessionListener listener : _sessionListeners)
listener.sessionCreated(event);
}
return session;
}
catch (Exception e)
{
LOG.warn(e);
}
_sessionsStats.increment();
if (_sessionListeners!=null)
{
HttpSessionEvent event=new HttpSessionEvent(session);
for (HttpSessionListener listener : _sessionListeners)
listener.sessionCreated(event);
}
return session;
return null;
}
}
/* ------------------------------------------------------------ */
@ -666,7 +632,7 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je
@ManagedOperation(value="reset statistics", impact="ACTION")
public void statsReset()
{
_sessionsStats.reset(getSessions());
_sessionStore.resetStats();
_sessionTimeStats.reset();
}
@ -752,7 +718,7 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je
try
{
SessionKey key = SessionKey.getKey(id, _context);
Session session = _sessionStore.get(key);
Session session = _sessionStore.get(key, true);
if (session != null)
{
//If the session we got back has expired
@ -760,18 +726,10 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je
{
//Tell the id manager that this session id should not be used in case other threads
//try to use the same session id in other contexts
_sessionIdManager.removeId(id);
//Remove the expired session from cache and any backing persistent store
try
{
_sessionStore.delete(key);
}
catch (Exception e)
{
LOG.warn("Unable to delete expired session {}", key);
}
_sessionIdManager.removeId(id);
//The scavenger thread will pick up this expired session
return null;
}
@ -845,18 +803,17 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je
{
//Remove the Session object from the session store and any backing data store
boolean removed = _sessionStore.delete(SessionKey.getKey(session.getId(), _context));
if (removed)
{
_sessionsStats.decrement();
_sessionTimeStats.set(round((System.currentTimeMillis() - session.getCreationTime())/1000.0));
if (invalidate && _sessionListeners!=null)
if (invalidate)
{
HttpSessionEvent event=new HttpSessionEvent(session);
for (int i = _sessionListeners.size()-1; i>=0; i--)
if (_sessionListeners!=null)
{
_sessionListeners.get(i).sessionDestroyed(event);
HttpSessionEvent event=new HttpSessionEvent(session);
for (int i = _sessionListeners.size()-1; i>=0; i--)
{
_sessionListeners.get(i).sessionDestroyed(event);
}
}
}
}
@ -925,10 +882,6 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je
new CookieConfig();
private long _scavengeIntervalMs;
private Scavenger _scavenger;
/* ------------------------------------------------------------ */
/**
* @return total amount of time all sessions remained valid
@ -994,7 +947,7 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je
SessionKey oldKey = SessionKey.getKey(oldId, _context);
SessionKey newKey = SessionKey.getKey(newId, _context);
Session session = _sessionStore.get(oldKey);
Session session = _sessionStore.get(oldKey, true);
if (session == null)
{
LOG.warn("Unable to renew id to "+newId+" for non-existant session "+oldId);
@ -1036,10 +989,14 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je
try
{
Session session = _sessionStore.get(SessionKey.getKey(id, _context));
Session session = _sessionStore.get(SessionKey.getKey(id, _context), false);
if (session == null)
{
return; // couldn't get/load a session for this context with that id
session.invalidateAndRemove();
}
_sessionTimeStats.set(round((System.currentTimeMillis() - session.getCreationTime())/1000.0));
session.invalidateAndRemove();
}
catch (Exception e)
{

View File

@ -73,12 +73,22 @@ public class SessionScavenger extends AbstractLifeCycle
}
}
/**
* SessionIdManager associated with this scavenger
* @param sessionIdManager
*/
public void setSessionIdManager (SessionIdManager sessionIdManager)
{
_sessionIdManager = sessionIdManager;
}
/**
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
*/
@Override
protected void doStart() throws Exception
{
@ -107,6 +117,9 @@ public class SessionScavenger extends AbstractLifeCycle
super.doStart();
}
/**
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStop()
*/
@Override
protected void doStop() throws Exception
{
@ -124,6 +137,10 @@ public class SessionScavenger extends AbstractLifeCycle
}
/**
* Set the period between scavenge cycles
* @param sec
*/
public void setScavengeIntervalSec (long sec)
{
if (sec<=0)
@ -156,11 +173,23 @@ public class SessionScavenger extends AbstractLifeCycle
}
}
/**
* Get the period between scavenge cycles.
*
* @return
*/
public long getScavengeIntervalSec ()
{
return _scavengeIntervalMs/1000;
}
/**
* Perform a scavenge cycle:
* ask all SessionManagers to find sessions they think have expired and then make
* sure that a session sharing the same id is expired on all contexts
*/
public void scavenge ()
{
//don't attempt to scavenge if we are shutting down
@ -203,12 +232,13 @@ public class SessionScavenger extends AbstractLifeCycle
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
return super.toString()+"[interval="+_scavengeIntervalMs+", ownscheduler="+_ownScheduler+"]";
}
}

View File

@ -21,6 +21,8 @@ package org.eclipse.jetty.server.session;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import org.eclipse.jetty.util.component.LifeCycle;
/**
@ -31,12 +33,15 @@ import org.eclipse.jetty.util.component.LifeCycle;
*/
public interface SessionStore extends LifeCycle
{
Session newSession (SessionKey key, long created, long accessed, long lastAccessed, long maxInactiveMs);
Session get(SessionKey key) throws Exception;
Session newSession (HttpServletRequest request, SessionKey key, long time, long maxInactiveMs);
Session get(SessionKey key, boolean staleCheck) throws Exception;
void put(SessionKey key, Session session) throws Exception;
boolean exists (SessionKey key) throws Exception;
boolean delete (SessionKey key) throws Exception;
void shutdown ();
Set<SessionKey> getExpired ();
int getSessions();
int getSessionsMax();
int getSessionsTotal();
void resetStats();
}

View File

@ -22,7 +22,8 @@ package org.eclipse.jetty.server.session;
/**
* StalePeriodStrategy
*
*
* A session is regarded as being stale if it has been
* x seconds since it was last read from the cluster.
*/
public class StalePeriodStrategy implements StalenessStrategy
{
@ -48,17 +49,26 @@ public class StalePeriodStrategy implements StalenessStrategy
}
else
{
return (session.getSessionData().getAccessed() - session.getSessionData().getLastSaved() >= _staleMs);
// return (session.getSessionData().getAccessed() - session.getSessionData().getLastSaved() >= _staleMs);
return (System.currentTimeMillis() - session.getSessionData().getLastSaved() >= _staleMs);
}
}
/**
* @return
*/
public long getStaleSec ()
{
return (_staleMs<=0?0L:_staleMs/1000L);
}
/**
* The amount of time in seconds that a session can be held
* in memory without being refreshed from the cluster.
* @param sec
*/
public void setStaleSec (long sec)
{
if (sec == 0)

View File

@ -41,6 +41,10 @@ public class UnreadableSessionDataException extends Exception
_key = key;
}
public UnreadableSessionDataException (SessionKey key, boolean loadAttemptsExhausted)
{
super("Unreadable session "+key+(loadAttemptsExhausted?" max load attempts":""));
}
}

View File

@ -38,7 +38,7 @@ public class FileSessionManagerTest
private static boolean _stacks;
// @BeforeClass
@BeforeClass
public static void beforeClass ()
{
_log = ((StdErrLog)Log.getLogger("org.eclipse.jetty.server.session"));
@ -46,7 +46,7 @@ public class FileSessionManagerTest
_log.setHideStacks(true);
}
//@AfterClass
@AfterClass
public static void afterClass()
{
_log.setHideStacks(_stacks);
@ -99,7 +99,6 @@ public class FileSessionManagerTest
manager.getSessionDataStore().setDeleteUnrestorableFiles(true);
manager.setSessionIdManager(idmgr);
handler.setSessionManager(manager);
// manager.setLazyLoad(true);
File testDir = MavenTestingUtils.getTargetTestingDir("hashes");
FS.ensureEmpty(testDir);

View File

@ -47,7 +47,7 @@ public class SessionCookieTest
* @see org.eclipse.jetty.server.session.SessionStore#newSession(org.eclipse.jetty.server.session.SessionKey, long, long, long, long)
*/
@Override
public Session newSession(SessionKey key, long created, long accessed, long lastAccessed, long maxInactiveMs)
public Session newSession(HttpServletRequest request, SessionKey key, long time, long maxInactiveMs)
{
// TODO Auto-generated method stub
return null;
@ -84,13 +84,12 @@ public class SessionCookieTest
}
/**
* @see org.eclipse.jetty.server.session.AbstractSessionStore#doPut(org.eclipse.jetty.server.session.SessionKey, org.eclipse.jetty.server.session.Session)
* @see org.eclipse.jetty.server.session.AbstractSessionStore#doPutIfAbsent(org.eclipse.jetty.server.session.SessionKey, org.eclipse.jetty.server.session.Session)
*/
@Override
public void doPut(SessionKey key, Session session)
public Session doPutIfAbsent(SessionKey key, Session session)
{
// TODO Auto-generated method stub
return null;
}
/**
@ -107,10 +106,9 @@ public class SessionCookieTest
* @see org.eclipse.jetty.server.session.AbstractSessionStore#doDelete(org.eclipse.jetty.server.session.SessionKey)
*/
@Override
public void doDelete(SessionKey key)
public Session doDelete(SessionKey key)
{
// TODO Auto-generated method stub
return null;
}
/**

View File

@ -43,7 +43,7 @@ public class InvalidationSessionTest extends AbstractInvalidationSessionTest
//that the node will re-load the session from the database and discover that it has gone.
try
{
Thread.sleep(2 * JdbcTestServer.SAVE_INTERVAL * 1000);
Thread.sleep(2 * JdbcTestServer.STALE_INTERVAL * 1000);
}
catch (InterruptedException e)
{

View File

@ -36,8 +36,21 @@ public class JdbcTestServer extends AbstractTestServer
{
public static final String DRIVER_CLASS = "org.apache.derby.jdbc.EmbeddedDriver";
public static final String DEFAULT_CONNECTION_URL = "jdbc:derby:sessions;create=true";
public static final int SAVE_INTERVAL = 1;
public static final int STALE_INTERVAL = 1;
public static final String EXPIRY_COL = "extime";
public static final String LAST_ACCESS_COL = "latime";
public static final String LAST_NODE_COL = "lnode";
public static final String LAST_SAVE_COL = "lstime";
public static final String MAP_COL = "mo";
public static final String MAX_IDLE_COL = "mi";
public static final String TABLE = "mysessions";
public static final String ID_COL = "mysessionid";
public static final String ACCESS_COL = "atime";
public static final String CONTEXT_COL = "cpath";
public static final String COOKIE_COL = "cooktime";
public static final String CREATE_COL = "ctime";
static
{
@ -81,33 +94,22 @@ public class JdbcTestServer extends AbstractTestServer
synchronized(JdbcTestServer.class)
{
JDBCSessionIdManager idManager = new JDBCSessionIdManager(_server);
idManager.setScavengeInterval(_scavengePeriod);
idManager.setWorkerName("w"+(__workers++));
idManager.setDriverInfo(DRIVER_CLASS, (config==null?DEFAULT_CONNECTION_URL:(String)config));
idManager.getDatabaseAdaptor().setDriverInfo(DRIVER_CLASS, (config==null?DEFAULT_CONNECTION_URL:(String)config));
JDBCSessionIdManager.SessionIdTableSchema idTableSchema = new JDBCSessionIdManager.SessionIdTableSchema();
idTableSchema.setTableName("mysessionids");
idTableSchema.setIdColumn("myid");
idManager.setSessionIdTableSchema(idTableSchema);
JDBCSessionIdManager.SessionTableSchema sessionTableSchema = new JDBCSessionIdManager.SessionTableSchema();
sessionTableSchema.setTableName("mysessions");
sessionTableSchema.setIdColumn("mysessionid");
sessionTableSchema.setAccessTimeColumn("atime");
sessionTableSchema.setContextPathColumn("cpath");
sessionTableSchema.setCookieTimeColumn("cooktime");
sessionTableSchema.setCreateTimeColumn("ctime");
sessionTableSchema.setExpiryTimeColumn("extime");
sessionTableSchema.setLastAccessTimeColumn("latime");
sessionTableSchema.setLastNodeColumn("lnode");
sessionTableSchema.setLastSavedTimeColumn("lstime");
sessionTableSchema.setMapColumn("mo");
sessionTableSchema.setMaxIntervalColumn("mi");
idManager.setSessionTableSchema(sessionTableSchema);
return idManager;
}
}
/**
* @see org.eclipse.jetty.server.session.AbstractTestServer#newSessionManager()
*/
/**
* @see org.eclipse.jetty.server.session.AbstractTestServer#newSessionManager()
*/
@ -116,7 +118,26 @@ public class JdbcTestServer extends AbstractTestServer
{
JDBCSessionManager manager = new JDBCSessionManager();
manager.setSessionIdManager((JDBCSessionIdManager)_sessionIdManager);
manager.setSaveInterval(SAVE_INTERVAL); //ensure we save any changes to the session at least once per second
JDBCSessionDataStore ds = manager.getSessionDataStore();
ds.setGracePeriodSec(_scavengePeriod);
manager.getDatabaseAdaptor().setDriverInfo(DRIVER_CLASS, DEFAULT_CONNECTION_URL);
JDBCSessionDataStore.SessionTableSchema sessionTableSchema = new JDBCSessionDataStore.SessionTableSchema();
sessionTableSchema.setTableName(TABLE);
sessionTableSchema.setIdColumn(ID_COL);
sessionTableSchema.setAccessTimeColumn(ACCESS_COL);
sessionTableSchema.setContextPathColumn(CONTEXT_COL);
sessionTableSchema.setCookieTimeColumn(COOKIE_COL);
sessionTableSchema.setCreateTimeColumn(CREATE_COL);
sessionTableSchema.setExpiryTimeColumn(EXPIRY_COL);
sessionTableSchema.setLastAccessTimeColumn(LAST_ACCESS_COL);
sessionTableSchema.setLastNodeColumn(LAST_NODE_COL);
sessionTableSchema.setLastSavedTimeColumn(LAST_SAVE_COL);
sessionTableSchema.setMapColumn(MAP_COL);
sessionTableSchema.setMaxIntervalColumn(MAX_IDLE_COL);
ds.setSessionTableSchema(sessionTableSchema);
StalePeriodStrategy staleStrategy = new StalePeriodStrategy();
staleStrategy.setStaleSec(STALE_INTERVAL);
((AbstractSessionStore)manager.getSessionStore()).setStaleStrategy(staleStrategy);
return manager;
}
@ -153,8 +174,8 @@ public class JdbcTestServer extends AbstractTestServer
{
con = DriverManager.getConnection(DEFAULT_CONNECTION_URL);
PreparedStatement statement = con.prepareStatement("select * from "+
((JDBCSessionIdManager)_sessionIdManager)._sessionTableSchema.getTableName()+
" where "+((JDBCSessionIdManager)_sessionIdManager)._sessionTableSchema.getIdColumn()+" = ?");
TABLE+
" where "+ID_COL+" = ?");
statement.setString(1, id);
ResultSet result = statement.executeQuery();
if (verbose)

View File

@ -74,7 +74,7 @@ public class ModifyMaxInactiveIntervalTest
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
//do another request to change the maxinactive interval
Request request = client.newRequest("http://localhost:" + port + "/mod/test?action=change&val="+newMaxInactive);
request.header("Cookie", sessionCookie);
@ -86,7 +86,6 @@ public class ModifyMaxInactiveIntervalTest
Thread.currentThread().sleep(10*1000L);
//do another request using the cookie to ensure the session is still there
request= client.newRequest("http://localhost:" + port + "/mod/test?action=test");
request.header("Cookie", sessionCookie);
response = request.send();

View File

@ -42,7 +42,7 @@ import org.junit.Test;
* SaveIntervalTest
*
* Checks to see that potentially stale sessions that have not
* changed are not always reloaded from the datase.
* changed are not always reloaded from the database.
*
* This test is Ignored because it takes a little while to run.
*
@ -65,7 +65,10 @@ public class SaveIntervalTest
TestSaveIntervalServlet servlet = new TestSaveIntervalServlet();
holder.setServlet(servlet);
ctxA.addServlet(holder, "/test");
((JDBCSessionManager)ctxA.getSessionHandler().getSessionManager()).setSaveInterval(SAVE);
StalePeriodStrategy strategy = new StalePeriodStrategy();
strategy.setStaleSec(SAVE);
((AbstractSessionStore)((JDBCSessionManager)ctxA.getSessionHandler().getSessionManager()).getSessionStore()).setStaleStrategy(strategy);
server.start();
int port=server.getPort();
try
@ -81,7 +84,7 @@ public class SaveIntervalTest
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
long lastSaved = ((JDBCSessionManager.Session)servlet._session).getLastSaved();
long lastSaved = ((Session)servlet._session).getSessionData().getLastSaved();
//do another request to change the session attribute
@ -89,7 +92,7 @@ public class SaveIntervalTest
request.header("Cookie", sessionCookie);
response = request.send();
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
long tmp = ((JDBCSessionManager.Session)servlet._session).getLastSaved();
long tmp = ((Session)servlet._session).getSessionData().getLastSaved();
assertNotEquals(lastSaved, tmp); //set of attribute will cause save to db
lastSaved = tmp;
@ -105,7 +108,7 @@ public class SaveIntervalTest
request.header("Cookie", sessionCookie);
response = request.send();
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
tmp = ((JDBCSessionManager.Session)servlet._session).getLastSaved();
tmp = ((Session)servlet._session).getSessionData().getLastSaved();
assertNotEquals(lastSaved, tmp);
lastSaved = tmp;
@ -119,7 +122,7 @@ public class SaveIntervalTest
request.header("Cookie", sessionCookie);
response = request.send();
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
tmp = ((JDBCSessionManager.Session)servlet._session).getLastSaved();
tmp = ((Session)servlet._session).getSessionData().getLastSaved();
assertEquals(lastSaved, tmp); //the save interval did not expire, so update to the access time will not have been persisted
}
finally
@ -147,7 +150,6 @@ public class SaveIntervalTest
if ("create".equals(action))
{
HttpSession session = request.getSession(true);
System.err.println("CREATE: Session id="+session.getId());
_session = session;
return;
}
@ -157,8 +159,7 @@ public class SaveIntervalTest
HttpSession session = request.getSession(false);
if (session == null)
throw new ServletException("Session is null for action=change");
System.err.println("SET: Session id="+session.getId());
session.setAttribute("aaa", "12345");
assertEquals(_session.getId(), session.getId());
return;
@ -169,7 +170,7 @@ public class SaveIntervalTest
HttpSession session = request.getSession(false);
if (session == null)
throw new ServletException("Session does not exist");
System.err.println("TICKLE: Session id="+session.getId());
assertEquals(_session.getId(), session.getId());
return;
}

View File

@ -50,7 +50,6 @@ public class StopSessionManagerPreserveSessionTest extends AbstractStopSessionMa
try
{
boolean actual = _server.existsInSessionTable(_id, true);
System.err.println(expected+":"+actual);
assertEquals(expected, actual);
}
catch (Exception e)

View File

@ -33,6 +33,7 @@ import javax.servlet.http.HttpSession;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.junit.Test;
@ -51,7 +52,8 @@ public abstract class AbstractImmortalSessionTest
int scavengePeriod = 2;
//turn off session expiry by setting maxInactiveInterval to -1
AbstractTestServer server = createServer(0, -1, scavengePeriod);
server.addContext(contextPath).addServlet(TestServlet.class, servletMapping);
ServletContextHandler context = server.addContext(contextPath);
context.addServlet(TestServlet.class, servletMapping);
try
{
@ -82,6 +84,8 @@ public abstract class AbstractImmortalSessionTest
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
resp = response.getContentAsString();
assertEquals(String.valueOf(value),resp.trim());
assertEquals(1, ((org.eclipse.jetty.server.session.SessionManager)context.getSessionHandler().getSessionManager()).getSessions());
}
finally
{

View File

@ -20,6 +20,7 @@ package org.eclipse.jetty.server.session;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException;
@ -83,9 +84,8 @@ public abstract class AbstractInvalidationSessionTest
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
// Be sure the session is also present in node2
Request request2 = client.newRequest(urls[1] + "?action=increment");
request2.header("Cookie", sessionCookie);
ContentResponse response2 = request2.send();
@ -142,6 +142,18 @@ public abstract class AbstractInvalidationSessionTest
{
HttpSession session = request.getSession(false);
session.invalidate();
try
{
session.invalidate();
fail("Session should be invalid");
}
catch (IllegalStateException e)
{
//expected
}
}
else if ("test".equals(action))
{

View File

@ -33,6 +33,7 @@ import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.SessionManager;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.junit.Test;
/**
@ -62,14 +63,16 @@ public abstract class AbstractLocalSessionScavengingTest
int inactivePeriod = 1;
int scavengePeriod = 2;
AbstractTestServer server1 = createServer(0, inactivePeriod, scavengePeriod);
server1.addContext(contextPath).addServlet(TestServlet.class, servletMapping);
ServletContextHandler context1 = server1.addContext(contextPath);
context1.addServlet(TestServlet.class, servletMapping);
try
{
server1.start();
int port1 = server1.getPort();
AbstractTestServer server2 = createServer(0, inactivePeriod, scavengePeriod * 3);
server2.addContext(contextPath).addServlet(TestServlet.class, servletMapping);
ServletContextHandler context2 = server2.addContext(contextPath);
context2.addServlet(TestServlet.class, servletMapping);
try
{
@ -90,28 +93,34 @@ public abstract class AbstractLocalSessionScavengingTest
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
org.eclipse.jetty.server.session.SessionManager m1 = (org.eclipse.jetty.server.session.SessionManager)context1.getSessionHandler().getSessionManager();
assertEquals(1, m1.getSessions());
// Be sure the session is also present in node2
org.eclipse.jetty.client.api.Request request = client.newRequest(urls[1] + "?action=test");
request.header("Cookie", sessionCookie);
ContentResponse response2 = request.send();
assertEquals(HttpServletResponse.SC_OK,response2.getStatus());
org.eclipse.jetty.server.session.SessionManager m2 = (org.eclipse.jetty.server.session.SessionManager)context2.getSessionHandler().getSessionManager();
assertEquals(1, m2.getSessions());
// Wait for the scavenger to run on node1, waiting 2.5 times the scavenger period
pause(scavengePeriod);
assertEquals(0, m1.getSessions());
// Check that node1 does not have any local session cached
request = client.newRequest(urls[0] + "?action=check");
request.header("Cookie", sessionCookie);
response1 = request.send();
assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
assertEquals(0, m1.getSessions());
// Wait for the scavenger to run on node2, waiting 2 times the scavenger period
// This ensures that the scavenger on node2 runs at least once.
pause(scavengePeriod);
// Check that node2 does not have any local session cached
request = client.newRequest(urls[1] + "?action=check");
request.header("Cookie", sessionCookie);

View File

@ -46,9 +46,7 @@ public abstract class AbstractNewSessionTest
{
try
{
System.err.println("Sleeping "+(scavenge * 2500L));
Thread.sleep(scavenge * 2500L);
System.err.println("Sleeping "+(scavenge * 2500L));
}
catch (InterruptedException e)
{

View File

@ -123,13 +123,12 @@ public abstract class AbstractSessionInvalidateAndCreateTest
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
// Make a request which will invalidate the existing session and create a new one
Request request2 = client.newRequest(url + "?action=test");
request2.header("Cookie", sessionCookie);
ContentResponse response2 = request2.send();
assertEquals(HttpServletResponse.SC_OK,response2.getStatus());
// Wait for the scavenger to run, waiting 3 times the scavenger period
pause(scavengePeriod);

View File

@ -62,7 +62,6 @@ public class WebAppObjectInSessionServlet extends HttpServlet
{
HttpSession session = request.getSession(false);
Object staticAttribute = session.getAttribute("staticAttribute");
System.err.println("staticAttribute="+staticAttribute);
Assert.assertTrue(staticAttribute instanceof TestSharedStatic);
// Object objectAttribute = session.getAttribute("objectAttribute");