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