You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by ha...@apache.org on 2004/03/06 22:00:39 UTC

cvs commit: cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl CachingSource.java AsyncCachingSource.java RefresherImpl.java

haul        2004/03/06 13:00:39

  Modified:    src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl
                        CachingSource.java AsyncCachingSource.java
                        RefresherImpl.java
  Log:
  Add log statements for swallowed exceptions
  Extract some methods in RefresherImpl
  Extract some constants in RefresherImpl
  (IOW just moving things around)
  
  Revision  Changes    Path
  1.6       +18 -4     cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl/CachingSource.java
  
  Index: CachingSource.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl/CachingSource.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- CachingSource.java	5 Mar 2004 10:07:25 -0000	1.5
  +++ CachingSource.java	6 Mar 2004 21:00:39 -0000	1.6
  @@ -109,7 +109,10 @@
       protected Source source;
       
       /**
  -     * Construct a new object
  +     * Construct a new object. Syntax for cached source:
  +     * "<code>cache-protocol</code>" + "<code>://</code>" + "<code>seconds</code>"
  +     * + "<code>@</code>" + "<code>wrapped-URL</code>".
  +     * 
        */
       public CachingSource( String location,
                             Map    parameters) 
  @@ -313,6 +316,11 @@
               SourceValidity expiresValidity = this.cachedResponse.getValidityObjects()[0];
               if ( this.expires != -1
                    && (this.expires == 0 || expiresValidity.isValid() != SourceValidity.VALID)) {
  +                // TODO: according to SourceValidity.isValid() validity should be checked against 
  +                //       new validity object if UNKNOWN is returned
  +                //       maybe this is too expensive?
  +                
  +                // remove from cache if not valid anymore
                   this.cache.remove( this.streamKey );
                   this.cachedResponse = null;
               }
  @@ -332,7 +340,7 @@
       /** 
        * Initialize the cache
        */
  -    protected void initCache(boolean alternative)
  +    protected boolean initCache(boolean alternative)
       throws IOException, SAXException {
           this.initSource();
           boolean storeResponse = false;
  @@ -356,10 +364,16 @@
           if ( storeResponse && this.expires > 0 ) {
               try {
                   this.cache.store(this.streamKey, this.cachedResponse);
  +                if (this.getLogger().isDebugEnabled()) {
  +                    this.getLogger().debug("Storing response for "+this.streamKey.getKey());
  +                }
               } catch (ProcessingException ignore) {
  -                // we ignore this
  +                if (this.getLogger().isDebugEnabled()) {
  +                    this.getLogger().debug("Ignoring exception when storing response.", ignore) ;
  +                }
               }
           }
  +        return storeResponse;
       }
       
       /**
  
  
  
  1.5       +11 -1     cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl/AsyncCachingSource.java
  
  Index: AsyncCachingSource.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl/AsyncCachingSource.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- AsyncCachingSource.java	5 Mar 2004 10:07:25 -0000	1.4
  +++ AsyncCachingSource.java	6 Mar 2004 21:00:39 -0000	1.5
  @@ -91,9 +91,19 @@
               try {
                   this.cache.store(this.streamKey, this.cachedResponse);
               } catch (ProcessingException ignore) {
  +                if (this.getLogger().isDebugEnabled()) {
  +					this.getLogger().debug("Storing cached response, ignoring exception:",ignore);
  +				}
               }
               
               response = this.cachedResponse.getResponse();
  +            if (this.getLogger().isDebugEnabled()) {
  +                this.getLogger().debug("Using fresh response for "+this.streamKey.getKey());
  +            }
  +        } else {
  +            if (this.getLogger().isDebugEnabled()) {
  +                this.getLogger().debug("Using cached response for "+this.streamKey.getKey());
  +            }
           }
           return new ByteArrayInputStream(response);            
       }
  
  
  
  1.5       +137 -70   cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl/RefresherImpl.java
  
  Index: RefresherImpl.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl/RefresherImpl.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- RefresherImpl.java	5 Mar 2004 10:07:25 -0000	1.4
  +++ RefresherImpl.java	6 Mar 2004 21:00:39 -0000	1.5
  @@ -29,6 +29,7 @@
   import org.apache.avalon.framework.CascadingException;
   import org.apache.avalon.framework.activity.Disposable;
   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.logger.AbstractLogEnabled;
   import org.apache.avalon.framework.parameters.ParameterException;
  @@ -61,6 +62,20 @@
       extends AbstractLogEnabled
       implements Parameterizable, ThreadSafe, Refresher, Serviceable, Disposable, CronJob {
       
  +    private static final String PARAM_CACHE_ROLE = "cache-role";
  +    private static final String PARAM_CACHE_EXPIRES = "cache-expires";
  +    private static final String PARAM_SCHEDULER_TARGET = "scheduler-target";
  +    private static final String PARAM_WRITE_INTERVAL = "write-interval";
  +    private static final String PARAM_WRITE_TARGET = "write-target";
  +
  +    private static final String CACHE_KEY = "cache-key";
  +	
  +    private static final String TAGNAME_TARGET = "target";
  +	private static final String ATTR_CACHE = "cache";
  +	private static final String ATTR_EXPIRES = "expires";
  +    private static final String ATTR_KEY = "key";
  +	private static final String ATTR_URI = "uri";
  +
       protected String schedulerTarget;
       
       protected ServiceManager manager;
  @@ -80,63 +95,108 @@
        * @see org.apache.avalon.framework.parameters.Parameterizable#parameterize(org.apache.avalon.framework.parameters.Parameters)
        */
       public void parameterize(Parameters parameters) throws ParameterException {
  -        this.schedulerTarget = parameters.getParameter("scheduler-target");
  -        int writeInterval = parameters.getParameterAsInteger("write-interval", 0);
  +        this.schedulerTarget = parameters.getParameter(PARAM_SCHEDULER_TARGET);
  +        int writeInterval = parameters.getParameterAsInteger(PARAM_WRITE_INTERVAL, 0);
           if ( writeInterval > 0) {
  -            try {
  -                this.writeSource = this.resolver.resolveURI(parameters.getParameter("write-source"));
  -            } catch (IOException ioe) {
  -                throw new ParameterException("Error getting write-source.", ioe);
  -            }
  -            if (!(this.writeSource instanceof ModifiableSource)) {
  -                throw new ParameterException("Write-source is not modifiable.");
  -            }
  -            SAXConfigurationHandler b = new SAXConfigurationHandler();
  -            try {
  -                SourceUtil.toSAX(this.manager, this.writeSource, this.writeSource.getMimeType(), b);
  -            } catch (Exception ignore) {
  -                this.getLogger().warn("Unable to read configuration from " + this.writeSource.getURI());
  -            }
  -            final Configuration conf = b.getConfiguration();
  -            if ( conf != null ) {
  -                final Configuration[] childs = conf.getChildren("target");
  -                if ( childs != null ) {
  -                    for(int i=0; i < childs.length; i++) {
  -                        try {
  -                            String uri = URLDecoder.decode(childs[i].getAttribute("uri"));
  -                            int expires = childs[i].getAttributeAsInteger("expires");
  -                            String cache = childs[i].getAttribute("cache");                        
  -                            String key = URLDecoder.decode(childs[i].getAttribute("key"));
  -                            SimpleCacheKey cacheKey = new SimpleCacheKey(key, false);
  -                            TargetConfiguration tc = new TargetConfiguration(cacheKey, uri, expires, cache);
  -                            this.entries.put(key, tc);
  -                            final String name = cacheKey.getKey();
  -                            
  -                            this.scheduler.addPeriodicJob(name, this.schedulerTarget,
  -                                                  expires,
  -                                                  true,
  -                                                  tc.parameters,
  -                                                  tc.map);
  -
  -                        } catch (CascadingException ignore) {
  -                        }
  -                    
  -                    }
  -                }
  -            }
  -            try {
  -                this.scheduler.addPeriodicJob(this.getClass().getName(), 
  -                                      parameters.getParameter("write-target"),
  -                                      (long)writeInterval * 1000,
  -                                      true,
  -                                      null,
  -                                      null);
  -            } catch (CascadingException ignore) {
  -            }
  +            this.setupRefreshJobSource(parameters);
  +            final Configuration conf = this.readRefreshJobConfiguration();
  +            this.setupRefreshJobs(conf);
  +            this.registerSelfWithScheduler(parameters, writeInterval);
           }
       }
   
  -    /* (non-Javadoc)
  +    /**
  +	 * @param parameters
  +	 * @param writeInterval
  +	 */
  +	private void registerSelfWithScheduler(Parameters parameters, int writeInterval) {
  +		try {
  +		    this.scheduler.addPeriodicJob(this.getClass().getName(), 
  +		                          parameters.getParameter(PARAM_WRITE_TARGET),
  +		                          (long)writeInterval * 1000,
  +		                          true,
  +		                          null,
  +		                          null);
  +		} catch (CascadingException ignore) {
  +            if (this.getLogger().isDebugEnabled()) {
  +				this.getLogger().debug("Registering self with scheduler, ignoring exception:", ignore);
  +			}
  +		}
  +	}
  +
  +	/**
  +	 * @param conf
  +	 */
  +	private void setupRefreshJobs(final Configuration conf) {
  +		if ( conf != null ) {
  +		    final Configuration[] childs = conf.getChildren(TAGNAME_TARGET);
  +		    if ( childs != null ) {
  +		        for(int i=0; i < childs.length; i++) {
  +		            try {
  +		                this.setupSingleRefreshJob(childs[i]);
  +		            } catch (CascadingException ignore) {
  +		                if (this.getLogger().isDebugEnabled()) {
  +							this.getLogger().debug("Setting up refresh jobs, ignoring exception:", ignore);
  +						}
  +		            }
  +		        }
  +		    }
  +		}
  +	}
  +
  +	/**
  +	 * @param childs
  +	 * @param i
  +	 * @throws ConfigurationException
  +	 * @throws CascadingException
  +	 */
  +	private void setupSingleRefreshJob(final Configuration conf) throws ConfigurationException, CascadingException {
  +		String uri = URLDecoder.decode(conf.getAttribute(ATTR_URI));
  +		int expires = conf.getAttributeAsInteger(ATTR_EXPIRES);
  +		String cache = conf.getAttribute(ATTR_CACHE);                        
  +		String key = URLDecoder.decode(conf.getAttribute(ATTR_KEY));
  +		SimpleCacheKey cacheKey = new SimpleCacheKey(key, false);
  +		TargetConfiguration tc = new TargetConfiguration(cacheKey, uri, expires, cache);
  +		this.entries.put(key, tc);
  +		final String name = cacheKey.getKey();
  +		
  +		this.scheduler.addPeriodicJob(name, this.schedulerTarget,
  +		                      expires,
  +		                      true,
  +		                      tc.parameters,
  +		                      tc.map);
  +	}
  +
  +	/**
  +	 * @return
  +	 */
  +	private Configuration readRefreshJobConfiguration() {
  +		SAXConfigurationHandler b = new SAXConfigurationHandler();
  +		try {
  +		    SourceUtil.toSAX(this.manager, this.writeSource, this.writeSource.getMimeType(), b);
  +		} catch (Exception ignore) {
  +		    this.getLogger().warn("Unable to read configuration from " + this.writeSource.getURI());
  +		}
  +		final Configuration conf = b.getConfiguration();
  +		return conf;
  +	}
  +
  +	/**
  +	 * @param parameters
  +	 * @throws ParameterException
  +	 */
  +	private void setupRefreshJobSource(Parameters parameters) throws ParameterException {
  +		try {
  +		    this.writeSource = this.resolver.resolveURI(parameters.getParameter("write-source"));
  +		} catch (IOException ioe) {
  +		    throw new ParameterException("Error getting write-source.", ioe);
  +		}
  +		if (!(this.writeSource instanceof ModifiableSource)) {
  +		    throw new ParameterException("Write-source is not modifiable.");
  +		}
  +	}
  +
  +	/* (non-Javadoc)
        * @see org.apache.cocoon.components.source.impl.Refresher#refresh(org.apache.cocoon.caching.SimpleCacheKey, java.lang.String, long, java.lang.String)
        */
       public void refresh(SimpleCacheKey cacheKey,
  @@ -227,17 +287,7 @@
                   writer.write("<targets>\n");
                   final Iterator iter = this.entries.values().iterator();
                   while ( iter.hasNext() ) {
  -                    
  -                    final TargetConfiguration c = (TargetConfiguration)iter.next();
  -                    writer.write("<target uri=\"");
  -                    writer.write(URLEncoder.encode(c.parameters.getParameter("uri", "")));
  -                    writer.write("\" expires=\"");
  -                    writer.write(c.parameters.getParameter("cache-expires", "0"));
  -                    writer.write("\" cache=\"");
  -                    writer.write(c.parameters.getParameter("cache-role", ""));
  -                    writer.write("\" key=\"");
  -                    writer.write(URLEncoder.encode(((SimpleCacheKey)c.map.get("cache-key")).getKey()));
  -                    writer.write("\"/>\n"); 
  +                    this.writeRefreshJobConfiguration(writer, (TargetConfiguration) iter.next()); 
                   }
                   writer.write("</targets>\n");
                   writer.flush();
  @@ -248,7 +298,24 @@
           }
       }
   
  -    class TargetConfiguration {
  +    /**
  +	 * @param writer
  +	 * @param iter
  +	 * @throws IOException
  +	 */
  +	private void writeRefreshJobConfiguration(Writer writer, final TargetConfiguration c) throws IOException {
  +		writer.write("<"+TAGNAME_TARGET+" "+ATTR_URI+"=\"");
  +		writer.write(URLEncoder.encode(c.parameters.getParameter(ATTR_URI, "")));
  +		writer.write("\" "+ATTR_EXPIRES+"=\"");
  +		writer.write(c.parameters.getParameter(PARAM_CACHE_EXPIRES, "0"));
  +		writer.write("\" "+ATTR_CACHE+"=\"");
  +		writer.write(c.parameters.getParameter(PARAM_CACHE_ROLE, ""));
  +		writer.write("\" "+ATTR_KEY+"=\"");
  +		writer.write(URLEncoder.encode(((SimpleCacheKey)c.map.get(CACHE_KEY)).getKey()));
  +		writer.write("\"/>\n");
  +	}
  +
  +	class TargetConfiguration {
           
           public Parameters parameters;
           
  @@ -262,13 +329,13 @@
               this.map = new HashMap();
   
               this.update(uri, expires, cacheRole);
  -            this.map.put("cache-key", cacheKey);
  +            this.map.put(CACHE_KEY, cacheKey);
           }
           
           public void update(String uri, long expires, String cacheRole) {
  -            this.parameters.setParameter("uri",uri);
  -            this.parameters.setParameter("cache-role", cacheRole);
  -            this.parameters.setParameter("cache-expires", String.valueOf(expires));
  +            this.parameters.setParameter(ATTR_URI,uri);
  +            this.parameters.setParameter(PARAM_CACHE_ROLE, cacheRole);
  +            this.parameters.setParameter(PARAM_CACHE_EXPIRES, String.valueOf(expires));
           }
           
       }
  
  
  

