MS RFC: Layer Plug-in Architecture
Paul Spencer
pspencer at DMSOLUTIONS.CA
Tue Sep 6 17:15:49 EDT 2005
Jani,
what will happen to mapscript code that changes the layer type on the
fly? What about dynamically created layers?
Paul
Jani Averbach wrote:
> Hello,
>
> Here is my updated proposal for the plug-in architecture.
>
> One note: I kept the CloseConnection and CloseLayer because POSTGIS
> needs both of them and it is already using new mappool API. So, if it
> is possible to remove this extra logic, it would be nice if someone
> who knows POSTGIS could comment. Otherwise, I think we should
> implement both of CloseConnection and CloseLayer.
>
> BR, Jani
>
>
> ==============================================
> MS RFC: Layer Plug-in Architecture
> ==============================================
> :Date: 2005/08/22
> :Author: Jani Averbach
> :Contact: javerbach at extendthereach.com
> :Last Edited: $Date: 2005-09-06 14:36:04 -0600 (Tue, 06 Sep 2005) $
> :Status: draft
>
>
> **Description:** Change current layer infrastructure from switch based
> static solution to the virtual table based dynamic solution. The main
> objectives for this proposal are cleaning and simplifying code and
> provide a robust architecture to implement dynamic plug-in API for
> external layer providers.
>
>
> Abstract Solution
> -----------------
>
> Implement a virtual table structure for ``layerObj``. This structure
> will contain function pointers for all layer specific operations.
> This structure will be populated when the layer is created or when it
> is opened. After that all back-end format specific layer operations
> will happen through this vtable which is cached in the ``layerObj``
> struct.
>
>
> Technical Solution
> ------------------
>
> All file names and numbers are against released MapServer 4.6.0 source
> code.
>
> 1. Add new field to the ``layerObj``. It will be pointer to the vtable,
> which will contain function pointers for this layer.
>
> 2. Add the virtual table architecture
>
> The vtable will be initialized when the layerObj is created and
> parsed, this will happen in the function (mapfile.c):
> ::
>
> int loadLayer(layerObj *layer, mapObj *map)
>
> The vtable will be populated with dummies when it is created and
> these dummies will implement feasible default actions if there are
> any (e.g. do nothing) or return error by default.
>
>
> 2.1. Standard functions which are found currently from ``maplayer.c``
>
> 2.1.1. InitItemInfo
> ::
>
> int (*LayerInitItemInfo)(layerObj *layer);
>
>
> 2.1.2. FreeItemInfo
> ::
>
> void (*LayerFreeItemInfo)(layerObj *layer);
>
>
> 2.1.3. Open
> ::
>
> int (*LayerOpen)(layerObj *layer);
>
> Currently there are two layers which accept more than
> the generic layer arg for LayerOpen function:
> ::
>
> int msOGRLayerOpen(layerObj *layer,
> const char *pszOverrideConnection);
> int msWFSLayerOpen(layerObj *lp,
> const char *pszGMLFilename,
> rectObj *defaultBBOX);
>
> However, these are called from ``msLayerOpen`` with
> ``NULL`` args, so I think that proposed interface for
> this virtual table function should be fine.
>
>
> 2.1.4. IsOpen
> ::
>
> int (*LayerIsOpen)(layerObj *layer);
>
>
> 2.1.5. WhichShapes
> ::
>
> int (*LayerWhichShapes)(layerObj *layer,
> rectObj rect);
>
> 2.1.6. NextShape
> ::
>
> int (*LayerNextShape)(layerObj *layer, shapeObj *shape);
>
>
> 2.1.7. GetShape
> ::
>
> int (*LayerGetShape)(layerObj *layer, shapeObj *shape,
> int tile, long record);
>
>
> 2.1.8. LayerClose
> ::
>
> int (*LayerClose)(layerObj *layer);
>
>
> 2.1.9. LayerGetItems
> ::
>
> int (*LayerGetItems)(layerObj *layer);
>
>
> 2.1.10. GetExtent
> ::
>
> int (*LayerGetExtent)(layerObj *layer,
> rectObj *extent);
>
>
> 2.1.11. GetAutoStyle
> ::
>
> int (*LayerGetAutoStyle)(mapObj *map, layerObj *layer,
> classObj *c, int tile,
> long record);
>
>
>
> 2.2. New functions and/or fields for vtable
>
> 2.2.1. CloseConnection
>
> This function is used to actually close the
> connection, in case that layer implements some kind of
> connection pooling by its own. If layer doesn't use
> any connection pooling, this function should be
> implemented as no-op. Caller should first call layer's
> "close" function, and finally at the very end
> ``CloseConnection``.
>
> The signature of function is
> ::
>
> int (*LayerCloseConnection)(layerObj *layer);
>
>
> And the main place where this function will be called,
> is ``mapfile.c: 4822``
> ::
>
> void msCloseConnections(mapObj *map)
>
> This function is needed because e.g. ``POSTGIS`` is
> implementing this usage pattern at the moment
> ``maplayer.c:599``
> ::
>
> void msLayerClose(layerObj *layer)
> ...
> /*
> * Due to connection sharing, we need to close the results
> * and free the cursor, but not close the connection.
> */
> msPOSTGISLayerResultClose(layer);
>
>
> 2.2.2. SetTimeFilter
>
> This function is used to create a time filter for
> layer. At the moment we have three special cases
> (``maplayer.c: 1635``):
>
> 1. ``POSTGIS`` with it's own function
> 2. Layers with backticks delimited expressions
> 3. Layers without backticks
>
> The idea is provide a generic helper function,
> ::
>
> int makeTimeFilter(layerObj *lp,
> const char *timestring,
> const char *timefield,
> const bool bBackTicks)
>
> And the actual layer's ``SetTimeFilter`` could use the
> above, or implement something totally different as
> ``POSTGIS`` is doing at the moment.
>
> The signature for layer's vtable function is
> ::
>
> int (*LayerSetTimeFilter)(layerObj *lp,
> const char *timestring,
> const char *timefield);
>
>
>
> 2.3. Extra functions to add to the vtable
>
> 2.3.1. FLTApplyFilterToLayer (``mapogcfilter.c: 1084``)
>
> This is the main filter interface for layers. We will
> provide two helper functions, one for "SQL" case and
> the another for "non-SQL" case, and set all layers,
> except ``POSTGIS``, ``ORACLESPATIAL`` and ``OGR`` to
> call directly this "non-SQL" version of this helper
> function (else-branch of if).
>
> ``ORACLESPATIAL``, ``POSTGIS`` and ``ORG`` could use
> "SQL" version of the helper function (actual if-branch)
> if the conditions for this are met, otherwise they will
> use Non-SQL version of the function.
>
>
> 2.3.2. layerObj->items allocation
>
> There will be vtable function for allocation ``items`` and
> initialization for ``numitems``. If layer has some
> special needs for these objects it can override default
> function.
>
> The signature for function will be:
> ::
>
> int (*CreateItems)(layerObj *)
>
> which does the allocation and set numitems to correct
> value.
>
> 2.3.3. msCheckConnection (``mapfile.c: 4779``)
>
> This API is deprecated. It is called only from
> ``msMYGISLayerOpen``. We will not provide this
> functionality through vtable.
>
>
> 2.4. Interface functions for internal layers
>
> We have to add at least some new interface functions for
> internal layers, e.g. ``msXXXInitializeLayerVirtualTable``,
> where ``XXX`` is the layer's name.
>
>
>
> 3. Remove unwanted interfaces
>
> Frank Warmerdam proposed [FW1]_ that we remove all layer specific
> interface functions from ``map.h``.
>
> I see each "built-in" module such as mapsde.c providing a
> registration function such as "msSDEInitializeLayerVirtualTable"
> so that none of the layer type specific definitions need to
> appear in map.h any more.
>
> .. [FW1]
> | ``Frank Warmerdam on the mapserver-dev:``
> | ``Message-Id: <smtpd.490f.4303f2ee.d8246.1 at mtaout-c.tc.umn.edu>``
> | ``Date: Wed, 17 Aug 2005 22:31:09 -0400``
> | ``Subject: Re: Mapserver Plug-in Infastructure: RFC and PATCH``
>
>
>
>
> Files and objects affected
> --------------------------
>
> This proposal will affect at least following files and objects:
>
> * ``map.h``
>
> * ``layerObj`` will contain new fields. There will be a new
> object ``vtableObj`` in the ``map.h``.
>
>
> * ``maplayer.c``
>
> * Various changes, layer specific ``switch``-statements will go
> away, vtable handling and layers vtable initialization will be
> added.
>
>
> * ``mapfile.c``
>
> * mapfile writing will change slightly, no more ``if-else``
> structure for connectiontype strings.
> * Cleaning of ``msCheckConnection``
> * Vtable for ``msCloseConnection``
>
>
> * ``mapogcfilter.c``
>
> * Remove layer-logic from ``FLTApplyFilterToLayer``
>
>
> * ``mapXXX.c``, where ``XXX`` is the name of layer.
>
> * Add new initialization function
> * Add all new interface functions
> * Fix existing interface functions, if needed / add wrappers for
> ``msOGRLayerOpen`` and ``msWFSLayerOpen``.
>
>
>
> Backwards compatibility issues
> ------------------------------
>
> This is binary and source code level backward incompatible change. The
> proposal will remove some previously public functions, and add new
> field(s) to the ``layerObj`` struct. The proposal is ``MAP``-file
> backward compatible.
>
>
> Implementation Issues
> ---------------------
>
> * Biggest problem is probably that the author has ignored or missed
> something by oversight which will show up during implementation.
> However, there is a prototype implementation of external plug-in
> architecture which works at the moment and is based on ideas
> presented in this proposal. So there is some real life experience
> that this architecture change is feasible thing to do.
>
> * I also like to note that this proposal won't remove all layer
> specific code from MapServer e.g. ``WMF``, ``WMS`` and ``GRATICULE``
> are used as special cases from place to place.
>
>
>
> Bug ID
> ------
>
> unassigned
>
>
>
> Voting history
> --------------
>
> None
>
>
>
> Open questions
> --------------
>
> * MapScript. What is the impact of this change to the MapServer's
> MapScript Interface?
>
> * How do we like to expose layer's virtual table to the layers. We
> have at least two different routes to go:
>
> * expose it as a struct, layers will fill vtable pointers by
> accessing directly struct's field.
>
> * expose it as a complete opaque type, vtable pointers will be set
> by accessing functions ``setLayerOpenFP``, ``setLayerCloseFP`` and
> so on.
>
> The advance of second option is that this way we could easily add
> new functions to the struct if we refactor code more or found some
> logic which is ignored by oversight in this proposal.
>
>
> * Are there any special issues with the raster query layer support
> which is handled via the layer API?
>
>
> =============
> Working Notes
> =============
>
>
>
> .. Local Variables:
> mode: text
> End:
>
--
+-----------------------------------------------------------------+
|Paul Spencer pspencer at dmsolutions.ca |
+-----------------------------------------------------------------+
|Applications & Software Development |
|DM Solutions Group Inc http://www.dmsolutions.ca/|
+-----------------------------------------------------------------+
More information about the mapserver-dev
mailing list