* GeomCache entry from the generic cache if one exists.
* If it doesn't exist, make a new empty one and return it.
*/
-#if 0
GeomCache*
-GetGeomCache(FunctionCallInfoData* fcinfo, int cache_entry)
-{
- GeomCache* cache;
- GenericCacheCollection* generic_cache = GetGenericCacheCollection(fcinfo);
-
- if ( (cache_entry) < 0 || (cache_entry >= NUM_CACHE_ENTRIES) )
- return NULL;
-
- cache = (GeomCache*)(generic_cache->entry[cache_entry]);
-
- if ( ! cache )
- {
- /* Allocate in the upper context */
- cache = MemoryContextAlloc(FIContext(fcinfo), sizeof(GeomCache));
- /* Zero everything out */
- memset(cache, 0, sizeof(GeomCache));
- /* Set the cache type */
- cache->type = cache_entry;
- cache->context_statement = FIContext(fcinfo);
-
- /* Store the pointer in GenericCache */
- generic_cache->entry[cache_entry] = (GenericCache*)cache;
-
- }
-
- /* The cache object type should always equal the entry type */
- if ( cache->type != cache_entry )
- {
- lwerror("cache type does not equal expected entry type");
- return NULL;
- }
-
- return cache;
-}
-#endif
-
-
-GeomCache*
-GetGeomCache2(FunctionCallInfoData* fcinfo, const GeomCacheMethods* cache_methods, const GSERIALIZED* g1, const GSERIALIZED* g2)
+GetGeomCache(FunctionCallInfoData* fcinfo, const GeomCacheMethods* cache_methods, const GSERIALIZED* g1, const GSERIALIZED* g2)
{
GeomCache* cache;
int cache_hit = 0;
}
-
-/**
-* Get an appropriate tree from the cache, based on the entry number
-* and the geometry values. Checks for a cache, checks for cache hits,
-* returns a built tree if one exists.
-*/
-#if 0
-void*
-GetGeomIndex(FunctionCallInfoData* fcinfo, int cache_entry, GeomIndexBuilder index_build, GeomIndexFreer index_free, const GSERIALIZED* geom1, const GSERIALIZED* geom2, int* argnum)
-{
- int cache_hit = 0;
- MemoryContext old_context;
- GeomCache* cache = GetGeomCache(fcinfo, cache_entry);
- const GSERIALIZED *geom;
-
- /* Initialize output of argnum */
- if ( argnum )
- *argnum = cache_hit;
-
- /* Cache hit on the first argument */
- if ( geom1 &&
- cache->argnum != 2 &&
- cache->geom1_size == VARSIZE(geom1) &&
- memcmp(cache->geom1, geom1, cache->geom1_size) == 0 )
- {
- cache_hit = 1;
- geom = geom1;
-
- }
- /* Cache hit on second argument */
- else if ( geom2 &&
- cache->argnum != 1 &&
- cache->geom2_size == VARSIZE(geom2) &&
- memcmp(cache->geom2, geom2, cache->geom2_size) == 0 )
- {
- cache_hit = 2;
- geom = geom2;
- }
- /* No cache hit. If we have a tree, free it. */
- else
- {
- cache_hit = 0;
- if ( cache->index )
- {
- index_free(cache);
- cache->index = NULL;
- }
- }
-
- /* Cache hit, but no tree built yet, build it! */
- if ( cache_hit && ! cache->index )
- {
- LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
- int rv;
-
- /* Can't build a tree on a NULL or empty */
- if ( (!lwgeom) || lwgeom_is_empty(lwgeom) )
- return NULL;
-
- cache->argnum = cache_hit;
- old_context = MemoryContextSwitchTo(FIContext(fcinfo));
- rv = index_build(lwgeom, cache);
- MemoryContextSwitchTo(old_context);
-
- /* Something went awry in the tree build phase */
- if ( ! rv )
- {
- cache->argnum = 0;
- return NULL;
- }
-
- }
-
- /* We have a hit and a calculated tree, we're done */
- if ( cache_hit && (cache_hit == cache->argnum) && cache->index )
- {
- if ( argnum )
- *argnum = cache_hit;
- return cache->index;
- }
-
- /* Argument one didn't match, so copy the new value in. */
- if ( geom1 && cache_hit != 1 )
- {
- if ( cache->geom1 ) pfree(cache->geom1);
- cache->geom1_size = VARSIZE(geom1);
- cache->geom1 = MemoryContextAlloc(FIContext(fcinfo), cache->geom1_size);
- memcpy(cache->geom1, geom1, cache->geom1_size);
- }
- /* Argument two didn't match, so copy the new value in. */
- if ( geom2 && cache_hit != 2 )
- {
- if ( cache->geom2 ) pfree(cache->geom2);
- cache->geom2_size = VARSIZE(geom2);
- cache->geom2 = MemoryContextAlloc(FIContext(fcinfo), cache->geom2_size);
- memcpy(cache->geom2, geom2, cache->geom2_size);
- }
-
- return NULL;
-}
-
-#endif
-
/**
* Builder, freeer and public accessor for cached CIRC_NODE trees
*/
CIRC_NODE*
GetCircTree(FunctionCallInfoData* fcinfo, const GSERIALIZED* g1, const GSERIALIZED* g2, int* argnum_of_cache)
{
- CircTreeGeomCache* cache = (CircTreeGeomCache*)GetGeomCache2(fcinfo, &CircTreeCacheMethods, g1, g2);
+ CircTreeGeomCache* cache = (CircTreeGeomCache*)GetGeomCache(fcinfo, &CircTreeCacheMethods, g1, g2);
if ( ! cache )
return NULL;
CircTreeGeomCache*
GetCircTreeGeomCache(FunctionCallInfoData* fcinfo, const GSERIALIZED* g1, const GSERIALIZED* g2)
{
- return (CircTreeGeomCache*)GetGeomCache2(fcinfo, &CircTreeCacheMethods, g1, g2);
+ return (CircTreeGeomCache*)GetGeomCache(fcinfo, &CircTreeCacheMethods, g1, g2);
}
#include "fmgr.h"
#include "liblwgeom_internal.h"
-#include "lwgeodetic.h";
+#include "lwgeodetic.h"
#include "lwgeodetic_tree.h"
#include "lwgeom_pg.h"
/*
-* For the geometry-with-tree case, we need space for
-* the serialized geometries and their sizes, so we can
-* test for cache hits/misses. The argnum tells us which
-* argument the tree is built for.
+* A generic GeomCache just needs space for the cache type,
+* the cache keys (GSERIALIZED geometries), the key sizes,
+* and the argument number the cached index/tree is going
+* to refer to.
*/
typedef struct {
int type;
int32 argnum;
} GeomCache;
+/*
+* Specific tree types include all the generic slots and
+* their own slots for their trees. We put the implementation
+* for the CircTreeGeomCache here because we can't shove
+* the PgSQL specific bits of the code (fcinfo) back into
+* liblwgeom, where most of the circtree logic lives.
+*/
typedef struct {
int type; // <GeomCache>
GSERIALIZED* geom1; //
CIRC_NODE* index;
} CircTreeGeomCache;
+/*
+* Other specific geometry cache types are the
+* RTreeGeomCache - lwgeom_rtree.h
+* PrepGeomCache - lwgeom_geos_prepared.h
+*/
+
+/*
+* Proj4 caching has it's own mechanism, but is
+* integrated into the generic caching system because
+* some geography functions make cached SRID lookup
+* calls and also CircTree accelerated calls, so
+* there needs to be a management object on
+* fcinfo->flinfo->fn_extra to avoid collisions.
+*/
/* An entry in the PROJ4 SRS cache */
typedef struct struct_PROJ4SRSCacheItem
}
PROJ4PortalCache;
-/*
-* Generic signature for function to take a serialized
-* geometry and return a tree structure for fast edge
-* access.
+/**
+* Generic signature for functions to manage a geometry
+* cache structure.
*/
-#if 0
-typedef int (*GeomIndexBuilder)(const LWGEOM* lwgeom, GeomCache* cache);
-typedef int (*GeomIndexFreer)(GeomCache* cache);
-typedef GeomCache* (*GeomCacheAllocator)(void);
-#endif
-
typedef struct
{
- int entry_number;
- int (*GeomIndexBuilder)(const LWGEOM* lwgeom, GeomCache* cache);
- int (*GeomIndexFreer)(GeomCache* cache);
- GeomCache* (*GeomCacheAllocator)(void);
+ int entry_number; /* What kind of structure is this? */
+ int (*GeomIndexBuilder)(const LWGEOM* lwgeom, GeomCache* cache); /* Build an index/tree and add it to your cache */
+ int (*GeomIndexFreer)(GeomCache* cache); /* Free the index/tree in your cache */
+ GeomCache* (*GeomCacheAllocator)(void); /* Allocate the kind of cache object you use (GeomCache+some extra space) */
} GeomCacheMethods;
/*
* Cache retrieval functions
*/
PROJ4PortalCache* GetPROJ4SRSCache(FunctionCallInfoData *fcinfo);
-GeomCache* GetGeomCache2(FunctionCallInfoData *fcinfo, const GeomCacheMethods* cache_methods, const GSERIALIZED* g1, const GSERIALIZED* g2);
+GeomCache* GetGeomCache(FunctionCallInfoData *fcinfo, const GeomCacheMethods* cache_methods, const GSERIALIZED* g1, const GSERIALIZED* g2);
CIRC_NODE* GetCircTree(FunctionCallInfoData* fcinfo, const GSERIALIZED* g1, const GSERIALIZED* g2, int* argnum_of_cache);
CircTreeGeomCache* GetCircTreeGeomCache(FunctionCallInfoData* fcinfo, const GSERIALIZED* g1, const GSERIALIZED* g2);
-/*
-* Given candidate geometries, a builer function and an entry type, cache and/or return an
-* appropriate tree.
-*/
-//void* GetGeomIndex(FunctionCallInfoData* fcinfo, int cache_entry, GeomIndexBuilder index_build, GeomIndexFreer tree_free, const GSERIALIZED* g1, const GSERIALIZED* g2, int* argnum);
#endif /* LWGEOM_CACHE_H_ */
PrepGeomCache*
GetPrepGeomCache(FunctionCallInfoData* fcinfo, GSERIALIZED* g1, GSERIALIZED* g2)
{
- return (PrepGeomCache*)GetGeomCache2(fcinfo, &PrepGeomCacheMethods, g1, g2);
+ return (PrepGeomCache*)GetGeomCache(fcinfo, &PrepGeomCacheMethods, g1, g2);
}
#include "lwgeom_geos.h"
/*
-** Cache structure. We use GSERIALIZED as keys so no transformations
-** are needed before we memcmp them with other keys. We store the
-** size to avoid having to calculate the size every time.
-** The argnum gives the number of function arguments we are caching.
-** Intersects requires that both arguments be checked for cacheability,
-** while Contains only requires that the containing argument be checked.
-** Both the Geometry and the PreparedGeometry have to be cached,
-** because the PreparedGeometry contains a reference to the geometry.
-typedef struct
-{
- char type;
- GSERIALIZED *pg_geom1;
- GSERIALIZED *pg_geom2;
- size_t pg_geom1_size;
- size_t pg_geom2_size;
- int32 argnum;
- const GEOSPreparedGeometry *prepared_geom;
- const GEOSGeometry *geom;
- MemoryContext context;
-}
-PrepGeomCache;
-*/
-/*
-typedef struct
-{
- int argnum;
- const GEOSPreparedGeometry *prepared_geom;
- const GEOSGeometry *geom;
-}
-PrepGeomCache;
+* Cache structure. We use GSERIALIZED as keys so no transformations
+* are needed before we memcmp them with other keys. We store the
+* size to avoid having to calculate the size every time.
+* The argnum gives the number of function arguments we are caching.
+* Intersects requires that both arguments be checked for cacheability,
+* while Contains only requires that the containing argument be checked.
+* Both the Geometry and the PreparedGeometry have to be cached,
+* because the PreparedGeometry contains a reference to the geometry.
+*
+* Note that the first 6 entries are part of the common GeomCache
+* structure and have to remain in order to allow the overall caching
+* system to share code (the cache checking code is common between
+* prepared geometry, circtrees, recttrees, and rtrees).
*/
typedef struct {
int type; // <GeomCache>
RTREE_POLY_CACHE*
GetRtreeCache(FunctionCallInfoData* fcinfo, GSERIALIZED* g1)
{
- RTreeGeomCache* cache = (RTreeGeomCache*)GetGeomCache2(fcinfo, &RTreeCacheMethods, g1, NULL);
+ RTreeGeomCache* cache = (RTreeGeomCache*)GetGeomCache(fcinfo, &RTreeCacheMethods, g1, NULL);
RTREE_POLY_CACHE* index = NULL;
if ( cache )