Merge branch 'master' of ssh://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project

This commit is contained in:
Greg Wilkins 2013-11-25 09:29:12 +11:00
commit 1f368ee7e4
5 changed files with 230 additions and 129 deletions

View File

@ -38,6 +38,8 @@ import org.eclipse.jetty.server.session.AbstractSessionIdManager;
import org.eclipse.jetty.server.session.SessionHandler; import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; 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.BasicDBObject;
import com.mongodb.BasicDBObjectBuilder; 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_false = new BasicDBObject(MongoSessionManager.__VALID,false);
final static DBObject __valid_true = new BasicDBObject(MongoSessionManager.__VALID,true); 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 static long __defaultScavengePeriod = 30 * 60 * 1000; // every 30 minutes
final DBCollection _sessions; final DBCollection _sessions;
protected Server _server; protected Server _server;
private Timer _scavengeTimer; private Scheduler _scheduler;
private Timer _purgeTimer; private boolean _ownScheduler;
private TimerTask _scavengerTask; private Scheduler.Task _scavengerTask;
private TimerTask _purgeTask; private Scheduler.Task _purgerTask;
private long _scavengeDelay = __defaultScavengeDelay;
private long _scavengePeriod = __defaultScavengePeriod; private long _scavengePeriod = __defaultScavengePeriod;
@ -117,6 +117,52 @@ public class MongoSessionIdManager extends AbstractSessionIdManager
protected final Set<String> _sessionsIds = new HashSet<String>(); 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 public MongoSessionIdManager(Server server) throws UnknownHostException, MongoException
{ {
@ -173,7 +219,6 @@ public class MongoSessionIdManager extends AbstractSessionIdManager
expireAll((String)session.get(MongoSessionManager.__ID)); expireAll((String)session.get(MongoSessionManager.__ID));
} }
} }
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -297,20 +342,6 @@ public class MongoSessionIdManager extends AbstractSessionIdManager
this._purge = purge; 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);
}
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
@ -377,56 +408,40 @@ public class MongoSessionIdManager extends AbstractSessionIdManager
{ {
__log.debug("MongoSessionIdManager:starting"); __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) if (_scavengerTask != null)
{ {
_scavengerTask.cancel(); _scavengerTask.cancel();
_scavengerTask = null;
} }
_scavengerTask = new TimerTask() _scavengerTask = _scheduler.schedule(new Scavenger(), _scavengePeriod, TimeUnit.MILLISECONDS);
{
@Override
public void run()
{
scavenge();
}
};
_scavengeTimer.schedule(_scavengerTask,_scavengeDelay,_scavengePeriod);
} }
}
/*
* if purging is enabled, setup the purge thread
*/
if ( _purge )
{
_purgeTimer = new Timer("MongoSessionPurger", true);
synchronized (this) //if purging is enabled, setup the purge thread
if ( _purge )
{ {
if (_purgeTask != null) if (_purgerTask != null)
{ {
_purgeTask.cancel(); _purgerTask.cancel();
_purgerTask = null;
} }
_purgeTask = new TimerTask() _purgerTask = _scheduler.schedule(new Purger(), _purgeDelay, TimeUnit.MILLISECONDS);
{
@Override
public void run()
{
purge();
}
};
_purgeTimer.schedule(_purgeTask,0,_purgeDelay);
} }
} }
} }
@ -435,18 +450,26 @@ public class MongoSessionIdManager extends AbstractSessionIdManager
@Override @Override
protected void doStop() throws Exception protected void doStop() throws Exception
{ {
if (_scavengeTimer != null) synchronized (this)
{ {
_scavengeTimer.cancel(); if (_scavengerTask != null)
_scavengeTimer = null; {
} _scavengerTask.cancel();
_scavengerTask = null;
}
if (_purgeTimer != null) if (_purgerTask != null)
{ {
_purgeTimer.cancel(); _purgerTask.cancel();
_purgeTimer = null; _purgerTask = null;
} }
if (_ownScheduler && _scheduler != null)
{
_scheduler.stop();
_scheduler = null;
}
}
super.doStop(); super.doStop();
} }

View File

