Repository: cayenne Updated Branches: refs/heads/master 5e9f0e0f6 -> 67225b387
New implementation of MapQueryCache plus new method in QueryCache interface for type-safe deletion of cache groups. Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/67225b38 Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/67225b38 Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/67225b38 Branch: refs/heads/master Commit: 67225b387a3e5e92a8f81a5059bdd9d27a6c0ac8 Parents: 5e9f0e0 Author: Nikita Timofeev <stari...@gmail.com> Authored: Mon Apr 3 15:17:57 2017 +0300 Committer: Nikita Timofeev <stari...@gmail.com> Committed: Mon Apr 3 15:17:57 2017 +0300 ---------------------------------------------------------------------- .../apache/cayenne/jcache/JCacheQueryCache.java | 8 ++ .../apache/cayenne/cache/EhCacheQueryCache.java | 4 + .../org/apache/cayenne/cache/MapQueryCache.java | 116 ++++++++++++------- .../apache/cayenne/cache/NestedQueryCache.java | 5 + .../org/apache/cayenne/cache/OSQueryCache.java | 4 + .../org/apache/cayenne/cache/QueryCache.java | 9 ++ .../apache/cayenne/cache/MockQueryCache.java | 4 + 7 files changed, 108 insertions(+), 42 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cayenne/blob/67225b38/cayenne-jcache/src/main/java/org/apache/cayenne/jcache/JCacheQueryCache.java ---------------------------------------------------------------------- diff --git a/cayenne-jcache/src/main/java/org/apache/cayenne/jcache/JCacheQueryCache.java b/cayenne-jcache/src/main/java/org/apache/cayenne/jcache/JCacheQueryCache.java index d10a83c..a91efc4 100644 --- a/cayenne-jcache/src/main/java/org/apache/cayenne/jcache/JCacheQueryCache.java +++ b/cayenne-jcache/src/main/java/org/apache/cayenne/jcache/JCacheQueryCache.java @@ -92,6 +92,14 @@ public class JCacheQueryCache implements QueryCache { } @Override + public void removeGroup(String groupKey, Class<?> keyType, Class<?> valueType) { + Cache cache = cacheManager.getCache(groupKey, keyType, valueType); + if (cache != null) { + cache.clear(); + } + } + + @Override public void clear() { for (String name : seenCacheNames) { getCache(name).clear(); http://git-wip-us.apache.org/repos/asf/cayenne/blob/67225b38/cayenne-server/src/main/java/org/apache/cayenne/cache/EhCacheQueryCache.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/cache/EhCacheQueryCache.java b/cayenne-server/src/main/java/org/apache/cayenne/cache/EhCacheQueryCache.java index 454e5fe..a3137a8 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/cache/EhCacheQueryCache.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/cache/EhCacheQueryCache.java @@ -172,6 +172,10 @@ public class EhCacheQueryCache implements QueryCache { } } + public void removeGroup(String groupKey, Class<?> keyType, Class<?> valueType) { + removeGroup(groupKey); + } + public void clear() { cacheManager.removalAll(); } http://git-wip-us.apache.org/repos/asf/cayenne/blob/67225b38/cayenne-server/src/main/java/org/apache/cayenne/cache/MapQueryCache.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/cache/MapQueryCache.java b/cayenne-server/src/main/java/org/apache/cayenne/cache/MapQueryCache.java index 3c60e1e..ea48311 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/cache/MapQueryCache.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/cache/MapQueryCache.java @@ -19,9 +19,9 @@ package org.apache.cayenne.cache; import java.io.Serializable; -import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import org.apache.cayenne.CayenneRuntimeException; import org.apache.cayenne.query.QueryMetadata; @@ -35,32 +35,32 @@ import org.apache.commons.collections.map.LRUMap; */ public class MapQueryCache implements QueryCache, Serializable { - public static final int DEFAULT_CACHE_SIZE = 2000; + public static final int DEFAULT_CACHE_SIZE = 1000; - protected Map<String, CacheEntry> map; + static final String DEFAULT_CACHE_NAME = "cayenne.default.cache"; + + protected final Map<String, Map<String, List<?>>> cacheGroups; + + private int maxSize; public MapQueryCache() { this(DEFAULT_CACHE_SIZE); } - @SuppressWarnings("unchecked") public MapQueryCache(int maxSize) { - this.map = new LRUMap(maxSize); + this.cacheGroups = new ConcurrentHashMap<>(); + this.maxSize = maxSize; } - @SuppressWarnings("rawtypes") public List get(QueryMetadata metadata) { String key = metadata.getCacheKey(); if (key == null) { return null; } - - CacheEntry entry; - synchronized (this) { - entry = map.get(key); + Map<String, List<?>> map = createIfAbsent(metadata); + synchronized (map) { + return map.get(key); } - - return (entry != null) ? entry.list : null; } /** @@ -85,24 +85,25 @@ public class MapQueryCache implements QueryCache, Serializable { return result; } - @SuppressWarnings("rawtypes") public void put(QueryMetadata metadata, List results) { String key = metadata.getCacheKey(); - if (key != null) { - - CacheEntry entry = new CacheEntry(); - entry.list = results; - entry.cacheGroup = metadata.getCacheGroup(); + if (key == null) { + return; + } - synchronized (this) { - map.put(key, entry); - } + Map<String, List<?>> map = createIfAbsent(metadata); + synchronized (map) { + map.put(key, results); } } public void remove(String key) { - if (key != null) { - synchronized (this) { + if (key == null) { + return; + } + + for(Map<String, List<?>> map : cacheGroups.values()) { + synchronized (map) { map.remove(key); } } @@ -110,33 +111,64 @@ public class MapQueryCache implements QueryCache, Serializable { public void removeGroup(String groupKey) { if (groupKey != null) { - synchronized (this) { - Iterator<CacheEntry> it = map.values().iterator(); - while (it.hasNext()) { - CacheEntry entry = it.next(); - if (entry.cacheGroup != null) { - if (groupKey.equals(entry.cacheGroup)) { - it.remove(); - break; - } - } - } - } + cacheGroups.remove(groupKey); } } + public void removeGroup(String groupKey, Class<?> keyType, Class<?> valueType) { + removeGroup(groupKey); + } + public void clear() { - synchronized (this) { - map.clear(); - } + cacheGroups.clear(); } public int size() { - return map.size(); + int size = 0; + for(Map<String, List<?>> map : cacheGroups.values()) { + synchronized (map) { + size += map.size(); + } + } + return size; } - final static class CacheEntry implements Serializable { - List<?> list; - String cacheGroup; + protected Map<String, List<?>> createIfAbsent(QueryMetadata metadata) { + return createIfAbsent(cacheName(metadata)); + } + + protected Map<String, List<?>> createIfAbsent(String cacheName) { + Map<String, List<?>> cache = getCache(cacheName); + if (cache == null) { + cache = createCache(cacheName); + } + + return cache; + } + + @SuppressWarnings("unchecked") + protected synchronized Map<String, List<?>> createCache(String cacheName) { + Map<String, List<?>> map = getCache(cacheName); + if(map != null) { + return map; + } + map = new LRUMap(maxSize); + cacheGroups.put(cacheName, map); + return map; + } + + protected Map<String, List<?>> getCache(String name) { + return cacheGroups.get(name); + } + + protected String cacheName(QueryMetadata metadata) { + + String cacheGroup = metadata.getCacheGroup(); + if (cacheGroup != null) { + return cacheGroup; + } + + // no explicit cache group + return DEFAULT_CACHE_NAME; } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/67225b38/cayenne-server/src/main/java/org/apache/cayenne/cache/NestedQueryCache.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/cache/NestedQueryCache.java b/cayenne-server/src/main/java/org/apache/cayenne/cache/NestedQueryCache.java index 2a465eb..8b96057 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/cache/NestedQueryCache.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/cache/NestedQueryCache.java @@ -109,6 +109,11 @@ public class NestedQueryCache implements QueryCache { delegate.removeGroup(groupKey); } + @Override + public void removeGroup(String groupKey, Class<?> keyType, Class<?> valueType) { + delegate.removeGroup(groupKey, keyType, valueType); + } + /** * Returns a shared cache size. * @see QueryCache#size() http://git-wip-us.apache.org/repos/asf/cayenne/blob/67225b38/cayenne-server/src/main/java/org/apache/cayenne/cache/OSQueryCache.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/cache/OSQueryCache.java b/cayenne-server/src/main/java/org/apache/cayenne/cache/OSQueryCache.java index 67777f3..70e1bb0 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/cache/OSQueryCache.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/cache/OSQueryCache.java @@ -337,6 +337,10 @@ public class OSQueryCache implements QueryCache { } } + public void removeGroup(String groupKey, Class<?> keyType, Class<?> valueType) { + removeGroup(groupKey); + } + public void clear() { osCache.flushAll(); } http://git-wip-us.apache.org/repos/asf/cayenne/blob/67225b38/cayenne-server/src/main/java/org/apache/cayenne/cache/QueryCache.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/cache/QueryCache.java b/cayenne-server/src/main/java/org/apache/cayenne/cache/QueryCache.java index b615b77..fb21b83 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/cache/QueryCache.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/cache/QueryCache.java @@ -67,6 +67,15 @@ public interface QueryCache { void removeGroup(String groupKey); /** + * Removes a group of entries identified by group key. + * Can be used if cache provider supports strictly typed caches. + * @see QueryCache#removeGroup(String) + * + * @since 4.0 + */ + void removeGroup(String groupKey, Class<?> keyType, Class<?> valueType); + + /** * Clears all cache entries. * * @deprecated since 4.0. Please use implementation specific methods to perform cache management tasks. http://git-wip-us.apache.org/repos/asf/cayenne/blob/67225b38/cayenne-server/src/test/java/org/apache/cayenne/cache/MockQueryCache.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/cache/MockQueryCache.java b/cayenne-server/src/test/java/org/apache/cayenne/cache/MockQueryCache.java index b0b0a55..0705a60 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/cache/MockQueryCache.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/cache/MockQueryCache.java @@ -44,6 +44,10 @@ public class MockQueryCache implements QueryCache { public void removeGroup(String groupKey) { } + public void removeGroup(String groupKey, Class<?> keyType, Class<?> valueType) { + removeGroup(groupKey); + } + public int size() { return 0; }