You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ju...@apache.org on 2007/01/09 21:33:37 UTC
svn commit: r494560 - in
/jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/name:
CachingNameResolver.java GenerationalCache.java
Author: jukka
Date: Tue Jan 9 12:33:37 2007
New Revision: 494560
URL: http://svn.apache.org/viewvc?view=rev&rev=494560
Log:
JCR-688: Extracted the generational cache to a separate class
Added:
jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/name/GenerationalCache.java (with props)
Modified:
jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/name/CachingNameResolver.java
Modified: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/name/CachingNameResolver.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/name/CachingNameResolver.java?view=diff&rev=494560&r1=494559&r2=494560
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/name/CachingNameResolver.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/name/CachingNameResolver.java Tue Jan 9 12:33:37 2007
@@ -16,144 +16,44 @@
*/
package org.apache.jackrabbit.name;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-
import javax.jcr.NamespaceException;
/**
* Name resolver decorator that uses a generational cache to speed up
* parsing and formatting of JCR names. Uncached names are resolved using
* the underlying decorated name resolver.
- * <p>
- * The cache consists of three parts: a long term cache and two generations
- * of recent cache entries. The two generations are used to collect recent new
- * entries, and those entries that are used within two successive generations
- * get promoted to the long term cache. The entries within the long term cache
- * are discarded only when the size of the cache exceeds the given maximum
- * cache size.
*/
public class CachingNameResolver implements NameResolver {
/**
- * Default maximum cache size.
- */
- private static final int DEFAULT_CACHE_SIZE = 1000;
-
- /**
- * Divisor used to determine the default generation age from the
- * maximum cache size.
- */
- private static final int DEFAULT_SIZE_AGE_RATIO = 10;
-
- /**
* Decorated name resolver.
*/
private final NameResolver resolver;
/**
- * Maximum size of the name cache.
- */
- private final int maxSize;
-
- /**
- * Maximum age of a cache generation.
- */
- private final int maxAge;
-
- /**
- * Long term name cache. Read only.
- */
- private Map cache = new HashMap();
-
- /**
- * Old cache generation. Read only.
- */
- private Map old = new HashMap();
-
- /**
- * Young cache generation. Write only.
+ * Generational cache.
*/
- private Map young = new HashMap();
+ private final GenerationalCache cache;
/**
- * Age of the young cache generation.
- */
- private int age = 0;
-
- /**
- * Creates a caching name resolver.
+ * Creates a caching decorator for the given name resolver. The given
+ * generational cache is used for caching.
*
* @param resolver decorated name resolver
- * @param maxSize maximum size of the long term cache
- * @param maxAge maximum age of a cache generation
+ * @param cache generational cache
*/
- public CachingNameResolver(NameResolver resolver, int maxSize, int maxAge) {
+ public CachingNameResolver(NameResolver resolver, GenerationalCache cache) {
this.resolver = resolver;
- this.maxSize = maxSize;
- this.maxAge = maxAge;
- }
-
- /**
- * Creates a caching name resolver using the default generation age for
- * the given cache size.
- *
- * @param resolver decorated name resolver
- * @param maxSize maximum size of the long term cache
- */
- public CachingNameResolver(NameResolver resolver, int maxSize) {
- this(resolver, maxSize, maxSize / DEFAULT_SIZE_AGE_RATIO);
+ this.cache = cache;
}
/**
- * Creates a caching name resolver using the default size and
- * generation age.
+ * Creates a caching decorator for the given name resolver.
*
- * @param resolver decorated name resolver
+ * @param resolver name resolver
*/
public CachingNameResolver(NameResolver resolver) {
- this(resolver, DEFAULT_CACHE_SIZE);
- }
-
- /**
- * Caches the given key-value pair and increases the age of the current
- * cache generation. When the maximum age of a generation is reached,
- * the following steps are taken:
- * <ol>
- * <li>The union of the two cache generations is calculated</li>
- * <li>The union is added to the long term name cache</li>
- * <li>If the cache size exceeds the maximum, only the union is kept</li>
- * <li>A new cache generation is started</li>
- * </ol>
- *
- * @param key key of the cache entry
- * @param value value of the cache entry
- */
- private synchronized void cache(Object key, Object value) {
- young.put(key, value);
-
- if (++age == maxAge) {
- Map union = new HashMap();
- Iterator iterator = old.entrySet().iterator();
- while (iterator.hasNext()) {
- Map.Entry entry = (Map.Entry) iterator.next();
- if (young.containsKey(entry.getKey())) {
- union.put(entry.getKey(), entry.getValue());
- }
- }
-
- if (!union.isEmpty()) {
- if (cache.size() + union.size() <= maxSize) {
- union.putAll(cache);
- }
- cache = union;
- }
-
- old = young;
- young = new HashMap();
- age = 0;
- }
+ this(resolver, new GenerationalCache());
}
//--------------------------------------------------------< NameResolver >
@@ -172,22 +72,17 @@
throws NameException, NamespaceException {
QName qname = (QName) cache.get(name);
if (qname == null) {
- qname = (QName) old.get(name);
- if (qname == null) {
- qname = resolver.getQName(name);
- }
- cache(name, qname);
+ qname = resolver.getQName(name);
+ cache.put(name, qname);
}
return qname;
}
/**
- * Returns the prefixed JCR name for the given qualified name.
- * If the name is in the default namespace, then the local name
- * is returned without a prefix. Otherwise the name is first looked
- * up form the generational cache and the call gets delegated to the
- * decorated name resolver only if the cache misses.
+ * Returns the prefixed JCR name for the given qualified name. The name
+ * is first looked up form the generational cache and the call gets
+ * delegated to the decorated name resolver only if the cache misses.
*
* @param qname qualified name
* @return prefixed JCR name
@@ -196,11 +91,8 @@
public String getJCRName(QName qname) throws NamespaceException {
String name = (String) cache.get(qname);
if (name == null) {
- name = (String) old.get(qname);
- if (name == null) {
- name = resolver.getJCRName(qname);
- }
- cache(qname, name);
+ name = resolver.getJCRName(qname);
+ cache.put(qname, name);
}
return name;
}
Added: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/name/GenerationalCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/name/GenerationalCache.java?view=auto&rev=494560
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/name/GenerationalCache.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/name/GenerationalCache.java Tue Jan 9 12:33:37 2007
@@ -0,0 +1,162 @@
+/*
+ * 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.jackrabbit.name;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * Generational cache. The cache implemented by this class consists of three
+ * parts: a long term cache and two generations of recent entries. The two
+ * generations are used to collect recent new entries, and those entries that
+ * are used within two successive generations get promoted to the long term
+ * cache. The entries within the long term cache are discarded only when the
+ * size of the cache exceeds the given maximum cache size.
+ */
+class GenerationalCache {
+
+ /**
+ * Default maximum cache size.
+ */
+ private static final int DEFAULT_CACHE_SIZE = 1000;
+
+ /**
+ * Divisor used to determine the default generation age from the
+ * maximum cache size.
+ */
+ private static final int DEFAULT_SIZE_AGE_RATIO = 10;
+
+ /**
+ * Maximum size of the name cache.
+ */
+ private final int maxSize;
+
+ /**
+ * Maximum age of a cache generation.
+ */
+ private final int maxAge;
+
+ /**
+ * Long term cache. Read only.
+ */
+ private Map cache = new HashMap();
+
+ /**
+ * Old cache generation.
+ */
+ private Map old = new HashMap();
+
+ /**
+ * Young cache generation.
+ */
+ private Map young = new HashMap();
+
+ /**
+ * Age of the young cache generation.
+ */
+ private int age = 0;
+
+ /**
+ * Creates a caching resolver.
+ *
+ * @param maxSize maximum size of the long term cache
+ * @param maxAge maximum age of a cache generation
+ */
+ public GenerationalCache(int maxSize, int maxAge) {
+ this.maxSize = maxSize;
+ this.maxAge = maxAge;
+ }
+
+ /**
+ * Creates a caching resolver using the default generation age for
+ * the given cache size.
+ *
+ * @param maxSize maximum size of the long term cache
+ */
+ public GenerationalCache(int maxSize) {
+ this(maxSize, maxSize / DEFAULT_SIZE_AGE_RATIO);
+ }
+
+ /**
+ * Creates a caching resolver using the default size and generation age.
+ */
+ public GenerationalCache() {
+ this(DEFAULT_CACHE_SIZE);
+ }
+
+ /**
+ * Returns the cached value (if any) for the given key. The value is
+ * looked up both from the long term cache and the old cache generation.
+ * If the value is only found in the old cache generation, it gets added
+ * to the young generation via a call to {@link #put(Object, Object)}.
+ *
+ * @param key key of the cache entry
+ * @return value of the cache entry, or <code>null</code>
+ */
+ public Object get(Object key) {
+ Object value = cache.get(key);
+ if (value == null) {
+ value = old.get(key);
+ if (value != null) {
+ put(key, value);
+ }
+ }
+ return value;
+ }
+
+ /**
+ * Caches the given key-value pair and increases the age of the current
+ * cache generation. When the maximum age of a generation is reached,
+ * the following steps are taken:
+ * <ol>
+ * <li>The union of the two cache generations is calculated</li>
+ * <li>The union is added to the long term name cache</li>
+ * <li>If the cache size exceeds the maximum, only the union is kept</li>
+ * <li>A new cache generation is started</li>
+ * </ol>
+ *
+ * @param key key of the cache entry
+ * @param value value of the cache entry
+ */
+ public synchronized void put(Object key, Object value) {
+ young.put(key, value);
+
+ if (++age == maxAge) {
+ Map union = new HashMap();
+ Iterator iterator = old.entrySet().iterator();
+ while (iterator.hasNext()) {
+ Map.Entry entry = (Map.Entry) iterator.next();
+ if (young.containsKey(entry.getKey())) {
+ union.put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ if (!union.isEmpty()) {
+ if (cache.size() + union.size() <= maxSize) {
+ union.putAll(cache);
+ }
+ cache = union;
+ }
+
+ old = young;
+ young = new HashMap();
+ age = 0;
+ }
+ }
+
+}
Propchange: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/name/GenerationalCache.java
------------------------------------------------------------------------------
svn:eol-style = native