You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by to...@apache.org on 2016/08/08 10:35:40 UTC

svn commit: r1755491 - in /jackrabbit/oak/branches/1.2/oak-core/src: main/java/org/apache/jackrabbit/oak/cache/CacheLIRS.java test/java/org/apache/jackrabbit/oak/cache/CacheTest.java

Author: tomekr
Date: Mon Aug  8 10:35:39 2016
New Revision: 1755491

URL: http://svn.apache.org/viewvc?rev=1755491&view=rev
Log:
OAK-3997: Include eviction cause to the LIRS removal callback

Modified:
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/cache/CacheLIRS.java
    jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/cache/CacheTest.java

Modified: jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/cache/CacheLIRS.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/cache/CacheLIRS.java?rev=1755491&r1=1755490&r2=1755491&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/cache/CacheLIRS.java (original)
+++ jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/cache/CacheLIRS.java Mon Aug  8 10:35:39 2016
@@ -37,6 +37,7 @@ import org.slf4j.LoggerFactory;
 import com.google.common.cache.CacheLoader;
 import com.google.common.cache.CacheStats;
 import com.google.common.cache.LoadingCache;
+import com.google.common.cache.RemovalCause;
 import com.google.common.cache.Weigher;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.util.concurrent.ListenableFuture;
@@ -96,8 +97,9 @@ public class CacheLIRS<K, V> implements
          * 
          * @param key the evicted item's key
          * @param value the evicted item's value or {@code null} if non-resident
+         * @param cause the cause of the eviction
          */
-        void evicted(@Nonnull K key, @Nullable V value);
+        void evicted(@Nonnull K key, @Nullable V value, @Nonnull RemovalCause cause);
     }
 
     /**
@@ -202,17 +204,17 @@ public class CacheLIRS<K, V> implements
         Segment<K, V> old = segments[index];
         segments[index] = s;
         if (evicted != null && old != null && old != s) {
-            old.evictedAll();
+            old.evictedAll(RemovalCause.EXPLICIT);
         }
     }
 
-    void evicted(Entry<K, V> entry) {
+    void evicted(Entry<K, V> entry, RemovalCause cause) {
         if (evicted == null) {
             return;
         }
         K key = entry.key;
         if (key != null) {
-            evicted.evicted(key, entry.value);
+            evicted.evicted(key, entry.value, cause);
         }
     }
 
@@ -384,7 +386,7 @@ public class CacheLIRS<K, V> implements
     @Override
     public void invalidate(Object key) {
         int hash = getHash(key);
-        getSegment(hash).invalidate(key, hash);
+        getSegment(hash).invalidate(key, hash, RemovalCause.EXPLICIT);
     }
     
     /**
@@ -618,7 +620,7 @@ public class CacheLIRS<K, V> implements
         for (Segment<K, V> s : segments) {
             synchronized (s) {
                 if (evicted != null) {
-                    s.evictedAll();
+                    s.evictedAll(RemovalCause.EXPLICIT);
                 }
                 s.clear();
             }
@@ -775,19 +777,19 @@ public class CacheLIRS<K, V> implements
             clear();
         }
 
-        public void evictedAll() {
+        public void evictedAll(RemovalCause cause) {
             for (Entry<K, V> e = stack.stackNext; e != stack; e = e.stackNext) {
                 if (e.value != null) {
-                    cache.evicted(e);
+                    cache.evicted(e, cause);
                 }
             }
             for (Entry<K, V> e = queue.queueNext; e != queue; e = e.queueNext) {
                 if (e.stackNext == null) {
-                    cache.evicted(e);
+                    cache.evicted(e, cause);
                 }
             }
             for (Entry<K, V> e = queue2.queueNext; e != queue2; e = e.queueNext) {
-                cache.evicted(e);
+                cache.evicted(e, cause);
             }
         }
 
@@ -1043,7 +1045,7 @@ public class CacheLIRS<K, V> implements
         synchronized boolean remove(Object key, int hash, Object value) {
             V old = get(key, hash);
             if (old != null && old.equals(value)) {
-                invalidate(key, hash);
+                invalidate(key, hash, RemovalCause.EXPLICIT);
                 return true;
             }
             return false;
@@ -1052,7 +1054,7 @@ public class CacheLIRS<K, V> implements
         synchronized V remove(Object key, int hash) {
             V old = get(key, hash);
             // even if old is null, there might still be a cold entry
-            invalidate(key, hash);
+            invalidate(key, hash, RemovalCause.EXPLICIT);
             return old;
         }
 
@@ -1112,7 +1114,7 @@ public class CacheLIRS<K, V> implements
                 old = null;
             } else {
                 old = e.value;
-                invalidate(key, hash);
+                invalidate(key, hash, RemovalCause.REPLACED);
             }
             e = new Entry<K, V>();
             e.key = key;
@@ -1141,7 +1143,7 @@ public class CacheLIRS<K, V> implements
          * @param key the key (may not be null)
          * @param hash the hash
          */
