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