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;
}
};
}