# HG changeset patch # User Sascha L. Teichmann # Date 1326735519 0 # Node ID f021080cb4094f95b3039485dc94a577b8997dd3 # Parent dc28ea60b53d2feea4ee1e282d90a5116698d366 Use improved caching for cross section lines data. flys-artifacts/trunk@3690 c6561f87-3c4e-4783-a992-168aeb5c3f6f diff -r dc28ea60b53d -r f021080cb409 flys-artifacts/ChangeLog --- a/flys-artifacts/ChangeLog Mon Jan 16 15:51:46 2012 +0000 +++ b/flys-artifacts/ChangeLog Mon Jan 16 17:38:39 2012 +0000 @@ -1,3 +1,36 @@ +2012-01-16 Sascha L. Teichmann + + Use improved caching for cross section data. + !!! This commit needs heavy testing !!! + + * src/main/java/de/intevation/flys/artifacts/services/CrossSectionKMService.java: + Refactored to provide the map to determine the nearest cross section line + neighbors for a given km to the public. This is a bit hackish because + it hhould have its own factory which is then used by this service and + other parts of the code. + + * src/main/java/de/intevation/flys/artifacts/CrossSectionArtifact.java: + searchCrossSectionLine() now returns a FastCrossSectionLine. To find this + line efficiently it uses the map of the CrossSectionKMService which + already provides a nearest neighbor searching mechanism for cross + section lines. The FastCrossSectionLine is fetched with the + FastCrossSectionLineFactory which uses a cache as described in the + previous commit. + + * src/main/java/de/intevation/flys/exports/CrossSectionGenerator.java + src/main/java/de/intevation/flys/artifacts/WaterLineArtifact.java, + src/main/java/de/intevation/flys/artifacts/model/CrossSectionWaterLineFacet.java, + src/main/java/de/intevation/flys/artifacts/StaticWKmsArtifact.java, + src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java: Uses + the FastCrossSectionLine instead of CrossSectionLines now. + + * src/main/java/de/intevation/flys/artifacts/model/FastCrossSectionLine.java: + Added method fetchCrossSectionProfile() to access the point data in + the profile generating compatible way. + + * src/main/java/de/intevation/flys/artifacts/ChartArtifact.java: Removed + superfluous import. + 2012-01-16 Sascha L. Teichmann * doc/conf/cache.xml: Added cache for fast section lines chunks. diff -r dc28ea60b53d -r f021080cb409 flys-artifacts/src/main/java/de/intevation/flys/artifacts/ChartArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/ChartArtifact.java Mon Jan 16 15:51:46 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/ChartArtifact.java Mon Jan 16 17:38:39 2012 +0000 @@ -25,7 +25,6 @@ import de.intevation.artifactdatabase.state.Output; import de.intevation.artifactdatabase.transition.TransitionEngine; -import de.intevation.flys.model.River; import de.intevation.flys.utils.FLYSUtils; import de.intevation.flys.artifacts.states.DefaultState; diff -r dc28ea60b53d -r f021080cb409 flys-artifacts/src/main/java/de/intevation/flys/artifacts/CrossSectionArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/CrossSectionArtifact.java Mon Jan 16 15:51:46 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/CrossSectionArtifact.java Mon Jan 16 17:38:39 2012 +0000 @@ -2,6 +2,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.NavigableMap; import org.apache.log4j.Logger; @@ -12,6 +13,8 @@ import de.intevation.artifacts.CallMeta; import de.intevation.flys.artifacts.model.CrossSectionFacet; +import de.intevation.flys.artifacts.model.FastCrossSectionLine; +import de.intevation.flys.artifacts.model.FastCrossSectionLineFactory; import de.intevation.flys.model.CrossSection; import de.intevation.flys.model.CrossSectionLine; @@ -26,6 +29,8 @@ import de.intevation.flys.utils.FLYSUtils; +import de.intevation.flys.artifacts.services.CrossSectionKMService; + /** * Artifact describing a cross-section. @@ -90,10 +95,14 @@ } List fs = new ArrayList(); - CrossSection cs = CrossSectionFactory.getCrossSection(Integer.valueOf(ids)); - CrossSectionLine csl = cs.getLines().get(0); - // Find min-km of cross sections, than set DATA_KM to min(DATA_KM, minCross). - if (csl != null) { + CrossSection cs = CrossSectionFactory.getCrossSection( + Integer.valueOf(ids)); + + List csls = cs.getLines(); + if (!csls.isEmpty()) { + CrossSectionLine csl = csls.get(0); + // Find min-km of cross sections, + // then set DATA_KM to min(DATA_KM, minCross). double masterKm = Double.valueOf(getDataAsString(DATA_KM)); if (masterKm < csl.getKm().doubleValue()) { addStringData(DATA_KM, csl.getKm().toString()); @@ -222,7 +231,7 @@ public double [][] getCrossSectionData() { logger.info("getCrossSectionData() for cross_section.km " + getDataAsString(DATA_KM)); - CrossSectionLine line = searchCrossSectionLine(); + FastCrossSectionLine line = searchCrossSectionLine(); return line != null ? line.fetchCrossSectionProfile() @@ -236,27 +245,35 @@ * * @return CrossSectionLine closest to "cross_section.km". */ - public CrossSectionLine searchCrossSectionLine() { - double wishKM = getKm(); + public FastCrossSectionLine searchCrossSectionLine() { - CrossSection crossSection = CrossSectionFactory.getCrossSection(getDBID()); - logger.debug("dbid " + getDBID() + " : " + crossSection); - List crossSectionLines = - crossSection.getLines(); - - // Get the cross section closest to requested km. - // Naive, linear approach. - CrossSectionLine oldLine = crossSectionLines.get(0); - double oldDiff = Math.abs(wishKM - oldLine.getKm().doubleValue()); - for (CrossSectionLine line: crossSectionLines) { - double diff = Math.abs(wishKM - line.getKm().doubleValue()); - if (diff > oldDiff) { - break; - } - oldDiff = diff; - oldLine = line; + CrossSection crossSection = CrossSectionFactory + .getCrossSection(getDBID()); + + if (logger.isDebugEnabled()) { + logger.debug("dbid " + getDBID() + " : " + crossSection); } - return oldLine; + + NavigableMap kms = CrossSectionKMService + .getKms(crossSection.getId()); + + Double wishKM = getKm(); + + Double floor = kms.floorKey(wishKM); + Double ceil = kms.ceilingKey(wishKM); + + double floorD = floor != null + ? Math.abs(floor - wishKM) + : Double.MAX_VALUE; + + double ceilD = ceil != null + ? Math.abs(ceil - wishKM) + : Double.MAX_VALUE; + + double km = floorD < ceilD ? floor : ceil; + + return FastCrossSectionLineFactory + .getCrossSectionLine(crossSection, km); } diff -r dc28ea60b53d -r f021080cb409 flys-artifacts/src/main/java/de/intevation/flys/artifacts/StaticWKmsArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/StaticWKmsArtifact.java Mon Jan 16 15:51:46 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/StaticWKmsArtifact.java Mon Jan 16 17:38:39 2012 +0000 @@ -30,7 +30,8 @@ import de.intevation.artifacts.common.utils.XMLUtils; import de.intevation.flys.geom.Lines; -import de.intevation.flys.model.CrossSectionLine; + +import de.intevation.flys.artifacts.model.FastCrossSectionLine; /** * Artifact to access additional "waterlevel"-type of data, like the height @@ -256,14 +257,15 @@ * @return an array holding coordinates of points of surface of water ( * in the form {{x1, x2} {y1, y2}} ). */ - public double [][] getWaterLines(int idx, CrossSectionLine csl) { + @Override + public double [][] getWaterLines(int idx, FastCrossSectionLine csl) { logger.debug("getWaterLines(" + idx + ")"); - List points = csl.fetchCrossSectionLinesPoints(); + List points = csl.getPoints(); WKms wkms = getWKms(0); - double km = csl.getKm().doubleValue(); + double km = csl.getKm(); // Find W at km. double wAtKm = getWAtKm(wkms, km); diff -r dc28ea60b53d -r f021080cb409 flys-artifacts/src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java Mon Jan 16 15:51:46 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java Mon Jan 16 17:38:39 2012 +0000 @@ -36,6 +36,7 @@ import de.intevation.flys.artifacts.model.WQKms; import de.intevation.flys.artifacts.model.WstValueTable; import de.intevation.flys.artifacts.model.WstValueTableFactory; +import de.intevation.flys.artifacts.model.FastCrossSectionLine; import de.intevation.flys.artifacts.states.DefaultState; import de.intevation.flys.artifacts.states.LocationDistanceSelect; @@ -44,7 +45,6 @@ import de.intevation.flys.model.Gauge; import de.intevation.flys.model.River; -import de.intevation.flys.model.CrossSectionLine; import de.intevation.flys.utils.DoubleUtil; import de.intevation.flys.utils.FLYSUtils; @@ -660,10 +660,10 @@ * @return an array holding coordinates of points of surface of water ( * in the form {{x1, x2} {y1, y2}} ). */ - public double [][] getWaterLines(int idx, CrossSectionLine csl) { + public double [][] getWaterLines(int idx, FastCrossSectionLine csl) { logger.debug("getWaterLines(" + idx + ")"); - List points = csl.fetchCrossSectionLinesPoints(); + List points = csl.getPoints(); // Need W at km WQKms [] wqkms = (WQKms[]) getWaterlevelData().getData(); @@ -681,7 +681,7 @@ WQKms triple = wqkms[idx]; // Find index of km. - double wishKM = csl.getKm().doubleValue(); + double wishKM = csl.getKm(); int old_idx = 0; if (triple.size() == 0) { diff -r dc28ea60b53d -r f021080cb409 flys-artifacts/src/main/java/de/intevation/flys/artifacts/WaterLineArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WaterLineArtifact.java Mon Jan 16 15:51:46 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WaterLineArtifact.java Mon Jan 16 17:38:39 2012 +0000 @@ -1,13 +1,14 @@ package de.intevation.flys.artifacts; -import de.intevation.flys.model.CrossSectionLine; + +import de.intevation.flys.artifacts.model.FastCrossSectionLine; /** - * Interfacet, Artifact can create WaterLines (Water against Cross-Profile). + * Interface, Artifact can create WaterLines (Water against Cross-Profile). */ public interface WaterLineArtifact { /** Get points that define a line of a (water)facet against a cross- * section. */ - public double [][] getWaterLines(int facetIdx, CrossSectionLine csl); + public double [][] getWaterLines(int facetIdx, FastCrossSectionLine csl); } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r dc28ea60b53d -r f021080cb409 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/CrossSectionWaterLineFacet.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/CrossSectionWaterLineFacet.java Mon Jan 16 15:51:46 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/CrossSectionWaterLineFacet.java Mon Jan 16 17:38:39 2012 +0000 @@ -4,8 +4,6 @@ import java.util.List; -import de.intevation.flys.model.CrossSectionLine; - import de.intevation.artifacts.Artifact; import de.intevation.artifacts.CallContext; @@ -14,6 +12,7 @@ import de.intevation.flys.artifacts.WaterLineArtifact; +import de.intevation.flys.artifacts.model.FastCrossSectionLine; /** * Facet for Waterlines in Cross Sections. @@ -49,7 +48,7 @@ WaterLineArtifact winfo = (WaterLineArtifact)artifact; - return winfo.getWaterLines(this.getIndex(), (CrossSectionLine) crossSection); + return winfo.getWaterLines(this.getIndex(), (FastCrossSectionLine) crossSection); } diff -r dc28ea60b53d -r f021080cb409 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FastCrossSectionLine.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FastCrossSectionLine.java Mon Jan 16 15:51:46 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FastCrossSectionLine.java Mon Jan 16 17:38:39 2012 +0000 @@ -59,5 +59,9 @@ public void setPoints(List points) { this.points = points; } + + public double [][] fetchCrossSectionProfile() { + return CrossSectionLine.fetchCrossSectionProfile(points); + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r dc28ea60b53d -r f021080cb409 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/CrossSectionKMService.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/CrossSectionKMService.java Mon Jan 16 15:51:46 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/CrossSectionKMService.java Mon Jan 16 17:38:39 2012 +0000 @@ -76,8 +76,6 @@ NodeList crossSectionNodes = data.getElementsByTagName("art:cross-section"); - Cache cache = CacheFactory.getCache(CACHE_NAME); - Document document = XMLUtils.newDocument(); Element all = document.createElement("cross-sections"); @@ -111,25 +109,7 @@ continue; } - NavigableMap map; - - if (cache == null) { - map = getUncached(crossSectionId); - } - else { - net.sf.ehcache.Element element = cache.get(crossSectionId); - if (element == null) { - map = getUncached(crossSectionId); - if (map != null) { - element = new net.sf.ehcache.Element( - crossSectionId, map); - cache.put(element); - } - } - else { - map = (NavigableMap)element.getValue(); - } - } + NavigableMap map = getKms(crossSectionId); if (map == null) { logger.debug("cannot find cross section " + crossSectionId); @@ -159,6 +139,32 @@ return document; } + public static NavigableMap getKms(int crossSectionId) { + + Cache cache = CacheFactory.getCache(CACHE_NAME); + + if (cache == null) { + return getUncached(crossSectionId); + } + + NavigableMap map; + + net.sf.ehcache.Element element = cache.get(crossSectionId); + if (element == null) { + map = getUncached(crossSectionId); + if (map != null) { + element = new net.sf.ehcache.Element( + crossSectionId, map); + cache.put(element); + } + } + else { + map = (NavigableMap)element.getValue(); + } + + return map; + } + /** * @param km the kilometer from which to start searching for other @@ -173,9 +179,10 @@ Deque> result = new ArrayDeque>(2*N); - if(map.get(km) != null) { - result.add(new AbstractMap.SimpleEntry(km,map.get(km))); + Integer v = map.get(km); + if (v != null) { + result.add(new AbstractMap.SimpleEntry(km, v)); } int i = 0; diff -r dc28ea60b53d -r f021080cb409 flys-artifacts/src/main/java/de/intevation/flys/exports/CrossSectionGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/CrossSectionGenerator.java Mon Jan 16 15:51:46 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/CrossSectionGenerator.java Mon Jan 16 17:38:39 2012 +0000 @@ -14,12 +14,12 @@ import de.intevation.artifactdatabase.state.ArtifactAndFacet; -import de.intevation.flys.model.CrossSectionLine; - import de.intevation.flys.artifacts.model.FacetTypes; import de.intevation.flys.artifacts.model.CrossSectionFacet; import de.intevation.flys.jfree.StyledXYSeries; +import de.intevation.flys.artifacts.model.FastCrossSectionLine; + /** * An OutGenerator that generates cross section graphs. */ @@ -96,10 +96,10 @@ context.getDataProvider(CrossSectionFacet.BLACKBOARD_CS_MASTER_DATA); double km = 0d; if (providers.size() > 0) { - CrossSectionLine csl = (CrossSectionLine) providers.get(0). + FastCrossSectionLine csl = (FastCrossSectionLine) providers.get(0). provideData(CrossSectionFacet.BLACKBOARD_CS_MASTER_DATA, null, context); - km = csl.getKm().doubleValue(); + km = csl.getKm(); } Object[] args = new Object[] {