]> granicus.if.org Git - postgis/commitdiff
PROJ: Remove the extra MemoryContext for PG9.6+
authorRaúl Marín Rodríguez <rmrodriguez@carto.com>
Wed, 19 Jun 2019 15:23:33 +0000 (15:23 +0000)
committerRaúl Marín Rodríguez <rmrodriguez@carto.com>
Wed, 19 Jun 2019 15:23:33 +0000 (15:23 +0000)
In PG9.6+ we can allocate callbacks in the parent node
and associate them directly without creating new contextes

References #4372

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

libpgcommon/lwgeom_cache.c
libpgcommon/lwgeom_cache.h
libpgcommon/lwgeom_transform.c

index aebd2867d911ad63acf0840448c253a8a4996b7f..ca82c82f300176fdb00b41a1d726d7b02569f883 100644 (file)
@@ -93,19 +93,11 @@ GetPROJSRSCache(FunctionCallInfo fcinfo)
 
                if (cache)
                {
-                       int i;
-
                        POSTGIS_DEBUGF(3,
                                       "Allocating PROJCache for portal with transform() MemoryContext %p",
                                       FIContext(fcinfo));
                        /* Put in any required defaults */
-                       for (i = 0; i < PROJ_CACHE_ITEMS; i++)
-                       {
-                               cache->PROJSRSCache[i].srid_from = SRID_UNKNOWN;
-                               cache->PROJSRSCache[i].srid_to = SRID_UNKNOWN;
-                               cache->PROJSRSCache[i].projection = NULL;
-                               cache->PROJSRSCache[i].projection_mcxt = NULL;
-                       }
+                       memset(cache->PROJSRSCache, 0, sizeof(PROJSRSCacheItem) * PROJ_CACHE_ITEMS);
                        cache->type = PROJ_CACHE_ENTRY;
                        cache->PROJSRSCacheCount = 0;
                        cache->PROJSRSCacheContext = FIContext(fcinfo);
index 4a5c88531aca28c4ae51b26f97d8133ee66c6e49..8863da50fcb24d8b027904ebe99b1ebbafbb5a7d 100644 (file)
@@ -68,7 +68,9 @@ typedef struct struct_PROJSRSCacheItem
        int32_t srid_from;
        int32_t srid_to;
        LWPROJ *projection;
+#if POSTGIS_PGSQL_VERSION < 96
        MemoryContext projection_mcxt;
+#endif
 }
 PROJSRSCacheItem;
 
index 7fdc02763c479f4f66acd18cc6cbc822b1e8a2e8..2389154578d4af5121c8959fa2ff5ec42236fd40 100644 (file)
@@ -48,18 +48,6 @@ static char *spatialRefSysSchema = NULL;
  */
 #define PROJ_BACKEND_HASH_SIZE 256
 
-/**
- * Backend PROJ hash table
- *
- * This hash table stores a key/value pair of MemoryContext/PJ objects.
- * Whenever we create a PJ object using pj_init(), we create a separate
- * MemoryContext as a child context of the current executor context.
- * The MemoryContext/PJ object is stored in this hash table so
- * that when PROJSRSCacheDelete() is called during query cleanup, we can
- * lookup the PJ object based upon the MemoryContext parameter and hence
- * pj_free() it.
- */
-static HTAB *PJHash = NULL;
 
 /**
  * Utility structure to get many potential string representations
@@ -71,23 +59,6 @@ typedef struct {
        char* proj4text;
 } PjStrs;
 
-
-typedef struct struct_PJHashEntry
-{
-       MemoryContext ProjectionContext;
-       LWPROJ *projection;
-}
-PJHashEntry;
-
-
-/* PJ Hash API */
-uint32 mcxt_ptr_hash(const void *key, Size keysize);
-
-static HTAB *CreatePJHash(void);
-static void DeletePJHashEntry(MemoryContext mcxt);
-static LWPROJ *GetPJHashEntry(MemoryContext mcxt);
-static void AddPJHashEntry(MemoryContext mcxt, LWPROJ *projection);
-
 /* Internal Cache API */
 static LWPROJ *AddToPROJSRSCache(PROJPortalCache *PROJCache, int32_t srid_from, int32_t srid_to);
 static void DeleteFromPROJSRSCache(PROJPortalCache *PROJCache, int32_t srid_from, int32_t srid_to);
