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.type.scope.storage.clean;
020
021import java.io.IOException;
022import java.util.Date;
023import java.util.Iterator;
024import java.util.List;
025import java.util.Map;
026import java.util.Map.Entry;
027
028import lucee.commons.io.cache.Cache;
029import lucee.commons.io.cache.CacheEntry;
030import lucee.commons.io.cache.CacheKeyFilter;
031import lucee.runtime.cache.CacheConnection;
032import lucee.runtime.config.ConfigWebImpl;
033import lucee.runtime.type.scope.storage.StorageScopeCache;
034import lucee.runtime.type.scope.storage.StorageScopeEngine;
035import lucee.runtime.type.scope.storage.StorageScopeListener;
036
037public class CacheStorageScopeCleaner extends StorageScopeCleanerSupport {
038        
039        private Filter filter;
040
041        public CacheStorageScopeCleaner(int type,StorageScopeListener listener) {
042                super(type,listener,INTERVALL_MINUTE);
043                //this.strType=VariableInterpreter.scopeInt2String(type);
044                filter=new Filter(strType);
045        }
046        
047        public void init(StorageScopeEngine engine) {
048                super.init(engine);
049                
050        }
051
052        protected void _clean() {
053                ConfigWebImpl config = (ConfigWebImpl) engine.getFactory().getConfig();
054                Map<String, CacheConnection> connections = config.getCacheConnections();
055                CacheConnection cc;
056                
057                if(connections!=null) {
058                        Map.Entry<String, CacheConnection> entry;
059                        Iterator<Entry<String, CacheConnection>> it = connections.entrySet().iterator();
060                        while(it.hasNext()){
061                                entry=it.next();
062                                cc=entry.getValue();
063                                if(cc.isStorage()){
064                                        try {
065                                                clean(cc,config);
066                                        } catch (IOException e) {
067                                                error(e);
068                                        }
069                                }
070                        }
071                }
072                
073        }
074
075        private void clean(CacheConnection cc, ConfigWebImpl config) throws IOException {
076                Cache cache = cc.getInstance(config);
077                int len=filter.length(),index;
078                List<CacheEntry> entries = cache.entries(filter);
079                CacheEntry ce;
080                long expires;
081                
082                String key,appname,cfid;
083                if(entries.size()>0){
084                        Iterator<CacheEntry> it = entries.iterator();
085                        while(it.hasNext()){
086                                ce=it.next();
087                                
088                                Date lm = ce.lastModified();
089                                long time=lm!=null?lm.getTime():0;
090                                expires=time+ce.idleTimeSpan()-StorageScopeCache.SAVE_EXPIRES_OFFSET;
091                                if(expires<=System.currentTimeMillis()) {
092                                        key=ce.getKey().substring(len);
093                                        index=key.indexOf(':');
094                                        cfid=key.substring(0,index);
095                                        appname=key.substring(index+1);
096                                        
097                                        if(listener!=null)listener.doEnd(engine, this,appname, cfid);
098                                        info("remove "+strType+"/"+appname+"/"+cfid+" from cache "+cc.getName());
099                                        engine.remove(type,appname,cfid);
100                                        cache.remove(ce.getKey());
101                                }
102                        }
103                }
104                
105                //engine.remove(type,appName,cfid);
106                
107                
108                //return (Struct) cache.getValue(key,null);
109        }
110
111        public static class Filter implements CacheKeyFilter {
112                private String startsWith;
113
114                public Filter(String type){
115                        startsWith=new StringBuilder("lucee-storage:").append(type).append(":").toString().toUpperCase();
116                }
117                
118                public String toPattern() {
119                        return startsWith+"*";
120                }
121
122                public boolean accept(String key) {
123                        return key.startsWith(startsWith);
124                }
125
126                public int length() {
127                        return startsWith.length();
128                }
129                
130        }
131}