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