TDR表

TDR表是指通过TDR协议定义和访问的数据表。

除TDR表之外,TcaplusDB同时还提供了PB(Protobuf)表(通过PB协议定义和访问的数据表)。

PB表与TDR表并无本质区别,用户可以根据自己对PB或TDR的熟悉程度,来决定使用PB表还是TDR表。需要注意的是当前TcaplusDB的PB表和TDR表支持的功能范围有些差异,用户在选择使用体种表类型的时候,也需要考虑功能是否能满足业务需求。

1. 关于TDR

TDR(Tencent Data Representation)是腾讯推出的,进行游戏开发的基础组件,所有的组件都是基于TDR进行开发。DR数据表示组件以程序库、TDR工具的形式发布。TDR-API本质是相当于一套独立于数据结构的算法,常用API的功能涉及网络编解码、XML数据输入输出、数据可视化、对象关系映射、数据排序。TDR工具实现各种元数据格式之间的转换,并且可以根据XML格式的元数据描述生成C/C++数据结构定义头文件。TDR工具还能够生成实现指定功能的代码,目前支持生成C++\AS3\C#三种语言的代码,支持的功能包括网络编解码、XML数据输入输出、数据可视化。

TDR使用XML来描述定义协议文件,可用TDR工具转换成对应的头文件和cpp文件。生成结构体,cmdID的定义和对应的打解包函数。生成之后的结构体和函数可以直接在程序中应用。Tdr支持生成C++\AS3\C#语言。因为游戏存在运营过程中动态更新,在实际的游戏协议应用中,最关注的是协议的兼容性问题,包括CS协议和SS协议的兼容性。Tdr通过版本号来进行协议兼容性的处理,新加字段需要增加对应的版本号,和整个TDR的版本号。Tdr打包的时候会打上对应的最大版本号和字段版本号。打包可以根据对方的版本号进行打包,解包的时候根据数据的版本号进行解包。支持高版本对低版本的兼容。

  <struct name="users" version="1" primarykey="user_id,username,role_id" splittablekey="user_id" desc="user table">
    <entry name="user_id" type="uint64" desc="user id"/>
    <entry name="username" type="string" size="64" desc="login username"/>
    <entry name="role_id" type="int32" desc="a user can have multiple roles"/>

    <entry name="level" type="int32" defaultvalue="1" desc="role's level"/>
    <entry name="role_name" type="string" size="1024" desc="role's name" version="100"/>
    <entry name="last_login_time" type="string" size="64" defaultvalue="" desc="user login timestamp" version="101"/>
    <entry name="last_logout_time" type="string" size="64" defaultvalue="" desc="user logout timestamp" version="102"/>

    <index name="index1" column="user_id"/>
  </struct>

例如以上的协议中,后面几个字段都是新增字段,需要严格按照版本号递增,除了修改具体结构中的版本号之外,还需要修改整体的版本号。

<metalib name="tcaplus_tb" tagsetversion="1" version="1">

这样TDR打包的数据中就有了具体的整体版本号信息和字段版本号信息。可以做到高版本兼容低版本,但是低版本无法兼容高版本。在实际的上线版本运营中,新增字段必须严格按照版本号升级,要注意具体新增字段和总版本号的同步更新。同时又存在cs协议和ss协议,所以新增字段的时候修改点比较多,检查版本号的步骤比较繁琐,需要人工保证。

2. TDR表定义文件示例

<?xml version="1.0" encoding="utf-8" standalone="yes" ?>

