From a8e79366e342541406faa25d1d0d711cc09981f7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ra=C3=BAl=20Mar=C3=ADn=20Rodr=C3=ADguez?= Date: Wed, 19 Jun 2019 15:23:33 +0000 Subject: [PATCH] PROJ: Remove the extra MemoryContext for PG9.6+ 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 | 10 +-- libpgcommon/lwgeom_cache.h | 2 + libpgcommon/lwgeom_transform.c | 142 +++++++++++++++------------------ 3 files changed, 68 insertions(+), 86 deletions(-) diff --git a/libpgcommon/lwgeom_cache.c b/libpgcommon/lwgeom_cache.c index aebd2867d..ca82c82f3 100644 --- a/libpgcommon/lwgeom_cache.c +++ b/libpgcommon/lwgeom_cache.c @@ -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); diff --git a/libpgcommon/lwgeom_cache.h b/libpgcommon/lwgeom_cache.h index 4a5c88531..8863da50f 100644 --- a/libpgcommon/lwgeom_cache.h +++ b/libpgcommon/lwgeom_cache.h @@ -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; diff --git a/libpgcommon/lwgeom_transform.c b/libpgcommon/lwgeom_transform.c index 7fdc02763..238915457 100644 --- a/libpgcommon/lwgeom_transform.c +++ b/libpgcommon/lwgeom_transform.c @@ -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 -- 2.40.0