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    }