EOS应用程序框架appbase

2018-10-23  本文已影响38人  vergil6

简介

EOS中的cleos,nodeos,keosd都是基于插件的应用程序框架appbase构建的,appbase库提供了一个从一组插件构建应用程序的基本框架, appbase管理插件生命周期并确保所有插件以正确的顺序配置,初始化,启动和关闭,appbase使用boost::asio作为异步库,目前是单线程单实例可以通过appbase :: app()访问这个单例,appbase给插件提供了插件之间的通信接口channel和method, 使插件的之间的通信耦合性更加低

示例

可以在appbase/examples目录中找到基于插件应用程序的简单示例。下面给出一个有2个插件的简单例子

#include <appbase/application.hpp>
#include <iostream>
#include <boost/exception/diagnostic_information.hpp>

struct database { };

namespace bpo = boost::program_options;

using bpo::options_description;
using bpo::variables_map;
using std::string;
using std::vector;


class chain_plugin : public appbase::plugin<chain_plugin>
{
   public:
     APPBASE_PLUGIN_REQUIRES();

      // 设置命令行选项参数
     virtual void set_program_options( options_description& cli, options_description& cfg ) override
     {
         cfg.add_options()
               ("readonly", "open the database in read only mode")
               ("dbsize", bpo::value<uint64_t>()->default_value( 8*1024 ), "Minimum size MB of database shared memory file")
               ;
         cli.add_options()
               ("replay", "clear chain database and replay all blocks" )
               ("reset", "clear chain database and block log" )
               ;
     }
        
      // 插件的初始化
     void plugin_initialize( const variables_map& options ) { std::cout << "initialize chain plugin\n"; }
      // 插件的启动
     void plugin_startup()  { std::cout << "starting chain plugin \n"; }
      // 插件的关闭
     void plugin_shutdown() { std::cout << "shutdown chain plugin \n"; }
};

class net_plugin : public appbase::plugin<net_plugin>
{
   public:
     net_plugin(){};
     ~net_plugin(){};

     APPBASE_PLUGIN_REQUIRES( (chain_plugin) );

     virtual void set_program_options( options_description& cli, options_description& cfg ) override
     {
        cfg.add_options()
              ("listen-endpoint", bpo::value<string>()->default_value( "127.0.0.1:9876" ), "The local IP address and port to listen for incoming connections.")
              ("remote-endpoint", bpo::value< vector<string> >()->composing(), "The IP address and port of a remote peer to sync with.")
              ("public-endpoint", bpo::value<string>()->default_value( "0.0.0.0:9876" ), "The public IP address and port that should be advertized to peers.")
              ;
     }

     void plugin_initialize( const variables_map& options ) { std::cout << "initialize net plugin\n"; }
     void plugin_startup()  { std::cout << "starting net plugin \n"; }
     void plugin_shutdown() { std::cout << "shutdown net plugin \n"; }

};
// 注册插件
static appbase::abstract_plugin& _producer_plugin = appbase::app().register_plugin<chain_plugin>();
// 注册插件
static appbase::abstract_plugin& _producer_plugin2 = appbase::app().register_plugin<net_plugin>();


int main( int argc, char** argv ) {
   try {
      // 需要加载的插件
      if( !appbase::app().initialize<chain_plugin, net_plugin>( argc, argv ) )
         return -1;
      // 启动所有加载的插件
      appbase::app().startup();
      // 注册信号,io_service.run()进入事件循环
      appbase::app().exec();
   } catch ( const boost::exception& e ) {
      std::cerr << boost::diagnostic_information(e) << "\n";
   } catch ( const std::exception& e ) {
      std::cerr << e.what() << "\n";
   } catch ( ... ) {
      std::cerr << "unknown exception\n";
   }
   std::cout << "exited cleanly\n";
   return 0;
}

执行之后的结果:

~/code/eos/build/libraries/appbase/examples$ ./appbase_example 
initialize chain plugin
initialize net plugin
starting chain plugin 
starting net plugin 
^Cshutdown net plugin 
shutdown chain plugin 
exited cleanly

main函数中启动一个基于appbase程序必须的3步:
1)appbase::app().initialize<plugin_name1,plugin_name2 ...>( argc, argv ) ,加载需要的插件,注意这些plugin_name必须是已经注册的,程序可以选择性的加载已注册的需要的插件
2)appbase::app().startup(),启动所有加载的插件
3)注册信号(SIGINT,SIGTERM,SIGPIPE),io_service.run()进入事件循环

上一篇下一篇

猜你喜欢

热点阅读