changeset 1030:c07d9f9a738c

Removed bugs that existed in the caching mechanism (issue264, issue268). gnv-artifacts/trunk@1067 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Thu, 06 May 2010 08:32:56 +0000
parents a5e0384fe464
children cf510bd46188
files gnv-artifacts/ChangeLog gnv-artifacts/src/main/java/de/intevation/gnv/state/DefaultInputData.java gnv-artifacts/src/main/java/de/intevation/gnv/state/MeasurementState.java gnv-artifacts/src/main/java/de/intevation/gnv/state/OutputStateBase.java gnv-artifacts/src/main/java/de/intevation/gnv/state/StateBase.java gnv-artifacts/src/main/java/de/intevation/gnv/state/profile/horizontal/HorizontalProfileMeshCrossOutputState.java gnv-artifacts/src/main/java/de/intevation/gnv/state/profile/horizontalcrosssection/HorizontalCrossSectionMeshOutputState.java gnv-artifacts/src/main/java/de/intevation/gnv/state/profile/verticalcrosssection/VerticalCrossSectionOutputState.java
diffstat 8 files changed, 182 insertions(+), 85 deletions(-) [+]
line wrap: on
line diff
--- a/gnv-artifacts/ChangeLog	Tue May 04 14:24:23 2010 +0000
+++ b/gnv-artifacts/ChangeLog	Thu May 06 08:32:56 2010 +0000
@@ -1,3 +1,33 @@
+2010-05-06  Ingo Weinzierl <ingo.weinzierl@intevation.de>
+
+	  Issue264 & Issue268 (Removed bugs in the caching mechanism)
+
+	* src/main/java/de/intevation/gnv/state/DefaultInputData.java: Implemented
+	  hashCode() and equals(.) method. The hashCode() method is used while
+	  creating hashes for caching elements (see StateBase).
+
+	* src/main/java/de/intevation/gnv/state/StateBase.java: Improved hash
+	  creation. The hashes are used as keys for the caching mechanism. The key
+	  contains the uuid of the current artifact, the state id and a hash code
+	  created by InputData elements. User input is stored in a TreeMap instead
+	  of a HashMap, because the elements in a TreeMap are sorted. This is very
+	  import for us, because we need a defined order to create equal hashes if
+	  the input data elements, uuid and state id are equal.
+
+	* src/main/java/de/intevation/gnv/state/MeasurementState.java: Replaced the
+	  HashMap to store user input with a TreeMap which elements are sorted.
+
+	* src/main/java/de/intevation/gnv/state/profile/horizontalcrosssection/HorizontalCrossSectionMeshOutputState.java,
+	  src/main/java/de/intevation/gnv/state/profile/verticalcrosssection/VerticalCrossSectionOutputState.java:
+	  Added some more debug output that shows the usage of the cache.
+
+	* src/main/java/de/intevation/gnv/state/profile/horizontal/HorizontalProfileMeshCrossOutputState.java:
+	  Removed a critical bug that avoided using this product type if no cache
+	  have been initialized.
+
+	* src/main/java/de/intevation/gnv/state/OutputStateBase.java: Adjusted
+	  getHash(.) method call.
+
 2010-05-04  Tim Englich  <tim.englich@intevation.de>
 
 	* doc/conf/conf.xml: 
--- a/gnv-artifacts/src/main/java/de/intevation/gnv/state/DefaultInputData.java	Tue May 04 14:24:23 2010 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/state/DefaultInputData.java	Thu May 06 08:32:56 2010 +0000
@@ -161,5 +161,53 @@
         return null;
     }
 
