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()进入事件循环