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-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org