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]