Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
appbase::application Class Reference

#include <application.hpp>

Public Member Functions

 ~application ()
 
void set_version (uint64_t version)
 Set version.
 
uint64_t version () const
 Get version.
 
string version_string () const
 Get version string; generated from git describe if available.
 
void set_version_string (std::string v)
 User provided version string for version_string() which overrides git describe value.
 
string full_version_string () const
 Get full version string; same as version_string() unless set differently.
 
void set_full_version_string (std::string v)
 User provided full version string for full_version_string()
 
void set_default_data_dir (const bfs::path &data_dir="data-dir")
 Set default data directory.
 
bfs::path data_dir () const
 Get data directory.
 
void set_default_config_dir (const bfs::path &config_dir="etc")
 Set default config directory.
 
bfs::path config_dir () const
 Get config directory.
 
bfs::path get_logging_conf () const
 Get logging configuration path.
 
bfs::path full_config_file_path () const
 Get full config.ini path.
 
void set_sighup_callback (std::function< void()> callback)
 Set function pointer invoked on receipt of SIGHUP.
 
template<typename... Plugin>
bool initialize (int argc, char **argv)
 Looks for the –plugin commandline / config option and calls initialize on those plugins.
 
void startup ()
 
void shutdown ()
 
void exec ()
 
void quit ()
 
bool is_quiting () const
 
template<typename T >
void register_config_type ()
 
void register_config_type_comparison (std::type_index, config_comparison_f comp)
 
abstract_pluginfind_plugin (const string &name) const
 
abstract_pluginget_plugin (const string &name) const
 
template<typename Plugin >
auto & register_plugin ()
 
template<typename Plugin >
Plugin * find_plugin () const
 
template<typename Plugin >
Plugin & get_plugin () const
 
template<typename MethodDecl >
auto get_method () -> std::enable_if_t< is_method_decl< MethodDecl >::value, typename MethodDecl::method_type & >
 
template<typename ChannelDecl >
auto get_channel () -> std::enable_if_t< is_channel_decl< ChannelDecl >::value, typename ChannelDecl::channel_type & >
 
boost::asio::io_service & get_io_service ()
 
template<typename Func >
auto post (int priority, Func &&func)
 
auto & get_priority_queue ()
 
const bpo::variables_map & get_options () const
 
void set_thread_priority_max ()
 

Static Public Member Functions

static applicationinstance ()
 

Protected Member Functions

bool initialize_impl (int argc, char **argv, vector< abstract_plugin * > autostart_plugins)
 
void plugin_initialized (abstract_plugin &plug)
 
void plugin_started (abstract_plugin &plug)
 

Friends

template<typename Impl >
class plugin
 

Detailed Description

Definition at line 16 of file application.hpp.

Constructor & Destructor Documentation

◆ ~application()

appbase::application::~application ( )

Definition at line 96 of file application.cpp.

96{ }

Member Function Documentation

◆ config_dir()

bfs::path appbase::application::config_dir ( ) const
Returns
Config directory, possibly from command line

Definition at line 531 of file application.cpp.

531 {
532 return my->_config_dir;
533}
Here is the caller graph for this function:

◆ data_dir()

bfs::path appbase::application::data_dir ( ) const
Returns
Data directory, possibly from command line

Definition at line 527 of file application.cpp.

527 {
528 return my->_data_dir;
529}
Here is the caller graph for this function:

◆ exec()

void appbase::application::exec ( )

Wait until quit(), SIGINT or SIGTERM and then shutdown. Should only be executed from one thread.

perform synchronous shutdown

Definition at line 442 of file application.cpp.

442 {
443 {
444 boost::asio::io_service::work work(*io_serv);
445 (void)work;
446 bool more = true;
447 while( more || io_serv->run_one() ) {
448 while( io_serv->poll_one() ) {}
449 // execute the highest priority item
450 more = pri_queue.execute_highest();
451 }
452
453 shutdown();
454 }
455 io_serv.reset();
456}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_plugin() [1/2]

template<typename Plugin >
Plugin * appbase::application::find_plugin ( ) const
inline

