001 package railo.runtime.cache.ram; 002 003 import java.io.IOException; 004 import java.util.ArrayList; 005 import java.util.HashMap; 006 import java.util.Iterator; 007 import java.util.List; 008 import java.util.Map; 009 import java.util.Map.Entry; 010 011 import railo.commons.io.SystemUtil; 012 import railo.commons.io.cache.CacheEntry; 013 import railo.runtime.cache.CacheSupport; 014 import railo.runtime.config.Config; 015 import railo.runtime.op.Caster; 016 import railo.runtime.op.Constants; 017 import railo.runtime.type.Struct; 018 019 public class RamCache extends CacheSupport { 020 021 private static final int DEFAULT_CONTROL_INTERVALL = 60; 022 private Map<String, RamCacheEntry> entries= new HashMap<String, RamCacheEntry>(); 023 private long missCount; 024 private int hitCount; 025 026 private long idleTime; 027 private long until; 028 private int controlIntervall=DEFAULT_CONTROL_INTERVALL*1000; 029 030 031 public static void init(Config config,String[] cacheNames,Struct[] arguments) {//print.ds(); 032 033 } 034 035 public void init(Config config,String cacheName, Struct arguments) throws IOException { 036 until=Caster.toLongValue(arguments.get("timeToLiveSeconds",Constants.LONG_ZERO),Constants.LONG_ZERO)*1000; 037 idleTime=Caster.toLongValue(arguments.get("timeToIdleSeconds",Constants.LONG_ZERO),Constants.LONG_ZERO)*1000; 038 controlIntervall=Caster.toIntValue(arguments.get("controlIntervall",null),DEFAULT_CONTROL_INTERVALL)*1000; 039 new Controler(this).start(); 040 } 041 042 @Override 043 public boolean contains(String key) { 044 return getQuiet(key,null)!=null; 045 } 046 047 048 049 050 public CacheEntry getQuiet(String key, CacheEntry defaultValue) { 051 RamCacheEntry entry = entries.get(key); 052 if(entry==null) { 053 return defaultValue; 054 } 055 if(!valid(entry)) { 056 entries.remove(key); 057 return defaultValue; 058 } 059 return entry; 060 } 061 062 @Override 063 public CacheEntry getCacheEntry(String key, CacheEntry defaultValue) { 064 RamCacheEntry ce = (RamCacheEntry) getQuiet(key, null); 065 if(ce!=null) { 066 hitCount++; 067 return ce.read(); 068 } 069 missCount++; 070 return defaultValue; 071 } 072 073 @Override 074 public long hitCount() { 075 return hitCount; 076 } 077 078 @Override 079 public long missCount() { 080 return missCount; 081 } 082 083 @Override 084 public List<String> keys() { 085 List<String> list=new ArrayList<String>(); 086 087 Iterator<Entry<String, RamCacheEntry>> it = entries.entrySet().iterator(); 088 RamCacheEntry entry; 089 while(it.hasNext()){ 090 entry=it.next().getValue(); 091 if(valid(entry))list.add(entry.getKey()); 092 } 093 return list; 094 } 095 096 public void put(String key, Object value, Long idleTime, Long until) { 097 098 RamCacheEntry entry= entries.get(key); 099 if(entry==null){ 100 entries.put(key, new RamCacheEntry(key,value, 101 idleTime==null?this.idleTime:idleTime.longValue(), 102 until==null?this.until:until.longValue())); 103 } 104 else 105 entry.update(value); 106 } 107 108 public boolean remove(String key) { 109 RamCacheEntry entry = entries.remove(key); 110 if(entry==null) { 111 return false; 112 } 113 return valid(entry); 114 115 } 116 117 public static class Controler extends Thread { 118 119 private RamCache ramCache; 120 121 public Controler(RamCache ramCache) { 122 this.ramCache=ramCache; 123 } 124 125 public void run(){ 126 while(true){ 127 try{ 128 _run(); 129 } 130 catch(Throwable t){ 131 t.printStackTrace(); 132 } 133 SystemUtil.sleep(ramCache.controlIntervall); 134 } 135 } 136 137 private void _run() { 138 RamCacheEntry[] values = ramCache.entries.values().toArray(new RamCacheEntry[ramCache.entries.size()]); 139 for(int i=0;i<values.length;i++){ 140 if(!CacheSupport.valid(values[i])){ 141 ramCache.entries.remove(values[i].getKey()); 142 } 143 } 144 } 145 } 146 147 }