422308 Change all session/sessionid managers to use shared Scheduler
This commit is contained in:
parent
3499c52019
commit
44416abb1f
|
@ -38,6 +38,8 @@ import org.eclipse.jetty.server.session.AbstractSessionIdManager;
|
|||
import org.eclipse.jetty.server.session.SessionHandler;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
|
||||
import org.eclipse.jetty.util.thread.Scheduler;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.BasicDBObjectBuilder;
|
||||
|
@ -69,20 +71,18 @@ public class MongoSessionIdManager extends AbstractSessionIdManager
|
|||
final static DBObject __valid_false = new BasicDBObject(MongoSessionManager.__VALID,false);
|
||||
final static DBObject __valid_true = new BasicDBObject(MongoSessionManager.__VALID,true);
|
||||
|
||||
final static long __defaultScavengeDelay = 10 * 6 * 1000; // wait at least 10 minutes
|
||||
final static long __defaultScavengePeriod = 30 * 60 * 1000; // every 30 minutes
|
||||
|
||||
|
||||
final DBCollection _sessions;
|
||||
protected Server _server;
|
||||
private Timer _scavengeTimer;
|
||||
private Timer _purgeTimer;
|
||||
private TimerTask _scavengerTask;
|
||||
private TimerTask _purgeTask;
|
||||
private Scheduler _scheduler;
|
||||
private boolean _ownScheduler;
|
||||
private Scheduler.Task _scavengerTask;
|
||||
private Scheduler.Task _purgerTask;
|
||||
|
||||
|
||||
|
||||
|
||||
private long _scavengeDelay = __defaultScavengeDelay;
|
||||
private long _scavengePeriod = __defaultScavengePeriod;
|
||||
|
||||
|
||||
|
@ -116,6 +116,52 @@ public class MongoSessionIdManager extends AbstractSessionIdManager
|
|||
*/
|
||||
protected final Set<String> _sessionsIds = new HashSet<String>();
|
||||
|
||||
|
||||
/**
|
||||
* Scavenger
|
||||
*
|
||||
*/
|
||||
protected class Scavenger implements Runnable
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
scavenge();
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_scheduler != null && _scheduler.isRunning())
|
||||
_scavengerTask = _scheduler.schedule(this, _scavengePeriod, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Purger
|
||||
*
|
||||
*/
|
||||
protected class Purger implements Runnable
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
purge();
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_scheduler != null && _scheduler.isRunning())
|
||||
_purgerTask = _scheduler.schedule(this, _purgeDelay, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public MongoSessionIdManager(Server server) throws UnknownHostException, MongoException
|
||||
|
@ -172,8 +218,7 @@ public class MongoSessionIdManager extends AbstractSessionIdManager
|
|||
__log.debug("SessionIdManager:scavenge: expiring session {}", (String)session.get(MongoSessionManager.__ID));
|
||||
expireAll((String)session.get(MongoSessionManager.__ID));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -297,20 +342,6 @@ public class MongoSessionIdManager extends AbstractSessionIdManager
|
|||
this._purge = purge;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* The delay before the first scavenge operation is performed.
|
||||
*
|
||||
* sets the scavengeDelay
|
||||
*/
|
||||
public void setScavengeDelay(long scavengeDelay)
|
||||
{
|
||||
if (scavengeDelay <= 0)
|
||||
this._scavengeDelay = __defaultScavengeDelay;
|
||||
else
|
||||
this._scavengeDelay = TimeUnit.SECONDS.toMillis(scavengeDelay);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
|
@ -376,77 +407,69 @@ public class MongoSessionIdManager extends AbstractSessionIdManager
|
|||
protected void doStart() throws Exception
|
||||
{
|
||||
__log.debug("MongoSessionIdManager:starting");
|
||||
|
||||
/*
|
||||
* setup the scavenger thread
|
||||
*/
|
||||
if (_scavengeDelay > 0)
|
||||
{
|
||||
_scavengeTimer = new Timer("MongoSessionIdScavenger",true);
|
||||
|
||||
synchronized (this)
|
||||
|
||||
synchronized (this)
|
||||
{
|
||||
//try and use a common scheduler, fallback to own
|
||||
_scheduler =_server.getBean(Scheduler.class);
|
||||
if (_scheduler == null)
|
||||
{
|
||||
_scheduler = new ScheduledExecutorScheduler();
|
||||
_ownScheduler = true;
|
||||
_scheduler.start();
|
||||
}
|
||||
|
||||
//setup the scavenger thread
|
||||
if (_scavengePeriod > 0)
|
||||
{
|
||||
if (_scavengerTask != null)
|
||||
{
|
||||
_scavengerTask.cancel();
|
||||
_scavengerTask = null;
|
||||
}
|
||||
|
||||
_scavengerTask = new TimerTask()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
scavenge();
|
||||
}
|
||||
};
|
||||
|
||||
_scavengeTimer.schedule(_scavengerTask,_scavengeDelay,_scavengePeriod);
|
||||
|
||||
_scavengerTask = _scheduler.schedule(new Scavenger(), _scavengePeriod, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* if purging is enabled, setup the purge thread
|
||||
*/
|
||||
if ( _purge )
|
||||
{
|
||||
_purgeTimer = new Timer("MongoSessionPurger", true);
|
||||
|
||||
synchronized (this)
|
||||
{
|
||||
if (_purgeTask != null)
|
||||
|
||||
|
||||
//if purging is enabled, setup the purge thread
|
||||
if ( _purge )
|
||||
{
|
||||
if (_purgerTask != null)
|
||||
{
|
||||
_purgeTask.cancel();
|
||||
_purgerTask.cancel();
|
||||
_purgerTask = null;
|
||||
}
|
||||
_purgeTask = new TimerTask()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
purge();
|
||||
}
|
||||
};
|
||||
|
||||
_purgeTimer.schedule(_purgeTask,0,_purgeDelay);
|
||||
_purgerTask = _scheduler.schedule(new Purger(), _purgeDelay, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
protected void doStop() throws Exception
|
||||
{
|
||||
if (_scavengeTimer != null)
|
||||
synchronized (this)
|
||||
{
|
||||
_scavengeTimer.cancel();
|
||||
_scavengeTimer = null;
|
||||
if (_scavengerTask != null)
|
||||
{
|
||||
_scavengerTask.cancel();
|
||||
_scavengerTask = null;
|
||||
}
|
||||
|
||||
if (_purgerTask != null)
|
||||
{
|
||||
_purgerTask.cancel();
|
||||
_purgerTask = null;
|
||||
}
|
||||
|
||||
if (_ownScheduler && _scheduler != null)
|
||||
{
|
||||
_scheduler.stop();
|
||||
_scheduler = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (_purgeTimer != null)
|
||||
{
|
||||
_purgeTimer.cancel();
|
||||
_purgeTimer = null;
|
||||
}
|
||||
|
||||
super.doStop();
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ import java.util.Timer;
|
|||
import java.util.TimerTask;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -39,6 +40,8 @@ import org.eclipse.jetty.server.handler.ContextHandler;
|
|||
import org.eclipse.jetty.util.ClassLoadingObjectInputStream;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
|
||||
import org.eclipse.jetty.util.thread.Scheduler;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -60,19 +63,64 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
|
||||
protected final ConcurrentMap<String,HashedSession> _sessions=new ConcurrentHashMap<String,HashedSession>();
|
||||
private static int __id;
|
||||
private Timer _timer;
|
||||
private Scheduler _timer;
|
||||
private boolean _timerStop=false;
|
||||
private TimerTask _task;
|
||||
private Scheduler.Task _task;
|
||||
long _scavengePeriodMs=30000;
|
||||
long _savePeriodMs=0; //don't do period saves by default
|
||||
long _idleSavePeriodMs = 0; // don't idle save sessions by default.
|
||||
private TimerTask _saveTask;
|
||||
private Scheduler.Task _saveTask;
|
||||
File _storeDir;
|
||||
private boolean _lazyLoad=false;
|
||||
private volatile boolean _sessionsLoaded=false;
|
||||
private boolean _deleteUnrestorableSessions=false;
|
||||
|
||||
|
||||
/**
|
||||
* Scavenger
|
||||
*
|
||||
*/
|
||||
protected class Scavenger implements Runnable
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
scavenge();
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_timer != null && _timer.isRunning())
|
||||
_timer.schedule(this, _scavengePeriodMs, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saver
|
||||
*
|
||||
*/
|
||||
protected class Saver implements Runnable
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
saveSessions(true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_timer != null && _timer.isRunning())
|
||||
_timer.schedule(this, _savePeriodMs, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -91,14 +139,24 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
super.doStart();
|
||||
|
||||
_timerStop=false;
|
||||
ServletContext context = ContextHandler.getCurrentContext();
|
||||
if (context!=null)
|
||||
_timer=(Timer)context.getAttribute("org.eclipse.jetty.server.session.timer");
|
||||
if (_timer==null)
|
||||
//try shared scheduler from Server first
|
||||
_timer = getSessionHandler().getServer().getBean(Scheduler.class);
|
||||
if (_timer == null)
|
||||
{
|
||||
//try one passwed into the context
|
||||
ServletContext context = ContextHandler.getCurrentContext();
|
||||
if (context!=null)
|
||||
_timer = (Scheduler)context.getAttribute("org.eclipse.jetty.server.session.timer");
|
||||
}
|
||||
|
||||
if (_timer == null)
|
||||
{
|
||||
//make a scheduler if none useable
|
||||
_timerStop=true;
|
||||
_timer=new Timer("HashSessionScavenger-"+__id++, true);
|
||||
_timer=new ScheduledExecutorScheduler();
|
||||
_timer.start();
|
||||
}
|
||||
|
||||
|
||||
setScavengePeriod(getScavengePeriod());
|
||||
|
||||
|
@ -131,7 +189,7 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
_task.cancel();
|
||||
_task=null;
|
||||
if (_timer!=null && _timerStop)
|
||||
_timer.cancel();
|
||||
_timer.stop();
|
||||
_timer=null;
|
||||
}
|
||||
|
||||
|
@ -217,24 +275,10 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
{
|
||||
if (_saveTask!=null)
|
||||
_saveTask.cancel();
|
||||
_saveTask = null;
|
||||
if (_savePeriodMs > 0 && _storeDir!=null) //only save if we have a directory configured
|
||||
{
|
||||
_saveTask = new TimerTask()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
saveSessions(true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
_timer.schedule(_saveTask,_savePeriodMs,_savePeriodMs);
|
||||
_saveTask = _timer.schedule(new Saver(),_savePeriodMs,TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -275,16 +319,11 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
synchronized (this)
|
||||
{
|
||||
if (_task!=null)
|
||||
_task.cancel();
|
||||
_task = new TimerTask()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
scavenge();
|
||||
}
|
||||
};
|
||||
_timer.schedule(_task,_scavengePeriodMs,_scavengePeriodMs);
|
||||
_task.cancel();
|
||||
_task = null;
|
||||
}
|
||||
_task = _timer.schedule(new Scavenger(),_scavengePeriodMs, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -303,13 +342,14 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
Thread thread=Thread.currentThread();
|
||||
ClassLoader old_loader=thread.getContextClassLoader();
|
||||
try
|
||||
{
|
||||
{
|
||||
if (_loader!=null)
|
||||
thread.setContextClassLoader(_loader);
|
||||
|
||||
// For each session
|
||||
long now=System.currentTimeMillis();
|
||||
|
||||
__log.debug("Scavenging sessions at {}", now);
|
||||
|
||||
for (Iterator<HashedSession> i=_sessions.values().iterator(); i.hasNext();)
|
||||
{
|
||||
HashedSession session=i.next();
|
||||
|
|
|
@ -35,6 +35,7 @@ import java.util.Random;
|
|||
import java.util.Set;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.naming.InitialContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -46,6 +47,8 @@ import org.eclipse.jetty.server.Server;
|
|||
import org.eclipse.jetty.server.SessionManager;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
|
||||
import org.eclipse.jetty.util.thread.Scheduler;
|
||||
|
||||
|
||||
|
||||
|
@ -73,8 +76,10 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
protected String _sessionTableRowId = "rowId";
|
||||
protected int _deleteBlockSize = 10; //number of ids to include in where 'in' clause
|
||||
|
||||
protected Timer _timer; //scavenge timer
|
||||
protected TimerTask _task; //scavenge task
|
||||
protected Scheduler.Task _task; //scavenge task
|
||||
protected Scheduler _scheduler;
|
||||
protected Scavenger _scavenger;
|
||||
protected boolean _ownScheduler;
|
||||
protected long _lastScavengeTime;
|
||||
protected long _scavengeIntervalMs = 1000L * 60 * 10; //10mins
|
||||
protected String _blobType; //if not set, is deduced from the type of the database at runtime
|
||||
|
@ -98,6 +103,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
protected DatabaseAdaptor _dbAdaptor;
|
||||
|
||||
private String _selectExpiredSessions;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
@ -232,6 +238,28 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Scavenger
|
||||
*
|
||||
*/
|
||||
protected class Scavenger implements Runnable
|
||||
{
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
scavenge();
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_scheduler != null && _scheduler.isRunning())
|
||||
_scheduler.schedule(this, _scavengeIntervalMs, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public JDBCSessionIdManager(Server server)
|
||||
|
@ -351,21 +379,17 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Scavenging every "+_scavengeIntervalMs+" ms");
|
||||
if (_timer!=null && (period!=old_period || _task==null))
|
||||
|
||||
//if (_timer!=null && (period!=old_period || _task==null))
|
||||
if (_scheduler != null && (period!=old_period || _task==null))
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
if (_task!=null)
|
||||
_task.cancel();
|
||||
_task = new TimerTask()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
scavenge();
|
||||
}
|
||||
};
|
||||
_timer.schedule(_task,_scavengeIntervalMs,_scavengeIntervalMs);
|
||||
if (_scavenger == null)
|
||||
_scavenger = new Scavenger();
|
||||
_task = _scheduler.schedule(_scavenger,_scavengeIntervalMs,TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -561,7 +585,16 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
super.doStart();
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Scavenging interval = "+getScavengeInterval()+" sec");
|
||||
_timer=new Timer("JDBCSessionScavenger", true);
|
||||
|
||||
//try and use a common scheduler, fallback to own
|
||||
_scheduler =_server.getBean(Scheduler.class);
|
||||
if (_scheduler == null)
|
||||
{
|
||||
_scheduler = new ScheduledExecutorScheduler();
|
||||
_ownScheduler = true;
|
||||
_scheduler.start();
|
||||
}
|
||||
|
||||
setScavengeInterval(getScavengeInterval());
|
||||
}
|
||||
|
||||
|
@ -577,9 +610,9 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
if (_task!=null)
|
||||
_task.cancel();
|
||||
_task=null;
|
||||
if (_timer!=null)
|
||||
_timer.cancel();
|
||||
_timer=null;
|
||||
if (_ownScheduler && _scheduler !=null)
|
||||
_scheduler.stop();
|
||||
_scheduler=null;
|
||||
}
|
||||
_sessionIds.clear();
|
||||
super.doStop();
|
||||
|
|
|
@ -23,6 +23,7 @@ import java.io.File;
|
|||
import junit.framework.Assert;
|
||||
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.StdErrLog;
|
||||
|
@ -96,11 +97,16 @@ public class HashSessionManagerTest
|
|||
{
|
||||
File testDir = MavenTestingUtils.getTargetTestingDir("saved");
|
||||
testDir.mkdirs();
|
||||
|
||||
Server server = new Server();
|
||||
SessionHandler handler = new SessionHandler();
|
||||
handler.setServer(server);
|
||||
HashSessionManager manager = new HashSessionManager();
|
||||
manager.setStoreDirectory(testDir);
|
||||
manager.setMaxInactiveInterval(5);
|
||||
Assert.assertTrue(testDir.exists());
|
||||
Assert.assertTrue(testDir.canWrite());
|
||||
handler.setSessionManager(manager);
|
||||
|
||||
AbstractSessionIdManager idManager = new HashSessionIdManager();
|
||||
idManager.setWorkerName("foo");
|
||||
|
|
|
@ -61,7 +61,6 @@ public class MongoTestServer extends AbstractTestServer
|
|||
System.err.println("MongoTestServer:SessionIdManager scavenge: delay:"+ _scavengePeriod + " period:"+_scavengePeriod);
|
||||
MongoSessionIdManager idManager = new MongoSessionIdManager(_server);
|
||||
idManager.setWorkerName("w"+(__workers++));
|
||||
idManager.setScavengeDelay((_scavengePeriod));
|
||||
idManager.setScavengePeriod(_scavengePeriod);
|
||||
|
||||
return idManager;
|
||||
|
|
Loading…
Reference in New Issue