package railo.runtime.cache.ram;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import railo.commons.io.SystemUtil;
import railo.commons.io.cache.CacheEntry;
import railo.runtime.cache.CacheSupport;
import railo.runtime.config.Config;
import railo.runtime.op.Caster;
import railo.runtime.op.Constants;
import railo.runtime.type.Struct;
public class RamCache extends CacheSupport {
private static final int DEFAULT_CONTROL_INTERVAL = 60;
private Map<String, RamCacheEntry> entries= new ConcurrentHashMap<String, RamCacheEntry>();
private long missCount;
private int hitCount;
private long idleTime;
private long until;
private int controlInterval=DEFAULT_CONTROL_INTERVAL*1000;
public static void init(Config config,String[] cacheNames,Struct[] arguments) {//print.ds();
}
public void init(Config config,String cacheName, Struct arguments) throws IOException {
until=Caster.toLongValue(arguments.get("timeToLiveSeconds",Constants.LONG_ZERO),Constants.LONG_ZERO)*1000;
idleTime=Caster.toLongValue(arguments.get("timeToIdleSeconds",Constants.LONG_ZERO),Constants.LONG_ZERO)*1000;
Object ci = arguments.get("controlIntervall",null);
if(ci==null)ci = arguments.get("controlInterval",null);
controlInterval=Caster.toIntValue(ci,DEFAULT_CONTROL_INTERVAL)*1000;
new Controler(this).start();
}
@Override
public boolean contains(String key) {
return getQuiet(key,null)!=null;
}
public CacheEntry getQuiet(String key, CacheEntry defaultValue) {
RamCacheEntry entry = entries.get(key);
if(entry==null) {
return defaultValue;
}
if(!valid(entry)) {
entries.remove(key);
return defaultValue;
}
return entry;
}
@Override
public CacheEntry getCacheEntry(String key, CacheEntry defaultValue) {
RamCacheEntry ce = (RamCacheEntry) getQuiet(key, null);
if(ce!=null) {
hitCount++;
return ce.read();
}
missCount++;
return defaultValue;
}
@Override
public long hitCount() {
return hitCount;
}
@Override
public long missCount() {
return missCount;
}
@Override
public List<String> keys() {
List<String> list=new ArrayList<String>();
Iterator<Entry<String, RamCacheEntry>> it = entries.entrySet().iterator();
RamCacheEntry entry;
while(it.hasNext()){
entry=it.next().getValue();
if(valid(entry))list.add(entry.getKey());
}
return list;
}
public void put(String key, Object value, Long idleTime, Long until) {
RamCacheEntry entry= entries.get(key);
if(entry==null){
entries.put(key, new RamCacheEntry(key,value,
idleTime==null?this.idleTime:idleTime.longValue(),
until==null?this.until:until.longValue()));
}
else
entry.update(value);
}
public boolean remove(String key) {
RamCacheEntry entry = entries.remove(key);
if(entry==null) {
return false;
}
return valid(entry);
}
public static class Controler extends Thread {
private RamCache ramCache;
public Controler(RamCache ramCache) {
this.ramCache=ramCache;
}
public void run(){
while(true){
try{
_run();
}
catch(Throwable t){
t.printStackTrace();
}
SystemUtil.sleep(ramCache.controlInterval);
}
}
private void _run() {
RamCacheEntry[] values = ramCache.entries.values().toArray(new RamCacheEntry[ramCache.entries.size()]);
for(int i=0;i<values.length;i++){
if(!CacheSupport.valid(values[i])){
ramCache.entries.remove(values[i].getKey());
}
}
}
}
}