管中窥豹 EOS 数据存储 | database::create

database::add_index 在内存映射文件上面创建 generic_index 类型对象,此对象的成员变量 _indices 为 multi_index_container,此多索引容器对象为 empty 通过 database::create 操作向容器内添加对象。nodeos 收到一笔延迟交易会把此交易放进缓存中,本文以此为入口 展开对 database::create 的详细讨论,eos 的版本是 mainnet-1.5.1 ,文件路径在 eos/libraries/chainbase/include/chainbase/chainbase.hpp。

transaction_context::schedule_transaction 函数分析

当 nodeos 对交易进行处理时,如果是延迟交易状态,交易会被放在缓存数据库中。当进入出块状态时,则会把到期的延迟交易处理完成并删除缓存中的延迟交易。

此过程利用了泛型 Lambda 表达式,此处理解为匿名函数对象。可知此时传递给 database::create 的函数参数变量是一个函数对象,此函数为变量进行赋值操作。

database::create 模版函数分析

参考以前博客 database::find 解析可知此时的 index_type 类型为 generated_transaction_multi_index 。 get_mutable_index 模版函数通过具体的容器类型获取相应的 generic_index 实例对象的引用,然后调用其 emplace 函数向容器内添加对象。

generic_index::emplace 模版函数分析

generic_index 的成员变量 _next_id 实质上 是一个递增的 int64_t 类型变量。所有的存储在 database 中的对象类型都会有一个 id 字段,在向容器中添加对象时此字段会被赋值为唯一的递增值。最后利用 multi_index_container::emplace 添加新的变量。此处 on_create 函数主要是向 _stack 成员变量里面增加一个操作,以方便后面的回滚。

generic_index::modify 和 generic_index::remove 函数分析

利用 multi_index_container::modify 函数完成更改。

利用 multi_index_container::erase 函数完成删除操作。

总结

  1. 通过要增删改的 ObjectType 类型获取相应绑定的 index_type 类型
  2. 通过 index_type 类型 可以在 _index_map 对象中通过下标 index_type::value_type::type_id 找到 generic_index 实例对象。
  3. 利用 multi_index_container 的相应操作完成容器中数据的操作。
  4. _stack 中添加相应的操作方便后面进行回滚和提交

预告

管中窥豹EOS数据存储系列致力于深入源码底层细节剖析 eos 的存储模型。

下篇管中窥豹EOS数据存储系列重点讲述 database::undo 和 database::commit 请关注后续更新。

发表评论

电子邮件地址不会被公开。 必填项已用*标注