# HG changeset patch # User Sascha L. Teichmann # Date 1261152832 0 # Node ID 3cbf11c67fdc0f6fd30f36573e8f944ce2a7c1a6 # Parent 27082b83c2677503b0c31927158aa1fcc93ea491 Experimental caching of SQL results via Ehache geo-backend/trunk@462 c6561f87-3c4e-4783-a992-168aeb5c3f6f diff -r 27082b83c267 -r 3cbf11c67fdc geo-backend/ChangeLog --- a/geo-backend/ChangeLog Thu Dec 17 14:35:02 2009 +0000 +++ b/geo-backend/ChangeLog Fri Dec 18 16:13:52 2009 +0000 @@ -1,4 +1,43 @@ -2009-12-171 Sascha L. Teichmann +2009-12-18 Sascha L. Teichmann + + Experimental caching of SQL results via Ehache + + * pom.xml: Added dependency to Ehcache + + * src/main/java/de/intevation/gnv/geobackend/base/query/QueryExecutor.java: + Extended interface to support caching by SQL statements as Strings. + + * src/main/java/de/intevation/gnv/geobackend/base/query/QueryExecutorBase.java: + Implements new interface with no caching + + * src/main/java/de/intevation/gnv/geobackend/base/query/container/QueryContainerFactory.java: + synchronized access to singleton. + + * src/main/java/de/intevation/gnv/geobackend/base/query/DefaultQueryExceutor.java: + calls caching methods of base class. + + * src/main/java/de/intevation/gnv/geobackend/base/query/QueryExecutorFactory.java: + When system property 'query.executor.factory' is given the value is used as + a class name to be instantiated as a sub class of QueryExecutorFactory. + This happens if the singleton of QueryExecutorFactory is created. With the + mechanism it is possible to replace the standard behavior of creating QueryExecutors. + + * src/main/java/de/intevation/gnv/geobackend/base/query/CachingQueryExecutorFactory.java: + New: This class extends QueryExecutorFactory and can be used as replacement for + the standard QueryExecutorFactory. Usage: + + -Dquery.executor.factory=de.intevation.gnv.geobackend.base.query.CachingQueryExecutorFactory + + If you pass in another system property 'caching.query.executor.config' you can + customize the caching. The value is used as a file name to an XML file with + Ehcache configuration. + + * contrib/sql-cache.xml: Demo configuration for sql caching. Usage: + + -Dquery.executor.factory=de.intevation.gnv.geobackend.base.query.CachingQueryExecutorFactory + -Dcaching.query.executor.config=contrib/sql-cache.xml + +2009-12-17 Sascha L. Teichmann RELEASE 0.3 diff -r 27082b83c267 -r 3cbf11c67fdc geo-backend/contrib/sql-cache.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/geo-backend/contrib/sql-cache.xml Fri Dec 18 16:13:52 2009 +0000 @@ -0,0 +1,14 @@ + + + + + diff -r 27082b83c267 -r 3cbf11c67fdc geo-backend/pom.xml --- a/geo-backend/pom.xml Thu Dec 17 14:35:02 2009 +0000 +++ b/geo-backend/pom.xml Fri Dec 18 16:13:52 2009 +0000 @@ -66,6 +66,11 @@ jts 1.9 + + net.sf.ehcache + ehcache + 1.6.2 + diff -r 27082b83c267 -r 3cbf11c67fdc geo-backend/src/main/java/de/intevation/gnv/geobackend/base/query/CachingQueryExecutorFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/geo-backend/src/main/java/de/intevation/gnv/geobackend/base/query/CachingQueryExecutorFactory.java Fri Dec 18 16:13:52 2009 +0000 @@ -0,0 +1,50 @@ +package de.intevation.gnv.geobackend.base.query; + +import java.util.Collection; + +import net.sf.ehcache.Cache; +import net.sf.ehcache.Element; +import net.sf.ehcache.CacheManager; + + +import de.intevation.gnv.geobackend.base.Result; + +/** + * @author Sascha L. Teichmann + * + */ +public class CachingQueryExecutorFactory +extends QueryExecutorFactory +{ + public static final String QUERY_EXECUTOR_FACTORY = "caching.query.executor.config"; + public static final String CACHE_NAME = "sql.cache"; + + protected CacheManager manager; + + public CachingQueryExecutorFactory() { + String configFile = System.getProperty(QUERY_EXECUTOR_FACTORY); + manager = configFile != null + ? new CacheManager(configFile) + : new CacheManager(); + manager.addCache(CACHE_NAME); + } + + public QueryExecutor getQueryExecutor() { + return new DefaultQueryExceutor() { + + public Collection cachedResults(String query) { + Cache cache = manager.getCache(CACHE_NAME); + Element element = cache.get(query); + return element != null + ? (Collection)element.getObjectValue() + : null; + } + + public void cacheResult(String query, Collection results) { + Cache cache = manager.getCache(CACHE_NAME); + cache.put(new Element(query, results)); + } + }; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8: diff -r 27082b83c267 -r 3cbf11c67fdc geo-backend/src/main/java/de/intevation/gnv/geobackend/base/query/DefaultQueryExceutor.java --- a/geo-backend/src/main/java/de/intevation/gnv/geobackend/base/query/DefaultQueryExceutor.java Thu Dec 17 14:35:02 2009 +0000 +++ b/geo-backend/src/main/java/de/intevation/gnv/geobackend/base/query/DefaultQueryExceutor.java Fri Dec 18 16:13:52 2009 +0000 @@ -58,9 +58,18 @@ queryString = super.setFilterValues(queryString, filter); } - log.debug("############ QUERY ##################"); - log.debug(queryString); - log.debug("#######################################"); + if (log.isDebugEnabled()) { + log.debug("############ QUERY ##################"); + log.debug(queryString); + log.debug("#######################################"); + } + + returnValue = cachedResults(queryString); + + if (returnValue != null) { + return returnValue; + } + Connection connection = null; ConnectionPool connectionPool = ConnectionPoolFactory.getInstance().getConnectionPool(); try { @@ -75,6 +84,8 @@ log.error("Could not establish Databaseconnection."); throw new QueryException("Could not establish Databaseconnection."); } + + cacheResults(queryString, returnValue); } catch (ConnectionException e) { log.error(e,e); @@ -101,6 +112,7 @@ log.error(e,e); throw new QueryException("Cannot get the Querystring",e); } + return returnValue; } } diff -r 27082b83c267 -r 3cbf11c67fdc geo-backend/src/main/java/de/intevation/gnv/geobackend/base/query/QueryExecutor.java --- a/geo-backend/src/main/java/de/intevation/gnv/geobackend/base/query/QueryExecutor.java Thu Dec 17 14:35:02 2009 +0000 +++ b/geo-backend/src/main/java/de/intevation/gnv/geobackend/base/query/QueryExecutor.java Fri Dec 18 16:13:52 2009 +0000 @@ -25,5 +25,9 @@ * @return the fetched Values * @throws QueryException */ - public Collection executeQuery(String queryID, String[] filter) throws QueryException; + Collection executeQuery(String queryID, String[] filter) throws QueryException; + + Collection cachedResults(String query); + + void cacheResults(String query, Collection results); } diff -r 27082b83c267 -r 3cbf11c67fdc geo-backend/src/main/java/de/intevation/gnv/geobackend/base/query/QueryExecutorBase.java --- a/geo-backend/src/main/java/de/intevation/gnv/geobackend/base/query/QueryExecutorBase.java Thu Dec 17 14:35:02 2009 +0000 +++ b/geo-backend/src/main/java/de/intevation/gnv/geobackend/base/query/QueryExecutorBase.java Fri Dec 18 16:13:52 2009 +0000 @@ -94,4 +94,11 @@ return result; } + public Collection cachedResults(String query) { + return null; + } + + public void cacheResults(String query, Collection result) { + } + } diff -r 27082b83c267 -r 3cbf11c67fdc geo-backend/src/main/java/de/intevation/gnv/geobackend/base/query/QueryExecutorFactory.java --- a/geo-backend/src/main/java/de/intevation/gnv/geobackend/base/query/QueryExecutorFactory.java Thu Dec 17 14:35:02 2009 +0000 +++ b/geo-backend/src/main/java/de/intevation/gnv/geobackend/base/query/QueryExecutorFactory.java Fri Dec 18 16:13:52 2009 +0000 @@ -10,6 +10,8 @@ * */ public class QueryExecutorFactory { + + public static final String QUERY_EXECUTOR_FACTORY = "query.executor.factory"; /** * the logger, used to log exceptions and additonaly information @@ -25,7 +27,7 @@ /** * Basic-Constructor of this Class */ - private QueryExecutorFactory() { + public QueryExecutorFactory() { super(); } @@ -33,8 +35,29 @@ * This Method provides an singleton Instance of this Class. * @return an singleton Instance of this Class */ - public static QueryExecutorFactory getInstance(){ - if (instance == null){ + public static synchronized QueryExecutorFactory getInstance(){ + if (instance == null) { + String className = System.getProperty(QUERY_EXECUTOR_FACTORY); + if (className != null) { + try { + Class clazz = Class.forName(className); + instance = (QueryExecutorFactory)clazz.newInstance(); + return instance; + } + catch (ClassNotFoundException cnfe) { + log.error(cnfe); + } + catch (InstantiationException ie) { + log.error(ie); + } + catch(IllegalAccessException iae) { + log.error(iae); + } + catch (ClassCastException cce) { + log.error(cce); + } + } + instance = new QueryExecutorFactory(); } return instance; diff -r 27082b83c267 -r 3cbf11c67fdc geo-backend/src/main/java/de/intevation/gnv/geobackend/base/query/container/QueryContainerFactory.java --- a/geo-backend/src/main/java/de/intevation/gnv/geobackend/base/query/container/QueryContainerFactory.java Thu Dec 17 14:35:02 2009 +0000 +++ b/geo-backend/src/main/java/de/intevation/gnv/geobackend/base/query/container/QueryContainerFactory.java Fri Dec 18 16:13:52 2009 +0000 @@ -42,7 +42,7 @@ * This Method provides an singleton Instance of this Class. * @return an singleton Instance of this Class */ - public static QueryContainerFactory getInstance(){ + public static synchronized QueryContainerFactory getInstance(){ if (instance == null){ instance = new QueryContainerFactory(); }