steem插件的注册、初始化和启动

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_plugindatabase_api_plugin的注册和初始化.
  • plugin_initialize负责初始化api成员。
  • plugin_startup负责启动插件,实质调用了condenser_api::api_startup

其他插件类的实现大同小异,它们必须实现abstract_plugin定义的4个纯虚函数,只是实现不同,因为每个插件要分别处理各自的任务.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,067评论 19 139
  • 如果,读这篇文章发现错误或者疑惑的欢迎在这里讨论:https://www.jianshu.com/p/d82405...
    yjy239阅读 7,121评论 23 25
  • EOS,企业操作系统,是为企业级分布式应用设计的一款区块链操作系统。相比于目前区块链平台性能低、开发难度大以及手续...
    币来网阅读 723评论 0 0
  • 上一篇已经分析了EOS节点程序eosd通过插件化的架构组织各种服务功能,本篇将介绍EOS所使用的石墨烯区块链引擎,...
    ansenyu阅读 4,343评论 0 6
  • 鸭子等动物的双眼长在两侧,这样就可以全视角的观察周围的环境,而人类的眼睛长在前面,虽然舍弃了一部分视角,也就...
    fengliwudi阅读 212评论 0 0