From fd323912677b3a193589556975302202d59c3f75 Mon Sep 17 00:00:00 2001 From: Luca Frosini Date: Thu, 5 Nov 2020 12:12:19 +0100 Subject: [PATCH] Added Context Cache --- .../contexts/ContextUtility.java | 29 +++------- .../contexts/entities/ContextManagement.java | 57 ++++++++++++++++++- .../contexts/ContextManagementTest.java | 45 +++++++++++++++ 3 files changed, 107 insertions(+), 24 deletions(-) diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/contexts/ContextUtility.java b/src/main/java/org/gcube/informationsystem/resourceregistry/contexts/ContextUtility.java index 5cf111e..5f636df 100644 --- a/src/main/java/org/gcube/informationsystem/resourceregistry/contexts/ContextUtility.java +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/contexts/ContextUtility.java @@ -12,6 +12,7 @@ import org.gcube.common.scope.api.ScopeProvider; import org.gcube.common.scope.impl.ScopeBean; import org.gcube.informationsystem.context.reference.entities.Context; import org.gcube.informationsystem.context.reference.relations.IsParentOf; +import org.gcube.informationsystem.resourceregistry.api.contexts.ContextCache; import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException; import org.gcube.informationsystem.resourceregistry.api.exceptions.context.ContextException; import org.gcube.informationsystem.resourceregistry.api.exceptions.context.ContextNotFoundException; @@ -38,7 +39,6 @@ public class ContextUtility { private static final Logger logger = LoggerFactory.getLogger(ContextUtility.class); - private Map contextUUIDs; private Map contexts; private static ContextUtility contextUtility; @@ -51,7 +51,6 @@ public class ContextUtility { } private ContextUtility() { - contextUUIDs = new HashMap<>(); contexts = new HashMap<>(); } @@ -93,25 +92,11 @@ public class ContextUtility { return adminSecurityContext; } - public synchronized void removeFromCache(UUID uuid, boolean fullNameOnly) throws ResourceRegistryException { - for(String fullName : contextUUIDs.keySet()) { - UUID uuidKey = contextUUIDs.get(fullName); - if(uuidKey.compareTo(uuid) == 0) { - contextUUIDs.remove(fullName); - if(!fullNameOnly) { - contexts.remove(uuid); - } - return; - } - } - } - public synchronized void addSecurityContext(SecurityContext securityContext) { contexts.put(securityContext.getUUID(), securityContext); } public synchronized void addSecurityContext(String fullname, SecurityContext securityContext) { - contextUUIDs.put(fullname, securityContext.getUUID()); contexts.put(securityContext.getUUID(), securityContext); } @@ -120,9 +105,13 @@ public class ContextUtility { SecurityContext securityContext = null; logger.trace("Trying to get {} for {}", SecurityContext.class.getSimpleName(), fullName); - UUID uuid = contextUUIDs.get(fullName); + UUID uuid = ContextCache.getInstance().getUUIDByFullName(fullName); - if(uuid == null) { + if(uuid != null) { + securityContext = contexts.get(uuid); + } + + if(securityContext==null) { logger.trace("{} for {} is not in cache. Going to get it", SecurityContext.class.getSimpleName(), fullName); @@ -133,9 +122,7 @@ public class ContextUtility { securityContext = getSecurityContextByUUID(uuid, contextVertex); addSecurityContext(fullName, securityContext); - } else { - securityContext = contexts.get(uuid); - } + } return securityContext; diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/contexts/entities/ContextManagement.java b/src/main/java/org/gcube/informationsystem/resourceregistry/contexts/entities/ContextManagement.java index 5545646..82745e3 100644 --- a/src/main/java/org/gcube/informationsystem/resourceregistry/contexts/entities/ContextManagement.java +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/contexts/entities/ContextManagement.java @@ -1,7 +1,9 @@ package org.gcube.informationsystem.resourceregistry.contexts.entities; +import java.io.IOException; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.UUID; import org.gcube.com.fasterxml.jackson.core.JsonProcessingException; @@ -15,7 +17,10 @@ import org.gcube.informationsystem.context.reference.entities.Context; import org.gcube.informationsystem.context.reference.relations.IsParentOf; import org.gcube.informationsystem.model.reference.properties.Header; import org.gcube.informationsystem.model.reference.relations.Relation; +import org.gcube.informationsystem.resourceregistry.api.contexts.ContextCache; +import org.gcube.informationsystem.resourceregistry.api.contexts.ContextCacheRenewal; import org.gcube.informationsystem.resourceregistry.api.exceptions.AlreadyPresentException; +import org.gcube.informationsystem.resourceregistry.api.exceptions.AvailableInAnotherContextException; import org.gcube.informationsystem.resourceregistry.api.exceptions.NotFoundException; import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException; import org.gcube.informationsystem.resourceregistry.api.exceptions.context.ContextAlreadyPresentException; @@ -29,6 +34,7 @@ import org.gcube.informationsystem.resourceregistry.dbinitialization.DatabaseEnv import org.gcube.informationsystem.resourceregistry.instances.base.ElementManagement; import org.gcube.informationsystem.resourceregistry.instances.base.entities.EntityElementManagement; import org.gcube.informationsystem.resourceregistry.utils.Utility; +import org.gcube.informationsystem.utils.ElementMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -54,9 +60,26 @@ public class ContextManagement extends EntityElementManagement { this.elementType = Context.NAME; } + protected ContextCacheRenewal contextCacheRenewal = new ContextCacheRenewal() { + + @Override + public List renew() throws ResourceRegistryException { + String contextsJsonString = allFromServer(false); + List contexts = null; + try { + contexts = ElementMapper.unmarshalList(contextsJsonString); + } catch (IOException e) { + logger.error("Unable to "); + } + return contexts; + } + }; + public ContextManagement() { super(AccessType.CONTEXT); init(); + ContextCache contextCache = ContextCache.getInstance(); + contextCache.setContextCacheRenewal(contextCacheRenewal); } public ContextManagement(ODatabaseDocument oDatabaseDocument) throws ResourceRegistryException { @@ -243,7 +266,7 @@ public class ContextManagement extends EntityElementManagement { if(parentSecurityContext!=null && securityContext!=null) { parentSecurityContext.getChildren().remove(securityContext); } - ContextUtility.getInstance().removeFromCache(uuid, false); + ContextCache.getInstance().cleanCache(); } throw e; } @@ -323,7 +346,7 @@ public class ContextManagement extends EntityElementManagement { element = (OVertex) ElementManagement.updateProperties(oClass, getElement(), jsonNode, ignoreKeys, ignoreStartWithKeys); - ContextUtility.getInstance().removeFromCache(uuid, (nameChanged && !parentChanged)); + ContextCache.getInstance().cleanCache(); return element; } @@ -379,7 +402,7 @@ public class ContextManagement extends EntityElementManagement { SecurityContext securityContext = contextUtility.getSecurityContextByUUID(uuid); securityContext.delete(oDatabaseDocument); - contextUtility.removeFromCache(uuid, false); + ContextCache.getInstance().cleanCache(); return true; @@ -420,4 +443,32 @@ public class ContextManagement extends EntityElementManagement { throw new UnsupportedOperationException(); } + + public String allFromServer(boolean polymorphic) throws ResourceRegistryException { + return super.all(polymorphic); + } + + @Override + public String all(boolean polymorphic) throws ResourceRegistryException { + try { + ContextCache contextCache = ContextCache.getInstance(); + return ElementMapper.marshal(contextCache.getContexts()); + } catch (JsonProcessingException | ResourceRegistryException e) { + return allFromServer(polymorphic); + } + } + + public String readFromServer() throws NotFoundException, AvailableInAnotherContextException, ResourceRegistryException { + return super.read(); + } + + @Override + public String read() throws NotFoundException, AvailableInAnotherContextException, ResourceRegistryException { + try { + ContextCache contextCache = ContextCache.getInstance(); + return ElementMapper.marshal(contextCache.getContextByUUID(uuid)); + } catch (JsonProcessingException | ResourceRegistryException e) { + return readFromServer(); + } + } } diff --git a/src/test/java/org/gcube/informationsystem/resourceregistry/contexts/ContextManagementTest.java b/src/test/java/org/gcube/informationsystem/resourceregistry/contexts/ContextManagementTest.java index 99374a0..245518c 100644 --- a/src/test/java/org/gcube/informationsystem/resourceregistry/contexts/ContextManagementTest.java +++ b/src/test/java/org/gcube/informationsystem/resourceregistry/contexts/ContextManagementTest.java @@ -2,6 +2,7 @@ package org.gcube.informationsystem.resourceregistry.contexts; import java.io.IOException; import java.util.List; +import java.util.Map; import java.util.UUID; import org.gcube.com.fasterxml.jackson.core.JsonProcessingException; @@ -10,6 +11,7 @@ import org.gcube.informationsystem.context.reference.entities.Context; import org.gcube.informationsystem.context.reference.relations.IsParentOf; import org.gcube.informationsystem.model.impl.properties.HeaderImpl; import org.gcube.informationsystem.resourceregistry.ContextTest; +import org.gcube.informationsystem.resourceregistry.api.contexts.ContextCache; import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException; import org.gcube.informationsystem.resourceregistry.api.exceptions.context.ContextAlreadyPresentException; import org.gcube.informationsystem.resourceregistry.api.exceptions.context.ContextException; @@ -463,4 +465,47 @@ public class ContextManagementTest extends ContextTest { delete(context); } + + @Test + public void testContextCache() throws Exception { + List contexts = getAll(); + logger.debug("{}", contexts); + + ContextCache contextCache = ContextCache.getInstance(); + Map uuidToContextFullName = contextCache.getUUIDToContextFullNameAssociation(); + logger.debug("{}", uuidToContextFullName); + + List contextsFromCache = contextCache.getContexts(); + for(Context c : contextsFromCache) { + UUID uuid = c.getHeader().getUUID(); + if(c.getParent()!=null) { + IsParentOf isParentOf = c.getParent(); + Context parentContext = isParentOf.getSource(); + UUID parentUUID = parentContext.getHeader().getUUID(); + Assert.assertEquals(parentContext, contextCache.getContextByUUID(parentUUID)); + List children = parentContext.getChildren(); + boolean found = false; + for(IsParentOf ipo : children) { + if(ipo.equals(isParentOf)) { + found = true; + break; + } + } + Assert.assertTrue(found); + logger.debug("{} : {} (parent {} : {})", c.getHeader().getUUID(), contextCache.getContextFullNameByUUID(uuid), parentUUID, contextCache.getContextFullNameByUUID(parentUUID)); + }else { + logger.debug("{} : {}", c.getHeader().getUUID(), contextCache.getContextFullNameByUUID(uuid)); + } + } + + Context currentContext = read(ContextUtility.getCurrentSecurityContext().getUUID()); + logger.debug("Current context : {}", currentContext); + + for(Context c : contexts) { + UUID uuid = c.getHeader().getUUID(); + Context context = read(uuid); + String fullName = ContextCache.getInstance().getContextFullNameByUUID(uuid); + logger.debug("{} - {} : {}", uuid, fullName, context); + } + } }