Files

236 lines
7.9 KiB
C++

#include <eosio/chain/application.hpp>
#include <eosio/chain_plugin/chain_plugin.hpp>
#include <eosio/http_plugin/http_plugin.hpp>
#include <eosio/net_plugin/net_plugin.hpp>
#include <eosio/producer_plugin/producer_plugin.hpp>
#include <eosio/resource_monitor_plugin/resource_monitor_plugin.hpp>
#include <eosio/version/version.hpp>
#include <fc/log/logger.hpp>
#include <fc/log/logger_config.hpp>
#include <fc/log/appender.hpp>
#include <fc/exception/exception.hpp>
#include <fc/scoped_exit.hpp>
#include <boost/dll/runtime_symbol_info.hpp>
#include <boost/exception/diagnostic_information.hpp>
#include <filesystem>
#include <string>
#include <vector>
#include <iterator>
#include "config.hpp"
using namespace appbase;
using namespace eosio;
namespace detail {
void log_non_default_options(const std::vector<bpo::basic_option<char>>& options) {
using namespace std::string_literals;
string result;
for (const auto& op : options) {
bool mask = false;
if (op.string_key == "signature-provider"s
|| op.string_key == "peer-private-key"s
|| op.string_key == "p2p-auto-bp-peer"s) {
mask = true;
}
std::string v;
for (auto i = op.value.cbegin(), b = op.value.cbegin(), e = op.value.cend(); i != e; ++i) {
if (i != b)
v += ", ";
if (mask)
v += "***";
else
v += *i;
}
if (!result.empty())
result += ", ";
if (v.empty()) {
result += op.string_key;
} else {
result += op.string_key;
result += " = ";
result += v;
}
}
ilog("Non-default options: ${v}", ("v", result));
}
fc::logging_config& add_deep_mind_logger(fc::logging_config& config) {
config.appenders.push_back(
fc::appender_config( "deep-mind", "dmlog" )
);
fc::logger_config dmlc;
dmlc.name = "deep-mind";
dmlc.level = fc::log_level::debug;
dmlc.enabled = true;
dmlc.appenders.push_back("deep-mind");
config.loggers.push_back( dmlc );
return config;
}
void configure_logging(const std::filesystem::path& config_path)
{
try {
try {
if( std::filesystem::exists( config_path ) ) {
fc::configure_logging( config_path );
} else {
auto cfg = fc::logging_config::default_config();
fc::configure_logging( ::detail::add_deep_mind_logger(cfg) );
}
} catch (...) {
elog("Error reloading logging.json");
throw;
}
} catch (const fc::exception& e) {
elog("${e}", ("e",e.to_detail_string()));
} catch (const boost::exception& e) {
elog("${e}", ("e",boost::diagnostic_information(e)));
} catch (const std::exception& e) {
elog("${e}", ("e",e.what()));
} catch (...) {
// empty
}
}
} // namespace detail
void logging_conf_handler()
{
auto config_path = app().get_logging_conf();
if( std::filesystem::exists( config_path ) ) {
ilog( "Received HUP. Reloading logging configuration from ${p}.", ("p", config_path.string()) );
} else {
ilog( "Received HUP. No log config found at ${p}, setting to default.", ("p", config_path.string()) );
}
::detail::configure_logging( config_path );
fc::log_config::initialize_appenders();
}
void initialize_logging()
{
auto config_path = app().get_logging_conf();
if(std::filesystem::exists(config_path))
fc::configure_logging(config_path); // intentionally allowing exceptions to escape
else {
auto cfg = fc::logging_config::default_config();
fc::configure_logging( ::detail::add_deep_mind_logger(cfg) );
}
fc::log_config::initialize_appenders();
app().set_sighup_callback(logging_conf_handler);
}
enum return_codes {
OTHER_FAIL = -2,
INITIALIZE_FAIL = -1,
SUCCESS = 0,
BAD_ALLOC = 1,
DATABASE_DIRTY = 2,
FIXED_REVERSIBLE = SUCCESS,
EXTRACTED_GENESIS = SUCCESS,
NODE_MANAGEMENT_SUCCESS = 5
};
int main(int argc, char** argv)
{
try {
appbase::scoped_app app;
fc::scoped_exit<std::function<void()>> on_exit = [&]() {
ilog("${name} version ${ver} ${fv}",
("name", nodeos::config::node_executable_name)("ver", app->version_string())
("fv", app->version_string() == app->full_version_string() ? "" : app->full_version_string()) );
::detail::log_non_default_options(app->get_parsed_options());
};
uint32_t short_hash = 0;
fc::from_hex(eosio::version::version_hash(), (char*)&short_hash, sizeof(short_hash));
app->set_version(htonl(short_hash));
app->set_version_string(eosio::version::version_client());
app->set_full_version_string(eosio::version::version_full());
auto root = fc::app_path();
app->set_default_data_dir(root / "eosio" / nodeos::config::node_executable_name / "data" );
app->set_default_config_dir(root / "eosio" / nodeos::config::node_executable_name / "config" );
http_plugin::set_defaults({
.default_unix_socket_path = "",
.default_http_port = 8888,
.server_header = nodeos::config::node_executable_name + "/" + app->version_string()
});
if(!app->initialize<chain_plugin, net_plugin, producer_plugin, resource_monitor_plugin>(argc, argv, initialize_logging)) {
const auto& opts = app->get_options();
if( opts.count("help") || opts.count("version") || opts.count("full-version") || opts.count("print-default-config") ) {
on_exit.cancel();
return SUCCESS;
}
return INITIALIZE_FAIL;
}
if (auto resmon_plugin = app->find_plugin<resource_monitor_plugin>()) {
resmon_plugin->monitor_directory(app->data_dir());
} else {
elog("resource_monitor_plugin failed to initialize");
return INITIALIZE_FAIL;
}
ilog("${name} version ${ver} ${fv}",
("name", nodeos::config::node_executable_name)("ver", app->version_string())
("fv", app->version_string() == app->full_version_string() ? "" : app->full_version_string()) );
ilog("${name} using configuration file ${c}", ("name", nodeos::config::node_executable_name)("c", app->full_config_file_path().string()));
ilog("${name} data directory is ${d}", ("name", nodeos::config::node_executable_name)("d", app->data_dir().string()));
::detail::log_non_default_options(app->get_parsed_options());
app->startup();
app->set_thread_priority_max();
app->exec();
} catch( const extract_genesis_state_exception& e ) {
return EXTRACTED_GENESIS;
} catch( const fixed_reversible_db_exception& e ) {
return FIXED_REVERSIBLE;
} catch( const node_management_success& e ) {
return NODE_MANAGEMENT_SUCCESS;
} catch( const fc::exception& e ) {
if( e.code() == fc::std_exception_code ) {
if( e.top_message().find( "atabase dirty flag set" ) != std::string::npos ) {
elog( "database dirty flag set (likely due to unclean shutdown): replay required" );
return DATABASE_DIRTY;
}
}
elog( "${e}", ("e", e.to_detail_string()));
return OTHER_FAIL;
} catch( const boost::interprocess::bad_alloc& e ) {
elog("bad alloc");
return BAD_ALLOC;
} catch( const boost::exception& e ) {
elog("${e}", ("e",boost::diagnostic_information(e)));
return OTHER_FAIL;
} catch( const std::runtime_error& e ) {
if( std::string(e.what()).find("atabase dirty flag set") != std::string::npos ) {
elog( "database dirty flag set (likely due to unclean shutdown): replay required" );
return DATABASE_DIRTY;
} else {
elog( "${e}", ("e",e.what()));
}
return OTHER_FAIL;
} catch( const std::exception& e ) {
elog("${e}", ("e",e.what()));
return OTHER_FAIL;
} catch( ... ) {
elog("unknown exception");
return OTHER_FAIL;
}
ilog("${name} successfully exiting", ("name", nodeos::config::node_executable_name));
return SUCCESS;
}