Re: cvs commit: cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl CachingSource.java AsyncCachingSource.java RefresherImpl.java

Posted by Christian Haul <ha...@informatik.tu-darmstadt.de>.
Unico Hommes wrote:
> 
> Christian Haul wrote:
> 
>> Unico Hommes wrote:

>> However, I'm not quite sure if this is the way to go. I'm currently
>> thinking of intercepting and wrapping sources at the selector level.
>>
>> With the current setup, we need to add the configuration to the URL
>> in all places it is used. By wrapping a protocol with a cached version
>> we wouldn't be able to distinguish eg access to a local services from
>> a remote service (in terms of network hops).
>>
>> So what if we were to intercept those sources at the selector based
>> on eg wildcard matching on URL? This would be "cross-cutting" and it
>> would be easy to provide more complex caching parameters for a wrapped
>> source.
>>
> 
> For the life of me I can't figure out what exactly it is you are saying. 
> Care to elaborate? Perhaps give an example?

Say, you would like to access you webdav always asynchronously as well 
as remote webservices. Local services, however, should be accessed
directly.

Solution 1 is to go through your sitemap and wrap your URLs accordingly.
Solution 2 is to say, for "http://*.localsite.com/*" use plain http, for
everything else use "acached://600@{0}" (or a better syntax that doesn't
encode everything into the URL).

