roller-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From agillil...@apache.org
Subject svn commit: r369957 - in /incubator/roller/trunk/src/org/roller/presentation: cache/CacheManager.java cache/LazyExpiringCacheEntry.java filters/FeedCacheFilter.java filters/IfModifiedFeedCacheFilter.java filters/WeblogPageCacheFilter.java
Date Tue, 17 Jan 2006 23:25:14 GMT
Author: agilliland
Date: Tue Jan 17 15:25:02 2006
New Revision: 369957

URL: http://svn.apache.org/viewcvs?rev=369957&view=rev
Log:
switching to lazy (passive) cache expiration strategy.  this eliminates the overhead of iterating
through the list of cache keys to find the right ones purge and gives us a better chance at
supporting Memcached, which doesn't provide a way to get the list of cache keys.


Added:
    incubator/roller/trunk/src/org/roller/presentation/cache/LazyExpiringCacheEntry.java
Modified:
    incubator/roller/trunk/src/org/roller/presentation/cache/CacheManager.java
    incubator/roller/trunk/src/org/roller/presentation/filters/FeedCacheFilter.java
    incubator/roller/trunk/src/org/roller/presentation/filters/IfModifiedFeedCacheFilter.java
    incubator/roller/trunk/src/org/roller/presentation/filters/WeblogPageCacheFilter.java

Modified: incubator/roller/trunk/src/org/roller/presentation/cache/CacheManager.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/roller/presentation/cache/CacheManager.java?rev=369957&r1=369956&r2=369957&view=diff
==============================================================================
--- incubator/roller/trunk/src/org/roller/presentation/cache/CacheManager.java (original)
+++ incubator/roller/trunk/src/org/roller/presentation/cache/CacheManager.java Tue Jan 17
15:25:02 2006
@@ -6,8 +6,10 @@
 
 package org.roller.presentation.cache;
 
+import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
@@ -50,6 +52,9 @@
     // a reference to the cache factory in use
     private static CacheFactory mCacheFactory = null;
     
+    // maintain a cache of the last expired time for each weblog
+    private static Hashtable lastExpiredCache = null;
+    
     // a list of all cache handlers who have obtained a cache
     private static Set cacheHandlers = new HashSet();
     
@@ -82,6 +87,9 @@
         mLogger.info("Cache Manager Initialized.");
         mLogger.info("Default cache factory = "+mCacheFactory.getClass().getName());
         
