001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.runtime.cache.tag.timespan;
020
021import java.io.IOException;
022import java.util.Iterator;
023import java.util.List;
024
025import lucee.commons.io.cache.Cache;
026import lucee.commons.io.cache.CacheEntry;
027import lucee.runtime.PageContext;
028import lucee.runtime.cache.ram.RamCache;
029import lucee.runtime.cache.tag.CacheHandler;
030import lucee.runtime.cache.tag.CacheHandlerFactory;
031import lucee.runtime.cache.tag.CacheHandlerFilter;
032import lucee.runtime.cache.tag.CacheItem;
033import lucee.runtime.cache.tag.query.QueryCacheItem;
034import lucee.runtime.cache.util.CacheKeyFilterAll;
035import lucee.runtime.exp.PageException;
036import lucee.runtime.functions.cache.Util;
037import lucee.runtime.op.Caster;
038import lucee.runtime.op.Decision;
039import lucee.runtime.type.dt.TimeSpan;
040
041public class TimespanCacheHandler implements CacheHandler {
042
043        private int defaultCacheType;
044        private Cache defaultCache;
045        
046        public TimespanCacheHandler(int defaultCacheType, Cache defaultCache){
047                this.defaultCacheType=defaultCacheType;
048                this.defaultCache=defaultCache;
049        }
050
051        @Override
052        public CacheItem get(PageContext pc, String id) {
053                return CacheHandlerFactory.toCacheItem(getCache(pc).getValue(id,null),null);
054        }
055        
056        @Override
057        public boolean remove(PageContext pc, String id) {
058                try {
059                        return getCache(pc).remove(id);
060                }
061                catch (IOException e) {}
062                return false;
063        }
064        
065
066        @Override
067        public void set(PageContext pc, String id, Object cachedWithin, CacheItem value) throws PageException {
068                long timeSpan;
069                if(Decision.isDate(cachedWithin, false) && !(cachedWithin instanceof TimeSpan))
070                        timeSpan=Caster.toDate(cachedWithin, null).getTime()-System.currentTimeMillis();
071                else
072                        timeSpan = Caster.toTimespan(cachedWithin).getMillis();
073                
074                // ignore timespan smaller or equal to 0
075                if(timeSpan<=0) return;
076                
077                getCache(pc).put(id, value, Long.valueOf(timeSpan), Long.valueOf(timeSpan));
078        }
079        
080        @Override
081        public void clean(PageContext pc) {
082                try{
083                Cache c = getCache(pc);
084                List<CacheEntry> entries = c.entries();
085                if(entries.size()<100) return;
086                
087                Iterator<CacheEntry> it = entries.iterator();
088                while(it.hasNext()){
089                        it.next(); // touch them to makes sure the cache remove them, not really good, cache must do this by itself
090                }
091                }
092                catch(IOException ioe){}
093        }
094        
095
096        @Override
097        public void clear(PageContext pc) {
098                try {
099                        getCache(pc).remove(CacheKeyFilterAll.getInstance());
100                }
101                catch (IOException e) {}
102        }
103        
104
105        @Override
106        public void clear(PageContext pc, CacheHandlerFilter filter) {
107                clear(pc, getCache(pc), filter);
108        }
109        
110        public static void clear(PageContext pc, Cache cache, CacheHandlerFilter filter) {
111                try{
112                        Iterator<CacheEntry> it = cache.entries().iterator();
113                        CacheEntry ce;
114                        Object obj;
115                        while(it.hasNext()){
116                                ce = it.next();
117                                if(filter==null) {
118                                        cache.remove(ce.getKey());
119                                        continue;
120                                }
121                                
122                                obj=ce.getValue();
123                                if(obj instanceof QueryCacheItem)
124                                        obj=((QueryCacheItem)obj).getQuery();
125                                if(filter.accept(obj)) 
126                                        cache.remove(ce.getKey());
127                        }
128                }
129                catch (IOException e) {}
130        }
131
132        @Override
133        public int size(PageContext pc) {
134                try {
135                        return getCache(pc).keys().size();
136                }
137                catch (IOException e) {
138                        return 0;
139                }
140        }
141        
142
143        private Cache getCache(PageContext pc) {
144                Cache c = Util.getDefault(pc,defaultCacheType,null);
145                if(c==null) {
146                        if(defaultCache==null)defaultCache=new RamCache().init(0, 0, RamCache.DEFAULT_CONTROL_INTERVAL);
147                        return defaultCache;
148                }
149                return c;
150        }
151
152        @Override
153        public String label() throws PageException {
154                return "timespan";
155        }
156
157}