package it.softecspa.fileproxy.cache; import it.softecspa.fileproxy.DatabaseBalancer.Balancer; import it.softecspa.fileproxy.services.ServerCacheFactory.CacheKey; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.SortedMap; import org.apache.log4j.Logger; public class CacheContainer { // Singleton instance private static CacheContainer instance; private Logger log = Logger.getLogger(getClass()); // Mappe degli elementi private HashMap>[] cache = null; private HashMap>>[] cachedTables = null; private CacheContainer() { super(); synchronized (CacheContainer.class) { if (instance == null) { instance = this; log.info(CacheContainer.class.getSimpleName()+" instance is starting!"); instance.flushAll(); } } } public static CacheContainer getInstance() { synchronized (CacheContainer.class) { if (instance == null) new CacheContainer(); } return instance; } protected synchronized void flushAll() { flush(Balancer.MASTER); flush(Balancer.STAGE); } @SuppressWarnings("unchecked") protected synchronized void flush(Balancer balancer) { // CACHE if (cache==null) cache = new HashMap[2]; if (cache[balancer.index()]==null) cache[balancer.index()] = new HashMap>(); // Elenco tabelle coinvolte per singola cache if (cachedTables==null) cachedTables = new HashMap[2]; if (cachedTables[balancer.index()]==null) cachedTables[balancer.index()] = new HashMap>>(); // ....pulizia Collection> collection = cache[balancer.index()].values(); for (Iterator> i = collection.iterator(); i.hasNext(); ) { CacheElement element = i.next(); if (element!=null) element.flush(); } } public void createContainer(CacheElement element) throws CacheException { createContainer(element.getUniqueName(), element, true); } public void createContainer(CacheKey uniqueNane, CacheElement element, boolean autoflush) throws CacheException { if (element==null) return; if (uniqueNane==null) throw new CacheException("CacheElement with null name"); String name = uniqueNane.toString(); if (log.isDebugEnabled()) log.debug("Create empty container with name '"+name+"'"); int index = element.getBalancer().index(); CacheElement found = cache[index].get(name); if (found!=null) { if (found.getClass()!=element.getClass()) { throw new CacheException("CacheElement ClassCastException: element named '"+name+"' class is "+found.getClass().getSimpleName()+"!"); } if (autoflush) { // Se esiste giĆ  un container con quel nome lo pulisco; cache[index].get(name).flush(); return; } else { throw new CacheException("CacheElement with name '"+name+"' just exist!"); } } else { addTables(name, element, index); } // Aggiungo l'elemento alla cache cache[element.getBalancer().index()].put(name, element); } private void addTables(String name, CacheElement element, int index) { for (String table : element.getTables()) { List> lista = cachedTables[index].get(table); if (lista==null) { lista = new ArrayList>(); cachedTables[index].put(table, lista); } if (!lista.contains(name)) { lista.add(element); } } } @SuppressWarnings("unchecked") public CacheElement getCacheElement(CacheKey uniqueName, Balancer balancer) throws CacheException { int index = balancer.index(); String name = uniqueName.toString(); // Estraggo il container CacheElement container = null; try { container = (CacheElement) cache[index].get(name); // FIXME aggiungere log dell'errore su DB e invio email return container; } catch (ClassCastException e) { throw new CacheException("ClassCastException estracting element with name '"+name+"'", e); } catch (Exception e) { throw new CacheException("Unhandled exception estracting element with name '"+name+"'"); } } /** * Restituisce il container dati legato alla chiave * @param uniqueName * @param balancer * @return * @throws CacheException */ public SortedMap getContainer(CacheKey uniqueName, Balancer balancer) throws CacheException { // Estraggo il container CacheElement cacheElement = getCacheElement(uniqueName, balancer); // Controllo se i dati sono validi, altrimenti faccio un load if (cacheElement.isExpired()) { cacheElement.load(); } return cacheElement.getContainer(); } /** * Restituisce la lista completa delle tabelle in cache * @return */ public HashMap>>[] getCachedTables() { return cachedTables; } }