Author: markt
Date: Fri Sep 28 08:40:38 2012
New Revision: 1391362
URL: http://svn.apache.org/viewvc?rev=1391362&view=rev
Log:
Further work on the caching implementation
- If a CachedResource fails validation, remove it from the cache and replace it
rather than update it as this makes it much easier to track the current cache
size.
- Track the current cache size
- Add configuration for the maximum cache size
- Start implementing (not finished) the background expiration
Modified:
tomcat/sandbox/trunk-resources/java/org/apache/catalina/WebResourceRoot.java
tomcat/sandbox/trunk-resources/java/org/apache/catalina/core/StandardContext.java
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/StandardRoot.java
tomcat/sandbox/trunk-resources/test/org/apache/catalina/webresources/TesterWebResourceRoot.java
Modified:
tomcat/sandbox/trunk-resources/java/org/apache/catalina/WebResourceRoot.java
URL:
http://svn.apache.org/viewvc/tomcat/sandbox/trunk-resources/java/org/apache/catalina/WebResourceRoot.java?rev=1391362&r1=1391361&r2=1391362&view=diff
==============================================================================
---
tomcat/sandbox/trunk-resources/java/org/apache/catalina/WebResourceRoot.java
(original)
+++
tomcat/sandbox/trunk-resources/java/org/apache/catalina/WebResourceRoot.java
Fri Sep 28 08:40:38 2012
@@ -255,6 +255,9 @@ public interface WebResourceRoot extends
*/
long getCacheTtl();
+ void setCacheMaxSize(long cacheMaxSize);
+ long getCacheMaxSize();
+
/**
* This method will be invoked by the context on a periodic basis and
allows
* the implementation a method that executes periodic tasks, such as
purging
Modified:
tomcat/sandbox/trunk-resources/java/org/apache/catalina/core/StandardContext.java
URL:
http://svn.apache.org/viewvc/tomcat/sandbox/trunk-resources/java/org/apache/catalina/core/StandardContext.java?rev=1391362&r1=1391361&r2=1391362&view=diff
==============================================================================
---
tomcat/sandbox/trunk-resources/java/org/apache/catalina/core/StandardContext.java
(original)
+++
tomcat/sandbox/trunk-resources/java/org/apache/catalina/core/StandardContext.java
Fri Sep 28 08:40:38 2012
@@ -4773,13 +4773,13 @@ public class StandardContext extends Con
resources.setAllowLinking(isAllowLinking());
- resources.setCacheTtl(getCacheTTL());
resources.setCachingAllowed(isCachingAllowed());
+ resources.setCacheTtl(getCacheTTL());
+ resources.setCacheMaxSize(getCacheMaxSize());
resources.start();
// TODO: Implement caching.
- // getCacheMaxSize()
// getCacheMaxObjectSize()
if (effectiveMajorVersion >=3 && addWebinfClassesResources) {
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=1391362&r1=1391361&r2=1391362&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
Fri Sep 28 08:40:38 2012
@@ -18,14 +18,23 @@ package org.apache.catalina.webresources
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicLong;
import org.apache.catalina.WebResource;
public class Cache {
+ // Estimate (on high side to be safe) of average size excluding content
+ // based on profiler data.
+ private static final long CACHE_ENTRY_SIZE = 500;
+
+ private static final long TARGET_FREE_PERCENT = 5;
+
private final StandardRoot root;
+ private final AtomicLong size = new AtomicLong(0);
private long ttl = 5000;
+ private long maxSize = 10 * 1024 * 1024;
private ConcurrentMap<String,CachedResource> resourceCache =
new ConcurrentHashMap<>();
@@ -35,25 +44,61 @@ public class Cache {
}
protected WebResource getResource(String path) {
- // Multiple concurrent callers will end up with the same CachedResource
- // instance
- CachedResource newCacheEntry = new CachedResource(root, path, ttl);
- CachedResource result =
- resourceCache.putIfAbsent(path, newCacheEntry);
+ CachedResource cacheEntry = resourceCache.get(path);
- if (result == null) {
- result = newCacheEntry;
+ if (cacheEntry != null && !cacheEntry.validate()) {
+ removeCacheEntry(path);
+ cacheEntry = null;
}
- // TODO check cache size and do minimum necessary to make room
- // TODO Cache size configuration
- result.validate();
+ if (cacheEntry == null) {
+ // Concurrent callers will end up with the same CachedResource
+ // instance
+ CachedResource newCacheEntry = new CachedResource(root, path, ttl);
+ cacheEntry = resourceCache.putIfAbsent(path, newCacheEntry);
+
+ if (cacheEntry == null) {
+ // newCacheEntry was inserted into the cache - validate it
+ cacheEntry = newCacheEntry;
+ cacheEntry.validate();
+
+ // Assume that the cache entry will include the content.
+ // This isn't always the case but it makes tracking the
+ // current cache size easier.
+ long delta = CACHE_ENTRY_SIZE;
+ delta += cacheEntry.getContentLength();
+ size.addAndGet(delta);
+
+ if (size.get() > maxSize) {
+ // TODO make room
+ }
+ } else {
+ // Another thread added the entry to the cache
+ // Make sure it is validated
+ cacheEntry.validate();
+ }
+ }
- return result;
+ return cacheEntry;
}
protected void backgroundProcess() {
- // TODO expiration
+ long targetSize = maxSize * (100 - TARGET_FREE_PERCENT) / 100;
+
+ while (targetSize > size.get()) {
+ // TODO ID resources to remove
+ }
+ }
+
+ private void removeCacheEntry(String path) {
+ // With concurrent calls for the same path, the entry is only removed
+ // once and the cache size is only updated once.
+ CachedResource cachedResource = resourceCache.remove(path);
+ if (cachedResource != null) {
+ long delta =
+ 0 - CACHE_ENTRY_SIZE - cachedResource.getContentLength();
+ size.addAndGet(delta);
+ }
}
public long getTtl() {
@@ -63,4 +108,12 @@ public class Cache {
public void setTtl(long ttl) {
this.ttl = ttl;
}
+
+ public long getMaxSize() {
+ return maxSize;
+ }
+
+ public void setMaxSize(long maxSize) {
+ this.maxSize = maxSize;
+ }
}
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=1391362&r1=1391361&r2=1391362&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
Fri Sep 28 08:40:38 2012
@@ -52,43 +52,34 @@ public class CachedResource implements W
this.ttl = ttl;
}
- protected void validate() {
+ protected boolean validate() {
long now = System.currentTimeMillis();
if (webResource == null) {
synchronized (this) {
if (webResource == null) {
- WebResource result = root.getResourceInternal(webAppPath);
- webResource = result;
+ webResource = root.getResourceInternal(webAppPath);
+ getLastModified();
+ getContentLength();
nextCheck = ttl + now;
- return;
+ return true;
}
}
}
if (now < nextCheck) {
- return;
+ return true;
}
- synchronized (this) {
- if (now < nextCheck) {
- return;
- }
-
- if (webResource.getLastModified() + ttl >= nextCheck) {
- WebResource result = root.getResourceInternal(webAppPath);
- webResource = result;
-
- cachedContent = null;
- cachedContentLength = null;
- cachedExists = null;
- cachedIsDirectory = null;
- cachedIsFile = null;
- cachedLastModified = null;
- cachedLastModifiedHttp = null;
- }
- nextCheck = ttl + now;
+ // If modified date or length change - resource has changed / been
+ // removed etc.
+ if (webResource.getLastModified() != getLastModified() ||
+ webResource.getContentLength() != getContentLength()) {
+ return false;
}
+
+ nextCheck = ttl + now;
+ return true;
}
Modified:
tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/StandardRoot.java
URL:
http://svn.apache.org/viewvc/tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/StandardRoot.java?rev=1391362&r1=1391361&r2=1391362&view=diff
==============================================================================
---
tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/StandardRoot.java
(original)
+++
tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/StandardRoot.java
Fri Sep 28 08:40:38 2012
@@ -321,6 +321,16 @@ public class StandardRoot extends Lifecy
}
@Override
+ public long getCacheMaxSize() {
+ return cache.getMaxSize();
+ }
+
+ @Override
+ public void setCacheMaxSize(long cacheMaxSize) {
+ cache.setMaxSize(cacheMaxSize);
+ }
+
+ @Override
public Context getContext() {
return context;
}
Modified:
tomcat/sandbox/trunk-resources/test/org/apache/catalina/webresources/TesterWebResourceRoot.java
URL:
http://svn.apache.org/viewvc/tomcat/sandbox/trunk-resources/test/org/apache/catalina/webresources/TesterWebResourceRoot.java?rev=1391362&r1=1391361&r2=1391362&view=diff
==============================================================================
---
tomcat/sandbox/trunk-resources/test/org/apache/catalina/webresources/TesterWebResourceRoot.java
(original)
+++
tomcat/sandbox/trunk-resources/test/org/apache/catalina/webresources/TesterWebResourceRoot.java
Fri Sep 28 08:40:38 2012
@@ -167,6 +167,16 @@ public class TesterWebResourceRoot imple
}
@Override
+ public void setCacheMaxSize(long cacheMaxSize) {
+ // NO-OP
+ }
+
+ @Override
+ public long getCacheMaxSize() {
+ return 0;
+ }
+
+ @Override
public void addPreResources(WebResourceSet webResourceSet) {
// NO-OP
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]