MS RFC 17:层、样式、类和符号的动态分配

日期

2006/05/12

作者

Frank Warmerdam,编辑:Daniel Morissette和Umberto Nicoletti

联系

在pobox.com上的warmerdam,在mapgears.com上的dmorissette,在gmail.com上的umberto.nicoletti

最后编辑

2007/07/18

状态

通过(2007/07/18)-完成实施(2007/07/23)

版本

MAPServer 5

目的

修改mapserver核心库,使层、类和样式的列表是动态的,而不是固定的,以编译限制ms-maxclasses、ms-maxstyles、ms-maxlayers和ms-maxsymbols。

MS_MAXSYMBOLS

将符号改为:

int numsymbols;
symbolObj symbol[MS_MAXSYMBOLS];

变成::

int numsymbols;
int maxsymbols;
symbolObj **symbol;

添加以下函数以确保symbolsetobj中的符号数组中至少有一个自由项。此函数仅在需要时增大已分配的指针数组(如果maxsymbols==numsymbols),然后在symbol[numsymbols]==null时分配新的symbolobj。数组中的新条目将设置为空,新符号obj[numsymbols]将全部设置为零字节。

symbolObj *msGrowSymbolSet( symbolSetObj * );
  • 修改所有添加新符号的地方以调用msgrowSymbolset(),以确保有空间。这些位置可以很容易地通过在ms_MaxSymbols上加灰来识别。

  • 修改通过索引访问符号的所有位置,以使用正确的方式引用新数组中的符号,可能使用类似于在MS-RFC-24中为层添加的get_layer()的get_symbol()宏。

  • c:修改msinitsymbolset()以最初使用一个仅包含一个符号的数组设置符号集。

  • 不应该需要对swig mapscript进行任何更改,因为它已经使用了msAppendSymbol()。

MS_MAXLAYERS

  • 地图:h以来 MS RFC 24:MapScript内存管理 已经将mapobj中的层数组转换为指针数组,我们只需要向mapobj添加“int maxlayers”;以指示层数组的当前分配大小。注意,这也决定了MAPOBJ图层顺序数组的大小。

  • mapdraw.c:将msdrawmap()更改为使用map->numlayers代替asowreqinfo数组的当前ms_maxlayers。

  • c:添加msgrowmaplayers(mapobj*)函数,以确保地图上至少还有一个图层的空间。这将增加层和层顺序数组。

  • mapobject.c:修改msinsertlayer()和mapscript层构造函数代码(参见最后一项)以使用msgrowmaplayers()。

  • mapfile.c:将maxlayers设置为ms_maxlayers,并在initmap()中相应地分配层。解析时,请在调用LoadLayer()和LoadLayerValue()之前使用msgrowMaplayers()。

  • mappluginlayer.c:让它充满活力。我不确定有什么静态工厂,其条目的尺寸是由层数决定的。

  • 看起来swig-mapscript已经有了一个使用msinsertlayer()的mapobj.insertlayer()方法,这应该是安全的。MAPScript应用程序有时会直接更新层和numlayers吗?答:所有层操作都是由层构造函数(当非空的mapobj作为唯一参数传递时)或msinsertlayer完成的。还必须修改层构造函数。

MS_MAXCLASSES

  • map.h:在layerobj中添加maxclasses字段(rfc-24已经将layerobj中的类数组转换为指针数组)。

  • layerObject.c:修改msinsertclass()和mapscript构造函数代码(类似于层)以使用msgrowlayerClasses()。

  • layerObject.c:添加msgrowlayerClasses()以确保类列表中至少有一个额外的类。

  • msdrawquerylayer()中的mapdraw.c:colorbuffer和mindistancebuffer需要动态调整大小并在堆上分配。

  • mapfile.c:initlayer()需要将maxclasses初始化为ms_maxclasses,并相应地分配类列表。

  • mapogcsld.c:修改以使用msgrowlayerClasses()而不是检查限制。

MS_MAXSTYLES

  • map.h:将maxStyles字段添加到classobj(RFC-24已经将classobj中的样式数组转换为指针数组)。

  • mapfile.c:将maxStyles设置为ms_maxStyles,并在initclass()中进行相应分配。使用msgrowClassStyles()作为apppriate。

  • classproject.c:添加msgrowClassStyles()以确保存在未使用的类。

  • classobject.c:在msinsertstyle()和样式构造函数中使用msgrowClassStyles()。

受影响的文件和对象

map.h
mapfile.c
mapsymbol.c
mapdraw.c
mapobject.c
mappluginlayer.c
layerobject.c
mapogcsld.c
classobject.c
mapscript/swiginc/layer.i
mapscript/swiginc/class.i
mapscript/swiginc/style.i

向后兼容性问题

没有。

测试套件

python单元测试条目将被添加以超过所有层、类、样式和符号的内置最大值。还将添加一个包含大量类的msautotest条目。

臭虫识别码

投票历史

投票于2007年7月19日完成:

+1来自丹尼尔、史蒂文、弗兰克、史蒂文、乌姆伯顿、塔马斯、阿塞菲。

审查期间的意见/问题

  • 由于代码已经在initmap()中分配了小于ms_max_层,因此RFC-24是否已经处理了以下问题?RFC-24是否正式要求使用适当的插入/添加方法添加层、样式和类?

答:采用的实施方式 MS RFC 24:MapScript内存管理 试图通过只分配有效需要的层的数量来节省内存。一张有5层的地图将精确分配5层,一张有50层的地图将分配50层,等等,直到达到ms_max_层的硬编码限制。对于类和样式也是如此。

指针数组之所以总是分配给ms-max-u层的大小,是有明显的原因的,但是内存使用量却减少了,因为指针数组比结构数组小得多。这代表了与以前相比的一个重大变化,即当MS_Max_在空白层中始终分配空白层时,会在小地图中造成一定的内存浪费。

MS RFC 17:层、样式、类和符号的动态分配 should then invoke the various msGrow*() methods to grow the arrays when numlayers == maxlayers-1. I'd suggest to grow the array to a sensible size (like half of the current size) as the impact on memory allocation is going to be mitigated by the dynamic allocation approach introduced by MS RFC 24:MapScript内存管理

MS RFC 24:MapScript内存管理 没有正式要求使用适当的插入方法,因为那些方法和对象构造函数是 only 向地图添加图层、类或样式的方法。我不知道符号是否也是这样。

  • 因为mapscript应用程序通常直接显式初始化“空白”层、类和样式,然后增加计数,所以我们不能依赖于通过适当的插入/添加方法进行的所有访问。因此,我们保留旧的ms_max值以建立初始分配。这意味着现有的应用程序将在未使用的内存中以某种代价继续工作。但是,使用insert方法增加大小的行为良好的mapscript应用程序将能够超出初始分配范围。”

我不知道任何绕过插入或构造函数的mapscript方法(即直接操作数组)。有这样的方法(我对此表示怀疑),我建议我们通过显式地更改ms_max_x名称并使必需字段在swig中不可变来禁止它。

  • Tamas的评论:mappluginlayer的东西应该具体化一点。vtables的静态存储库将阻止加载同一个库两次。该数组也应该动态分配,因为我认为我们不会有不同插件层的ms-maxlayers数量。