# HG changeset patch # User Tim Englich # Date 1271788702 0 # Node ID 797a6264b89b67cadc58d20ea5998608129ff100 # Parent 74608c12b4fe9a17f6f9e870aa66ca0c7852c0fc Integrated the CacheCleaner for the ThematicDataCache gnv-artifacts/trunk@961 c6561f87-3c4e-4783-a992-168aeb5c3f6f diff -r 74608c12b4fe -r 797a6264b89b gnv-artifacts/ChangeLog --- a/gnv-artifacts/ChangeLog Tue Apr 20 12:53:00 2010 +0000 +++ b/gnv-artifacts/ChangeLog Tue Apr 20 18:38:22 2010 +0000 @@ -1,3 +1,22 @@ +2010-04-20 Tim Englich + + * src/main/java/de/intevation/gnv/artifacts/cache/CacheFactory.java (initializeCache): + Initialize the CacheCline after the initialization of the ThematicDataCache. + + * src/main/java/de/intevation/gnv/state/StateBase.java (setHash): + Integrate an '#' as separator in the Hashvalue of an State to separate the + StateId unambiguously. This is required because a StateId can be a + Substring of an other StateId. + + * src/main/java/de/intevation/gnv/state/cache/QueryObject.java: + Bean for representing all database-Queries which are used for fetching + Data which is stoted in the ThematicDataCache. + + * src/main/java/de/intevation/gnv/state/cache/ThematicDataCacheCleaner.java: + Specific CacheCleaner for cleaning the ThematicData-Cache. It extend the + CacheCleaner of the geo-backand and has the same configuration + possibilities. + 2010-04-20 Tim Englich * doc/conf/queries.properties: diff -r 74608c12b4fe -r 797a6264b89b gnv-artifacts/src/main/java/de/intevation/gnv/artifacts/cache/CacheFactory.java --- a/gnv-artifacts/src/main/java/de/intevation/gnv/artifacts/cache/CacheFactory.java Tue Apr 20 12:53:00 2010 +0000 +++ b/gnv-artifacts/src/main/java/de/intevation/gnv/artifacts/cache/CacheFactory.java Tue Apr 20 18:38:22 2010 +0000 @@ -5,6 +5,9 @@ import org.apache.log4j.Logger; +import de.intevation.gnv.geobackend.base.query.cache.CacheCleaner; +import de.intevation.gnv.state.cache.ThematicDataCacheCleaner; + /** * The CacheFactory is used to initialize and retrieve Cache. * @@ -25,11 +28,16 @@ private static CacheFactory instance = null; /** - * + * The manager of the Cache */ private CacheManager cacheManager = null; /** + * The Cleaner of the Cache + */ + private CacheCleaner cacheCleaner = null; + + /** * Basic-Constructor of this Class */ private CacheFactory() { @@ -67,6 +75,8 @@ if (cacheManager == null) { cacheManager = new CacheManager(configurationFileName); cacheManager.addCache(CACHENAME); + this.cacheCleaner = new ThematicDataCacheCleaner(); + this.cacheCleaner.start(); } } diff -r 74608c12b4fe -r 797a6264b89b gnv-artifacts/src/main/java/de/intevation/gnv/state/StateBase.java --- a/gnv-artifacts/src/main/java/de/intevation/gnv/state/StateBase.java Tue Apr 20 12:53:00 2010 +0000 +++ b/gnv-artifacts/src/main/java/de/intevation/gnv/state/StateBase.java Tue Apr 20 18:38:22 2010 +0000 @@ -82,6 +82,8 @@ public static final String EXCEPTION_INVALID_INPUT = "input.is.not.valid"; + + public final static String HASH_ID_SEPARATOR = "#"; /** input value names which should not be rendered from State itself */ public final static String[] BLACKLIST = {"sourceid", "fisname"}; @@ -935,7 +937,11 @@ protected void setHash(String uuid) { - this.hash = uuid + id + inputData.hashCode(); + this.hash = uuid + + HASH_ID_SEPARATOR + + id + + HASH_ID_SEPARATOR + + inputData.hashCode(); } diff -r 74608c12b4fe -r 797a6264b89b gnv-artifacts/src/main/java/de/intevation/gnv/state/cache/QueryObject.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gnv-artifacts/src/main/java/de/intevation/gnv/state/cache/QueryObject.java Tue Apr 20 18:38:22 2010 +0000 @@ -0,0 +1,55 @@ +/** + * + */ +package de.intevation.gnv.state.cache; +/** + * @author Tim Englich + * + */ +public class QueryObject { + + /** + * The Id of the State the Query belongs to + */ + private String stateId = null; + + /** + * The Query which belongs to the State + */ + private String query = null; + + /** + * Constructor + * @param stateId the Id of the State the Query belongs to + * @param query the Query which belongs to the State + */ + public QueryObject(String stateId, String query) { + this.stateId = stateId; + this.query = query.toUpperCase(); + } + + /** + * Returns the StateId + * @return the Stateid + */ + public String getStateId() { + return stateId; + } + + /** + * Returns the Querystring + * @return the QueryString + */ + public String getQuery() { + return query; + } + + /** + * Returns true if the given Name of the Table is Contained in the Query + * @param tableName the Name of the Table + * @return true if the Name of the Table is contained in the Query + */ + public boolean queryContainsTableName(String tableName){ + return this.query.contains(tableName); + } +} diff -r 74608c12b4fe -r 797a6264b89b gnv-artifacts/src/main/java/de/intevation/gnv/state/cache/ThematicDataCacheCleaner.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gnv-artifacts/src/main/java/de/intevation/gnv/state/cache/ThematicDataCacheCleaner.java Tue Apr 20 18:38:22 2010 +0000 @@ -0,0 +1,237 @@ +/** + * + */ +package de.intevation.gnv.state.cache; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +import net.sf.ehcache.Cache; + +import org.apache.log4j.Logger; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +import de.intevation.artifactdatabase.Config; +import de.intevation.gnv.artifacts.cache.CacheFactory; +import de.intevation.gnv.geobackend.base.query.cache.CacheCleaner; +import de.intevation.gnv.geobackend.base.query.container.QueryContainerFactory; +import de.intevation.gnv.geobackend.base.query.container.exception.QueryContainerException; +import de.intevation.gnv.geobackend.base.query.exception.QueryException; +import de.intevation.gnv.state.StateBase; +import de.intevation.gnv.utils.ArtifactXMLUtilities; + + +/** + * Extended Class of the CacheCleaner. + * This Cleaner has the job to cleanup the ThematicData-Cache if it + * is necessary. + * @author Tim Englich + * + */ +public class ThematicDataCacheCleaner extends CacheCleaner { + + /** + * the logger, used to log exceptions and additonaly information + */ + private static Logger log = Logger.getLogger(ThematicDataCacheCleaner.class); + + private final static String XPATH_ARTIFACTS = + "/artifact-database/artifacts/artifact"; + private final static String XPATH_STATES = "states/state"; + private final static String XPATH_STATEID = "id"; + private final static String XPATH_QUERYID = "queryID"; + + /** + * The Queries that should be Cleaned with its links to the + * StateIds. + */ + private Collection queryObjects = null; + + /** + * Constructor + */ + public ThematicDataCacheCleaner() { + this.setUp(); + } + + /** + * Constructor + * @param arg0 + */ + public ThematicDataCacheCleaner(Runnable arg0) { + this.setUp(); + } + + /** + * Constructor + * @param arg0 + */ + public ThematicDataCacheCleaner(String arg0) { + this.setUp(); + } + + /** + * Constructor + * @param arg0 + * @param arg1 + */ + public ThematicDataCacheCleaner(ThreadGroup arg0, Runnable arg1) { + this.setUp(); + } + + /** + * Constructor + * @param arg0 + * @param arg1 + */ + public ThematicDataCacheCleaner(ThreadGroup arg0, String arg1) { + this.setUp(); + } + + /** + * Constructor + * @param arg0 + * @param arg1 + */ + public ThematicDataCacheCleaner(Runnable arg0, String arg1) { + this.setUp(); + } + + /** + * Constructor + * @param arg0 + * @param arg1 + * @param arg2 + */ + public ThematicDataCacheCleaner(ThreadGroup arg0, Runnable arg1, String arg2) { + this.setUp(); + } + + /** + * Constructor + * @param arg0 + * @param arg1 + * @param arg2 + * @param arg3 + */ + public ThematicDataCacheCleaner(ThreadGroup arg0, Runnable arg1, + String arg2, long arg3) { + this.setUp(); + } + + /** + * Initializes the QueryObjects. + * The Queryobjects will be read from the Configuration. + * Only Queries which are defined in queryID-Elements + * are used. + * The other Queries are currently not put into the Cache. + */ + @Override + protected void setUp(){ + super.setUp(); + this.queryObjects = new ArrayList(); + Document configuration = Config.getConfig(); + NodeList artifactList = Config.getNodeSetXPath(configuration, + XPATH_ARTIFACTS); + log.debug("ThematicDataCacheCleaner.setUp()"); + if (artifactList != null && artifactList.getLength() > 0){ + for (int i = 0; i < artifactList.getLength(); i++){ + Element currentArtifactNode = (Element)artifactList.item(i); + + String link = currentArtifactNode.getAttribute("xlink:href"); + if (link != null && link.length() > 0){ + String absolutFileName = Config.replaceConfigDir(link); + currentArtifactNode = (Element)new ArtifactXMLUtilities() + .readConfiguration(absolutFileName); + } + NodeList stateList = Config.getNodeSetXPath(currentArtifactNode, + XPATH_STATES); + if (stateList != null && stateList.getLength() > 0){ + for (int j = 0; j < stateList.getLength() ; j++){ + Element currentStateNode = (Element)stateList.item(j); + String stateId = currentStateNode + .getAttribute(XPATH_STATEID); + String queryID = Config.getStringXPath(currentStateNode, + XPATH_QUERYID); + try { + if (queryID != null){ + String query = QueryContainerFactory + .getInstance() + .getQueryContainer() + .getQuery(queryID); + QueryObject qo = new QueryObject(stateId, query); + queryObjects.add(qo); + } + } catch (QueryContainerException e) { + log.error(e,e); + } + } + } + } + } + } + + @Override + protected void cleanup() { + log.debug("ThematicDataCacheCleaner.cleanup"); + try { + if (queryObjects != null && queryObjects.size() > 0){ + String[] tableNames = this.getUpdatedTableNames(); + if (tableNames != null && tableNames.length > 0){ + Iterator it = queryObjects.iterator(); + while (it.hasNext()){ + QueryObject qo = it.next(); + for (int i = 0; i < tableNames.length; i++){ + if (qo.queryContainsTableName(tableNames[i])){ + String stateId = qo.getStateId(); + this.cleanUpCache(stateId); + break; + } + } + } + }else{ + log.debug("No Tables found to cleanup."); + } + }else{ + log.warn("No Queries to clean"); + } + } catch (QueryException e) { + log.error(e,e); + } + } + + /** + * Removes the Entries which Keys matches to the stateId + * from the Cache. + * @param stateId The Id of the State which Entries has to be removed. + */ + private void cleanUpCache(String stateId){ + log.debug("ThematicDataCacheCleaner.cleanUpCache "+stateId); + CacheFactory factory = CacheFactory.getInstance(); + Cache cache = factory.getCache(); + List keys = cache.getKeys(); + String keySample = StateBase.HASH_ID_SEPARATOR + + stateId + + StateBase.HASH_ID_SEPARATOR; + if (keys != null && keys.size() > 0){ + Iterator it = keys.iterator(); + while (it.hasNext()){ + String key = it.next(); + if (key != null && key.contains(keySample)){ + boolean removed = cache.remove(key); + if (!removed){ + log.warn("Object with Key " + + key + "could not be removed from Cache"); + }else{ + log.debug("Object with Key " + + key + "has been removed from Cache"); + } + } + } + } + } +}