@ -31,6 +31,7 @@ import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest; 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.ClassLoadingObjectInputStream;
import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.log.Logger; 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>(); protected final ConcurrentMap<String,HashedSession> _sessions=new ConcurrentHashMap<String,HashedSession>();
private static int __id; private static int __id;
private Timer _timer; private Scheduler _timer;
private boolean _timerStop=false; private boolean _timerStop=false;
private TimerTask _task; private Scheduler.Task _task;
long _scavengePeriodMs=30000; long _scavengePeriodMs=30000;
long _savePeriodMs=0; //don't do period saves by default long _savePeriodMs=0; //don't do period saves by default
long _idleSavePeriodMs = 0; // don't idle save sessions by default. long _idleSavePeriodMs = 0; // don't idle save sessions by default.
private TimerTask _saveTask; private Scheduler.Task _saveTask;
File _storeDir; File _storeDir;
private boolean _lazyLoad=false; private boolean _lazyLoad=false;
private volatile boolean _sessionsLoaded=false; private volatile boolean _sessionsLoaded=false;
private boolean _deleteUnrestorableSessions=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,15 +139,25 @@ public class HashSessionManager extends AbstractSessionManager
super.doStart(); super.doStart();
_timerStop=false; _timerStop=false;
ServletContext context = ContextHandler.getCurrentContext(); //try shared scheduler from Server first
if (context!=null) _timer = getSessionHandler().getServer().getBean(Scheduler.class);
_timer=(Timer)context.getAttribute("org.eclipse.jetty.server.session.timer"); if (_timer == null)
if (_timer==null)
{ {
_timerStop=true; //try one passwed into the context
_timer=new Timer("HashSessionScavenger-"+__id++, true); 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 ScheduledExecutorScheduler();
_timer.start();
}
setScavengePeriod(getScavengePeriod()); setScavengePeriod(getScavengePeriod());
if (_storeDir!=null) if (_storeDir!=null)
@ -131,7 +189,7 @@ public class HashSessionManager extends AbstractSessionManager
_task.cancel(); _task.cancel();
_task=null; _task=null;
if (_timer!=null && _timerStop) if (_timer!=null && _timerStop)
_timer.cancel(); _timer.stop();
_timer=null; _timer=null;
} }
@ -217,24 +275,10 @@ public class HashSessionManager extends AbstractSessionManager
{ {
if (_saveTask!=null) if (_saveTask!=null)
_saveTask.cancel(); _saveTask.cancel();
_saveTask = null;
if (_savePeriodMs > 0 && _storeDir!=null) //only save if we have a directory configured if (_savePeriodMs > 0 && _storeDir!=null) //only save if we have a directory configured
{ {
_saveTask = new TimerTask() _saveTask = _timer.schedule(new Saver(),_savePeriodMs,TimeUnit.MILLISECONDS);
{
@Override
public void run()
{
try
{
saveSessions(true);
}
catch (Exception e)
{
LOG.warn(e);
}
}
};
_timer.schedule(_saveTask,_savePeriodMs,_savePeriodMs);
} }
} }
} }
@ -275,16 +319,11 @@ public class HashSessionManager extends AbstractSessionManager
synchronized (this) synchronized (this)
{ {
if (_task!=null) if (_task!=null)
_task.cancel();
_task = new TimerTask()
{ {
@Override _task.cancel();
public void run() _task = null;
{ }
scavenge(); _task = _timer.schedule(new Scavenger(),_scavengePeriodMs, TimeUnit.MILLISECONDS);
}
};
_timer.schedule(_task,_scavengePeriodMs,_scavengePeriodMs);
} }
} }
} }
@ -309,6 +348,7 @@ public class HashSessionManager extends AbstractSessionManager
// For each session // For each session
long now=System.currentTimeMillis(); long now=System.currentTimeMillis();
__log.debug("Scavenging sessions at {}", now);
for (Iterator<HashedSession> i=_sessions.values().iterator(); i.hasNext();) for (Iterator<HashedSession> i=_sessions.values().iterator(); i.hasNext();)
{ {

View File

@ -35,6 +35,7 @@ import java.util.Random;
import java.util.Set; import java.util.Set;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
import javax.naming.InitialContext; import javax.naming.InitialContext;
import javax.servlet.http.HttpServletRequest; 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.SessionManager;
import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.log.Logger; 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 String _sessionTableRowId = "rowId";
protected int _deleteBlockSize = 10; //number of ids to include in where 'in' clause protected int _deleteBlockSize = 10; //number of ids to include in where 'in' clause
protected Timer _timer; //scavenge timer protected Scheduler.Task _task; //scavenge task
protected TimerTask _task; //scavenge task protected Scheduler _scheduler;
protected Scavenger _scavenger;
protected boolean _ownScheduler;
protected long _lastScavengeTime; protected long _lastScavengeTime;
protected long _scavengeIntervalMs = 1000L * 60 * 10; //10mins protected long _scavengeIntervalMs = 1000L * 60 * 10; //10mins
protected String _blobType; //if not set, is deduced from the type of the database at runtime protected String _blobType; //if not set, is deduced from the type of the database at runtime
@ -100,6 +105,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
private String _selectExpiredSessions; private String _selectExpiredSessions;
/** /**
* DatabaseAdaptor * DatabaseAdaptor
* *
@ -233,6 +239,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) public JDBCSessionIdManager(Server server)
{ {
@ -351,21 +379,17 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("Scavenging every "+_scavengeIntervalMs+" ms"); 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) synchronized (this)
{ {
if (_task!=null) if (_task!=null)
_task.cancel(); _task.cancel();
_task = new TimerTask() if (_scavenger == null)
{ _scavenger = new Scavenger();
@Override _task = _scheduler.schedule(_scavenger,_scavengeIntervalMs,TimeUnit.MILLISECONDS);
public void run()
{
scavenge();
}
};
_timer.schedule(_task,_scavengeIntervalMs,_scavengeIntervalMs);
} }
} }
} }
@ -561,7 +585,16 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
super.doStart(); super.doStart();
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("Scavenging interval = "+getScavengeInterval()+" sec"); 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()); setScavengeInterval(getScavengeInterval());
} }
@ -577,9 +610,9 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
if (_task!=null) if (_task!=null)
_task.cancel(); _task.cancel();
_task=null; _task=null;
if (_timer!=null) if (_ownScheduler && _scheduler !=null)
_timer.cancel(); _scheduler.stop();
_timer=null; _scheduler=null;
} }
_sessionIds.clear(); _sessionIds.clear();
super.doStop(); super.doStop();

View File

@ -23,6 +23,7 @@ import java.io.File;
import junit.framework.Assert; import junit.framework.Assert;
import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.StdErrLog; import org.eclipse.jetty.util.log.StdErrLog;
@ -96,11 +97,16 @@ public class HashSessionManagerTest
{ {
File testDir = MavenTestingUtils.getTargetTestingDir("saved"); File testDir = MavenTestingUtils.getTargetTestingDir("saved");
testDir.mkdirs(); testDir.mkdirs();
Server server = new Server();
SessionHandler handler = new SessionHandler();
handler.setServer(server);
HashSessionManager manager = new HashSessionManager(); HashSessionManager manager = new HashSessionManager();
manager.setStoreDirectory(testDir); manager.setStoreDirectory(testDir);
manager.setMaxInactiveInterval(5); manager.setMaxInactiveInterval(5);
Assert.assertTrue(testDir.exists()); Assert.assertTrue(testDir.exists());
Assert.assertTrue(testDir.canWrite()); Assert.assertTrue(testDir.canWrite());
handler.setSessionManager(manager);
AbstractSessionIdManager idManager = new HashSessionIdManager(); AbstractSessionIdManager idManager = new HashSessionIdManager();
idManager.setWorkerName("foo"); idManager.setWorkerName("foo");

View File

@ -61,7 +61,6 @@ public class MongoTestServer extends AbstractTestServer
System.err.println("MongoTestServer:SessionIdManager scavenge: delay:"+ _scavengePeriod + " period:"+_scavengePeriod); System.err.println("MongoTestServer:SessionIdManager scavenge: delay:"+ _scavengePeriod + " period:"+_scavengePeriod);
MongoSessionIdManager idManager = new MongoSessionIdManager(_server); MongoSessionIdManager idManager = new MongoSessionIdManager(_server);
idManager.setWorkerName("w"+(__workers++)); idManager.setWorkerName("w"+(__workers++));
idManager.setScavengeDelay((_scavengePeriod));
idManager.setScavengePeriod(_scavengePeriod); idManager.setScavengePeriod(_scavengePeriod);
return idManager; return idManager;