application类
application
类是应用程序入口函数最重要的类。除了提供一些初始化任务、载入配置外,它还统一管理所有插件,同时提供了统一的方法:
-
template< typename Plugin > auto& register_plugin()
- 模板参数为要注册的插件,它构造插件对象并将其注册到
application
- 注册和构造依赖插件到
application
- 模板参数为要注册的插件,它构造插件对象并将其注册到
-
template< typename... Plugin > bool initialize( int argc, char** argv )
- 初始化模板参数指定的插件
- 初始化配置和命令行指定的插件
-
template< typename Plugin > Plugin* find_plugin()const
从application插件注册列表中查找给定的插件类型
-
void startup()
启动application插件初始化列表中的插件。
为配合对插件的统一控制,application
类根据插件的状态定义了几个插件列表:
//已注册的插件列表
map< string, std::shared_ptr< abstract_plugin > > plugins;
//已初始化的插件列表
vector< abstract_plugin* > initialized_plugins;
//已启动的插件列表
vector< abstract_plugin* > running_plugins;
在程序入口main
函数中只需简单的调用application
提供的方法即可在初始阶段统一控制插件:
int main( int argc, char** argv )
{
....
//初始化所有配置的插件
bool initialized = appbase::app().initialize<
steem::plugins::chain::chain_plugin,
steem::plugins::p2p::p2p_plugin,
steem::plugins::webserver::webserver_plugin >
( argc, argv );
...
//启动所有已经初始化的插件
appbase::app().startup();
}
abstract_plugin抽象基类
abstract_plugin
抽象基类定义两组接口,其中一组是所有final插件
必须实现的接口:
//依赖插件的注册
virtual void plugin_for_each_dependency(plugin_processor&& processor) = 0;
//插件初始化
virtual void plugin_initialize( const variables_map& options ) = 0;
//启动插件
virtual void plugin_startup() = 0;
//插件中止
virtual void plugin_shutdown() = 0;
另一组接口需要在plugin模板基类
中实现,这些是统一控制各个final插件的接口:
virtual void initialize(const variables_map& options) = 0;
virtual void startup() = 0;
virtual void shutdown() = 0;
application
正是使用包含abstract_plugin
指针的插件列表管理所有插件,利用OO实现了插件的统一操作。
插件自动注册
前面说了application::register_plugin
模板函数提供了注册插件方法,但注册插件的代码是在编译期间自动生成的而非手动添加
每个插件位于
libraries/plugins/
和external_plugins
路径下,其中每个文件夹为一个插件单元。插件目录中 需要包含一个CMakeLists.txt
,其中描述该插件的源码文件有哪些,编译时需要连接哪些库。还需要包含一个
plugin.json
用以帮助模板生成器加载该插件,用以生成该插件初始化时的注册函数。 在steemd
编译过程中,会使用python3-jinja2
来加载每个插件目录中的plugin.json
生成插件注册函数steem::plugins::register_plugins
,其生成路径为${build}/libraries/manifest/gensrc/plugins/mf_plugins.cpp
。 该中的每一行为向应用程序注册一个插件。
自动生成的mf_plugins.cpp文件中定义了一个register_plugins
函数:
void register_plugins()
{
appbase::app().register_plugin< account_by_key_plugin >();
appbase::app().register_plugin< account_history_plugin >();
appbase::app().register_plugin< account_history_rocksdb_plugin >();
...
appbase::app().register_plugin< tags_plugin >();
appbase::app().register_plugin< webserver_plugin >();
appbase::app().register_plugin< witness_plugin >();
}
各个插件类作为模板参数调用application::register_plugin
以实现插件的注册.
具体插件分析-condenser_api_plugin
接下来分析一个插件实例:
class condenser_api_plugin : public appbase::plugin< condenser_api_plugin >
{
public:
APPBASE_PLUGIN_REQUIRES( (steem::plugins::json_rpc::json_rpc_plugin)(steem::plugins::database_api::database_api_plugin) )
condenser_api_plugin();
virtual ~condenser_api_plugin();
static const std::string& name() { static std::string name = STEEM_CONDENSER_API_PLUGIN_NAME; return name; }
virtual void set_program_options( options_description& cli, options_description& cfg ) override;
virtual void plugin_initialize( const variables_map& options ) override;
virtual void plugin_startup() override;
virtual void plugin_shutdown() override;
std::shared_ptr< class condenser_api > api;
};
condenser_api_plugin
继承自plugin
模板基类,模板参数即为自己。它完全实现了abstract_plugin
定义的4个纯虚函数。
-
APPBASE_PLUGIN_REQUIRES
宏展开实质为plugin_for_each_dependency
, 在注册condenser_api_plugin
插件的同时,完成了其依赖插件json_rpc_plugin
和database_api_plugin
的注册和初始化. -
plugin_initialize
负责初始化api
成员。 -
plugin_startup
负责启动插件,实质调用了condenser_api::api_startup
其他插件类的实现大同小异,它们必须实现abstract_plugin
定义的4个纯虚函数,只是实现不同,因为每个插件要分别处理各自的任务.
网友评论