package com.quickserverlab.quickcached.cache.impl.concurrenthashmap; import java.io.*; import java.util.Date; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; import com.quickserverlab.quickcached.QuickCached; import com.quickserverlab.quickcached.cache.impl.BaseCacheImpl; /** * * @author Akshathkumar Shetty */ public class ConcurrentHashMapImpl extends BaseCacheImpl { private static final Logger logger = Logger.getLogger(ConcurrentHashMapImpl.class.getName()); private static int tunerSleeptime = 130;//in sec private Map map = new ConcurrentHashMap(); private Map mapTtl = new ConcurrentHashMap(); protected volatile long expired; private Thread purgeThread = null; public ConcurrentHashMapImpl() { startPurgeThread(); } private void startPurgeThread() { purgeThread = new Thread("ConcurrentHashMap-PurgeThread") { public void run() { long timespent = 0; long timeToSleep = 0; long stime = 0; long etime = 0; while(true) { timeToSleep = tunerSleeptime*1000 - timespent; if(timeToSleep>0) { try { Thread.sleep(timeToSleep); } catch (InterruptedException ex) { logger.log(Level.FINE, "Interrupted "+ ex); break; } } stime = System.currentTimeMillis(); try { purgeOperation(); } catch (Exception ex) { Logger.getLogger(ConcurrentHashMapImpl.class.getName()).log( Level.SEVERE, null, ex); } etime = System.currentTimeMillis(); timespent = etime - stime; } } }; purgeThread.setDaemon(true); purgeThread.start(); } public void purgeOperation() { try { Iterator iterator = mapTtl.keySet().iterator(); String key = null; Date expTime; Date currentTime = new Date(); while(iterator.hasNext()) { key = (String) iterator.next(); expTime = (Date) mapTtl.get(key); if(expTime==null) { continue; } if(expTime.before(currentTime)) { mapTtl.remove(key); map.remove(key); expired++; } } } catch (Exception e) { logger.log(Level.WARNING, "Error: " + e, e); } } public void saveStats(Map stats) { if(stats==null) stats = new LinkedHashMap(); super.saveStats(stats); //expired - Number of items that expired stats.put("expired", ""+expired); } public String getName() { return "ConcurrentHashMapImpl"; } public long getSize() { return map.size(); } public void setToCache(String key, Object value, int objectSize, int expInSec) throws Exception { map.put(key, value); if (expInSec != 0) { mapTtl.put(key, new Date(System.currentTimeMillis()+expInSec*1000)); } else { mapTtl.remove(key);//just in case } } public void updateToCache(String key, Object value, int objectSize) throws Exception { //no action required here for ref based cache } public void updateToCache(String key, Object value, int objectSize, int expInSec) throws Exception { //no action required here for ref based cache if (expInSec != 0) { mapTtl.put(key, new Date(System.currentTimeMillis()+expInSec*1000)); } else { mapTtl.remove(key);//just in case } } public Object getFromCache(String key) throws Exception { Object object = map.get(key); if (object != null) { return object; } else { if(QuickCached.DEBUG) logger.log(Level.FINE, "no value in db for key: {0}", key); return null; } } public boolean deleteFromCache(String key) throws Exception { mapTtl.remove(key); Object obj = map.remove(key); return obj!=null; } public void flushCache() throws Exception { mapTtl.clear(); map.clear(); } private String fileName = "./"+getName()+"_"+QuickCached.getPort()+".dat"; public boolean saveToDisk() { System.out.println("Saving state to disk.."); ObjectOutputStream oos = null; try { oos = new ObjectOutputStream(new FileOutputStream(fileName)); oos.writeObject(map); oos.writeObject(mapTtl); oos.flush(); return true; } catch (Exception e) { logger.log(Level.WARNING, "Error: {0}", e); } finally { if(oos!=null) { try { oos.close(); } catch (IOException ex) { Logger.getLogger(ConcurrentHashMapImpl.class.getName()).log( Level.WARNING, "Error: "+ex, ex); } } System.out.println("Done"); } return false; } public boolean readFromDisk() { File file = new File(fileName); if(file.canRead()==false) return false; System.out.println("Reading state from disk.."); ObjectInputStream ois = null; try { ois = new ObjectInputStream(new FileInputStream(fileName)); map = (Map) ois.readObject(); mapTtl = (Map) ois.readObject(); return true; } catch (Exception e) { logger.log(Level.WARNING, "Error: {0}", e); } finally { if(ois!=null) { try { ois.close(); } catch (IOException ex) { Logger.getLogger(ConcurrentHashMapImpl.class.getName()).log( Level.WARNING, "Error: "+ex, ex); } } file.delete(); System.out.println("Done"); } return false; } }