You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2017/12/12 01:35:27 UTC

groovy git commit: Minor refactoring and add test for CommonCache

Repository: groovy
Updated Branches:
  refs/heads/master 6d0c66773 -> 9f7783de7


Minor refactoring and add test for CommonCache


Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/9f7783de
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/9f7783de
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/9f7783de

Branch: refs/heads/master
Commit: 9f7783de7803c0b856a37c2a0510e15be3c87f67
Parents: 6d0c667
Author: sunlan <su...@apache.org>
Authored: Tue Dec 12 09:35:07 2017 +0800
Committer: sunlan <su...@apache.org>
Committed: Tue Dec 12 09:35:21 2017 +0800

----------------------------------------------------------------------
 .../groovy/runtime/memoize/CommonCache.java     |  28 ++-
 .../runtime/memoize/ConcurrentCommonCache.java  |  11 +-
 .../groovy/runtime/memoize/EvictableCache.java  |  15 ++
 .../groovy/runtime/memoize/CommonCacheTest.java | 204 +++++++++++++++++++
 .../memoize/ConcurrentCommonCacheTest.java      |  28 +++
 .../java/groovy/json/internal/SimpleCache.java  |   2 +-
 6 files changed, 272 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/9f7783de/src/main/org/codehaus/groovy/runtime/memoize/CommonCache.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/runtime/memoize/CommonCache.java b/src/main/org/codehaus/groovy/runtime/memoize/CommonCache.java
