Skip to content

Commit

Permalink
Cleanup config deserialization errors
Browse files Browse the repository at this point in the history
  • Loading branch information
pwojcikdev committed Jun 2, 2024
1 parent f02cee1 commit 3551af9
Showing 1 changed file with 113 additions and 115 deletions.
228 changes: 113 additions & 115 deletions nano/nano_node/daemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,158 +74,156 @@ void nano::daemon::run (std::filesystem::path const & data_path, nano::node_flag

nano::network_params network_params{ nano::network_constants::active_network };
nano::daemon_config config{ data_path, network_params };
auto error = nano::read_node_config_toml (data_path, config, flags.config_overrides);
if (auto error = nano::read_node_config_toml (data_path, config, flags.config_overrides))
{
logger.critical (nano::log::type::daemon, "Error deserializing node config: {}", error.get_message ());
std::exit (1);
}
if (auto error = nano::flags_config_conflicts (flags, config.node))
{
logger.critical (nano::log::type::daemon, "Error parsing command line options: {}", error.message ());
std::exit (1);
}

nano::set_use_memory_pools (config.node.use_memory_pools);

if (!error)
std::shared_ptr<boost::asio::io_context> io_ctx = std::make_shared<boost::asio::io_context> ();

auto opencl = nano::opencl_work::create (config.opencl_enable, config.opencl, logger, config.node.network_params.work);
nano::opencl_work_func_t opencl_work_func;
if (opencl)
{
error = nano::flags_config_conflicts (flags, config.node);
opencl_work_func = [&opencl] (nano::work_version const version_a, nano::root const & root_a, uint64_t difficulty_a, std::atomic<int> & ticket_a) {
return opencl->generate_work (version_a, root_a, difficulty_a, ticket_a);
};
}
if (!error)
nano::work_pool opencl_work (config.node.network_params.network, config.node.work_threads, config.node.pow_sleep_interval, opencl_work_func);
try
{
std::shared_ptr<boost::asio::io_context> io_ctx = std::make_shared<boost::asio::io_context> ();
// This avoids a blank prompt during any node initialization delays
logger.info (nano::log::type::daemon, "Starting up Nano node...");

auto opencl = nano::opencl_work::create (config.opencl_enable, config.opencl, logger, config.node.network_params.work);
nano::opencl_work_func_t opencl_work_func;
if (opencl)
// Print info about number of logical cores detected, those are used to decide how many IO, worker and signature checker threads to spawn
logger.info (nano::log::type::daemon, "Hardware concurrency: {} ( configured: {} )", std::thread::hardware_concurrency (), nano::hardware_concurrency ());

nano::set_file_descriptor_limit (OPEN_FILE_DESCRIPTORS_LIMIT);
auto const file_descriptor_limit = nano::get_file_descriptor_limit ();
logger.info (nano::log::type::daemon, "File descriptors limit: {}", file_descriptor_limit);
if (file_descriptor_limit < OPEN_FILE_DESCRIPTORS_LIMIT)
{
opencl_work_func = [&opencl] (nano::work_version const version_a, nano::root const & root_a, uint64_t difficulty_a, std::atomic<int> & ticket_a) {
return opencl->generate_work (version_a, root_a, difficulty_a, ticket_a);
};
logger.warn (nano::log::type::daemon, "File descriptors limit is lower than the {} recommended. Node was unable to change it.", OPEN_FILE_DESCRIPTORS_LIMIT);
}
nano::work_pool opencl_work (config.node.network_params.network, config.node.work_threads, config.node.pow_sleep_interval, opencl_work_func);
try
{
// This avoids a blank prompt during any node initialization delays
logger.info (nano::log::type::daemon, "Starting up Nano node...");

// Print info about number of logical cores detected, those are used to decide how many IO, worker and signature checker threads to spawn
logger.info (nano::log::type::daemon, "Hardware concurrency: {} ( configured: {} )", std::thread::hardware_concurrency (), nano::hardware_concurrency ());

nano::set_file_descriptor_limit (OPEN_FILE_DESCRIPTORS_LIMIT);
auto const file_descriptor_limit = nano::get_file_descriptor_limit ();
logger.info (nano::log::type::daemon, "File descriptors limit: {}", file_descriptor_limit);
if (file_descriptor_limit < OPEN_FILE_DESCRIPTORS_LIMIT)
{
logger.warn (nano::log::type::daemon, "File descriptors limit is lower than the {} recommended. Node was unable to change it.", OPEN_FILE_DESCRIPTORS_LIMIT);
}

// for the daemon start up, if the user hasn't specified a port in
// the config, we must use the default peering port for the network
//
if (!config.node.peering_port.has_value ())
{
config.node.peering_port = network_params.network.default_node_port;
}
// for the daemon start up, if the user hasn't specified a port in
// the config, we must use the default peering port for the network
//
if (!config.node.peering_port.has_value ())
{
config.node.peering_port = network_params.network.default_node_port;
}

auto node = std::make_shared<nano::node> (io_ctx, data_path, config.node, opencl_work, flags);
if (!node->init_error ())
{
auto network_label = node->network_params.network.get_current_network_as_string ();
std::time_t dateTime = std::time (nullptr);
auto node = std::make_shared<nano::node> (io_ctx, data_path, config.node, opencl_work, flags);
if (!node->init_error ())
{
auto network_label = node->network_params.network.get_current_network_as_string ();
std::time_t dateTime = std::time (nullptr);

logger.info (nano::log::type::daemon, "Network: {}", network_label);
logger.info (nano::log::type::daemon, "Version: {}", NANO_VERSION_STRING);
logger.info (nano::log::type::daemon, "Data path: '{}'", node->application_path.string ());
logger.info (nano::log::type::daemon, "Build info: {}", BUILD_INFO);
logger.info (nano::log::type::daemon, "Database backend: {}", node->store.vendor_get ());
logger.info (nano::log::type::daemon, "Start time: {:%c} UTC", fmt::gmtime (dateTime));
logger.info (nano::log::type::daemon, "Network: {}", network_label);
logger.info (nano::log::type::daemon, "Version: {}", NANO_VERSION_STRING);
logger.info (nano::log::type::daemon, "Data path: '{}'", node->application_path.string ());
logger.info (nano::log::type::daemon, "Build info: {}", BUILD_INFO);
logger.info (nano::log::type::daemon, "Database backend: {}", node->store.vendor_get ());
logger.info (nano::log::type::daemon, "Start time: {:%c} UTC", fmt::gmtime (dateTime));

// IO context runner should be started first and stopped last to allow asio handlers to execute during node start/stop
runner = std::make_unique<nano::thread_runner> (io_ctx, logger, node->config.io_threads, nano::thread_role::name::io_daemon);
// IO context runner should be started first and stopped last to allow asio handlers to execute during node start/stop
runner = std::make_unique<nano::thread_runner> (io_ctx, logger, node->config.io_threads, nano::thread_role::name::io_daemon);

node->start ();
node->start ();

std::atomic stopped{ false };
std::atomic stopped{ false };

std::unique_ptr<nano::ipc::ipc_server> ipc_server = std::make_unique<nano::ipc::ipc_server> (*node, config.rpc);
std::unique_ptr<boost::process::child> rpc_process;
std::unique_ptr<nano::rpc_handler_interface> rpc_handler;
std::shared_ptr<nano::rpc> rpc;
std::unique_ptr<nano::ipc::ipc_server> ipc_server = std::make_unique<nano::ipc::ipc_server> (*node, config.rpc);
std::unique_ptr<boost::process::child> rpc_process;
std::unique_ptr<nano::rpc_handler_interface> rpc_handler;
std::shared_ptr<nano::rpc> rpc;

if (config.rpc_enable)
if (config.rpc_enable)
{
// In process RPC
if (!config.rpc.child_process.enable)
{
if (!config.rpc.child_process.enable)
auto stop_callback = [this, &stopped] () {
logger.warn (nano::log::type::daemon, "RPC stop request received, stopping...");
stopped = true;
stopped.notify_all ();
};

// Launch rpc in-process
nano::rpc_config rpc_config{ config.node.network_params.network };
if (auto error = nano::read_rpc_config_toml (data_path, rpc_config, flags.rpc_config_overrides))
{
auto stop_callback = [this, &stopped] () {
logger.warn (nano::log::type::daemon, "RPC stop request received, stopping...");
stopped = true;
stopped.notify_all ();
};

// Launch rpc in-process
nano::rpc_config rpc_config{ config.node.network_params.network };
auto error = nano::read_rpc_config_toml (data_path, rpc_config, flags.rpc_config_overrides);
if (error)
{
std::cout << error.get_message () << std::endl;
std::exit (1);
}

rpc_handler = std::make_unique<nano::inprocess_rpc_handler> (*node, *ipc_server, config.rpc, stop_callback);
rpc = nano::get_rpc (io_ctx, rpc_config, *rpc_handler);
rpc->start ();
logger.critical (nano::log::type::daemon, "Error deserializing RPC config: {}", error.get_message ());
std::exit (1);
}
else

rpc_handler = std::make_unique<nano::inprocess_rpc_handler> (*node, *ipc_server, config.rpc, stop_callback);
rpc = nano::get_rpc (io_ctx, rpc_config, *rpc_handler);
rpc->start ();
}
else
{
// Spawn a child rpc process
if (!std::filesystem::exists (config.rpc.child_process.rpc_path))
{
// Spawn a child rpc process
if (!std::filesystem::exists (config.rpc.child_process.rpc_path))
{
throw std::runtime_error (std::string ("RPC is configured to spawn a new process however the file cannot be found at: ") + config.rpc.child_process.rpc_path);
}
throw std::runtime_error (std::string ("RPC is configured to spawn a new process however the file cannot be found at: ") + config.rpc.child_process.rpc_path);
}

auto network = node->network_params.network.get_current_network_as_string ();
auto network = node->network_params.network.get_current_network_as_string ();

rpc_process = std::make_unique<boost::process::child> (config.rpc.child_process.rpc_path, "--daemon", "--data_path", data_path.string (), "--network", network);
}
debug_assert (rpc || rpc_process);
rpc_process = std::make_unique<boost::process::child> (config.rpc.child_process.rpc_path, "--daemon", "--data_path", data_path.string (), "--network", network);
}
debug_assert (rpc || rpc_process);
}

auto signal_handler = [this, &stopped] (int signum) {
logger.warn (nano::log::type::daemon, "Interrupt signal received ({}), stopping...", to_signal_name (signum));
stopped = true;
stopped.notify_all ();
};

nano::signal_manager sigman;
// keep trapping Ctrl-C to avoid a second Ctrl-C interrupting tasks started by the first
sigman.register_signal_handler (SIGINT, signal_handler, true);
// sigterm is less likely to come in bunches so only trap it once
sigman.register_signal_handler (SIGTERM, signal_handler, false);
auto signal_handler = [this, &stopped] (int signum) {
logger.warn (nano::log::type::daemon, "Interrupt signal received ({}), stopping...", to_signal_name (signum));
stopped = true;
stopped.notify_all ();
};

// Keep running until stopped flag is set
stopped.wait (false);
nano::signal_manager sigman;
// keep trapping Ctrl-C to avoid a second Ctrl-C interrupting tasks started by the first
sigman.register_signal_handler (SIGINT, signal_handler, true);
// sigterm is less likely to come in bunches so only trap it once
sigman.register_signal_handler (SIGTERM, signal_handler, false);

logger.info (nano::log::type::daemon, "Stopping...");
// Keep running until stopped flag is set
stopped.wait (false);

if (rpc)
{
rpc->stop ();
}
ipc_server->stop ();
node->stop ();
io_ctx->stop ();
runner->join ();
logger.info (nano::log::type::daemon, "Stopping...");

if (rpc_process)
{
rpc_process->wait ();
}
if (rpc)
{
rpc->stop ();
}
else
ipc_server->stop ();
node->stop ();
io_ctx->stop ();
runner->join ();

if (rpc_process)
{
logger.critical (nano::log::type::daemon, "Error initializing node");
rpc_process->wait ();
}
}
catch (std::runtime_error const & e)
else
{
logger.critical (nano::log::type::daemon, "Error while running node: {}", e.what ());
logger.critical (nano::log::type::daemon, "Error initializing node");
}
}
else
catch (std::runtime_error const & e)
{
logger.critical (nano::log::type::daemon, "Error deserializing config: {}", error.get_message ());
logger.critical (nano::log::type::daemon, "Error while running node: {}", e.what ());
}

logger.info (nano::log::type::daemon, "Daemon stopped");
Expand Down

0 comments on commit 3551af9

Please sign in to comment.