+        // setup our cache for expiration dates
+        lastExpiredCache = new Hashtable();
+        
         // finally, add custom handlers
         String customHandlers = RollerConfig.getProperty("cache.customHandlers");
         if(customHandlers != null && customHandlers.trim().length() > 0) {
@@ -190,6 +198,8 @@
         
         mLogger.debug("invalidating entry = "+entry.getAnchor());
         
+        lastExpiredCache.put(entry.getWebsite().getHandle(), new Date());
+        
         Iterator handlers = cacheHandlers.iterator();
         while(handlers.hasNext()) {
             ((CacheHandler) handlers.next()).invalidate(entry);
@@ -201,6 +211,8 @@
         
         mLogger.debug("invalidating website = "+website.getHandle());
         
+        lastExpiredCache.put(website.getHandle(), new Date());
+        
         Iterator handlers = cacheHandlers.iterator();
         while(handlers.hasNext()) {
             ((CacheHandler) handlers.next()).invalidate(website);
@@ -212,6 +224,8 @@
         
         mLogger.debug("invalidating bookmark = "+bookmark.getId());
         
+        lastExpiredCache.put(bookmark.getWebsite().getHandle(), new Date());
+        
         Iterator handlers = cacheHandlers.iterator();
         while(handlers.hasNext()) {
             ((CacheHandler) handlers.next()).invalidate(bookmark);
@@ -223,6 +237,8 @@
         
         mLogger.debug("invalidating folder = "+folder.getId());
         
+        lastExpiredCache.put(folder.getWebsite().getHandle(), new Date());
+        
         Iterator handlers = cacheHandlers.iterator();
         while(handlers.hasNext()) {
             ((CacheHandler) handlers.next()).invalidate(folder);
@@ -234,6 +250,8 @@
         
         mLogger.debug("invalidating comment = "+comment.getId());
         
+        lastExpiredCache.put(comment.getWeblogEntry().getWebsite().getHandle(), new Date());
+        
         Iterator handlers = cacheHandlers.iterator();
         while(handlers.hasNext()) {
             ((CacheHandler) handlers.next()).invalidate(comment);
@@ -245,6 +263,8 @@
         
         mLogger.debug("invalidating referer = "+referer.getId());
         
+        lastExpiredCache.put(referer.getWebsite().getHandle(), new Date());
+        
         Iterator handlers = cacheHandlers.iterator();
         while(handlers.hasNext()) {
             ((CacheHandler) handlers.next()).invalidate(referer);
@@ -267,6 +287,8 @@
         
         mLogger.debug("invalidating category = "+category.getId());
         
+        lastExpiredCache.put(category.getWebsite().getHandle(), new Date());
+        
         Iterator handlers = cacheHandlers.iterator();
         while(handlers.hasNext()) {
             ((CacheHandler) handlers.next()).invalidate(category);
@@ -278,6 +300,8 @@
         
         mLogger.debug("invalidating template = "+template.getId());
         
+        lastExpiredCache.put(template.getWebsite().getHandle(), new Date());
+        
         Iterator handlers = cacheHandlers.iterator();
         while(handlers.hasNext()) {
             ((CacheHandler) handlers.next()).invalidate(template);
@@ -290,6 +314,14 @@
      */
     public static void clear() {
         
+        // update all expired dates
+        Iterator it = lastExpiredCache.keySet().iterator();
+        String key = null;
+        while(it.hasNext()) {
+            key = (String) it.next();
+            lastExpiredCache.put(key, new Date());
+        }
+        
         // loop through all handlers and trigger a clear
         CacheHandler handler = null;
         Iterator handlers = cacheHandlers.iterator();
@@ -306,6 +338,14 @@
      */
     public static void clear(String handlerClass) {
         
+        // update all expired dates
+        Iterator it = lastExpiredCache.keySet().iterator();
+        String key = null;
+        while(it.hasNext()) {
+            key = (String) it.next();
+            lastExpiredCache.put(key, new Date());
+        }
+        
         // loop through all handlers to find the one we want
         CacheHandler handler = null;
         Iterator handlers = cacheHandlers.iterator();
@@ -316,6 +356,14 @@
                 handler.clear();
             }
         }
+    }
+    
+    
+    /**
+     * Get the date of the last time the specified weblog was invalidated.
+     */
+    public static Date getLastExpiredDate(String weblogHandle) {
+        return (Date) lastExpiredCache.get(weblogHandle);
     }
     
     

Added: incubator/roller/trunk/src/org/roller/presentation/cache/LazyExpiringCacheEntry.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/roller/presentation/cache/LazyExpiringCacheEntry.java?rev=369957&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/roller/presentation/cache/LazyExpiringCacheEntry.java (added)
+++ incubator/roller/trunk/src/org/roller/presentation/cache/LazyExpiringCacheEntry.java Tue
Jan 17 15:25:02 2006
@@ -0,0 +1,73 @@
+/*
+ * LazyExpiringCacheEntry.java
+ *
+ * Created on January 17, 2006, 10:14 AM
+ */
+
+package org.roller.presentation.cache;
+
+import java.util.Date;
+
+/**
+ * A cache entry that is meant to expire in a lazy fashion.
+ *
+ * The way to use this class is to wrap the object you want to cache in an
+ * instance of this class and store that in your cache.  Then when you want
+ * to retrieve this entry you must input a last-expired time which can be
+ * compared against the time this entry was cached to determine if the cached
+ * entry is "fresh".  If the object is not fresh then we don't return it.
+ *
+ * This essentially allows us to track when an object is cached and then before
+ * we can retrieve that cached object we must compare it with it's last known
+ * invalidation time to make sure it hasn't expired.  This is useful because
+ * instead of actively purging lots of cached objects from the cache at 
+ * invalidation time, we can now be lazy and just invalidate them when we
+ * actually try to retrieve the cached object.
+ *
+ * This is useful for Roller because we will no longer have to iterate through
+ * the list of cached objects and inspect the keys to figure out what items to
+ * invalidate.  Instead we can just sit back and let the items be invalidated as
+ * we try to use them.
+ *
+ * @author Allen Gilliland
+ */
+public class LazyExpiringCacheEntry {
+    
+    private Object value = null;
+    private long timeCached = -1;
+    
+    
+    public LazyExpiringCacheEntry(Object item) {
+        this.value = item;
+        this.timeCached = System.currentTimeMillis();
+    }
+    
+    
+    /**
+     * Retrieve the value of this cache entry if it is still "fresh".
+     *
+     * If the value has expired then we return null.
+     */
+    public Object getValue(long lastInvalidated) {
+        if(this.isInvalid(lastInvalidated)) {
+            return null;
+        } else {
+            return this.value;
+        }
+    }
+    
+    
+    /**
+     * Determine if this cache entry has expired.
+     */
+    public boolean isInvalid(long lastInvalidated) {
+        
+        return (this.timeCached < lastInvalidated);
+    }
+
+    
+    public long getTimeCached() {
+        return timeCached;
+    }
+    
+}

Modified: incubator/roller/trunk/src/org/roller/presentation/filters/FeedCacheFilter.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/roller/presentation/filters/FeedCacheFilter.java?rev=369957&r1=369956&r2=369957&view=diff
==============================================================================
--- incubator/roller/trunk/src/org/roller/presentation/filters/FeedCacheFilter.java (original)
+++ incubator/roller/trunk/src/org/roller/presentation/filters/FeedCacheFilter.java Tue Jan
17 15:25:02 2006
@@ -38,6 +38,7 @@
 import org.roller.presentation.cache.Cache;
 import org.roller.presentation.cache.CacheHandler;
 import org.roller.presentation.cache.CacheManager;
+import org.roller.presentation.cache.LazyExpiringCacheEntry;
 import org.roller.presentation.util.CacheHttpServletResponseWrapper;
 import org.roller.presentation.util.ResponseContent;
 
@@ -91,10 +92,27 @@
             return;
         }
         
-        String key = "feedCache:"+this.generateKey(feedRequest);
+        String key = this.CACHE_ID+":"+this.generateKey(feedRequest);
         
         try {
-            ResponseContent respContent = (ResponseContent) this.mCache.get(key);
+            ResponseContent respContent = null;
+            
+            // we need the last expiration time for the given weblog
+            long lastExpiration = 0;
+            Date lastExpirationDate =
+                    (Date) CacheManager.getLastExpiredDate(feedRequest.getWeblogHandle());
+            if(lastExpirationDate != null)
+                lastExpiration = lastExpirationDate.getTime();
+            
+            LazyExpiringCacheEntry entry =
+                    (LazyExpiringCacheEntry) this.mCache.get(key);
+            if(entry != null) {
+                respContent = (ResponseContent) entry.getValue(lastExpiration);
+                
+                if(respContent == null)
+                    mLogger.debug("HIT-INVALID "+key);
+            }
+                
             if (respContent == null) {
                 
                 mLogger.debug("MISS "+key);
@@ -111,7 +129,7 @@
                 if (request.getAttribute("DisplayException") == null) {
                     ResponseContent rc = cacheResponse.getContent();
                     
-                    this.mCache.put(key, rc);
+                    this.mCache.put(key, new LazyExpiringCacheEntry(rc));
                 } else {
                     // it is expected that whoever caught this display exception
                     // is the one who reported it to the logs
@@ -212,6 +230,7 @@
         //   - the planet feed
         //   - all weblog feeds
         
+        /*
         Set removeSet = new HashSet();
         
         // TODO: it would be nice to be able to do this without iterating 
@@ -235,6 +254,7 @@
         
         this.mCache.remove(removeSet);
         this.purges += removeSet.size();
+        */
     }
     
     

Modified: incubator/roller/trunk/src/org/roller/presentation/filters/IfModifiedFeedCacheFilter.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/roller/presentation/filters/IfModifiedFeedCacheFilter.java?rev=369957&r1=369956&r2=369957&view=diff
==============================================================================
--- incubator/roller/trunk/src/org/roller/presentation/filters/IfModifiedFeedCacheFilter.java
(original)
+++ incubator/roller/trunk/src/org/roller/presentation/filters/IfModifiedFeedCacheFilter.java
Tue Jan 17 15:25:02 2006
@@ -44,12 +44,13 @@
 import org.roller.presentation.cache.Cache;
 import org.roller.presentation.cache.CacheHandler;
 import org.roller.presentation.cache.CacheManager;
+import org.roller.presentation.cache.LazyExpiringCacheEntry;
 
 
 /**
  * A filter used for caching last modified dates.
  *
- * This may be applied to /rss/*, /atom/*, /flavor/*, and /planetrss
+ * This may be applied to /rss/*, /atom/*, /flavor/*
  * 
  * @web.filter name="IfModifiedFeedCacheFilter"
  *
@@ -92,11 +93,25 @@
             return;
         }
         
-        String key = "ifmod:"+this.generateKey(feedRequest);
+        String key = this.CACHE_ID+":"+this.generateKey(feedRequest);
         
         Date updateTime = null;
         try {
-            updateTime = (Date) this.mCache.get(key);
+            // we need the last expiration time for the given weblog
+            long lastExpiration = 0;
+            Date lastExpirationDate =
+                    (Date) CacheManager.getLastExpiredDate(feedRequest.getWeblogHandle());
+            if(lastExpirationDate != null)
+                lastExpiration = lastExpirationDate.getTime();
+            
+            LazyExpiringCacheEntry entry =
+                    (LazyExpiringCacheEntry) this.mCache.get(key);
+            if(entry != null) {
+                updateTime = (Date) entry.getValue(lastExpiration);
+                
+                if(updateTime == null)
+                    mLogger.debug("HIT-INVALID "+key);
+            }
             
             if (updateTime == null) {
                 mLogger.debug("MISS "+key);
@@ -110,7 +125,7 @@
                             umgr.getWebsiteByHandle(feedRequest.getWeblogHandle()),
                             feedRequest.getWeblogCategory());
                     
-                    this.mCache.put(key, updateTime);
+                    this.mCache.put(key, new LazyExpiringCacheEntry(updateTime));
                 }
                 
             } else {
@@ -218,6 +233,7 @@
         //   - the planet feed
         //   - all weblog feeds
         
+        /*
         Set removeSet = new HashSet();
         
         // TODO: it would be nice to be able to do this without iterating 
@@ -240,6 +256,7 @@
         }
         
         this.mCache.remove(removeSet);
+        */
     }
     
     

Modified: incubator/roller/trunk/src/org/roller/presentation/filters/WeblogPageCacheFilter.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/roller/presentation/filters/WeblogPageCacheFilter.java?rev=369957&r1=369956&r2=369957&view=diff
==============================================================================
--- incubator/roller/trunk/src/org/roller/presentation/filters/WeblogPageCacheFilter.java
(original)
+++ incubator/roller/trunk/src/org/roller/presentation/filters/WeblogPageCacheFilter.java
Tue Jan 17 15:25:02 2006
@@ -9,10 +9,7 @@
 import java.util.Date;
 import java.util.Enumeration;
 import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
 import java.util.Map;
-import java.util.Set;
 import javax.servlet.Filter;
 import javax.servlet.FilterChain;
 import javax.servlet.FilterConfig;
@@ -37,6 +34,7 @@
 import org.roller.presentation.cache.Cache;
 import org.roller.presentation.cache.CacheHandler;
 import org.roller.presentation.cache.CacheManager;
+import org.roller.presentation.cache.LazyExpiringCacheEntry;
 import org.roller.presentation.util.CacheHttpServletResponseWrapper;
 import org.roller.presentation.util.ResponseContent;
 
@@ -50,8 +48,7 @@
  */
 public class WeblogPageCacheFilter implements Filter, CacheHandler {
     
-    private static Log mLogger =
-            LogFactory.getFactory().getInstance(WeblogPageCacheFilter.class);
+    private static Log mLogger = LogFactory.getLog(WeblogPageCacheFilter.class);
     
     // a unique identifier for this cache, this is used as the prefix for
     // roller config properties that apply to this cache
@@ -89,12 +86,26 @@
             return;
         }
         
-        String key = "pageCache:"+this.generateKey(pageRequest);
+        String key = this.CACHE_ID+":"+this.generateKey(pageRequest);
         
         try {
             ResponseContent respContent = null;
             if(!this.excludeOwnerPages || !pageRequest.isLoggedIn()) {
-                respContent = (ResponseContent) this.mCache.get(key);
+                // we need the last expiration time for the given weblog
+                long lastExpiration = 0;
+                Date lastExpirationDate = 
+                        (Date) CacheManager.getLastExpiredDate(pageRequest.getWeblogHandle());
+                if(lastExpirationDate != null)
+                    lastExpiration = lastExpirationDate.getTime();
+                
+                LazyExpiringCacheEntry entry = 
+                        (LazyExpiringCacheEntry) this.mCache.get(key);
+                if(entry != null) {
+                    respContent = (ResponseContent) entry.getValue(lastExpiration);
+                    
+                    if(respContent == null)
+                        mLogger.debug("HIT-INVALID "+key);
+                }
             }
             
             if (respContent == null) {
@@ -117,8 +128,8 @@
                     // only cache if this is not a logged in user?
                     if (!this.excludeOwnerPages || !pageRequest.isLoggedIn()) {
                         if (rc != null && rc.getSize() > 0) {
-                            this.mCache.put(key, rc);
-                        } else if (mLogger.isDebugEnabled()) {
+                            this.mCache.put(key, new LazyExpiringCacheEntry(rc));
+                        } else {
                             mLogger.debug("Not caching zero length content for key: " + key);
                         }
                     } else {
@@ -233,6 +244,7 @@
         //   - the weblog entry permalink page
         //   - the weblog archive pages
         
+        /*
         String handle = entry.getWebsite().getHandle();
         String keyBase = "pageCache:weblog/"+handle+"/page";
         
@@ -260,6 +272,9 @@
 
         this.mCache.remove(removeSet);
         this.purges += removeSet.size();
+        */
+        
+        this.invalidate(entry.getWebsite());
     }
     
     
@@ -270,6 +285,7 @@
         
         mLogger.debug("invalidating website = "+website.getHandle());
         
+        /*
         // we need to remove the following cached items if they exist
         //   - all pages for this weblog
         
@@ -292,6 +308,7 @@
         
         this.mCache.remove(removeSet);
         this.purges += removeSet.size();
+        */
     }
     
     



Mime
View raw message