index 8070a50..e698535 100644
--- a/src/main/org/codehaus/groovy/runtime/memoize/CommonCache.java
+++ b/src/main/org/codehaus/groovy/runtime/memoize/CommonCache.java
@@ -38,6 +38,14 @@ import java.util.Set;
  * @since 2.5.0
  */
 public class CommonCache<K, V> implements EvictableCache<K, V> {
+    /**
+     * The default load factor
+     */
+    public static final float DEFAULT_LOAD_FACTOR = 0.75f;
+    /**
+     * The default initial capacity
+     */
+    public static final int DEFAULT_INITIAL_CAPACITY = 16;
     private final Map<K, V> map;
 
     /**
@@ -49,12 +57,14 @@ public class CommonCache<K, V> implements EvictableCache<K, V> {
 
     /**
      * Constructs a cache with limited size
-     * @param initialCapacity initial capacity of the LRU cache
-     * @param maxSize max size of the LRU cache
-     * @param accessOrder the ordering mode - <tt>true</tt> for access-order, <tt>false</tt> for insertion-order, see the parameter accessOrder of {@link LinkedHashMap#LinkedHashMap(int, float, boolean)}
+     * @param initialCapacity initial capacity of the cache
+     * @param maxSize max size of the cache
+     * @param evictionStrategy LRU or FIFO, see {@link org.codehaus.groovy.runtime.memoize.EvictableCache.EvictionStrategy}
      */
-    public CommonCache(final int initialCapacity, final int maxSize, final boolean accessOrder) {
-        this(new LinkedHashMap<K, V>(initialCapacity, 0.75f, accessOrder) {
+    public CommonCache(final int initialCapacity, final int maxSize, final EvictionStrategy evictionStrategy) {
+        this(new LinkedHashMap<K, V>(initialCapacity, DEFAULT_LOAD_FACTOR, EvictionStrategy.LRU == evictionStrategy) {
+            private static final long serialVersionUID = -8012450791479726621L;
+
             @Override
             protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
                 return size() > maxSize;
@@ -68,17 +78,17 @@ public class CommonCache<K, V> implements EvictableCache<K, V> {
      * @param initialCapacity initial capacity of the LRU cache
      * @param maxSize max size of the LRU cache
      */
-    public CommonCache(final int initialCapacity, final int maxSize) {
-        this(initialCapacity, maxSize, true);
+    public CommonCache(int initialCapacity, int maxSize) {
+        this(initialCapacity, maxSize, EvictionStrategy.LRU);
     }
 
     /**
-     * Constructs a LRU cache with the default initial capacity(16)
+     * Constructs a LRU cache with the default initial capacity
      * @param maxSize max size of the LRU cache
      * @see #CommonCache(int, int)
      */
     public CommonCache(final int maxSize) {
-        this(16, maxSize);
+        this(DEFAULT_INITIAL_CAPACITY, maxSize);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/groovy/blob/9f7783de/src/main/org/codehaus/groovy/runtime/memoize/ConcurrentCommonCache.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/runtime/memoize/ConcurrentCommonCache.java b/src/main/org/codehaus/groovy/runtime/memoize/ConcurrentCommonCache.java
index 81345d9..3854b12 100644
--- a/src/main/org/codehaus/groovy/runtime/memoize/ConcurrentCommonCache.java
+++ b/src/main/org/codehaus/groovy/runtime/memoize/ConcurrentCommonCache.java
@@ -19,7 +19,6 @@
 package org.codehaus.groovy.runtime.memoize;
 
 import java.util.Collection;
-import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -45,12 +44,12 @@ public class ConcurrentCommonCache<K, V> extends CommonCache<K, V> {
 
     /**
      * Constructs a cache with limited size
-     * @param initialCapacity initial capacity of the LRU cache
-     * @param maxSize max size of the LRU cache
-     * @param accessOrder the ordering mode - <tt>true</tt> for access-order, <tt>false</tt> for insertion-order, see the parameter accessOrder of {@link LinkedHashMap#LinkedHashMap(int, float, boolean)}
+     * @param initialCapacity initial capacity of the cache
+     * @param maxSize max size of the cache
+     * @param evictionStrategy LRU or FIFO, see {@link org.codehaus.groovy.runtime.memoize.EvictableCache.EvictionStrategy}
      */
-    public ConcurrentCommonCache(int initialCapacity, int maxSize, boolean accessOrder) {
-        super(initialCapacity, maxSize, accessOrder);
+    public ConcurrentCommonCache(int initialCapacity, int maxSize, EvictionStrategy evictionStrategy) {
+        super(initialCapacity, maxSize, evictionStrategy);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/groovy/blob/9f7783de/src/main/org/codehaus/groovy/runtime/memoize/EvictableCache.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/runtime/memoize/EvictableCache.java b/src/main/org/codehaus/groovy/runtime/memoize/EvictableCache.java
index 43bc8bd..67bb794 100644
--- a/src/main/org/codehaus/groovy/runtime/memoize/EvictableCache.java
+++ b/src/main/org/codehaus/groovy/runtime/memoize/EvictableCache.java
@@ -87,4 +87,19 @@ public interface EvictableCache<K, V> extends MemoizeCache<K, V> {
          */
         V provide(K key);
     }
+
+    /**
+     * Represents a eviction strategy for the cache with limited size
+     */
+    enum EvictionStrategy {
+        /**
+         * The oldest entry(i.e. the Less Recently Used entry) will be evicted
+         */
+        LRU,
+
+        /**
+         * Entries are evicted in the same order as they come in
+         */
+        FIFO
+    }
 }

http://git-wip-us.apache.org/repos/asf/groovy/blob/9f7783de/src/test/org/codehaus/groovy/runtime/memoize/CommonCacheTest.java
----------------------------------------------------------------------
diff --git a/src/test/org/codehaus/groovy/runtime/memoize/CommonCacheTest.java b/src/test/org/codehaus/groovy/runtime/memoize/CommonCacheTest.java
new file mode 100644
index 0000000..2b32c4a
--- /dev/null
+++ b/src/test/org/codehaus/groovy/runtime/memoize/CommonCacheTest.java
@@ -0,0 +1,204 @@
+/*
+ *  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.codehaus.groovy.runtime.memoize;
+
+import org.apache.groovy.util.Maps;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+
+public class CommonCacheTest {
+    @Test
+    public void get() {
+        CommonCache<String, String> sc =
+                new CommonCache<>(
+                        new LinkedHashMap<>(
+                                Maps.of("name", "Daniel",
+                                        "gender", "Male",
+                                        "city", "Shanghai")
+                        )
+                );
+
+        Assert.assertEquals("Daniel", sc.get("name"));
+        Assert.assertEquals("Male", sc.get("gender"));
+        Assert.assertEquals("Shanghai", sc.get("city"));
+        Assert.assertNull(sc.get("foo"));
+    }
+
+    @Test
+    public void put() {
+        CommonCache<String, String> sc = new CommonCache<>();
+
+        Assert.assertNull(sc.put("name", "Daniel"));
+        Assert.assertEquals("Daniel", sc.get("name"));
+
+        Assert.assertEquals("Daniel", sc.put("name", "sunlan"));
+        Assert.assertEquals("sunlan", sc.get("name"));
+    }
+
+    @Test
+    public void getAndPut() {
+        CommonCache<String, String> sc = new CommonCache<>();
+
+        EvictableCache.ValueProvider vp =
+                new EvictableCache.ValueProvider<String, String>() {
+                    @Override
+                    public String provide(String key) {
+                        return "Chinese";
+                    }
+                };
+
+        Assert.assertEquals("Chinese", sc.getAndPut("language", vp,false));
+        Assert.assertNull(sc.get("language"));
+
+        Assert.assertEquals("Chinese", sc.getAndPut("language", vp));
+        Assert.assertEquals("Chinese", sc.get("language"));
+    }
+
+    @Test
+    public void values() {
+        CommonCache<String, String> sc =
+                new CommonCache<>(
+                        new LinkedHashMap<>(
+                                Maps.of("name", "Daniel",
+                                        "gender", "Male",
+                                        "city", "Shanghai")
+                        )
+                );
+
+        Assert.assertArrayEquals(new String[] {"Daniel", "Male", "Shanghai"}, sc.values().toArray(new String[0]));
+    }
+
+    @Test
+    public void keys() {
+        CommonCache<String, String> sc =
+                new CommonCache<>(
+                        new LinkedHashMap<>(
+                                Maps.of("name", "Daniel",
+                                        "gender", "Male",
+                                        "city", "Shanghai")
+                        )
+                );
+
+        Assert.assertArrayEquals(new String[] {"name", "gender", "city"}, sc.keys().toArray(new String[0]));
+    }
+
+    @Test
+    public void containsKey() {
+        CommonCache<String, String> sc =
+                new CommonCache<>(
+                        new LinkedHashMap<>(
+                                Maps.of("name", "Daniel",
+                                        "gender", "Male",
+                                        "city", "Shanghai")
+                        )
+                );
+
+        Assert.assertTrue(sc.containsKey("name"));
+    }
+
+    @Test
+    public void size() {
+        CommonCache<String, String> sc =
+                new CommonCache<>(
+                        new LinkedHashMap<>(
+                                Maps.of("name", "Daniel",
+                                        "gender", "Male",
+                                        "city", "Shanghai")
+                        )
+                );
+
+        Assert.assertEquals(3, sc.size());
+    }
+
+    @Test
+    public void remove() {
+        CommonCache<String, String> sc =
+                new CommonCache<>(
+                        new HashMap<>(
+                                Maps.of("name", "Daniel",
+                                        "gender", "Male",
+                                        "city", "Shanghai")
+                        )
+                );
+
+        Assert.assertEquals("Shanghai", sc.remove("city"));
+        Assert.assertNull(sc.get("city"));
+    }
+
+    @Test
+    public void clear() {
+        CommonCache<String, String> sc =
+                new CommonCache<>(
+                        new LinkedHashMap<>(
+                                Maps.of("name", "Daniel",
+                                        "gender", "Male",
+                                        "city", "Shanghai")
+                        )
+                );
+
+        Assert.assertArrayEquals(new String[] {"Daniel", "Male", "Shanghai"}, sc.values().toArray(new String[0]));
+    }
+
+    @Test
+    public void cleanUpNullReferences() {
+        CommonCache<String, String> sc =
+                new CommonCache<>(
+                        new LinkedHashMap<>(
+                                Maps.of("name", "Daniel",
+                                        "gender", "Male",
+                                        "city", null)
+                        )
+                );
+
+        sc.cleanUpNullReferences();
+        Assert.assertArrayEquals(new String[] {"Daniel", "Male"}, sc.values().toArray(new String[0]));
+    }
+
+    @Test
+    public void testLruCache() {
+        CommonCache<String, String> sc = new CommonCache<String, String>(3);
+        sc.put("a", "1");
+        sc.put("b", "2");
+        sc.put("c", "3");
+        sc.put("a", "4");
+        sc.put("d", "5");
+        Assert.assertArrayEquals(new String[] {"c", "a", "d"}, sc.keys().toArray(new String[0]));
+        Assert.assertEquals("3", sc.get("c"));
+        Assert.assertEquals("4", sc.get("a"));
+        Assert.assertEquals("5", sc.get("d"));
+    }
+
+    @Test
+    public void testFifoCache() {
+        CommonCache<String, String> sc = new CommonCache<String, String>(3, 3, EvictableCache.EvictionStrategy.FIFO);
+        sc.put("a", "1");
+        sc.put("b", "2");
+        sc.put("c", "3");
+        sc.put("a", "4");
+        sc.put("d", "5");
+        Assert.assertArrayEquals(new String[] {"b", "c", "d"}, sc.keys().toArray(new String[0]));
+        Assert.assertEquals("2", sc.get("b"));
+        Assert.assertEquals("3", sc.get("c"));
+        Assert.assertEquals("5", sc.get("d"));
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/9f7783de/src/test/org/codehaus/groovy/runtime/memoize/ConcurrentCommonCacheTest.java
----------------------------------------------------------------------
diff --git a/src/test/org/codehaus/groovy/runtime/memoize/ConcurrentCommonCacheTest.java b/src/test/org/codehaus/groovy/runtime/memoize/ConcurrentCommonCacheTest.java
index e78c6e2..340c286 100644
--- a/src/test/org/codehaus/groovy/runtime/memoize/ConcurrentCommonCacheTest.java
+++ b/src/test/org/codehaus/groovy/runtime/memoize/ConcurrentCommonCacheTest.java
@@ -172,4 +172,32 @@ public class ConcurrentCommonCacheTest {
         sc.cleanUpNullReferences();
         Assert.assertArrayEquals(new String[] {"Daniel", "Male"}, sc.values().toArray(new String[0]));
     }
+
+    @Test
+    public void testLruCache() {
+        ConcurrentCommonCache<String, String> sc = new ConcurrentCommonCache<String, String>(3);
+        sc.put("a", "1");
+        sc.put("b", "2");
+        sc.put("c", "3");
+        sc.put("a", "4");
+        sc.put("d", "5");
+        Assert.assertArrayEquals(new String[] {"c", "a", "d"}, sc.keys().toArray(new String[0]));
+        Assert.assertEquals("3", sc.get("c"));
+        Assert.assertEquals("4", sc.get("a"));
+        Assert.assertEquals("5", sc.get("d"));
+    }
+
+    @Test
+    public void testFifoCache() {
+        ConcurrentCommonCache<String, String> sc = new ConcurrentCommonCache<String, String>(3, 3, EvictableCache.EvictionStrategy.FIFO);
+        sc.put("a", "1");
+        sc.put("b", "2");
+        sc.put("c", "3");
+        sc.put("a", "4");
+        sc.put("d", "5");
+        Assert.assertArrayEquals(new String[] {"b", "c", "d"}, sc.keys().toArray(new String[0]));
+        Assert.assertEquals("2", sc.get("b"));
+        Assert.assertEquals("3", sc.get("c"));
+        Assert.assertEquals("5", sc.get("d"));
+    }
 }

http://git-wip-us.apache.org/repos/asf/groovy/blob/9f7783de/subprojects/groovy-json/src/main/java/groovy/json/internal/SimpleCache.java
----------------------------------------------------------------------
diff --git a/subprojects/groovy-json/src/main/java/groovy/json/internal/SimpleCache.java b/subprojects/groovy-json/src/main/java/groovy/json/internal/SimpleCache.java
index 45153d5..92bb400 100644
--- a/subprojects/groovy-json/src/main/java/groovy/json/internal/SimpleCache.java
+++ b/subprojects/groovy-json/src/main/java/groovy/json/internal/SimpleCache.java
@@ -31,7 +31,7 @@ public class SimpleCache<K, V> implements Cache<K, V> {
         if (type.equals(CacheType.LRU)) {
             cache = new CommonCache<K, V>(limit);
         } else {
-            cache = new CommonCache<K, V>(16, limit, false);
+            cache = new CommonCache<K, V>(CommonCache.DEFAULT_INITIAL_CAPACITY, limit, EvictableCache.EvictionStrategy.FIFO);
         }
     }