+    @Override
+    public int hashCode() {
+        logger.debug("*************************************");
+        logger.debug("HashCode name: " + name);
+
+        int hash = 0;
+
+        hash ^= name.hashCode();
+
+        if (value != null) {
+            hash ^= value.hashCode() << 2;
+        }
+
+        if (object != null) {
+            hash ^= object.hashCode() << 4;
+        }
+
+        logger.debug("HashCode value: " + hash);
+        logger.debug("*************************************");
+
+        return hash;
+    }
+
+
+    @Override
+    public boolean equals(Object o) {
+        if (!(o instanceof DefaultInputData))
+            return false;
+
+        DefaultInputData other = (DefaultInputData) o;
+
+        if (!name.equals(other.name))
+            return false;
+
+        if ((value == null) && (other.value == null))
+            return false;
+
+        if (!value.equals(other.value))
+            return false;
+
+        if (!(object == null) && (other.object == null))
+            return false;
+
+        if (!(object == other.object))
+            return false;
+
+        return true;
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- a/gnv-artifacts/src/main/java/de/intevation/gnv/state/MeasurementState.java	Tue May 04 14:24:23 2010 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/state/MeasurementState.java	Thu May 06 08:32:56 2010 +0000
@@ -22,10 +22,10 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
+import java.util.TreeMap;
 
 import org.apache.log4j.Logger;
 
@@ -388,7 +388,7 @@
             }
 
             if (inputData == null) {
-                inputData = new HashMap<String, InputData>();
+                inputData = new TreeMap<String, InputData>();
             }
 
             ExtendedInputData extended = new ExtendedInputData(
--- a/gnv-artifacts/src/main/java/de/intevation/gnv/state/OutputStateBase.java	Tue May 04 14:24:23 2010 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/state/OutputStateBase.java	Thu May 06 08:32:56 2010 +0000
@@ -209,7 +209,7 @@
             // we use a cache
             log.info("Using cache.");
             Cache cache = factory.getCache();
-            String key  = "chart_" + getHash();
+            String key  = "chart_" + getHash(uuid);
 
             net.sf.ehcache.Element value = cache.get(key);
             if (value != null) {
@@ -242,7 +242,7 @@
         log.debug("Fetch chart [" + uuid + "] from cache");
         CacheFactory cacheFactory = CacheFactory.getInstance();
         if (cacheFactory.isInitialized()) {
-            String key = "chart_" + getHash();
+            String key = "chart_" + getHash(uuid);
             net.sf.ehcache.Element object = cacheFactory.getCache().get(key);
 
             if (object != null) {
@@ -302,7 +302,7 @@
     protected void removeChartResult(String uuid) {
         log.debug("OutputStateBase.getChartResult");
         if (CacheFactory.getInstance().isInitialized()) {
-            String key = "chart_" + getHash();
+            String key = "chart_" + getHash(uuid);
             log.debug("Hash for Queryelements: " + key);
             net.sf.ehcache.Element value = CacheFactory.getInstance().getCache().get(key);
             if (value != null) {
@@ -321,7 +321,7 @@
 
         CacheFactory cacheFactory = CacheFactory.getInstance();
         if (cacheFactory.isInitialized()) {
-            String key = "chart_" + getHash();
+            String key = "chart_" + getHash(uuid);
             net.sf.ehcache.Element object = cacheFactory.getCache().get(key);
             if (object != null)
                 cacheFactory.getCache().remove(key);
@@ -335,7 +335,7 @@
         log.debug("Prufify chart [" + uuid + "]");
         CacheFactory cacheFactory = CacheFactory.getInstance();
         if (cacheFactory.isInitialized()) {
-            String key = "chart_" + getHash();
+            String key = "chart_" + getHash(uuid);
             cacheFactory.getCache().put(new net.sf.ehcache.Element(key, chart));
         }
     }
--- a/gnv-artifacts/src/main/java/de/intevation/gnv/state/StateBase.java	Tue May 04 14:24:23 2010 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/state/StateBase.java	Thu May 06 08:32:56 2010 +0000
@@ -13,6 +13,8 @@
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
 
 import javax.xml.xpath.XPathConstants;
 
@@ -243,8 +245,7 @@
                 InputValue inputValue = this.inputValues.get(tmpItem.getName());
                 if (inputValue != null) {
                     if (this.inputData == null) {
-                        this.inputData = new HashMap<String, InputData>(
-                                inputData.size());
+                        this.inputData = new TreeMap<String, InputData>();
                     }
 
                     boolean valid = InputValidator.isInputValid(tmpItem.getValue(),
@@ -348,8 +349,7 @@
                 InputValue inputValue = this.inputValues.get(tmpItem.getName());
                 if (inputValue != null) {
                     if (this.inputData == null) {
-                        this.inputData = new HashMap<String, InputData>(
-                                inputData.size());
+                        this.inputData = new TreeMap<String, InputData>();
                     }
 
                     boolean valid = InputValidator.isInputValid(tmpItem.getValue(),
@@ -462,6 +462,7 @@
             InputData data = this.inputData.get(value);
             if (data != null
                 && this.inputValues.containsKey(data.getName())) {
+
                 int size = this.inputValues.get(data.getName())
                         .usedInQueries();
                 String type = this.inputValues.get(data.getName())
@@ -695,7 +696,7 @@
         String                  uuid)
     {
         State parent = getParent();
-        if (parent != null && parent instanceof StateBase) {
+        if (parent instanceof StateBase) {
             ((StateBase) parent).describeStatic(
                 artCreator, creator, document, staticNode, context, uuid);
         }
@@ -712,7 +713,7 @@
         Node                    staticNode,
         CallMeta                callMeta
     ) {
-        InputData  data = inputData.get(dataName);
+        InputData  data = dataName!= null ? inputData.get(dataName) : null;
 
         if (data == null) {
             return;
@@ -937,15 +938,25 @@
 
 
     protected void setHash(String uuid) {
-        this.hash = uuid +
-                    HASH_ID_SEPARATOR +
-                    id +
-                    HASH_ID_SEPARATOR +
-                    inputData.hashCode();
+        String newHash = uuid + HASH_ID_SEPARATOR + id + HASH_ID_SEPARATOR;
+        Set    keys    = inputData.keySet();
+
+        int nhash = 0;
+        int shift = 0;
+
+        for (Object o: keys) {
+            nhash ^= inputData.get(o).hashCode() << shift;
+            shift += 2;
+        }
+
+        log.info("### OLD HASH: " + hash);
+        log.info("### NEW HASH: " + (newHash + nhash));
+
+        this.hash = newHash + nhash;
     }
 
 
-    protected String getHash() {
+    protected String getHash(String uuid) {
         return this.hash;
     }
 
@@ -954,9 +965,10 @@
         CacheFactory factory = CacheFactory.getInstance();
         if (factory.isInitialized()) {
             // we use a cache
-            log.debug("Using cache.");
             Cache cache = factory.getCache();
-            String key  = getHash();
+            String key  = getHash(uuid);
+
+            log.debug("Using cache - key: " + key);
 
             net.sf.ehcache.Element value = cache.get(key);
             if (value != null) {
@@ -973,6 +985,7 @@
                     List<Object> data     = queryDatabase(filterValues, uuid);
 
                     cache.put(new net.sf.ehcache.Element(key, data));
+
                     return data;
                 }
                 catch (QueryException qe) {
--- a/gnv-artifacts/src/main/java/de/intevation/gnv/state/profile/horizontal/HorizontalProfileMeshCrossOutputState.java	Tue May 04 14:24:23 2010 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/state/profile/horizontal/HorizontalProfileMeshCrossOutputState.java	Thu May 06 08:32:56 2010 +0000
@@ -163,69 +163,73 @@
     @Override
     protected Object getChartResult(String uuid, CallContext callContext) {
         log.debug("HorizontalProfileMeshCrossOutputState.getChartResult");
-        Collection<Result> result = null;
-        if (CacheFactory.getInstance().isInitialized()) {
-            String key = uuid + super.getID();
-            log.debug("Hash for Queryelements: " + key);
-            net.sf.ehcache.Element value = CacheFactory.getInstance().getCache().get(key);
-            if (value != null) {
-                result = (Collection<Result>) (value.getObjectValue());
-            }else{
-
-                InputData meshLine = inputData.get("mesh_linestring");
-                InputData meshId   = inputData.get("meshid");
-
-                if (meshLine == null) {
-                    log.error("mesh_linestring is not defined");
-                    throw new IllegalStateException("missing mesh_linestring");
-                }
-
-                if (meshId == null) {
-                    log.error("meshid is not defined");
-                    throw new IllegalStateException("missing meshid");
-                }
-
-                Coordinate [] coords = WKTUtils.toCoordinates(
-                    meshLine.getValue());
-
-                if (coords == null) {
-                    throw new IllegalStateException("cannot read coordinates");
-                }
 
-                try {
-                    String additionWhere = USE_INDEX_BUFFER
-                        ? WKTUtils.worldCoordinatesToIndex(
-                            coords,
-                            result,
-                            meshId.getValue(),
-                            ijkQueryID)
-                        : WKTUtils.TRUE_EXPRESSION;
-
-                    String[] addedFilterValues = StringUtils.append(
-                        generateFilterValuesFromInputData(),
-                        additionWhere);
+        String key = getHash(uuid);
+        if (CacheFactory.getInstance().isInitialized()) {
+            log.debug("Using cache - key: " + key);
+            net.sf.ehcache.Element value = CacheFactory.getInstance().getCache().get(key);
 
-                    QueryExecutor queryExecutor = QueryExecutorFactory
-                        .getInstance()
-                        .getQueryExecutor();
-
-                    result = process(
-                        Arrays.asList(coords),
-						numSamples(callContext),
-                        queryExecutor.executeQuery(
-                        queryID,
-                        addedFilterValues));
-                }
-                catch (QueryException e) {
-                    log.error(e,e);
-                }
-
-                if (CacheFactory.getInstance().isInitialized()) {
-                    CacheFactory.getInstance().getCache().put(new net.sf.ehcache.Element(key, result));
-                }
-
+            if (value != null) {
+                log.debug("Found element in cache.");
+                return (Collection<Result>) (value.getObjectValue());
             }
         }
+
+        log.debug("Not using cache or element not found.");
+        Collection<Result> result = null;
+
+        InputData meshLine = inputData.get("mesh_linestring");
+        InputData meshId   = inputData.get("meshid");
+
+        if (meshLine == null) {
+            log.error("mesh_linestring is not defined");
+            throw new IllegalStateException("missing mesh_linestring");
+        }
+
+        if (meshId == null) {
+            log.error("meshid is not defined");
+            throw new IllegalStateException("missing meshid");
+        }
+
+        Coordinate [] coords = WKTUtils.toCoordinates(
+            meshLine.getValue());
+
+        if (coords == null) {
+            throw new IllegalStateException("cannot read coordinates");
+        }
+
+        try {
+            String additionWhere = USE_INDEX_BUFFER
+                ? WKTUtils.worldCoordinatesToIndex(
+                    coords,
+                    result,
+                    meshId.getValue(),
+                    ijkQueryID)
+                : WKTUtils.TRUE_EXPRESSION;
+
+            String[] addedFilterValues = StringUtils.append(
+                generateFilterValuesFromInputData(),
+                additionWhere);
+
+            QueryExecutor queryExecutor = QueryExecutorFactory
+                .getInstance()
+                .getQueryExecutor();
+
+            result = process(
+                Arrays.asList(coords),
+                numSamples(callContext),
+                queryExecutor.executeQuery(
+                queryID,
+                addedFilterValues));
+        }
+        catch (QueryException e) {
+            log.error(e,e);
+        }
+
+        if (CacheFactory.getInstance().isInitialized()) {
+            CacheFactory.getInstance().getCache().put(new net.sf.ehcache.Element(key, result));
+        }
+
         return result;
     }
 
--- a/gnv-artifacts/src/main/java/de/intevation/gnv/state/profile/horizontalcrosssection/HorizontalCrossSectionMeshOutputState.java	Tue May 04 14:24:23 2010 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/state/profile/horizontalcrosssection/HorizontalCrossSectionMeshOutputState.java	Thu May 06 08:32:56 2010 +0000
@@ -501,15 +501,18 @@
     throws StateException
     {
         CacheFactory cf  = CacheFactory.getInstance();
-        String       key = getHash();
+        String       key = getHash(uuid);
 
         if (cf.isInitialized()) {
+            log.debug("Using cache - key: " + key);
             net.sf.ehcache.Element value = cf.getCache().get(key);
             if (value != null) {
-                 return (AttributedPoint2ds)value.getObjectValue();
+                log.debug("Found element in cache.");
+                return (AttributedPoint2ds)value.getObjectValue();
             }
         }
 
+        log.debug("Not using cache or element not found.");
         AttributedPoint2ds result = produceResult(callContext);
 
         if (result != null && cf.isInitialized()) {
--- a/gnv-artifacts/src/main/java/de/intevation/gnv/state/profile/verticalcrosssection/VerticalCrossSectionOutputState.java	Tue May 04 14:24:23 2010 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/state/profile/verticalcrosssection/VerticalCrossSectionOutputState.java	Thu May 06 08:32:56 2010 +0000
@@ -158,12 +158,11 @@
     @Override
     protected Object getChartResult(String uuid, CallContext callContext) {
         log.debug("VerticalCrossSectionOutputState.getChartResult");
-        String key = getHash();
-        log.debug("Hash: "+key);
+        String key = getHash(uuid);
 
         CacheFactory factory = CacheFactory.getInstance();
         if (factory.isInitialized()) {
-            log.info("Using a cachce.");
+            log.info("Using a cachce - key: " + key);
             Cache cache = factory.getCache();
 
             Element element = cache.get(key);

http://dive4elements.wald.intevation.org