From 21d1c0e0d07d1d3758e7e9376a74da10822cdde2 Mon Sep 17 00:00:00 2001 From: Martin Ledvinka Date: Mon, 5 Oct 2020 18:27:16 +0200 Subject: [PATCH] [Enhancement #73] Working on modifications of second level cache to support plural contexts. --- .../kbss/jopa/sessions/RepositoryMap.java | 35 ++++++++---------- .../kbss/jopa/sessions/UnitOfWorkImpl.java | 4 +- .../kbss/jopa/sessions/cache/EntityCache.java | 37 ++++++++++++------- .../jopa/sessions/cache/LruCacheManager.java | 25 +++++++------ .../jopa/sessions/cache/TtlCacheManager.java | 15 +++++--- 5 files changed, 62 insertions(+), 54 deletions(-) diff --git a/jopa-impl/src/main/java/cz/cvut/kbss/jopa/sessions/RepositoryMap.java b/jopa-impl/src/main/java/cz/cvut/kbss/jopa/sessions/RepositoryMap.java index c13a47565..eab0a37d4 100644 --- a/jopa-impl/src/main/java/cz/cvut/kbss/jopa/sessions/RepositoryMap.java +++ b/jopa-impl/src/main/java/cz/cvut/kbss/jopa/sessions/RepositoryMap.java @@ -1,31 +1,28 @@ /** * Copyright (C) 2020 Czech Technical University in Prague - * - * This program is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. You should have received a copy of the GNU General Public License - * along with this program. If not, see . + *

+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. + *

+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. You should have received a copy of the GNU General Public License along with this program. If not, see + * . */ package cz.cvut.kbss.jopa.sessions; +import cz.cvut.kbss.jopa.model.descriptors.Descriptor; + import java.net.URI; import java.util.HashMap; import java.util.IdentityHashMap; import java.util.Map; - -import cz.cvut.kbss.jopa.model.descriptors.Descriptor; +import java.util.Set; final class RepositoryMap { - private static final URI DEFAULT_CONTEXT = URI.create("http://defaultContext"); - - private final Map> origsToClones = new HashMap<>(); + private final Map, Map> origsToClones = new HashMap<>(); private Map entityDescriptors; RepositoryMap() { @@ -91,13 +88,11 @@ Descriptor getEntityDescriptor(Object entity) { void clear() { origsToClones.values().forEach(Map::clear); - if (entityDescriptors != null) { - initDescriptors(); - } + initDescriptors(); } private Map getMap(Descriptor descriptor) { - final URI ctx = descriptor.getContext() != null ? descriptor.getContext() : DEFAULT_CONTEXT; + final Set ctx = descriptor.getContexts(); Map entities; if (!origsToClones.containsKey(ctx)) { entities = new IdentityHashMap<>(); diff --git a/jopa-impl/src/main/java/cz/cvut/kbss/jopa/sessions/UnitOfWorkImpl.java b/jopa-impl/src/main/java/cz/cvut/kbss/jopa/sessions/UnitOfWorkImpl.java index a45655f99..e5ce686aa 100644 --- a/jopa-impl/src/main/java/cz/cvut/kbss/jopa/sessions/UnitOfWorkImpl.java +++ b/jopa-impl/src/main/java/cz/cvut/kbss/jopa/sessions/UnitOfWorkImpl.java @@ -562,7 +562,7 @@ private void mergeChangesIntoParent() { private void evictPossiblyUpdatedReferencesFromCache() { cloneToOriginals.forEach((clone, orig) -> { if (orig == null && !deletedObjects.containsKey(clone)) { - removeObjectFromCache(clone, getDescriptor(clone).getContext()); + removeObjectFromCache(clone, getDescriptor(clone).getSingleContext().orElse(null)); } }); } @@ -618,7 +618,7 @@ private T mergeDetachedInternal(T entity, Descriptor descriptor) { throw e; } if (cacheManager.contains(et.getJavaType(), idUri, descriptor)) { - cacheManager.evict(et.getJavaType(), idUri, descriptor.getContext()); + cacheManager.evict(et.getJavaType(), idUri, descriptor.getSingleContext().orElse(null)); } setHasChanges(); checkForIndirectObjects(clone); diff --git a/jopa-impl/src/main/java/cz/cvut/kbss/jopa/sessions/cache/EntityCache.java b/jopa-impl/src/main/java/cz/cvut/kbss/jopa/sessions/cache/EntityCache.java index c34043785..6a2c9e039 100644 --- a/jopa-impl/src/main/java/cz/cvut/kbss/jopa/sessions/cache/EntityCache.java +++ b/jopa-impl/src/main/java/cz/cvut/kbss/jopa/sessions/cache/EntityCache.java @@ -17,10 +17,7 @@ import cz.cvut.kbss.jopa.model.descriptors.Descriptor; import java.net.URI; -import java.util.Collections; -import java.util.HashMap; -import java.util.IdentityHashMap; -import java.util.Map; +import java.util.*; class EntityCache { @@ -41,9 +38,12 @@ class EntityCache { void put(Object identifier, Object entity, Descriptor descriptor) { assert identifier != null; assert entity != null; + if (!isCacheable(descriptor)) { + return; + } final Class cls = entity.getClass(); - final URI ctx = descriptor.getContext() != null ? descriptor.getContext() : defaultContext; + final URI ctx = descriptor.getSingleContext().orElse(defaultContext); Map, Object>> ctxMap; if (!repoCache.containsKey(ctx)) { @@ -66,12 +66,15 @@ void put(Object identifier, Object entity, Descriptor descriptor) { descriptors.put(entity, descriptor); } + boolean isCacheable(Descriptor descriptor) { + return descriptor.getContexts().size() <= 1; + } + T get(Class cls, Object identifier, Descriptor descriptor) { assert cls != null; assert identifier != null; - final URI ctx = descriptor.getContext() != null ? descriptor.getContext() : defaultContext; - final Map, Object> m = getMapForId(ctx, identifier); + final Map, Object> m = getMapForId(descriptor.getContexts(), identifier); final Object result = m.get(cls); return result != null && descriptors.get(result).equals(descriptor) ? cls.cast(result) : null; @@ -82,14 +85,20 @@ boolean contains(Class cls, Object identifier, Descriptor descriptor) { assert identifier != null; assert descriptor != null; - final Map, Object> m = getMapForId(descriptor.getContext(), identifier); - if (!m.containsKey(cls)) { - return false; + final Set contexts = descriptor.getContexts().isEmpty() ? Collections.singleton(defaultContext) : descriptor.getContexts(); + for (URI ctx : contexts) { + final Map, Object> m = getMapForId(ctx, identifier); + if (!m.containsKey(cls)) { + continue; + } + final Object result = m.get(cls); + assert descriptors.containsKey(result); + + if (descriptors.get(result).equals(descriptor)) { + return true; + } } - final Object result = m.get(cls); - assert descriptors.containsKey(result); - - return descriptors.get(result).equals(descriptor); + return false; } void evict(Class cls, Object identifier, URI context) { diff --git a/jopa-impl/src/main/java/cz/cvut/kbss/jopa/sessions/cache/LruCacheManager.java b/jopa-impl/src/main/java/cz/cvut/kbss/jopa/sessions/cache/LruCacheManager.java index cc5974165..a1dfb2fb0 100644 --- a/jopa-impl/src/main/java/cz/cvut/kbss/jopa/sessions/cache/LruCacheManager.java +++ b/jopa-impl/src/main/java/cz/cvut/kbss/jopa/sessions/cache/LruCacheManager.java @@ -1,16 +1,14 @@ /** * Copyright (C) 2020 Czech Technical University in Prague - * - * This program is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. You should have received a copy of the GNU General Public License - * along with this program. If not, see . + *

+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. + *

+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. You should have received a copy of the GNU General Public License along with this program. If not, see + * . */ package cz.cvut.kbss.jopa.sessions.cache; @@ -215,7 +213,10 @@ public void accept(LruCache.CacheNode cacheNode) { @Override void put(Object identifier, Object entity, Descriptor descriptor) { - final URI ctx = descriptor.getContext() != null ? descriptor.getContext() : defaultContext; + if (!isCacheable(descriptor)) { + return; + } + final URI ctx = descriptor.getSingleContext().orElse(defaultContext); super.put(identifier, entity, descriptor); cache.put(new LruCache.CacheNode(ctx, entity.getClass(), identifier), NULL_VALUE); } diff --git a/jopa-impl/src/main/java/cz/cvut/kbss/jopa/sessions/cache/TtlCacheManager.java b/jopa-impl/src/main/java/cz/cvut/kbss/jopa/sessions/cache/TtlCacheManager.java index bc89b535d..6f3462c36 100644 --- a/jopa-impl/src/main/java/cz/cvut/kbss/jopa/sessions/cache/TtlCacheManager.java +++ b/jopa-impl/src/main/java/cz/cvut/kbss/jopa/sessions/cache/TtlCacheManager.java @@ -285,7 +285,7 @@ public void run() { final List toEvict = new ArrayList<>(); // Mark the objects for eviction (can't evict them now, it would // cause ConcurrentModificationException) - for (Entry e : cache.ttls.entrySet()) { + for (Entry e : cache.ttl.entrySet()) { final long lm = e.getValue(); if (lm + TtlCacheManager.this.timeToLive < currentTime) { toEvict.add(e.getKey()); @@ -302,12 +302,15 @@ public void run() { private static final class TtlCache extends EntityCache { - private final Map ttls = new HashMap<>(); + private final Map ttl = new HashMap<>(); @Override void put(Object identifier, Object entity, Descriptor descriptor) { + if (!isCacheable(descriptor)) { + return; + } super.put(identifier, entity, descriptor); - final URI ctx = descriptor.getContext() != null ? descriptor.getContext() : defaultContext; + final URI ctx = descriptor.getSingleContext().orElse(defaultContext); updateTimeToLive(ctx); } @@ -327,14 +330,14 @@ T get(Class cls, Object identifier, Descriptor descriptor) { private void updateTimeToLive(URI context) { assert context != null; - ttls.put(context, System.currentTimeMillis()); + ttl.put(context, System.currentTimeMillis()); } @Override void evict(URI context) { final URI ctx = context != null ? context : defaultContext; super.evict(ctx); - ttls.remove(context); + ttl.remove(context); } @Override @@ -348,7 +351,7 @@ void evict(Class cls) { } } if (m.isEmpty()) { - ttls.remove(e.getKey()); + ttl.remove(e.getKey()); } } }