Mercurial > hg > openmind
view src/main/java/org/mpi/openmind/cache/AbstractCacheService.java @ 41:2079c35739c8
more comments and cleanup.
author | casties |
---|---|
date | Mon, 17 Oct 2016 12:28:39 +0200 |
parents | 86c343109257 |
children | b7a8db041f68 |
line wrap: on
line source
package org.mpi.openmind.cache; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import org.mpi.openmind.repository.bo.Attribute; import org.mpi.openmind.repository.bo.Entity; import org.mpi.openmind.repository.bo.Node; import org.mpi.openmind.repository.bo.Relation; import org.mpi.openmind.repository.bo.ViewerAttribute; import org.mpi.openmind.repository.bo.ViewerPage; import org.mpi.openmind.repository.services.PersistenceService; import cl.maps.duplex.DuplexKey; import cl.maps.duplex.DuplexMap; import cl.maps.penta.PentaMap; import cl.maps.triple.TripleMap; import cl.maps.utils.AttKey; import cl.maps.utils.RelKey; public abstract class AbstractCacheService{ private static Logger logger = Logger.getLogger(AbstractCacheService.class); private PersistenceService persistenceService; private DuplexMap<Entity, String, Long> entMap; private Map<String, Boolean> entLoadedByOC; public AbstractCacheService(){ logger.info( "[" + Thread.currentThread().getId() + "]\tInitializing AbstractCacheService HashCode=" + this.hashCode()); //Initializing entities structures this.entMap = new DuplexMap<Entity, String, Long>(); this.entLoadedByOC = new HashMap<String, Boolean>(); //Initializing attributes structures this.attMap = new TripleMap<Attribute, AttKey, Long, Long>(); this.attLoadedByOCAndName = new HashMap<AttKey, Boolean>(); this.attLoadedBySrcId = new HashMap<Long, Boolean>(); //Initializing relations structures this.relMap = new PentaMap<Relation, RelKey, Long, Long, String, Long>(); this.relLoadedBySrcId = new HashMap<Long, Boolean>(); this.relLoadedByTarId = new HashMap<Long, Boolean>(); this.relLoadedByName = new HashMap<String, Boolean>(); } /** * Remove the entity from the cache. * * @param entId * @param oc * @return */ protected Entity removeEntity(Long entId, String oc){ return this.entMap.remove(new DuplexKey<String, Long>(oc, entId)); } /** * Put the entity in the cache. * * @param ent */ protected void updateLWEntity(Entity ent){ this.entMap.put(ent.getKey(), ent); } /** * Returns (a clone of) an entity from the cache by id. * * @param id * @return */ public Entity getEntityById(Long id) { Entity ent = getEntityByIdReadOnly(id); if (ent != null) { return (Entity) ent.clone(); } return null; } /** * Returns an entity from the cache by id. * * Do not modify the entity! * * @param id * @return */ public Entity getEntityByIdReadOnly(Long id){ if (id == null) { // TODO: WTF? try { throw new Exception("Id of entity can not be null."); } catch (Exception e) { logger.error(e.getMessage(), e); } } else { // get entity from cache Entity ent = this.entMap.getValuesByOwnKey(id); if (ent == null) { // load entity from db logger.debug("Entity no found in cache ID=" + id); List<Entity> list = getPs().getLightweightEntities(Node.SYS_STATUS_CURRENT_VERSION, id, Node.TYPE_ABOX, null, null, true, 1); if (list.size() > 0) { ent = list.get(0); // load all entities of the same object class loadEntitiesByDef(ent.getObjectClass()); } } return ent; } return null; } /** * Load all entities of the given object class into the cache. * * @param oc * @return */ public List<Entity> loadEntitiesByDef(String oc) { logger.debug( "[" + Thread.currentThread().getId() + "]\tgetEntitiesByDef=" + oc + "\nHashCode=" + this.hashCode()); if (entLoadedByOC.get(oc) == null || entLoadedByOC.get(oc) == false) { synchronized (entMap) { if (entLoadedByOC.get(oc) == null) { long start = System.currentTimeMillis(); logger.debug("[" + Thread.currentThread().getId() + "]\t Starting loading Entities from DB for OC=" + oc + "\nHashCode=" + this.hashCode()); entLoadedByOC.put(oc, false); // load entities from database List<Entity> list = getPs().getLightweightEntities(Node.SYS_STATUS_CURRENT_VERSION, null, Node.TYPE_ABOX, oc, null, true, -1); // put entities in cache for (Entity ent : list) { entMap.put(ent.getKey(), ent); } entLoadedByOC.put(oc, true); long end = System.currentTimeMillis(); logger.debug("[" + Thread.currentThread().getId() + "]\tFinished loading Entities from DB for OC=" + oc + " - time= " + (end - start) + "\nHashCode=" + this.hashCode()); } } } List<Entity> list = entMap.getValuesByAKey(oc); return list; } /** * Saves the Entities (without content) in the database and puts them in the cache. * * @param nodeList * @throws Exception */ public void saveEntityListAsNodeWithoutContent(List<Entity> nodeList) throws Exception{ this.getPs().saveEntityListAsNodeWithoutContent(nodeList); for(Entity ent : nodeList){ entMap.put(ent.getKey(), ent); } } //****************************************** //************Attributes******************** //****************************************** //AttKey(OC, attName), SrcId private TripleMap<Attribute, AttKey, Long, Long> attMap; private Map<Long, Boolean> attLoadedBySrcId; private Map<AttKey, Boolean> attLoadedByOCAndName; protected boolean removeAtt(Long attId){ Attribute att = this.attMap.getValuesByOwnKey(attId); if(att != null){ this.attMap.remove(att.getKey()); return true; } return false; } protected boolean removeAtt(Attribute att){ if(att != null){ this.attMap.remove(att.getKey()); return true; } return false; } /** * Put attribute in cache. * * @param att */ protected void updateAtt(Attribute att){ this.attMap.put(att.getKey(), att); } /** * Put list of attributes in cache. * * @param list */ protected void updateAttList(List<Attribute> list){ for(Attribute att : list){ this.attMap.put(att.getKey(), att); } } /** * Return a list of (cloned) Attributes of the Entity. * * Loads Attributes from the database into the cache. * * @param entId * @return */ public List<Attribute> getAttsBySrcId(Long entId){ List<Attribute> list = new ArrayList<Attribute>(); for(Attribute att : getAttsBySrcIdReadOnly(entId)){ list.add((Attribute)att.clone()); } return list; } public List<Attribute> getAttsBySrcIdReadOnly(Long srcId){ //logger.info("getAttsBySrcIdReadOnly srcId=" + srcId); if(attLoadedBySrcId.get(srcId) == null || attLoadedBySrcId.get(srcId) == false){ synchronized (attMap) { if(attLoadedBySrcId.get(srcId) == null){ //logger.info("getAttsBySrcIdReadOnly fromDB entId=" + srcId); attLoadedBySrcId.put(srcId, false); List<Attribute> list = getPs().getAllAttributes(srcId, -1); for(Attribute att : list){ this.attMap.put(att.getKey(), att); } attLoadedBySrcId.put(srcId, true); //logger.info("STARTING getAttsBySrcIdReadOnly srcId=" + srcId + " - size=" + list.size()); } } } return this.attMap.getValuesByBKey(srcId); } public List<Attribute> getAttsByOCAndName(String oc, String attName){ AttKey ocNameKey = new AttKey(oc, attName); //logger.info("[" + Thread.currentThread().getId() + // "]\tgetAttsByOCAndNames oc=" + oc + " - attName=" + attName + "\nHashCode=" + this.hashCode()); if(attLoadedByOCAndName.get(ocNameKey) == null || attLoadedByOCAndName.get(ocNameKey) == false){ synchronized (attMap) { if(attLoadedByOCAndName.get(ocNameKey) == null){ logger.info("STARTING getAttsByOCAndNames oc=" + oc + " - attName=" + attName); attLoadedByOCAndName.put(ocNameKey, false); List<Attribute> list = getPs().getAttributeByDefByName(oc, attName, -1); for(Attribute att : list){ this.attMap.put(att.getKey(), att); } attLoadedByOCAndName.put(ocNameKey, true); logger.info("FINISHED getAttsByOCAndNames oc=" + oc + " - attName=" + attName + " - size=" + list.size()); } } } return this.attMap.getValuesByAKey(ocNameKey); } //****************************************** //************Relations********************* //****************************************** //RelKey<>, src, tar, relId private PentaMap<Relation, RelKey, Long, Long, String, Long> relMap; private Map<Long, Boolean> relLoadedBySrcId; private Map<Long, Boolean> relLoadedByTarId; private Map<String, Boolean> relLoadedByName; protected boolean removeRel(Long relId){ Relation rel = this.relMap.getValuesByOwnKey(relId); if(rel != null){ this.relMap.remove(rel.getKey()); return true; } return false; } protected boolean removeRel(Relation rel){ if(rel != null){ this.relMap.remove(rel.getKey()); return true; } return false; } /** * Put Relation in cache. * * @param rel */ protected void updateRel(Relation rel){ this.relMap.put(rel.getKey(), rel); } /** * Put list of Relations in cache. * * @param list */ protected void updateRelList(List<Relation> list){ for(Relation rel : list){ this.relMap.put(rel.getKey(), rel); } } /** * Return Relations with matching source id from cache. * * Loads Relations from db and stores in cache if not in cache. * * @param srcId * @return * @throws Exception */ public List<Relation> getRelsBySrcId(long srcId) throws Exception { if (relLoadedBySrcId.get(srcId) == null || relLoadedBySrcId.get(srcId) == false) { // Relation not in cache synchronized (relMap) { if (relLoadedBySrcId.get(srcId) == null) { relLoadedBySrcId.put(srcId, false); List<Relation> list = getPs().getSourceRelationsFromDB(this.getEntityByIdReadOnly(srcId), null, null, -1, false); for (Relation rel : list) { this.relMap.put(rel.getKey(), rel); } relLoadedBySrcId.put(srcId, true); } } } return relMap.getValuesByBKey(srcId); } public List<Relation> getRelsByTarId(Long tarId){ if(relLoadedByTarId.get(tarId) == null || relLoadedByTarId.get(tarId) == false){ synchronized (relMap) { if(relLoadedByTarId.get(tarId) == null){ //logger.info("getRelsByTarId fromDB tarId=" + tarId); relLoadedByTarId.put(tarId, false); List<Relation> list = getPs().getTargetRelationsFromDB(this.getEntityByIdReadOnly(tarId), null, null, -1, false); for(Relation rel : list){ this.relMap.put(rel.getKey(), rel); } relLoadedByTarId.put(tarId, true); } } } return relMap.getValuesByCKey(tarId); } /** * TODO the relations returned by this method have no attributes. * 'cause the performance. * There are to ways to correct this issue: * 1) load the attributes directly from the DB (slow solution) * 2) use LW state for the relation, like the entities. * * It should not mean a problem, because the other methods to get relations load the relation with attributes. * Only getting relation one by one (using ID) would be a problem, but this method does not exist. * * @param name * @return */ public List<Relation> getRelsByName(String name) throws Exception{ if(relLoadedByName.get(name) == null || relLoadedByName.get(name) == false){ synchronized (relMap) { if(relLoadedByName.get(name) == null){ logger.info("getRelsByName fromDB name=" + name); relLoadedByName.put(name, false); List<Relation> list = getPs().getRelationByNameDB(name, -1); for(Relation rel : list){ this.relMap.put(rel.getKey(), rel); } relLoadedByName.put(name, true); } } } return relMap.getValuesByDKey(name); } public PersistenceService getPs() { return persistenceService; } public void setPs(PersistenceService ps){ this.persistenceService = ps; } //*********************************** //*********************************** //*********************************** //*********************************** private Map<Long, ViewerPage> viewerPageMap; private DuplexMap<ViewerAttribute, Long, Long> viewerAttMap; protected Map<Long, ViewerPage> getViewerPageMap(){ if(viewerPageMap == null){ this.loadViewerPageMap(); } return viewerPageMap; } protected DuplexMap<ViewerAttribute, Long, Long> getViewerAttMap(){ if(viewerAttMap == null){ this.loadViewerAttMap(); } return viewerAttMap; } public int removeViewerPage(Long id){ int rows = 0; if(viewerPageMap == null){ this.loadViewerPageMap(); } synchronized (viewerPageMap) { viewerPageMap.remove(id); rows += getPs().removeViewerPage(id); List<ViewerAttribute> attrs = getViewerAttMap().getValuesByAKey(id); for(ViewerAttribute attr : attrs){ rows += removeViewerAttribute(attr.getId()); } } return rows; } public int removeViewerAttribute(Long id){ int rows = 0; if(viewerAttMap == null){ this.loadViewerAttMap(); } synchronized (viewerAttMap) { ViewerAttribute att = viewerAttMap.getValuesByOwnKey(id); if(att != null){ viewerAttMap.remove(att.getKey()); rows = getPs().removeViewerAttribute(att.getId()); } } return rows; } private void loadViewerAttMap(){ if(viewerAttMap == null){ viewerAttMap = new DuplexMap<ViewerAttribute, Long, Long>(); synchronized (viewerAttMap) { List<ViewerAttribute> list = getPs().getViewerAttributes(); for(ViewerAttribute att : list){ viewerAttMap.put(att.getKey(), att); } } } } private void loadViewerPageMap(){ if(viewerPageMap == null){ viewerPageMap = new HashMap<Long, ViewerPage>(); synchronized (viewerPageMap) { viewerPageMap = new HashMap<Long, ViewerPage>(); List<ViewerPage> list = getPs().getViewerPages(); for(ViewerPage page : list){ viewerPageMap.put(page.getId(), page); } } } } }