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 2010/10/21 12:37:02 UTC

svn commit: r1025933 - in /jackrabbit/branches/2.1: ./ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/MLRUItemStateCache.java jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java

Author: jukka
Date: Thu Oct 21 10:37:02 2010
New Revision: 1025933

URL: http://svn.apache.org/viewvc?rev=1025933&view=rev
Log:
2.1: Merged revisions 1001707, 1002065 and 1002066 (JCR-2699)

Modified:
    jackrabbit/branches/2.1/   (props changed)
    jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/MLRUItemStateCache.java
    jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java

Propchange: jackrabbit/branches/2.1/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Thu Oct 21 10:37:02 2010
@@ -2,4 +2,4 @@
 /jackrabbit/sandbox/JCR-1456:774917-886178
 /jackrabbit/sandbox/JCR-2170:812417-816332
 /jackrabbit/sandbox/tripod-JCR-2209:795441-795863
-/jackrabbit/trunk:931121,931479,931483-931484,931504,931609,931613,931838,931919,932318-932319,933144,933197,933203,933213,933216,933554,933646,933694,934405,934412,934849,935557,936668,938099,945528,950440,950680,955222,955229,955307,955852,961487,961626,964362,965539,986682,986686,986715,991144,996810
+/jackrabbit/trunk:931121,931479,931483-931484,931504,931609,931613,931838,931919,932318-932319,933144,933197,933203,933213,933216,933554,933646,933694,934405,934412,934849,935557,936668,938099,945528,950440,950680,955222,955229,955307,955852,961487,961626,964362,965539,986682,986686,986715,991144,996810,1001707,1002065-1002066

Modified: jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/MLRUItemStateCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/MLRUItemStateCache.java?rev=1025933&r1=1025932&r2=1025933&view=diff
==============================================================================
--- jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/MLRUItemStateCache.java (original)
+++ jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/MLRUItemStateCache.java Thu Oct 21 10:37:02 2010
@@ -16,7 +16,10 @@
  */
 package org.apache.jackrabbit.core.state;
 
-import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
 
 import org.apache.commons.collections.map.LinkedMap;
 import org.apache.jackrabbit.core.id.ItemId;
@@ -41,16 +44,16 @@ public class MLRUItemStateCache implemen
     public static final int DEFAULT_MAX_MEM = 4 * 1024 * 1024;
 
     /** the amount of memory the entries use */
-    private long totalMem;
+    private volatile long totalMem;
 
     /** the maximum of memory the cache may use */
-    private long maxMem;
+    private volatile long maxMem;
 
     /** the number of writes */
-    private long numWrites;
+    private volatile long numWrites;
 
     /** the access count */
-    private long accessCount;
+    private volatile long accessCount;
 
     /** the cache access listeners */
     private CacheAccessListener accessListener;
@@ -58,7 +61,7 @@ public class MLRUItemStateCache implemen
     /**
      * A cache for <code>ItemState</code> instances
      */
-    private final LinkedMap cache = new LinkedMap();
+    private final Map<ItemId, Entry> cache;
 
     /**
      * Constructs a new, empty <code>ItemStateCache</code> with a maximum amount
@@ -74,8 +77,21 @@ public class MLRUItemStateCache implemen
      *
      * @param maxMem the maximum amount of memory this cache may use.
      */
+    @SuppressWarnings("serial")
     private MLRUItemStateCache(int maxMem) {
         this.maxMem = maxMem;
+        this.cache = new LinkedHashMap<ItemId, MLRUItemStateCache.Entry>(
+                maxMem / 1024, 0.75f, true /* access-ordered */) {
+            @Override
+            protected boolean removeEldestEntry(Map.Entry<ItemId, Entry> e) {
+                if (totalMem > MLRUItemStateCache.this.maxMem) {
+                    totalMem -= e.getValue().size;
+                    return true;
+                } else {
+                    return false;
+                }
+            }
+        };
     }
 
     //-------------------------------------------------------< ItemStateCache >