Definition at line 148 of file application.hpp.

148 {
149 string name = boost::core::demangle(typeid(Plugin).name());
150 return dynamic_cast<Plugin*>(find_plugin(name));
151 }
std::string name
Plugin * find_plugin() const
Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_plugin() [2/2]

abstract_plugin * appbase::application::find_plugin ( const string & name) const

Definition at line 511 of file application.cpp.

512{
513 auto itr = plugins.find(name);
514 if(itr == plugins.end()) {
515 return nullptr;
516 }
517 return itr->second.get();
518}
Here is the caller graph for this function:

◆ full_config_file_path()

bfs::path appbase::application::full_config_file_path ( ) const
Returns
Config directory & config file name, possibly from command line. Only valid after initialize() has been called.

Definition at line 535 of file application.cpp.

535 {
536 return bfs::canonical(my->_config_file_name);
537}
Here is the caller graph for this function:

◆ full_version_string()

string appbase::application::full_version_string ( ) const
Returns
A string worthy of output with -v/–version, or "Unknown" if git not available

Definition at line 114 of file application.cpp.

114 {
115 return my->_full_version_str;
116}
Here is the caller graph for this function:

◆ get_channel()

template<typename ChannelDecl >
auto appbase::application::get_channel ( ) -> std::enable_if_t<is_channel_decl<ChannelDecl>::value, typename ChannelDecl::channel_type&>
inline

Fetch a reference to the channel declared by the passed in type. This will construct the channel on first access. This allows loose and deferred binding between plugins

Template Parameters
ChannelDecl- appbase::channel_decl
Returns
reference to the channel described by the declaration

Definition at line 188 of file application.hpp.

189 {
190 using channel_type = typename ChannelDecl::channel_type;
191 auto key = std::type_index(typeid(ChannelDecl));
192 auto itr = channels.find(key);
193 if(itr != channels.end()) {
194 return *channel_type::get_channel(itr->second);
195 } else {
196 channels.emplace(std::make_pair(key, channel_type::make_unique()));
197 return *channel_type::get_channel(channels.at(key));
198 }
199 }
Here is the caller graph for this function:

◆ get_io_service()

boost::asio::io_service & appbase::application::get_io_service ( )
inline

Do not run io_service in any other threads, as application assumes single-threaded execution in exec().

Returns
io_serivice of application

Definition at line 205 of file application.hpp.

205{ return *io_serv; }
Here is the caller graph for this function:

◆ get_logging_conf()

bfs::path appbase::application::get_logging_conf ( ) const
Returns
Logging configuration location from command line

Definition at line 130 of file application.cpp.

130 {
131 return my->_logging_conf;
132}
Here is the caller graph for this function:

◆ get_method()

template<typename MethodDecl >
auto appbase::application::get_method ( ) -> std::enable_if_t<is_method_decl<MethodDecl>::value, typename MethodDecl::method_type&>
inline

Fetch a reference to the method declared by the passed in type. This will construct the method on first access. This allows loose and deferred binding between plugins

Template Parameters
MethodDecl- appbase::method_decl
Returns
reference to the method described by the declaration

Definition at line 167 of file application.hpp.

168 {
169 using method_type = typename MethodDecl::method_type;
170 auto key = std::type_index(typeid(MethodDecl));
171 auto itr = methods.find(key);
172 if(itr != methods.end()) {
173 return *method_type::get_method(itr->second);
174 } else {
175 methods.emplace(std::make_pair(key, method_type::make_unique()));
176 return *method_type::get_method(methods.at(key));
177 }
178 }
Here is the caller graph for this function:

◆ get_options()

const bpo::variables_map & appbase::application::get_options ( ) const

Definition at line 543 of file application.cpp.

543 {
544 return my->_options;
545}
Here is the caller graph for this function:

◆ get_plugin() [1/2]

template<typename Plugin >
Plugin & appbase::application::get_plugin ( ) const
inline

Definition at line 154 of file application.hpp.

