The attached diff will show how we can use the Event package which is a released product instead of the Cornerstone JARs for the same purpose.
We have the added benefit of knowing that we can access the Event stuff via the same mechanisms when (and if) Cocoon migrates to using Fortress instead of ECM.
It is pretty easy to use, and we are trading a requirement for four jars to a requirement for one.
Cornerstone-Thread requires Excalibur Thread and Excalibur ThreadContext Cornerstone-Scheduler requires Cornerstone-Thread.
Event (in its current incarnation) has all the functionality under one roof. It also has a vastly improved pooling mechanism, but that is another excersize completely.
If you think its a good idea, I can make the commit...
? useevent.diff ? src/java/org/apache/cocoon/ResourceListener.java Index: src/java/org/apache/cocoon/Cocoon.java =================================================================== RCS file: /home/cvs/xml-cocoon2/src/java/org/apache/cocoon/Cocoon.java,v retrieving revision 1.51 diff -u -b -r1.51 Cocoon.java --- src/java/org/apache/cocoon/Cocoon.java 31 Jan 2003 22:51:18 -0000 1.51 +++ src/java/org/apache/cocoon/Cocoon.java 26 Feb 2003 17:00:46 -0000 @@ -62,10 +62,13 @@ import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.avalon.framework.configuration.SAXConfigurationHandler; +import org.apache.avalon.framework.container.ContainerUtil; import org.apache.avalon.framework.context.Context; import org.apache.avalon.framework.context.ContextException; import org.apache.avalon.framework.context.Contextualizable; +import org.apache.avalon.framework.context.DefaultContext; import org.apache.avalon.framework.logger.AbstractLogEnabled; +import org.apache.avalon.framework.parameters.Parameters; import org.apache.avalon.framework.thread.ThreadSafe; import org.apache.cocoon.components.CocoonComponentManager; import org.apache.cocoon.components.EnvironmentStack; @@ -79,6 +82,10 @@ import org.apache.cocoon.environment.Request; import org.apache.cocoon.environment.Session; import org.apache.cocoon.util.ClassUtils; +import org.apache.excalibur.event.Queue; +import org.apache.excalibur.event.command.CommandManager; +import org.apache.excalibur.event.command.TPCThreadManager; +import org.apache.excalibur.event.command.ThreadManager; import org.apache.excalibur.instrument.InstrumentManageable; import org.apache.excalibur.instrument.InstrumentManager; import org.apache.excalibur.source.Source; @@ -185,10 +192,23 @@ */ public void contextualize(Context context) throws ContextException { if (this.context == null) { - this.context = context; + this.context = new DefaultContext(context); this.classpath = (String)context.get(Constants.CONTEXT_CLASSPATH); this.workDir = (File)context.get(Constants.CONTEXT_WORK_DIR); try { + final CommandManager cm = new CommandManager(); + final ThreadManager tm = new TPCThreadManager(); + Parameters tmParams = new Parameters(); + tmParams.setParameter("threads-per-processor", "2"); + ContainerUtil.enableLogging( tm, getLogger().getChildLogger("threadManager") ); + ContainerUtil.parameterize(tm, tmParams); + ContainerUtil.initialize(tm); + + tm.register( cm ); + + ((DefaultContext)this.context).put(Queue.ROLE, cm.getCommandSink()); + ((DefaultContext)this.context).makeReadOnly(); + // FIXME : add a configuration option for the refresh delay. // for now, hard-coded to 1 second. URLSource urlSource = new URLSource(); Index: src/java/org/apache/cocoon/components/flow/ContinuationsManagerImpl.java =================================================================== RCS file: /home/cvs/xml-cocoon2/src/java/org/apache/cocoon/components/flow/ContinuationsManagerImpl.java,v retrieving revision 1.8 diff -u -b -r1.8 ContinuationsManagerImpl.java --- src/java/org/apache/cocoon/components/flow/ContinuationsManagerImpl.java 31 Jan 2003 22:51:24 -0000 1.8 +++ src/java/org/apache/cocoon/components/flow/ContinuationsManagerImpl.java 26 Feb 2003 17:00:46 -0000 @@ -48,18 +48,20 @@ import org.apache.avalon.framework.component.Component; import org.apache.avalon.framework.configuration.Configurable; import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.ConfigurationException; +import org.apache.avalon.framework.context.Context; +import org.apache.avalon.framework.context.ContextException; +import org.apache.avalon.framework.context.Contextualizable; 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 org.apache.excalibur.event.Queue; +import org.apache.excalibur.event.Sink; +import org.apache.excalibur.event.command.RepeatedCommand; + +//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.*; @@ -74,8 +76,8 @@ */ public class ContinuationsManagerImpl extends AbstractLogEnabled - implements ContinuationsManager, Component, Configurable, - ThreadSafe, Composable, Disposable, Target { + implements ContinuationsManager, Contextualizable, Component, Configurable, + ThreadSafe { static final int CONTINUATION_ID_LENGTH = 20; static final String EXPIRE_CONTINUATIONS="expire-continuations"; @@ -84,8 +86,7 @@ protected SecureRandom random = null; protected byte[] bytes; - protected TimeScheduler m_scheduler; - protected ComponentManager m_manager; + protected Sink m_commandSink; /** * How long does a continuation exist in memory since the last @@ -125,12 +126,7 @@ 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); + m_commandSink.enqueue(new ExpireContinuations(expireConf)); } catch (Exception ex) { if (this.getLogger().isDebugEnabled()) { @@ -319,11 +315,6 @@ } } - public void compose(ComponentManager manager) throws ComponentException - { - this.m_manager = manager; - } - /** * Remove all continuations which have * already expired @@ -361,24 +352,47 @@ * * @param trigger an <code>String</code> value */ - public void targetTriggered(String trigger) + private final class ExpireContinuations implements RepeatedCommand { - // Expire continuations whenever this - // trigger goes off. - if (trigger.equals(EXPIRE_CONTINUATIONS)) { - if (this.getLogger().isDebugEnabled()) { - getLogger().debug("WK: ExpireContinuations clean up triggered:"); + private final long m_delayInterval; + private final long m_repeatInterval; + + public ExpireContinuations(Configuration config) + throws ConfigurationException + { + String type = config.getAttribute("type", "periodic"); + + // ( "periodic".equals(type) ) + m_delayInterval = config.getChild("offset").getValueAsLong(0L); + m_repeatInterval = config.getChild("period").getValueAsLong(1000L); + } + + public void execute() throws Exception + { + expireContinuations(); + } + + public int getNumberOfRepeats() + { + return -1; + } + + public long getDelayInterval() + { + return m_delayInterval; } - this.expireContinuations(); + + public long getRepeatInterval() + { + return m_repeatInterval; } } /** - * dispose of this component + * Get the command sink */ - public void dispose() { - this.m_scheduler.removeTrigger(EXPIRE_CONTINUATIONS); - this.m_manager.release((Component)m_scheduler); - this.m_manager = null; + public void contextualize(Context context) throws ContextException + { + m_commandSink = (Sink) context.get(Queue.ROLE); } }