Skip to content
Permalink
Browse files
PROJ6: make sure that the projection context is reused by all FastCGI…
…/MapScript requests of the same thread
  • Loading branch information
rouault committed Oct 1, 2019
1 parent aed7223 commit f595e91
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 17 deletions.
@@ -5848,6 +5848,7 @@ int msUpdateWebFromString(webObj *web, char *string, int url_string)
** This really belongs in mapobject.c, but currently it also depends on
** lots of other init methods in this file.
*/

int initMap(mapObj *map)
{
int i=0;
@@ -5925,18 +5926,21 @@ int initMap(mapObj *map)
initQueryMap(&map->querymap);

#ifdef USE_PROJ
map->projContext = msProjectionContextGetFromPool();

if(msInitProjection(&(map->projection)) == -1)
return(-1);
if(msInitProjection(&(map->latlon)) == -1)
return(-1);

msProjectionSetContext(&(map->projection), map->projContext);
msProjectionSetContext(&(map->latlon), map->projContext);

/* initialize a default "geographic" projection */
map->latlon.numargs = 2;
map->latlon.args[0] = msStrdup("proj=latlong");
map->latlon.args[1] = msStrdup("ellps=WGS84"); /* probably want a different ellipsoid */
if(msProcessProjection(&(map->latlon)) == -1) return(-1);

msProjectionInheritContextFrom(&(map->projection), &(map->latlon));
#endif

map->templatepattern = map->datapattern = NULL;
@@ -6314,7 +6318,7 @@ static int loadMapInternal(mapObj *map)
if((map->interlace = getSymbol(2, MS_ON,MS_OFF)) == -1) return MS_FAILURE;
break;
case(LATLON):
msFreeProjection(&map->latlon);
msFreeProjectionExceptContext(&map->latlon);
if(loadProjection(&map->latlon) == -1) return MS_FAILURE;
break;
case(LAYER):
@@ -6486,7 +6490,7 @@ mapObj *msLoadMapFromString(char *buffer, char *new_mappath)
/*
** Sets up file-based mapfile loading and calls loadMapInternal to do the work.
*/
mapObj *msLoadMap(char *filename, char *new_mappath)
mapObj *msLoadMap(const char *filename, const char *new_mappath)
{
mapObj *map;
struct mstimeval starttime, endtime;
@@ -93,8 +93,11 @@ void msFreeMap(mapObj *map)
msFree(map->shapepath);
msFree(map->mappath);

#ifdef USE_PROJ
msFreeProjection(&(map->projection));
msFreeProjection(&(map->latlon));
msProjectionContextReleaseToPool(map->projContext);
#endif

msFreeLabelCache(&(map->labelcache));

@@ -38,10 +38,26 @@

#ifdef USE_PROJ
static char *ms_proj_lib = NULL;
#if PROJ_VERSION_MAJOR >= 6
static unsigned ms_proj_lib_change_counter = 0;
#endif

typedef struct LinkedListOfProjContext LinkedListOfProjContext;
struct LinkedListOfProjContext
{
LinkedListOfProjContext* next;
projectionContext* context;
};

static LinkedListOfProjContext* headOfLinkedListOfProjContext = NULL;

static int msTestNeedWrap( pointObj pt1, pointObj pt2, pointObj pt2_geo,
reprojectionObj* reprojector );


static projectionContext* msProjectionContextCreate(void);
static void msProjectionContextUnref(projectionContext* ctx);

#if defined(USE_PROJ) && PROJ_VERSION_MAJOR >= 6

#include "proj_experimental.h"
@@ -69,6 +85,7 @@ typedef struct
struct projectionContext
{
PJ_CONTEXT* proj_ctx;
unsigned ms_proj_lib_change_counter;
int ref_count;
pjCacheEntry pj_cache[PJ_CACHE_ENTRY_SIZE];
int pj_cache_size;
@@ -253,7 +270,6 @@ static void msProjErrorLogger(void * user_data,
/* msProjectionContextCreate() */
/************************************************************************/

static
projectionContext* msProjectionContextCreate(void)
{
projectionContext* ctx = (projectionContext*)msSmallCalloc(1, sizeof(projectionContext));
@@ -265,11 +281,6 @@ projectionContext* msProjectionContextCreate(void)
}
ctx->ref_count = 1;
proj_context_use_proj4_init_rules(ctx->proj_ctx, TRUE);
if( ms_proj_lib )
{
const char* const paths[1] = { ms_proj_lib };
proj_context_set_search_paths(ctx->proj_ctx, 1, paths);
}
proj_log_func (ctx->proj_ctx, NULL, msProjErrorLogger);
return ctx;
}
@@ -278,7 +289,6 @@ projectionContext* msProjectionContextCreate(void)
/* msProjectionContextUnref() */
/************************************************************************/

static
void msProjectionContextUnref(projectionContext* ctx)
{
if( !ctx )
@@ -409,6 +419,24 @@ int msProjectTransformPoints( reprojectionObj* reprojector,

#else

/************************************************************************/
/* msProjectionContextCreate() */
/************************************************************************/

projectionContext* msProjectionContextCreate(void)
{
return NULL;
}

/************************************************************************/
/* msProjectionContextUnref() */
/************************************************************************/

void msProjectionContextUnref(projectionContext* ctx)
{
(void)ctx;
}

struct reprojectionObj
{
projectionObj* in;
@@ -564,6 +592,25 @@ void msProjectionInheritContextFrom(projectionObj *pDst, projectionObj* pSrc)
#endif
}

/************************************************************************/
/* msProjectionSetContext() */
/************************************************************************/

void msProjectionSetContext(projectionObj *p, projectionContext* ctx)
{
#if !defined(USE_PROJ)
/* do nothing */
#elif PROJ_VERSION_MAJOR >= 6
if( p->proj_ctx == NULL && ctx != NULL)
{
p->proj_ctx = ctx;
p->proj_ctx->ref_count ++;
}
#else
/* do nothing */
#endif
}

/*
** Handle OGC WMS/WFS AUTO projection in the format:
** "AUTO:proj_id,units_id,lon0,lat0"
@@ -728,6 +775,16 @@ int msProcessProjection(projectionObj *p)
return -1;
}
}
if( p->proj_ctx->ms_proj_lib_change_counter != ms_proj_lib_change_counter )
{
msAcquireLock( TLOCK_PROJ );
p->proj_ctx->ms_proj_lib_change_counter = ms_proj_lib_change_counter;
{
const char* const paths[1] = { ms_proj_lib };
proj_context_set_search_paths(p->proj_ctx->proj_ctx, 1, ms_proj_lib ? paths : NULL);
}
msReleaseLock( TLOCK_PROJ );
}
#endif

if (strncasecmp(p->args[0], "AUTO:", 5) == 0 ||
@@ -2259,8 +2316,21 @@ void msSetPROJ_LIB( const char *proj_lib, const char *pszRelToPath )

msAcquireLock( TLOCK_PROJ );
#if PROJ_VERSION_MAJOR >= 6
free( ms_proj_lib );
ms_proj_lib = proj_lib ? msStrdup(proj_lib) : NULL;
if( proj_lib == NULL && ms_proj_lib == NULL )
{
/* do nothing */
}
else if( proj_lib != NULL && ms_proj_lib != NULL &&
strcmp(proj_lib, ms_proj_lib) == 0 )
{
/* do nothing */
}
else
{
ms_proj_lib_change_counter++;
free( ms_proj_lib );
ms_proj_lib = proj_lib ? msStrdup(proj_lib) : NULL;
}
#else
{
static int finder_installed = 0;
@@ -2589,3 +2659,75 @@ int GetMapserverUnitUsingProj(projectionObj *psProj)
return -1;
}

/************************************************************************/
/* msProjectionContextGetFromPool() */
/* */
/* Returns a projection context from the pool, or create a new */
/* one if the pool is empty. */
/* After use, it should normally be returned with */
/* msProjectionContextReleaseToPool() */
/************************************************************************/

projectionContext* msProjectionContextGetFromPool()
{
#ifdef USE_PROJ
projectionContext* context;
msAcquireLock( TLOCK_PROJ );

if( headOfLinkedListOfProjContext )
{
LinkedListOfProjContext* next = headOfLinkedListOfProjContext->next;
context = headOfLinkedListOfProjContext->context;
msFree(headOfLinkedListOfProjContext);
headOfLinkedListOfProjContext = next;
}
else
{
context = msProjectionContextCreate();
}

msReleaseLock( TLOCK_PROJ );
return context;
#else
return NULL;
#endif
}

/************************************************************************/
/* msProjectionContextReleaseToPool() */
/************************************************************************/

void msProjectionContextReleaseToPool(projectionContext* ctx)
{
#ifdef USE_PROJ
LinkedListOfProjContext* link =
(LinkedListOfProjContext*)msSmallMalloc(sizeof(LinkedListOfProjContext));
link->context = ctx;
msAcquireLock( TLOCK_PROJ );
link->next = headOfLinkedListOfProjContext;
headOfLinkedListOfProjContext = link;
msReleaseLock( TLOCK_PROJ );
#endif
}

/************************************************************************/
/* msProjectionContextPoolCleanup() */
/************************************************************************/

void msProjectionContextPoolCleanup()
{
#ifdef USE_PROJ
LinkedListOfProjContext* link;
msAcquireLock( TLOCK_PROJ );
link = headOfLinkedListOfProjContext;
while( link )
{
LinkedListOfProjContext* next = link->next;
msProjectionContextUnref(link->context);
msFree(link);
link = next;
}
headOfLinkedListOfProjContext = NULL;
msReleaseLock( TLOCK_PROJ );
#endif
}
@@ -55,9 +55,7 @@ extern "C" {
#define wkp_lonlat 1
#define wkp_gmerc 2

#ifndef SWIG
typedef struct projectionContext projectionContext;
#endif
typedef struct projectionContext projectionContext;

typedef struct {
#ifdef SWIG
@@ -94,6 +92,10 @@ extern "C" {
MS_DLL_EXPORT reprojectionObj* msProjectCreateReprojector(projectionObj* in, projectionObj* out);
MS_DLL_EXPORT void msProjectDestroyReprojector(reprojectionObj* reprojector);

MS_DLL_EXPORT projectionContext* msProjectionContextGetFromPool(void);
MS_DLL_EXPORT void msProjectionContextReleaseToPool(projectionContext* ctx);
MS_DLL_EXPORT void msProjectionContextPoolCleanup(void);

MS_DLL_EXPORT int msIsAxisInverted(int epsg_code);
MS_DLL_EXPORT int msProjectPoint(projectionObj *in, projectionObj *out, pointObj *point); /* legacy interface */
MS_DLL_EXPORT int msProjectPointEx(reprojectionObj* reprojector, pointObj *point);
@@ -111,6 +113,7 @@ extern "C" {
MS_DLL_EXPORT void msFreeProjectionExceptContext(projectionObj *p);
MS_DLL_EXPORT int msInitProjection(projectionObj *p);
MS_DLL_EXPORT void msProjectionInheritContextFrom(projectionObj *pDst, projectionObj* pSrc);
MS_DLL_EXPORT void msProjectionSetContext(projectionObj *p, projectionContext* ctx);
MS_DLL_EXPORT int msProcessProjection(projectionObj *p);
MS_DLL_EXPORT int msLoadProjectionString(projectionObj *p, const char *value);
MS_DLL_EXPORT int msLoadProjectionStringEPSG(projectionObj *p, const char *value);
@@ -1962,6 +1962,10 @@ void msPopulateTextSymbolForLabelAndString(textSymbolObj *ts, labelObj *l, char
#ifdef USE_V8_MAPSCRIPT
void *v8context;
#endif

#ifndef SWIG
projectionContext* projContext;
#endif
};

/************************************************************************/
@@ -2120,7 +2124,7 @@ void msPopulateTextSymbolForLabelAndString(textSymbolObj *ts, labelObj *l, char
MS_DLL_EXPORT int msValidateParameter(const char *value, const char *pattern1, const char *pattern2, const char *pattern3, const char *pattern4);
MS_DLL_EXPORT int msGetLayerIndex(mapObj *map, const char *name);
MS_DLL_EXPORT int msGetSymbolIndex(symbolSetObj *set, char *name, int try_addimage_if_notfound);
MS_DLL_EXPORT mapObj *msLoadMap(char *filename, char *new_mappath);
MS_DLL_EXPORT mapObj *msLoadMap(const char *filename, const char *new_mappath);
MS_DLL_EXPORT int msTransformXmlMapfile(const char *stylesheet, const char *xmlMapfile, FILE *tmpfile);
MS_DLL_EXPORT int msSaveMap(mapObj *map, char *filename);
MS_DLL_EXPORT void msFreeCharArray(char **array, int num_items);
@@ -2080,6 +2080,7 @@ void msCleanup()
pj_deallocate_grids();
#endif
msSetPROJ_LIB( NULL, NULL );
msProjectionContextPoolCleanup();
#endif
#if defined(USE_CURL)
msHTTPCleanup();

0 comments on commit f595e91

Please sign in to comment.