<metalib name="tcaplus_tb" tagsetversion="1" version="4">

  <struct name="TestInfo" version="1" desc="" >
        <entry name="d"          type="uint64" />  
        <entry name="test"       type="uint64" />  
  </struct>

  <struct name="TableInfo" version="1" desc="" >
        <entry name="c"              type="TestInfo" />  
        <entry name="test"          type="uint64" />  
        <entry name="string_array"     type="string"  size="100" />
        <entry name="binary"           type="tinyint" />
  </struct>

  <struct name="simple_struct" version="4">
        <entry name="c_int8" type="int8" defaultvalue="-1"/>
        <entry name="c_uint8" type="uint8" defaultvalue="2"/>
        <entry name="c_int16" type="int16" defaultvalue="-3"/>
        <entry name="c_uint16" type="uint16" defaultvalue="4"/>
        <entry name="c_int32" type="int32" defaultvalue="-5"/>
        <entry name="c_uint32" type="uint32" defaultvalue="6"/>
        <entry name="c_int64" type="int64" defaultvalue="-7"/>
        <entry name="c_uint64" type="uint64" defaultvalue="8"/>
  </struct>

  <union name="union_type" version="1">
        <entry name="Id"          type="int32"  id="0" defaultvalue="0"     desc="id" />
        <entry name="Name"      type="string"  id="1" size="64" defaultvalue="hello" desc="name" />
  </union>

  <struct name="struct_type" version="1">
        <entry name="x"         type="int32"  defaultvalue="0"     desc="x" />
        <entry name="y"            type="int32"  defaultvalue="0"    desc="y" />
        <entry name="score"          type="double" defaultvalue="1.11" version="2" />  
        <entry name="rank"          type="uint8" defaultvalue="1" version="3" />  
        <entry name="title"          type="string" size="48" desc="title" />  
        <entry name="level2_struct" type="struct_nested" version="2" />
  </struct>

  <struct name="table_list" version="1"  primarykey="uin,name,key1" splittablekey="uin"  customattr2="TableType=LIST;ListNum=100;DataProtocolType=PLAIN">
        <entry name="uin" type="uint64" desc="QQ"/>
        <entry name="name" type="string" size="255" desc="Name"/>
        <entry name="key1" type="uint8" desc="key4"/>
        <entry name="level"    type="int32"   defaultvalue="1" />
       <entry name="count"    type="uint8"   defaultvalue="0" />
        <entry name="array_count"  type="uint32"  defaultvalue="1" /> 
        <entry name="items"    type="uint64" count="10" refer="array_count"/>
        <entry name="c_int8" type="int8" defaultvalue="-1"/>
        <entry name="c_uint8" type="uint8" defaultvalue="2"/>
        <entry name="c_int16" type="int16" defaultvalue="-3"/>
        <entry name="c_uint16" type="uint16" defaultvalue="4"/>
        <entry name="c_int32" type="int32" defaultvalue="-5"/>
        <entry name="c_uint32" type="uint32" defaultvalue="6"/>
        <entry name="c_int64" type="int64" defaultvalue="-7"/>
        <entry name="c_uint64" type="uint64"/>
        <entry name="c_float" type="float" defaultvalue="1.23456789" version="2"/>
        <entry name="c_double" type="double" defaultvalue="9.87654321" version="3" />
        <entry name="c_string" type="string" size="200" version="3" />
        <entry name="c_string_128K" type="string" size="VALUE_128KB_SIZE" defaultvalue="123456789"/>
        <entry name="c_string_256K" type="string" size="VALUE_256KB_SIZE" defaultvalue="123456789"/>
        <entry name="c_binary" type="tinyint"  count="10" refer="array_count" />
        <entry name="binary" type="tinyint"  version="5"/>
        <entry name="selector" type="short" />
        <entry name="single_struct" type="struct_type"/>
        <entry name="simple_struct" type="simple_struct" version="4"/>
        <entry name="single_union_selector" type="int8" defaultvalue="0" />
        <entry name="single_union" type="union_type" select="single_union_selector" />
        <entry name="array"        type="TableInfo" count="3" refer="array_count"/>
        <entry name="c_union"  type="union_type" select="selector"/>
        <entry name="union_array" type="union_type"  count="3" select="selector" refer="array_count"/>
        <entry name="c_struct" type="struct_type"/>
        <entry name="struct_array" type="struct_type"  count="3" refer="array_count"/>        
        <index name="index1" column="uin"/>
        <index name="index2" column="uin,name"/>
    </struct>

</metalib>

说明:

  • 元素metalib是xml文件的根元素。

  • 包含属性primarykey的struct元素定义一个表;否则,它只是一个普通的结构体。

  • 每次修改表结构时,版本属性值需要相应地加1,初始版本始终为1。

  • primarykey属性指定主键字段;对于generic表,您最多可以指定8个主键字段,对于list表,则可以指定7个。

  • splittablekey属性等效于分片键(shard key),TcaplusDB表被拆分存储到多个存储节点。 splittablekey必须是主键字段之一,一个好的splittablekey应该具有高度分散性,这意味着值的范围很广。

  • desc属性包含当前元素的描述。

  • entry元素定义一个字段。支持的值类型包括int32,string,char,int64,double,short等。

  • index元素定义一个索引,该索引必须包含splittablekey。由于可以使用主键查询表,因此索引不应与主键属性相同。

另外,您可以使用union创建嵌套类型。

  • union元素包含原始类型的集合,例如整数和字符串,可以将Union也可以作为自定义类型来引用。

  • Macro标签用于定义常量。

<union name="union_type" version="1">
        <entry name="Id"          type="int32"  id="0" defaultvalue="0"     desc="id" />
        <entry name="Name"      type="string"  id="1" size="64" defaultvalue="hello" desc="name" />
</union>
  • customattr2:

    TableType:用于指定表格类型,如list或者sortlist,若不指定类型默认为generic表,且generic表无需添加customattr2属性,关于表格类型的说明请见 Generic表和List表

    ListNum:用于定义list或者sortlist表中,单个key最多可以指向多少个value值,若超过该值可指定从头部或尾部删除老元素。

    SortFieldNum:用于sortlist表中,表示该表有多少个排序字段,每个排序字段需要用customattr2标识,如第一个为“sort1”,第二个“sort2”。

    SortRule:用于sortlist表中,表示该表的排序方式,如DESC表示降序,INSC升序。如果有多个排序字段,按照sort的序号进行排序,序号小的字段优先级更高。比如排序是降序:sort1不同时按sort1降序;sort1相同时按sort2降序,以此类推。

<struct name="following_action_list" version="1" primarykey="game,myuin",  customattr2="TableType=SORTLIST;ListNum=1023;SortFieldNum=1;SortRule=DESC">
   <entry name="TimeStamp"      type="uint32"   desc="单位为分钟" />
   <entry name="time"           type="uint32"   customattr2="sort1"  desc="时间"/>
</struct>

下文会对示例中提到的相关属性进行详细描述。

3. TDR表定义文件说明

3.1. 文件结构

3.1.1. XML文件头

标准的XML文件头如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>

前期为了减少字符编码问题带来的影响,先使用GBK作为字符编码。长期来讲,应使用UTF-8作为字符编码,以支持多语言和可移植性。

目前暂时先使用:

