ovidiu      2003/01/08 21:40:00

  Modified:    src/java/org/apache/cocoon/components/flow
                        ContinuationsManagerImpl.java
                        ContinuationsManager.java
  Log:
  Added support for expiring continuations.
  
  Revision  Changes    Path
  1.7       +155 -16   
xml-cocoon2/src/java/org/apache/cocoon/components/flow/ContinuationsManagerImpl.java
  
  Index: ContinuationsManagerImpl.java
  ===================================================================
  RCS file: 
/home/cvs/xml-cocoon2/src/java/org/apache/cocoon/components/flow/ContinuationsManagerImpl.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- ContinuationsManagerImpl.java     6 Dec 2002 18:20:15 -0000       1.6
  +++ ContinuationsManagerImpl.java     9 Jan 2003 05:40:00 -0000       1.7
  @@ -51,6 +51,16 @@
   import org.apache.avalon.framework.logger.AbstractLogEnabled;
   import org.apache.avalon.framework.thread.ThreadSafe;
   
  +import org.apache.avalon.framework.component.ComponentManager;
  +import org.apache.avalon.framework.component.ComponentException;
  +import org.apache.avalon.framework.component.Composable;
  +
  +import org.apache.avalon.framework.activity.Disposable;
  +
  +import org.apache.avalon.cornerstone.services.scheduler.TimeScheduler;
  +import org.apache.avalon.cornerstone.services.scheduler.Target;
  +import org.apache.avalon.cornerstone.services.scheduler.TimeTriggerFactory;
  +
   import java.security.SecureRandom;
   import java.util.*;
   
  @@ -58,21 +68,28 @@
    * The default implementation of {@link ContinuationsManager}.
    *
    * @author <a href="mailto:[EMAIL PROTECTED]";>Ovidiu Predescu</a>
  + * @author <a href="mailto:[EMAIL PROTECTED]";>Michael Melhem</a>
    * @since March 19, 2002
    * @see ContinuationsManager
    */
   public class ContinuationsManagerImpl
     extends AbstractLogEnabled
  -  implements ContinuationsManager, Component, Configurable, ThreadSafe {
  +  implements ContinuationsManager, Component, Configurable, 
  +  ThreadSafe, Composable, Disposable, Target {
   
     static final int CONTINUATION_ID_LENGTH = 20;
  +  static final String EXPIRE_CONTINUATIONS="expire-continuations"; 
  +
   
     protected SecureRandom random = null;
     protected byte[] bytes;
   
  +  protected TimeScheduler m_scheduler;
  +  protected ComponentManager m_manager;
  +
     /**
      * How long does a continuation exist in memory since the last
  -   * access? The time is in seconds, and the default is 3600 (1 hour).
  +   * access? The time is in miliseconds, and the default is 1 hour.
      */
     protected int defaultTimeToLive;
   
  @@ -92,7 +109,7 @@
      * their expiration time. This is used by the background thread to
      * invalidate continuations.
      */
  -  protected SortedSet expirations = new TreeSet();
  +  protected SortedSet expirations = Collections.synchronizedSortedSet(new 
TreeSet());
   
     public ContinuationsManagerImpl()
       throws Exception
  @@ -104,7 +121,22 @@
   
     public void configure(Configuration config)
     {
  -    defaultTimeToLive = config.getAttributeAsInteger("time-to-live", 3600);
  +    defaultTimeToLive = config.getAttributeAsInteger("time-to-live", (3600 * 1000));
  +    Configuration expireConf = config.getChild("expirations-check");
  +
  +    try {
  +      m_scheduler = (TimeScheduler)this.m_manager.lookup(TimeScheduler.ROLE);
  +      TimeTriggerFactory    triggerFac = new TimeTriggerFactory();
  +
  +      m_scheduler.addTrigger(EXPIRE_CONTINUATIONS,
  +                             triggerFac.createTimeTrigger(expireConf),
  +                             this);
  +    }
  +    catch (Exception ex) {
  +      if (this.getLogger().isDebugEnabled()) {
  +        getLogger().debug("WK: Exception while configuring WKManager " + ex);
  +      }
  +    }
     }
   
     public WebContinuation createWebContinuation(Object kont,
  @@ -119,7 +151,8 @@
       if (parentKont == null)
         forrest.add(wk);
   
  -    // REVISIT: Place only the "leaf" nodes in the expirations Sorted Set.
  +    // REVISIT: This Places only the "leaf" nodes in the expirations Sorted Set.
  +    // do we really want to do this?
       if (parentKont != null) {
           if (wk.getParentContinuation().getChildren().size() < 2) {
               expirations.remove(wk.getParentContinuation());
  @@ -128,14 +161,13 @@
   
       expirations.add(wk);
   
  -    if (this.getLogger().isDebugEnabled()) {
  -      displayAllContinuations();
  -      displayExpireSet();
  -    }
  -    
       // No need to add the WebContinuation in idToWebCont as it was
       // already done during its construction.
   
  +    if (this.getLogger().isDebugEnabled()) {
  +      getLogger().debug("WK: Just Created New Continuation " + wk.getId());
  +    }
  +
       return wk;
     }
   
  @@ -155,7 +187,7 @@
     protected void _invalidate(WebContinuation wk)
     {
       if (this.getLogger().isDebugEnabled()) {
  -      getLogger().debug("WK: Expiring Continuation " + wk.getId());
  +      getLogger().debug("WK: Manual Expire of Continuation " + wk.getId());
       }
       idToWebCont.remove(wk.getId());
       expirations.remove(wk);
  @@ -169,6 +201,8 @@
   
     public WebContinuation lookupWebContinuation(String id)
     {
  +    // REVISIT: Is the folliwing check needed to avoid threading issues:
  +    // return wk only if !(wk.hasExpired) ?
       return (WebContinuation)idToWebCont.get(id);
     }
   
  @@ -211,21 +245,63 @@
       return continuationId;
     }
   
  +
  +  /**
  +   * Removes an expired leaf <code>WebContinuation</code> node
  +   * from its continuation tree, and recursively removes its
  +   * parent(s) if it they have expired and have no (other) children.
  +   * 
  +   * @param  a <code>WebContinuation</code> node 
  +   */
  +  public void removeContinuation(WebContinuation wk) {
  +    if (wk.getChildren().size() != 0) {
  +      return;
  +    }
  +
  +    // remove access to this contination
  +    idToWebCont.remove(wk.getId());
  +     
  +    WebContinuation parent = wk.getParentContinuation();
  +    if (parent == null) {
  +      forrest.remove(wk);
  +    }
  +    else {
  +      List parentKids = parent.getChildren();
  +      parentKids.remove(wk);
  +    }
  +
  +    if (this.getLogger().isDebugEnabled()) {
  +      getLogger().debug("WK: deleted this WK: " + wk.getId());
  +    }
  +
  +    // now check if parent needs to be removed.
  +    if (null != parent && parent.hasExpired()) {
  +      removeContinuation(parent);
  +    }
  +  }
  +
  +  
     /**
      * Dump to Log file the current contents of 
      * the expirations <code>SortedSet</code> 
      */
     public void displayExpireSet() {
       Iterator iter = expirations.iterator();
  -    StringBuffer wkSet = new StringBuffer("\nWK: Expire Set, size: " + 
expirations.size());
  +    StringBuffer wkSet = new StringBuffer("\nWK; Expire Set Size: "+ 
expirations.size());
       while (iter.hasNext()) {
         final WebContinuation wk = (WebContinuation)iter.next();
  -      final long lat = wk.getLastAccessTime();
  +      final long lat = wk.getLastAccessTime() + wk.getTimeToLive();
         wkSet.append("\nWK: ")
              .append(wk.getId())
  -           .append(" Last Touched [")
  -           .append(lat)
  -           .append("]");
  +           .append(" ExpireTime [");
  +
  +      if (lat <  System.currentTimeMillis()) {
  +        wkSet.append("Expired");
  +      }
  +      else {
  +        wkSet.append(lat);
  +      }
  +      wkSet.append("]");
       }
   
       getLogger().debug(wkSet.toString());
  @@ -241,5 +317,68 @@
       while (iter.hasNext()) {
         ((WebContinuation)iter.next()).display();
       }
  +  }
  + 
  +  public void compose(ComponentManager manager) throws ComponentException
  +  {
  +      this.m_manager = manager;
  +  }
  +
  +  /**
  +   * Remove all continuations which have 
  +   * already expired
  +   */
  +  public void expireContinuations() {
  +    // log state before continuations clean up
  +    if (this.getLogger().isDebugEnabled()) {
  +      getLogger().debug("WK: Forrest size: " + forrest.size());  
  +      displayAllContinuations();
  +      displayExpireSet();
  +    }
  +
  +    // clean up
  +    if (this.getLogger().isDebugEnabled()) {
  +      getLogger().debug("WK CurrentSytemTime[" + System.currentTimeMillis() + 
  +                        "]: Cleaning up expired Continuations....");
  +    }
  +    WebContinuation wk;
  +    Iterator iter = expirations.iterator();
  +    while (iter.hasNext() && ((wk=(WebContinuation)iter.next()).hasExpired())) {
  +      iter.remove();
  +      this.removeContinuation(wk);
  +    }
  +
  +    // log state after continuations clean up
  +    if (this.getLogger().isDebugEnabled()) {
  +      getLogger().debug("WK: Forrest size: " + forrest.size());  
  +      displayAllContinuations();
  +      displayExpireSet();
  +    }
  +  } 
  +
  +  /**
  +   * Handle cornerstone triggers 
  +   *
  +   * @param trigger an <code>String</code> value
  +   */
  +   public void targetTriggered(String trigger)   
  +   {
  +     // Expire continuations whenever this
  +     // trigger goes off.
  +     if (trigger.equals(EXPIRE_CONTINUATIONS)) {
  +       if (this.getLogger().isDebugEnabled()) {
  +         getLogger().debug("WK: ExpireContinuations clean up triggered:");
  +       }
  +        this.expireContinuations();
  +     }
  +   }
  +
  +  /**
  +   * dispose of this component
  +   */
  +  public void dispose() {
  +    this.m_scheduler.removeTrigger(EXPIRE_CONTINUATIONS);
  +    this.m_manager.release((Component)m_scheduler);
  +    this.m_manager = null;
     }
   }
  
  
  
  1.4       +0 -5      
xml-cocoon2/src/java/org/apache/cocoon/components/flow/ContinuationsManager.java
  
  Index: ContinuationsManager.java
  ===================================================================
  RCS file: 
/home/cvs/xml-cocoon2/src/java/org/apache/cocoon/components/flow/ContinuationsManager.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- ContinuationsManager.java 12 Aug 2002 07:50:52 -0000      1.3
  +++ ContinuationsManager.java 9 Jan 2003 05:40:00 -0000       1.4
  @@ -42,11 +42,6 @@
    (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   
  - This software  consists of voluntary contributions made  by many individuals
  - on  behalf of the Apache Software  Foundation and was  originally created by
  - Stefano Mazzocchi  <[EMAIL PROTECTED]>. For more  information on the Apache
  - Software Foundation, please see <http://www.apache.org/>.
  -
   */
   package org.apache.cocoon.components.flow;
   
  
  
  

----------------------------------------------------------------------
In case of troubles, e-mail:     [EMAIL PROTECTED]
To unsubscribe, e-mail:          [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to