# HG changeset patch # User Sascha L. Teichmann # Date 1311353736 0 # Node ID 0c8aca463bd4a491a1d732d2acff5ec6e05869a9 # Parent d0c9a5f32c30febeeb0a3ebf8f967d26e5efdfed Added caching support for the static part of the datacage. flys-artifacts/trunk@2398 c6561f87-3c4e-4783-a992-168aeb5c3f6f diff -r d0c9a5f32c30 -r 0c8aca463bd4 flys-artifacts/ChangeLog --- a/flys-artifacts/ChangeLog Fri Jul 22 11:18:00 2011 +0000 +++ b/flys-artifacts/ChangeLog Fri Jul 22 16:55:36 2011 +0000 @@ -1,3 +1,24 @@ +2011-07-21 Sascha L. Teichmann + + * doc/conf/cache.xml: Added configuration for static datacage db access. + + * src/main/java/de/intevation/flys/artifacts/services/meta/App.java: Using + caches seems to need an explicit System.exit(). + + * src/main/java/de/intevation/flys/artifacts/services/meta/CompiledStatement.java: + Added support for caching the SQL statements and there results. + + * src/main/java/de/intevation/flys/artifacts/services/meta/Builder.java: Some + clean up. Reordered code for performance. Strip SQL statements more + aggressively. + + * src/main/java/de/intevation/flys/artifacts/services/meta/ResultData.java: + Made it Serializable. + + * src/main/java/de/intevation/flys/artifacts/cache/CacheFactory.java: + Introduced system property 'flys.artifacts.cache.config.file' to make + the caching configurable without pulling up the whole stack. + 2011-07-22 Ingo Weinzierl * src/main/java/de/intevation/flys/collections/FLYSArtifactCollection.java: diff -r d0c9a5f32c30 -r 0c8aca463bd4 flys-artifacts/doc/conf/cache.xml --- a/flys-artifacts/doc/conf/cache.xml Fri Jul 22 11:18:00 2011 +0000 +++ b/flys-artifacts/doc/conf/cache.xml Fri Jul 22 16:55:36 2011 +0000 @@ -46,4 +46,12 @@ diskPersistent="true" memoryStoreEvictionPolicy="LRU" /> + + + diff -r d0c9a5f32c30 -r 0c8aca463bd4 flys-artifacts/src/main/java/de/intevation/flys/artifacts/cache/CacheFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/cache/CacheFactory.java Fri Jul 22 11:18:00 2011 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/cache/CacheFactory.java Fri Jul 22 16:55:36 2011 +0000 @@ -12,6 +12,9 @@ { private static Logger log = Logger.getLogger(CacheFactory.class); + public static final String CACHE_CONFIG_FILE_PROPERTY = + "flys.artifacts.cache.config.file"; + public static final String XPATH_CACHE_CONFIG_FILE = "/artifact-database/cache/config-file/text()"; @@ -26,12 +29,27 @@ return getCache(Cache.DEFAULT_CACHE_NAME); } + public static final String getConfigFile() { + String configFile = System.getProperty(CACHE_CONFIG_FILE_PROPERTY); + + if (configFile != null) { + return configFile; + } + + configFile = Config.getStringXPath(XPATH_CACHE_CONFIG_FILE); + + if (configFile != null) { + configFile = Config.replaceConfigDir(configFile); + } + + return configFile; + } + public static final synchronized Cache getCache(String cacheName) { if (!initialized) { initialized = true; // try only once - String configFile = Config.getStringXPath(XPATH_CACHE_CONFIG_FILE); + String configFile = getConfigFile(); if (configFile != null) { - configFile = Config.replaceConfigDir(configFile); try { cacheManager = CacheManager.create(configFile); //System.setProperty( diff -r d0c9a5f32c30 -r 0c8aca463bd4 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/App.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/App.java Fri Jul 22 11:18:00 2011 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/App.java Fri Jul 22 16:55:36 2011 +0000 @@ -112,6 +112,7 @@ } } } + System.exit(0); } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r d0c9a5f32c30 -r 0c8aca463bd4 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/Builder.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/Builder.java Fri Jul 22 11:18:00 2011 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/Builder.java Fri Jul 22 16:55:36 2011 +0000 @@ -1,5 +1,6 @@ package de.intevation.flys.artifacts.services.meta; +import java.util.regex.Pattern; import java.util.regex.Matcher; import java.util.ArrayList; @@ -28,6 +29,9 @@ { private static Logger log = Logger.getLogger(Builder.class); + public static final Pattern STRIP_LINE_INDENT = + Pattern.compile("\\s*\\r?\\n\\s*"); + public static final String DC_NAMESPACE_URI = "http://www.intevation.org/2011/Datacage"; @@ -39,11 +43,6 @@ protected Document template; - protected static Document getOwnerDocument(Node node) { - Document document = node.getOwnerDocument(); - return document != null ? document : (Document)node; - } - public class BuildHelper { @@ -109,7 +108,7 @@ String stmntText = stmntNode.item(0).getTextContent(); if (stmntText == null - || (stmntText = stmntText.trim()).length() == 0) { + || (stmntText = trimStatement(stmntText)).length() == 0) { log.warn("dc:context: no sql statement found -> ignored"); return; } @@ -335,17 +334,23 @@ } else { String localName = current.getLocalName(); - if ("context".equals(localName)) { + if ("attribute".equals(localName)) { + attribute(parent, (Element)current); + } + else if ("context".equals(localName)) { context(parent, (Element)current); } + else if ("if".equals(localName)) { + ifClause(parent, (Element)current); + } else if ("choose".equals(localName)) { choose(parent, (Element)current); } - else if ("if".equals(localName)) { - ifClause(parent, (Element)current); + else if ("call-macro".equals(localName)) { + callMacro(parent, (Element)current); } - else if ("attribute".equals(localName)) { - attribute(parent, (Element)current); + else if ("macro".equals(localName)) { + // simply ignore the definition. } else if ("element".equals(localName)) { element(parent, (Element)current); @@ -356,12 +361,6 @@ else if ("convert".equals(localName)) { convert(parent, (Element)current); } - else if ("call-macro".equals(localName)) { - callMacro(parent, (Element)current); - } - else if ("macro".equals(localName)) { - // simply ignore the definition. - } else { log.warn("unknown '" + localName + "' -> ignore"); } @@ -411,6 +410,16 @@ return elements; } + protected static final String trimStatement(String stmnt) { + //XXX: Maybe a bit to radical for multiline strings? + return STRIP_LINE_INDENT.matcher(stmnt.trim()).replaceAll(" "); + } + + protected static Document getOwnerDocument(Node node) { + Document document = node.getOwnerDocument(); + return document != null ? document : (Document)node; + } + public void build( Connection connection, Node output, diff -r d0c9a5f32c30 -r 0c8aca463bd4 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/CompiledStatement.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/CompiledStatement.java Fri Jul 22 11:18:00 2011 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/CompiledStatement.java Fri Jul 22 16:55:36 2011 +0000 @@ -5,7 +5,7 @@ import java.util.List; import java.util.Map; -import java.util.HashMap; +import java.util.TreeMap; import java.util.ArrayList; import java.sql.PreparedStatement; @@ -13,8 +13,16 @@ import java.sql.Connection; import java.sql.ResultSet; +import net.sf.ehcache.Cache; +import net.sf.ehcache.Element; + +import de.intevation.flys.artifacts.cache.CacheFactory; + public class CompiledStatement { + public static final String DATACAGE_DB_CACHE = + "datacage.db"; + public static final Pattern VAR = Pattern.compile("\\$\\{([a-zA-Z0-9_-]+)\\}"); @@ -25,12 +33,15 @@ protected PreparedStatement preparedStatement; + protected int numVars; + public CompiledStatement() { } public CompiledStatement(String original) { this.original = original; - positions = new HashMap>(); + // TreeMap to ensure order + positions = new TreeMap>(); compile(); } @@ -40,7 +51,7 @@ Matcher m = VAR.matcher(original); - int index = 1; + int index = 0; while (m.find()) { String key = m.group(1); @@ -56,6 +67,8 @@ m.appendTail(sb); + numVars = index; + statement = sb.toString(); } @@ -63,7 +76,65 @@ return statement; } - public ResultData execute(Connection connection, StackFrames frames) + protected ResultData executeCached( + Cache cache, + Connection connection, + StackFrames frames + ) + throws SQLException + { + Object [] values = new Object[numVars]; + + StringBuilder sb = new StringBuilder(original); + + for (Map.Entry> entry: positions.entrySet()) { + String key = entry.getKey(); + Object value = frames.get(key); + sb.append(';').append(key).append(':').append(value); + for (Integer index: entry.getValue()) { + values[index] = value; + } + } + + // XXX: Maybe too many collisions? + // String key = original + Arrays.hashCode(values); + String key = sb.toString(); + + Element element = cache.get(key); + + if (element != null) { + return (ResultData)element.getValue(); + } + + if (preparedStatement == null) { + preparedStatement = connection.prepareStatement(statement); + } + + for (int i = 0; i < values.length; ++i) { + preparedStatement.setObject(i+1, values[i]); + } + + ResultData data; + + ResultSet result = preparedStatement.executeQuery(); + try { + data = new ResultData(preparedStatement.getMetaData()) + .addAll(result); + } + finally { + result.close(); + } + + element = new Element(key, data); + cache.put(element); + + return data; + } + + protected ResultData executeUncached( + Connection connection, + StackFrames frames + ) throws SQLException { if (preparedStatement == null) { @@ -73,7 +144,7 @@ for (Map.Entry> entry: positions.entrySet()) { Object value = frames.get(entry.getKey()); for (Integer index: entry.getValue()) { - preparedStatement.setObject(index, value); + preparedStatement.setObject(index+1, value); } } @@ -87,6 +158,16 @@ } } + public ResultData execute(Connection connection, StackFrames frames) + throws SQLException + { + Cache cache = CacheFactory.getCache(DATACAGE_DB_CACHE); + + return cache != null + ? executeCached(cache, connection, frames) + : executeUncached(connection, frames); + } + public void close() { if (preparedStatement != null) { try { diff -r d0c9a5f32c30 -r 0c8aca463bd4 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/ResultData.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/ResultData.java Fri Jul 22 11:18:00 2011 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/ResultData.java Fri Jul 22 16:55:36 2011 +0000 @@ -1,5 +1,7 @@ package de.intevation.flys.artifacts.services.meta; +import java.io.Serializable; + import java.sql.ResultSetMetaData; import java.sql.ResultSet; import java.sql.SQLException; @@ -8,6 +10,7 @@ import java.util.ArrayList; public class ResultData +implements Serializable { protected String [] columns;