<?xml version="1.0" encoding="GBK" standalone="yes" ?>

3.1.2. metalib

一个XML文件只能有一个根元素(Root Element)。对于元数据描述用途的文档,根元素是metalib。表明该XML文件的内容是一个元数据描述集合。

3.2. 属性说明

3.2.1. TcaplusDB相关属性

3.2.1.1. primarykey(主键)

primarykey属性指明此元素对应数据库表的主键,其取值为以当前元素为父元素的特定子元数据成员名串,如果有多个成员组成表的主键,则成员名之间用逗号(',')隔开。

约束:

  1. 作为主键的成员不能为复合数据类型,只能是基本内置数据类型。

  2. 作为主键的成员其取值不能为NULL。

<struct name="GameItem" primarykey="gameid,itemid">
    <entry name="gameid" type="uint" />
    <entry name="itemid" type="uint" />
    <entry name="buytime" type="datetime" />
    <entry name="validtime" type="datetime" />
</struct>

根据上面的描述,GameItem的数据表使用gameid和itemid两个成员作为主键。

3.2.1.2. splittablekey(分表因子/分表属性)

splittablekey属性指明计算当前结构与具体数据表映射关系的数据源,其取值为以当前元素为父元素的特定子元数据成员,支持多个key字段组合成为splittablekey。

约束:

作为此成员不能为复合数据类型,只能是基本内置数据类型(void类型除外)。

<struct name="GameItem" primarykey="gameid,itemid" splittablekey="gameid">
    <entry name="gameid" type="uint" />
    <entry name="itemid" type="uint" />
    <entry name="buytime" type="datetime" />
    <entry name="validtime" type="datetime" />