@@ -118,42 +89,61 @@ SetSpatialRefSysSchema(FunctionCallInfo fcinfo)
 }
 
 static void
-PROJSRSDestroyPJ(LWPROJ *pj)
+PROJSRSDestroyPJ(void *projection)
 {
+       LWPROJ *pj = (LWPROJ *)projection;
 #if POSTGIS_PROJ_VERSION < 60
 /* Ape the Proj 6+ API for versions < 6 */
        if (pj->pj_from)
+       {
                pj_free(pj->pj_from);
+               pj->pj_from = NULL;
+       }
        if (pj->pj_to)
+       {
                pj_free(pj->pj_to);
-       pfree(pj);
+               pj->pj_to = NULL;
+       }
 #else
-       proj_destroy(pj->pj);
-       pfree(pj);
+       if (pj->pj)
+       {
+               proj_destroy(pj->pj);
+               pj->pj = NULL;
+       }
 #endif
 }
 
-#if 0
-static const char *
-PJErrStr()
+#if POSTGIS_PGSQL_VERSION < 96
+/**
+ * Backend PROJ hash table
+ *
+ * This hash table stores a key/value pair of MemoryContext/PJ objects.
+ * Whenever we create a PJ object using pj_init(), we create a separate
+ * MemoryContext as a child context of the current executor context.
+ * The MemoryContext/PJ object is stored in this hash table so
+ * that when PROJSRSCacheDelete() is called during query cleanup, we can
+ * lookup the PJ object based upon the MemoryContext parameter and hence
+ * pj_free() it.
+ */
+static HTAB *PJHash = NULL;
+
+typedef struct struct_PJHashEntry
 {
-       const char *pj_errstr = pj_strerrno(*pj_get_errno_ref());
-       if (!pj_errstr)
-               return "";
-       return pj_errstr;
-}
-#endif
+       MemoryContext ProjectionContext;
+       LWPROJ *projection;
+} PJHashEntry;
+
+/* PJ Hash API */
+uint32 mcxt_ptr_hash(const void *key, Size keysize);
+
+static HTAB *CreatePJHash(void);
+static void DeletePJHashEntry(MemoryContext mcxt);
+static LWPROJ *GetPJHashEntry(MemoryContext mcxt);
+static void AddPJHashEntry(MemoryContext mcxt, LWPROJ *projection);
 
 static void
