changeset 541:3cbf11c67fdc

Experimental caching of SQL results via Ehache geo-backend/trunk@462 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Fri, 18 Dec 2009 16:13:52 +0000
parents 27082b83c267
children f0b6d0e2a0f6
files geo-backend/ChangeLog geo-backend/contrib/sql-cache.xml geo-backend/pom.xml geo-backend/src/main/java/de/intevation/gnv/geobackend/base/query/CachingQueryExecutorFactory.java geo-backend/src/main/java/de/intevation/gnv/geobackend/base/query/DefaultQueryExceutor.java geo-backend/src/main/java/de/intevation/gnv/geobackend/base/query/QueryExecutor.java geo-backend/src/main/java/de/intevation/gnv/geobackend/base/query/QueryExecutorBase.java geo-backend/src/main/java/de/intevation/gnv/geobackend/base/query/QueryExecutorFactory.java geo-backend/src/main/java/de/intevation/gnv/geobackend/base/query/container/QueryContainerFactory.java
diffstat 9 files changed, 163 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- 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	<sascha.teichmann@intevation.de>
+2009-12-18	Sascha L. Teichmann	<sascha.teichmann@intevation.de>
+
+	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	<sascha.teichmann@intevation.de>
 
 	RELEASE 0.3
 
--- /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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ehcache>
+    <defaultCache 
+        maxElementsInMemory="100"
+        eternal="false"
+        overflowToDisk="true"
+        memoryStoreEvictionPolicy="LFU"
+        diskPersistent="true"
+        maxElementsOnDisk="256"
+        timeToIdleSeconds="10800"
+        timeToLiveSeconds="14400"
+        />
+</ehcache>
+
--- 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 @@
       <artifactId>jts</artifactId>
       <version>1.9</version>
     </dependency>
+    <dependency>
+      <groupId>net.sf.ehcache</groupId>
+      <artifactId>ehcache</artifactId>
+      <version>1.6.2</version>
+    </dependency>
   </dependencies>
   <repositories>
     <repository>
--- /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 <sascha.teichmann@intevation.de>
+ *
+ */
+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<Result> cachedResults(String query) {
+                Cache   cache   = manager.getCache(CACHE_NAME);
+                Element element = cache.get(query);
+                return element != null
+                    ? (Collection<Result>)element.getObjectValue()
+                    : null;
+            }
+
+            public void cacheResult(String query, Collection<Result> 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:
--- 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;
     }
 }
--- 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<Result> executeQuery(String queryID, String[] filter) throws QueryException;
+    Collection<Result> executeQuery(String queryID, String[] filter) throws QueryException;
+
+    Collection<Result> cachedResults(String query);
+
+    void cacheResults(String query, Collection<Result> results);
 }
--- 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<Result> cachedResults(String query) {
+        return null;
+    }
+
+    public void cacheResults(String query, Collection<Result> result) {
+    }
+
 }
--- 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;
--- 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();
         }

http://dive4elements.wald.intevation.org