</struct>
3.2.1.3. index(本地索引

基于TcaplusDB主键字段建立的索引,在建表时随表一起建立,并且一旦表创建后,就不能再增加、修改和删除本地索引了,删除表的时候,本地索引会一并删除。

  • 本地索引是实时索引,当插入或者删除数据时,会同时更新索引数据。

  • 本地索引的字段必须包含在主键字段中,并且字段中还必须包含分表因子,因此,查询时最终只会落到一个数据分片上进行查询。

  • 本地索引只支持等值查询。

  • 一个表可以建立多个本地索引,查询时必须包含某一个本地索引的全部字段。

  • 目前只有Generic表支持本地索引。

<struct name="PLAYERONLINECNT" version="1" primarykey="TimeStamp,GameSvrID,GameAppID" splittablekey="TimeStamp">
    <entry name="TimeStamp"           type="uint32"     desc="单位为分钟" />
    <entry name="GameSvrID"         type="string"     size="64" />
    <entry name="GameAppID"         type="string"     size="64" desc="gameapp id" />
    <index name="index_1"  column="TimeStamp"/>
    <index name="index_2"  column="TimeStamp, GameSvrID"/>
    <index name="index_3"  column="TimeStamp, GameAppID"/>
</struct>

如上文所示,index的name不可以重复,且不同的index必须拥有不同的column。

3.2.2. 通用属性

这里的通用属性是指除了根元素外,所有的非根元素都可以具有的属性。对于那些不通用的属性,在描述相关的元素的时候统一进行描述。但是对于include元素,通用属性中只有name属性才有意义。

3.2.2.1. id

id属性表明了该元素的唯一标识,在DR提供的API中可以利用此id来查找、定位特定的元素。

id的取值可以是一个字面量的数字,也可以是一个Macro的名字(对于非Macro类型的元素)。

约束:

  1. 同一父元素下的所有子元素的id属性值不能重复。

  2. metalib元素的id属性只能是一个字面量的数字,不可以是Macro名字。

  3. struc/union元素的id属性值只能是0或者正整数。

3.2.2.2. name

name属性提供该元素的字符类型标识。在DR提供的API中可以利用此Name来查找、定位特定的元素。

约束:

  1. 同一父元素下的所有子元素的Name属性的值除后面描述的特例外是不可重复的。

  2. name属性的属性值区分大小写,即name="net"与name="NET"认为是不同的属性值。

  3. 元数据描述的所有元素必须包含name属性。

3.2.2.3. cname

cname属性提供该元素的中文标识名。通过提供有意义的中文名,可以对元素的意义有更好的理解。(目前已知的应用领域是从Excel表中读取数据生成所需的内存结构)。

3.2.2.4. version

版本属性指明了该元素被引入时该元数据描述库的版本号。该版本号在打包、解包的时候提供裁减的依据。version的取值可以是一个字面量的数字,也可以是一个Macro的名字(对于非Macro类型的元素)。

约束:

  1. metalib,struct,union元素必须包含version属性。

  2. 对于struct和union元素,其version属性指明其基准版本号,即该版本号表明该元素加入到metalib时的库版本号。

metalib,struct,union,entry元素的version属性的约束:

  1. metalib元素必须指定version属性,此属性指明该元数据描述库的当前版本,称为库版本。库版本号的变化反映了整个元数据描述库的变化情况,只要库发生了变化,库版本号就必须同步保持变化。库版本号永远只能增加,不能减少。

  2. 每个struct和union元数据都必须包含version属性,此属性表明该Meta创建时的库版本号,称为元数据基准版本号(MetaBaseVersion),一旦表创建后不能更改。

  3. 每个元数据成员有自己的当前版本号,该版本号表明该MetaMember被添加时的库版本号,即该版本号表明了该元数据成员是在那个库版本中被引入的。当一个MetaMember没有定义其版本号时,缺省继承它所在的元数据的基准版本号。

  4. 一个元数据(Meta)的当前版本号,此版本号为其成员中当前版本号的最大值。

3.2.2.5. desc

描述信息。对该元素的一些简要描述,表明该元素的用途、意义等等。

3.2.3. metalib元素

metalib元素只能包含如下子元素:include, macro, macrosgroup, struct, union。

metalib元素除可以包含以上描述的id,name,version属性外,还可以包含以下属性:tagsetversion。

3.2.3.1. name

只有name属性值相同的XML描述文件才能放在一起生成元数据描述库,除非其name属性为空串。metalib的name属性类似于名字空间。

3.2.3.2. tagsetversion

此属性指明元数据描述使用的XML标签集的版本信息,通过此属性处理程序可以兼容使用不同版本元数据标签集定义的XML描述文件。

此属性的值为无符号整数,并且必须是递增的,每调整一次元数据描述XML标签集定义,必须使用新的版本号。

如果XML文件中,metaLib元素中没有包含此属性,则处理程序缺省按DR API支持的最新版本的标签定义进行解析。

约束:

本文档中元数据描述XML标签集tagsetversion值定义为1,即使用本文档中定义的标签生成的XML描述文件,其metaLib元素的tagsetversion属性值为1。

3.2.3.3. include元素

include元素必须是metalib元素的子元素。

include元素用于指示XML文件间的依赖关系。Include元素只需要定义file属性,但是建议定义name(通用)属性。定义全局唯一的name属性,有助于在TDR进行include元素规范性检测时,对不规范的地方提供详细的定位信息。在严格意义上,include不属于元数据库,include元素不影响元数据库的hash值,不受版本的约束,TDR不对include节点的name属性做唯一性检查。

当使用TDR的xml2h功能时,include元素被转换为头文件中的#include宏定义,file属性值对应的文件路径名中的xml后缀被直接替换为h。

例如,XML文件中的include元素

<include name="head" file="./head.xml">

对应头文件中的如下宏定义:

#include "./head.h"

当使用TDR的cplusplus功能时,include元素被转换为头文件中的#include宏定义,file属性值对应的文件路径名中的xml后缀被直接替换为h,并删除了路径中的目录信息。之所以删除路径中的目录信息,是因为对于cplusplus功能,TDR把所有的文件都生成在相同的目录中。

例如,XML文件中的include元素

<include name="head" file="../comm.xml">

对应头文件中的如下宏定义:

#include "comm.h"

对于XML文件中出现的多个include元素,TDR依次处理这些include元素。

3.2.3.4. file

file属性用于指明当前XML文件依赖的其他XML文件。如果XML文件中include元素的file属性值是当前XML文件路径本身或为””,则此include元素不起作用。

约束:

file属性的值(XML文件路径)指定的文件必须出现在(启动TDR工具时的)命令行指定的XML文件列表中。

3.2.4. macro元素

macro元素可以是metalib元素的子元素,也可以是macrosgoup元素的子元素。macro元素与C语言中的宏的意义类似,在实际的处理中也是映射到C语言的宏。Macro元素相对简单,只需要有name(通用)属性和value属性就可以了。

3.2.4.1. value

value属性用于指明该macro代表的值是多少(相比与C语言中宏的概念,name属性的值是宏的名字,value属性的值是宏的内容)。其取值可以是一个字面量的数字,也可以是一个之前已定义的Macro的名字。

约束:

目前value属性值是通过int数据类型来存储的,因此只能处理int数据类型值域范围里的数据。

3.2.5. macrosgroup元素

macrosgroup元素用于对macro元素进行分类,每一类macro元素组成一个宏定义组。Macrosgroup只需包含name和desc属性就可以了。

macrosgroup元素的子元素为macro元素,当然macro元素也可以不属于任何宏定义组。

约束:

  1. macrosgroup元素必须指定name属性。

  2. macrosgroup的macro子元素的value属性值必须唯一,即value属性值相同的macro元素不能放入同一个macrosgroup元素下。

<macro name="MAX_BODY_LEN" value="32000" />
<macrosgroup name=”MsgID” desc=”id of net message” >
    <macro name="CMD_LOGIN" value="0" />
    <macro name="CMD_LOGOUT" value="1" />
</macrosgroup >

3.2.6. struct元素

struct元素必须是metalib元素的子元素,在tcaplus中一张表对应一个struct。

struct元素是DR中最复杂的元素,与C语言的struct概念类似。

3.2.6.1. size

size属性指明该struct的内存占用大小。如果不指明size属性,那么该struct的大小会通过计算成员的大小后自动得出该struct的大小。但是通过指定size属性,可以让该struct预占多一些空间,size属性指定的大小不能比自动计算出来的大小更小。entry中的string类型字段必须定义size属性大小

3.2.6.2. align

align属性对应于编译器的#pragma pack指令。利用align属性可以指定该struct内部所有成员的对齐大小。如果不指定align属性,缺省对齐大小为1。指定align属性会影响到该结构体的大小、每个成员的偏移。

3.2.6.3. customattr2

customattr2属性用于定义表格的属性,包括:

  1. TableType:用于指定表格类型,如list或者sortlist,若不指定类型默认为generic表,且generic表无需添加customattr2属性,关于表格类型的说明请见 Generic表和List表

  2. ListNum:用于定义list或者sortlist表中,单个key最多可以指向多少个value值,若超过该值可指定从头部或尾部删除老元素。

  3. SortFieldNum:用于sortlist表中,表示该表有多少个排序字段,每个排序字段需要用customattr2标识,如第一个为“sort1”,第二个“sort2”。

  4. SortRule:用于sortlist表中,表示该表的排序方式,如DESC表示降序,INSC升序。如果有多个排序字段,按照sort的序号进行排序,序号小的字段优先级更高。比如排序是降序:sort1不同时按sort1降序;sort1相同时按sort2降序,以此类推。

<struct name="table_Sortlist_single" primarykey="key, name" customattr2="TableType=SORTLIST;ListNum=1023;SortFieldNum=1;SortRule=DESC" version="5" desc="用于list表遍历测试, 需要4个shard, 建表list最大1023个元素" >
    ...
</struct>
3.2.6.4. entry子元素

entry对应的是元数据成员的概念,下面描述了entry元素可以包含的属性。

3.2.6.4.1. type

指明entry数据成员的数据类型;其取值为可以为基本内置数据类型,也可以为自定义的复合数据类型,在DR API中对type属性值不区分大小写。

约束:

自定义复合类型不支持后向引用。

<struct name="type1">
</struct>
<struct name="type2">
    <entry name="item1" type="int" />
    <entry name="item2" type="float" />
    <entry name="item3" type="type1" />
</struct>

目前对于C/C++/c#语言,支持的基本数据类型如下表所示:

类型名 分类 存储长度(字节) 取值范围
byte 字节 1
char 单字节字符 1
tinyint 整数 1 -128~127
tinyuint 整数 1 0~255
smallint 整数 2 -32768~32767
smalluint 整数 2 0~65535
int 整数 4 -231~231-1
uint 整数 4 0~232-1
bigint 整数 8 -263~263-1
biguint 整数 8 0~264-1
float 浮点 4
double 浮点 8
date 日期 4 -9999-00-00 ~9999-12-31
time 时间 4 -999:00:00~999:59:59
dateTime 日期/时间 8 0000-00-00 00:00:00~9999-12-31 23:59:59
string 字符串 可变
wchar 宽字符 2
wstring 宽字符集
ip Ipv4地址 4 0.0.0.0~255:255:255:255
void 空类型
int8 整数 1 -128~127
uint8 整数 1 0~255
int16 整数 2 -32768~32767
uint16 整数 2 0~65535
int32 整数 4 -231~231-1
uint32 整数 4 0~232 -1
int64 整数 8 -263~263-1
uint64 整数 8 0~264-1
  • date

表示日期数据类型,c/c++支持的范围是-9999-00-00 到9999-12-31, c#支持的范围是0001-01-01到9999-12-31。DR的API采用4字节整数对date数据进行存储,实际存储格式是自定义的;但以"YYYY-MM-DD"格式对date数据类型进行显示,输入和输出; DR提供了存储格式和显示格式相互转换的API接口。

  • time

表示时间数据类型,c/c++支持的范围是-999:00:00 到999:59:59, c#支持的范围是00:00:00到23:59:59。DR的API采用4字节整数对time数据进行存储,实际存储格式是自定义的;但以"HHH:MM:SS"格式对time数据类型进行显示,输入和输出; DR提供了存储格式和显示格式相互转换的API接口。

  • datetime

表示日期时间组合数据类型,c/c++支持的范围是-9999-00-00 00:00:00~9999-12-31 23:59:59 ,c#支持的范围是0001-01-01 00:00:00 ~9999-12-31 23:59:59。DR的API采用8字节长整数对datetime数据进行存储,实际存储格式是自定义的;但以"YYYY-MM-DD HH:MM:SS"格式对time数据类型进行显示,输入和输出; DR提供了存储格式和显示格式相互转换的API接口。

  • ip

基本数据类型Ip表示IPV4地址,以"数字."格式的字符串作为输入和显示,此自符串的具体格式如为:a.b.c.d,其中a,b,c,d为值为0-255之间的数字,这个数字可以采用8,10,16进制进行表示。

ipv4地址串 描述
"4.3.2.16" 十进制表示
"004.003.002.020" 8进制表示
"0x4.0x3.0x2.0x10" 16进制表示
"4.003.002.0x10" 各种进制混合
  • void

TDR引入void数据类型的主要目的是为支持通用指针,即void类型必须和指针类型一起使用才有效。

3.2.6.4.2. size

size属性指明该元素的内存占用大小。如果不指明size属性,那么该元素的大小会通过计算成员的大小后自动得出该元素的大小。但是通过指定size属性,可以让该元素预占多一些空间,size属性指定的大小不能比自动计算出来的大小更小。

其取值为正整数或合法的宏定义。

约束:

  1. 对于自定义类型(union/struct)元素,entry本身设置的size属性将忽略,将以union/struct元素中定义的size属性为准。

  2. 对于内置数据类型,目前只有string,wstring类型支持size属性,其他内置数据类型不支持size属性。

<struct name="type1" >
    <entry name="name" type="string" size="32" />
    <entry name="pass" type="string" size="32" />    
</struct>
3.2.6.4.3. count

count属性指明了当前元数据成员的个数(数组大小)。count可以是字面量的数字,也可以是一个Macro。

count属性如果不指定,缺省值为"1",否则取值必须范围为:>=1的整数,此时必须使用refer属性来指明可以用于确定数组大小的元数据成员。

<macro name="MAX_COUNT" value="100" />

<struct name="type1">
    <entry name="item1" type="int" count="10" />
    <entry name="item2" type="float" count="MAX_COUNT" />
    <entry name="is_exist" type="int" />
    <entry name="item3" type="int" refer="is_exist" />
    <entry name="total" type="int" />
    <entry name="item4" type="int" count="10" refer="total" />
</struct>

注意,一级字段string类型不需要定义count和refer属性,如果要定义可以改成struct嵌套进去,例如:

   <macro name="MAX_TEX_ID_LENGTH" value="35" />
   <macro name="MAX_TEX_IDS_COUNT" value="150" />
   <struct name="Cube1150" version="1" primarykey="FUin" splittablekey="FUin" >
          <entry name="TxnIds" type="TxnIdWrapper" count="MAX_TEX_IDS_COUNT" version="2"  refer="TxnIdsCount" />
   </struct>
   <struct name="TxnIdWrapper" version="2" >
       <entry name="TxnId" type="string" size="MAX_TEX_ID_LENGTH" />
   </struct>
3.2.6.4.4. refer

refer属性通常指向该元数据结构中的另一个元数据成员。

当前元数据成员是数组时,refer属性指向的元素的值指明了该数据成员的实际大小。

当前元数据成员是单一元素时,refer属性指向的元素的值指明了该数据成员是否在实际数据中存在(用于处理Option的数据)。

取值为:该元素的直接父元素包含的特定子元素(不支持后向引用,值元素必须在当前元素之前)。

<struct name="type1">
    <entry name="item1" type="int" />
    <entry name="item2" type="float" count="10" refer="item1" />
</struct>

扩展情况:有时候还需要引用跟当前元素不在同一层次的子元素,此时使用类似Path.Target的形式来指定。

<struct name="type1">
    <entry name="item1" type="int" />
    <entry name="item2" type="int" />
</struct>

<struct name="type2">
    <entry name="head" type="type1" />
    <entry name="item4" type="float" count="10" refer="head.item1" />
</struct>

约束:

  1. refer属性所指元素的值必须小于等于此元素的count属性的值,以上例为例head.item1的值必须不大于10;当元素是单一元素时,count属性取默认值1,这时refer属性所指元素的值只能为1或0,取值为1时表示比元素存在,取值为0时表示此元素不存在。

  2. 此元素的refer属性所指元素,不能同时被其它元素或父元素指定为sizeinfo或versionindicator属性。

3.2.6.4.5. defaultvalue

defaultvalue属性指明了如何对该元数据成员的值在没有显式定义时该怎么取值。

取值:合法的字符串,同时该串的内容应该跟该元数据成员的类型匹配。

如果不指定defaultvalue属性,则缺省值为0(同时对于数组不作填充处理)。

约束:

目前支持对内置数据类型设定缺省值,对于自定义复杂数据类型不支持设置缺省值。

<struct name="type1">
    <entry name="item1" type="int" count="100" defaultvalue="100" />
    <entry name="item2" type="date" defaultvalue="2009-11-03" />
    <entry name="item3" type="int"/>
</struct>
3.2.6.4.6. select

select属性和refer属性类似,通常指向该元数据结构中的另一个元数据成员。

select属性指明了如何选择union中数据成员的方法。通常是使用select属性指向的元素的值来决定union中到底使用哪个数据成员。

取值为:该元素的直接父元素包含的特定子元素(不支持后向引用,值元素必须在当前元素之前)。

<union name="type1">
    <entry name="item1" type="int" id="1" />
    <entry name="item2" type="int" id="2" />
</union>

<struct name="type2">
    <entry name="selector" type="short" />
    <entry name="item3" type="type1" select="selector" />
</struct>
3.2.6.4.7. customattr2

customattr2属性用于表示字段是否属于排序字段,比如排序是降序:sort1不同时按sort1降序;sort1相同时按sort2降序,以此类推。

<struct name="table_Sortlist_single" primarykey="key, name" customattr2="TableType=SORTLIST;ListNum=1023;SortFieldNum=1;SortRule=DESC" version="5" desc="用于list表遍历测试, 需要4个shard, 建表list最大1023个元素" >
    <entry name="key"      type="uint32"   desc="单个uint32作为KEY的时候, hashcode = key % 10000"/>
    <entry name="name"     type="int16" />
    <entry name="type_int16" type="int16" desc="type_int16" customattr2="sort1"/>
    <entry name="type_int64" type="int64" desc="type_int64" customattr2="sort2"/>
</struct>

3.2.7. Union元素

union元素必须是metalib元素的子元素。

union元素与C语言中的union类似。在定义上,union元素和struct元素基本相同。union元素与struct元素的区别与C语言中union和struct的区别相同。

3.2.7.1. entry子元素

和struct元素一样,entry对应的也是元数据成员的概念。union中的entry子元素除了可以拥有struct中的entry子元素一样的属性外,还可以拥有另外两个额外的属性。

约束:

union中不能再包含有union类型的元数据成员。

3.2.7.1.1 minid & maxid

通常使用ID属性来作为确定union中到底选择那个元数据成员的依据。但是在实际应用中,可能需要使用一个范围来对应一个元数据成员,这时候使用minid和maxid属性来表示。

当使用minid和maxid时,表示的意义是区间:[minid, maxid]。

当使用ID时,表示的意义是区间:[ID, ID]。

union类型的数据结构的子元素可以没有ID,此时表示该子元素是缺省的元素。当其他子元素都无法匹配的时候,该子元素匹配选择。

为了支持多重取值范围的情况,对于union类型的元数据结构的子元素的名字可以重复,但是这些同名的子元素的类型必需完全一致(对于这种情况,在编译的时候需要给出一些Info类型的提示)。

约束:

  1. union元素的子元素,有且仅有一个可以没有ID属性。

  2. maxid,minid属性必须同时出现。

  3. 如果同时出现了maxid,minid,id属性,则在union结构中选择成员时,以maxid和minid两个属性为准。

  4. ID不能为负数,多个entry的ID也不能交叉

<union name="type1">
    <entry name="example" type="int" minid="1" maxid="100" />
    <entry name="example" type="int" id="108" />
    <entry name="example" type="int" minid="200" maxid="300" />
    <entry name="item2" type="int" id="2" />
</union>

则example子元素对应的选择器的取值范围可以是:{[1,100],[108,108],[200,300],[-99,-99]}。

4. TDR表修改说明

表元数据信息变更约束条件具体如下:

XML/TDR文件

(1)一个表内不允许有重复的字段名。要求Key字段名无重名,Value字段名无重名,Value字段名和Key字段名无重名。

(2)TDR meta定义中primarykey的值(即Key字段名)必须属于存在的字段名,splittablekey的值必须属于存在的primarykey的值(即Key字段名)。注意:primarykey定义的就是Key字段。

(3)不允许删除Key字段,不允许添加Key字段,不允许更改Key字段类型。Key字段长度不允许改变。不允许给Key字段配置默认值。

(4)允许添加Value字段,允许更改Value字段默认值,不允许删除Value字段,不允许更改Value字段类型,Value字段最大长度允许加长不允许缩短,允许更改Value字段默认值但默认值实际长度不能超过该Value字段的最大长度。

(5)Index字段必须属于存在的Key字段名,Index字段中必须包含splittablekey所指定的字段,并且Index字段必须全部属于primarykey。

(6)Index字段中不允许有重复的字段名,Index字段的column属性长度不能超过120个字节

(7)List类型表不允许配置Index字段。

(8)List类型表的LIST最多元素个数允许被改大不允许被改小,同时List类型表的LIST最多元素个数不能超过10000个。

(9)Index的数量及Index所包括的字段名均不允许变更。

(10)修改“LIST最多元素个数”需要表所在的tcapsvrs版本均高于3.13.0.115217。

(11)现有的TDR限制: Key字段名不允许变更、Value字段名不允许变更。

(12)如果新增字段定义了count没定义refer的字段,不影响变更表,但之后不允许对count做修改,不允许通过变更; count和size属性一旦定义,表变更时只能改大不能改小,不需要修改版本号。

(13)tcaplus表的entry字段个数上限是256个, 到达110个的时候会有warning提示, list类型表value个数上限需减1

5. TDR表修改示例

原始结构:

<?xml version="1.0" encoding="GBK" standalone="yes" ?>

<metalib name="tcaplus_tb" tagsetversion="1" version="1">
  <struct name="PLAYERONLINECNT" version="1" primarykey="TimeKey,GameSvrID" splittablekey="TimeKey">
    <entry name="TimeKey"           type="uint32"     desc="time min" />
    <entry name="GameSvrID"         type="string"     size="32" />
    <entry name="GameAppID"         type="string"     size="64" desc="game app id" />
    <entry name="OnlineCntIOS"      type="uint32"     defaultvalue="0" desc="ios online" />
    <entry name="OnlineCntAndroid"  type="uint32"     defaultvalue="0" desc="android online" />
    <entry name="array_count"       type="uint32"     defaultvalue="1" /> 
        <entry name="items"             type="uint64"     count="10" refer="array_count"/>
    <entry name="strstr"            type="string"     size="4096" desc="string" />
    <entry name="strstr1"            type="string"     size="4096" desc="string" />
    <index name="index1" column="TimeKey"/>
    <index name="index2" column="TimeKey,GameSvrID"/>
  </struct>   
</metalib>

5.1. 示例1:增加struct内的字段的情况

  1. metalib的版本号加一。

  2. 新增字段strstr2的版本号为新metalib的版本号。

<?xml version="1.0" encoding="GBK" standalone="yes" ?>

<metalib name="tcaplus_tb" tagsetversion="1" version="2">
  <struct name="PLAYERONLINECNT" primarykey="TimeKey,GameSvrID" splittablekey="TimeKey" version="1">
    <entry name="TimeKey"           type="uint32"     desc="time min" />
    <entry name="GameSvrID"         type="string"     size="32" />
    <entry name="GameAppID"         type="string"     size="64" desc="game app id" />
    <entry name="OnlineCntIOS"      type="uint32"     defaultvalue="0" desc="ios online" />
    <entry name="OnlineCntAndroid"  type="uint32"     defaultvalue="0" desc="android online" />
    <entry name="array_count"       type="uint32"     defaultvalue="1" /> 
        <entry name="items"             type="uint64"      count="10" refer="array_count"/>
    <entry name="strstr"            type="string"     size="4096" desc="string" />
    <entry name="strstr1"            type="string"     size="4096" desc="string" />
    <entry name="strstr2"            type="string"     size="4096" desc="string" version="2"/>
    <index name="index1" column="TimeKey"/>
    <index name="index2" column="TimeKey,GameSvrID"/>
  </struct>   
</metalib>

注意:结构体内增加字段的情况

  1. metalib的版本号加一。

  2. 结构体TestInfo内新增字段testadd的版本号为新metalib的版本号。

原XML:

<?xml version="1.0" encoding="GBK" standalone="yes" ?>
<metalib name="tcaplus_tb" tagsetversion="1" version="3">

  <struct name="TestInfo" version="3" desc="" >
        <entry name="d"          type="uint64" />  
        <entry name="test"       type="uint64" /> 
  </struct>

  <struct name="PLAYERONLINECNT222" primarykey="TimeKey,GameSvrID" splittablekey="TimeKey" version="1">
    <entry name="TimeKey"           type="uint32"     desc="time min" />
    <entry name="GameSvrID"         type="string"     size="32" />
    <entry name="strstr1"            type="string"     size="4096" desc="string" />
    <entry name="tableinfo"         type="TestInfo"    desc="table info"        version="3"/>
  </struct>   
  </metalib>

新XML:

<?xml version="1.0" encoding="GBK" standalone="yes" ?>
<metalib name="tcaplus_tb" tagsetversion="1" version="4">

  <struct name="TestInfo" version="3" desc="" >
        <entry name="d"          type="uint64" />  
        <entry name="test"       type="uint64" /> 
        <entry name="testadd"       type="uint64" version="4"/> 
  </struct>

  <struct name="PLAYERONLINECNT222" primarykey="TimeKey,GameSvrID" splittablekey="TimeKey" version="1">
    <entry name="TimeKey"           type="uint32"     desc="time min" />
    <entry name="GameSvrID"         type="string"     size="32" />
    <entry name="strstr1"            type="string"     size="4096" desc="string" />
    <entry name="tableinfo"         type="TestInfo"    desc="table info"        version="3"/>
  </struct>   
  </metalib>

5.2. 示例2:增加一个新struct的情况

  1. metalib的版本号加一。

  2. 新增结构体TestInfo的版本号为新metalib版本号。

  3. 新增字段tableinfo的版本号为新metalib版本号。

<?xml version="1.0" encoding="GBK" standalone="yes" ?>

<metalib name="tcaplus_tb" tagsetversion="1" version="3">

  <struct name="TestInfo" version="3" desc="" >
        <entry name="d"          type="uint64" />  
        <entry name="test"       type="uint64" />  
  </struct>

  <struct name="PLAYERONLINECNT" primarykey="TimeKey,GameSvrID" splittablekey="TimeKey" version="1">
    <entry name="TimeKey"           type="uint32"     desc="time min" />
    <entry name="GameSvrID"         type="string"     size="32" />
    <entry name="GameAppID"         type="string"     size="64" desc="game app id" />
    <entry name="OnlineCntIOS"      type="uint32"     defaultvalue="0" desc="ios online" />
    <entry name="OnlineCntAndroid"  type="uint32"     defaultvalue="0" desc="android online" />
    <entry name="array_count"       type="uint32"     defaultvalue="1" /> 
        <entry name="items"              type="uint64"     count="10" refer="array_count"/>
    <entry name="strstr"            type="string"     size="4096" desc="string" />
    <entry name="strstr1"            type="string"     size="4096" desc="string" />
    <entry name="strstr2"            type="string"     size="4096" desc="string" version="2"/>
    <entry name="tableinfo"         type="TestInfo"    desc="table info"        version="3"/>
    <index name="index1" column="TimeKey"/>
    <index name="index2" column="TimeKey,GameSvrID"/>
  </struct>   
</metalib>

5.3. 示例3:扩大数组大小的情况(不需要修改版本号)

  1. 被修改字段items的count变成15。

<?xml version="1.0" encoding="GBK" standalone="yes" ?>

<metalib name="tcaplus_tb" tagsetversion="1" version="3">

  <struct name="TestInfo" version="3" desc="" >
        <entry name="d"          type="uint64" />  
        <entry name="test"       type="uint64" />  
  </struct>

  <struct name="PLAYERONLINECNT" primarykey="TimeKey,GameSvrID" splittablekey="TimeKey" version="1">
    <entry name="TimeKey"           type="uint32"     desc="time min" />
    <entry name="GameSvrID"         type="string"     size="32" />
    <entry name="GameAppID"         type="string"     size="64" desc="game app id" />
    <entry name="OnlineCntIOS"      type="uint32"     defaultvalue="0" desc="ios online" />
    <entry name="OnlineCntAndroid"  type="uint32"     defaultvalue="0" desc="android online" />
    <entry name="array_count"       type="uint32"     defaultvalue="1" /> 
        <entry name="items"             type="uint64"     count="15"    refer="array_count" />
    <entry name="strstr"            type="string"     size="4096" desc="string" />
    <entry name="strstr1"            type="string"     size="4096" desc="string" />
    <entry name="strstr2"            type="string"     size="4096" desc="string" version="2"/>
    <entry name="tableinfo"         type="TestInfo"    desc="table info"        version="3"/>
    <index name="index1" column="TimeKey"/>
    <index name="index2" column="TimeKey,GameSvrID"/>
  </struct>   
</metalib>

results matching ""

    No results matching ""