-        synchronized void invalidate(Object key, int hash) {
+        synchronized void invalidate(Object key, int hash, RemovalCause cause) {
             Entry<K, V>[] array = entries;
             int mask = array.length - 1;            
             int index = hash & mask;
@@ -1181,7 +1183,7 @@ public class CacheLIRS<K, V> implements
                 removeFromQueue(e);
             }
             pruneStack();
-            cache.evicted(e);
+            cache.evicted(e, cause);
         }
 
         /**
@@ -1209,7 +1211,7 @@ public class CacheLIRS<K, V> implements
                 usedMemory -= e.memory;
                 evictionCount++;
                 removeFromQueue(e);
-                cache.evicted(e);
+                cache.evicted(e, RemovalCause.SIZE);
                 e.value = null;
                 e.memory = 0;
                 addToQueue(queue2, e);
@@ -1217,7 +1219,7 @@ public class CacheLIRS<K, V> implements
                 while (queue2Size + queue2Size > stackSize) {
                     e = queue2.queuePrev;
                     int hash = getHash(e.key);
-                    invalidate(e.key, hash);
+                    invalidate(e.key, hash, RemovalCause.SIZE);
                 }
             }
         }

Modified: jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/cache/CacheTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/cache/CacheTest.java?rev=1755491&r1=1755490&r2=1755491&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/cache/CacheTest.java (original)
+++ jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/cache/CacheTest.java Mon Aug  8 10:35:39 2016
@@ -26,9 +26,11 @@ import static org.junit.Assert.assertNul
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Random;
 import java.util.Set;
@@ -40,6 +42,7 @@ import org.apache.jackrabbit.oak.cache.C
 import org.junit.Test;
 
 import com.google.common.cache.CacheLoader;
+import com.google.common.cache.RemovalCause;
 import com.google.common.cache.Weigher;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.SettableFuture;
@@ -693,12 +696,13 @@ public class CacheTest {
                 .maximumSize(100)
                 .evictionCallback(new EvictionCallback<String, Integer>() {
                     @Override
-                    public void evicted(String key, Integer value) {
+                    public void evicted(String key, Integer value, RemovalCause cause) {
                         evictedKeys.add(key);
                         if (value != null) {
                             assertEquals(key, valueOf(value));
                             evictedValues.add(value);
                         }
+                        assertTrue(cause == RemovalCause.SIZE || cause == RemovalCause.EXPLICIT);
                     }
                 })
                 .build();
@@ -718,6 +722,69 @@ public class CacheTest {
     }
     
     @Test
+    public void evictionCallbackCause() {
+        final Map<String, RemovalCause> causes = new HashMap<String, RemovalCause>();
+
+        CacheLIRS<String, Integer> cache = CacheLIRS.<String, Integer> newBuilder().maximumSize(100)
+                .evictionCallback(new EvictionCallback<String, Integer>() {
+                    @Override
+                    public void evicted(String key, Integer value, RemovalCause cause) {
+                        if (key.startsWith("ignore-")) {
+                            return;
+                        }
+                        causes.put(key, cause);
+                    }
+                }).build();
+
+        cache.put("k1", 1);
+        cache.remove("k1");
+        assertEquals(RemovalCause.EXPLICIT, causes.remove("k1"));
+
+        cache.put("k6", 1);
+        cache.remove("k6", 1);
+        assertEquals(RemovalCause.EXPLICIT, causes.remove("k6"));
+
+        cache.put("k2", 1);
+        cache.invalidate("k2");
+        assertEquals(RemovalCause.EXPLICIT, causes.remove("k2"));
+
+        cache.put("k3", 1);
+        cache.invalidateAll();
+        assertEquals(RemovalCause.EXPLICIT, causes.remove("k3"));
+
+        cache.put("k4", 1);
+        cache.put("k5", 1);
+        cache.invalidateAll(Arrays.asList("k4", "k5"));
+        assertEquals(RemovalCause.EXPLICIT, causes.remove("k4"));
+        assertEquals(RemovalCause.EXPLICIT, causes.remove("k5"));
+
+        cache.put("k7", 1);
+        cache.clear();
+        assertEquals(RemovalCause.EXPLICIT, causes.remove("k7"));
+
+        cache.put("k8", 1);
+        cache.put("k8", 2);
+        assertEquals(RemovalCause.REPLACED, causes.remove("k8"));
+
+        for (int i = 0; i < 50; i++) {
+            cache.put("kk" + i, 1);
+        }
+        for (int i = 0; i < 200; i++) {
+            cache.put("ignore-" + i, Integer.MAX_VALUE);
+        }
+
+        int checkedCount = 0;
+        for (int i = 0; i < 50; i++) {
+            String key = "kk" + i;
+            if (!cache.containsKey(key)) {
+                assertEquals("Callback hasn't been called for " + key, RemovalCause.SIZE, causes.get(key));
+                checkedCount++;
+            }
+        }
+        assertTrue(checkedCount > 10);
+    }
+
+    @Test
     public void evictionCallbackRandomized() throws ExecutionException {
         final HashMap<Integer, Integer> evictedMap = new HashMap<Integer, Integer>();
         final HashSet<Integer> evictedNonResidentSet = new HashSet<Integer>();
@@ -725,7 +792,7 @@ public class CacheTest {
                 .maximumSize(10)
                 .evictionCallback(new EvictionCallback<Integer, Integer>() {
                     @Override
-                    public void evicted(Integer key, Integer value) {
+                    public void evicted(Integer key, Integer value, RemovalCause cause) {
                         if (value == null) {
                             assertTrue(evictedNonResidentSet.add(key));
                         } else {