Return-Path: Delivered-To: apmail-cocoon-cvs-archive@www.apache.org Received: (qmail 10229 invoked from network); 24 Mar 2004 15:19:23 -0000 Received: from daedalus.apache.org (HELO mail.apache.org) (208.185.179.12) by minotaur-2.apache.org with SMTP; 24 Mar 2004 15:19:23 -0000 Received: (qmail 57915 invoked by uid 500); 24 Mar 2004 15:19:17 -0000 Delivered-To: apmail-cocoon-cvs-archive@cocoon.apache.org Received: (qmail 57858 invoked by uid 500); 24 Mar 2004 15:19:16 -0000 Mailing-List: contact cvs-help@cocoon.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@cocoon.apache.org list-help: list-unsubscribe: list-post: Delivered-To: mailing list cvs@cocoon.apache.org Received: (qmail 57847 invoked by uid 500); 24 Mar 2004 15:19:16 -0000 Delivered-To: apmail-cocoon-2.1-cvs@apache.org Received: (qmail 57843 invoked from network); 24 Mar 2004 15:19:16 -0000 Received: from unknown (HELO minotaur.apache.org) (209.237.227.194) by daedalus.apache.org with SMTP; 24 Mar 2004 15:19:16 -0000 Received: (qmail 10175 invoked by uid 1758); 24 Mar 2004 15:19:20 -0000 Date: 24 Mar 2004 15:19:20 -0000 Message-ID: <20040324151920.10174.qmail@minotaur.apache.org> From: unico@apache.org To: cocoon-2.1-cvs@apache.org Subject: cvs commit: cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl CachedSourceResponse.java CachingSource.java TraversableCachingSource.java UpdateTarget.java X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N X-Spam-Rating: minotaur-2.apache.org 1.6.2 0/1000/N unico 2004/03/24 07:19:20 Modified: src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl CachedSourceResponse.java CachingSource.java TraversableCachingSource.java UpdateTarget.java Log: Only update cache if source is actually invalid; Don't store response if expires = 0 Add more debugging and improve documentation. Revision Changes Path 1.2 +2 -2 cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl/CachedSourceResponse.java Index: CachedSourceResponse.java =================================================================== RCS file: /home/cvs/cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl/CachedSourceResponse.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- CachedSourceResponse.java 22 Mar 2004 17:38:25 -0000 1.1 +++ CachedSourceResponse.java 24 Mar 2004 15:19:20 -0000 1.2 @@ -30,8 +30,8 @@ private byte[] m_xml; private Serializable m_extra; - public CachedSourceResponse(SourceValidity validity) { - super(validity, null); + public CachedSourceResponse(SourceValidity[] validities) { + super(validities, null); } public byte[] getBinaryResponse() { 1.9 +105 -22 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.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- CachingSource.java 23 Mar 2004 16:28:54 -0000 1.8 +++ CachingSource.java 24 Mar 2004 15:19:20 -0000 1.9 @@ -57,7 +57,7 @@ * *

Syntax for Protocol

*

- * cached:http://www.apache.org[?cocoon:cache-expires=60&cocoon:cache-name=main] + * cached:http://www.apache.org/[?cocoon:cache-expires=60&cocoon:cache-name=main] *

*

