package AgentProvider.Implementation.Database; import AgentSystemPluginAPI.Contract.StateAction; import EnvironmentPluginAPI.Exceptions.TechnicalException; import java.util.HashMap; import java.util.Map; import java.util.Random; /** * This class implements a cache that is only stored in memory. */ public class MemoryCache implements ICache { private final ICache child; private int size; private int elementCount; private final Map<StateAction, Float> dict; public MemoryCache(ICache child, int size) { this.child = child; this.size = size; dict = new HashMap<StateAction, Float>(size); elementCount = 0; } @Override public void store(StateAction stateAction, float value) throws TechnicalException { if(elementCount >= size) { flushPartly(); } if(!dict.containsKey(stateAction)) { elementCount++; } dict.put(stateAction, value); } @Override public boolean hasStored(StateAction stateAction) { return dict.containsKey(stateAction); } /** * Removes about one quarter of the elements randomly and flushes them to the parent cache. */ private void flushPartly() throws TechnicalException { int nrToPush = elementCount / 4; elementCount -= nrToPush; StateAction[] entries = dict.keySet().toArray(new StateAction[dict.keySet().size()]); Random random = new Random(); StateAction stateAction; int i; float value; while (nrToPush > 0) { i = random.nextInt(entries.length); stateAction = entries[i]; if (stateAction != null) { value = remove(stateAction); child.store(stateAction, value); nrToPush--; entries[i] = null; } } } public float remove(StateAction stateAction) { float value = dict.remove(stateAction); elementCount--; return value; } @Override public float get(StateAction stateAction) throws ValueNotFoundException, TechnicalException { if(dict.containsKey(stateAction)) { return dict.get(stateAction); } if(child.hasStored(stateAction)) { float value = child.remove(stateAction); store(stateAction, value); return value; } return child.get(stateAction); } @Override public void flush() throws TechnicalException { for (Map.Entry<StateAction, Float> stateActionFloatEntry : dict.entrySet()) { child.store(stateActionFloatEntry.getKey(), stateActionFloatEntry.getValue()); } child.flush(); } @Override public void clear() throws TechnicalException { dict.clear(); elementCount = 0; child.clear(); } }