Author: markt
Date: Wed Oct  3 10:00:21 2012
New Revision: 1393381

URL: http://svn.apache.org/viewvc?rev=1393381&view=rev
Log:
Implement cache expiry during getResource()

Modified:
    
tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/Cache.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=1393381&r1=1393380&r2=1393381&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 
Wed Oct  3 10:00:21 2012
@@ -38,7 +38,8 @@ public class Cache {
     // based on profiler data.
     private static final long CACHE_ENTRY_SIZE = 500;
 
-    private static final long TARGET_FREE_PERCENT = 5;
+    private static final long TARGET_FREE_PERCENT_GET = 5;
+    private static final long TARGET_FREE_PERCENT_BACKGROUND = 10;
 
     private final StandardRoot root;
     private final AtomicLong size = new AtomicLong(0);
@@ -83,7 +84,20 @@ public class Cache {
                 size.addAndGet(delta);
 
                 if (size.get() > maxSize) {
-                    // TODO make room
+                    // Process resources unordered for speed. Trades cache
+                    // efficiency (younger entries may be evicted before older
+                    // ones) for speed since this is on the critical path for
+                    // request processing
+                    long targetSize =
+                            maxSize * (100 - TARGET_FREE_PERCENT_GET) / 100;
+                    long newSize = evict(
+                            targetSize, resourceCache.values().iterator());
+                    if (newSize > maxSize) {
+                        // Unable to create sufficient space for this resource
+                        // Remove it from the cache
+                        removeCacheEntry(path);
+                        log.warn(sm.getString("cache.addFail"));
+                    }
                 }
             } else {
                 // Another thread added the entry to the cache
@@ -96,19 +110,34 @@ public class Cache {
     }
 
     protected void backgroundProcess() {
-        long targetSize = maxSize * (100 - TARGET_FREE_PERCENT) / 100;
-
-        long now = System.currentTimeMillis();
-
         // Create an ordered set of all cached resources with the least 
recently
-        // used first.
+        // used first. This is a background process so we can afford to take 
the
+        // time to order the elements first
         TreeSet<CachedResource> orderedResources =
                 new TreeSet<>(new EvictionOrder());
         orderedResources.addAll(resourceCache.values());
 
         Iterator<CachedResource> iter = orderedResources.iterator();
 
-        while (targetSize > size.get() && iter.hasNext()) {
+        long targetSize =
+                maxSize * (100 - TARGET_FREE_PERCENT_BACKGROUND) / 100;
+        long newSize = evict(targetSize, iter);
+
+        if (targetSize > newSize) {
+            log.info(sm.getString("cache.backgroundEvictFail",
+                    Long.valueOf(TARGET_FREE_PERCENT_BACKGROUND),
+                    root.getContext().getName(),
+                    Long.valueOf(newSize / 1024)));
+        }
+    }
+
+    private long evict(long targetSize, Iterator<CachedResource> iter) {
+
+        long now = System.currentTimeMillis();
+
+        long newSize = size.get();
+
+        while (targetSize > newSize && iter.hasNext()) {
             CachedResource resource = iter.next();
 
             // Don't expire anything that has been checked within the TTL
@@ -118,15 +147,11 @@ public class Cache {
 
             // 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)));
+            newSize = size.get();
         }
+
+        return newSize;
     }
 
     private void removeCacheEntry(String path) {

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=1393381&r1=1393380&r2=1393381&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
 Wed Oct  3 10:00:21 2012
@@ -16,7 +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.
+cache.addFail=Unable to add the resource at [{0}] to the cache because there 
was insufficient free space available after evicting expired cache entries - 
consider increasing the maximum size of the cache
+cache.backgroundEvictFail=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