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}