436345 Refactor AbstractSession to minimize burden on subclasses to implement behaviour

Conflicts:
	jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java
	jetty-server/src/main/java/org/eclipse/jetty/server/session/MemSession.java
This commit is contained in:
Jan Bartel 2015-03-11 17:29:26 +11:00
parent ec2a520aa1
commit 5fb6b93a61
25 changed files with 1563 additions and 202 deletions

View File

@ -19,6 +19,7 @@
package org.eclipse.jetty.session.infinispan;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
@ -32,7 +33,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.infinispan.Cache;
import org.infinispan.commons.api.BasicCache;
@ -51,18 +53,25 @@ import org.infinispan.Cache;
* </pre>
* where [id] is the id of the session.
*
* If the first session to be added is not immortal (ie it has a timeout on it) then
* the corresponding session id is entered into infinispan with an idle expiry timeout
* equivalent to double the session's timeout (the multiplier is configurable).
*
*
* Having one entry per in-use session id means that there is no contention on
* cache entries (as would be the case if a single entry was kept containing a
* list of in-use session ids).
*
* TODO synchronization
*
*/
public class InfinispanSessionIdManager extends AbstractSessionIdManager
{
private final static Logger LOG = Log.getLogger("org.eclipse.jetty.server.session");
protected final static String ID_KEY = "__o.e.j.s.infinispanIdMgr__";
protected Cache<String,Object> _cache;
public final static String ID_KEY = "__o.e.j.s.infinispanIdMgr__";
public static final int DEFAULT_IDLE_EXPIRY_MULTIPLE = 2;
protected BasicCache<String,Object> _cache;
private Server _server;
private int _idleExpiryMultiple = DEFAULT_IDLE_EXPIRY_MULTIPLE;
@ -131,7 +140,8 @@ public class InfinispanSessionIdManager extends AbstractSessionIdManager
String clusterId = getClusterId(id);
//ask the cluster
//ask the cluster - this should also tickle the idle expiration timer on the sessionid entry
//keeping it valid
try
{
return exists(clusterId);
@ -154,13 +164,35 @@ public class InfinispanSessionIdManager extends AbstractSessionIdManager
@Override
public void addSession(HttpSession session)
{
if (session == null)
return;
if (session == null)
return;
//insert into the cache and set an idle expiry on the entry that
//is based off the max idle time configured for the session. If the
//session is immortal, then there is no idle expiry on the corresponding
//session id
if (session.getMaxInactiveInterval() == 0)
insert (((AbstractSession)session).getClusterId());
else
insert (((AbstractSession)session).getClusterId(), session.getMaxInactiveInterval() * getIdleExpiryMultiple());
}
//insert into the cache
insert (((AbstractSession)session).getClusterId());
public void setIdleExpiryMultiple (int multiplier)
{
if (multiplier <= 1)
{
LOG.warn("Idle expiry multiple of {} for session ids set to less than minimum. Using value of {} instead.", multiplier, DEFAULT_IDLE_EXPIRY_MULTIPLE);
}
_idleExpiryMultiple = multiplier;
}
public int getIdleExpiryMultiple ()
{
return _idleExpiryMultiple;
}
/**
* Remove a session id from the list of in-use ids.
*
@ -245,16 +277,38 @@ public class InfinispanSessionIdManager extends AbstractSessionIdManager
}
public Cache<String,Object> getCache()
/**
* Get the cache.
* @return
*/
public BasicCache<String,Object> getCache()
{
return _cache;
}
public void setCache(Cache<String,Object> cache)
/**
* Set the cache.
* @param cache
*/
public void setCache(BasicCache<String,Object> cache)
{
this._cache = cache;
}
/**
* Do any operation to the session id in the cache to
* ensure its idle expiry time moves forward
* @param id
*/
public void touch (String id)
{
exists(id);
}
/**
* Ask the cluster if a particular id exists.
*
@ -266,10 +320,7 @@ public class InfinispanSessionIdManager extends AbstractSessionIdManager
if (_cache == null)
throw new IllegalStateException ("No cache");
Object key =_cache.get(makeKey(id));
if (key == null)
return false;
return true;
return _cache.containsKey(makeKey(id));
}
@ -287,6 +338,19 @@ public class InfinispanSessionIdManager extends AbstractSessionIdManager
}
/**
* Put a session id into the cluster with an idle expiry.
*
* @param id
*/
protected void insert (String id, long idleTimeOutSec)
{
if (_cache == null)
throw new IllegalStateException ("No cache");
_cache.putIfAbsent(makeKey(id),id,-1L, TimeUnit.SECONDS, idleTimeOutSec, TimeUnit.SECONDS);
}
/**
* Remove a session id from the cluster.

View File

@ -42,6 +42,8 @@ import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
import org.eclipse.jetty.util.thread.Scheduler;
import org.infinispan.Cache;
import org.infinispan.commons.api.BasicCache;
import org.omg.CORBA._IDLTypeStub;
/**
* InfinispanSessionManager
@ -73,7 +75,7 @@ public class InfinispanSessionManager extends AbstractSessionManager
/**
* Clustered cache of sessions
*/
private Cache<String, Object> _cache;
private BasicCache<String, Object> _cache;
/**
@ -197,7 +199,7 @@ public class InfinispanSessionManager extends AbstractSessionManager
lastNode = in.readUTF(); //last managing node
expiry = in.readLong();
maxInactive = in.readLong();
HashMap<String,Object> attributes = (HashMap<String,Object>)in.readObject();
attributes = (HashMap<String,Object>)in.readObject();
}
}
@ -205,102 +207,6 @@ public class InfinispanSessionManager extends AbstractSessionManager
/**
* SerializableSession
*
* Helper class that is responsible for de/serialization of the non-serializable session object.
*/
public class SerializableSession implements Serializable
{
/**
*
*/
private static final long serialVersionUID = -7603529353470249059L;
private transient Session _session;
public SerializableSession ()
{
}
public SerializableSession (Session session)
{
setSession(session);
}
/**
* Existing session
* @param session
*/
public void setSession (Session session)
{
_session = session;
}
public Session getSession ()
{
return _session;
}
private void writeObject(java.io.ObjectOutputStream out) throws IOException
{
if (_session == null)
throw new IOException ("No session to serialize");
out.writeUTF(_session.getClusterId()); //session id
out.writeUTF(_session.getContextPath()); //context path
out.writeUTF(_session.getVHost()); //first vhost
out.writeLong(_session.getAccessed());//accessTime
out.writeLong(_session.getLastAccessedTime()); //lastAccessTime
out.writeLong(_session.getCreationTime()); //time created
out.writeLong(_session.getCookieSetTime());//time cookie was set
out.writeUTF(_session.getLastNode()); //name of last node managing
out.writeLong(_session.getExpiry());
out.writeLong(_session.getMaxInactiveInterval());
out.writeObject(_session.getAttributeMap());
}
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException
{
String clusterId = in.readUTF();
String context = in.readUTF();
String vhost = in.readUTF();
Long accessed = in.readLong();//accessTime
Long lastAccessed = in.readLong(); //lastAccessTime
Long created = in.readLong(); //time created
Long cookieSet = in.readLong();//time cookie was set
String lastNode = in.readUTF(); //last managing node
Long expiry = in.readLong();
Long maxIdle = in.readLong();
HashMap<String,Object> attributes = (HashMap<String,Object>)in.readObject();
Session session = new Session(clusterId, created, accessed, maxIdle);
session.setCookieSetTime(cookieSet);
session.setLastAccessedTime(lastAccessed);
session.setLastNode(lastNode);
session.setContextPath(context);
session.setVHost(vhost);
session.setExpiry(expiry);
session.addAttributes(attributes);
setSession(session);
}
private void readObjectNoData() throws ObjectStreamException
{
setSession(null);
}
}
/**
* Session
*
@ -317,11 +223,6 @@ public class InfinispanSessionManager extends AbstractSessionManager
private String _contextPath;
/**
* The number of currently active request threads in this session
*/
private AtomicInteger _activeThreads = new AtomicInteger(0);
/**
* The time in msec since the epoch at which this session should expire
@ -341,12 +242,24 @@ public class InfinispanSessionManager extends AbstractSessionManager
private String _lastNode;
/**
* If dirty, session needs to be (re)sent to cluster
*/
protected boolean _dirty=false;
/**
* Any virtual hosts for the context with which this session is associated
*/
private String _vhost;
/**
* Count of how many threads are active in this session
*/
private AtomicInteger _activeThreads = new AtomicInteger(0);
@ -364,6 +277,7 @@ public class InfinispanSessionManager extends AbstractSessionManager
_lastNode = getSessionIdManager().getWorkerName();
setVHost(InfinispanSessionManager.getVirtualHost(_context));
setContextPath(InfinispanSessionManager.getContextPath(_context));
_activeThreads.incrementAndGet(); //access will not be called on a freshly created session so increment here
}
@ -404,13 +318,13 @@ public class InfinispanSessionManager extends AbstractSessionManager
LOG.debug("Access session({}) for context {} on worker {}", getId(), getContextPath(), getSessionIdManager().getWorkerName());
try
{
_lock.lock();
long now = System.currentTimeMillis();
//lock so that no other thread can call access or complete until the first one has refreshed the session object if necessary
_lock.lock();
//a request thread is entering
if (_activeThreads.incrementAndGet() == 1)
{
long now = System.currentTimeMillis();
//if the first thread, check that the session in memory is not stale, if we're checking for stale sessions
if (getStaleIntervalSec() > 0 && (now - getLastSyncTime()) >= (getStaleIntervalSec() * 1000L))
{
@ -448,28 +362,65 @@ public class InfinispanSessionManager extends AbstractSessionManager
{
super.complete();
//if this is the last request thread to be in the session
if (_activeThreads.decrementAndGet() == 0)
//lock so that no other thread that might be calling access can proceed until this complete is done
_lock.lock();
try
{
try
//if this is the last request thread to be in the session
if (_activeThreads.decrementAndGet() == 0)
{
//an invalid session will already have been removed from the
//local session map and deleted from the cluster. If its valid save
//it to the cluster.
//TODO consider doing only periodic saves if only the last access
//time to the session changes
if (isValid())
try
{
willPassivate();
save(this);
didActivate();
//an invalid session will already have been removed from the
//local session map and deleted from the cluster. If its valid save
//it to the cluster.
//TODO consider doing only periodic saves if only the last access
//time to the session changes
if (isValid())
{
//if session still valid && its dirty or stale or never been synced, write it to the cluster
//otherwise, we just keep the updated last access time in memory
if (_dirty || getLastSyncTime() == 0 || isStale(System.currentTimeMillis()))
{
willPassivate();
save(this);
didActivate();
}
}
}
catch (Exception e)
{
LOG.warn("Problem saving session({})",getId(), e);
}
finally
{
_dirty = false;
}
}
catch (Exception e)
{
LOG.warn("Problem saving session({})",getId(), e);
}
}
}
finally
{
_lock.unlock();
}
}
/** Test if the session is stale
* @param atTime
* @return
*/
protected boolean isStale (long atTime)
{
return (getStaleIntervalSec() > 0) && (atTime - getLastSyncTime() >= (getStaleIntervalSec()*1000L));
}
/** Test if the session is dirty
* @return
*/
protected boolean isDirty ()
{
return _dirty;
}
/**
@ -483,6 +434,8 @@ public class InfinispanSessionManager extends AbstractSessionManager
super.timeout();
}
/**
* Reload the session from the cluster. If the node that
* last managed the session from the cluster is ourself,
@ -494,8 +447,8 @@ public class InfinispanSessionManager extends AbstractSessionManager
private void refresh ()
{
//get fresh copy from the cluster
Session fresh = load(getId());
Session fresh = load(makeKey(getClusterId(), _context));
//if the session no longer exists, invalidate
if (fresh == null)
{
@ -564,6 +517,7 @@ public class InfinispanSessionManager extends AbstractSessionManager
public void swapId (String newId, String newNodeId)
{
//TODO probably synchronize rather than use the access/complete lock?
_lock.lock();
setClusterId(newId);
setNodeId(newNodeId);
@ -577,7 +531,7 @@ public class InfinispanSessionManager extends AbstractSessionManager
if (value == null && old == null)
return; //if same as remove attribute but attribute was already removed, no change
//TODO _dirty = true;
_dirty = true;
}
@ -709,7 +663,7 @@ public class InfinispanSessionManager extends AbstractSessionManager
candidateIds.add(entry.getKey());
}
}
for (String candidateId:candidateIds)
{
if (LOG.isDebugEnabled())
@ -719,7 +673,8 @@ public class InfinispanSessionManager extends AbstractSessionManager
if (candidateSession != null)
{
//double check the state of the session in the cache, as the
//session may have migrated to another node
//session may have migrated to another node. This leaves a window
//where the cached session may have been changed by another node
Session cachedSession = load(makeKey(candidateId, _context));
if (cachedSession == null)
{
@ -755,8 +710,7 @@ public class InfinispanSessionManager extends AbstractSessionManager
/**
* Set the interval between runs of the scavenger. As this will be a costly
* exercise (need to iterate over all cache entries) it should not be run too
* Set the interval between runs of the scavenger. It should not be run too
* often.
*
*
@ -803,7 +757,7 @@ public class InfinispanSessionManager extends AbstractSessionManager
*
* @return
*/
public Cache<String, Object> getCache()
public BasicCache<String, Object> getCache()
{
return _cache;
}
@ -815,7 +769,7 @@ public class InfinispanSessionManager extends AbstractSessionManager
*
* @param cache
*/
public void setCache (Cache<String, Object> cache)
public void setCache (BasicCache<String, Object> cache)
{
this._cache = cache;
}
@ -873,7 +827,6 @@ public class InfinispanSessionManager extends AbstractSessionManager
{
Session session = null;
//try and find the session in this node's memory
Session memSession = (Session)_sessions.get(idInCluster);
@ -940,7 +893,7 @@ public class InfinispanSessionManager extends AbstractSessionManager
}
catch (Exception e)
{
LOG.warn("Unable to load session {}", idInCluster, e);
LOG.warn("Unable to load session="+idInCluster, e);
return null;
}
}
@ -955,8 +908,28 @@ public class InfinispanSessionManager extends AbstractSessionManager
@Override
protected void shutdownSessions() throws Exception
{
//TODO if implementing period saves, if we might have un-saved changes,
//then we need to write them back to the clustered cache
Set<String> keys = new HashSet<String>(_sessions.keySet());
for (String key:keys)
{
Session session = _sessions.remove(key); //take the session out of the session list
//If the session is dirty, then write it to the cluster.
//If the session is simply stale do NOT write it to the cluster, as some other node
//may have started managing that session - this means that the last accessed/expiry time
//will not be updated, meaning it may look like it can expire sooner than it should.
try
{
if (session.isDirty())
{
if (LOG.isDebugEnabled())
LOG.debug("Saving dirty session {} before exiting ", session.getId());
save(session);
}
}
catch (Exception e)
{
LOG.warn(e);
}
}
}
@ -1029,7 +1002,7 @@ public class InfinispanSessionManager extends AbstractSessionManager
throw new IllegalStateException("No cache");
if (LOG.isDebugEnabled()) LOG.debug("Loading session {} from cluster", key);
//SerializableSession storableSession = (SerializableSession)_cache.get(key);
SerializableSessionData storableSession = (SerializableSessionData)_cache.get(key);
if (storableSession == null)
{
@ -1038,7 +1011,6 @@ public class InfinispanSessionManager extends AbstractSessionManager
}
else
{
//Session session = storableSession.getSession();
Session session = new Session (storableSession);
session.setLastSyncTime(System.currentTimeMillis());
return session;
@ -1062,7 +1034,20 @@ public class InfinispanSessionManager extends AbstractSessionManager
if (LOG.isDebugEnabled()) LOG.debug("Writing session {} to cluster", session.getId());
SerializableSessionData storableSession = new SerializableSessionData(session);
_cache.put(makeKey(session, _context), storableSession);
//Put an idle timeout on the cache entry if the session is not immortal -
//if no requests arrive at any node before this timeout occurs, or no node
//scavenges the session before this timeout occurs, the session will be removed.
//NOTE: that no session listeners can be called for this.
InfinispanSessionIdManager sessionIdManager = (InfinispanSessionIdManager)getSessionIdManager();
if (storableSession.maxInactive > 0)
_cache.put(makeKey(session, _context), storableSession, -1, TimeUnit.SECONDS, storableSession.maxInactive*sessionIdManager.getIdleExpiryMultiple(), TimeUnit.SECONDS);
else
_cache.put(makeKey(session, _context), storableSession);
//tickle the session id manager to keep the sessionid entry for this session up-to-date
sessionIdManager.touch(session.getClusterId());
session.setLastSyncTime(System.currentTimeMillis());
}
@ -1074,7 +1059,7 @@ public class InfinispanSessionManager extends AbstractSessionManager
* @param session
*/
protected void delete (InfinispanSessionManager.Session session)
{
{
if (_cache == null)
throw new IllegalStateException("No cache");
if (LOG.isDebugEnabled()) LOG.debug("Removing session {} from cluster", session.getId());

View File

@ -21,9 +21,9 @@ package org.eclipse.jetty.server.session;
import org.junit.Test;
/**
* LightLoadTest
* ScatterGunLoadTest
*/
public class LightLoadTest extends AbstractLightLoadTest
public class ScatterGunLoadTest extends AbstractScatterGunLoadTest
{
public AbstractTestServer createServer(int port)

View File

@ -41,6 +41,9 @@
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>false</skipTests>
<includes>
<include>org/eclipse/jetty/server/session/*.java</include>
</includes>
</configuration>
</plugin>
<plugin>
@ -108,14 +111,20 @@
<artifactId>jetty-test-helper</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-client-hotrod</artifactId>
<version>7.1.1.Final</version>
<scope>test</scope>
</dependency>
</dependencies>
<!--
<profiles>
<!-- to test hotrod, configure a cache called "remote-session-test" -->
<profile>
<id>mongodb</id>
<id>remote</id>
<activation>
<property>
<name>mongodb.enabled</name>
<name>hotrod.enabled</name>
<value>true</value>
</property>
</activation>
@ -125,12 +134,13 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>false</skipTests>
<includes>
<include>**/*.java</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
-->
</project>

View File

@ -24,6 +24,7 @@ import org.eclipse.jetty.server.SessionManager;
import org.eclipse.jetty.session.infinispan.InfinispanSessionIdManager;
import org.eclipse.jetty.session.infinispan.InfinispanSessionManager;
import org.infinispan.Cache;
import org.infinispan.commons.api.BasicCache;
import org.infinispan.commons.util.CloseableIteratorSet;
public class InfinispanTestSessionServer extends AbstractTestServer
@ -34,14 +35,14 @@ public class InfinispanTestSessionServer extends AbstractTestServer
public InfinispanTestSessionServer(int port, Cache config)
public InfinispanTestSessionServer(int port, BasicCache config)
{
this(port, 30, 10, config);
}
public InfinispanTestSessionServer(int port, int maxInactivePeriod, int scavengePeriod, Cache config)
public InfinispanTestSessionServer(int port, int maxInactivePeriod, int scavengePeriod, BasicCache config)
{
super(port, maxInactivePeriod, scavengePeriod, config);
}
@ -53,7 +54,7 @@ public class InfinispanTestSessionServer extends AbstractTestServer
{
InfinispanSessionIdManager idManager = new InfinispanSessionIdManager(getServer());
idManager.setWorkerName("w"+(__workers++));
idManager.setCache((Cache)config);
idManager.setCache((BasicCache)config);
return idManager;
}
@ -75,22 +76,40 @@ public class InfinispanTestSessionServer extends AbstractTestServer
return new SessionHandler(sessionManager);
}
public boolean exists (String id)
{
BasicCache cache = ((InfinispanSessionIdManager)_sessionIdManager).getCache();
if (cache != null)
{
return cache.containsKey(id);
}
return false;
}
public Object get (String id)
{
BasicCache cache = ((InfinispanSessionIdManager)_sessionIdManager).getCache();
if (cache != null)
{
return cache.get(id);
}
return null;
}
public void dumpCache ()
{
Cache cache = ((InfinispanSessionIdManager)_sessionIdManager).getCache();
BasicCache cache = ((InfinispanSessionIdManager)_sessionIdManager).getCache();
if (cache != null)
{
System.err.println(cache.getName()+" contains "+cache.size()+" entries");
CloseableIteratorSet<String> keys = cache.keySet();
for (String key:keys)
System.err.println(key + " "+cache.get(key));
System.err.println(cache.getName()+" contains "+cache.size()+" entries");
}
}
public void clearCache ()
{
Cache cache = ((InfinispanSessionIdManager)_sessionIdManager).getCache();
BasicCache cache = ((InfinispanSessionIdManager)_sessionIdManager).getCache();
if (cache != null)
cache.clear();
}

View File

@ -19,17 +19,6 @@
package org.eclipse.jetty.server.session;
import java.io.File;
import org.eclipse.jetty.server.SessionManager;
import org.eclipse.jetty.session.infinispan.InfinispanSessionIdManager;
import org.eclipse.jetty.session.infinispan.InfinispanSessionManager;
import org.eclipse.jetty.util.IO;
import org.infinispan.Cache;
import org.infinispan.configuration.cache.Configuration;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.manager.DefaultCacheManager;
import org.infinispan.manager.EmbeddedCacheManager;
import org.junit.AfterClass;
import org.junit.BeforeClass;
@ -66,20 +55,6 @@ public class InvalidationSessionTest extends AbstractInvalidationSessionTest
public AbstractTestServer createServer(int port)
{
return new InfinispanTestSessionServer(port, __testSupport.getCache());
// return new InfinispanTestSessionServer(port, __cache)
// {
//
// @Override
// public SessionManager newSessionManager()
// {
// InfinispanSessionManager sessionManager = new InfinispanSessionManager();
// sessionManager.setSessionIdManager((InfinispanSessionIdManager)_sessionIdManager);
// sessionManager.setStaleIntervalSec(__staleSec);
// sessionManager.setCache(((InfinispanSessionIdManager)_sessionIdManager).getCache());
// return sessionManager;
// }
// };
}

View File

@ -0,0 +1,66 @@
//
// ========================================================================
// 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;
import org.junit.AfterClass;
import org.junit.BeforeClass;
/**
* SameNodeLoadTest
*
*
*/
public class SameNodeLoadTest extends AbstractSameNodeLoadTest
{
public static InfinispanTestSupport __testSupport;
@BeforeClass
public static void setup () throws Exception
{
__testSupport = new InfinispanTestSupport();
__testSupport.setup();
}
@AfterClass
public static void teardown () throws Exception
{
__testSupport.teardown();
}
/**
* @see org.eclipse.jetty.server.session.AbstractSameNodeLoadTest#createServer(int)
*/
@Override
public AbstractTestServer createServer(int port)
{
InfinispanTestSessionServer server = new InfinispanTestSessionServer(port, __testSupport.getCache());
return server;
}
@Override
public void testLoad() throws Exception
{
super.testLoad();
}
}

View File

@ -0,0 +1,69 @@
//
// ========================================================================
// 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.remote;
import org.eclipse.jetty.server.session.AbstractClientCrossContextSessionTest;
import org.eclipse.jetty.server.session.AbstractTestServer;
import org.eclipse.jetty.server.session.InfinispanTestSessionServer;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
/**
* RemoteClientCrossContextSessionTest
*
*
*/
public class RemoteClientCrossContextSessionTest extends AbstractClientCrossContextSessionTest
{
public static RemoteInfinispanTestSupport __testSupport;
@BeforeClass
public static void setup () throws Exception
{
__testSupport = new RemoteInfinispanTestSupport("remote-session-test");
__testSupport.setup();
}
@AfterClass
public static void teardown () throws Exception
{
__testSupport.teardown();
}
@Override
public AbstractTestServer createServer(int port)
{
InfinispanTestSessionServer server = new InfinispanTestSessionServer(port, __testSupport.getCache());
return server;
}
@Test
public void testCrossContextDispatch() throws Exception
{
super.testCrossContextDispatch();
}
}

View File

@ -0,0 +1,74 @@
//
// ========================================================================
// 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.remote;
import org.eclipse.jetty.server.session.AbstractImmortalSessionTest;
import org.eclipse.jetty.server.session.AbstractTestServer;
import org.eclipse.jetty.server.session.InfinispanTestSessionServer;
import org.infinispan.Cache;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.manager.DefaultCacheManager;
import org.infinispan.manager.EmbeddedCacheManager;
import org.junit.AfterClass;
import org.junit.BeforeClass;
/**
* ImmortalSessionTest
*
*
*/
public class RemoteImmortalSessionTest extends AbstractImmortalSessionTest
{
public static RemoteInfinispanTestSupport __testSupport;
@BeforeClass
public static void setup () throws Exception
{
__testSupport = new RemoteInfinispanTestSupport("remote-session-test");
__testSupport.setup();
}
@AfterClass
public static void teardown () throws Exception
{
__testSupport.teardown();
}
/**
* @see org.eclipse.jetty.server.session.AbstractImmortalSessionTest#createServer(int, int, int)
*/
@Override
public AbstractTestServer createServer(int port, int maxInactiveMs, int scavengeMs)
{
return new InfinispanTestSessionServer(port, maxInactiveMs, scavengeMs, __testSupport.getCache());
}
@Override
public void testImmortalSession() throws Exception
{
super.testImmortalSession();
}
}

View File

@ -0,0 +1,88 @@
//
// ========================================================================
// 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.remote;
import java.io.File;
import org.eclipse.jetty.util.IO;
import org.infinispan.Cache;
import org.infinispan.client.hotrod.RemoteCache;
import org.infinispan.client.hotrod.RemoteCacheManager;
import org.infinispan.configuration.cache.Configuration;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.configuration.global.GlobalConfigurationBuilder;
import org.infinispan.manager.DefaultCacheManager;
import org.infinispan.manager.EmbeddedCacheManager;
/**
* RemoteInfinispanTestSupport
*
*
*/
public class RemoteInfinispanTestSupport
{
public static final String DEFAULT_CACHE_NAME = "session_test_cache";
public RemoteCache _cache;
private String _name;
public static RemoteCacheManager _manager;
static
{
try
{
_manager = new RemoteCacheManager();
}
catch (Exception e)
{
e.printStackTrace();
}
}
public RemoteInfinispanTestSupport ()
{
this (null);
}
public RemoteInfinispanTestSupport(String cacheName)
{
if (cacheName == null)
cacheName = DEFAULT_CACHE_NAME+System.currentTimeMillis();
_name = cacheName;
}
public RemoteCache getCache ()
{
return _cache;
}
public void setup () throws Exception
{
_cache = _manager.getCache(_name);
}
public void teardown () throws Exception
{
}
}

View File

@ -0,0 +1,93 @@
//
// ========================================================================
// 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.remote;
import org.eclipse.jetty.server.session.AbstractInvalidationSessionTest;
import org.eclipse.jetty.server.session.AbstractTestServer;
import org.eclipse.jetty.server.session.InfinispanTestSessionServer;
import org.junit.AfterClass;
import org.junit.BeforeClass;
/**
* InvalidationSessionTest
*
*
*/
public class RemoteInvalidationSessionTest extends AbstractInvalidationSessionTest
{
public static RemoteInfinispanTestSupport __testSupport;
public static long __staleSec = 3L;
@BeforeClass
public static void setup () throws Exception
{
__testSupport = new RemoteInfinispanTestSupport("remote-session-test");
__testSupport.setup();
}
@AfterClass
public static void teardown () throws Exception
{
__testSupport.teardown();
}
/**
* @see org.eclipse.jetty.server.session.AbstractInvalidationSessionTest#createServer(int)
*/
@Override
public AbstractTestServer createServer(int port)
{
return new InfinispanTestSessionServer(port, __testSupport.getCache());
}
@Override
public void testInvalidation() throws Exception
{
super.testInvalidation();
}
/**
* @see org.eclipse.jetty.server.session.AbstractInvalidationSessionTest#pause()
*/
@Override
public void pause()
{
//This test moves a session from node 1 to node 2, then invalidates the session back on node1. This
//should never happen with a decent load balancer.
//The infinispan session manager on node 2 will hold the session in local memory for a specific (configurable)
//amount of time. We've set the stale session time to 3 sec, so we need to pause for at least this long before making
//another request to node2 so
//that the node will re-load the session from the database and discover that it has gone.
try
{
Thread.sleep(2 * __staleSec * 1000);
}
catch (InterruptedException e)
{
}
}
}

View File

@ -0,0 +1,67 @@
//
// ========================================================================
// 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.remote;
import java.io.File;
import org.eclipse.jetty.server.session.AbstractLastAccessTimeTest;
import org.eclipse.jetty.server.session.AbstractTestServer;
import org.eclipse.jetty.server.session.InfinispanTestSessionServer;
import org.eclipse.jetty.util.IO;
import org.infinispan.Cache;
import org.infinispan.configuration.cache.Configuration;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.manager.DefaultCacheManager;
import org.infinispan.manager.EmbeddedCacheManager;
import org.junit.AfterClass;
import org.junit.BeforeClass;
public class RemoteLastAccessTimeTest extends AbstractLastAccessTimeTest
{
public static RemoteInfinispanTestSupport __testSupport;
@BeforeClass
public static void setup () throws Exception
{
__testSupport = new RemoteInfinispanTestSupport("remote-session-test");
__testSupport.setup();
}
@AfterClass
public static void teardown () throws Exception
{
__testSupport.teardown();
}
@Override
public AbstractTestServer createServer(int port, int max, int scavenge)
{
return new InfinispanTestSessionServer(port, max, scavenge, __testSupport.getCache());
}
@Override
public void testLastAccessTime() throws Exception
{
super.testLastAccessTime();
}
}

View File

@ -0,0 +1,61 @@
//
// ========================================================================
// 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.remote;
import org.eclipse.jetty.server.session.AbstractLocalSessionScavengingTest;
import org.eclipse.jetty.server.session.AbstractTestServer;
import org.eclipse.jetty.server.session.InfinispanTestSessionServer;
import org.junit.AfterClass;
import org.junit.BeforeClass;
/**
* LocalSessionScavengingTest
*
*
*/
public class RemoteLocalSessionScavengingTest extends AbstractLocalSessionScavengingTest
{
public static RemoteInfinispanTestSupport __testSupport;
@BeforeClass
public static void setup () throws Exception
{
__testSupport = new RemoteInfinispanTestSupport("remote-session-test");
__testSupport.setup();
}
@AfterClass
public static void teardown () throws Exception
{
__testSupport.teardown();
}
/**
* @see org.eclipse.jetty.server.session.AbstractLocalSessionScavengingTest#createServer(int, int, int)
*/
@Override
public AbstractTestServer createServer(int port, int max, int scavenge)
{
return new InfinispanTestSessionServer(port, max, scavenge, __testSupport.getCache());
}
}

View File

@ -0,0 +1,69 @@
//
// ========================================================================
// 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.remote;
import org.eclipse.jetty.server.session.AbstractNewSessionTest;
import org.eclipse.jetty.server.session.AbstractTestServer;
import org.eclipse.jetty.server.session.InfinispanTestSessionServer;
import org.junit.AfterClass;
import org.junit.BeforeClass;
/**
* NewSessionTest
*
*
*/
public class RemoteNewSessionTest extends AbstractNewSessionTest
{
public static RemoteInfinispanTestSupport __testSupport;
@BeforeClass
public static void setup () throws Exception
{
__testSupport = new RemoteInfinispanTestSupport("remote-session-test");
__testSupport.setup();
}
@AfterClass
public static void teardown () throws Exception
{
__testSupport.teardown();
}
/**
* @see org.eclipse.jetty.server.session.AbstractNewSessionTest#createServer(int, int, int)
*/
@Override
public AbstractTestServer createServer(int port, int max, int scavenge)
{
return new InfinispanTestSessionServer(port, max, scavenge, __testSupport.getCache());
}
@Override
public void testNewSession() throws Exception
{
super.testNewSession();
}
}

View File

@ -0,0 +1,67 @@
//
// ========================================================================
// 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.remote;
import org.eclipse.jetty.server.session.AbstractReentrantRequestSessionTest;
import org.eclipse.jetty.server.session.AbstractTestServer;
import org.eclipse.jetty.server.session.InfinispanTestSessionServer;
import org.junit.AfterClass;
import org.junit.BeforeClass;
/**
* ReentrantRequestSessionTest
*
*
*/
public class RemoteReentrantRequestSessionTest extends AbstractReentrantRequestSessionTest
{
public static RemoteInfinispanTestSupport __testSupport;
@BeforeClass
public static void setup () throws Exception
{
__testSupport = new RemoteInfinispanTestSupport("remote-session-test");
__testSupport.setup();
}
@AfterClass
public static void teardown () throws Exception
{
__testSupport.teardown();
}
/**
* @see org.eclipse.jetty.server.session.AbstractReentrantRequestSessionTest#createServer(int)
*/
@Override
public AbstractTestServer createServer(int port)
{
return new InfinispanTestSessionServer(port, __testSupport.getCache());
}
@Override
public void testReentrantRequestSession() throws Exception
{
super.testReentrantRequestSession();
}
}

View File

@ -0,0 +1,61 @@
//
// ========================================================================
// 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.remote;
import org.eclipse.jetty.server.session.AbstractRemoveSessionTest;
import org.eclipse.jetty.server.session.AbstractTestServer;
import org.eclipse.jetty.server.session.InfinispanTestSessionServer;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class RemoteRemoveSessionTest extends AbstractRemoveSessionTest
{
public static RemoteInfinispanTestSupport __testSupport;
@BeforeClass
public static void setup () throws Exception
{
__testSupport = new RemoteInfinispanTestSupport("remote-session-test");
__testSupport.setup();
}
@AfterClass
public static void teardown () throws Exception
{
__testSupport.teardown();
}
@Override
public AbstractTestServer createServer(int port, int max, int scavenge)
{
InfinispanTestSessionServer s = new InfinispanTestSessionServer(port, max, scavenge, __testSupport.getCache());
return s;
}
@Test
public void testRemoveSession() throws Exception
{
super.testRemoveSession();
}
}

View File

@ -0,0 +1,69 @@
//
// ========================================================================
// 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.remote;
import org.eclipse.jetty.server.session.AbstractSameNodeLoadTest;
import org.eclipse.jetty.server.session.AbstractTestServer;
import org.eclipse.jetty.server.session.InfinispanTestSessionServer;
import org.junit.AfterClass;
import org.junit.BeforeClass;
/**
* SameNodeLoadTest
*
*
*/
public class RemoteSameNodeLoadTest extends AbstractSameNodeLoadTest
{
public static RemoteInfinispanTestSupport __testSupport;
@BeforeClass
public static void setup () throws Exception
{
__testSupport = new RemoteInfinispanTestSupport("remote-session-test");
__testSupport.setup();
}
@AfterClass
public static void teardown () throws Exception
{
__testSupport.teardown();
}
/**
* @see org.eclipse.jetty.server.session.AbstractSameNodeLoadTest#createServer(int)
*/
@Override
public AbstractTestServer createServer(int port)
{
InfinispanTestSessionServer server = new InfinispanTestSessionServer(port, __testSupport.getCache());
return server;
}
@Override
public void testLoad() throws Exception
{
super.testLoad();
}
}

View File

@ -0,0 +1,73 @@
//
// ========================================================================
// 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.remote;
import org.eclipse.jetty.server.session.AbstractSessionExpiryTest;
import org.eclipse.jetty.server.session.AbstractTestServer;
import org.eclipse.jetty.server.session.InfinispanTestSessionServer;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class RemoteSessionExpiryTest extends AbstractSessionExpiryTest
{
public static RemoteInfinispanTestSupport __testSupport;
@BeforeClass
public static void setup () throws Exception
{
__testSupport = new RemoteInfinispanTestSupport("remote-session-test");
__testSupport.setup();
}
@AfterClass
public static void teardown () throws Exception
{
__testSupport.teardown();
}
@Override
public AbstractTestServer createServer(int port, int max, int scavenge)
{
InfinispanTestSessionServer server = new InfinispanTestSessionServer(port, max, scavenge, __testSupport.getCache());
return server;
}
@Test
@Override
public void testSessionNotExpired() throws Exception
{
super.testSessionNotExpired();
}
@Test
@Override
public void testSessionExpiry() throws Exception
{
super.testSessionExpiry();
}
@Override
public void verifySessionDestroyed (TestHttpSessionListener listener, String sessionId)
{
//noop - sessions that expired when the InfinispanSessionManager was not running are not reloaded and do not have their listeners called on them.
}
}

View File

@ -0,0 +1,69 @@
//
// ========================================================================
// 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.remote;
import org.eclipse.jetty.server.session.AbstractSessionInvalidateAndCreateTest;
import org.eclipse.jetty.server.session.AbstractTestServer;
import org.eclipse.jetty.server.session.InfinispanTestSessionServer;
import org.junit.AfterClass;
import org.junit.BeforeClass;
/**
* SessionInvalidateAndCreateTest
*
*
*/
public class RemoteSessionInvalidateAndCreateTest extends AbstractSessionInvalidateAndCreateTest
{
public static RemoteInfinispanTestSupport __testSupport;
@BeforeClass
public static void setup () throws Exception
{
__testSupport = new RemoteInfinispanTestSupport("remote-session-test");
__testSupport.setup();
}
@AfterClass
public static void teardown () throws Exception
{
__testSupport.teardown();
}
/**
* @see org.eclipse.jetty.server.session.AbstractSessionInvalidateAndCreateTest#createServer(int, int, int)
*/
@Override
public AbstractTestServer createServer(int port, int max, int scavenge)
{
return new InfinispanTestSessionServer(port, max, scavenge, __testSupport.getCache());
}
@Override
public void testSessionScavenge() throws Exception
{
super.testSessionScavenge();
}
}

View File

@ -0,0 +1,68 @@
//
// ========================================================================
// 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.remote;
import org.eclipse.jetty.server.session.AbstractSessionMigrationTest;
import org.eclipse.jetty.server.session.AbstractTestServer;
import org.eclipse.jetty.server.session.InfinispanTestSessionServer;
import org.junit.AfterClass;
import org.junit.BeforeClass;
/**
* RemoteSessionMigrationTest
*
*
*/
public class RemoteSessionMigrationTest extends AbstractSessionMigrationTest
{
public static RemoteInfinispanTestSupport __testSupport;
@BeforeClass
public static void setup () throws Exception
{
__testSupport = new RemoteInfinispanTestSupport("remote-session-test");
__testSupport.setup();
}
@AfterClass
public static void teardown () throws Exception
{
__testSupport.teardown();
}
/**
* @see org.eclipse.jetty.server.session.AbstractSessionMigrationTest#createServer(int)
*/
@Override
public AbstractTestServer createServer(int port)
{
return new InfinispanTestSessionServer(port, __testSupport.getCache());
}
@Override
public void testSessionMigration() throws Exception
{
super.testSessionMigration();
}
}

View File

@ -0,0 +1,70 @@
//
// ========================================================================
// 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.remote;
import org.eclipse.jetty.server.session.AbstractSessionRenewTest;
import org.eclipse.jetty.server.session.AbstractTestServer;
import org.eclipse.jetty.server.session.InfinispanTestSessionServer;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* SessionRenewTest
*
*
*/
public class RemoteSessionRenewTest extends AbstractSessionRenewTest
{
public static RemoteInfinispanTestSupport __testSupport;
@BeforeClass
public static void setup () throws Exception
{
__testSupport = new RemoteInfinispanTestSupport("remote-session-test");
__testSupport.setup();
}
@AfterClass
public static void teardown () throws Exception
{
__testSupport.teardown();
}
/**
* @see org.eclipse.jetty.server.session.AbstractSessionRenewTest#createServer(int, int, int)
*/
@Override
public AbstractTestServer createServer(int port, int max, int scavenge)
{
return new InfinispanTestSessionServer(port, max, scavenge, __testSupport.getCache());
}
@Test
public void testSessionRenewal() throws Exception
{
super.testSessionRenewal();
}
}

View File

@ -18,14 +18,14 @@
package org.eclipse.jetty.nosql.mongodb;
import org.eclipse.jetty.server.session.AbstractLightLoadTest;
import org.eclipse.jetty.server.session.AbstractScatterGunLoadTest;
import org.eclipse.jetty.server.session.AbstractTestServer;
import org.junit.Test;
/**
* LightLoadTest
* ScatterGunLoadTest
*/
public class LightLoadTest extends AbstractLightLoadTest
public class ScatterGunLoadTest extends AbstractScatterGunLoadTest
{
public AbstractTestServer createServer(int port)

View File

@ -0,0 +1,231 @@
//
// ========================================================================
// 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;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertNotNull;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Random;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
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.junit.Test;
/**
* AbstractSameNodeLoadTest
*
* This test performs multiple concurrent requests for the same session on the same node.
*
*/
public abstract class AbstractSameNodeLoadTest
{
protected boolean _stress = Boolean.getBoolean( "STRESS" );
public abstract AbstractTestServer createServer(int port);
@Test
public void testLoad() throws Exception
{
if ( _stress )
{
String contextPath = "";
String servletMapping = "/server";
AbstractTestServer server1 = createServer( 0 );
server1.addContext( contextPath ).addServlet( TestServlet.class, servletMapping );
try
{
server1.start();
int port1 = server1.getPort();
HttpClient client = new HttpClient();
client.start();
try
{
String url = "http://localhost:" + port1 + contextPath + servletMapping;
//create session via first server
ContentResponse response1 = client.GET(url + "?action=init");
assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
String sessionCookie = response1.getHeaders().getStringField( "Set-Cookie" );
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
//simulate 10 clients making 100 requests each
ExecutorService executor = Executors.newCachedThreadPool();
int clientsCount = 10;
CyclicBarrier barrier = new CyclicBarrier( clientsCount + 1 );
int requestsCount = 100;
Worker[] workers = new Worker[clientsCount];
for ( int i = 0; i < clientsCount; ++i )
{
workers[i] = new Worker(barrier, client, requestsCount, sessionCookie, url);
executor.execute( workers[i] );
}
// Wait for all workers to be ready
barrier.await();
long start = System.nanoTime();
// Wait for all workers to be done
barrier.await();
long end = System.nanoTime();
long elapsed = TimeUnit.NANOSECONDS.toMillis( end - start );
System.out.println( "elapsed ms: " + elapsed );
executor.shutdownNow();
// Perform one request to get the result
Request request = client.newRequest( url + "?action=result" );
request.header("Cookie", sessionCookie);
ContentResponse response2 = request.send();
assertEquals(HttpServletResponse.SC_OK,response2.getStatus());
String response = response2.getContentAsString();
System.out.println( "get = " + response );
assertEquals(response.trim(), String.valueOf( clientsCount * requestsCount ) );
}
finally
{
client.stop();
}
}
finally
{
server1.stop();
}
}
}
public static class Worker implements Runnable
{
public static int COUNT = 0;
private final HttpClient client;
private final CyclicBarrier barrier;
private final int requestsCount;
private final String sessionCookie;
private final String url;
private final String name;
public Worker(CyclicBarrier barrier, HttpClient client, int requestsCount, String sessionCookie, String url)
{
this.client = client;
this.barrier = barrier;
this.requestsCount = requestsCount;
this.sessionCookie = sessionCookie;
this.url = url;
this.name = ""+(COUNT++);
}
public void run()
{
try
{
// Wait for all workers to be ready
barrier.await();
Random random = new Random( System.nanoTime() );
for ( int i = 0; i < requestsCount; ++i )
{
int pauseMsec = random.nextInt(1000);
//wait a random number of milliseconds between requests up to 1 second
if (pauseMsec > 0)
{
Thread.currentThread().sleep(pauseMsec);
}
Request request = client.newRequest(url + "?action=increment");
request.header("Cookie", sessionCookie);
ContentResponse response = request.send();
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
}
// Wait for all workers to be done
barrier.await();
}
catch ( Exception x )
{
throw new RuntimeException( x );
}
}
}
public static class TestServlet
extends HttpServlet
{
@Override
protected void doGet( HttpServletRequest request, HttpServletResponse response )
throws ServletException, IOException
{
String action = request.getParameter( "action" );
if ( "init".equals( action ) )
{
HttpSession session = request.getSession( true );
session.setAttribute( "value", 0 );
}
else if ( "increment".equals( action ) )
{
HttpSession session = request.getSession( false );
assertNotNull(session);
synchronized(session)
{
int value = (Integer) session.getAttribute( "value" );
session.setAttribute( "value", value + 1 );
}
}
else if ( "result".equals( action ) )
{
HttpSession session = request.getSession( false );
assertNotNull(session);
Integer value = null;
synchronized (session)
{
value = (Integer) session.getAttribute( "value" );
}
PrintWriter writer = response.getWriter();
writer.println( value );
writer.flush();
}
}
}
}

View File

@ -42,9 +42,15 @@ import org.junit.Test;
/**
* AbstractLightLoadTest
* AbstractScatterGunLoadTest
*
* This is an unrealistic test. It takes a scatter-gun approach to smearing a
* single session across 2 different nodes at once.
*
* In the real world, we must have a load balancer that uses sticky sessions
* to keep the session pinned to a particular node.
*/
public abstract class AbstractLightLoadTest
public abstract class AbstractScatterGunLoadTest
{
protected boolean _stress = Boolean.getBoolean( "STRESS" );
@ -80,6 +86,7 @@ public abstract class AbstractLightLoadTest
urls[0] = "http://localhost:" + port1 + contextPath + servletMapping;
urls[1] = "http://localhost:" + port2 + contextPath + servletMapping;
//create session via first server
ContentResponse response1 = client.GET(urls[0] + "?action=init");
assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
String sessionCookie = response1.getHeaders().get( "Set-Cookie" );
@ -87,6 +94,7 @@ public abstract class AbstractLightLoadTest
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
//simulate 50 clients making 100 requests each
ExecutorService executor = Executors.newCachedThreadPool();
int clientsCount = 50;
CyclicBarrier barrier = new CyclicBarrier( clientsCount + 1 );
@ -216,7 +224,7 @@ public abstract class AbstractLightLoadTest
}
else if ( "increment".equals( action ) )
{
// Without synchronization, because it is taken care by Jetty/Terracotta
// Without synchronization
HttpSession session = request.getSession( false );
int value = (Integer) session.getAttribute( "value" );
session.setAttribute( "value", value + 1 );

View File

@ -35,6 +35,11 @@ import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.Test;
/**
* AbstractStopSessionManagerPreserveSessionTest
*
*
*/
public abstract class AbstractStopSessionManagerPreserveSessionTest
{
public String _id;