MS RFC 22A:用于长时间运行进程和查询处理的功能缓存

日期

2007/06/24

作者

塔玛斯塞克勒斯

联系

gmail.com上的szekerest

最后编辑

2007/06/24

状态

讨论稿

版本

MAPServer 5

1。概述

目前,各种查询操作涉及对数据提供程序的多次访问,这可能会对性能产生重大影响,具体取决于提供程序。在第一阶段,检索给定搜索区域中的所有功能,并将相关形状的索引存储在结果缓存中。在第二阶段中,结果缓存中的特性将逐个从提供程序中检索。保留内存中的形状,我们可以消除对提供者的后续访问需求,并提高查询的整体性能。实现缓存需要在数据提供程序和客户机之间转换数据。从这一方面来说,需要提供一个框架来在更高的抽象层次上实现这种转换。

2。目的

此RFC的主要目的是实现功能缓存,并将形状保留在内存中,以便在查询操作期间进一步检索。不过,我也希望创建一种机制,以便一个层可以使用另一个层作为数据源。这个外层可以对来自基础层的形状应用转换,甚至可以将形状保留在内存中以供后续提取。下面是一些其他示例,其中该框架将提供解决方案:

  1. 基于特征属性构造几何图形

  2. 修改几何图形或特征属性值

  3. 几何变换(如地理操作)

  4. 特征缓存

  5. 基于外部样式信息或基于属性的样式提供默认图层样式

  6. 提供自定义数据筛选器

建立一个适当的层层次结构可以解决相当复杂的问题,而不需要创建额外的(如mapscript)代码。稍后,作为一个实况示例,我将展示以下场景的解决方案:

  1. 用户将在一个层中选择一个或多个形状(在本例中,按属性选择)。

  2. 层叠转换将应用于所选形状(我将使用geos converxfull和buffer操作)

  3. 在另一层中,将根据转换后的形状选择特征作为选择形状。

在这个建议中,为了确保更好的可读性,我将避免将大部分代码嵌入到内联中。然而,大多数实现补丁都可以在这个RFC的跟踪标签上找到(见下文)。

三。解决方案的一般原则

这个提议涉及到编写额外的数据提供者。这些提供者将使用另一个层作为特性的源。要设置层的层次结构,这些层的连接参数将包含源层的名称。在某些情况下,源层不参与渲染,应保持在原始层内部。因此,我们将建立将层嵌套到彼此中的支持。在这方面,连接参数将包含它所引用的层的完整路径。路径包含层次结构中的层名称,使用斜线“/”作为名称之间的分隔符。我们可以指定相对于实际图层或相对于地图本身的路径名。

  1. 指定相对于地图的引用:

LAYER
  NAME "roads"
  CONNECTIONTYPE OGR
  CONNECTION "roads.tab"
  ...
END
LAYER
  NAME "cache"
  CONNECTIONTYPE CACHE
  CONNECTION "/roads"
  ...
END
  1. 指定相对于外层的参照

LAYER
  NAME "cache"
  CONNECTIONTYPE CACHE
  CONNECTION "roads"
  ...
  LAYER
    NAME "roads"
    CONNECTIONTYPE OGR
    CONNECTION "roads.tab"
    ...
  END
END

这两个选项之间的主要区别在于,在第一种情况下,引用的图层包含在地图的图层集合中,因此图层将参与到图形中。在第二种情况下,参考层位于外层的内部。支持两个或多个层连接到同一个基础层,以便从同一个缓存存储库提供功能。基础层可以位于层层次的任何位置。

在任何情况下,扩展层也可以实现为可插拔的外部层。(ConnectionType插件)

为了实现所需的功能,将实施以下3个供应商:

3.1功能缓存提供程序

此提供程序的目的是将源层中的功能保留在内存中,以便从内部缓存提供对功能缓存提供程序的后续提取。在当前的实现中,我计划保留最后一个方面的形状。当后续的形状检索引用相同的范围(或在该范围内)时,将从缓存提供功能。目前,我不会处理来自多个不重叠扩展数据块的缓存功能,也不会实现更复杂的缓存管理(如大小限制/到期处理),但它可能是将来增强的对象。所有特定于提供程序的数据都将放置在提供程序的layerInfo结构中。缓存中的形状将存储在哈希表中。此提供程序将在单独的文件(mapcache.c)中实现。

3.1.1形状检索选项

此提供程序将能够使用给定范围内的所有形状或仅使用源层的resultcache中的形状填充缓存。第一个是默认选项,后者可以通过以下处理指令选择:

PROCESSING "fetch_mode=selection"

当给定的rect超出前一个rect时,将根据缓存提供程序的whichshapes调用填充缓存。我们还可以指定,无论搜索区域如何,提供者都将使用以下设置重新提取当前地图范围的所有形状:

PROCESSING "spatial_selection_mode=mapextent"

3.1.2项目选择

功能缓存提供程序将存储所有可用的项目,而不管从外部选择了哪些项目(通过使用which items调用)。但是,iteminfo将只包含请求项的索引。getshape和nextshape操作将只将请求的项目子集复制到调用方。此解决方案将提供与任何其他现有提供程序的兼容性,因此无需从这一方面更改公共MapServer代码。

3.1.3支持样式项“auto”选项

通过使用样式项“auto”选项,提供程序可以从数据源中检索每个shapeobj的classobj。为了继续支持此选项,缓存提供程序将能够在单独的哈希表中缓存这些classobj-s以及shapeobj-s。当在功能缓存提供程序上设置了样式项“auto”选项时,也将通过将getautostyle函数调用到源层来填充样式缓存。功能缓存提供程序上的后续getautostyle调用将从样式缓存中检索Classobj-s,并向调用者提供一个副本。

3.1.4支持属性过滤器

功能缓存提供程序将与现有查询操作兼容(在mapquery.c中的msqueryby[]函数中实现)。为了支持msquerybyattributes,nextshape将在将形状返回给调用方之前使用msevelExpression。

3.2几何变换提供者

几何转换提供程序(在mapgeomtrans.c中实现)将支持对源层的透明访问。每个vtable操作将被调度到源层的相应vtable操作。此外,某些其他层属性可能需要在连接的层之间进行复制。

3.2.1项目选择

此提供程序将与源层提供的项目子集相同。因此,initeminfo将把外部层的items和numitems复制到源层,例如:

int msGeomTransLayerInitItemInfo( layerObj *layer )
{
    /* copying the item array an call the subsequent InitItemInfo*/
    return msLayerSetItems(((GeomTransLayerInfo*)layer->layerinfo)->srclayer, layer->items, layer->numitems);
}

在getitems调用时,这些值将被复制回外部层,如:

int msGeomTransLayerGetItems(layerObj *layer)
{
    /* copying the item array back */
    int result;
    GeomTransLayerInfo* layerinfo = (GeomTransLayerInfo*)layer->layerinfo;
    result = msLayerGetItems(layerinfo->srclayer);
    msLayerSetItems(layer, layerinfo->srclayer->items, layerinfo->srclayer->numitems);
    return result;
}

3.2.2应用转换

提议的实现将支持MapServer支持的大多数GEO转换(buffer、converxfull、boundary、union、intersection、difference、symdifference)。转换将在将形状检索到调用方之前应用。可以使用处理选项选择所需的转换,例如:

PROCESSING "transformation=buffer"

一些转换将接受进一步的参数:

PROCESSING "buffer_width=0.2"

其中一些操作将使用两个形状来创建转换后的形状。这些转换的引用形状可以使用处理选项的wkt表示法从外部设置:

PROCESSING "ref_shape=[WKT of the shape]"

我还计划支持从层的特性集合和外部层中检索此形状。

3.3层过滤器提供程序

层筛选器提供程序(在mapfilter.c中实现)将提供从源层检索到的形状,并且不会对此应用任何转换。但是,根据空间和属性选择选项,在下一个形状操作中将跳过某些形状。此提供程序确保对源层(与前一层一样)的透明访问,但使用缓存存储选择形状。将从另一层检索选择形状,该层可以在以下处理选项中指定:

PROCESSING "selection_layer=[path to the layer]"

在填充选择缓存时,我将支持检索结果缓存中的所有形状或仅检索结果缓存中的形状,就像前面提到的缓存提供程序一样:

PROCESSING "fetch_mode=selection"

4。把东西放在一起(例子)

在本章中,我将描述前面提到的场景的解决方案。我将从一个简单的 Mapfile 定义开始,其中包含两层国家和城市点:

MAP
      NAME "Hungary"
      STATUS ON
      EXTENT 421543.362603 47885.103526 933973.563202 367180.479761
      SIZE 800 600
      IMAGETYPE PNG
      IMAGECOLOR 255 255 255

      PROJECTION
              "proj=somerc"
              "lat_0=47.14439372222222"
              "lon_0=19.04857177777778"
              "x_0=650000"
              "y_0=200000"
              "ellps=GRS67"
              "units=m"
              "no_defs"
      END

      SYMBOL
          Name 'point'
          Type ELLIPSE
          POINTS
              1 1
          END
          FILLED TRUE
      END

      LAYER
              PROJECTION
                      "AUTO"
              END
              NAME "Hun_Counties"
              CONNECTIONTYPE OGR
              CONNECTION "Hun_Megye.TAB"
              STATUS default
              TYPE POLYGON
              LABELITEM "name"
              CLASS
                      TEMPLATE "query.html"
                      LABEL
                              SIZE medium
                              COLOR 64 128 64
                      END
                      STYLE
                              COLOR 208 255 208
                              OUTLINECOLOR 64 64 64
                      END
              END
      END
      LAYER
              PROJECTION
                      "AUTO"
              END
              NAME "Hun_CityPoints"
              CONNECTIONTYPE OGR
              CONNECTION "Hun_CityPoints.TAB"
              STATUS default
              TYPE POINT
              CLASS
                      STYLE
                              COLOR 255 0 0
                              SYMBOL "point"
                              SIZE 2
                      END
              END
      END
END

此地图将如下所示:

http://trac.osgeo.org/mapserver/attachment/ticket/2128/sample.png

4.1添加层的功能缓存

任何层都可以使用缓存层提供程序进行缓存。原始提供程序可能嵌套在缓存中。应为外层指定与图纸相关的参数,如:

LAYER
            PROJECTION
                    "AUTO"
            END
            NAME "Hun_Counties_cache"
            CONNECTIONTYPE CACHE
            CONNECTION "Hun_Counties"
            STATUS default
            TYPE POLYGON
            LABELITEM "name"
            CLASS
                    TEMPLATE "query.html"
                    LABEL
                            SIZE medium
                            COLOR 64 128 64
                    END
                    STYLE
                            COLOR 208 255 208
                            OUTLINECOLOR 64 64 64
                    END
            END
            LAYER
                PROJECTION
                        "AUTO"
                END
                NAME "Hun_Counties"
                CONNECTIONTYPE OGR
                CONNECTION "Hun_Megye.TAB"
                TYPE POLYGON
            END
    END

Hun_Counties_缓存层是可查询的,所有现有方法都可用于填充ResultCache。在我的示例中,我将使用mapscript c drawquery示例(在drawquery.cs中实现)来执行属性查询,然后使用drawquery。以下命令将与此示例一起使用:

drawquery sample.map "('[Name]'='Tolna')" sample.png

它将(“[名称]”=“tolna”)查询字符串传递给第一层的queryByAttributes。

渲染的结果如下:

http://trac.osgeo.org/mapserver/attachment/ticket/2128/sample1.png

在这里可以找到相应的映射文件:

http://trac.osgeo.org/mapserver/attachment/ticket/2128/sample1.map

4.2对县实施改造

在下一步中,我将在第一层应用层叠的geos converxfull和buffer操作。将使用以下定义在单独的层中呈现结果:

LAYER
             NAME "selectionshape"
             CONNECTIONTYPE GEOMTRANS
             CONNECTION "simplify"
             STATUS default
             TYPE POLYGON
             TRANSPARENCY 50
             CLASS
                     STYLE
                             COLOR 64 255 64
                             OUTLINECOLOR 64 64 64
                     END
             END
             PROCESSING "transformation=buffer"
             PROCESSING "buffer_width=0.2"
             LAYER
                NAME "simplify"
                TYPE POLYGON
                CONNECTIONTYPE GEOMTRANS
                CONNECTION "/Hun_Counties_cache"
                PROCESSING "transformation=convexhull"
             END
     END

渲染的结果如下:

http://trac.osgeo.org/mapserver/attachment/ticket/2128/sample2.png

对应的映射文件:

http://trac.osgeo.org/mapserver/attachment/ticket/2128/sample2.map

这不是所期望的结果,因为所有的多边形都被转换了。为了仅转换所选形状,应使用“fetch_mode=selection”处理选项指定附加缓存:

