数通平台软件的封装库:对象管理库
数通平台软件中,信息通信区分为即时消息通信和持久型数据传输。即时消息通信库有单播库,多播库;持久型数据传输有单播同步库,多播同步库。
由于单播/多播同步库必须保证传输信息的可靠性、有序性,兼顾传输效率,同时支持传输数据对象的创建、删除与更新操作等,因而实现了对象管理库(OM)满足持久型数据的传输要求。
对象管理库数据结构如下图所示,一个CLASS通常会下挂三条基本链表,分别为创建链、删除链、更新链:
创建链:创建链用于存放OM分配的数据对象。创建链使用双向链表,所有通过OM库新分配的对象都需要插入到创建链的链尾。同时,OM库为其申请一个在CLASS下唯一的对象ID号(oid)。为了保证对象的有序性,申请的oid每次自增1,同时为了防止oid反转,oid用uint64_t定义。
特别需要说明的是,创建链在新插入第一个对象时,需要先申请&插入一个哨兵(sentinel)节点,便于对象的删除操作。
删除链:为了减少对象内嵌链节点大小,删除链使用单向链表。考虑到1)源端对象删除操作时,该对象可以立即从链中摘除并释放,2)提高源端对象删除消息的传输效率,删除链不真正挂接被删除的对象,而是挂接有效对象节点来表示删除对象的开区间,即挂接被删除对象的前一个有效对象。如删除对象5,通过创建链查找到其前一个对象4和后一个对象6,确定开区间为(4,6)。
如下图所示,删除对象5、2、3、8之后,则在删除链上挂接对象4、1、7即可。在发送对象删除消息时,只需携带三个开区间(4,6),(1,4),(7,9)。注意到没有,删除4个对象,仅需要发送三个消息体!!因此,删除的连续对象越多,同步对象删除事件的效率越高。
或许你会产生疑问,删除对象8,为什么开区间是(7,9)呢?很简单,因为对象9并没有分配过,这里只是取用了待分配的oid而已!开区间是(7,9),而非(7,UINT64_MAX),目的是为了防止后续新创建的对象,如9、10… 被错误的删除。而上一段落中提到的哨兵节点,在删除了对象1之后,其作用就会体现出来。
更新链:更新链主要用于有效数据对象的更新或请求。为了支持对象更新的取消操作,更新链建议采用双向链表。
上面,讲述了同一CLASS下数据对象的基本组织方式,那么上级CLASS结构是如何组织的呢?一般可以是avl树或红黑树,以全局唯一的class_id为key值进行存储。
当然,为了尽可能地减小对象固定内嵌管理头对内存的占用,在对象管理库的实现中,一个对象中仅固定地内嵌创建链节点,而删除链、更新链、异步应答链、老化链的节点等,则根据实际情况来确定是否需要内嵌到对象内嵌头结构中。内嵌管理头结构与常用内嵌节点的定义可参考如下:
+-------------+-----+-------------+--------------+--------------+-------------+-------------+
| LIB n EMBED | ... | LIB 1 EMBED | OM_EMBED_UPT | OM_EMBED_DEL | OM_MGR_HEAD | Object Data |
+-------------+-----+-------------+--------------+--------------+-------------+-------------+
^ ^
usembed_total_offset 0
/**
*\brief 对象的内嵌管理头
*/
typedef struct tag_om_mgr_head
{
DLL_NODE tcrt_node; /*!<对象的内嵌创建链表节点 */
UINT64 l_oid; /*!<本地oid */
UINT32 l_class; /*!<本地对象所属class */
UINT16propagate_flag; /*!<判断是否需要通知(OCM_PROP_TYPE) */
UINT8 ucembed_type; /*!< 对象内嵌链表类型(与class中一致,避免链表操作时搜索class) */
UINT8 res;
}OM_MGR_HEAD;
/**
*\brief 对象的内嵌删除链节点(根据LIB注册信息确定)
*/
typedef struct tag_om_embed_del
{
SLL_NODE tdel_node;
}OM_EMBED_DEL;
/**
*\brief 对象的内嵌更新链节点(根据LIB注册信息确定)
*/
typedef struct tag_om_embed_upt
{
DLL_NODE tupt_node;
}OM_EMBED_UPT;
上述即实现对象管理库(OM)的基本方法。若要实现单播/多播同步库(UTS/MTS),除了需要对象管理库(OM),还需要 1)依赖观察库(OBS)来刷新删除游标、更新游标等,依赖 2)定时器库定时触发数据的同步,依赖 3)单播/多播库(UCS/MCS)打包并传输消息数据。限于篇幅原因,后续再详述!!