To achieve this, one could replace the component selector holding the
source factories and always return a wrapper. Only when the real URL
is available (eg absolutize() or get() is called), the decision is made
which factory to use.

>> Esp. with a event based cache, how would you specify the event to 
>> invalidate the source from within the URL?
>>
> 
> I was thinking to use querystring parameter to pass it in and default to 
> the wrapped Source's system id (getURI). This is what I am using right 
> now for WebDAV sources and it works perfectly.

Ah well. I have Documentum DQL as URL and would need to have something
else for a key, like the document ID or a folder name.

>>
>>> By the way I think you are the one to ask Christian: I noticed there 
>>> is no scheduler.addPeriodicJob(.. Object job, ..) method. Is there a 
>>> reason for this or can I add one? So that the Refresher can add 
>>> itself and its update targets directly.
>>
>>
>>
>> Although I'd like to help I haven't touched the Cron block before. But 
>> speaking of addPeriodicJob() it would be great to have a way to say 
>> "do this right now AND repeat every 10 minutes". The current 
>> implementation
>> provides only for a "do this every 10 minutes and start in 10 minutes 
>> for the first time". IIUC this limitation does not stem from the Qartz 
>> API but from what the Cocoon JobScheduler provides.
>>
> 
> Yeah it does. There already exists a plain addJob method with the 
> signature I am talking about.