* The above examples show how the real source http://www.apache.org @@ -150,14 +150,69 @@ * Initialize the Source. */ public void initialize() throws Exception { + + boolean checkValidity = true; + if (this.expires == -1) { + if (getLogger().isDebugEnabled()) { + getLogger().debug("Using cached response if available."); + } + checkValidity = false; + } + + if (this.async && this.expires != 0) { + if (getLogger().isDebugEnabled()) { + getLogger().debug("Not invalidating cached response " + "for asynch source " + getSourceURI()); + } + checkValidity = false; + } + this.response = (CachedSourceResponse) this.cache.get(this.cacheKey); - if (this.response != null && (!this.async || expires == 0)) { - // check if the source is cached, throw it out if invalid - final SourceValidity validity = this.response.getValidityObjects()[0]; - if (expires != -1 && (expires == 0 || validity.isValid() != SourceValidity.VALID)) { + if (this.response == null) { + if (getLogger().isDebugEnabled()) { + getLogger().debug("No cached response found " + "for source " + getSourceURI()); + } + checkValidity = false; + } + + if (checkValidity) { + + final ExpiresValidity cacheValidity = (ExpiresValidity) this.response.getValidityObjects()[0]; + final SourceValidity sourceValidity = this.response.getValidityObjects()[1]; + + boolean remove = false; + if (this.expires == 0) { if (getLogger().isDebugEnabled()) { - getLogger().debug("Invalid cached response for source " + getSourceURI()); + getLogger().debug("Force invalidation of cached response" + " of source " + getSourceURI()); } + remove = true; + } + else { + boolean expired = cacheValidity.isValid() != SourceValidity.VALID; + if (expired) { + if (getLogger().isDebugEnabled()) { + getLogger().debug("Cached response of source " + + getSourceURI() + " is expired."); + } + boolean invalid = !isValid(sourceValidity, this.source); + if (invalid) { + if (getLogger().isDebugEnabled()) { + getLogger().debug("Cached response of source " + + getSourceURI() + " is invalid."); + } + remove = true; + } + else { + if (getLogger().isDebugEnabled()) { + getLogger().debug("Cached response of source " + + getSourceURI() + " is still valid."); + } + // set new expiration period + this.response.getValidityObjects()[0] = new ExpiresValidity(getExpiration()); + } + } + } + + if (remove) { this.response = null; // remove it if it no longer exists if (!exists()) { @@ -165,7 +220,7 @@ } } } - if (this.async && expires > 0) { + if (this.async && this.expires > 0) { // schedule it with the refresher this.refresher.refresh(this.cacheKey, getSourceURI(), @@ -193,14 +248,21 @@ * @param refresh whether to force refresh * @throws IOException if an the binary response could not be initialized */ - protected void initMetaResponse(boolean refresh) throws IOException { + protected void initMetaResponse() throws IOException { boolean storeResponse = false; CachedSourceResponse response = this.response; if (response == null) { - response = new CachedSourceResponse(new ExpiresValidity(getExpiration())); - storeResponse = true; + if (this.expires != 0) { + final SourceValidity cacheValidity = new ExpiresValidity(getExpiration()); + final SourceValidity sourceValidity = source.getValidity(); + response = new CachedSourceResponse(new SourceValidity[] {cacheValidity, sourceValidity}); + storeResponse = true; + } + else { + response = new CachedSourceResponse(null); + } } - if (response.getExtra() == null || refresh) { + if (response.getExtra() == null) { response.setExtra(readMeta(this.source)); this.freshMeta = true; } @@ -221,15 +283,22 @@ * @param refresh whether to force refresh * @throws IOException if an the binary response could not be initialized */ - protected void initBinaryResponse(boolean refresh) throws IOException { + protected void initBinaryResponse() throws IOException { boolean storeResponse = false; /* delay caching the response until we have a valid new one */ CachedSourceResponse response = this.response; if (response == null) { - response = new CachedSourceResponse(new ExpiresValidity(getExpiration())); - storeResponse = true; + if (this.expires != 0) { + final SourceValidity cacheValidity = new ExpiresValidity(getExpiration()); + final SourceValidity sourceValidity = source.getValidity(); + response = new CachedSourceResponse(new SourceValidity[] {cacheValidity, sourceValidity}); + storeResponse = true; + } + else { + response = new CachedSourceResponse(null); + } } - if (response.getBinaryResponse() == null || refresh) { + if (response.getBinaryResponse() == null) { response.setBinaryResponse(readBinaryResponse(this.source)); if (!this.freshMeta) { /* always refresh meta in this case */ @@ -260,8 +329,15 @@ /* delay caching the response until we have a valid new one */ CachedSourceResponse response = this.response; if (response == null) { - response = new CachedSourceResponse(new ExpiresValidity(getExpiration())); - storeResponse = true; + if (this.expires != 0) { + final SourceValidity cacheValidity = new ExpiresValidity(getExpiration()); + final SourceValidity sourceValidity = source.getValidity(); + response = new CachedSourceResponse(new SourceValidity[] {cacheValidity, sourceValidity}); + storeResponse = true; + } + else { + response = new CachedSourceResponse(null); + } } if (response.getXMLResponse() == null || refresh) { byte[] binary = response.getBinaryResponse(); @@ -306,7 +382,7 @@ */ public long getLastModified() { try { - initMetaResponse(false); + initMetaResponse(); } catch (IOException io) { return 0; } @@ -320,7 +396,7 @@ */ public String getMimeType() { try { - initMetaResponse(false); + initMetaResponse(); } catch (IOException io) { return null; } @@ -332,7 +408,7 @@ */ public InputStream getInputStream() throws IOException, SourceException { try { - initBinaryResponse(false); + initBinaryResponse(); } catch (IOException se) { throw new SourceException("Failure getting input stream", se); } @@ -425,7 +501,7 @@ protected long getExpiration() { return this.expires * 1000; } - + /** * Read XML content from source. * @@ -537,6 +613,13 @@ meta.setMimeType(source.getMimeType()); return meta; + } + + protected static boolean isValid(SourceValidity validity, Source source) { + if (validity == null) return false; + return validity.isValid() == SourceValidity.VALID || + (validity.isValid() == SourceValidity.UNKNOWN && + validity.isValid(source.getValidity()) == SourceValidity.VALID); } /** 1.4 +5 -5 cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl/TraversableCachingSource.java Index: TraversableCachingSource.java =================================================================== RCS file: /home/cvs/cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl/TraversableCachingSource.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- TraversableCachingSource.java 23 Mar 2004 16:28:54 -0000 1.3 +++ TraversableCachingSource.java 24 Mar 2004 15:19:20 -0000 1.4 @@ -47,7 +47,7 @@ public String getName() { try { - initMetaResponse(false); + initMetaResponse(); } catch (IOException e) { if (getLogger().isDebugEnabled()) { @@ -62,7 +62,7 @@ public boolean isCollection() { try { - initMetaResponse(false); + initMetaResponse(); } catch (IOException e) { if (getLogger().isDebugEnabled()) { @@ -78,7 +78,7 @@ Source child; try { - initMetaResponse(false); + initMetaResponse(); child = this.tsource.getChild(name); } catch (SourceException e) { @@ -98,7 +98,7 @@ public Collection getChildren() throws SourceException { try { - initMetaResponse(false); + initMetaResponse(); } catch (SourceException e) { throw e; @@ -132,7 +132,7 @@ Source parent; try { - initMetaResponse(false); + initMetaResponse(); parent = this.tsource.getParent(); } catch (SourceException e) { 1.5 +33 -14 cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl/UpdateTarget.java Index: UpdateTarget.java =================================================================== RCS file: /home/cvs/cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl/UpdateTarget.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- UpdateTarget.java 23 Mar 2004 16:28:54 -0000 1.4 +++ UpdateTarget.java 24 Mar 2004 15:19:20 -0000 1.5 @@ -27,6 +27,7 @@ import org.apache.cocoon.components.cron.ConfigurableCronJob; import org.apache.excalibur.source.Source; import org.apache.excalibur.source.SourceResolver; +import org.apache.excalibur.source.SourceValidity; import org.apache.excalibur.source.impl.validity.ExpiresValidity; /** @@ -57,24 +58,23 @@ * * * @since 2.1.1 - * @author Carsten Ziegeler * @version CVS $Id$ */ public class UpdateTarget extends AbstractLogEnabled implements Serviceable, ConfigurableCronJob { // service dependencies - protected ServiceManager manager; - protected SourceResolver resolver; + private ServiceManager manager; + private SourceResolver resolver; // configuration - protected String uri; - protected String cacheRole; - protected int expires; - protected boolean failSafe; + private String uri; + private String cacheRole; + private int expires; + private boolean failSafe; // the key under which to store the CachedResponse in the Cache - protected SimpleCacheKey cacheKey; + private SimpleCacheKey cacheKey; // ---------------------------------------------------- Lifecycle @@ -109,8 +109,8 @@ */ public void execute(String name) { if (this.uri != null) { - if (this.getLogger().isInfoEnabled()) { - this.getLogger().info("Refreshing " + this.uri); + if (this.getLogger().isDebugEnabled()) { + this.getLogger().debug("Refreshing " + this.uri); } Source source = null; @@ -120,7 +120,18 @@ cache = (Cache) this.manager.lookup(this.cacheRole); source = this.resolver.resolveURI(this.uri); + // check if the source is really expired and invalid CachedSourceResponse response = (CachedSourceResponse) cache.get(this.cacheKey); + if (response != null) { + final SourceValidity sourceValidity = response.getValidityObjects()[1]; + if (CachingSource.isValid(sourceValidity, source)) { + if (getLogger().isDebugEnabled()) { + getLogger().debug("Cached response is still valid " + "for source " + this.uri + "."); + } + response.getValidityObjects()[0] = new ExpiresValidity(this.expires * 1000); + return; + } + } if (source.exists()) { @@ -133,7 +144,9 @@ } // create a new cached response - response = new CachedSourceResponse(new ExpiresValidity(this.expires * 1000)); + final ExpiresValidity cacheValidity = new ExpiresValidity(this.expires * 1000); + final SourceValidity sourceValidity = source.getValidity(); + response = new CachedSourceResponse(new SourceValidity[] {cacheValidity, sourceValidity}); // only create objects that have previously been used if (binary != null) { @@ -146,17 +159,23 @@ } // meta info is always set response.setExtra(CachingSource.readMeta(source)); - cache.store(this.cacheKey, response); } else if (response != null) { + // FIXME: There is a potential problem when the parent + // source has not yet been updated thus listing this + // source still as one of its children. We'll have to remove + // the parent's cached response here too. + if (getLogger().isDebugEnabled()) { + getLogger().debug("Source " + this.uri + " no longer exists." + " Throwing out cached response."); + } cache.remove(this.cacheKey); } } catch (Exception e) { if (!failSafe) { // the content expires, so remove it cache.remove(cacheKey); - getLogger().warn("Exception during updating " + this.uri, e); + getLogger().warn("Exception during updating of source " + this.uri, e); } else { getLogger().warn("Updating of source " + this.uri + " failed. " +