]> granicus.if.org Git - postgis/commitdiff
Have both RTREE and PREPARED_GEOM caches cohexist (#547)
authorSandro Santilli <strk@keybit.net>
Thu, 19 Jan 2012 17:15:45 +0000 (17:15 +0000)
committerSandro Santilli <strk@keybit.net>
Thu, 19 Jan 2012 17:15:45 +0000 (17:15 +0000)
Fixes a memory leak and improves performances when both p-i-p
and other kind of overlays are requested during the same statement.

git-svn-id: http://svn.osgeo.org/postgis/trunk@8877 b70326c6-7e19-0410-871a-916f4a2858ee

postgis/Makefile.in
postgis/lwgeom_cache.c [new file with mode: 0644]
postgis/lwgeom_cache.h [new file with mode: 0644]
postgis/lwgeom_geos.c
postgis/lwgeom_geos_prepared.c
postgis/lwgeom_rtree.c
postgis/lwgeom_rtree.h

index e359fb0492abe471cdcb5bf7c356fcc84bfda526..4e26abec842987050da06f038bd34bc97e1d8372 100644 (file)
@@ -33,6 +33,7 @@ PG_OBJS= \
        lwgeom_btree.o \
        lwgeom_box.o \
        lwgeom_box3d.o \
+       lwgeom_cache.o \
        lwgeom_geos.o \
        lwgeom_geos_prepared.o \
        lwgeom_geos_clean.o \
diff --git a/postgis/lwgeom_cache.c b/postgis/lwgeom_cache.c
new file mode 100644 (file)
index 0000000..9063036
--- /dev/null
@@ -0,0 +1,30 @@
+/**********************************************************************
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://postgis.refractions.net
+ *
+ * Copyright (C) 2012 Sandro Santilli <strk@keybit.net>
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
+ *
+ **********************************************************************/
+
+#include "postgres.h"
+#include "fmgr.h"
+
+#include "lwgeom_cache.h"
+
+GeomCache* GetGeomCache(FunctionCallInfoData *fcinfo)
+{
+       MemoryContext old_context;
+       GeomCache* cache = fcinfo->flinfo->fn_extra;
+       if ( ! cache ) {
+               old_context = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
+               cache = palloc(sizeof(GeomCache));
+               MemoryContextSwitchTo(old_context);
+               cache->prep = 0;
+               cache->rtree = 0;
+       }
+}
+
diff --git a/postgis/lwgeom_cache.h b/postgis/lwgeom_cache.h
new file mode 100644 (file)
index 0000000..e687398
--- /dev/null
@@ -0,0 +1,30 @@
+/**********************************************************************
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://postgis.refractions.net
+ *
+ * Copyright (C) 2012 Sandro Santilli <strk@keybit.net>
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
+ *
+ **********************************************************************/
+
+#ifndef LWGEOM_GEOS_CACHE_H_
+#define LWGEOM_GEOS_CACHE_H_ 1
+
+#include "postgres.h"
+#include "fmgr.h"
+
+#include "lwgeom_pg.h"
+#include "lwgeom_rtree.h"
+#include "lwgeom_geos_prepared.h"
+
+typedef struct {
+       PrepGeomCache* prep;
+       RTREE_POLY_CACHE* rtree;
+} GeomCache;
+
+GeomCache* GetGeomCache(FunctionCallInfoData *fcinfo);
+
+#endif /* LWGEOM_GEOS_CACHE_H_ 1 */
index f81e8edc324b3864e36375e5bfed5e960947af9e..ce214ca342eb4d4c1e3bf8160fa879627072d20d 100644 (file)
@@ -3,7 +3,7 @@
  * PostGIS - Spatial Types for PostgreSQL
  * http://postgis.refractions.net
  *
- * Copyright 2009-2011 Sandro Santilli <strk@keybit.net>
+ * Copyright 2009-2012 Sandro Santilli <strk@keybit.net>
  * Copyright 2008 Paul Ramsey <pramsey@cleverelephant.ca>
  * Copyright 2001-2003 Refractions Research Inc.
  *
@@ -17,6 +17,7 @@
 #include "lwgeom_rtree.h"
 #include "lwgeom_functions_analytic.h" /* for point_in_polygon */
 #include "funcapi.h"
+#include "lwgeom_cache.h"
 
 /*
 ** GEOS prepared geometry is only available from GEOS 3.1 onwards
@@ -80,11 +81,30 @@ Datum hausdorffdistancedensify(PG_FUNCTION_ARGS);
 Datum pgis_union_geometry_array_old(PG_FUNCTION_ARGS);
 Datum pgis_union_geometry_array(PG_FUNCTION_ARGS);
 
-
 /*
 ** Prototypes end
 */
 
+static RTREE_POLY_CACHE *
+GetRtreeCache(FunctionCallInfoData *fcinfo, LWGEOM *lwgeom, GSERIALIZED *poly)
+{
+       MemoryContext old_context;
+       GeomCache* supercache = GetGeomCache(fcinfo);
+       RTREE_POLY_CACHE *poly_cache = supercache->rtree;
+
+       /*
+        * Switch the context to the function-scope context,
+        * retrieve the appropriate cache object, cache it for
+        * future use, then switch back to the local context.
+        */
+       old_context = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
+       poly_cache = retrieveCache(lwgeom, poly, poly_cache);
+       supercache->rtree = poly_cache;
+       MemoryContextSwitchTo(old_context);
+
+       return poly_cache;
+}
+
 
 PG_FUNCTION_INFO_V1(postgis_geos_version);
 Datum postgis_geos_version(PG_FUNCTION_ARGS)
@@ -1794,7 +1814,6 @@ Datum contains(PG_FUNCTION_ARGS)
        LWGEOM *lwgeom;
        LWPOINT *point;
        RTREE_POLY_CACHE *poly_cache;
-       MemoryContext old_context;
        bool result;
 #ifdef PREPARED_GEOM
        PrepGeomCache *prep_cache;
@@ -1841,15 +1860,7 @@ Datum contains(PG_FUNCTION_ARGS)
 
                POSTGIS_DEBUGF(3, "Precall point_in_multipolygon_rtree %p, %p", lwgeom, point);
 
-               /*
-                * Switch the context to the function-scope context,
-                * retrieve the appropriate cache object, cache it for
-                * future use, then switch back to the local context.
-                */
-               old_context = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
-               poly_cache = retrieveCache(lwgeom, geom1, fcinfo->flinfo->fn_extra);
-               fcinfo->flinfo->fn_extra = poly_cache;
-               MemoryContextSwitchTo(old_context);
+               poly_cache = GetRtreeCache(fcinfo, lwgeom, geom1);
 
                if ( poly_cache->ringIndices )
                {
@@ -2040,7 +2051,6 @@ Datum covers(PG_FUNCTION_ARGS)
        LWGEOM *lwgeom;
        LWPOINT *point;
        RTREE_POLY_CACHE *poly_cache;
-       MemoryContext old_context;
 #ifdef PREPARED_GEOM
        PrepGeomCache *prep_cache;
 #endif
@@ -2084,15 +2094,7 @@ Datum covers(PG_FUNCTION_ARGS)
 
                POSTGIS_DEBUGF(3, "Precall point_in_multipolygon_rtree %p, %p", lwgeom, point);
 
-               /*
-                * Switch the context to the function-scope context,
-                * retrieve the appropriate cache object, cache it for
-                * future use, then switch back to the local context.
-                */
-               old_context = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
-               poly_cache = retrieveCache(lwgeom, geom1, fcinfo->flinfo->fn_extra);
-               fcinfo->flinfo->fn_extra = poly_cache;
-               MemoryContextSwitchTo(old_context);
+               poly_cache = GetRtreeCache(fcinfo, lwgeom, geom1);
 
                if ( poly_cache->ringIndices )
                {
@@ -2197,7 +2199,6 @@ Datum within(PG_FUNCTION_ARGS)
        LWGEOM *lwgeom;
        LWPOINT *point;
        int type1, type2;
-       MemoryContext old_context;
        RTREE_POLY_CACHE *poly_cache;
 
        geom1 = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
@@ -2237,15 +2238,7 @@ Datum within(PG_FUNCTION_ARGS)
                point = lwgeom_as_lwpoint(lwgeom_from_gserialized(geom1));
                lwgeom = lwgeom_from_gserialized(geom2);
 
-               /*
-                * Switch the context to the function-scope context,
-                * retrieve the appropriate cache object, cache it for
-                * future use, then switch back to the local context.
-                */
-               old_context = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
-               poly_cache = retrieveCache(lwgeom, geom2, fcinfo->flinfo->fn_extra);
-               fcinfo->flinfo->fn_extra = poly_cache;
-               MemoryContextSwitchTo(old_context);
+               poly_cache = GetRtreeCache(fcinfo, lwgeom, geom2);
 
                if ( poly_cache->ringIndices )
                {
@@ -2331,7 +2324,6 @@ Datum coveredby(PG_FUNCTION_ARGS)
        LWGEOM *lwgeom;
        LWPOINT *point;
        int type1, type2;
-       MemoryContext old_context;
        RTREE_POLY_CACHE *poly_cache;
        char *patt = "**F**F***";
 
@@ -2374,15 +2366,7 @@ Datum coveredby(PG_FUNCTION_ARGS)
                point = lwgeom_as_lwpoint(lwgeom_from_gserialized(geom1));
                lwgeom = lwgeom_from_gserialized(geom2);
 
-               /*
-                * Switch the context to the function-scope context,
-                * retrieve the appropriate cache object, cache it for
-                * future use, then switch back to the local context.
-                */
-               old_context = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
-               poly_cache = retrieveCache(lwgeom, geom2, fcinfo->flinfo->fn_extra);
-               fcinfo->flinfo->fn_extra = poly_cache;
-               MemoryContextSwitchTo(old_context);
+               poly_cache = GetRtreeCache(fcinfo, lwgeom, geom2);
 
                if ( poly_cache->ringIndices )
                {
@@ -2534,7 +2518,6 @@ Datum intersects(PG_FUNCTION_ARGS)
        int type1, type2, polytype;
        LWPOINT *point;
        LWGEOM *lwgeom;
-       MemoryContext old_context;
        RTREE_POLY_CACHE *poly_cache;
 #ifdef PREPARED_GEOM
        PrepGeomCache *prep_cache;
@@ -2589,15 +2572,8 @@ Datum intersects(PG_FUNCTION_ARGS)
                        serialized_poly = geom1;
                        polytype = type1;
                }
-               /*
-                * Switch the context to the function-scope context,
-                * retrieve the appropriate cache object, cache it for
-                * future use, then switch back to the local context.
-                */
-               old_context = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
-               poly_cache = retrieveCache(lwgeom, serialized_poly, fcinfo->flinfo->fn_extra);
-               fcinfo->flinfo->fn_extra = poly_cache;
-               MemoryContextSwitchTo(old_context);
+
+               poly_cache = GetRtreeCache(fcinfo, lwgeom, serialized_poly);
 
                if ( poly_cache->ringIndices )
                {
index 0e482b383945ab43cd93ed9a8f7815ecf29da8f7..8b76b9089e72c285b2b4806fa2a103e494de5d90 100644 (file)
@@ -3,6 +3,7 @@
  * PostGIS - Spatial Types for PostgreSQL
  * http://postgis.refractions.net
  *
+ * Copyright (C) 2012 Sandro Santilli <strk@keybit.net>
  * Copyright (C) 2008 Paul Ramsey <pramsey@cleverelephant.ca>
  * Copyright (C) 2007 Refractions Research Inc.
  *
  *
  **********************************************************************/
 
+#include <assert.h>
+
 #include "lwgeom_geos_prepared.h"
+#include "lwgeom_cache.h"
 
 /***********************************************************************
 **
@@ -273,13 +277,13 @@ PrepGeomCache*
 GetPrepGeomCache(FunctionCallInfoData *fcinfo, GSERIALIZED *pg_geom1, GSERIALIZED *pg_geom2)
 {
        MemoryContext old_context;
-       PrepGeomCache* cache = fcinfo->flinfo->fn_extra;
+       GeomCache* supercache = GetGeomCache(fcinfo);
+       PrepGeomCache* cache = supercache->prep;
        int copy_keys = 1;
        size_t pg_geom1_size = 0;
        size_t pg_geom2_size = 0;
 
-       /* Make sure this isn't someone else's cache object. */
-       if ( cache && cache->type != 2 ) cache = NULL;
+       assert ( ! cache || cache->type == 2 );
 
        if (!PrepGeomHash)
                CreatePrepGeomHash();
@@ -324,7 +328,7 @@ GetPrepGeomCache(FunctionCallInfoData *fcinfo, GSERIALIZED *pg_geom1, GSERIALIZE
                pghe.prepared_geom = 0;
                AddPrepGeomHashEntry( pghe );
 
-               fcinfo->flinfo->fn_extra = cache;
+               supercache->prep = cache;
 
                POSTGIS_DEBUGF(3, "GetPrepGeomCache: adding context to hash: %p", cache);
        }
index a0f43f9a39d6fd6cd0b16a9391ae61c491effead..bb9942f5adde2ed0994130a2a680c15a86a2c859 100644 (file)
@@ -9,6 +9,8 @@
  *
  **********************************************************************/
 
+#include <assert.h>
+
 #include "lwgeom_pg.h"
 #include "liblwgeom.h"
 #include "liblwgeom_internal.h"         /* For FP comparators. */
@@ -488,8 +490,7 @@ RTREE_POLY_CACHE *retrieveCache(LWGEOM *lwgeom, GSERIALIZED *serializedPoly, RTR
 
        POSTGIS_DEBUGF(2, "retrieveCache called with %p %p %p", lwgeom, serializedPoly, currentCache);
 
-       /* Make sure this isn't someone else's cache object. */
-       if ( currentCache && currentCache->type != 1 ) currentCache = NULL;
+       assert ( ! currentCache || currentCache->type == 1 );
 
        if (!currentCache)
        {
index be7835de3006e13963cbce30da1f0477160d85f5..d2e33da905a8962a38d69d6228bf5321f75195f1 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _LWGEOM_RTREE_H\r
 #define _LWGEOM_RTREE_H\r
 \r
+#include "liblwgeom.h"\r
+\r
 typedef struct\r
 {\r
        double min;\r