But AFAIK there's either "do now", "do at cron spec" (like mondays at 
12am), or "do every x minutes starting in x minutes". Of course, what
I would like to have is just a combination of addPeriodicJob() and 
fireJob() ....

>> Speaking of random ideas around the cached source, it might be nice to
>> provide a URL for the content when it's not yet available. But then this
>> might add too much features to a supposed to be simple concept.
>>
> 
> I was also thinking of an implementation of the update mechanism where 
> objects don't get invalidated if they cannot be regenerated (eg. due to 
> WebDAV server offline, network problems, etc.) but get rescheduled instead.

Makes sense.

	Chris.

Re: cvs commit: cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl CachingSource.java AsyncCachingSource.java RefresherImpl.java

Posted by Unico Hommes <un...@hippo.nl>.

Christian Haul wrote:
> Unico Hommes wrote:
> 
>> :-( I had so many changes on my local FS for these classes. I totally 
>> reworked their implemenatations. Not your fault though. I should have 
>> worked more incrementally and checked them in sooner. I'll find a way 
>> to merge it all.
> 
> 
> Well, I wouldn't mind if you just dump my changes. As the message said,
> I was just moving things around for documentation purposes, really.
> (Some prefer comments, some prefer speaking names for rather small methods)
> 
>> Just to give you an idea of what I am doing here is a quick summary:
>>
>> Basically I want to move all communication with the Cache into the 
>> Refresher. I am renaming RefresherImpl to DelayRefresher and adding a 
>> Refresher implementation that is externally triggered by events. I am 
>> changing the location protocol string as discussed earlier. Probably 
>> can merge CachingSource and AsynchCachingSource.
> 
> 
> This sound really cool and actually, I was planning for something 
> similar :-)
> 
> However, I'm not quite sure if this is the way to go. I'm currently
> thinking of intercepting and wrapping sources at the selector level.
> 
> With the current setup, we need to add the configuration to the URL
> in all places it is used. By wrapping a protocol with a cached version
> we wouldn't be able to distinguish eg access to a local services from
> a remote service (in terms of network hops).
> 
> So what if we were to intercept those sources at the selector based
> on eg wildcard matching on URL? This would be "cross-cutting" and it
> would be easy to provide more complex caching parameters for a wrapped
> source.
> 

