package com.janrain.backplane2.server.dao; import com.janrain.commons.supersimpledb.message.Message; import org.apache.log4j.Logger; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicLong; /** * @author Johnny Bufu */ public class ConfigLRUCache<T extends Message> { // - PUBLIC /** * @param maxCacheSizeBytes max cache size in bytes; 0 or negative values effectively disable the cache */ public ConfigLRUCache(long maxCacheSizeBytes) { this.maxCacheSizeBytes = maxCacheSizeBytes; } public synchronized long getMaxCacheSizeBytes() { return maxCacheSizeBytes; } public synchronized void setMaxCacheSizeBytes(long maxCacheSizeBytes) { this.maxCacheSizeBytes = maxCacheSizeBytes; } public boolean isCached(String tokenId) { return cache.keySet().contains(tokenId); } public synchronized T get(String id) { return cache.get(id); } public synchronized T add(T item) { return cache.put(item.getIdValue(), item); } /** allows caching of null items */ public synchronized T add(String id, T item) { return cache.put(id, item); } public synchronized T delete(String id) { return cache.remove(id); } // - PRIVATE private static final Logger logger = Logger.getLogger(ConfigLRUCache.class); private static final int DEFAULT_INITIAL_CAPACITY = 500; private static final float DEFAULT_LOAD_FACTOR = 0.75f; private final AtomicLong size = new AtomicLong(0); private long maxCacheSizeBytes; private final Map<String,T> cache = new LinkedHashMap<String, T>(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, true) { @Override protected boolean removeEldestEntry(Map.Entry<String, T> eldest) { int removed = 0; Iterator<Map.Entry<String, T>> entries = entrySet().iterator(); while ( size.get() > maxCacheSizeBytes && entries.hasNext()) { Map.Entry<String, T> next = entries.next(); entries.remove(); size.addAndGet( -1 * next.getValue().sizeBytes()); removed++; } if (removed > 0) { logger.info( "Removed " + removed + " " + eldest.getClass().getSimpleName() + " items from cache, " + "new size is: " + size() + " items / " + size.get() + " bytes"); } return false; } }; }