changeset 64:83b209aa4226

working on stale entity update problem.
author casties
date Thu, 26 Jan 2017 19:37:25 +0100
parents 9d342e713c2f
children 74cd973f6ece
files src/main/java/org/mpi/openmind/cache/AbstractCacheService.java src/main/java/org/mpi/openmind/cache/CacheService.java src/main/java/org/mpi/openmind/cache/WrapperService.java src/main/java/org/mpi/openmind/repository/bo/Entity.java src/main/java/org/mpi/openmind/repository/bo/Node.java
diffstat 5 files changed, 88 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/src/main/java/org/mpi/openmind/cache/AbstractCacheService.java	Mon Jan 09 20:38:55 2017 +0100
+++ b/src/main/java/org/mpi/openmind/cache/AbstractCacheService.java	Thu Jan 26 19:37:25 2017 +0100
@@ -67,8 +67,13 @@
 	 * 
 	 * @param ent
 	 */
-	protected void updateLWEntity(Entity ent){
-		this.entMap.put(ent.getKey(), ent);
+	protected void updateLWEntity(Entity ent) {
+		// update access timestamp
+		ent.setAccessTime(System.currentTimeMillis());
+		Entity oldEnt = this.entMap.put(ent.getKey(), ent);
+		if (oldEnt != null && oldEnt.getAccessTime() == ent.getAccessTime()) {
+			logger.error("Cache updated with entity with same accessTime! old="+oldEnt+" new="+ent);
+		}
 	}
 	
 	/**
@@ -97,12 +102,7 @@
 	 */
 	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);
-			}
+			logger.error("ID of entity is null!");
 		} else {
 		    // get entity from cache
 			Entity ent = this.entMap.getValuesByOwnKey(id);
@@ -115,6 +115,7 @@
 		        	ent = list.get(0);
 		        	// load all entities of the same object class
 		        	loadEntitiesByDef(ent.getObjectClass());
+		        	// TODO: should we use the newly loaded entity?
 		        }
 			}	
 			return ent;	
@@ -130,14 +131,14 @@
 	 */
     public List<Entity> loadEntitiesByDef(String oc) {
         logger.debug(
-                "[" + Thread.currentThread().getId() + "]\tgetEntitiesByDef=" + oc + "\nHashCode=" + this.hashCode());
+                "[" + Thread.currentThread().getId() + "] getEntitiesByDef=" + oc + " HashCode=" + 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());
+                    logger.debug("[" + Thread.currentThread().getId() + "] Starting loading Entities from DB for OC="
+                            + oc + " HashCode=" + this.hashCode());
                     entLoadedByOC.put(oc, false);
                     
                     // load entities from database
@@ -145,13 +146,15 @@
                             Node.TYPE_ABOX, oc, null, true, -1);
                     // put entities in cache
                     for (Entity ent : list) {
+                    	// set access timestamp
+                    	ent.setAccessTime(System.currentTimeMillis());
                         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());
+                    logger.debug("[" + Thread.currentThread().getId() + "] Finished loading Entities from DB for OC="
+                            + oc + " - time= " + (end - start) + " HashCode=" + this.hashCode());
                 }
             }
         }
@@ -168,10 +171,27 @@
 	public void saveEntityListAsNodeWithoutContent(List<Entity> nodeList) throws Exception{
 		this.getPs().saveEntityListAsNodeWithoutContent(nodeList);
 		for(Entity ent : nodeList){
+			// update access timestamp
+			ent.setAccessTime(System.currentTimeMillis());
 			entMap.put(ent.getKey(), ent);
 		}
 	}
 	
+	
+	public boolean isEntityCurrent(Entity ent) {
+		Entity cacheEnt = this.entMap.getValuesByOwnKey(ent.getId());
+		if (cacheEnt == null) {
+			// not in cache
+			return true;
+		}
+		long ct = cacheEnt.getAccessTime();
+		long et = ent.getAccessTime();
+		if (ct == 0 || et == 0 || et > ct) {
+			logger.error("Weird cache access times! old="+Long.toString(ct)+" new="+Long.toString(et));
+		}
+		return (ct == et);
+	}
+	
 	//******************************************
 	//************Attributes********************
 	//******************************************
@@ -204,6 +224,8 @@
 	 * @param att
 	 */
 	protected void updateAtt(Attribute att){
+		// update access timestamp
+		att.setAccessTime(System.currentTimeMillis());
 		this.attMap.put(att.getKey(), att);
 	}
 	
