Hook up scavenging; implement HashSessionManager; add delete unrestorable sessions to session data stores
This commit is contained in:
parent
d91fe48edc
commit
305b7bb776
|
@ -214,10 +214,10 @@ public class InfinispanSessionIdManager extends AbstractSessionIdManager
|
|||
* Remove a session id. This compels all other contexts who have a session
|
||||
* with the same id to also remove it.
|
||||
*
|
||||
* @see org.eclipse.jetty.server.SessionIdManager#invalidateAll(java.lang.String)
|
||||
* @see org.eclipse.jetty.server.SessionIdManager#expireAll(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void invalidateAll(String id)
|
||||
public void expireAll(String id)
|
||||
{
|
||||
//delete the session id from list of in-use sessions
|
||||
delete (id);
|
||||
|
|
|
@ -632,10 +632,10 @@ public class MongoSessionIdManager extends AbstractSessionIdManager
|
|||
/** Remove the session id from the list of in-use sessions.
|
||||
* Inform all other known contexts that sessions with the same id should be
|
||||
* invalidated.
|
||||
* @see org.eclipse.jetty.server.SessionIdManager#invalidateAll(java.lang.String)
|
||||
* @see org.eclipse.jetty.server.SessionIdManager#expireAll(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void invalidateAll(String sessionId)
|
||||
public void expireAll(String sessionId)
|
||||
{
|
||||
_sessionsIds.remove(sessionId);
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ public interface SessionIdManager extends LifeCycle
|
|||
*
|
||||
* @param id The session ID without any cluster node extension
|
||||
*/
|
||||
public void invalidateAll(String id);
|
||||
public void expireAll(String id);
|
||||
|
||||
/**
|
||||
* Create a new Session ID.
|
||||
|
|
|
@ -742,7 +742,7 @@ public abstract class AbstractSessionManager extends ContainerLifeCycle implemen
|
|||
/** Remove session from manager
|
||||
* @param session The session to remove
|
||||
* @param invalidate True if {@link HttpSessionListener#sessionDestroyed(HttpSessionEvent)} and
|
||||
* {@link SessionIdManager#invalidateAll(String)} should be called.
|
||||
* {@link SessionIdManager#expireAll(String)} should be called.
|
||||
*/
|
||||
public void removeSession(HttpSession session, boolean invalidate)
|
||||
{
|
||||
|
@ -755,7 +755,7 @@ public abstract class AbstractSessionManager extends ContainerLifeCycle implemen
|
|||
* Remove session from manager
|
||||
* @param session The session to remove
|
||||
* @param invalidate True if {@link HttpSessionListener#sessionDestroyed(HttpSessionEvent)} and
|
||||
* {@link SessionIdManager#invalidateAll(String)} should be called.
|
||||
* {@link SessionIdManager#expireAll(String)} should be called.
|
||||
* @return if the session was removed
|
||||
*/
|
||||
public boolean removeSession(AbstractSession session, boolean invalidate)
|
||||
|
@ -771,7 +771,7 @@ public abstract class AbstractSessionManager extends ContainerLifeCycle implemen
|
|||
// Remove session from all context and global id maps
|
||||
_sessionIdManager.removeId(session.getId());
|
||||
if (invalidate)
|
||||
_sessionIdManager.invalidateAll(session.getClusterId());
|
||||
_sessionIdManager.expireAll(session.getClusterId());
|
||||
|
||||
if (invalidate && _sessionListeners!=null)
|
||||
{
|
||||
|
|
|
@ -124,10 +124,10 @@ public class HashSessionIdManager extends AbstractSessionIdManager
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see SessionIdManager#invalidateAll(String)
|
||||
* @see SessionIdManager#expireAll(String)
|
||||
*/
|
||||
@Override
|
||||
public void invalidateAll(String id)
|
||||
public void expireAll(String id)
|
||||
{
|
||||
//take the id out of the list of known sessionids for this node
|
||||
removeId(id);
|
||||
|
|
|
@ -900,10 +900,10 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
/**
|
||||
* Invalidate the session matching the id on all contexts.
|
||||
*
|
||||
* @see org.eclipse.jetty.server.SessionIdManager#invalidateAll(java.lang.String)
|
||||
* @see org.eclipse.jetty.server.SessionIdManager#expireAll(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void invalidateAll(String id)
|
||||
public void expireAll(String id)
|
||||
{
|
||||
//take the id out of the list of known sessionids for this node
|
||||
removeId(id);
|
||||
|
|
|
@ -780,7 +780,7 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
/** Remove session from manager
|
||||
* @param session The session to remove
|
||||
* @param invalidate True if {@link HttpSessionListener#sessionDestroyed(HttpSessionEvent)} and
|
||||
* {@link SessionIdManager#invalidateAll(String)} should be called.
|
||||
* {@link SessionIdManager#expireAll(String)} should be called.
|
||||
*/
|
||||
@Override
|
||||
public boolean removeSession(AbstractSession session, boolean invalidate)
|
||||
|
|
|
@ -23,8 +23,11 @@ import java.util.Random;
|
|||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.SessionIdManager;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.server.session.SessionHandler;
|
||||
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
@ -41,6 +44,7 @@ public abstract class AbstractSessionIdManager extends AbstractLifeCycle impleme
|
|||
protected String _workerAttr;
|
||||
protected long _reseed=100000L;
|
||||
protected Server _server;
|
||||
protected SessionScavenger _scavenger;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public AbstractSessionIdManager()
|
||||
|
@ -64,9 +68,13 @@ public abstract class AbstractSessionIdManager extends AbstractLifeCycle impleme
|
|||
return _server;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public abstract void renewSessionId(String oldClusterId, String oldNodeId, HttpServletRequest request);
|
||||
|
||||
public void setSessionScavenger (SessionScavenger scavenger)
|
||||
{
|
||||
_scavenger = scavenger;
|
||||
_scavenger.setSessionIdManager(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -227,12 +235,22 @@ public abstract class AbstractSessionIdManager extends AbstractLifeCycle impleme
|
|||
throw new IllegalStateException("No Server for SessionIdManager");
|
||||
initRandom();
|
||||
_workerAttr=(_workerName!=null && _workerName.startsWith("$"))?_workerName.substring(1):null;
|
||||
|
||||
if (_scavenger == null)
|
||||
{
|
||||
LOG.warn("No SessionScavenger set, using defaults");
|
||||
_scavenger = new SessionScavenger();
|
||||
_scavenger.setSessionIdManager(this);
|
||||
}
|
||||
|
||||
_scavenger.start();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
protected void doStop() throws Exception
|
||||
{
|
||||
_scavenger.stop();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -294,5 +312,82 @@ public abstract class AbstractSessionIdManager extends AbstractLifeCycle impleme
|
|||
return (dot>0)?extendedId.substring(0,dot):extendedId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an id from use by telling all contexts to remove a session with this id.
|
||||
*
|
||||
* @see org.eclipse.jetty.server.SessionIdManager#expireAll(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void expireAll(String id)
|
||||
{
|
||||
//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);
|
||||
for (int i=0; contexts!=null && i<contexts.length; i++)
|
||||
{
|
||||
SessionHandler sessionHandler = ((ContextHandler)contexts[i]).getChildHandlerByClass(SessionHandler.class);
|
||||
if (sessionHandler != null)
|
||||
{
|
||||
SessionManager manager = (SessionManager)sessionHandler.getSessionManager();
|
||||
|
||||
if (manager != null)
|
||||
{
|
||||
manager.invalidate(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void invalidateAll (String id)
|
||||
{
|
||||
//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);
|
||||
for (int i=0; contexts!=null && i<contexts.length; i++)
|
||||
{
|
||||
SessionHandler sessionHandler = ((ContextHandler)contexts[i]).getChildHandlerByClass(SessionHandler.class);
|
||||
if (sessionHandler != null)
|
||||
{
|
||||
SessionManager manager = (SessionManager)sessionHandler.getSessionManager();
|
||||
|
||||
if (manager != null)
|
||||
{
|
||||
manager.invalidate(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.SessionIdManager#renewSessionId(java.lang.String, java.lang.String, javax.servlet.http.HttpServletRequest)
|
||||
*/
|
||||
@Override
|
||||
public void renewSessionId (String oldClusterId, String oldNodeId, HttpServletRequest request)
|
||||
{
|
||||
//generate a new id
|
||||
String newClusterId = newSessionId(request.hashCode());
|
||||
|
||||
removeId(oldClusterId);//remove the old one from the list (and database)
|
||||
|
||||
//tell all contexts to update the id
|
||||
Handler[] contexts = _server.getChildHandlersByClass(ContextHandler.class);
|
||||
for (int i=0; contexts!=null && i<contexts.length; i++)
|
||||
{
|
||||
SessionHandler sessionHandler = ((ContextHandler)contexts[i]).getChildHandlerByClass(SessionHandler.class);
|
||||
if (sessionHandler != null)
|
||||
{
|
||||
SessionManager manager = (SessionManager)sessionHandler.getSessionManager();
|
||||
|
||||
if (manager != null)
|
||||
{
|
||||
manager.renewSessionId(oldClusterId, oldNodeId, newClusterId, getExtendedId(newClusterId, request));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,11 +47,10 @@ public class FileSessionDataStore extends AbstractSessionDataStore
|
|||
{
|
||||
private final static Logger LOG = Log.getLogger("org.eclipse.jetty.server.session");
|
||||
private File _storeDir;
|
||||
private boolean _deleteUnrestorableFiles = false;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void doStart() throws Exception
|
||||
{
|
||||
|
@ -72,11 +71,21 @@ public class FileSessionDataStore extends AbstractSessionDataStore
|
|||
|
||||
public void setStoreDir(File storeDir)
|
||||
{
|
||||
checkStarted();
|
||||
_storeDir = storeDir;
|
||||
}
|
||||
|
||||
public boolean isDeleteUnrestorableFiles()
|
||||
{
|
||||
return _deleteUnrestorableFiles;
|
||||
}
|
||||
|
||||
public void setDeleteUnrestorableFiles(boolean deleteUnrestorableFiles)
|
||||
{
|
||||
checkStarted();
|
||||
_deleteUnrestorableFiles = deleteUnrestorableFiles;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.x.SessionDataStore#newSessionData(org.eclipse.jetty.server.session.x.SessionKey, long, long, long, long)
|
||||
*/
|
||||
|
@ -139,6 +148,23 @@ public class FileSessionDataStore extends AbstractSessionDataStore
|
|||
file.delete();
|
||||
return data;
|
||||
}
|
||||
catch (UnreadableSessionDataException e)
|
||||
{
|
||||
if (isDeleteUnrestorableFiles() && file.exists())
|
||||
{
|
||||
file.delete();
|
||||
LOG.warn("Deleted unrestorable file for session {}", key);
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void checkStarted()
|
||||
throws IllegalStateException
|
||||
{
|
||||
if (isStarted())
|
||||
throw new IllegalStateException("Already started");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
|
||||
package org.eclipse.jetty.server.session.x;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jetty.util.ConcurrentHashSet;
|
||||
|
||||
/**
|
||||
* HashSessionIdManager
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class HashSessionIdManager extends AbstractSessionIdManager
|
||||
{
|
||||
private final Set<String> _ids = new ConcurrentHashSet<String>();
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.SessionIdManager#isIdInUse(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public boolean isIdInUse(String id)
|
||||
{
|
||||
return _ids.contains(id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.x.AbstractSessionIdManager#newSessionId(long)
|
||||
*/
|
||||
@Override
|
||||
public String newSessionId(long seedTerm)
|
||||
{
|
||||
String id = super.newSessionId(seedTerm);
|
||||
useId(id);
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.SessionIdManager#useId(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void useId(String id)
|
||||
{
|
||||
if (id == null)
|
||||
return;
|
||||
|
||||
_ids.add(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.SessionIdManager#removeId(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void removeId(String id)
|
||||
{
|
||||
_ids.remove(id);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
|
||||
package org.eclipse.jetty.server.session.x;
|
||||
|
||||
/**
|
||||
* HashSessionManager
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class HashSessionManager extends SessionManager
|
||||
{
|
||||
protected FileSessionDataStore _sessionDataStore = new FileSessionDataStore();
|
||||
|
||||
|
||||
@Override
|
||||
public void doStart() throws Exception
|
||||
{
|
||||
_sessionStore = new MemorySessionStore();
|
||||
((AbstractSessionStore)_sessionStore).setSessionDataStore(_sessionDataStore);
|
||||
|
||||
super.doStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doStop() throws Exception
|
||||
{
|
||||
super.doStop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SessionDataStore to configure it
|
||||
* @return
|
||||
*/
|
||||
public FileSessionDataStore getSessionDataStore()
|
||||
{
|
||||
return _sessionDataStore;
|
||||
}
|
||||
|
||||
}
|
|
@ -33,6 +33,8 @@ import java.util.Collections;
|
|||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.eclipse.jetty.util.ClassLoadingObjectInputStream;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
|
@ -47,20 +49,16 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
|
|||
{
|
||||
final static Logger LOG = Log.getLogger("org.eclipse.jetty.server.session");
|
||||
|
||||
|
||||
|
||||
protected int _deleteBlockSize = 10; //number of ids to include in where 'in' clause for finding long expired sessions
|
||||
protected boolean _initialized = false;
|
||||
protected long _lastScavengeTime = 0;
|
||||
|
||||
|
||||
protected Map<SessionKey, AtomicInteger> _unloadables = new ConcurrentHashMap<>();
|
||||
|
||||
private DatabaseAdaptor _dbAdaptor;
|
||||
|
||||
|
||||
|
||||
private SessionTableSchema _sessionTableSchema;
|
||||
|
||||
private int _attempts = -1; // <= 0 means unlimited attempts to load a session
|
||||
private boolean _deleteUnloadables = false; //true means if attempts exhausted delete the session
|
||||
|
||||
/**
|
||||
* SessionTableSchema
|
||||
*
|
||||
|
@ -521,20 +519,6 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
|
|||
super ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void setDeleteBlockSize (int bsize)
|
||||
{
|
||||
this._deleteBlockSize = bsize;
|
||||
}
|
||||
|
||||
public int getDeleteBlockSize ()
|
||||
{
|
||||
return this._deleteBlockSize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
@ -554,6 +538,7 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
|
|||
if (_dbAdaptor == null)
|
||||
throw new IllegalStateException("No jdbc config");
|
||||
|
||||
_unloadables.clear();
|
||||
initialize();
|
||||
super.doStart();
|
||||
}
|
||||
|
@ -564,6 +549,7 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
|
|||
@Override
|
||||
protected void doStop() throws Exception
|
||||
{
|
||||
_unloadables.clear();
|
||||
super.doStop();
|
||||
}
|
||||
|
||||
|
@ -622,17 +608,38 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (getLoadAttempts() > 0)
|
||||
{
|
||||
incLoadAttempt (key);
|
||||
}
|
||||
throw new UnreadableSessionDataException (key, e);
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("LOADED session "+data);
|
||||
LOG.debug("LOADED session {}", data);
|
||||
}
|
||||
else
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Failed to load session "+key.getId());
|
||||
LOG.debug("No session {}", key.getId());
|
||||
return data;
|
||||
}
|
||||
catch (UnreadableSessionDataException e)
|
||||
{
|
||||
if (getLoadAttempts() > 0 && loadAttemptsExhausted(key))
|
||||
{
|
||||
try
|
||||
{
|
||||
delete (key);
|
||||
_unloadables.remove(key);
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
LOG.warn("Problem deleting unloadable session {}", key);
|
||||
}
|
||||
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -864,14 +871,55 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
|
|||
|
||||
public void setDatabaseAdaptor (DatabaseAdaptor dbAdaptor)
|
||||
{
|
||||
checkStarted();
|
||||
_dbAdaptor = dbAdaptor;
|
||||
}
|
||||
|
||||
public void setSessionTableSchema (SessionTableSchema schema)
|
||||
{
|
||||
checkStarted();
|
||||
_sessionTableSchema = schema;
|
||||
}
|
||||
|
||||
public void setLoadAttempts (int attempts)
|
||||
{
|
||||
checkStarted();
|
||||
_attempts = attempts;
|
||||
}
|
||||
|
||||
public int getLoadAttempts ()
|
||||
{
|
||||
return _attempts;
|
||||
}
|
||||
|
||||
public boolean loadAttemptsExhausted (SessionKey key)
|
||||
{
|
||||
AtomicInteger i = _unloadables.get(key);
|
||||
if (i == null)
|
||||
return false;
|
||||
return (i.get() >= _attempts);
|
||||
}
|
||||
|
||||
public void setDeleteUnloadableSessions (boolean delete)
|
||||
{
|
||||
checkStarted();
|
||||
_deleteUnloadables = delete;
|
||||
}
|
||||
|
||||
protected void incLoadAttempt (SessionKey key)
|
||||
{
|
||||
AtomicInteger i = new AtomicInteger(0);
|
||||
AtomicInteger count = _unloadables.putIfAbsent(key, i);
|
||||
if (count == null)
|
||||
count = i;
|
||||
count.incrementAndGet();
|
||||
}
|
||||
|
||||
protected void checkStarted () throws IllegalStateException
|
||||
{
|
||||
if (isStarted())
|
||||
throw new IllegalStateException("Already started");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ import org.eclipse.jetty.util.thread.Scheduler;
|
|||
* to support distributed sessions.
|
||||
*
|
||||
*/
|
||||
public class JDBCSessionIdManager extends org.eclipse.jetty.server.session.AbstractSessionIdManager
|
||||
public class JDBCSessionIdManager extends org.eclipse.jetty.server.session.x.AbstractSessionIdManager
|
||||
{
|
||||
private final static Logger LOG = Log.getLogger("org.eclipse.jetty.server.session");
|
||||
|
||||
|
@ -185,7 +185,12 @@ public class JDBCSessionIdManager extends org.eclipse.jetty.server.session.Abstr
|
|||
}
|
||||
|
||||
|
||||
//TODO useId might not be the right paradigm
|
||||
|
||||
/**
|
||||
* Record the session id as being in use
|
||||
*
|
||||
* @see org.eclipse.jetty.server.SessionIdManager#useId(java.lang.String)
|
||||
*/
|
||||
public void useId (String id)
|
||||
{
|
||||
if (id == null)
|
||||
|
@ -209,6 +214,10 @@ public class JDBCSessionIdManager extends org.eclipse.jetty.server.session.Abstr
|
|||
|
||||
|
||||
/**
|
||||
* Remove the id from in-use set
|
||||
*
|
||||
* Prevents another context from using this id
|
||||
*
|
||||
* @see org.eclipse.jetty.server.SessionIdManager#removeId(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
|
@ -339,66 +348,28 @@ public class JDBCSessionIdManager extends org.eclipse.jetty.server.session.Abstr
|
|||
/**
|
||||
* Invalidate the session matching the id on all contexts.
|
||||
*
|
||||
* @see org.eclipse.jetty.server.SessionIdManager#invalidateAll(java.lang.String)
|
||||
* @see org.eclipse.jetty.server.SessionIdManager#expireAll(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void invalidateAll(String id)
|
||||
{
|
||||
//take the id out of the list of known sessionids for this node
|
||||
removeId(id);
|
||||
|
||||
public void expireAll(String id)
|
||||
{
|
||||
synchronized (_sessionIds)
|
||||
{
|
||||
//tell all contexts that may have a session object with this id to
|
||||
//get rid of them
|
||||
Handler[] contexts = _server.getChildHandlersByClass(ContextHandler.class);
|
||||
for (int i=0; contexts!=null && i<contexts.length; i++)
|
||||
{
|
||||
SessionHandler sessionHandler = ((ContextHandler)contexts[i]).getChildHandlerByClass(SessionHandler.class);
|
||||
if (sessionHandler != null)
|
||||
{
|
||||
SessionManager manager = sessionHandler.getSessionManager();
|
||||
|
||||
if (manager != null)
|
||||
{
|
||||
manager.expire(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
super.expireAll(id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void renewSessionId (String oldClusterId, String oldNodeId, HttpServletRequest request)
|
||||
{
|
||||
//generate a new id
|
||||
String newClusterId = newSessionId(request.hashCode());
|
||||
|
||||
synchronized (_sessionIds)
|
||||
{
|
||||
removeId(oldClusterId);//remove the old one from the list (and database)
|
||||
|
||||
//tell all contexts to update the id
|
||||
Handler[] contexts = _server.getChildHandlersByClass(ContextHandler.class);
|
||||
for (int i=0; contexts!=null && i<contexts.length; i++)
|
||||
{
|
||||
SessionHandler sessionHandler = ((ContextHandler)contexts[i]).getChildHandlerByClass(SessionHandler.class);
|
||||
if (sessionHandler != null)
|
||||
{
|
||||
SessionManager manager = sessionHandler.getSessionManager();
|
||||
|
||||
if (manager != null)
|
||||
{
|
||||
manager.renewSessionId(oldClusterId, oldNodeId, newClusterId, getExtendedId(newClusterId, request));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void renewSessionId(String oldClusterId, String oldNodeId, HttpServletRequest request)
|
||||
{
|
||||
synchronized (_sessionIds)
|
||||
{
|
||||
super.renewSessionId(oldClusterId, oldNodeId, request);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the database adaptor in order to configure it
|
||||
* @return
|
||||
|
@ -424,14 +395,6 @@ public class JDBCSessionIdManager extends org.eclipse.jetty.server.session.Abstr
|
|||
_dbAdaptor.initialize();
|
||||
_sessionIdTableSchema.prepareTables(_dbAdaptor);
|
||||
|
||||
if (_scavenger == null)
|
||||
{
|
||||
LOG.warn("No SessionScavenger set, using defaults");
|
||||
_scavenger = new SessionScavenger();
|
||||
_scavenger.setSessionIdManager(this);
|
||||
}
|
||||
|
||||
_scavenger.start();
|
||||
super.doStart();
|
||||
|
||||
}
|
||||
|
@ -444,64 +407,10 @@ public class JDBCSessionIdManager extends org.eclipse.jetty.server.session.Abstr
|
|||
throws Exception
|
||||
{
|
||||
_sessionIds.clear();
|
||||
_scavenger.stop();
|
||||
|
||||
super.doStop();
|
||||
}
|
||||
|
||||
|
||||
public void setSessionScavenger (SessionScavenger scavenger)
|
||||
{
|
||||
_scavenger = scavenger;
|
||||
_scavenger.setSessionIdManager(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private void cleanExpiredSessionIds (Set<String> expiredIds)
|
||||
throws Exception
|
||||
{
|
||||
if (expiredIds == null || expiredIds.isEmpty())
|
||||
return;
|
||||
|
||||
String[] ids = expiredIds.toArray(new String[expiredIds.size()]);
|
||||
try (Connection con = getConnection())
|
||||
{
|
||||
con.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
|
||||
con.setAutoCommit(false);
|
||||
|
||||
int start = 0;
|
||||
int end = 0;
|
||||
int blocksize = _deleteBlockSize;
|
||||
int block = 0;
|
||||
|
||||
try (Statement statement = con.createStatement())
|
||||
{
|
||||
while (end < ids.length)
|
||||
{
|
||||
start = block*blocksize;
|
||||
if ((ids.length - start) >= blocksize)
|
||||
end = start + blocksize;
|
||||
else
|
||||
end = ids.length;
|
||||
|
||||
//take them out of the sessionIds table
|
||||
statement.executeUpdate(fillInClause("delete from "+_sessionIdTableSchema.getTableName()+" where "+_sessionIdTableSchema.getIdColumn()+" in ", ids, start, end));
|
||||
//take them out of the sessions table
|
||||
statement.executeUpdate(fillInClause("delete from "+_sessionTableSchema.getTableName()+" where "+_sessionTableSchema.getIdColumn()+" in ", ids, start, end));
|
||||
block++;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
con.rollback();
|
||||
throw e;
|
||||
}
|
||||
con.commit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -59,4 +59,13 @@ public class JDBCSessionManager extends SessionManager
|
|||
return _db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SessionDataStore to configure it
|
||||
* @return
|
||||
*/
|
||||
public JDBCSessionDataStore getSessionDataStore ()
|
||||
{
|
||||
return _sessionDataStore;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -127,9 +127,12 @@ public class Session implements SessionManager.SessionIf
|
|||
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
protected void timeout() throws Exception
|
||||
/**
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void invalidateAndRemove() throws Exception
|
||||
{
|
||||
// remove session from context and invalidate other sessions with same ID.
|
||||
if (_manager == null)
|
||||
throw new IllegalStateException ("No session manager for session "+ _sessionData.getId());
|
||||
|
||||
|
@ -545,6 +548,12 @@ public class Session implements SessionManager.SessionIf
|
|||
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
/** Called by users to invalidate a session, or called by the
|
||||
* access method as a request enters the session if the session
|
||||
* has expired.
|
||||
*
|
||||
* @see javax.servlet.http.HttpSession#invalidate()
|
||||
*/
|
||||
@Override
|
||||
public void invalidate()
|
||||
{
|
||||
|
@ -555,9 +564,15 @@ public class Session implements SessionManager.SessionIf
|
|||
try
|
||||
{
|
||||
|
||||
// remove session from context and invalidate other sessions with same ID.
|
||||
/* // 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());
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
|
@ -837,7 +837,7 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je
|
|||
* Remove session from manager
|
||||
* @param session The session to remove
|
||||
* @param invalidate True if {@link HttpSessionListener#sessionDestroyed(HttpSessionEvent)} and
|
||||
* {@link SessionIdManager#invalidateAll(String)} should be called.
|
||||
* {@link SessionIdManager#expireAll(String)} should be called.
|
||||
* @return if the session was removed
|
||||
*/
|
||||
public boolean removeSession(Session session, boolean invalidate)
|
||||
|
@ -1027,7 +1027,10 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je
|
|||
}
|
||||
}
|
||||
|
||||
public void expire (String id)
|
||||
|
||||
|
||||
|
||||
public void invalidate (String id)
|
||||
{
|
||||
if (StringUtil.isBlank(id))
|
||||
return;
|
||||
|
@ -1037,7 +1040,7 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je
|
|||
Session session = _sessionStore.get(SessionKey.getKey(id, _context));
|
||||
if (session == null)
|
||||
return; // couldn't get/load a session for this context with that id
|
||||
session.timeout();
|
||||
session.invalidateAndRemove();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -1047,7 +1050,6 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je
|
|||
|
||||
|
||||
|
||||
|
||||
public Set<SessionKey> scavenge ()
|
||||
{
|
||||
//don't attempt to scavenge if we are shutting down
|
||||
|
|
|
@ -181,11 +181,13 @@ public class SessionScavenger extends AbstractLifeCycle
|
|||
{
|
||||
//call scavenge on each manager to find keys for sessions that have expired
|
||||
Set<SessionKey> expiredKeys = manager.scavenge();
|
||||
|
||||
//for each expired session, tell the session id manager to invalidate its key on all contexts
|
||||
for (SessionKey key:expiredKeys)
|
||||
{
|
||||
try
|
||||
{
|
||||
((AbstractSessionIdManager)_sessionIdManager).invalidateAll(key.getId());
|
||||
((AbstractSessionIdManager)_sessionIdManager).expireAll(key.getId());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
|
@ -164,10 +164,10 @@ public class SessionCookieTest
|
|||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.SessionIdManager#invalidateAll(java.lang.String)
|
||||
* @see org.eclipse.jetty.server.SessionIdManager#expireAll(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void invalidateAll(String id)
|
||||
public void expireAll(String id)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue