/
daemon.cpp
123 lines (117 loc) · 4.19 KB
/
daemon.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include <boost/property_tree/json_parser.hpp>
#include <fstream>
#include <iostream>
#include <nano/lib/utility.hpp>
#include <nano/nano_node/daemon.hpp>
#include <nano/node/daemonconfig.hpp>
#include <nano/node/ipc.hpp>
#include <nano/node/json_handler.hpp>
#include <nano/node/node.hpp>
#include <nano/node/openclwork.hpp>
#include <nano/node/working.hpp>
#include <nano/rpc/rpc.hpp>
#ifndef BOOST_PROCESS_SUPPORTED
#error BOOST_PROCESS_SUPPORTED must be set, check configuration
#endif
#if BOOST_PROCESS_SUPPORTED
#include <boost/process.hpp>
#endif
void nano_daemon::daemon::run (boost::filesystem::path const & data_path, nano::node_flags const & flags)
{
boost::filesystem::create_directories (data_path);
boost::system::error_code error_chmod;
nano::set_secure_perm_directory (data_path, error_chmod);
std::unique_ptr<nano::thread_runner> runner;
nano::daemon_config config (data_path);
auto error = nano::read_and_update_daemon_config (data_path, config);
if (!error)
{
config.node.logging.init (data_path);
nano::logger_mt logger{ config.node.logging.min_time_between_log_output };
boost::asio::io_context io_ctx;
auto opencl (nano::opencl_work::create (config.opencl_enable, config.opencl, logger));
nano::work_pool opencl_work (config.node.work_threads, config.node.pow_sleep_interval, opencl ? [&opencl](nano::uint256_union const & root_a, uint64_t difficulty_a) {
return opencl->generate_work (root_a, difficulty_a);
}
: std::function<boost::optional<uint64_t> (nano::uint256_union const &, uint64_t)> (nullptr));
nano::alarm alarm (io_ctx);
nano::node_init init;
try
{
auto node (std::make_shared<nano::node> (init, io_ctx, data_path, alarm, config.node, opencl_work, flags));
if (!init.error ())
{
node->start ();
nano::ipc::ipc_server ipc_server (*node, config.rpc);
#if BOOST_PROCESS_SUPPORTED
std::unique_ptr<boost::process::child> rpc_process;
#endif
std::unique_ptr<std::thread> rpc_process_thread;
std::unique_ptr<nano::rpc> rpc;
std::unique_ptr<nano::rpc_handler_interface> rpc_handler;
if (config.rpc_enable)
{
if (config.rpc.rpc_in_process)
{
nano::rpc_config rpc_config;
auto error = nano::read_and_update_rpc_config (data_path, rpc_config);
if (error)
{
throw std::runtime_error ("Could not deserialize rpc_config file");
}
rpc_handler = std::make_unique<nano::inprocess_rpc_handler> (*node, config.rpc, [&ipc_server]() {
ipc_server.stop ();
});
rpc = nano::get_rpc (io_ctx, rpc_config, *rpc_handler);
rpc->start ();
}
else
{
if (!boost::filesystem::exists (config.rpc.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.rpc_path);
}
auto network = node->network_params.network.get_current_network_as_string ();
#if BOOST_PROCESS_SUPPORTED
rpc_process = std::make_unique<boost::process::child> (config.rpc.rpc_path, "--daemon", "--data_path", data_path, "--network", network);
#else
auto rpc_exe_command = boost::str (boost::format ("%1% --daemon --data_path=%2% --network=%3%") % config.rpc.rpc_path % data_path % network);
// clang-format off
rpc_process_thread = std::make_unique<std::thread> ([rpc_exe_command, &logger = node->logger]() {
nano::thread_role::set (nano::thread_role::name::rpc_process_container);
std::system (rpc_exe_command.c_str ());
logger.always_log ("RPC server has stopped");
});
// clang-format on
#endif
}
}
runner = std::make_unique<nano::thread_runner> (io_ctx, node->config.io_threads);
runner->join ();
#if BOOST_PROCESS_SUPPORTED
if (rpc_process)
{
rpc_process->wait ();
}
#else
if (rpc_process_thread)
{
rpc_process_thread->join ();
}
#endif
}
else
{
std::cerr << "Error initializing node\n";
}
}
catch (const std::runtime_error & e)
{
std::cerr << "Error while running node (" << e.what () << ")\n";
}
}
else
{
std::cerr << "Error deserializing config: " << error.get_message () << std::endl;
}
}