Author: markt
Date: Wed Sep 26 21:29:22 2012
New Revision: 1390733
URL: http://svn.apache.org/viewvc?rev=1390733&view=rev
Log:
Add the initial Cache implementation. Validation of individual resources
against a TTL is implemented but there are several configuration and cache
cleaning TODOs.
Added:
tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/Cache.java
(with props)
tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/CachedResource.java
(with props)
Modified:
tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/StandardRoot.java
Added:
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=1390733&view=auto
==============================================================================
---
tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/Cache.java
(added)
+++
tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/Cache.java
Wed Sep 26 21:29:22 2012
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.catalina.webresources;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.catalina.WebResource;
+
+public class Cache {
+
+ private final StandardRoot root;
+
+ private ConcurrentMap<String,CachedResource> resourceCache =
+ new ConcurrentHashMap<>();
+
+ public Cache(StandardRoot root) {
+ this.root = root;
+ }
+
+ protected WebResource getResource(String path) {
+ // Multiple concurrent callers will end up with the same CachedResource
+ // instance
+ // TODO Config for TTL
+ CachedResource newCacheEntry = new CachedResource(root, path, 5000);
+ CachedResource result =
+ resourceCache.putIfAbsent(path, newCacheEntry);
+
+ if (result == null) {
+ result = newCacheEntry;
+ }
+
+ // TODO check cache size and do minimum necessary to make room
+ // TODO Cache size configuration
+ result.validate();
+
+ return result;
+ }
+
+ // TODO add background expiration
+}
Propchange:
tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/Cache.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
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=1390733&view=auto
==============================================================================
---
tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/CachedResource.java
(added)
+++
tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/CachedResource.java
Wed Sep 26 21:29:22 2012
@@ -0,0 +1,230 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.catalina.webresources;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.net.URL;
+
+import org.apache.catalina.WebResource;
+import org.apache.catalina.WebResourceRoot;
+
+/**
+ * This class is designed to wrap a 'raw' WebResource and providing caching for
+ * expensive operations. Inexpensive operations may be passed through to the
+ * underlying resource.
+ */
+public class CachedResource implements WebResource {
+
+ private final StandardRoot root;
+ private final String webAppPath;
+ private final long ttl;
+
+ private volatile WebResource webResource;
+ private volatile long nextCheck;
+
+ private volatile Long cachedLastModified = null;
+ private volatile String cachedLastModifiedHttp = null;
+ private volatile byte[] cachedContent = null;
+ private volatile Boolean cachedIsFile = null;
+ private volatile Boolean cachedIsDirectory = null;
+ private volatile Boolean cachedExists = null;
+ private volatile Long cachedContentLength = null;
+
+
+ public CachedResource(StandardRoot root, String path, long ttl) {
+ this.root = root;
+ this.webAppPath = path;
+ this.ttl = ttl;
+ }
+
+ protected void validate() {
+ long now = System.currentTimeMillis();
+
+ if (webResource == null) {
+ synchronized (this) {
+ if (webResource == null) {
+ WebResource result = root.getResourceInternal(webAppPath);
+ webResource = result;
+ nextCheck = ttl + now;
+ return;
+ }
+ }
+ }
+
+ if (now < nextCheck) {
+ return;
+ }
+
+ 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;
+ }
+ }
+
+
+ @Override
+ public long getLastModified() {
+ Long cachedLastModified = this.cachedLastModified;
+ if (cachedLastModified == null) {
+ cachedLastModified =
+ Long.valueOf(webResource.getLastModified());
+ this.cachedLastModified = cachedLastModified;
+ }
+ return cachedLastModified.longValue();
+ }
+
+ @Override
+ public String getLastModifiedHttp() {
+ String cachedLastModifiedHttp = this.cachedLastModifiedHttp;
+ if (cachedLastModifiedHttp == null) {
+ cachedLastModifiedHttp = webResource.getLastModifiedHttp();
+ this.cachedLastModifiedHttp = cachedLastModifiedHttp;
+ }
+ return cachedLastModifiedHttp;
+ }
+
+ @Override
+ public boolean exists() {
+ Boolean cachedExists = this.cachedExists;
+ if (cachedExists == null) {
+ cachedExists = Boolean.valueOf(webResource.exists());
+ this.cachedExists = cachedExists;
+ }
+ return cachedExists.booleanValue();
+ }
+
+ @Override
+ public boolean isDirectory() {
+ Boolean cachedIsDirectory = this.cachedIsDirectory;
+ if (cachedIsDirectory == null) {
+ cachedIsDirectory = Boolean.valueOf(webResource.isDirectory());
+ this.cachedIsDirectory = cachedIsDirectory;
+ }
+ return cachedIsDirectory.booleanValue();
+ }
+
+ @Override
+ public boolean isFile() {
+ Boolean cachedIsFile = this.cachedIsFile;
+ if (cachedIsFile == null) {
+ cachedIsFile = Boolean.valueOf(webResource.isFile());
+ this.cachedIsFile = cachedIsFile;
+ }
+ return cachedIsFile.booleanValue();
+ }
+
+ @Override
+ public boolean delete() {
+ return webResource.delete();
+ }
+
+ @Override
+ public String getName() {
+ return webResource.getName();
+ }
+
+ @Override
+ public long getContentLength() {
+ Long cachedContentLength = this.cachedContentLength;
+ if (cachedContentLength == null) {
+ cachedContentLength = Long.valueOf(webResource.getContentLength());
+ this.cachedContentLength = cachedContentLength;
+ }
+ return cachedContentLength.longValue();
+ }
+
+ @Override
+ public String getCanonicalPath() {
+ return webResource.getCanonicalPath();
+ }
+
+ @Override
+ public boolean canRead() {
+ return webResource.canRead();
+ }
+
+ @Override
+ public String getWebappPath() {
+ return webAppPath;
+ }
+
+ @Override
+ public String getETag() {
+ return webResource.getETag();
+ }
+
+ @Override
+ public void setMimeType(String mimeType) {
+ webResource.setMimeType(mimeType);
+ }
+
+ @Override
+ public String getMimeType() {
+ return webResource.getMimeType();
+ }
+
+ @Override
+ public InputStream getInputStream() {
+ byte[] content = cachedContent;
+ if (content == null) {
+ // Can't cache InputStreams
+ return webResource.getInputStream();
+ }
+ return new ByteArrayInputStream(content);
+ }
+
+ @Override
+ public byte[] getContent() {
+ byte[] cachedContent = this.cachedContent;
+ if (cachedContent == null) {
+ cachedContent = webResource.getContent();
+ this.cachedContent = cachedContent;
+ }
+ return cachedContent;
+ }
+
+ @Override
+ public long getCreation() {
+ return webResource.getCreation();
+ }
+
+ @Override
+ public URL getURL() {
+ return webResource.getURL();
+ }
+
+ @Override
+ public WebResourceRoot getWebResourceRoot() {
+ return webResource.getWebResourceRoot();
+ }
+}
Propchange:
tomcat/sandbox/trunk-resources/java/org/apache/catalina/webresources/CachedResource.java
------------------------------------------------------------------------------
svn:eol-style = native
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=1390733&r1=1390732&r2=1390733&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
Wed Sep 26 21:29:22 2012
@@ -61,6 +61,8 @@ public class StandardRoot extends Lifecy
private ArrayList<WebResourceSet> jarResources = new ArrayList<>();
private ArrayList<WebResourceSet> postResources = new ArrayList<>();
+ private Cache cache = new Cache(this);
+
// Constructs to make iteration over all WebResourceSets simpler
private ArrayList<WebResourceSet> mainResources = new ArrayList<>();
private ArrayList<ArrayList<WebResourceSet>> allResources =
@@ -156,6 +158,10 @@ public class StandardRoot extends Lifecy
@Override
public WebResource getResource(String path) {
+ return cache.getResource(path);
+ }
+
+ protected WebResource getResourceInternal(String path) {
checkState();
WebResource result = null;
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]