美文网首页
steem插件的注册、初始化和启动

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

作者: jiongua | 来源:发表于2018-09-19 18:32 被阅读0次

    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个纯虚函数,只是实现不同,因为每个插件要分别处理各自的任务.

    相关文章

      网友评论

          本文标题:steem插件的注册、初始化和启动

          本文链接:https://www.haomeiwen.com/subject/yfxwnftx.html