Author: markt
Date: Tue Oct  2 10:50:52 2012
New Revision: 1392832

URL: http://svn.apache.org/viewvc?rev=1392832&view=rev
Log:
Implement the background cache expiry

Modified:
    
tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/Cache.java
    
tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/CachedResource.java
    
tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/LocalStrings.properties

Modified: 
tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/Cache.java
URL: 
http://svn.apache.org/viewvc/tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/Cache.java?rev=1392832&r1=1392831&r2=1392832&view=diff
==============================================================================
--- 
tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/Cache.java 
(original)
+++ 
tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/Cache.java 
Tue Oct  2 10:50:52 2012
@@ -16,14 +16,24 @@
  */
 package org.apache.catalina.webresources;
 
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.TreeSet;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.catalina.WebResource;
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.res.StringManager;
 
 public class Cache {
 
+    private static final Log log = LogFactory.getLog(Cache.class);
+    protected static final StringManager sm =
+            StringManager.getManager(Constants.Package);
+
     // Estimate (on high side to be safe) of average size excluding content
     // based on profiler data.
     private static final long CACHE_ENTRY_SIZE = 500;
@@ -44,6 +54,9 @@ public class Cache {
     }
 
     protected WebResource getResource(String path) {
+
+        // TODO Should some resources be excluded from caching?
+
         CachedResource cacheEntry = resourceCache.get(path);
 
         if (cacheEntry != null && !cacheEntry.validate()) {
@@ -85,8 +98,34 @@ public class Cache {
     protected void backgroundProcess() {
         long targetSize = maxSize * (100 - TARGET_FREE_PERCENT) / 100;
 
-        while (targetSize > size.get()) {
-            // TODO ID resources to remove
+        long now = System.currentTimeMillis();
+
+        // Create an ordered set of all cached resources with the least 
recently
+        // used first.
+        TreeSet<CachedResource> orderedResources =
+                new TreeSet<>(new EvictionOrder());
+        orderedResources.addAll(resourceCache.values());
+
+        Iterator<CachedResource> iter = orderedResources.iterator();
+
+        while (targetSize > size.get() && iter.hasNext()) {
+            CachedResource resource = iter.next();
+
+            // Don't expire anything that has been checked within the TTL
+            if (resource.getNextCheck() > now) {
+                continue;
+            }
+
+            // Remove the entry from the cache
+            removeCacheEntry(resource.getWebappPath());
+        }
+
+        long cacheSize = size.get();
+        if (targetSize > cacheSize) {
+            log.info(sm.getString("cache.backgroundEvict",
+                    Long.valueOf(TARGET_FREE_PERCENT),
+                    root.getContext().getName(),
+                    Long.valueOf(cacheSize / 1024)));
         }
     }
 
@@ -116,4 +155,23 @@ public class Cache {
     public void setMaxSize(long maxSize) {
         this.maxSize = maxSize;
     }
+
+    private static class EvictionOrder implements Comparator<CachedResource> {
+
+        @Override
+        public int compare(CachedResource cr1, CachedResource cr2) {
+            long nc1 = cr1.getNextCheck();
+            long nc2 = cr2.getNextCheck();
+
+            // Oldest resource should be first (so iterator goes from oldest to
+            // youngest.
+            if (nc1 == nc2) {
+                return 0;
+            } else if (nc1 > nc2) {
+                return -1;
+            } else {
+                return 1;
+            }
+        }
+    }
 }

Modified: 
tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/CachedResource.java
URL: 
http://svn.apache.org/viewvc/tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/CachedResource.java?rev=1392832&r1=1392831&r2=1392832&view=diff
==============================================================================
--- 
tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/CachedResource.java
 (original)
+++ 
tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/CachedResource.java
 Tue Oct  2 10:50:52 2012
@@ -82,6 +82,9 @@ public class CachedResource implements W
         return true;
     }
 
+    protected long getNextCheck() {
+        return nextCheck;
+    }
 
     @Override
     public long getLastModified() {

Modified: 
tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/LocalStrings.properties
URL: 
http://svn.apache.org/viewvc/tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/LocalStrings.properties?rev=1392832&r1=1392831&r2=1392832&view=diff
==============================================================================
--- 
tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/LocalStrings.properties
 (original)
+++ 
tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/LocalStrings.properties
 Tue Oct  2 10:50:52 2012
@@ -16,6 +16,8 @@
 abstractResource.getContentFail=Unable to return [{0}] as a byte array
 abstractResource.getContentTooLarge=Unable to return [{0}] as a byte array 
since the resource is [{1}] bytes in size which is larger than the maximum size 
of a byte array
 
+cache.backgroundEvict=The background cache eviction process was unable to free 
[{0}] percent of the cache for Context [{1}] - consider increasing the maximum 
size of the cache. After eviction approximately [{2}] KB of data remained in 
the cache.
+
 dirResourceSet.writeExists=The target of the write already exists
 dirResourceSet.writeNpe=The input stream may not be null
 



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to