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

Reply via email to