You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2014/08/11 14:29:44 UTC

svn commit: r1617265 - in /tomcat/trunk/java/org/apache/catalina/webresources: Cache.java CachedResource.java StandardRoot.java

Author: markt
Date: Mon Aug 11 12:29:43 2014
New Revision: 1617265

URL: http://svn.apache.org/r1617265
Log:
Add simple caching support for calls to getResources()

Modified:
    tomcat/trunk/java/org/apache/catalina/webresources/Cache.java
    tomcat/trunk/java/org/apache/catalina/webresources/CachedResource.java
    tomcat/trunk/java/org/apache/catalina/webresources/StandardRoot.java

Modified: tomcat/trunk/java/org/apache/catalina/webresources/Cache.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/webresources/Cache.java?rev=1617265&r1=1617264&r2=1617265&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/webresources/Cache.java (original)
+++ tomcat/trunk/java/org/apache/catalina/webresources/Cache.java Mon Aug 11 12:29:43 2014
@@ -67,7 +67,7 @@ public class Cache {
 
         CachedResource cacheEntry = resourceCache.get(path);
 
-        if (cacheEntry != null && !cacheEntry.validate(useClassLoaderResources)) {
+        if (cacheEntry != null && !cacheEntry.validateResource(useClassLoaderResources)) {
             removeCacheEntry(path);
             cacheEntry = null;
         }
@@ -85,7 +85,7 @@ public class Cache {
             if (cacheEntry == null) {
                 // newCacheEntry was inserted into the cache - validate it
                 cacheEntry = newCacheEntry;
-                cacheEntry.validate(useClassLoaderResources);
+                cacheEntry.validateResource(useClassLoaderResources);
 
                 // Even if the resource content larger than objectMaxSizeBytes
                 // there is still benefit in caching the resource metadata
@@ -112,7 +112,7 @@ public class Cache {
             } else {
                 // Another thread added the entry to the cache
                 // Make sure it is validated
-                cacheEntry.validate(useClassLoaderResources);
+                cacheEntry.validateResource(useClassLoaderResources);
             }
         } else {
             hitCount.incrementAndGet();
@@ -121,6 +121,66 @@ public class Cache {
         return cacheEntry;
     }
 
+    protected WebResource[] getResources(String path, boolean useClassLoaderResources) {
+        lookupCount.incrementAndGet();
+
+        // Don't call noCache(path) since the class loader only caches
+        // individual resources. Therefore, always cache collections here
+
+        CachedResource cacheEntry = resourceCache.get(path);
+
+        if (cacheEntry != null && !cacheEntry.validateResources(useClassLoaderResources)) {
+            removeCacheEntry(path);
+            cacheEntry = null;
+        }
+
+        if (cacheEntry == null) {
+            // Local copy to ensure consistency
+            int objectMaxSizeBytes = getObjectMaxSizeBytes();
+            CachedResource newCacheEntry =
+                    new CachedResource(this, root, path, getTtl(), objectMaxSizeBytes);
+
+            // Concurrent callers will end up with the same CachedResource
+            // instance
+            cacheEntry = resourceCache.putIfAbsent(path, newCacheEntry);
+
+            if (cacheEntry == null) {
+                // newCacheEntry was inserted into the cache - validate it
+                cacheEntry = newCacheEntry;
+                cacheEntry.validateResources(useClassLoaderResources);
+
+                // Content will not be cached but we still need metadata size
+                long delta = cacheEntry.getSize();
+                size.addAndGet(delta);
+
+                if (size.get() > maxSize) {
+                    // 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", path));
+                    }
+                }
+            } else {
+                // Another thread added the entry to the cache
+                // Make sure it is validated
+                cacheEntry.validateResources(useClassLoaderResources);
+            }
+        } else {
+            hitCount.incrementAndGet();
+        }
+
+        return cacheEntry.getWebResources();
+    }
+
     protected void backgroundProcess() {
         // Create an ordered set of all cached resources with the least recently
         // used first. This is a background process so we can afford to take the

Modified: tomcat/trunk/java/org/apache/catalina/webresources/CachedResource.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/webresources/CachedResource.java?rev=1617265&r1=1617264&r2=1617265&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/webresources/CachedResource.java (original)
+++ tomcat/trunk/java/org/apache/catalina/webresources/CachedResource.java Mon Aug 11 12:29:43 2014
@@ -43,6 +43,7 @@ public class CachedResource implements W
     private final int objectMaxSizeBytes;
 
     private volatile WebResource webResource;
+    private volatile WebResource[] webResources;
     private volatile long nextCheck;
 
     private volatile Long cachedLastModified = null;
@@ -64,7 +65,7 @@ public class CachedResource implements W
         this.objectMaxSizeBytes = objectMaxSizeBytes;
     }
 
-    protected boolean validate(boolean useClassLoaderResources) {
+    protected boolean validateResource(boolean useClassLoaderResources) {
         long now = System.currentTimeMillis();
 
         if (webResource == null) {
@@ -110,11 +111,33 @@ public class CachedResource implements W
             return false;
         }
 
-
         nextCheck = ttl + now;
         return true;
     }
 
+    protected boolean validateResources(boolean useClassLoaderResources) {
+        long now = System.currentTimeMillis();
+
+        if (webResources == null) {
+            synchronized (this) {
+                if (webResources == null) {
+                    webResources = root.getResourcesInternal(
+                            webAppPath, useClassLoaderResources);
+                    nextCheck = ttl + now;
+                    return true;
+                }
+            }
+        }
+
+        if (now < nextCheck) {
+            return true;
+        }
+
+        // At this point, always expire the entry as re-populating it is likely
+        // to be as expensive as validating it.
+        return false;
+    }
+
     protected long getNextCheck() {
         return nextCheck;
     }
@@ -291,6 +314,10 @@ public class CachedResource implements W
         return webResource;
     }
 
+    WebResource[] getWebResources() {
+        return webResources;
+    }
+
     // Assume that the cache entry will always include the content unless the
     // resource content is larger than objectMaxSizeBytes. This isn't always the
     // case but it makes tracking the current cache size easier.

Modified: tomcat/trunk/java/org/apache/catalina/webresources/StandardRoot.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/webresources/StandardRoot.java?rev=1617265&r1=1617264&r2=1617265&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/webresources/StandardRoot.java (original)
+++ tomcat/trunk/java/org/apache/catalina/webresources/StandardRoot.java Mon Aug 11 12:29:43 2014
@@ -310,6 +310,15 @@ public class StandardRoot extends Lifecy
             boolean useClassLoaderResources) {
         path = validate(path);
 
+        if (isCachingAllowed()) {
+            return cache.getResources(path, useClassLoaderResources);
+        } else {
+            return getResourcesInternal(path, useClassLoaderResources);
+        }
+    }
+
+    protected WebResource[] getResourcesInternal(String path,
+            boolean useClassLoaderResources) {
         ArrayList<WebResource> result = new ArrayList<>();
         for (ArrayList<WebResourceSet> list : allResources) {
             for (WebResourceSet webResourceSet : list) {



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