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);
}
}