For the life of me I can't figure out what exactly it is you are saying. 
Care to elaborate? Perhaps give an example?

> Esp. with a event based cache, how would you specify the event to 
> invalidate the source from within the URL?
> 

I was thinking to use querystring parameter to pass it in and default to 
the wrapped Source's system id (getURI). This is what I am using right 
now for WebDAV sources and it works perfectly.

>> I also changed the way DelayRefresher persists its entry 
>> configurations to instead of doing a manual xml serialization of the 
>> data just dump the  whole Map of entries into a persistent store.
> 
> 
> Cool.
> 
>> By the way I think you are the one to ask Christian: I noticed there 
>> is no scheduler.addPeriodicJob(.. Object job, ..) method. Is there a 
>> reason for this or can I add one? So that the Refresher can add itself 
>> and its update targets directly.
> 
> 
> Although I'd like to help I haven't touched the Cron block before. But 
> speaking of addPeriodicJob() it would be great to have a way to say "do 
> this right now AND repeat every 10 minutes". The current implementation
> provides only for a "do this every 10 minutes and start in 10 minutes 
> for the first time". IIUC this limitation does not stem from the Qartz 
> API but from what the Cocoon JobScheduler provides.
> 

Yeah it does. There already exists a plain addJob method with the 
signature I am talking about.

