config-dir:设置config路径,保存在类成员_config_dir中。config和data的路径结构如下:
evsward@evsward-TM1701:~/.local/share/eosio/nodeos$ tree . ├── config │ └── config.ini └── data ├── blocks │ ├── blocks.index │ ├── blocks.log │ └── reversible │ ├── shared_memory.bin │ └── shared_memory.meta └── state ├── forkdb.dat ├── shared_memory.bin └── shared_memory.meta 5 directories, 8 fileslogconf:默认是logging.json,放置在config目录下面,可自定义设置,保存在类成员_logging_conf中。
config:指定配置文件的名字,默认是config.ini。如果发现在config目录下找到config.ini文件,则按照该文件的配置载入。
bpo::store(bpo::parse_config_file<char>(config_file_name.make_preferred().string().c_str(), my->_cfg_options, true), options);得到整合好本地config.ini文本配置的options对象。然后对其参数配置项进行设置。
plugin:读取配置文件中的plugin配置(多条),对于每一个plugin,要重新调用各自的initialize方法去按照新的配置初始化。
autostart_plugins:设置前面的初始化插件chain_plugin, http_plugin, net_plugin, producer_plugin,同样分别调用他们的初始化函数设置新的配置。
(4)plugin initialize承接上文,所有相关的plugin的执行各自的initialize。这个initialize函数是abstract_plugin的虚函数,而该虚函数被plugin类所复写:
virtual void initialize(const variables_map& options) override { if(_state == registered) {//如果注册过 _state = initialized; static_cast<Impl*>(this)->plugin_requires([&](auto& plug){ plug.initialize(options); });// 先执行依赖plugin的initialize方法。 static_cast<Impl*>(this)->plugin_initialize(options);// 调用自身的plugin_initialize方法实现。 //ilog( "initializing plugin ${name}", ("name",name()) ); app().plugin_initialized(*this);// 保存到一个initialized_plugins类成员变量中,用来按顺序记录已经开始启动运行的plugin。 } assert(_state == initialized); /// 如果插件未注册,则不能执行initialize方法。 }所以在plugin调用initialize函数的时候,是先执行的以上复写的plugin的虚函数。我们这里先设定几个要跟踪的plugin为目标吧,否则plugin太多,望山止步。
目标:主要研究mongo_db_plugin,以及基础plugin(chain_plugin, http_plugin, net_plugin, producer_plugin),路线是研究主plugin,若有额外的依赖plugin,看情况控制研究的深浅程度。
(5)eosio::mongo_db_plugin::plugin_initialize前面写set_program_options()提到了mongo_db_plugin,这里研究它的plugin_initialize方法。传入的参数是结合了命令行以及本地config文件的合并配置项,按照此配置环境。
void mongo_db_plugin::plugin_initialize(const variables_map& options) { try { if( options.count( "mongodb-uri" )) {//查mongodb-uri的配置,config.ini中有对应的。 ilog( "initializing mongo_db_plugin" ); my->configured = true;//设置标志位:已配置 if( options.at( "replay-blockchain" ).as<bool>() || options.at( "hard-replay-blockchain" ).as<bool>() || options.at( "delete-all-blocks" ).as<bool>() ) {//捕捉是否有replay-blockchain、hard-replay-blockchain、delete-all-blocks三个动作,有的话要判断是否要擦出mongo历史数据。 if( options.at( "mongodb-wipe" ).as<bool>()) {//检查擦除项mongodb-wipe的配置 ilog( "Wiping mongo database on startup" ); my->wipe_database_on_startup = true;//如果设置擦除,这里设置本地标志位wipe_database_on_startup } else if( options.count( "mongodb-block-start" ) == 0 ) {//如果设置是从0开始,检查是否要全部擦除历史数据。 EOS_ASSERT( false, chain::plugin_config_exception, "--mongodb-wipe required with --replay-blockchain, --hard-replay-blockchain, or --delete-all-blocks" " --mongodb-wipe will remove all EOS collections from mongodb." ); } } if( options.count( "abi-serializer-max-time-ms") == 0 ) {//eosio::chain_plugin的配置 EOS_ASSERT(false, chain::plugin_config_exception, "--abi-serializer-max-time-ms required as default value not appropriate for parsing full blocks"); } my->abi_serializer_max_time = app().get_plugin<chain_plugin>().get_abi_serializer_max_time(); if( options.count( "mongodb-queue-size" )) {// queue大小 my->queue_size = options.at( "mongodb-queue-size" ).as<uint32_t>(); } if( options.count( "mongodb-block-start" )) {// mongo对应的开始区块号 my->start_block_num = options.at( "mongodb-block-start" ).as<uint32_t>(); } if( my->start_block_num == 0 ) { my->start_block_reached = true; } std::string uri_str = options.at( "mongodb-uri" ).as<std::string>(); ilog( "connecting to ${u}", ("u", uri_str)); mongocxx::uri uri = mongocxx::uri{uri_str}; my->db_name = uri.database(); if( my->db_name.empty()) my->db_name = "EOS";// 默认起的库名字为EOS,如果在mongodb-uri有配置的话就使用配置的名字。 my->mongo_conn = mongocxx::client{uri};// 客户端连接到mongod // controller中拉取得信号,在init函数中注册信号机制,始终监听链上信号,作出反应。 chain_plugin* chain_plug = app().find_plugin<chain_plugin>();//检查chain_plugin是否加载,chain_plugin是必要依赖,下面我们要使用chain的数据。 EOS_ASSERT( chain_plug, chain::missing_chain_plugin_exception, "" ); auto& chain = chain_plug->chain();// 获得chain实例 my->chain_id.emplace( chain.get_chain_id()); // accepted_block_connection对应了chain的signal,是boost提供的一种信号槽机制,这种connection对象有四个,见当前源码的下方展示。 my->accepted_block_connection.emplace( chain.accepted_block.connect( [&]( const chain::block_state_ptr& bs ) {// 建立connect,每当chain有accepted_block信号(这些信号是定义在controller.hpp中,稍后会介绍),即调用下面的函数。 my->accepted_block( bs );// accepted_block认同block信息 } )); my->irreversible_block_connection.emplace(//含义同上 chain.irreversible_block.connect( [&]( const chain::block_state_ptr& bs ) { my->applied_irreversible_block( bs );// applied_irreversible_block,应用不可逆区块 } )); my->accepted_transaction_connection.emplace(//含义同上 chain.accepted_transaction.connect( [&]( const chain::transaction_metadata_ptr& t ) { my->accepted_transaction( t );// accepted_transaction认同交易 } )); my->applied_transaction_connection.emplace(//含义同上 chain.applied_transaction.connect( [&]( const chain::transaction_trace_ptr& t ) { my->applied_transaction( t );// applied_transaction,应用交易 } )); if( my->wipe_database_on_startup ) { my->wipe_database();// 擦除mongo历史数据 } my->init();//初始化函数 } else { wlog( "eosio::mongo_db_plugin configured, but no --mongodb-uri specified." ); wlog( "mongo_db_plugin disabled." ); } } FC_LOG_AND_RETHROW() }