User: jules_gosnell
Date: 02/01/12 02:57:45
Modified: jetty/src/main/org/jboss/jetty
DistributedSessionManager.java JBossLogSink.java
JBossWebApplicationContext.java
Log:
disable DistributedSessionmanager, temporarily, whilst I do some more work on it.
Revision Changes Path
1.4 +910 -203
contrib/jetty/src/main/org/jboss/jetty/DistributedSessionManager.java
Index: DistributedSessionManager.java
===================================================================
RCS file:
/cvsroot/jboss/contrib/jetty/src/main/org/jboss/jetty/DistributedSessionManager.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- DistributedSessionManager.java 2002/01/06 23:54:16 1.3
+++ DistributedSessionManager.java 2002/01/12 10:57:45 1.4
@@ -5,25 +5,33 @@
* See terms of license at gnu.org.
*/
-// $Id: DistributedSessionManager.java,v 1.3 2002/01/06 23:54:16 jules_gosnell Exp $
+// $Id: DistributedSessionManager.java,v 1.4 2002/01/12 10:57:45 jules_gosnell Exp $
// TODO
-// 1. abstract out ID allocation and move into DistributedStore
-// 2. keep all state in HttpSessionState objects
-// 3. keep all HttpSessionState instances in DistributedStore
-// 4. we need to know when the data is dirty - will DAOs do this for us ?
-// 5. we need a handler to flush dirty state to the DistributedStore after each
request
-// 6. choice of DistributedStore and frequency of flushing should be parameterisable
-// 7. remember whether attributes were properly passivated
+// keep all state in HttpSessionState objects
+// keep all HttpSessionState instances in Store
+// rename a few things
+// test....
+// release !!!!
+
package org.jboss.jetty;
+//----------------------------------------
+
import java.rmi.RemoteException;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Enumeration;
import java.util.EventListener;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Map;
import javax.ejb.CreateException;
import javax.ejb.FinderException;
import javax.ejb.ObjectNotFoundException;
@@ -31,20 +39,26 @@
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;
+import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
-import javax.servlet.http.HttpSessionListener;
import javax.servlet.http.HttpSessionActivationListener;
+import javax.servlet.http.HttpSessionAttributeListener;
+import javax.servlet.http.HttpSessionBindingEvent;
+import javax.servlet.http.HttpSessionBindingEvent;
+import javax.servlet.http.HttpSessionBindingListener;
+import javax.servlet.http.HttpSessionContext;
import javax.servlet.http.HttpSessionEvent;
+import javax.servlet.http.HttpSessionListener;
import org.jboss.jetty.interfaces.CoarseHttpSession;
-import org.jboss.jetty.interfaces.CoarseHttpSessionHome;
import org.jboss.jetty.interfaces.CoarseHttpSessionData;
+import org.jboss.jetty.interfaces.CoarseHttpSessionHome;
import org.jboss.logging.Logger;
import org.mortbay.jetty.servlet.ServletHandler;
+import org.mortbay.jetty.servlet.SessionContext;
import org.mortbay.util.LifeCycle;
//----------------------------------------
-
/**
* An abstraction of a manager for the distributed store of HttpSessions
*
@@ -52,7 +66,7 @@
* @version 1.0
* @since 1.0
*/
-interface AbstractDistributedStore
+interface AbstractStore
{
public String nextId();
public AbstractHttpSessionData make();
@@ -68,10 +82,10 @@
* @author <a href="mailto:jules_gosnell@@yahoo.com">Jules Gosnell</a>
* @version 1.0
* @since 1.0
- * @see AbstractDistributedStore
+ * @see AbstractStore
*/
class EJBDistributedStore
- implements AbstractDistributedStore
+ implements AbstractStore
{
Logger _log = Logger.getLogger(getClass().getName());
InitialContext _jndiContext;
@@ -152,294 +166,987 @@
catch (CreateException e)
{}
}
-
- // dummy implementation
- static int _nextId=0;
+ final Object _idLock=new Object();
+ long _nextId=0;
public synchronized String
nextId()
+ {
+ long id;
+ synchronized (_idLock) {
+ id=_nextId++;
+ }
+ return ""+System.currentTimeMillis()+"-"+id;
+ }
+}
+
+//------------------------------------------------------------------------------
+
+interface AbstractScavenger
+{
+ public void register(AbstractScavenged session, long timeRemaining);
+ public void reregister(AbstractScavenged session, long timeRemaining);
+ public void deregister(AbstractScavenged session);
+
+ public void start();
+ public void stop();
+}
+
+interface AbstractScavenged
+{
+ public long getTimeRemaining(long now);
+}
+
+//------------------------------------------------------------------------------
+
+class LocalHttpSessionScavenger
+ implements AbstractScavenger
+{
+ long _smallestRemainingTime;
+
+ // called by HttpSession[Manager]
+
+ // [(r/d)e]registering a session should not result in any calls on
+ // the session - thus contention is kept at a minimum...
+
+ List _sessions;
+
+ class Pair
+ {
+ long _timeRemaining;
+ final AbstractScavenged _session;
+
+ Pair(long timeRemaining, AbstractScavenged session)
+ {
+ _timeRemaining=timeRemaining;
+ _session=session;
+ }
+
+ void
+ update(long now)
+ {
+ _timeRemaining=_session.getTimeRemaining(now);
+ }
+
+ public int
+ compare(Object o1, Object o2)
+ {
+ return (int)(((Pair)o1)._timeRemaining-((Pair)o2)._timeRemaining);
+ }
+
+ public boolean
+ equals(Object object)
+ {
+ return ((Pair)object)._timeRemaining==_timeRemaining;
+ }
+ }
+
+ public synchronized void
+ register(AbstractScavenged session, long timeRemaining)
+ {
+ if (timeRemaining<0)
+ return; // never timeout
+
+ stop();
+
+ Pair pair=new Pair(timeRemaining, session);
+
+ update(System.currentTimeMillis()); // update all timeRemainings
+ _sessions.add(pair);
+ Collections.sort(_sessions); // sort by timeRemaining
+
+ _smallestRemainingTime=((Pair)_sessions.get(0))._timeRemaining;
+
+ start();
+ }
+
+ public synchronized void
+ reregister(AbstractScavenged session, long timeRemaining)
+ {
+ // could be optimised - but this is simpler for the moment...
+ deregister(session);
+ register(session, timeRemaining);
+ }
+
+ public synchronized void
+ deregister(AbstractScavenged session)
+ {
+ stop();
+
+ Pair p=find(session);
+ _sessions.remove(p);
+
+ update(System.currentTimeMillis()); // update all timeRemainings
+ Collections.sort(_sessions); // sort by timeRemaining
+
+ _smallestRemainingTime=((Pair)_sessions.get(0))._timeRemaining;
+
+ start();
+ }
+
+ // utils...
+
+ Pair
+ find(AbstractScavenged session)
+ {
+ Iterator i=_sessions.iterator();
+ while (i.hasNext())
+ {
+ Pair p=(Pair)i.next();
+ if (p._session==session)
+ return p;
+ }
+ return null;
+ }
+
+ void
+ update(long now)
{
- return "uid-"+_nextId++;
+ Iterator i=_sessions.iterator();
+ while (i.hasNext())
+ ((Pair)i.next()).update(now);
}
+
+ // thread
+
+ // sleep for smallest timeRemaining()
+ // wake up
+ // refresh timeRemaining() on expired sessions - removing stale ones
+ // go back to sleep
+
+ // questions - what happens if smallest timeRemaining() changes
+ // whilst thread is asleep - can I wake it...
+
+ public synchronized void
+ start()
+ {}
+
+ public synchronized void
+ stop()
+ {}
+
+ synchronized void
+ loop()
+ {
+ Pair p=(Pair)_sessions.get(0);
+
+ }
+}
+
+// Scavenging is done for us by HA - Dummy implementation - does nothing...
+class
+ DistributedHttpSessionScavenger
+ implements AbstractScavenger
+{
+ public void
+ register(AbstractScavenged session, long timeRemaining)
+ {}
+
+ public void
+ deregister(AbstractScavenged session)
+ {}
+
+ public void
+ reregister(AbstractScavenged session, long timeRemaining)
+ {}
+
+
+ public void
+ start()
+ {}
+
+ public void
+ stop()
+ {}
}
/* --------------------------------------------------------------------- */
/**
*
- * @version $Id: DistributedSessionManager.java,v 1.3 2002/01/06 23:54:16
jules_gosnell Exp $
+ * @version $Id: DistributedSessionManager.java,v 1.4 2002/01/12 10:57:45
jules_gosnell Exp $
* @author [EMAIL PROTECTED]
*/
+
public class DistributedSessionManager
- extends org.mortbay.jetty.servlet.HashSessionManager
+ implements org.mortbay.jetty.servlet.SessionManager
{
- Logger _log;
- JBossWebApplicationContext _context;
- static AbstractDistributedStore _manager=new EJBDistributedStore(); // hardwired
for the moment - TODO
+ static AbstractStore _store =new
EJBDistributedStore(); // hardwired for the moment - TODO
+ static AbstractScavenger _scavenger =new
LocalHttpSessionScavenger(); // breaks confinement
+
+ final Logger _log;
+ final JBossWebApplicationContext _context;
+ final ServletHandler _handler;
+ final ArrayList _sessionListeners =new ArrayList();
+ final ArrayList _sessionAttributeListeners =new ArrayList();
+ final Map _sessions =new HashMap();
+ final boolean _isDistributed =true;
+ volatile boolean _isStarted =false; // TODO
+ volatile int _dftMaxIdleSecs =-1; // negative
means never timeout...
+ //----------------------------------------
+
DistributedSessionManager(JBossWebApplicationContext context)
{
- super(context.getServletHandler());
-
_context=context;
+ _handler=_context.getServletHandler();
_log =Logger.getLogger(getClass().getName()+"#" +_context.getContextPath());
}
+ //----------------------------------------
+ // factory
+
public HttpSession
- getHttpSession(String id)
+ newHttpSession()
+ {
+ String id=getStore().nextId();
+ DistributedSession session = new DistributedSession(this, id, _dftMaxIdleSecs);
+
+ putSession(id,session);
+ notifySessionCreated(session);
+ getScavenger().register(session, _dftMaxIdleSecs*1000);
+
+ return session;
+ }
+
+ public void
+ destroyHttpSession(DistributedSession session)
+ {
+ getScavenger().deregister(session);
+ removeSession(session);
+ notifySessionDestroyed(session);
+ session.destroy();
+ }
+
+ public void
+ passivateHttpSession(DistributedSession session)
{
+ getScavenger().deregister(session);
+ removeSession(session);
+ session.passivate();
+ }
+
+ public HttpSession
+ getHttpSession(String id) // hopefully local and distributed store will
become same
+ {
+ HttpSession s=null;
+
// 1. check local store
- HttpSession s = (HttpSession)_sessions.get(id);
+ s = getSession(id);
// 2. check distributed store
- if (s==null && _manager!=null)
- s=new DistributedSession(id, _manager.get(id));
+ if (s==null && _store!=null)
+ s=new DistributedSession(this, id, _store.get(id));
return s;
}
- // we have to create a DistributedSession instead of a standard Session
- public synchronized HttpSession
- newHttpSession()
+ // wrappers to access session table...
+
+ DistributedSession
+ getSession(String id)
{
- DistributedSession session = new DistributedSession();
- session.setMaxInactiveInterval(_dftMaxIdleSecs);
- _sessions.put(session.getId(),session);
-
- for(int i=0;i<_sessionListeners.size();i++)
- ((HttpSessionListener)_sessionListeners.get(i))
- .sessionCreated(session.getHttpSessionEvent());
- return session;
+ synchronized (_sessions) {return (DistributedSession)_sessions.get(id);}
+ }
+
+ void
+ putSession(String id, DistributedSession session)
+ {
+ synchronized (_sessions) {_sessions.put(id, session);}
}
- // {
- // HttpSession session=super.newHttpSession();
- // String id=session.getId();
- // _log.info("creating distributed data for session: "+id);
- // return session;
- // }
-
- // public synchronized void setMaxInactiveInterval(int seconds) {}
- // public synchronized void setScavangePeriod(int seconds) {}
- // public void addEventListener(EventListener listener) throws
IllegalArgumentException {}
- // public void removeEventListener(EventListener listener) {}
+ void
+ removeSession(DistributedSession session)
+ {
+ synchronized (_sessions) {_sessions.remove(session.getId());}
+ }
+ //----------------------------------------
// lifecycle
- // public boolean isStarted() {}
+ public boolean
+ isStarted()
+ {
+ return _isStarted;
+ }
public void
start()
throws Exception
{
- super.start();
+ _isStarted=true;
+ // sessions are activated lazily...
}
public void
- stop()
+ stop() // TODO
{
- // passivate all sessions...
+ _isStarted=false; // TODO
+
+ // tidy up all sessions...
ArrayList sessions = new ArrayList(_sessions.values());
for (Iterator i = sessions.iterator(); i.hasNext(); )
{
- DistributedSession session = (DistributedSession)i.next();
- session.passivate();
+ DistributedSession session=(DistributedSession)i.next();
+ if (_isDistributed)
+ passivateHttpSession(session);
+ else
+ destroyHttpSession(session);
}
+ }
+
+ //----------------------------------------
+ // SessionManager API
+
+ public synchronized
+ void setMaxInactiveInterval(int seconds) // TODO
+ {
+ _dftMaxIdleSecs = seconds;
+ }
+
+ //----------------------------------------
+
+ // extra accessors to make relationship with session more
+ // explicit...
+
+ AbstractScavenger
+ getScavenger() // TODO
+ {
+ return _scavenger;
+ }
+
+ AbstractStore
+ getStore() // TODO
+ {
+ return _store;
+ }
- // by calling clear we ensure that attributes will not be sent
- // AttributeRemoved events by super() - is this correct
- // behaviour...?
- _sessions.clear();
+ ServletHandler
+ getHandler() // TODO
+ {
+ return _handler;
+ }
- super.stop();
+ ServletContext
+ getServletContext() // TODO
+ {
+ return getHandler().getServletContext();
}
+
+ //----------------------------------------
+ // Listeners
- // scavenging
+ // Listeners are added before requests start coming in, so this code
+ // needs no synchronisation...
- // private void scavenge() {}
- //
- // class SessionScavenger
- // extends Thread
- // {
- // public void run() {}
- // SessionScavenger() {}
- // }
- //
- class DistributedSession
- extends org.mortbay.jetty.servlet.HashSessionManager.Session
+ public void
+ addEventListener(EventListener listener)
+ throws IllegalArgumentException
{
- Logger _log;
+ boolean known=false;
+ if (listener instanceof HttpSessionAttributeListener)
+ {
+ _sessionAttributeListeners.add(listener);
+ known=true;
+ }
+ if (listener instanceof HttpSessionListener)
+ {
+ _sessionListeners.add(listener);
+ known=true;
+ }
+
+ if (!known)
+ throw new IllegalArgumentException("Unknown listener "+listener);
+ }
- // lifecycle - needs init/ctor and destroy()...
+ public void
+ removeEventListener(EventListener listener)
+ {
+ if (listener instanceof HttpSessionAttributeListener)
+ _sessionAttributeListeners.remove(listener);
+ if (listener instanceof HttpSessionListener)
+ _sessionListeners.remove(listener);
+ }
- // create a completely new session
- DistributedSession()
+ void
+ notifyAttributeAdded(HttpSession session, String key, Object value)
+ {
+ if (_sessionAttributeListeners.size()>0)
{
- _id =_manager.nextId();
- _log=Logger.getLogger(getClass().getName()+"#" +getId());
- _log.info("new: "+getId());
+ HttpSessionBindingEvent event =
+ new HttpSessionBindingEvent(session, key, value);
+
+ for(int i=0;i<_sessionAttributeListeners.size();i++)
+ ((HttpSessionAttributeListener)
+ _sessionAttributeListeners.get(i)).attributeAdded(event);
+ }
+ }
- int dftMaxIdleSecs=_dftMaxIdleSecs;
+ void
+ notifyAttributeReplaced(HttpSession session, String key, Object value)
+ {
+ if (_sessionAttributeListeners.size()>0)
+ {
+ HttpSessionBindingEvent event =
+ new HttpSessionBindingEvent(session, key, value);
- if (dftMaxIdleSecs>=0)
- _maxIdleMs=dftMaxIdleSecs*1000;
+ for(int i=0;i<_sessionAttributeListeners.size();i++)
+ ((HttpSessionAttributeListener)
+ _sessionAttributeListeners.get(i)).attributeReplaced(event);
}
+ }
- // reactivate a passivated session
- DistributedSession(String id, AbstractHttpSessionData data)
+ void
+ notifyAttributeRemoved(HttpSession session, String key, Object value)
+ {
+ if (_sessionAttributeListeners.size()>0)
{
- _id=id;
- _log=Logger.getLogger(getClass().getName()+"#" +getId());
+ HttpSessionBindingEvent event =
+ new HttpSessionBindingEvent(session, key, value);
- activate(data);
+ for(int i=0;i<_sessionAttributeListeners.size();i++)
+ ((HttpSessionAttributeListener)
+ _sessionAttributeListeners.get(i)).attributeRemoved(event);
}
+ }
- protected void
- activate(AbstractHttpSessionData data)
+ void
+ notifySessionCreated(HttpSession session)
+ {
+ if (_sessionListeners.size()>0)
{
- activate(data, true);
+ HttpSessionEvent event = new HttpSessionEvent(session);
+
+ for(int i=0;i<_sessionListeners.size();i++)
+ ((HttpSessionListener)_sessionListeners.get(i))
+ .sessionCreated(event);
}
+ }
- protected synchronized void
- activate(AbstractHttpSessionData data, boolean activateAttributes)
+ void
+ notifySessionDestroyed(HttpSession session)
+ {
+ if (_sessionListeners.size()>0)
{
- if (_invalid) throw new IllegalStateException();
+ HttpSessionEvent event = new HttpSessionEvent(session);
+
+ for(int i=0;i<_sessionListeners.size();i++)
+ ((HttpSessionListener)_sessionListeners.get(i))
+ .sessionDestroyed(event);
+ }
+ }
+}
+
+/**
+ * Implementation of HttpSession with support for a DistributedStore
+ *
+ * @author <a href="mailto:jules_gosnell@@yahoo.com">Jules Gosnell</a>
+ * @version 1.0
+ * @since 1.0
+ * @see javax.servlet.http.HttpSession
+ */
+
+interface AbstractHttpSession
+ extends HttpSession, AbstractScavenged,
org.mortbay.jetty.servlet.SessionManager.Session
+{
+}
+
+class DistributedSession
+ implements AbstractHttpSession
+{
+ final DistributedSessionManager _manager;
+ final String _id;
+ final Logger _log;
+ final long _creationTime;
+ final HashMap _attributes;
+
+ final boolean _heldByValue =true; // attributes are
held in store by value, not reference
+ final boolean _accessDirties =true; // updating
_lastAccessedTime dirties session
+ final boolean _snapshotNeedsActivation =true; // they will not
have been properly passivated
+ final boolean _isDistributed =true;
+ volatile boolean _isNew =true; // risky !
+ volatile boolean _isValid =true; // risky !
+ volatile boolean _isDirty =false; // needs storing
+
+ final Object _lastAccessedTimeLock =new Object();
+ long _lastAccessedTime;
- _values = new HashMap(11);
- _values.putAll(data.getAttributes());
- _created =data.getCreationTime();
- _accessed =data.getLastAccessedTime();
- _maxIdleMs =data.getMaxInactiveInterval()*1000;
- _newSession =false;
+ final Object _maxInactiveIntervalLock =new Object();
+ int _maxInactiveInterval;
- // send activate events to listening attributes
- if (activateAttributes && _values.size()>0)
+ //----------------------------------------
+
+ // create a completely new session
+ DistributedSession(DistributedSessionManager manager,String id, int
maxInactiveInterval)
+ {
+ // final
+ _manager =manager;
+ _id =id;
+ _log =Logger.getLogger(getClass().getName()+"#" +getId());
+ _creationTime =System.currentTimeMillis();
+ _attributes =new HashMap(11);
+
+ // non-final - no need to lock in ctor
+ _lastAccessedTime =_creationTime;
+ _maxInactiveInterval =maxInactiveInterval;
+ }
+
+ // reactivate a passivated session
+ DistributedSession(DistributedSessionManager manager, String id,
AbstractHttpSessionData data)
+ {
+ // assume we own 'data' and don't have to synchronise access
+
+ // final
+ _manager =manager;
+ _id =id;
+ _log =Logger.getLogger(getClass().getName()+"#" +getId());
+ _creationTime =data.getCreationTime();
+ _attributes =new HashMap(data.getAttributes().size()); // we could
just cast...
+
+ // volatile
+ _isNew =false;
+
+ // non-final
+ _lastAccessedTime =data.getLastAccessedTime(); // no need to lock in ctor
+ _maxInactiveInterval =data.getMaxInactiveInterval(); // no need to lock in ctor
+
+ _attributes.putAll(data.getAttributes());
+
+ // send activate events to listening attributes
+ if (_snapshotNeedsActivation && _attributes.size()>0)
+ {
+ boolean warn=!data.getAttributesWerePassivated();
+ HttpSessionEvent event=new HttpSessionEvent(this);
+ Iterator i = _attributes.values().iterator();
+
+ try
{
- boolean warn=!data.getAttributesWerePassivated();
- HttpSessionEvent event=new HttpSessionEvent(this);
- Iterator i = _values.values().iterator();
+ while (i.hasNext())
+ notifySessionDidActivate(i.next(), event, warn);
+ }
+ catch (Exception e)
+ {
+ _log.error("Problem whilst activating session attributes", e);
+ }
+ }
+ _log.info("Session activated: "+getId());
+ }
- try
- {
- while (i.hasNext())
- activateValue(i.next(), event, warn);
- }
- catch (Exception e)
- {
- _log.error("Problem whilst activating session attributes", e);
- }
+ void
+ destroy()
+ {
+ synchronized (_attributes) {
+ Iterator iter = _attributes.entrySet().iterator(); // guarded
+ while (iter.hasNext())
+ {
+ Entry entry = (Entry)iter.next();
+ String key = (String)entry.getKey();
+ Object value = entry.getValue();
+
+ iter.remove();
+
+ notifyValueUnbound(key, value);
+ _manager.notifyAttributeRemoved(this, key, value);
}
- _log.info("Session activated: "+getId());
}
+ }
- protected void
- activateValue(Object attribute, HttpSessionEvent event, boolean warn)
- {
- if (attribute!=null && attribute instanceof HttpSessionActivationListener)
+ //----------------------------------------
+ // AbstractScavenged
+
+ public long
+ getTimeRemaining(long now)
+ {
+ long timeAllowed,timeTaken;
+
+ // watch out for deadlock
+ synchronized (_lastAccessedTimeLock) {
+ synchronized (_maxInactiveIntervalLock){
+ timeAllowed=_maxInactiveInterval*1000;
+ timeTaken=now-_lastAccessedTime;
+ }
+ }
+
+ return timeAllowed-timeTaken;
+ }
+
+ //----------------------------------------
+
+ // Greg's API - where does he use it ? Should be inheriting it from
+ // some interface...
+
+ public void
+ access()
+ {
+ setLastAccessedTime(System.currentTimeMillis());
+ }
+
+ public void
+ setLastAccessedTime(long time)
+ {
+ synchronized (_lastAccessedTimeLock) {
+ if (_lastAccessedTime!=time) // guarded
+ {
+ _lastAccessedTime=time; // guarded
+ if (_accessDirties) // final
+ _isDirty=true; // volatile
+ }
+ _isNew=false; // volatile
+ }
+ }
+
+ //----------------------------------------
+ // HttpSession API
+
+ public String
+ getId()
+ {
+ return _id; // final
+ }
+
+ public long
+ getCreationTime()
+ throws IllegalStateException
+ {
+ if (!isValid()) throw new IllegalStateException();
+
+ return _creationTime; // final
+ }
+
+ public long
+ getLastAccessedTime()
+ {
+ synchronized (_lastAccessedTimeLock) {return _lastAccessedTime;} // guarded
+ }
+
+ public int
+ getMaxInactiveInterval()
+ {
+ synchronized (_maxInactiveIntervalLock){return _maxInactiveInterval;} // guarded
+ }
+
+ public ServletContext
+ getServletContext()
+ {
+ return _manager.getServletContext();
+ }
+
+ /**
+ * @deprecated
+ */
+ public HttpSessionContext
+ getSessionContext() // TODO
+ {
+ return SessionContext.NULL_IMPL;
+ }
+
+ public boolean
+ isValid()
+ {
+ return _isValid; // volatile
+ }
+
+ public void
+ setMaxInactiveInterval(int secs)
+ {
+ synchronized (_maxInactiveIntervalLock) {
+ if (_maxInactiveInterval!=secs) // guarded
{
- _log.warn("WARNING: About to activate a session attribute that was not
passivated: "+attribute);
- _log.warn("WARNING: This was probably due to an uncontrolled server
shutdown.");
- ((HttpSessionActivationListener)attribute)
- .sessionDidActivate(event);
+ _maxInactiveInterval=secs; // guarded
+ _isDirty=true; // volatile
}
}
+
+ _manager.getScavenger().reregister(this, secs*1000);
+ }
+
+ public void
+ invalidate()
+ throws IllegalStateException
+ {
+ _isValid=false;
+ _manager.destroyHttpSession(this);
+ }
- protected void
- passivate()
+ public boolean
+ isNew()
+ throws IllegalStateException
+ {
+ if (!isValid()) throw new IllegalStateException();
+
+ return _isNew; // volatile
+ }
+
+ // attributes
+
+ public Object
+ getAttribute(String name)
+ throws IllegalStateException
+ {
+ if (!isValid()) throw new IllegalStateException();
+
+ synchronized (_attributes) {
+ return _attributes.get(name);
+ }
+ }
+
+ public Enumeration
+ getAttributeNames()
+ throws IllegalStateException
+ {
+ if (!isValid()) throw new IllegalStateException();
+
+ // make the Collection whilst synchronised, in case another
+ // request modifies _attributes whilst we are copying out of it.
+ synchronized (_attributes) {
+ return Collections.enumeration(_attributes.keySet());
+ }
+ }
+
+ public void
+ setAttribute(String name, Object value)
+ throws IllegalStateException
+ {
+ if (value==null)
{
- passivate(true);
+ // the javadoc says if the value is null, this is the same as
+ // remove...
+ removeAttribute(name);
+ return;
}
- // PROBLEM: If passivate is going to be called not simply as a
- // Session is shutdown, but also during the active life of a
- // session, then there is a chance that one request may be
- // adding/removing attributes whilst another thread is passivating
- // the session.
+ if (!isValid()) throw new IllegalStateException();
- // how can we prevent this, without throwing a lock around every
- // attribute access ?
+ Object oldValue;
+ synchronized (_attributes) {
+ oldValue = _attributes.put(name,value);
+ }
- // I think this is not the only place where concurrency represents
- // a threat to the attributes - theseshould all be considered in a
- // rationalisation of HttpSession implementations... - Jules
+ if (oldValue==value)
+ {
+ if (_heldByValue) // TODO
+ _isDirty=true; // the contents of value may have changed
- protected synchronized void
- passivate(boolean passivateAttributes)
+ // perhaps we should raise an 'attributeReplaced' here ?
+ // this should be configurable - TODO
+ }
+ else
{
- if (_invalid) throw new IllegalStateException();
+ _isDirty=true;
- if (_manager!=null &&
- _values.size()>0) // not sure about 2nd test - TODO
- {
- if (passivateAttributes)
- {
- // send passivate events to listening attributes...
- HttpSessionEvent event=new HttpSessionEvent(this);
- Iterator i = _values.values().iterator();
-
- try
- {
- while (i.hasNext())
- passivateValue(i.next(), event);
- }
- catch (Exception e)
- {
- _log.error("Problem whilst passivating session attributes", e);
- }
- }
+ // perhaps this test should have been 'equals()' - but I
+ // figure that would be too expensive... - TODO
- // should we bother to remove ourselves from our manager's
- // session list ?
+ Object tmp=value; // assume an attribute was added
- // create and EJB and dump data into it - in a single transaction
- AbstractHttpSessionData data=_manager.make();
- data.setId(getId());
- data.setAttributes(_values);
- data.setCreationTime(getCreationTime());
- data.setLastAccessedTime(getLastAccessedTime());
- data.setMaxInactiveInterval(getMaxInactiveInterval());
- data.setAttributesWerePassivated(passivateAttributes);
- _manager.set(getId(), data);
+ // notify the old value if necessary
+ if (oldValue!=null)
+ {
+ notifyValueUnbound(name, oldValue);
+ tmp=oldValue; // actually - an attribute was replaced
}
- _log.info("Session passivated: "+getId());
+ // notify the new value if necessary
+ notifyValueBound(name, value);
+
+ // notfy the session listeners...
+
+ // we don't need to synchronise access to this ArrayList,
+ // because all modifications to it would have been complete
+ // before the first request comes through.
+
+ if (oldValue==null)
+ _manager.notifyAttributeAdded(this, name, value);
+ else
+ _manager.notifyAttributeReplaced(this, name, oldValue);
+ }
+ }
+
+ public void
+ removeAttribute(String name)
+ throws IllegalStateException
+ {
+ if (!isValid()) throw new IllegalStateException();
+
+ Object oldValue=null;
+ synchronized (_attributes) {
+ oldValue=_attributes.remove(name);
}
- protected void
- passivateValue(Object attribute, HttpSessionEvent event)
+ if (oldValue!=null)
{
- if (attribute!=null && attribute instanceof HttpSessionActivationListener)
- ((HttpSessionActivationListener)attribute)
- .sessionWillPassivate(event);
- }
-
- // void destroy() {}
- // HttpSessionEvent getHttpSessionEvent() {}
- // public void access() {}
- // public boolean isValid() {}
- // public ServletContext getServletContext() {}
- // public String getId() throws IllegalStateException {}
- // public long getCreationTime() throws IllegalStateException {}
- // public long getLastAccessedTime() throws IllegalStateException {}
- // public int getMaxInactiveInterval() {}
- // public HttpSessionContext getSessionContext() throws
IllegalStateException {}
- // public void setMaxInactiveInterval(int secs) {}
- // public synchronized void invalidate() throws IllegalStateException {}
- // public boolean isNew() throws IllegalStateException {}
-
- // attributes
-
- // public Object getAttribute(String name) {}
- // public Enumeration getAttributeNames() {}
- // public void setAttribute(String name, Object value) {}
- // public void removeAttribute(String name) {}
-
- // public Object getValue(String name) throws IllegalStateException {}
- // public synchronized String[] getValueNames() throws
IllegalStateException {}
- // public void putValue(String name, Object value) throws
IllegalStateException {}
- // public void removeValue(String name) throws IllegalStateException {}
+ // we did remove an attribute...
+ _isDirty=true;
- // private void bindValue(String name, Object value) {}
- // private void unbindValue(String name, Object value) {}
+ // notify the old value if necessary
+ notifyValueUnbound(name, oldValue);
+ _manager.notifyAttributeRemoved(this, name, oldValue);
+ }
+ }
+ /**
+ * @deprecated
+ */
+ public Object
+ getValue(String name)
+ throws IllegalStateException
+ {
+ return getAttribute(name);
+ }
+
+ /**
+ * @deprecated
+ */
+ public String[]
+ getValueNames()
+ throws IllegalStateException
+ {
+ if (!isValid()) throw new IllegalStateException();
+
+ // ouch - this is an expensive one...
+ synchronized (_attributes) {
+ return (String[])_attributes.keySet().toArray(new String[_attributes.size()]);
+ }
}
+
+ /**
+ * @deprecated
+ */
+ public void
+ putValue(String name, Object value)
+ throws IllegalStateException
+ {
+ setAttribute(name, value);
+ }
+
+ /**
+ * @deprecated
+ */
+ public void
+ removeValue(String name)
+ throws IllegalStateException
+ {
+ removeAttribute(name);
+ }
+
+ //----------------------------------------
+ // IMPLEMENTATION
+ //----------------------------------------
+ // notification
+
+ protected void
+ notifyValueBound(String name, Object value)
+ {
+ if (value instanceof HttpSessionBindingListener)
+ ((HttpSessionBindingListener)value)
+ .valueBound(new HttpSessionBindingEvent(this,name));
+ }
+
+ protected void
+ notifyValueUnbound(String name, Object value)
+ {
+ if (value instanceof HttpSessionBindingListener)
+ ((HttpSessionBindingListener)value)
+ .valueUnbound(new HttpSessionBindingEvent(this,name));
+ }
+
+ protected void
+ notifySessionDidActivate(Object attribute, HttpSessionEvent event, boolean warn)
+ {
+ if (attribute instanceof HttpSessionActivationListener)
+ {
+ _log.warn("WARNING: About to activate a session attribute that was not
passivated: "+attribute);
+ _log.warn("WARNING: This was probably due to an uncontrolled server
shutdown.");
+ ((HttpSessionActivationListener)attribute)
+ .sessionDidActivate(event);
+ }
+ }
+
+ protected void
+ notifySessionWillPassivate(Object attribute, HttpSessionEvent event)
+ {
+ if (attribute instanceof HttpSessionActivationListener)
+ ((HttpSessionActivationListener)attribute)
+ .sessionWillPassivate(event);
+ }
+
+ //----------------------------------------
+
+ protected void
+ snapshot()
+ {
+ store(false, false);
+ }
+
+ protected void
+ passivate()
+ {
+ store(true, true);
+ }
+
+ protected synchronized void
+ store(boolean notifyAttributes, boolean shutdown)
+ {
+ // if there are no changes and this is not the final passivation
+ // during a controlled shutdown of webapp or webcontainer, we
+ // can avoid doing any work. - check - TODO.
+ if (!_isDirty && !shutdown)
+ return;
+
+ if (_manager.getStore()!=null)
+ {
+ // whilst this method is synchronized, _attributes may still be
+ // modified via their public access which only synchronise on
+ // _attributes itself. In order to cause as little contention for
+ // the _attributes map as possible I am going to try taking a copy
+ // here - otherwise we will have to hang on to a ock on it for
+ // ages.
+
+ // copy is a shallow, not deep, copy. If attributes within it
+ // are being modified by another thread whilst being
+ // passivated, it is their responsibility to synchronise so
+ // that we see a consistent state...
+
+ HashMap copy=null;
+ synchronized (_attributes) {
+ int size=_attributes.size();
+ if (size>0)
+ {
+ copy=new HashMap(size);
+ copy.putAll(_attributes);
+ }
+ }
+
+ if (notifyAttributes && copy!=null)
+ {
+ // send passivate events to listening attributes...
+ HttpSessionEvent event=new HttpSessionEvent(this);
+ Iterator i = copy.values().iterator();
+
+ try
+ {
+ while (i.hasNext())
+ notifySessionWillPassivate(i.next(), event);
+ }
+ catch (Exception e)
+ {
+ _log.error("Problem whilst passivating session attributes", e);
+ }
+ }
+
+ // create distributed store and dump data into it.
+ // how could we ensure this was a single transaction - TODO
+ AbstractHttpSessionData data=_manager.getStore().make();
+ data.setId(getId());
+ data.setAttributes(copy);
+ data.setCreationTime(getCreationTime());
+ data.setLastAccessedTime(getLastAccessedTime());
+ data.setMaxInactiveInterval(getMaxInactiveInterval());
+ data.setAttributesWerePassivated(notifyAttributes);
+ _manager.getStore().set(getId(), data);
+
+ _log.info("Session passivated: "+getId());
+ }
+ }
+
+ //----------------------------------------
}
1.9 +3 -3 contrib/jetty/src/main/org/jboss/jetty/JBossLogSink.java
Index: JBossLogSink.java
===================================================================
RCS file: /cvsroot/jboss/contrib/jetty/src/main/org/jboss/jetty/JBossLogSink.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- JBossLogSink.java 2001/12/09 06:05:49 1.8
+++ JBossLogSink.java 2002/01/12 10:57:45 1.9
@@ -5,7 +5,7 @@
* See terms of license at gnu.org.
*/
-// $Id: JBossLogSink.java,v 1.8 2001/12/09 06:05:49 user57 Exp $
+// $Id: JBossLogSink.java,v 1.9 2002/01/12 10:57:45 jules_gosnell Exp $
package org.jboss.jetty;
@@ -24,14 +24,14 @@
* This class bidges the API between Jetty and Log4J.
*
* @author <a href="mailto:">Jules Gosnell</a>
- * @version $Id: JBossLogSink.java,v 1.8 2001/12/09 06:05:49 user57 Exp $
+ * @version $Id: JBossLogSink.java,v 1.9 2002/01/12 10:57:45 jules_gosnell Exp $
* @since 1.0
* @see org.mortbay.util.LogSink
*/
public class JBossLogSink
implements LogSink
{
- Logger _log;
+ Logger _log;
boolean _started = false;
HashMap _dispatch = new HashMap();
1.13 +6 -6
contrib/jetty/src/main/org/jboss/jetty/JBossWebApplicationContext.java
Index: JBossWebApplicationContext.java
===================================================================
RCS file:
/cvsroot/jboss/contrib/jetty/src/main/org/jboss/jetty/JBossWebApplicationContext.java,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- JBossWebApplicationContext.java 2002/01/03 20:51:05 1.12
+++ JBossWebApplicationContext.java 2002/01/12 10:57:45 1.13
@@ -5,7 +5,7 @@
* See terms of license at gnu.org.
*/
-// $Id: JBossWebApplicationContext.java,v 1.12 2002/01/03 20:51:05 jules_gosnell
Exp $
+// $Id: JBossWebApplicationContext.java,v 1.13 2002/01/12 10:57:45 jules_gosnell
Exp $
// A Jetty HttpServer with the interface expected by JBoss'
// J2EEDeployer...
@@ -113,11 +113,11 @@
{
//_log.info("Don't moan : "+element);
}
- else if ("distributable".equals(element))
- {
- _distributed=true;
- getServletHandler().setSessionManager(new DistributedSessionManager(this));
- }
+ // else if ("distributable".equals(element))
+ // {
+ // _distributed=true;
+ // getServletHandler().setSessionManager(new
DistributedSessionManager(this));
+ // }
// these are handled by Jetty
else
super.initWebXmlElement(element, node);
_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/jboss-development