-#if POSTGIS_PGSQL_VERSION < 96
 PROJSRSCacheDelete(MemoryContext context)
 {
-#else
-PROJSRSCacheDelete(void *ptr)
-{
-       MemoryContext context = (MemoryContext)ptr;
-#endif
-
        /* Lookup the PJ pointer in the global hash table so we can free it */
        LWPROJ *projection = GetPJHashEntry(context);
 
@@ -168,8 +158,6 @@ PROJSRSCacheDelete(void *ptr)
        DeletePJHashEntry(context);
 }
 
-#if POSTGIS_PGSQL_VERSION < 96
-
 static void
 PROJSRSCacheInit(MemoryContext context)
 {
@@ -237,7 +225,6 @@ static MemoryContextMethods PROJSRSCacheContextMethods =
 #endif
 };
 
-#endif /* POSTGIS_PGSQL_VERSION < 96 */
 
 /*
  * PROJ PJ Hash Table functions
@@ -327,6 +314,7 @@ static void DeletePJHashEntry(MemoryContext mcxt)
                he->projection = NULL;
 }
 
+#endif /* POSTGIS_PGSQL_VERSION < 96 */
 
 /*****************************************************************************
  * Per-cache management functions
@@ -600,7 +588,10 @@ GetProj4String(int32_t srid)
 static LWPROJ *
 AddToPROJSRSCache(PROJPortalCache *PROJCache, int32_t srid_from, int32_t srid_to)
 {
-       MemoryContext PJMemoryContext, oldContext;
+#if POSTGIS_PGSQL_VERSION < 96
+       MemoryContext PJMemoryContext;
+#endif
+       MemoryContext oldContext;
 
        PjStrs from_strs, to_strs;
        char *pj_from_str, *pj_to_str;
@@ -710,38 +701,28 @@ AddToPROJSRSCache(PROJPortalCache *PROJCache, int32_t srid_from, int32_t srid_to
                                              &PROJSRSCacheContextMethods,
                                              PROJCache->PROJSRSCacheContext,
                                              "PostGIS PROJ PJ Memory Context");
-#else
-       PJMemoryContext = AllocSetContextCreate(PROJCache->PROJSRSCacheContext,
-                                               "PostGIS PROJ PJ Memory Context",
-                                               ALLOCSET_SMALL_SIZES);
 
-       /* PgSQL comments suggest allocating callback in the context */
-       /* being managed, so that the callback object gets cleaned along with */
-       /* the context */
-       {
-               MemoryContextCallback *callback = MemoryContextAlloc(PJMemoryContext, sizeof(MemoryContextCallback));
-               callback->arg = (void*)PJMemoryContext;
-               callback->func = PROJSRSCacheDelete;
-               MemoryContextRegisterResetCallback(PJMemoryContext, callback);
-       }
-#endif
-
-       /* Create the backend hash if it doesn't already exist */
+       /* We register a new memory context to use it to delete the projection on exit */
        if (!PJHash)
                PJHash = CreatePJHash();
 
-       /*
-        * Add the MemoryContext to the backend hash so we can
-        * clean up upon portal shutdown
-        */
-       POSTGIS_DEBUGF(3, "adding projection object (%p) to hash table with MemoryContext key (%p)", projection, PJMemoryContext);
-
        AddPJHashEntry(PJMemoryContext, projection);
 
+#else
+       /* We register a new callback to delete the projection on exit */
+       MemoryContextCallback *callback =
+           MemoryContextAlloc(PROJCache->PROJSRSCacheContext, sizeof(MemoryContextCallback));
+       callback->func = PROJSRSDestroyPJ;
+       callback->arg = (void *)projection;
+       MemoryContextRegisterResetCallback(PROJCache->PROJSRSCacheContext, callback);
+#endif
+
        PROJCache->PROJSRSCache[PROJCache->PROJSRSCacheCount].srid_from = srid_from;
        PROJCache->PROJSRSCache[PROJCache->PROJSRSCacheCount].srid_to = srid_to;
        PROJCache->PROJSRSCache[PROJCache->PROJSRSCacheCount].projection = projection;
+#if POSTGIS_PGSQL_VERSION < 96
        PROJCache->PROJSRSCache[PROJCache->PROJSRSCacheCount].projection_mcxt = PJMemoryContext;
+#endif
        PROJCache->PROJSRSCacheCount++;
 
        MemoryContextSwitchTo(oldContext);
@@ -766,9 +747,16 @@ DeleteFromPROJSRSCache(PROJPortalCache *PROJCache, int32_t srid_from, int32_t sr
                         * Zero out the entries and free the PROJ handle
                         * by deleting the memory context
                         */
+#if POSTGIS_PGSQL_VERSION < 96
+                       /* Deleting the memory context will free the PROJ objects */
                        MemoryContextDelete(PROJCache->PROJSRSCache[i].projection_mcxt);
-                       PROJCache->PROJSRSCache[i].projection = NULL;
                        PROJCache->PROJSRSCache[i].projection_mcxt = NULL;
+#else
+                       /* Call PROJSRSDestroyPJ to free the PROJ objects memory now instead of
+                        * waiting for the parent memory context to exit */
+                       PROJSRSDestroyPJ(PROJCache->PROJSRSCache[i].projection);
+#endif
+                       PROJCache->PROJSRSCache[i].projection = NULL;
                        PROJCache->PROJSRSCache[i].srid_from = SRID_UNKNOWN;
                        PROJCache->PROJSRSCache[i].srid_to = SRID_UNKNOWN;
                }
@@ -796,7 +784,7 @@ GetPJUsingFCInfo(FunctionCallInfo fcinfo, int32_t srid_from, int32_t srid_to, LW
                *pj = AddToPROJSRSCache(proj_cache, srid_from, srid_to);
        }
 
-       return LW_SUCCESS;
+       return pj != NULL;
 }
 
 static int