diff options
author | Jan Bartel | 2015-03-11 06:29:26 +0000 |
---|---|---|
committer | Jan Bartel | 2015-03-11 06:29:26 +0000 |
commit | 73234c988ec3f7f336e21d193e96ef35931eae6d (patch) | |
tree | f5ab92b5a73b60a3e584d1f6bcdf0149e5767c36 | |
parent | 61a478943e87688457d8eba92e0125cb7dd488ff (diff) | |
download | org.eclipse.jetty.project-73234c988ec3f7f336e21d193e96ef35931eae6d.tar.gz org.eclipse.jetty.project-73234c988ec3f7f336e21d193e96ef35931eae6d.tar.xz org.eclipse.jetty.project-73234c988ec3f7f336e21d193e96ef35931eae6d.zip |
436345 Refactor AbstractSession to minimize burden on subclasses to implement behaviour
31 files changed, 1874 insertions, 310 deletions
diff --git a/jetty-infinispan/src/main/java/org/eclipse/jetty/session/infinispan/InfinispanSessionIdManager.java b/jetty-infinispan/src/main/java/org/eclipse/jetty/session/infinispan/InfinispanSessionIdManager.java index ceb0d1c760..7ca6a58b73 100644 --- a/jetty-infinispan/src/main/java/org/eclipse/jetty/session/infinispan/InfinispanSessionIdManager.java +++ b/jetty-infinispan/src/main/java/org/eclipse/jetty/session/infinispan/InfinispanSessionIdManager.java @@ -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. diff --git a/jetty-infinispan/src/main/java/org/eclipse/jetty/session/infinispan/InfinispanSessionManager.java b/jetty-infinispan/src/main/java/org/eclipse/jetty/session/infinispan/InfinispanSessionManager.java index ca4d80899d..6e79a2a463 100644 --- a/jetty-infinispan/src/main/java/org/eclipse/jetty/session/infinispan/InfinispanSessionManager.java +++ b/jetty-infinispan/src/main/java/org/eclipse/jetty/session/infinispan/InfinispanSessionManager.java @@ -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(); } } @@ -206,102 +208,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 * * Representation of a session in local memory. @@ -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()); diff --git a/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/NoSqlSession.java b/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/NoSqlSession.java index 1a1459a45a..8b732d4d2b 100644 --- a/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/NoSqlSession.java +++ b/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/NoSqlSession.java @@ -24,13 +24,13 @@ import java.util.concurrent.atomic.AtomicInteger; import javax.servlet.http.HttpServletRequest; -import org.eclipse.jetty.server.session.AbstractSession; +import org.eclipse.jetty.server.session.MemSession; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /* ------------------------------------------------------------ */ -public class NoSqlSession extends AbstractSession +public class NoSqlSession extends MemSession { private final static Logger __log = Log.getLogger("org.eclipse.jetty.server.session"); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java index 689ca702e0..c909883fd4 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java @@ -21,8 +21,6 @@ package org.eclipse.jetty.server.session; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; -import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -54,7 +52,6 @@ public abstract class AbstractSession implements AbstractSessionManager.SessionI private String _clusterId; // ID without any node (ie "worker") id appended private String _nodeId; // ID of session with node(ie "worker") id appended private final AbstractSessionManager _manager; - private final Map<String,Object> _attributes=new HashMap<String, Object>(); private boolean _idChanged; private final long _created; private long _cookieSet; @@ -127,53 +124,21 @@ public abstract class AbstractSession implements AbstractSessionManager.SessionI } /* ------------------------------------------------------------- */ - public Map<String,Object> getAttributeMap() - { - return _attributes; - } + public abstract Map<String,Object> getAttributeMap(); - /* ------------------------------------------------------------ */ - @Override - public Object getAttribute(String name) - { - synchronized (this) - { - checkValid(); - return _attributes.get(name); - } - } - /* ------------------------------------------------------------ */ - public int getAttributes() - { - synchronized (this) - { - checkValid(); - return _attributes.size(); - } - } + + /* ------------------------------------------------------------ */ - @SuppressWarnings({ "unchecked" }) - @Override - public Enumeration<String> getAttributeNames() - { - synchronized (this) - { - checkValid(); - List<String> names=_attributes==null?Collections.EMPTY_LIST:new ArrayList<String>(_attributes.keySet()); - return Collections.enumeration(names); - } - } + public abstract int getAttributes(); + + + /* ------------------------------------------------------------ */ - public Set<String> getNames() - { - synchronized (this) - { - return new HashSet<String>(_attributes.keySet()); - } - } + public abstract Set<String> getNames(); + /* ------------------------------------------------------------- */ public long getCookieSetTime() @@ -266,25 +231,7 @@ public abstract class AbstractSession implements AbstractSessionManager.SessionI return getAttribute(name); } - /* ------------------------------------------------------------- */ - /** - * @deprecated As of Version 2.2, this method is replaced by - * {@link #getAttributeNames} - */ - @Deprecated - @Override - public String[] getValueNames() throws IllegalStateException - { - synchronized(this) - { - checkValid(); - if (_attributes==null) - return new String[0]; - String[] a=new String[_attributes.size()]; - return (String[])_attributes.keySet().toArray(a); - } - } - + /* ------------------------------------------------------------ */ public void renewId(HttpServletRequest request) @@ -397,34 +344,8 @@ public abstract class AbstractSession implements AbstractSessionManager.SessionI } /* ------------------------------------------------------------- */ - public void clearAttributes() - { - while (_attributes!=null && _attributes.size()>0) - { - ArrayList<String> keys; - synchronized(this) - { - keys=new ArrayList<String>(_attributes.keySet()); - } - - Iterator<String> iter=keys.iterator(); - while (iter.hasNext()) - { - String key=(String)iter.next(); - - Object value; - synchronized(this) - { - value=doPutOrRemove(key,null); - } - unbindValue(key,value); - - _manager.doSessionAttributeListeners(this,key,value,null); - } - } - if (_attributes!=null) - _attributes.clear(); - } + public abstract void clearAttributes(); + /* ------------------------------------------------------------- */ public boolean isIdChanged() @@ -470,18 +391,65 @@ public abstract class AbstractSession implements AbstractSessionManager.SessionI { removeAttribute(name); } - + /* ------------------------------------------------------------ */ - protected Object doPutOrRemove(String name, Object value) + @SuppressWarnings({ "unchecked" }) + @Override + public Enumeration<String> getAttributeNames() { - return value==null?_attributes.remove(name):_attributes.put(name,value); + synchronized (this) + { + checkValid(); + return doGetAttributeNames(); + } } + + /* ------------------------------------------------------------- */ + /** + * @deprecated As of Version 2.2, this method is replaced by + * {@link #getAttributeNames} + */ + @Deprecated + @Override + public String[] getValueNames() throws IllegalStateException + { + synchronized(this) + { + checkValid(); + Enumeration<String> anames = doGetAttributeNames(); + if (anames == null) + return new String[0]; + ArrayList<String> names = new ArrayList<String>(); + while (anames.hasMoreElements()) + names.add(anames.nextElement()); + return names.toArray(new String[names.size()]); + } + } + + + /* ------------------------------------------------------------ */ + public abstract Object doPutOrRemove(String name, Object value); + /* ------------------------------------------------------------ */ - protected Object doGet(String name) + public abstract Object doGet(String name); + + + /* ------------------------------------------------------------ */ + public abstract Enumeration<String> doGetAttributeNames(); + + + /* ------------------------------------------------------------ */ + @Override + public Object getAttribute(String name) { - return _attributes.get(name); + synchronized (this) + { + checkValid(); + return doGet(name); + } } + /* ------------------------------------------------------------ */ @Override @@ -565,12 +533,7 @@ public abstract class AbstractSession implements AbstractSessionManager.SessionI _manager.doSessionAttributeListeners(this,name,oldValue,newValue); } } - - /* ------------------------------------------------------------ */ - protected void addAttributes(Map<String,Object> map) - { - _attributes.putAll(map); - } + /* ------------------------------------------------------------- */ public void setIdChanged(boolean changed) @@ -647,7 +610,7 @@ public abstract class AbstractSession implements AbstractSessionManager.SessionI synchronized(this) { HttpSessionEvent event = new HttpSessionEvent(this); - for (Iterator<Object> iter = _attributes.values().iterator(); iter.hasNext();) + for (Iterator<Object> iter = getAttributeMap().values().iterator(); iter.hasNext();) { Object value = iter.next(); if (value instanceof HttpSessionActivationListener) @@ -665,7 +628,7 @@ public abstract class AbstractSession implements AbstractSessionManager.SessionI synchronized(this) { HttpSessionEvent event = new HttpSessionEvent(this); - for (Iterator<Object> iter = _attributes.values().iterator(); iter.hasNext();) + for (Iterator<Object> iter = getAttributeMap().values().iterator(); iter.hasNext();) { Object value = iter.next(); if (value instanceof HttpSessionActivationListener) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashedSession.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashedSession.java index dc599cc5dc..d36e4277e4 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashedSession.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashedSession.java @@ -34,7 +34,7 @@ import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; -public class HashedSession extends AbstractSession +public class HashedSession extends MemSession { private static final Logger LOG = Log.getLogger(HashedSession.class); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java index 348c9ca547..da6f0a7955 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java @@ -88,7 +88,7 @@ public class JDBCSessionManager extends AbstractSessionManager * * Session instance. */ - public class Session extends AbstractSession + public class Session extends MemSession { private static final long serialVersionUID = 5208464051134226143L; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/MemSession.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/MemSession.java new file mode 100644 index 0000000000..72dbea8fa8 --- /dev/null +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/MemSession.java @@ -0,0 +1,146 @@ +// +// ======================================================================== +// Copyright (c) 1995-2014 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 java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; + + +/** + * MemSession + * + * A session whose data is kept in memory + */ +public class MemSession extends AbstractSession +{ + + private final Map<String,Object> _attributes=new HashMap<String, Object>(); + + protected MemSession(AbstractSessionManager abstractSessionManager, HttpServletRequest request) + { + super(abstractSessionManager, request); + } + + public MemSession(AbstractSessionManager abstractSessionManager, long created, long accessed, String clusterId) + { + super(abstractSessionManager, created, accessed, clusterId); + } + + + /* ------------------------------------------------------------- */ + @Override + public Map<String,Object> getAttributeMap() + { + return _attributes; + } + + + /* ------------------------------------------------------------ */ + @Override + public int getAttributes() + { + synchronized (this) + { + checkValid(); + return _attributes.size(); + } + } + + /* ------------------------------------------------------------ */ + @SuppressWarnings({ "unchecked" }) + @Override + public Enumeration<String> doGetAttributeNames() + { + List<String> names=_attributes==null?Collections.EMPTY_LIST:new ArrayList<String>(_attributes.keySet()); + return Collections.enumeration(names); + } + + + /* ------------------------------------------------------------ */ + @Override + public Set<String> getNames() + { + synchronized (this) + { + return new HashSet<String>(_attributes.keySet()); + } + } + + + /* ------------------------------------------------------------- */ + @Override + public void clearAttributes() + { + while (_attributes!=null && _attributes.size()>0) + { + ArrayList<String> keys; + synchronized(this) + { + keys=new ArrayList<String>(_attributes.keySet()); + } + + Iterator<String> iter=keys.iterator(); + while (iter.hasNext()) + { + String key=(String)iter.next(); + + Object value; + synchronized(this) + { + value=doPutOrRemove(key,null); + } + unbindValue(key,value); + + ((AbstractSessionManager)getSessionManager()).doSessionAttributeListeners(this,key,value,null); + } + } + if (_attributes!=null) + _attributes.clear(); + } + + /* ------------------------------------------------------------ */ + public void addAttributes(Map<String,Object> map) + { + _attributes.putAll(map); + } + + /* ------------------------------------------------------------ */ + @Override + public Object doPutOrRemove(String name, Object value) + { + return value==null?_attributes.remove(name):_attributes.put(name,value); + } + + /* ------------------------------------------------------------ */ + @Override + public Object doGet(String name) + { + return _attributes.get(name); + } + +} diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/session/SessionCookieTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/session/SessionCookieTest.java index 94e92ead7e..8f3813ba84 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/session/SessionCookieTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/session/SessionCookieTest.java @@ -21,6 +21,10 @@ package org.eclipse.jetty.server.session; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import java.util.Enumeration; +import java.util.Map; +import java.util.Set; + import javax.servlet.SessionCookieConfig; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; @@ -50,6 +54,96 @@ public class SessionCookieTest super(abstractSessionManager, created, accessed, clusterId); } + /** + * @see javax.servlet.http.HttpSession#getAttribute(java.lang.String) + */ + @Override + public Object getAttribute(String name) + { + return null; + } + + /** + * @see javax.servlet.http.HttpSession#getAttributeNames() + */ + @Override + public Enumeration<String> getAttributeNames() + { + return null; + } + + /** + * @see javax.servlet.http.HttpSession#getValueNames() + */ + @Override + public String[] getValueNames() + { + return null; + } + + /** + * @see org.eclipse.jetty.server.session.AbstractSession#getAttributeMap() + */ + @Override + public Map<String, Object> getAttributeMap() + { + return null; + } + + /** + * @see org.eclipse.jetty.server.session.AbstractSession#getAttributes() + */ + @Override + public int getAttributes() + { + return 0; + } + + /** + * @see org.eclipse.jetty.server.session.AbstractSession#getNames() + */ + @Override + public Set<String> getNames() + { + return null; + } + + /** + * @see org.eclipse.jetty.server.session.AbstractSession#clearAttributes() + */ + @Override + public void clearAttributes() + { + + } + + /** + * @see org.eclipse.jetty.server.session.AbstractSession#doPutOrRemove(java.lang.String, java.lang.Object) + */ + @Override + public Object doPutOrRemove(String name, Object value) + { + return null; + } + + /** + * @see org.eclipse.jetty.server.session.AbstractSession#doGet(java.lang.String) + */ + @Override + public Object doGet(String name) + { + return null; + } + + /** + * @see org.eclipse.jetty.server.session.AbstractSession#doGetAttributeNames() + */ + @Override + public Enumeration<String> doGetAttributeNames() + { + return null; + } + } public class MockSessionIdManager extends AbstractSessionIdManager diff --git a/tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/LightLoadTest.java b/tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/ScatterGunLoadTest.java index 097066399f..bcb581659a 100644 --- a/tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/LightLoadTest.java +++ b/tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/ScatterGunLoadTest.java @@ -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) diff --git a/tests/test-sessions/test-infinispan-sessions/pom.xml b/tests/test-sessions/test-infinispan-sessions/pom.xml index c94a6e18ab..d39696dac5 100644 --- a/tests/test-sessions/test-infinispan-sessions/pom.xml +++ b/tests/test-sessions/test-infinispan-sessions/pom.xml @@ -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> diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/InfinispanTestSessionServer.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/InfinispanTestSessionServer.java index 6cb5db399f..c6b21229a5 100644 --- a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/InfinispanTestSessionServer.java +++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/InfinispanTestSessionServer.java @@ -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(); } diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/InvalidationSessionTest.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/InvalidationSessionTest.java index 44123a590d..10afc28def 100644 --- a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/InvalidationSessionTest.java +++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/InvalidationSessionTest.java @@ -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; -// } -// }; } diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/SameNodeLoadTest.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/SameNodeLoadTest.java new file mode 100644 index 0000000000..44a9c1785c --- /dev/null +++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/SameNodeLoadTest.java @@ -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(); + } + +} diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteClientCrossContextSessionTest.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteClientCrossContextSessionTest.java new file mode 100644 index 0000000000..c7fe124e9c --- /dev/null +++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteClientCrossContextSessionTest.java @@ -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(); + } + +} diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteImmortalSessionTest.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteImmortalSessionTest.java new file mode 100644 index 0000000000..3654fe02a8 --- /dev/null +++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteImmortalSessionTest.java @@ -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(); + } + + +} diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteInfinispanTestSupport.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteInfinispanTestSupport.java new file mode 100644 index 0000000000..a936e20a4a --- /dev/null +++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteInfinispanTestSupport.java @@ -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 + { + + } +} diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteInvalidationSessionTest.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteInvalidationSessionTest.java new file mode 100644 index 0000000000..95841c6d5e --- /dev/null +++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteInvalidationSessionTest.java @@ -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) + { + } + } + +} diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteLastAccessTimeTest.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteLastAccessTimeTest.java new file mode 100644 index 0000000000..e4e82fa99a --- /dev/null +++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteLastAccessTimeTest.java @@ -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(); + } + + +} diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteLocalSessionScavengingTest.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteLocalSessionScavengingTest.java new file mode 100644 index 0000000000..1881ab7bb7 --- /dev/null +++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteLocalSessionScavengingTest.java @@ -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()); + } + +} diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteNewSessionTest.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteNewSessionTest.java new file mode 100644 index 0000000000..d46d64b895 --- /dev/null +++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteNewSessionTest.java @@ -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(); + } + + +} diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteReentrantRequestSessionTest.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteReentrantRequestSessionTest.java new file mode 100644 index 0000000000..fedb5b9e3d --- /dev/null +++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteReentrantRequestSessionTest.java @@ -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(); + } + + +} diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteRemoveSessionTest.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteRemoveSessionTest.java new file mode 100644 index 0000000000..26ce9ce3d7 --- /dev/null +++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteRemoveSessionTest.java @@ -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(); + } + +} diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteSameNodeLoadTest.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteSameNodeLoadTest.java new file mode 100644 index 0000000000..ea98f0f8b6 --- /dev/null +++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteSameNodeLoadTest.java @@ -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(); + } + +} diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteSessionExpiryTest.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteSessionExpiryTest.java new file mode 100644 index 0000000000..b328a902dd --- /dev/null +++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteSessionExpiryTest.java @@ -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. + } +} diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteSessionInvalidateAndCreateTest.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteSessionInvalidateAndCreateTest.java new file mode 100644 index 0000000000..581354edf8 --- /dev/null +++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteSessionInvalidateAndCreateTest.java @@ -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(); + } + + + +} diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteSessionMigrationTest.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteSessionMigrationTest.java new file mode 100644 index 0000000000..ded67c582f --- /dev/null +++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteSessionMigrationTest.java @@ -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(); + } + + +} diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteSessionRenewTest.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteSessionRenewTest.java new file mode 100644 index 0000000000..f39fcb2ed5 --- /dev/null +++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/remote/RemoteSessionRenewTest.java @@ -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(); + } + + +} diff --git a/tests/test-sessions/test-mongodb-sessions/src/test/java/org/eclipse/jetty/nosql/mongodb/LightLoadTest.java b/tests/test-sessions/test-mongodb-sessions/src/test/java/org/eclipse/jetty/nosql/mongodb/ScatterGunLoadTest.java index af3dfacb7b..a171700de8 100644 --- a/tests/test-sessions/test-mongodb-sessions/src/test/java/org/eclipse/jetty/nosql/mongodb/LightLoadTest.java +++ b/tests/test-sessions/test-mongodb-sessions/src/test/java/org/eclipse/jetty/nosql/mongodb/ScatterGunLoadTest.java @@ -18,15 +18,15 @@ 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.Ignore; import org.junit.Test; /** - * LightLoadTest + * ScatterGunLoadTest */ -public class LightLoadTest extends AbstractLightLoadTest +public class ScatterGunLoadTest extends AbstractScatterGunLoadTest { public AbstractTestServer createServer(int port) diff --git a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSameNodeLoadTest.java b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSameNodeLoadTest.java new file mode 100644 index 0000000000..999858fb5b --- /dev/null +++ b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSameNodeLoadTest.java @@ -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(); + } + } + } +} diff --git a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractLightLoadTest.java b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractScatterGunLoadTest.java index 56df9033dd..dee180d9e0 100644 --- a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractLightLoadTest.java +++ b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractScatterGunLoadTest.java @@ -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().getStringField( "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 ); diff --git a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractStopSessionManagerPreserveSessionTest.java b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractStopSessionManagerPreserveSessionTest.java index 41247daf67..b856533a63 100644 --- a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractStopSessionManagerPreserveSessionTest.java +++ b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractStopSessionManagerPreserveSessionTest.java @@ -36,6 +36,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; |