> Speaking of random ideas around the cached source, it might be nice to
> provide a URL for the content when it's not yet available. But then this
> might add too much features to a supposed to be simple concept.
> 

I was also thinking of an implementation of the update mechanism where 
objects don't get invalidated if they cannot be regenerated (eg. due to 
WebDAV server offline, network problems, etc.) but get rescheduled instead.

> Sorry for messing your stuff up. I'm very excited to see what you have 
> done.
> 

No problem. I expect to check in some of my work later this week.

--
Unico


Re: cvs commit: cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl CachingSource.java AsyncCachingSource.java RefresherImpl.java

Posted by Christian Haul <ha...@informatik.tu-darmstadt.de>.
Unico Hommes wrote:
> :-( I had so many changes on my local FS for these classes. I totally 
> reworked their implemenatations. Not your fault though. I should have 
> worked more incrementally and checked them in sooner. I'll find a way to 
> merge it all.

Well, I wouldn't mind if you just dump my changes. As the message said,
I was just moving things around for documentation purposes, really.
(Some prefer comments, some prefer speaking names for rather small methods)

> Just to give you an idea of what I am doing here is a quick summary:
> 
> Basically I want to move all communication with the Cache into the 
> Refresher. I am renaming RefresherImpl to DelayRefresher and adding a 
> Refresher implementation that is externally triggered by events. I am 
> changing the location protocol string as discussed earlier. Probably can 
> merge CachingSource and AsynchCachingSource.

This sound really cool and actually, I was planning for something 
similar :-)

However, I'm not quite sure if this is the way to go. I'm currently
thinking of intercepting and wrapping sources at the selector level.

With the current setup, we need to add the configuration to the URL
in all places it is used. By wrapping a protocol with a cached version
we wouldn't be able to distinguish eg access to a local services from
a remote service (in terms of network hops).

So what if we were to intercept those sources at the selector based
on eg wildcard matching on URL? This would be "cross-cutting" and it
would be easy to provide more complex caching parameters for a wrapped
source.

Esp. with a event based cache, how would you specify the event to 
invalidate the source from within the URL?

