package org.hwo.servicelink.ng; import java.util.Hashtable; import static org.hwo.logging.Logging.*; import static org.hwo.logging.LogLevel.*; public class ServiceRegisterCache { ServiceLink serviceLink; Hashtable cache; public class BaseCacheItem { Integer ax, node, register; boolean isFloat; long lastReadTime; Object value; public BaseCacheItem(int hash){ this.ax = axFromHash(hash); this.node = nodeFromHash(hash); this.register = regFromHash(hash); this.isFloat = ((hash & 0x40000000) != 0); this.value = null; } public BaseCacheItem(int ax,int node,int register, boolean isFloat) { this.ax = ax; this.node = node; this.register = register; this.isFloat = isFloat; this.value = null; } long age() { return System.currentTimeMillis() - lastReadTime; } boolean isOld() { return age() > 250; } private void fetchValue(){ if (isOld() && serviceLink.isConnected()) { try { if (isFloat){ Float f = serviceLink.readFloat(ax.byteValue(),node.byteValue(),register); setValue(f); } else { Integer i = serviceLink.readInteger(ax.byteValue(),node.byteValue(),register); setValue(i); } } catch (Exception e) { e.printStackTrace(); } } } public Object getValue(){ if (isOld()){ log(DEBUGDETAIL,"OLDCACHE:SLA: [%d:%d:%d:%s] = %s", ax,node,register,isFloat ? "F" : "I",value); fetchValue(); log(DEBUGDETAIL,"NEWCACHE:SLA: [%d:%d:%d:%s] = %s", ax,node,register,isFloat ? "F" : "I",value); } return value; } public void setValue(Object value){ this.value = value; this.lastReadTime = System.currentTimeMillis(); log(DEBUGDETAIL,"CACHE: SLA: [%d:%d:%d:%s] = %s", ax,node,register,isFloat ? "F" : "I",value); } public void invalidate(){ this.lastReadTime = 0; } } public static Integer axFromHash(Integer hash){ return (hash >> 20) & 0x0F; } public static Integer nodeFromHash(Integer hash){ return (hash >> 16) & 0x0F; } public static Integer regFromHash(Integer hash){ return (hash) & 0xFFFF; } public int calcHash(int ax,int node,int register,boolean isFloat) { return (isFloat ? 0x40000000 : 0) | (ax << 20) | (node << 16) | register; } ServiceRegisterCache(ServiceLink serviceLink) { this.serviceLink = serviceLink; this.cache = new Hashtable<>(); } public ServiceLink getServiceLink() { return serviceLink; } private BaseCacheItem getCacheItem(int hash){ if (!cache.containsKey(hash)){ BaseCacheItem bci = new BaseCacheItem(hash); cache.put(new Integer(hash), bci); log( DEBUGDETAIL, "new cache-item: 0x%08x = %s", hash, bci); } return cache.get(hash); } public void updateValue(int hash){ BaseCacheItem bci = getCacheItem(hash); bci.invalidate(); bci.getValue(); } public void updateValue(int hash,Object value){ getCacheItem(hash).setValue(value); } public synchronized Object getCachedValue(int hash){ return getCacheItem(hash).getValue(); } public synchronized Object getCachedValue(int ax,int node,int register,boolean isFloat){ int hash = calcHash(ax, node, register, isFloat); return getCacheItem(hash).getValue(); } public synchronized Integer getCachedInteger(int ax,int node,int register) { return (Integer)getCachedValue(ax, node, register, false); } public synchronized Float getCachedFloat(int ax,int node,int register) { return (Float)getCachedValue(ax, node, register, true); } public synchronized void invalidate(int ax,int node,int register,boolean isFloat) { cache.remove(calcHash(ax, node, register,isFloat)); } }