LAYER
            NAME "selectionshape"
            CONNECTIONTYPE GEOMTRANS
            CONNECTION "simplify"
            STATUS default
            TYPE POLYGON
            TRANSPARENCY 50
            CLASS
                    STYLE
                            COLOR 64 255 64
                            OUTLINECOLOR 64 64 64
                    END
            END
            PROCESSING "transformation=buffer"
            PROCESSING "buffer_width=0.2"
            LAYER
               NAME "simplify"
               TYPE POLYGON
               CONNECTIONTYPE GEOMTRANS
               CONNECTION "selectioncache"
               PROCESSING "transformation=convexhull"
               LAYER
                   NAME "selectioncache"
                   TYPE POLYGON
                   CONNECTIONTYPE CACHE
                   CONNECTION "/Hun_Counties_cache"
                   PROCESSING "fetch_mode=selection"
               END
            END
    END

这是图纸的结果:

http://trac.osgeo.org/mapserver/attachment/ticket/2128/sample3.png

对应的映射文件:

http://trac.osgeo.org/mapserver/attachment/ticket/2128/sample3.map

4.3将转换后的形状作为选择形状

我的最终目标是选择点图层的特征,使用转换后的形状作为选择形状。因此,我必须在点图层上使用图层过滤器提供程序,并将选择图层设置为转换图层:

LAYER
         TYPE POINT
         CONNECTIONTYPE LAYERFILTER
         CONNECTION "Hun_CityPoints"
         NAME "selectedpoints"
         STATUS default
         PROCESSING "selection_layer=/selectionshape"
         CLASS
             STYLE
                     COLOR 255 0 0
                     SYMBOL "point"
                     SIZE 2
             END
         END
         LAYER
                 PROJECTION
                         "AUTO"
                 END
                 NAME "Hun_CityPoints"
                 CONNECTIONTYPE OGR
                 CONNECTION "Hun_CityPoints.TAB"
                 TYPE POINT
         END
     END

结果如下:

http://trac.osgeo.org/mapserver/attachment/ticket/2128/sample4.png

对应的映射文件:

http://trac.osgeo.org/mapserver/attachment/ticket/2128/sample4.map

注1:在不改变地图配置的情况下,我可以从外部修改选择,渲染的图像将自动反映更改。例如,我可以使用查询字符串选择2个县:('[name]='tolna'或'[name]='baranya')

结果图像可以在这里找到:

http://trac.osgeo.org/mapserver/attachment/ticket/2128/sample4a.png

注2:如果不需要呈现选择层,我可以直接指定配置:

LAYER
        TYPE POINT
        CONNECTIONTYPE LAYERFILTER
        CONNECTION "Hun_CityPoints"
        NAME "selectedpoints"
        STATUS default
        PROCESSING "selection_layer=selectionshape"
        CLASS
            STYLE
                    COLOR 255 0 0
                    SYMBOL "point"
                    SIZE 2
            END
        END
        LAYER
                PROJECTION
                        "AUTO"
                END
                NAME "Hun_CityPoints"
                CONNECTIONTYPE OGR
                CONNECTION "Hun_CityPoints.TAB"
                TYPE POINT
        END
        LAYER
                NAME "selectionshape"
                CONNECTIONTYPE GEOMTRANS
                CONNECTION "simplify"
                STATUS default
                TYPE POLYGON
                TRANSPARENCY 50
                CLASS
                        STYLE
                                COLOR 64 255 64
                                OUTLINECOLOR 64 64 64
                        END
                END
                PROCESSING "transformation=buffer"
                PROCESSING "buffer_width=0.2"
                LAYER
                    NAME "simplify"
                    TYPE POLYGON
                    CONNECTIONTYPE GEOMTRANS
                    CONNECTION "selectioncache"
                    PROCESSING "transformation=convexhull"
                    LAYER
                        NAME "selectioncache"
                        TYPE POLYGON
                        CONNECTIONTYPE CACHE
                        CONNECTION "/Hun_Counties_cache"
                        PROCESSING "fetch_mode=selection"
                    END
                END
        END
    END

结果如下:

http://trac.osgeo.org/mapserver/attachment/ticket/2128/sample5.png

以及相应的映射文件:

http://trac.osgeo.org/mapserver/attachment/ticket/2128/sample5.map

回想一下,因为我在Countries层上使用了缓存,所以所有这些渲染都只需要从原始提供者那里检索一次形状。这是这个RFC的主要目标。

5。修改MapServer核心

要实现所需的功能性,应在MapServer核心中执行以下主要步骤。建议更改的详细信息可在此处找到:

http://trac.osgeo.org/mapserver/attachment/ticket/2128/common.patch

5.1哈希表实现

