Hi,
I've recently found users that have stores using thread locals, either the
Dispatcher.REQUEST or
other thread locals set in servlet filters, that are then needed during the
data access (yeah, I know,
I know, that breaks proper layering, however these store are applying
different behaviors depending
on the service that is used to access them, wms or wfs).

Unfortunately the renderer now is threaded and normally in GS it uses a
global thread pool,
meaning that during data access within the renderer one does not get to see
the thread locals
anymore. In particular Dispatcher.REQUEST is not accessible anymore.

Solution: disable the global thread pool under request (system variable) so
that a new small
thread pool is created from the current thread instead, and make Dispatcher
an inheritable
thread local, so that it can be seen from the child threads as well.

Patch attached. Seems innocuous to me, what do you think?

Cheers
Andrea

-- 
-------------------------------------------------------
Ing. Andrea Aime
GeoSolutions S.A.S.
Tech lead

Via Poggio alle Viti 1187
55054  Massarosa (LU)
Italy

phone: +39 0584 962313
fax:      +39 0584 962313
mob:    +39 333 8128928

http://www.geo-solutions.it
http://geo-solutions.blogspot.com/
http://www.youtube.com/user/GeoSolutionsIT
http://www.linkedin.com/in/andreaaime
http://twitter.com/geowolf

-------------------------------------------------------
diff --git a/src/ows/src/main/java/org/geoserver/ows/Dispatcher.java b/src/ows/src/main/java/org/geoserver/ows/Dispatcher.java
index 5e6c27f..34492f7 100644
--- a/src/ows/src/main/java/org/geoserver/ows/Dispatcher.java
+++ b/src/ows/src/main/java/org/geoserver/ows/Dispatcher.java
@@ -116,7 +116,7 @@ public class Dispatcher extends AbstractController {
     boolean citeCompliant = false;
 
     /** thread local variable for the request */
-    public static final ThreadLocal<Request> REQUEST = new ThreadLocal<Request>();
+    public static final ThreadLocal<Request> REQUEST = new InheritableThreadLocal<Request>();
     
     static final Charset UTF8 = Charset.forName("UTF-8");
     
diff --git a/src/wms/src/main/java/org/geoserver/wms/DefaultWebMapService.java b/src/wms/src/main/java/org/geoserver/wms/DefaultWebMapService.java
index 6d3aee3..be24bf3 100644
--- a/src/wms/src/main/java/org/geoserver/wms/DefaultWebMapService.java
+++ b/src/wms/src/main/java/org/geoserver/wms/DefaultWebMapService.java
@@ -34,7 +34,6 @@ import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.operation.TransformException;
 import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.DisposableBean;
-import org.springframework.beans.factory.InitializingBean;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationContextAware;
 
@@ -66,7 +65,7 @@ import com.vividsolutions.jts.geom.Envelope;
  * @author Gabriel Roldan
  */
 public class DefaultWebMapService implements WebMapService, ApplicationContextAware,
-        InitializingBean, DisposableBean {
+        DisposableBean {
     /**
      * default for 'format' parameter.
      */
@@ -137,6 +136,11 @@ public class DefaultWebMapService implements WebMapService, ApplicationContextAw
      * Enable continuous map wrapping
      */
     private static Boolean ENABLE_MAP_WRAPPING = null;
+    
+    /**
+     * Use a global rendering pool, or use a new pool each time
+     */
+    private static Boolean USE_GLOBAL_RENDERING_POOL = null;
 
     private GetCapabilities getCapabilities;
 
@@ -247,6 +251,16 @@ public class DefaultWebMapService implements WebMapService, ApplicationContextAw
             else
                 ENABLE_MAP_WRAPPING = Boolean.valueOf(wrapping);
         }
+        
+        // control usage of the global rendering thread pool
+        if (USE_GLOBAL_RENDERING_POOL == null) {
+            String usePool = GeoServerExtensions.getProperty("USE_GLOBAL_RENDERING_POOL", context);
+            // default to true, but allow switching off
+            if (usePool == null)
+                USE_GLOBAL_RENDERING_POOL = true;
+            else
+                USE_GLOBAL_RENDERING_POOL = Boolean.valueOf(usePool);
+        }
     }
 
     /**
@@ -678,6 +692,14 @@ public class DefaultWebMapService implements WebMapService, ApplicationContextAw
      * @return
      */
     public static ExecutorService getRenderingPool() {
+        if(USE_GLOBAL_RENDERING_POOL && RENDERING_POOL == null) {
+            synchronized (DefaultWebMapService.class) {
+                if(RENDERING_POOL == null) {
+                    RENDERING_POOL = Executors.newCachedThreadPool();
+                }
+            }
+        }
+        
         return RENDERING_POOL;
     }
 
@@ -688,7 +710,4 @@ public class DefaultWebMapService implements WebMapService, ApplicationContextAw
         }
     }
 
-    public void afterPropertiesSet() throws Exception {
-        RENDERING_POOL = Executors.newCachedThreadPool();
-    }
 }
------------------------------------------------------------------------------
The ultimate all-in-one performance toolkit: Intel(R) Parallel Studio XE:
Pinpoint memory and threading errors before they happen.
Find and fix more than 250 security defects in the development cycle.
Locate bottlenecks in serial and parallel code that limit performance.
http://p.sf.net/sfu/intel-dev2devfeb
_______________________________________________
Geoserver-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/geoserver-devel

Reply via email to