154 {
155 auto ptr = find_plugin<Plugin>();
156 return *ptr;
157 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_plugin() [2/2]

abstract_plugin & appbase::application::get_plugin ( const string & name) const

Definition at line 520 of file application.cpp.

520 {
521 auto ptr = find_plugin(name);
522 if(!ptr)
523 BOOST_THROW_EXCEPTION(std::runtime_error("unable to find plugin: " + name));
524 return *ptr;
525}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_priority_queue()

auto & appbase::application::get_priority_queue ( )
inline

Provide access to execution priority queue so it can be used to wrap functions for prioritized execution.

Example: boost::asio::steady_timer timer( app().get_io_service() ); timer.async_wait( app().get_priority_queue().wrap(priority::low, [](){ do_something(); }) );

Definition at line 227 of file application.hpp.

227 {
228 return pri_queue;
229 }

◆ initialize()

template<typename... Plugin>
bool appbase::application::initialize ( int argc,
char ** argv )
inline
Template Parameters
PluginList of plugins to initalize even if not mentioned by configuration. For plugins started by configuration settings or dependency resolution, this template has no effect.
Returns
true if the application and plugins were initialized, false or exception on error

Definition at line 99 of file application.hpp.

99 {
100 return initialize_impl(argc, argv, {find_plugin<Plugin>()...});
101 }
bool initialize_impl(int argc, char **argv, vector< abstract_plugin * > autostart_plugins)
char ** argv
Here is the call graph for this function:
Here is the caller graph for this function:

◆ initialize_impl()

bool appbase::application::initialize_impl ( int argc,
char ** argv,
vector< abstract_plugin * > autostart_plugins )
protected

Definition at line 250 of file application.cpp.

250 {
251 set_program_options();
252
253 bpo::variables_map& options = my->_options;
254 try {
255 bpo::parsed_options parsed = bpo::command_line_parser(argc, argv).options(my->_app_options).run();
256 bpo::store(parsed, options);
257 vector<string> positionals = bpo::collect_unrecognized(parsed.options, bpo::include_positional);
258 if(!positionals.empty())
259 BOOST_THROW_EXCEPTION(std::runtime_error("Unknown option '" + positionals[0] + "' passed as command line argument"));
260 } catch( const boost::program_options::unknown_option& e ) {
261 BOOST_THROW_EXCEPTION(std::runtime_error("Unknown option '" + e.get_option_name() + "' passed as command line argument"));
262 }
263
264 if( options.count( "help" ) ) {
265 cout << my->_app_options << std::endl;
266 return false;
267 }
268
269 if( options.count( "version" ) ) {
270 cout << version_string() << std::endl;
271 return false;
272 }
273
274 if( options.count( "full-version" ) ) {
275 cout << full_version_string() << std::endl;
276 return false;
277 }
278
279 if( options.count( "print-default-config" ) ) {
280 print_default_config(cout);
281 return false;
282 }
283
284 if( options.count( "data-dir" ) ) {
285 // Workaround for 10+ year old Boost defect
286 // See https://svn.boost.org/trac10/ticket/8535
287 // Should be .as<bfs::path>() but paths with escaped spaces break bpo e.g.
288 // std::exception::what: the argument ('/path/with/white\ space') for option '--data-dir' is invalid
289 auto workaround = options["data-dir"].as<std::string>();
290 bfs::path data_dir = workaround;
291 if( data_dir.is_relative() )
292 data_dir = bfs::current_path() / data_dir;
293 my->_data_dir = data_dir;
294 }
295
296 if( options.count( "config-dir" ) ) {
297 auto workaround = options["config-dir"].as<std::string>();
298 bfs::path config_dir = workaround;
299 if( config_dir.is_relative() )
300 config_dir = bfs::current_path() / config_dir;
301 my->_config_dir = config_dir;
302 }
303
304 auto workaround = options["logconf"].as<std::string>();
305 bfs::path logconf = workaround;
306 if( logconf.is_relative() )
307 logconf = my->_config_dir / logconf;
308 my->_logging_conf = logconf;
309
310 workaround = options["config"].as<std::string>();
311 my->_config_file_name = workaround;
312 if( my->_config_file_name.is_relative() )
313 my->_config_file_name = my->_config_dir / my->_config_file_name;
314
315 if(!bfs::exists(my->_config_file_name)) {
316 if(my->_config_file_name.compare(my->_config_dir / "config.ini") != 0)
317 {
318 cout << "Config file " << my->_config_file_name << " missing." << std::endl;
319 return false;
320 }
321 write_default_config(my->_config_file_name);
322 }
323
324 std::vector< bpo::basic_option<char> > opts_from_config;
325 try {
326 bpo::parsed_options parsed_opts_from_config = bpo::parse_config_file<char>(my->_config_file_name.make_preferred().string().c_str(), my->_cfg_options, false);
327 bpo::store(parsed_opts_from_config, options);
328 opts_from_config = parsed_opts_from_config.options;
329 } catch( const boost::program_options::unknown_option& e ) {
330 BOOST_THROW_EXCEPTION(std::runtime_error("Unknown option '" + e.get_option_name() + "' inside the config file " + full_config_file_path().string()));
331 }
332
333 std::vector<string> set_but_default_list;
334
335 for(const boost::shared_ptr<bpo::option_description>& od_ptr : my->_cfg_options.options()) {
336 boost::any default_val, config_val;
337 if(!od_ptr->semantic()->apply_default(default_val))
338 continue;
339
340 if(my->_any_compare_map.find(default_val.type()) == my->_any_compare_map.end()) {
341 std::cerr << "APPBASE: Developer -- the type " << default_val.type().name() << " is not registered with appbase," << std::endl;
342 std::cerr << " add a register_config_type<>() in your plugin's ctor" << std::endl;
343 return false;
344 }
345
346 for(const bpo::basic_option<char>& opt : opts_from_config) {
347 if(opt.string_key != od_ptr->long_name())
348 continue;
349
350 od_ptr->semantic()->parse(config_val, opt.value, true);
351 if(my->_any_compare_map.at(default_val.type())(default_val, config_val))
352 set_but_default_list.push_back(opt.string_key);
353 break;
354 }
355 }
356 if(set_but_default_list.size()) {
357 std::cerr << "APPBASE: Warning: The following configuration items in the config.ini file are redundantly set to" << std::endl;
358 std::cerr << " their default value:" << std::endl;
359 std::cerr << " ";
360 size_t chars_on_line = 0;
361 for(auto it = set_but_default_list.cbegin(); it != set_but_default_list.end(); ++it) {
362 std::cerr << *it;
363 if(it + 1 != set_but_default_list.end())
364 std::cerr << ", ";
365 if((chars_on_line += it->size()) > 65) {
366 std::cerr << std::endl << " ";
367 chars_on_line = 0;
368 }
369 }
370 std::cerr << std::endl;
371 std::cerr << " Explicit values will override future changes to application defaults. Consider commenting out or" << std::endl;
372 std::cerr << " removing these items." << std::endl;
373 }
374
375 if(options.count("plugin") > 0)
376 {
377 auto plugins = options.at("plugin").as<std::vector<std::string>>();
378 for(auto& arg : plugins)
379 {
380 vector<string> names;
381 boost::split(names, arg, boost::is_any_of(" \t,"));
382 for(const std::string& name : names)
383 get_plugin(name).initialize(options);
384 }
385 }
386 try {
387 for (auto plugin : autostart_plugins)
388 if (plugin != nullptr && plugin->get_state() == abstract_plugin::registered)
389 plugin->initialize(options);
390
391 bpo::notify(options);
392 } catch (...) {
393 std::cerr << "Failed to initialize\n";
394 return false;
395 }
396
397 return true;
398}
@ registered
the plugin is constructed but doesn't do anything
Definition plugin.hpp:31
bfs::path data_dir() const
Get data directory.
bfs::path full_config_file_path() const
Get full config.ini path.
string version_string() const
Get version string; generated from git describe if available.
bfs::path config_dir() const
Get config directory.
Plugin & get_plugin() const
string full_version_string() const
Get full version string; same as version_string() unless set differently.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ instance()

application & appbase::application::instance ( )
static

Definition at line 206 of file application.cpp.

206 {
207 static application _app;
208 return _app;
209}
Here is the caller graph for this function:

◆ is_quiting()

bool appbase::application::is_quiting ( ) const

If in long running process this flag can be checked to see if processing should be stoppped.

Returns
true if quit() has been called.

Definition at line 420 of file application.cpp.

420 {
421 return my->_is_quiting;
422}
Here is the caller graph for this function:

◆ plugin_initialized()

void appbase::application::plugin_initialized ( abstract_plugin & plug)
inlineprotected

these notifications get called from the plugin when their state changes so that the application can call shutdown in the reverse order.

Definition at line 249 of file application.hpp.

249{ initialized_plugins.push_back(&plug); }
Here is the caller graph for this function:

◆ plugin_started()

void appbase::application::plugin_started ( abstract_plugin & plug)
inlineprotected

Definition at line 250 of file application.hpp.

250{ running_plugins.push_back(&plug); }
Here is the caller graph for this function:

◆ post()

template<typename Func >
auto appbase::application::post ( int priority,
Func && func )
inline

Post func to run on io_service with given priority.

Parameters
prioritycan be appbase::priority::* constants or any int, larger ints run first
funcfunction to run on io_service
Returns
result of boost::asio::post

Definition at line 215 of file application.hpp.

215 {
216 return boost::asio::post(*io_serv, pri_queue.wrap(priority, std::forward<Func>(func)));
217 }
boost::asio::executor_binder< Function, executor > wrap(int priority, Function &&func)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ quit()

void appbase::application::quit ( )

Definition at line 415 of file application.cpp.

415 {
416 my->_is_quiting = true;
417 io_serv->stop();
418}
Here is the caller graph for this function:

◆ register_config_type()

template<typename T >
void appbase::application::register_config_type ( )
inline

Register a configuration type with appbase. most "plain" types are already registered in application.cpp. Failure to register a type will cause initialization to fail.

Definition at line 123 of file application.hpp.

123 {
124 register_config_type_comparison(typeid(T), [](const auto& a, const auto& b) {
125 return boost::any_cast<const T&>(a) == boost::any_cast<const T&>(b);
126 });
127 }
void register_config_type_comparison(std::type_index, config_comparison_f comp)
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1181
#define T(meth, val, expected)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ register_config_type_comparison()

void appbase::application::register_config_type_comparison ( std::type_index i,
config_comparison_f comp )

Definition at line 212 of file application.cpp.

212 {
213 my->_any_compare_map.emplace(i, comp);
214}
Here is the caller graph for this function:

◆ register_plugin()

template<typename Plugin >
auto & appbase::application::register_plugin ( )
inline

Definition at line 136 of file application.hpp.

136 {
137 auto existing = find_plugin<Plugin>();
138 if(existing)
139 return *existing;
140
141 auto plug = new Plugin();
142 plugins[plug->name()].reset(plug);
143 plug->register_dependencies();
144 return *plug;
145 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_default_config_dir()

void appbase::application::set_default_config_dir ( const bfs::path & config_dir = "etc")
Parameters
config_dirDefault configuration directory to use if not specified on the command line.

Definition at line 126 of file application.cpp.

126 {
127 my->_config_dir = config_dir;
128}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_default_data_dir()

void appbase::application::set_default_data_dir ( const bfs::path & data_dir = "data-dir")
Parameters
data_dirDefault data directory to use if not specified on the command line.

Definition at line 122 of file application.cpp.

122 {
123 my->_data_dir = data_dir;
124}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_full_version_string()

void appbase::application::set_full_version_string ( std::string v)

Definition at line 118 of file application.cpp.

118 {
119 my->_full_version_str = std::move( v );
120}
Here is the caller graph for this function:

◆ set_sighup_callback()

void appbase::application::set_sighup_callback ( std::function< void()> callback)

The provided function will be invoked on receipt of SIGHUP followed by invoking handle_sighup() on all initialized plugins. Caller is responsible for preserving an object if necessary.

Parameters
callbackFunction pointer that will be invoked when the process receives the HUP (1) signal.

Definition at line 539 of file application.cpp.

539 {
540 sighup_callback = callback;
541}
Here is the caller graph for this function:

◆ set_thread_priority_max()

void appbase::application::set_thread_priority_max ( )

Set the current thread schedule priority to maximum. Works for pthreads.

Definition at line 424 of file application.cpp.

424 {
425#if __has_include(<pthread.h>)
426 pthread_t this_thread = pthread_self();
427 struct sched_param params{};
428 int policy = 0;
429 int ret = pthread_getschedparam(this_thread, &policy, &params);
430 if( ret != 0 ) {
431 std::cerr << "ERROR: Unable to get thread priority" << std::endl;
432 }
433
434 params.sched_priority = sched_get_priority_max(policy);
435 ret = pthread_setschedparam(this_thread, policy, &params);
436 if( ret != 0 ) {
437 std::cerr << "ERROR: Unable to set thread priority" << std::endl;
438 }
439#endif
440}
account_query_db::get_accounts_by_authorizers_params params
CK_RV ret
Here is the caller graph for this function:

◆ set_version()

void appbase::application::set_version ( uint64_t version)
Parameters
versionVersion output with -v/–version

Definition at line 98 of file application.cpp.

98 {
99 my->_version = version;
100}
uint64_t version() const
Get version.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_version_string()

void appbase::application::set_version_string ( std::string v)

Definition at line 110 of file application.cpp.

110 {
111 my->_version_str = std::move( v );
112}
Here is the caller graph for this function:

◆ shutdown()

void appbase::application::shutdown ( )

Definition at line 400 of file application.cpp.

400 {
401 for(auto ritr = running_plugins.rbegin();
402 ritr != running_plugins.rend(); ++ritr) {
403 (*ritr)->shutdown();
404 }
405 for(auto ritr = running_plugins.rbegin();
406 ritr != running_plugins.rend(); ++ritr) {
407 plugins.erase((*ritr)->name());
408 }
409 running_plugins.clear();
410 initialized_plugins.clear();
411 plugins.clear();
412 quit();
413}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ startup()

void appbase::application::startup ( )

Definition at line 156 of file application.cpp.

156 {
157 //during startup, run a second thread to catch SIGINT/SIGTERM/SIGPIPE/SIGHUP
158 boost::asio::io_service startup_thread_ios;
159 setup_signal_handling_on_ios(startup_thread_ios, true);
160 std::thread startup_thread([&startup_thread_ios]() {
161 startup_thread_ios.run();
162 });
163 auto clean_up_signal_thread = [&startup_thread_ios, &startup_thread]() {
164 startup_thread_ios.stop();
165 startup_thread.join();
166 };
167
168 try {
169 for( auto plugin : initialized_plugins ) {
170 if( is_quiting() ) break;
171 plugin->startup();
172 }
173
174 } catch( ... ) {
175 clean_up_signal_thread();
176 shutdown();
177 throw;
178 }
179
180 //after startup, shut down the signal handling thread and catch the signals back on main io_service
181 clean_up_signal_thread();
182 setup_signal_handling_on_ios(get_io_service(), false);
183
184#ifdef SIGHUP
185 std::shared_ptr<boost::asio::signal_set> sighup_set(new boost::asio::signal_set(get_io_service(), SIGHUP));
186 start_sighup_handler( sighup_set );
187#endif
188}
boost::asio::io_service & get_io_service()
bool is_quiting() const
Here is the call graph for this function:
Here is the caller graph for this function:

◆ version()

uint64_t appbase::application::version ( ) const
Returns
Version output with -v/–version

Definition at line 102 of file application.cpp.

102 {
103 return my->_version;
104}
Here is the caller graph for this function:

◆ version_string()

string appbase::application::version_string ( ) const
Returns
A string worthy of output with -v/–version, or "Unknown" if git not available

Definition at line 106 of file application.cpp.

106 {
107 return my->_version_str;
108}
Here is the caller graph for this function:

Friends And Related Symbol Documentation

◆ plugin

template<typename Impl >
friend class plugin
friend

Definition at line 241 of file application.hpp.


The documentation for this class was generated from the following files: