changeset 845:797a6264b89b

Integrated the CacheCleaner for the ThematicDataCache gnv-artifacts/trunk@961 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Tim Englich <tim.englich@intevation.de>
date Tue, 20 Apr 2010 18:38:22 +0000
parents 74608c12b4fe
children 8b6ef091d38c
files gnv-artifacts/ChangeLog gnv-artifacts/src/main/java/de/intevation/gnv/artifacts/cache/CacheFactory.java gnv-artifacts/src/main/java/de/intevation/gnv/state/StateBase.java gnv-artifacts/src/main/java/de/intevation/gnv/state/cache/QueryObject.java gnv-artifacts/src/main/java/de/intevation/gnv/state/cache/ThematicDataCacheCleaner.java
diffstat 5 files changed, 329 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- 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  <tim.englich@intevation.de>
+
+	* 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  <tim.englich@intevation.de>
 
 	* doc/conf/queries.properties: 
--- 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 <code>CacheFactory</code> 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();
         }
     }
 
--- 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();
     }
 
 
--- /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 <a href="mailto:tim.englich@intevation.de">Tim Englich</a>
+ *
+ */
+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);
+    }
+}
--- /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 <a href="mailto:tim.englich@intevation.de">Tim Englich</a>
+ *
+ */
+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<QueryObject> 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 <code>queryID</code>-Elements
+     * are used.
+     * The other Queries are currently not put into the Cache.
+     */
+    @Override
+    protected void setUp(){
+        super.setUp();
+        this.queryObjects = new ArrayList<QueryObject>();
+        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<QueryObject> 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 <code>stateId</code>
+     * 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<String> keys = cache.getKeys();
+        String keySample = StateBase.HASH_ID_SEPARATOR +
+                     stateId + 
+                     StateBase.HASH_ID_SEPARATOR;
+        if (keys != null && keys.size() > 0){
+            Iterator<String> 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");
+                    }
+                }
+            }
+        }
+    }
+}

http://dive4elements.wald.intevation.org