MS RFC 3:功能层插件架构

日期

2005/08/22

作者

贾尼阿维巴赫

联系方式

javerbach在extendtherach.com上

状态

采用

版本

MAPServer 4.8

抽象解

为实现虚拟表结构 layerObj . 此结构将包含用于所有层特定操作的函数指针。当层打开或第一次访问时,将填充此结构。之后,所有特定于后端格式的层操作都将通过缓存在 layerObj 结构。

技术解决方案

所有文件名和编号都与发布的MapServer 4.6.0源代码相对应。

  1. 将新字段添加到 layerObj . 它将是指向vtable的指针,vtable将包含此层的函数指针。

  2. 添加虚拟表体系结构

    当第一次访问层时,vtable将被初始化。vtable在创建时将被填充为假人,如果存在任何(例如不做任何事情)或默认返回错误,这些假人将执行可行的默认操作。

    2.1。当前从中找到的标准函数 maplayer.c

    2.1.1初始化信息

    int (*LayerInitItemInfo)(layerObj *layer);
    

    2.1.2.自由项信息

    void (*LayerFreeItemInfo)(layerObj *layer);
    

    2.1.3.正常开放

    int (*LayerOpen)(layerObj *layer);
    

    目前,有两个层接受的layeropen函数多于通用层arg:

    int msOGRLayerOpen(layerObj *layer,
                       const char *pszOverrideConnection);
    int msWFSLayerOpen(layerObj *lp,
                       const char *pszGMLFilename,
                       rectObj *defaultBBOX);
    

    但是,这些是从 msLayerOpen 具有 NULL 参数,所以我认为为这个虚拟表函数建议的接口应该是好的。

    2.1.4.ISOPEN

    int (*LayerIsOpen)(layerObj *layer);
    

    2.1.5。哪些形状

    int (*LayerWhichShapes)(layerObj *layer,
                            rectObj rect);
    

    2.1.6下一个形状

    int (*LayerNextShape)(layerObj *layer, shapeObj *shape);
    

    2.1.7.获得形状

    int (*LayerGetShape)(layerObj *layer, shapeObj *shape,
                         int tile, long record);
    

    2.1.8。层关闭

    int (*LayerClose)(layerObj *layer);
    

    2.1.9.层积物

    int (*LayerGetItems)(layerObj *layer);
    

    2.1.10。获得范围

    int (*LayerGetExtent)(layerObj *layer,
                          rectObj *extent);
    

    2.1.11.获取自动样式

    int (*LayerGetAutoStyle)(mapObj *map, layerObj *layer,
                             classObj *c, int tile,
                             long record);
    

    2.2.vtable的新功能和/或字段

    2.2.1闭连通

    此函数用于实际关闭连接,以防层自己实现某种连接池。如果层不使用任何连接池,则应将此函数作为no-op实现。调用方应首先调用层的“close”函数,最后调用 CloseConnection .

    函数的签名是

    int (*LayerCloseConnection)(layerObj *layer);
    

    调用这个函数的主要位置是 mapfile.c: 4822

    void msCloseConnections(mapObj *map)
    

    此功能是必需的,因为例如 POSTGIS 目前正在实现此使用模式 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.设置时间过滤器

    此函数用于为层创建时间筛选器。目前我们有三个特例( maplayer.c: 1635 ):

    1. POSTGIS 有它自己的功能

    2. 带有反勾号分隔表达式的层

    3. 没有背景的图层

    它的想法是提供一个通用的助手函数,

    int makeTimeFilter(layerObj *lp,
                       const char *timestring,
                       const char *timefield,
                       const bool bBackTicks)
    

    实际层的 SetTimeFilter 可以使用上面的内容,或者实现完全不同的内容,比如 POSTGIS 目前正在做。

    层vtable函数的签名是

    int (*LayerSetTimeFilter)(layerObj *lp,
                              const char *timestring,
                              const char *timefield);
    

    2.3。要添加到vtable的额外功能

    2.3.1Fltaply过滤器层( mapogcfilter.c: 1084

    这是图层的主要过滤界面。我们将提供两个助手函数,一个用于“SQL”案例,另一个用于“非SQL”案例,并设置所有层,除了 POSTGISORACLESPATIALOGR 直接调用这个助手函数的“非SQL”版本(if的else分支)。

    ORACLESPATIALPOSTGISOGR 如果满足此条件,则可以使用helper函数的“sql”版本(如果branch为actual),否则它们将使用该函数的非sql版本。

    2.3.2.layerobj->items allocation

    将有vtable功能用于分配 items 和的初始化 numitems . 如果层对这些对象有一些特殊的需求,它可以覆盖默认函数。

    函数的签名为:

    int (*CreateItems)(layerObj *)
    

    它进行分配并将numitems设置为正确的值。

    2.3.3mscheckconnection(检查连接)( mapfile.c: 4779

    此API已弃用。只有从 msMYGISLayerOpen . 我们不会通过vtable提供此功能。

    2.4。内部层的接口功能

    我们必须添加一些新的接口函数来访问层。

    2.4.1内部层类型初始化功能接口

    我们需要一个每层类型的函数,当必须初始化层的vtable时将调用该函数。这些功能将

    int msXXXInitializeLayerVirtualTable(layerObj *)
    

    其中,xxx将是层的名称。当vtable未初始化并且第一次访问层时,随时调用此函数。

    2.4.2更改层连接类型的功能接口

    要更改层的连接类型,必须通过函数接口完成。直接访问 connectiontype 不再支持字段。

    要更改连接类型并连接到新层,将有以下接口函数

    int msConnectLayer(int connectiontype,
                       const char *library_str)
    

    在哪里? connectiontype 是新层的类型,并且 library_str 是将为新层生成功能的库的名称。对于内部层类型,忽略第二个参数。

  3. 删除不需要的接口

    Frank Warmerdam建议[fw1]我们从 map.h .

    我看到每个“内置”模块(如mapsde.c)都提供了注册功能(如“mssdeinitializelayervirtualtable”),这样就不需要在map.h中再出现任何特定于层类型的定义。

    FW1
    Frank Warmerdam on the mapserver-dev:
    Message-Id: <smtpd.490f.4303f2ee.d8246.1@mtaout-c.tc.umn.edu>
    Date:       Wed, 17 Aug 2005 22:31:09 -0400
    Subject:    Re: MapServer  Plug-in Infastructure: RFC and PATCH

受影响的文件和对象

此建议将至少影响以下文件和对象:

  • map.h

    • layerObj 将包含新字段。将有一个新对象 vtableObjmap.h .

  • maplayer.c

    • 各种变化,层特定 switch -语句将消失,将添加vtable处理和层vtable初始化。

  • mapfile.c

    • 清洗 msCheckConnection

    • VTAT msCloseConnection

  • mapogcfilter.c

    • 从中删除层逻辑 FLTApplyFilterToLayer

  • mapXXX.c 在哪里 XXX 是层的名称。

    • 添加新的初始化函数

    • 添加所有新接口函数

    • 如果需要,修复现有接口函数/添加包装器 msOGRLayerOpenmsWFSLayerOpen .

向后兼容性问题

这是二进制和源代码级别的向后不兼容更改。该提案将删除一些以前的公共功能,并将新字段添加到 layerObj 结构。

此建议不是mapscript向后兼容,它将中断直接更改的脚本 connectiontype 字段在 layerObj .

建议是向后兼容的 Mapfile 。

实施问题

  • 最大的问题可能是作者忽略或错过了一些将在实施过程中出现的疏忽。但是,目前有一个外部插件架构的原型实现,它是基于本提案中提出的思想而工作的。因此,有一些实际的经验表明,这种架构更改是可行的。

  • 我还想指出,这个建议不会从MapServer中删除所有特定于层的代码,例如。 WMFWMSGRATICULE 在不同地方用作特殊情况。

臭虫识别码

错误 1477

投票历史

Jani Averbach于2005年9月19日提出投票,结果为+4(3名无投票权成员)。

投票+1:Howard Butler、Frank Warmerdam、Yewondwossen Assefa、Daniel Morissette

提案通过并将继续推进。

开放性问题

  • 我们希望如何向层公开层的虚拟表。我们至少要走两条不同的路线:

    • 将其作为结构公开,层将直接访问结构的字段来填充vtable指针。

    • 将其公开为完全不透明的类型,vtable指针将通过访问函数来设置 setLayerOpenFPsetLayerCloseFP 等等。

    第二个选项的先进之处在于,这样,如果我们重构更多的代码或者找到一些逻辑,我们可以很容易地向结构添加新的函数,而这些逻辑在这个建议中被忽略了。

  • 通过层API处理的栅格查询层支持有什么特殊问题吗?