@@ -214,6 +236,8 @@
 	 */
 	protected void updateAttList(List<Attribute> list){
 		for(Attribute att : list){
+			// update access timestamp
+			att.setAccessTime(System.currentTimeMillis());
 			this.attMap.put(att.getKey(), att);	
 		}
 	}
@@ -244,6 +268,8 @@
 					List<Attribute> list = 
 						getPs().getAllAttributes(srcId, -1);
 					for(Attribute att : list){
+						// update access timestamp
+						att.setAccessTime(System.currentTimeMillis());
 						this.attMap.put(att.getKey(), att);
 					}
 					attLoadedBySrcId.put(srcId, true);
@@ -266,6 +292,8 @@
 					List<Attribute> list = 
 						getPs().getAttributeByDefByName(oc, attName, -1);
 					for(Attribute att : list){
+						// update access timestamp
+						att.setAccessTime(System.currentTimeMillis());
 						this.attMap.put(att.getKey(), att);
 					}
 					attLoadedByOCAndName.put(ocNameKey, true);
@@ -309,6 +337,8 @@
 	 * @param rel
 	 */
 	protected void updateRel(Relation rel){
+		// update access timestamp
+		rel.setAccessTime(System.currentTimeMillis());
 		this.relMap.put(rel.getKey(), rel);
 	}
 	
@@ -319,6 +349,8 @@
 	 */
 	protected void updateRelList(List<Relation> list){
 		for(Relation rel : list){
+			// update access timestamp
+			rel.setAccessTime(System.currentTimeMillis());
 			this.relMap.put(rel.getKey(), rel);
 		}
 	}
@@ -341,6 +373,8 @@
                     List<Relation> list = getPs().getSourceRelationsFromDB(this.getEntityByIdReadOnly(srcId), null,
                             null, -1, false);
                     for (Relation rel : list) {
+						// update access timestamp
+						rel.setAccessTime(System.currentTimeMillis());
                         this.relMap.put(rel.getKey(), rel);
                     }
                     relLoadedBySrcId.put(srcId, true);
@@ -359,6 +393,8 @@
 					List<Relation> list = 
 						getPs().getTargetRelationsFromDB(this.getEntityByIdReadOnly(tarId), null, null, -1, false);
 					for(Relation rel : list){
+						// update access timestamp
+						rel.setAccessTime(System.currentTimeMillis());
 						this.relMap.put(rel.getKey(), rel);
 					}
 					relLoadedByTarId.put(tarId, true);
@@ -392,6 +428,8 @@
 					List<Relation> list = 
 						getPs().getRelationByNameDB(name, -1);
 					for(Relation rel : list){
+						// update access timestamp
+						rel.setAccessTime(System.currentTimeMillis());
 						this.relMap.put(rel.getKey(), rel);
 					}
 					
--- a/src/main/java/org/mpi/openmind/cache/CacheService.java	Mon Jan 09 20:38:55 2017 +0100
+++ b/src/main/java/org/mpi/openmind/cache/CacheService.java	Thu Jan 26 19:37:25 2017 +0100
@@ -340,7 +340,6 @@
 				this.updateAttList(ent.getAttributes());
 			}	
 		} catch (Exception e) {
-			e.printStackTrace();
 			logger.error(e.getMessage(), e);
 		}
 	}
--- a/src/main/java/org/mpi/openmind/cache/WrapperService.java	Mon Jan 09 20:38:55 2017 +0100
+++ b/src/main/java/org/mpi/openmind/cache/WrapperService.java	Thu Jan 26 19:37:25 2017 +0100
@@ -663,16 +663,19 @@
 		entity = removeEmptyAttributes(entity);
 
 		txLog.debug("** START save entity: user="+user+" entity="+entity.toSmallString());
+		// check if entity is up to date with cache
+		if (!cache.isEntityCurrent(entity)) {
+			logger.error("Entity to save not up to date with cache!");
+		}
+		
 		// save in database
 		this.getPS().saveEntity(entity);
 		// save in cache
 		cache.saveEntity(entity);
 		txLog.debug("** END save entity: user="+user+" entity="+entity.toSmallString());
 	