> I also changed the way DelayRefresher persists its entry configurations 
> to instead of doing a manual xml serialization of the data just dump the 
>  whole Map of entries into a persistent store.

Cool.

> By the way I think you are the one to ask Christian: I noticed there is 
> no scheduler.addPeriodicJob(.. Object job, ..) method. Is there a reason 
> for this or can I add one? So that the Refresher can add itself and its 
> update targets directly.

Although I'd like to help I haven't touched the Cron block before. But 
speaking of addPeriodicJob() it would be great to have a way to say "do 
this right now AND repeat every 10 minutes". The current implementation
provides only for a "do this every 10 minutes and start in 10 minutes 
for the first time". IIUC this limitation does not stem from the Qartz 
API but from what the Cocoon JobScheduler provides.

Speaking of random ideas around the cached source, it might be nice to
provide a URL for the content when it's not yet available. But then this
might add too much features to a supposed to be simple concept.

Sorry for messing your stuff up. I'm very excited to see what you have done.

	Chris.

(who's currently too busy to read this list every day :-(



Re: cvs commit: cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/sou rce/implCachingSource.java AsyncCachingSource.java RefresherImpl.java

Posted by Unico Hommes <un...@hippo.nl>.
Hi Antonio :-)

Integration of JCS as an excalibur Store service is going pretty well. 
Solved most of the remaining issues I think.

There's one quite fundamental issue on the JCS side that still needs to 
be addressed though. There seems to be a problem flushing the memory 
cache onto disk during shutdown. This effectively means that a lot of 
stuff won't be recoverable between server runs. Obviously this MUST be 
fixed before considering JCS as a caching system for cocoon, let alone 
the default one.

Going by what the guy that helped me on the JCS users mailinglist said 
this is a known issue but no big deal. They just need to put in a simple 
fix.

--
Unico


Antonio Gallardo wrote:
> Unico:
> 
> Is near the day, when we will have JCS as the default Cache system in Cocoon?
> 
> I cannot wait. :-)
> 
> Best Regards,
> 
> Antonio Gallardo

Re: cvs commit: cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/sou rce/implCachingSource.java AsyncCachingSource.java RefresherImpl.java

Posted by Antonio Gallardo <ag...@agssa.net>.
Unico:

Is near the day, when we will have JCS as the default Cache system in Cocoon?

I cannot wait. :-)

Best Regards,

Antonio Gallardo

Re: cvs commit: cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl CachingSource.java AsyncCachingSource.java RefresherImpl.java

Posted by Unico Hommes <un...@hippo.nl>.

haul@apache.org wrote:

> haul        2004/03/06 13:00:39
> 
>   Modified:    src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl
>                         CachingSource.java AsyncCachingSource.java
>                         RefresherImpl.java
>   Log:
>   Add log statements for swallowed exceptions
>   Extract some methods in RefresherImpl
>   Extract some constants in RefresherImpl
>   (IOW just moving things around)
>   
>   Revision  Changes    Path
>   1.6       +18 -4     cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl/CachingSource.java
>   
>

:-( I had so many changes on my local FS for these classes. I totally 
reworked their implemenatations. Not your fault though. I should have 
worked more incrementally and checked them in sooner. I'll find a way to 
merge it all.

Just to give you an idea of what I am doing here is a quick summary:

Basically I want to move all communication with the Cache into the 
Refresher. I am renaming RefresherImpl to DelayRefresher and adding a 
Refresher implementation that is externally triggered by events. I am 
changing the location protocol string as discussed earlier. Probably can 
merge CachingSource and AsynchCachingSource.

I also changed the way DelayRefresher persists its entry configurations 
to instead of doing a manual xml serialization of the data just dump the 
  whole Map of entries into a persistent store.

By the way I think you are the one to ask Christian: I noticed there is 
no scheduler.addPeriodicJob(.. Object job, ..) method. Is there a reason 
for this or can I add one? So that the Refresher can add itself and its 
update targets directly.

Cheers,
Unico