该函数首先遍历插件列表,调用每个插件都会实现的plugin基类的虚函数set_program_options(options_description& cli, options_description& cfg),例如下面就是mongo_db_plugin的实现:
void mongo_db_plugin::set_program_options(options_description& cli, options_description& cfg) { cfg.add_options() ("mongodb-queue-size,q", bpo::value<uint32_t>()->default_value(256), "The target queue size between nodeos and MongoDB plugin thread.") ("mongodb-wipe", bpo::bool_switch()->default_value(false), "Required with --replay-blockchain, --hard-replay-blockchain, or --delete-all-blocks to wipe mongo db." "This option required to prevent accidental wipe of mongo db.") ("mongodb-block-start", bpo::value<uint32_t>()->default_value(0), "If specified then only abi data pushed to mongodb until specified block is reached.") ("mongodb-uri,m", bpo::value<std::string>(), "MongoDB URI connection string, see: https://docs.mongodb.com/master/reference/connection-string/." " If not specified then plugin is disabled. Default database 'EOS' is used if not specified in URI." " Example: mongodb://127.0.0.1:27017/EOS") ; }通过调用mongo_db_plugin的这个方法,就可以拼凑到config.ini文件中关于mongo_db_plugin的部分,因为这个插件只有对于config.ini配置文件的配置,没有对于命令行的内容,我们可以去查看chain_plugin的实现,它会同时有配置文件和命令行两个方面的内容设置,源码较长请自行查看。
配置的对象options_description_easy_init是一个灵活的结构。可以表示:一个配置项,一个配置的值;一个配置项,一个配置的值,一个注释或者描述;一个配置项,一个注释或者描述。这些多种组合,我们也可以直接去查看自己的config.ini的每一个配置项去对应。
那么是如何拼凑所有的插件配置内容呢?
application.cpp文件中的set_program_options()函数的函数体中使用了application的两个类变量来存储这些参数:
_app_options:用于接收来自于命令行和config.ini两个参数来源的参数。
_cfg_options:仅存储来自于config.ini配置文件的参数。
插件遍历结束后,我们已经有了所有插件的config.ini配置内容以及命令行提示配置内容,下面要从宏观角度去配置一些属于application的配置项,config.ini中加入了plugins的配置,通过这个配置我们可以手动指定要启动的插件,例如mongo_db_plugin就是需要手动配置的。接着,要配置命令行的参数内容,包括help, version, print-default-config, data-dir, config-dir, config, logconf。将他们追加存储到上面那两个类变量中。
到这里,application.cpp文件中的set_program_options()函数的工作就完成了。
上面提到的_app_options和_cfg_options仍就是傻傻分不清楚,他们的用意到底是什么呢?
简单来理解就是,命令行能够做所有配置文件config.ini中的配置的工作,同时命令行还有专属于自己的help, version, print-default-config, data-dir, config-dir, config, logconf配置。这样就好理解了,config.ini是命令行配置的子集,命令行配置是全集。
(2)app全局参数的检测与合并我们回到initialize_impl,目前我们已经拥有了两套默认配置参数,这里直接使用全集_app_options配置,我们先接收来自于命令行的参数,将以它为优先级高的方式与_app_options配置合并:
bpo::variables_map options; bpo::store(bpo::parse_command_line(argc, argv, my->_app_options), options); (3)app全局参数配置项生效与响应拿到合并后的配置对象options,依次针对配置项的内容进行响应:
help:直接输出_app_options配置项的全部内容。
version:输出application实例的类成员_version的值。
print-default-config:与_app_options无关,重新去每个plugin找配置,然后会基于_cfg_options生成一份默认的config配置打印到终端界面。
data-dir:是设置data目录的命令保存至application的类成员_data_dir,没有响应的输出。