-		System.gc();
 		logger.debug("[U=" + user + "] SaveEntity - execution time[ms]: " + (System.currentTimeMillis() - start));
 		Entity clone = (Entity) entity.clone();
-		// logger.info(clone.toString());
 		return clone;
 	}
 	
@@ -899,8 +902,7 @@
 				}
 			}
 		}
-		logger.debug("getSourcesForTargetRelation (loading sources) - execution time[ms]: "
-				+ (System.currentTimeMillis() - start));
+		//logger.debug("getSourcesForTargetRelation (loading sources) - execution time[ms]: "+(System.currentTimeMillis() - start));
 		Collections.sort(rs, new EntitySortByNormalizedOwnValue());
 		return rs;
 	}
@@ -996,8 +998,7 @@
 			}
 		}
 		Collections.sort(list, new RelationSortBySourceOW());
-		logger.debug("getTargetRelations - execution time[ms]: "
-				+ (System.currentTimeMillis() - start));
+		//logger.debug("getTargetRelations - execution time[ms]: "+ (System.currentTimeMillis() - start));
 		return list;
 	}
 
@@ -1037,8 +1038,7 @@
 			}
 		}
 		Collections.sort(list, new RelationSortByTargetOW());
-		logger.debug("getSourceRelations - execution time[ms]: "
-				+ (System.currentTimeMillis() - start));
+		//logger.debug("getSourceRelations - execution time[ms]: "+ (System.currentTimeMillis() - start));
 
 		return list;
 	}
--- a/src/main/java/org/mpi/openmind/repository/bo/Entity.java	Mon Jan 09 20:38:55 2017 +0100
+++ b/src/main/java/org/mpi/openmind/repository/bo/Entity.java	Thu Jan 26 19:37:25 2017 +0100
@@ -174,6 +174,13 @@
 		return false;
 	}
     
+    /**
+     * Returns a list of source Relations of this Entity with the given relation name and target object class.
+     * 
+     * @param relationName
+     * @param tarObjClass
+     * @return
+     */
     public List<Relation> getSourceRelations(String relationName, String tarObjClass){
     	List<Relation> list = new ArrayList<Relation>();
     	try {
@@ -191,6 +198,13 @@
         return list;
     }
     
+    /**
+     * Returns a list of target Relations of this Entity with the given relation name and source object class.
+     * 
+     * @param relationName
+     * @param srcObjClass
+     * @return
+     */
     public List<Relation> getTargetRelations(String relationName, String srcObjClass){
     	List<Relation> list = new ArrayList<Relation>();
     	try {
--- a/src/main/java/org/mpi/openmind/repository/bo/Node.java	Mon Jan 09 20:38:55 2017 +0100
+++ b/src/main/java/org/mpi/openmind/repository/bo/Node.java	Thu Jan 26 19:37:25 2017 +0100
@@ -3,7 +3,6 @@
 import java.io.Serializable;
 import java.io.UnsupportedEncodingException;
 import java.text.DateFormat;
-import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
@@ -47,31 +46,33 @@
     public static String SYS_STATUS_CURRENT_VERSION = "CURRENT_VERSION";
     public static String SYS_STATUS_PREVIOUS_VERSION = "PREVIOUS_VERSION";
     
-    private static SimpleDateFormat timeFormat = new SimpleDateFormat("hh:mm:ss" );
 
     @Id
     @GeneratedValue(strategy = GenerationType.AUTO)
     @Column(name="row_id")
     private Long rowId;
 
-    @Transient
-    private Date dateModification;
-
+    
+    /** modification time for frontend access */
     public String getTimeStamp(){
     	return DateFormat.getDateTimeInstance(
-                DateFormat.MEDIUM, DateFormat.SHORT).format(getDateModification());
+                DateFormat.MEDIUM, DateFormat.SHORT).format(new Date(this.modificationTime));
     }
     
-    public Date getDateModification() {
-        dateModification = new Date(this.modificationTime);
-        return dateModification;
-    }
+
+    /** timestamp for cache modification times */
+    @Transient
+    private long accessTime;
 
-    public void setDateModification(Date dateModification) {
-        this.dateModification = dateModification;
-    }
+    public long getAccessTime() {
+		return accessTime;
+	}
 
-    @Transient
+	public void setAccessTime(long accessTime) {
+		this.accessTime = accessTime;
+	}
+
+	@Transient
     private List<View> views = new ArrayList<View>();
 
     public void addView(View view){