@@ -94,10 +110,8 @@ public class MLRUItemStateCache implemen
     public ItemState retrieve(ItemId id) {
         touch();
         synchronized (cache) {
-            Entry entry = (Entry) cache.remove(id);
+            Entry entry = cache.get(id);
             if (entry != null) {
-                // 'touch' item, by adding at end of list
-                cache.put(id, entry);
                 return entry.state;
             } else {
                 return null;
@@ -110,7 +124,12 @@ public class MLRUItemStateCache implemen
      */
     public ItemState[] retrieveAll() {
         synchronized (cache) {
-            return (ItemState[]) cache.values().toArray(new ItemState[cache.size()]);
+            ItemState[] states = new ItemState[cache.size()];
+            int i = 0;
+            for (Entry entry : cache.values()) {
+                states[i++] = entry.state;
+            }
+            return states;
         }
     }
 
@@ -120,7 +139,7 @@ public class MLRUItemStateCache implemen
     public void update(ItemId id) {
         touch();
         synchronized (cache) {
-            Entry entry = (Entry) cache.get(id);
+            Entry entry = cache.get(id);
             if (entry != null) {
                 totalMem -= entry.size;
                 entry.recalc();
@@ -141,33 +160,21 @@ public class MLRUItemStateCache implemen
                 evict(id);
             }
             Entry entry = new Entry(state);
-            cache.put(id, entry);
             totalMem += entry.size;
-            shrinkIfRequired();
+            cache.put(id, entry);
             if (numWrites++ % 10000 == 0 && log.isDebugEnabled()) {
                 log.debug(this + " size=" + cache.size() + ", " + totalMem + "/" + maxMem);
             }
         }
     }
 
-    private void shrinkIfRequired() {
-        // remove items, if too many
-        synchronized (cache) {
-            while (totalMem > maxMem) {
-                ItemId id = (ItemId) cache.firstKey();
-                Entry entry = (Entry) cache.remove(id);
-                totalMem -= entry.size;
-            }
-        }
-    }
-
     /**
      * {@inheritDoc}
      */
     public void evict(ItemId id) {
         touch();
         synchronized (cache) {
-            Entry entry = (Entry) cache.remove(id);
+            Entry entry = cache.remove(id);
             if (entry != null) {
                 totalMem -= entry.size;
             }
@@ -220,15 +227,6 @@ public class MLRUItemStateCache implemen
      * {@inheritDoc}
      */
     public long getMemoryUsed() {
-        synchronized (cache) {
-            totalMem = 0;
-            Iterator iter = cache.values().iterator();
-            while (iter.hasNext()) {
-                Entry entry = (Entry) iter.next();
-                entry.recalc();
-                totalMem += entry.size;
-            }
-        }
         return totalMem;
     }
 
@@ -247,7 +245,21 @@ public class MLRUItemStateCache implemen
     public void setMaxMemorySize(long size) {
         synchronized (cache) {
             this.maxMem = size;
-            shrinkIfRequired();
+
+            // remove items, if too many
+            if (totalMem > maxMem) {
+                totalMem = 0;
+                List<Map.Entry<ItemId, Entry>> entries =
+                    new ArrayList<Map.Entry<ItemId, Entry>>(cache.entrySet());
+                for (Map.Entry<ItemId, Entry> entry : entries) {
+                    long entrySize = entry.getValue().size;
+                    if (totalMem + entrySize > maxMem) {
+                        cache.remove(entry.getKey());
+                    } else {
+                        totalMem += entrySize;
+                    }
+                }
+            }
         }
     }
 

Modified: jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java?rev=1025933&r1=1025932&r2=1025933&view=diff
==============================================================================
--- jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java (original)
+++ jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java Thu Oct 21 10:37:02 2010
@@ -257,9 +257,12 @@ public class SharedItemStateManager
         ISMLocking.ReadLock readLock = acquireReadLock(id);
         try {
             // check internal first
-            if (hasNonVirtualItemState(id)) {
-                return getNonVirtualItemState(id);
-            }
+            return getNonVirtualItemState(id);
+        } catch (NoSuchItemStateException e) {
+            // Fall through to virtual state providers. We can afford the
+            // exception-for-control-flow performance hit here, as almost
+            // all performance-critical content is non-virtual. With this
+            // catch we can avoid an extra hasNonVirtualItemState() call.
         } finally {
             readLock.release();
         }
@@ -1702,20 +1705,22 @@ public class SharedItemStateManager
             throws NoSuchItemStateException, ItemStateException {
         ItemState state = cache.retrieve(id);
         if (state == null) {
+            // not found in cache, load from persistent storage
+            state = loadItemState(id);
+            state.setStatus(ItemState.STATUS_EXISTING);
             synchronized (this) {
                 // Use a double check to ensure that the cache entry is
                 // not created twice. We don't synchronize the entire
                 // method to allow the first cache retrieval to proceed
                 // even when another thread is loading a new item state.
-                state = cache.retrieve(id);
-                if (state == null) {
-                    // not found in cache, load from persistent storage
-                    state = loadItemState(id);
-                    state.setStatus(ItemState.STATUS_EXISTING);
+                ItemState cachedState = cache.retrieve(id);
+                if (cachedState == null) {
                     // put it in cache
                     cache.cache(state);
                     // set parent container
                     state.setContainer(this);
+                } else {
+                    state = cachedState;
                 }
             }
         }