当前的哈希表实现(在maphash.c中)将被概括为能够存储对象和字符串。当前哈希表只能存储字符串值。此外,我们还将在构造哈希表时提供指定哈希大小的支持。对象将被引用存储在哈希表中,对象的销毁功能也可以在外部指定。以下函数将添加到maphash.c中

int initHashTableEx( hashTableObj *table, int hashSize );
void msClearHashItems( hashTableObj *table );
struct hashObj *msInsertHashTablePtr(hashTableObj *table, const char *key, const char *value);
struct hashObj *msFirstItemFromHashTable( hashTableObj *table);
struct hashObj *msNextItemFromHashTable( hashTableObj *table, struct hashObj *lastItem );
int msGetHashTableItemCount(hashTableObj *table);

可以调用initHashTableEx以在外部指定哈希大小。实际上,原始的inithashtable将实现为使用ms_hashsize调用inithashtableex。msclearhashitems将清除哈希表的所有元素,但不清除items数组。msinserthashtableptr提供通过引用哈希表添加对象的支持。msfirstitemfromhashtable和msnextitemfromhashtable将有效地提供元素的迭代,并由功能缓存提供程序的nextshape调用。msgethashtableitemcount将检索哈希表项的实际数目。

5.2扩展layerobj结构以支持嵌套层(map.h)

layerObj结构中的子层将存储为一个层数组。

typedef struct layer_obj {
  ...
  #ifndef SWIG
  struct layer_obj **layers;
  int numlayers; /* number of sublayers in layer */
  #endif /* SWIG */
  ...
} layerObj;

解析器将负责加载嵌套层:

int loadLayer(layerObj *layer, mapObj *map)
{
  ...
  case (LAYER):
    if(layer->numlayers == 0)
        layer->layers = (layerObj**) malloc(sizeof(layerObj*));
    else
        layer->layers = (layerObj**) realloc(layer->layers, sizeof(layerObj*) * (layer->numlayers));
    layer->layers[layer->numlayers]=(layerObj*)malloc(sizeof(layerObj));
    if (layer->layers[layer->numlayers] == NULL) {
         msSetError(MS_MEMERR, "Malloc of a new layer failed.", "loadLayer()");
             return MS_FAILURE;
    }
    if(loadLayer(layer->layers[layer->numlayers], map) == -1) return MS_FAILURE;
    layer->layers[layer->numlayers]->index = layer->numlayers; /* save the index */
    ++layer->numlayers;
    break;
  ...
}

5.3添加新的内置数据连接类型(map.h)

为新的提供程序建立了新的数据连接类型。

enum MS_CONNECTION_TYPE {MS_INLINE, MS_SHAPEFILE, MS_TILED_SHAPEFILE, MS_SDE, MS_OGR, MS_UNUSED_1, MS_POSTGIS, MS_WMS,   MS_ORACLESPATIAL, MS_WFS, MS_GRATICULE, MS_MYGIS, MS_RASTER, MS_PLUGIN, MS_GEOMTRANS, MS_LAYERFILTER, MS_CACHE };

将修改lexer以解释新的连接类型。

5.4支持销毁提供者的持久数据(map.h、maplayer.c)

提供程序将在该层上的各种连接/关闭操作之间保留持久性数据,因此我们应该建立一种机制,通过向layervtable添加新方法来销毁此提供程序特定的数据:

void (*LayerDestroy)(layerObj *layer);

5.5新数据提供程序的vtable初始化(maplayer.c)

int
msInitializeVirtualTable(layerObj *layer)
{
  if (layer->baselayer)
      msInitializeVirtualTable(layer->baselayer);
  ...
  switch(layer->connectiontype) {
  ...
  case(MS_GEOMTRANS):
          return(msGeomTransLayerInitializeVirtualTable(layer));
          break;
      case(MS_LAYERFILTER):
          return(msFilterLayerInitializeVirtualTable(layer));
          break;
      case(MS_CACHE):
          return(msCacheLayerInitializeVirtualTable(layer));
          break;
  ...
  }
  ..
}

6。受影响的文件

以下文件将受此RFC的影响:

maphash.c
maphash.h
maplayer.c
maplexer.l
mapfile.c
map.h
Makefile.vc
Makefile.in
mapcache.c  (new)
mapgeomtrans.c  (new)
mapfilter.c  (new)

7。向后兼容性问题

这些更改将保持mapfile和mapscript向后兼容性。

8.错误ID

这里有RFC-22A的票。

错误2128

9。投票历史

没有