rippled
Loading...
Searching...
No Matches
Main.cpp
1#include <xrpld/app/main/Application.h>
2#include <xrpld/app/rdb/Vacuum.h>
3#include <xrpld/core/Config.h>
4#include <xrpld/core/ConfigSections.h>
5#include <xrpld/core/TimeKeeper.h>
6#include <xrpld/rpc/RPCCall.h>
7
8#include <xrpl/basics/Log.h>
9#include <xrpl/beast/core/CurrentThreadName.h>
10#include <xrpl/protocol/BuildInfo.h>
11
12#include <boost/asio/io_context.hpp>
13#include <boost/process/v1/args.hpp>
14#include <boost/process/v1/child.hpp>
15#include <boost/process/v1/exe.hpp>
16
17#ifdef ENABLE_TESTS
18#include <test/unit_test/multi_runner.h>
19
20#include <xrpl/beast/unit_test/match.h>
21#endif // ENABLE_TESTS
22#include <boost/algorithm/string.hpp>
23#include <boost/program_options.hpp>
24
25#include <google/protobuf/stubs/common.h>
26
27#include <cstdlib>
28#include <fstream>
29#include <stdexcept>
30#include <utility>
31
32#if BOOST_OS_WINDOWS
33#include <sys/timeb.h>
34#include <sys/types.h>
35#endif
36
37// Do we know the platform we're compiling on? If you're adding new platforms
38// modify this check accordingly.
39#if !BOOST_OS_LINUX && !BOOST_OS_WINDOWS && !BOOST_OS_MACOS
40#error Supported platforms are: Linux, Windows and MacOS
41#endif
42
43// Ensure that precisely one platform is detected.
44#if (BOOST_OS_LINUX && (BOOST_OS_WINDOWS || BOOST_OS_MACOS)) || \
45 (BOOST_OS_MACOS && (BOOST_OS_WINDOWS || BOOST_OS_LINUX)) || \
46 (BOOST_OS_WINDOWS && (BOOST_OS_LINUX || BOOST_OS_MACOS))
47#error Multiple supported platforms appear active at once
48#endif
49
50#ifdef ENABLE_VOIDSTAR
51#include "antithesis_instrumentation.h"
52#endif
53
54namespace po = boost::program_options;
55
56namespace xrpl {
57
58bool
60{
61#ifdef RLIMIT_NOFILE
62 // Get the current limit, then adjust it to what we need.
63 struct rlimit rl;
64
65 int available = 0;
66
67 if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
68 {
69 // If the limit is infinite, then we are good.
70 if (rl.rlim_cur == RLIM_INFINITY)
71 available = needed;
72 else
73 available = rl.rlim_cur;
74
75 if (available < needed)
76 {
77 // Ignore the rlim_max, as the process may
78 // be configured to override it anyways. We
79 // ask for the number descriptors we need.
80 rl.rlim_cur = needed;
81
82 if (setrlimit(RLIMIT_NOFILE, &rl) == 0)
83 available = rl.rlim_cur;
84 }
85 }
86
87 if (needed > available)
88 {
89 j.fatal() << "Insufficient number of file descriptors: " << needed << " are needed, but only " << available
90 << " are available.";
91
92 std::cerr << "Insufficient number of file descriptors: " << needed << " are needed, but only " << available
93 << " are available.\n";
94
95 return false;
96 }
97#endif
98
99 return true;
100}
101
102void
103printHelp(po::options_description const& desc)
104{
105 std::cerr << systemName() << "d [options] <command> <params>\n"
106 << desc << std::endl
107 << "Commands: \n"
108 " account_currencies <account> [<ledger>]\n"
109 " account_info <account>|<key> [<ledger>]\n"
110 " account_lines <account> <account>|\"\" [<ledger>]\n"
111 " account_channels <account> <account>|\"\" [<ledger>]\n"
112 " account_objects <account> [<ledger>]\n"
113 " account_offers <account>|<account_public_key> [<ledger>]\n"
114 " account_tx accountID [ledger_index_min [ledger_index_max "
115 "[limit "
116 "]]] [binary]\n"
117 " book_changes [<ledger hash|id>]\n"
118 " book_offers <taker_pays> <taker_gets> [<taker [<ledger> "
119 "[<limit> [<proof> [<marker>]]]]]\n"
120 " can_delete [<ledgerid>|<ledgerhash>|now|always|never]\n"
121 " channel_authorize <private_key> <channel_id> <drops>\n"
122 " channel_verify <public_key> <channel_id> <drops> <signature>\n"
123 " connect <ip> [<port>]\n"
124 " consensus_info\n"
125 " deposit_authorized <source_account> <destination_account> "
126 "[<ledger> [<credentials>, ...]]\n"
127 " feature [<feature> [accept|reject]]\n"
128 " fetch_info [clear]\n"
129 " gateway_balances [<ledger>] <issuer_account> [ <hotwallet> [ "
130 "<hotwallet> ]]\n"
131 " get_counts\n"
132 " json <method> <json>\n"
133 " ledger [<id>|current|closed|validated] [full]\n"
134 " ledger_accept\n"
135 " ledger_cleaner\n"
136 " ledger_closed\n"
137 " ledger_current\n"
138 " ledger_request <ledger>\n"
139 " log_level [[<partition>] <severity>]\n"
140 " logrotate\n"
141 " manifest <public_key>\n"
142 " peers\n"
143 " ping\n"
144 " random\n"
145 " peer_reservations_add <public_key> [<description>]\n"
146 " peer_reservations_del <public_key>\n"
147 " peer_reservations_list\n"
148 " ripple ...\n"
149 " ripple_path_find <json> [<ledger>]\n"
150 " server_definitions [<hash>]\n"
151 " server_info [counters]\n"
152 " server_state [counters]\n"
153 " sign <private_key> <tx_json> [offline]\n"
154 " sign_for <signer_address> <signer_private_key> <tx_json> "
155 "[offline] [<signature_field>]\n"
156 " stop\n"
157 " simulate [<tx_blob>|<tx_json>] [<binary>]\n"
158 " submit <tx_blob>|[<private_key> <tx_json>]\n"
159 " submit_multisigned <tx_json>\n"
160 " tx <id>\n"
161 " validation_create [<seed>|<pass_phrase>|<key>]\n"
162 " validator_info\n"
163 " validators\n"
164 " validator_list_sites\n"
165 " version\n"
166 " wallet_propose [<passphrase>]\n";
167}
168
169//------------------------------------------------------------------------------
170
171#ifdef ENABLE_TESTS
172/* simple unit test selector that allows a comma separated list
173 * of selectors
174 */
175class multi_selector
176{
177private:
179
180public:
181 explicit multi_selector(std::string const& patterns = "")
182 {
184 boost::split(v, patterns, boost::algorithm::is_any_of(","));
185 selectors_.reserve(v.size());
186 std::for_each(v.begin(), v.end(), [this](std::string s) {
187 boost::trim(s);
188 if (selectors_.empty() || !s.empty())
189 selectors_.emplace_back(beast::unit_test::selector::automatch, s);
190 });
191 }
192
193 bool
194 operator()(beast::unit_test::suite_info const& s)
195 {
196 for (auto& sel : selectors_)
197 if (sel(s))
198 return true;
199 return false;
200 }
201
203 size() const
204 {
205 return selectors_.size();
206 }
207};
208
209namespace test {
211}
212
213template <class Runner>
214static bool
215anyMissing(Runner& runner, multi_selector const& pred)
216{
217 if (runner.tests() == 0)
218 {
219 runner.add_failures(1);
220 std::cout << "Failed: No tests run" << std::endl;
221 return true;
222 }
223 if (runner.suites() < pred.size())
224 {
225 auto const missing = pred.size() - runner.suites();
226 runner.add_failures(missing);
227 std::cout << "Failed: " << missing << " filters did not match any existing test suites" << std::endl;
228 return true;
229 }
230 return false;
231}
232
233static int
234runUnitTests(
235 std::string const& pattern,
236 std::string const& argument,
237 bool quiet,
238 bool log,
239 bool child,
240 bool ipv6,
241 std::size_t num_jobs,
242 int argc,
243 char** argv)
244{
245 using namespace beast::unit_test;
246 using namespace xrpl::test;
247
248 xrpl::test::envUseIPv4 = (!ipv6);
249
250 if (!child && num_jobs == 1)
251 {
252 multi_runner_parent parent_runner;
253
254 multi_runner_child child_runner{num_jobs, quiet, log};
255 child_runner.arg(argument);
256 multi_selector pred(pattern);
257 auto const any_failed = child_runner.run_multi(pred) || anyMissing(child_runner, pred);
258
259 if (any_failed)
260 return EXIT_FAILURE;
261 return EXIT_SUCCESS;
262 }
263 if (!child)
264 {
265 multi_runner_parent parent_runner;
267
268 std::string const exe_name = argv[0];
270 {
271 args.reserve(argc);
272 for (int i = 1; i < argc; ++i)
273 args.emplace_back(argv[i]);
274 args.emplace_back("--unittest-child");
275 }
276
277 for (std::size_t i = 0; i < num_jobs; ++i)
278 children.emplace_back(boost::process::v1::exe = exe_name, boost::process::v1::args = args);
279
280 int bad_child_exits = 0;
281 int terminated_child_exits = 0;
282 for (auto& c : children)
283 {
284 try
285 {
286 c.wait();
287 if (c.exit_code())
288 ++bad_child_exits;
289 }
290 catch (...)
291 {
292 // wait throws if process was terminated with a signal
293 ++bad_child_exits;
294 ++terminated_child_exits;
295 }
296 }
297
298 parent_runner.add_failures(terminated_child_exits);
299 anyMissing(parent_runner, multi_selector(pattern));
300
301 if (parent_runner.any_failed() || bad_child_exits)
302 return EXIT_FAILURE;
303 return EXIT_SUCCESS;
304 }
305 else
306 {
307 // child
308 multi_runner_child runner{num_jobs, quiet, log};
309 runner.arg(argument);
310 auto const anyFailed = runner.run_multi(multi_selector(pattern));
311
312 if (anyFailed)
313 return EXIT_FAILURE;
314 return EXIT_SUCCESS;
315 }
316}
317
318#endif // ENABLE_TESTS
319//------------------------------------------------------------------------------
320
321int
322run(int argc, char** argv)
323{
324 using namespace std;
325
327
328 po::variables_map vm;
329
330 std::string importText;
331 {
332 importText += "Import an existing node database (specified in the [";
333 importText += ConfigSection::importNodeDatabase();
334 importText += "] configuration file section) into the current ";
335 importText += "node database (specified in the [";
336 importText += ConfigSection::nodeDatabase();
337 importText += "] configuration file section).";
338 }
339
340 // Set up option parsing.
341 //
342 po::options_description gen("General Options");
343 gen.add_options()("conf", po::value<std::string>(), "Specify the configuration file.")(
344 "debug", "Enable normally suppressed debug logging")("help,h", "Display this message.")(
345 "newnodeid", "Generate a new node identity for this server.")(
346 "nodeid", po::value<std::string>(), "Specify the node identity for this server.")(
347 "quorum", po::value<std::size_t>(), "Override the minimum validation quorum.")(
348 "silent", "No output to the console after startup.")("standalone,a", "Run with no peers.")(
349 "verbose,v", "Verbose logging.")
350
351 ("force_ledger_present_range",
352 po::value<std::string>(),
353 "Specify the range of present ledgers for testing purposes. Min and "
354 "max values are comma separated.")("version", "Display the build version.");
355
356 po::options_description data("Ledger/Data Options");
357 data.add_options()("import", importText.c_str())(
358 "ledger", po::value<std::string>(), "Load the specified ledger and start from the value given.")(
359 "ledgerfile", po::value<std::string>(), "Load the specified ledger file.")(
360 "load", "Load the current ledger from the local DB.")("net", "Get the initial ledger from the network.")(
361 "replay", "Replay a ledger close.")(
362 "trap_tx_hash", po::value<std::string>(), "Trap a specific transaction during replay.")(
363 "start", "Start from a fresh Ledger.")("vacuum", "VACUUM the transaction db.")(
364 "valid", "Consider the initial ledger a valid network ledger.");
365
366 po::options_description rpc("RPC Client Options");
367 rpc.add_options()(
368 "rpc",
369 "Perform rpc command - see below for available commands. "
370 "This is assumed if any positional parameters are provided.")(
371 "rpc_ip",
372 po::value<std::string>(),
373 "Specify the IP address for RPC command. "
374 "Format: <ip-address>[':'<port-number>]")(
375 "rpc_port",
376 po::value<std::uint16_t>(),
377 "DEPRECATED: include with rpc_ip instead. "
378 "Specify the port number for RPC command.");
379
380#ifdef ENABLE_TESTS
381 po::options_description test("Unit Test Options");
382 test.add_options()(
383 "quiet,q",
384 "Suppress test suite messages, "
385 "including suite/case name (at start) and test log messages.")(
386 "unittest,u",
387 po::value<std::string>()->implicit_value(""),
388 "Perform unit tests. The optional argument specifies one or "
389 "more comma-separated selectors. Each selector specifies a suite name, "
390 "suite name prefix, full-name (lib.module.suite), module, or library "
391 "(checked in that order).")(
392 "unittest-arg",
393 po::value<std::string>()->implicit_value(""),
394 "Supplies an argument string to unit tests. If provided, this argument "
395 "is made available to each suite that runs. Interpretation of the "
396 "argument is handled individually by any suite that accesses it -- "
397 "as such, it typically only make sense to provide this when running "
398 "a single suite.")("unittest-ipv6", "Use IPv6 localhost when running unittests (default is IPv4).")(
399 "unittest-log",
400 "Force unit test log message output. Only useful in combination with "
401 "--quiet, in which case log messages will print but suite/case names "
402 "will not.")(
403 "unittest-jobs", po::value<std::size_t>(), "Number of unittest jobs to run in parallel (child processes).");
404#endif // ENABLE_TESTS
405
406 // These are hidden options, not intended to be shown in the usage/help
407 // message
408 po::options_description hidden("Hidden Options");
409 hidden.add_options()(
410 "parameters",
411 po::value<vector<string>>(),
412 "Specify rpc command and parameters. This option must be repeated "
413 "for each command/param. Positional parameters also serve this "
414 "purpose, "
415 "so this option is not needed for users")
416#ifdef ENABLE_TESTS
417 ("unittest-child", "For internal use only when spawning child unit test processes.")
418#else
419 ("unittest", "Disabled in this build.")("unittest-child", "Disabled in this build.")
420#endif // ENABLE_TESTS
421 ("fg", "Deprecated: server always in foreground mode.");
422
423 // Interpret positional arguments as --parameters.
424 po::positional_options_description p;
425 p.add("parameters", -1);
426
427 po::options_description all;
428 all.add(gen)
429 .add(rpc)
430 .add(data)
431#ifdef ENABLE_TESTS
432 .add(test)
433#endif // ENABLE_TESTS
434 .add(hidden);
435
436 po::options_description desc;
437 desc.add(gen)
438 .add(rpc)
439 .add(data)
440#ifdef ENABLE_TESTS
441 .add(test)
442#endif // ENABLE_TESTS
443 ;
444
445 // Parse options, if no error.
446 try
447 {
448 po::store(
449 po::command_line_parser(argc, argv)
450 .options(all) // Parse options.
451 .positional(p) // Remainder as --parameters.
452 .run(),
453 vm);
454 po::notify(vm); // Invoke option notify functions.
455 }
456 catch (std::exception const& ex)
457 {
458 std::cerr << "rippled: " << ex.what() << std::endl;
459 std::cerr << "Try 'rippled --help' for a list of options." << std::endl;
460 return 1;
461 }
462
463 if (vm.count("help"))
464 {
465 printHelp(desc);
466 return 0;
467 }
468
469 if (vm.count("version"))
470 {
471 std::cout << "rippled version " << BuildInfo::getVersionString() << std::endl;
472#ifdef GIT_COMMIT_HASH
473 std::cout << "Git commit hash: " << GIT_COMMIT_HASH << std::endl;
474#endif
475#ifdef GIT_BRANCH
476 std::cout << "Git build branch: " << GIT_BRANCH << std::endl;
477#endif
478 return 0;
479 }
480
481#ifndef ENABLE_TESTS
482 if (vm.count("unittest") || vm.count("unittest-child"))
483 {
484 std::cerr << "rippled: Tests disabled in this build." << std::endl;
485 std::cerr << "Try 'rippled --help' for a list of options." << std::endl;
486 return 1;
487 }
488#else
489 // Run the unit tests if requested.
490 // The unit tests will exit the application with an appropriate return code.
491 //
492 if (vm.count("unittest"))
493 {
494 std::string argument;
495
496 if (vm.count("unittest-arg"))
497 argument = vm["unittest-arg"].as<std::string>();
498
499 std::size_t numJobs = 1;
500 bool unittestChild = false;
501 if (vm.count("unittest-jobs"))
502 numJobs = std::max(numJobs, vm["unittest-jobs"].as<std::size_t>());
503 unittestChild = bool(vm.count("unittest-child"));
504
505 return runUnitTests(
506 vm["unittest"].as<std::string>(),
507 argument,
508 bool(vm.count("quiet")),
509 bool(vm.count("unittest-log")),
510 unittestChild,
511 bool(vm.count("unittest-ipv6")),
512 numJobs,
513 argc,
514 argv);
515 }
516 // LCOV_EXCL_START
517 else
518 {
519 if (vm.count("unittest-jobs"))
520 {
521 // unittest jobs only makes sense with `unittest`
522 std::cerr << "rippled: '--unittest-jobs' specified without "
523 "'--unittest'.\n";
524 std::cerr << "To run the unit tests the '--unittest' option must "
525 "be present.\n";
526 return 1;
527 }
528 }
529#endif // ENABLE_TESTS
530
531 auto config = std::make_unique<Config>();
532
533 auto configFile = vm.count("conf") ? vm["conf"].as<std::string>() : std::string();
534
535 // config file, quiet flag.
536 config->setup(configFile, bool(vm.count("quiet")), bool(vm.count("silent")), bool(vm.count("standalone")));
537
538 if (vm.count("vacuum"))
539 {
540 if (config->standalone())
541 {
542 std::cerr << "vacuum not applicable in standalone mode.\n";
543 return -1;
544 }
545
546 try
547 {
548 auto setup = setup_DatabaseCon(*config);
549 if (!doVacuumDB(setup, config->journal()))
550 return -1;
551 }
552 catch (std::exception const& e)
553 {
554 std::cerr << "exception " << e.what() << " in function " << __func__ << std::endl;
555 return -1;
556 }
557
558 return 0;
559 }
560
561 if (vm.contains("force_ledger_present_range"))
562 {
563 try
564 {
565 auto const r = [&vm]() -> std::vector<std::uint32_t> {
567 boost::split(
568 strVec, vm["force_ledger_present_range"].as<std::string>(), boost::algorithm::is_any_of(","));
570 for (auto& s : strVec)
571 {
572 boost::trim(s);
573 if (!s.empty())
574 result.push_back(std::stoi(s));
575 }
576 return result;
577 }();
578
579 if (r.size() == 2)
580 {
581 if (r[0] > r[1])
582 {
583 throw std::runtime_error("Invalid force_ledger_present_range parameter");
584 }
585 config->FORCED_LEDGER_RANGE_PRESENT.emplace(r[0], r[1]);
586 }
587 else
588 {
589 throw std::runtime_error("Invalid force_ledger_present_range parameter");
590 }
591 }
592 catch (std::exception const& e)
593 {
594 std::cerr << "invalid 'force_ledger_present_range' parameter. The "
595 "parameter must be two numbers separated by a comma. "
596 "The first number must be <= the second."
597 << std::endl;
598 return -1;
599 }
600 }
601
602 if (vm.count("start"))
603 {
604 config->START_UP = Config::FRESH;
605 }
606
607 if (vm.count("import"))
608 config->doImport = true;
609
610 if (vm.count("ledger"))
611 {
612 config->START_LEDGER = vm["ledger"].as<std::string>();
613 if (vm.count("replay"))
614 {
615 config->START_UP = Config::REPLAY;
616 if (vm.count("trap_tx_hash"))
617 {
618 uint256 tmp = {};
619 auto hash = vm["trap_tx_hash"].as<std::string>();
620 if (tmp.parseHex(hash))
621 {
622 config->TRAP_TX_HASH = tmp;
623 }
624 else
625 {
626 std::cerr << "Trap parameter was ill-formed, expected "
627 "valid transaction hash but received: "
628 << hash << std::endl;
629 return -1;
630 }
631 }
632 }
633 else
634 config->START_UP = Config::LOAD;
635 }
636 else if (vm.count("ledgerfile"))
637 {
638 config->START_LEDGER = vm["ledgerfile"].as<std::string>();
639 config->START_UP = Config::LOAD_FILE;
640 }
641 else if (vm.count("load") || config->FAST_LOAD)
642 {
643 config->START_UP = Config::LOAD;
644 }
645
646 if (vm.count("trap_tx_hash") && vm.count("replay") == 0)
647 {
648 std::cerr << "Cannot use trap option without replay option" << std::endl;
649 return -1;
650 }
651
652 if (vm.count("net") && !config->FAST_LOAD)
653 {
654 if ((config->START_UP == Config::LOAD) || (config->START_UP == Config::REPLAY))
655 {
656 std::cerr << "Net and load/replay options are incompatible" << std::endl;
657 return -1;
658 }
659
660 config->START_UP = Config::NETWORK;
661 }
662
663 if (vm.count("valid"))
664 {
665 config->START_VALID = true;
666 }
667
668 // Override the RPC destination IP address. This must
669 // happen after the config file is loaded.
670 if (vm.count("rpc_ip"))
671 {
672 auto endpoint = beast::IP::Endpoint::from_string_checked(vm["rpc_ip"].as<std::string>());
673 if (!endpoint)
674 {
675 std::cerr << "Invalid rpc_ip = " << vm["rpc_ip"].as<std::string>() << "\n";
676 return -1;
677 }
678
679 if (endpoint->port() == 0)
680 {
681 std::cerr << "No port specified in rpc_ip.\n";
682 if (vm.count("rpc_port"))
683 {
684 std::cerr << "WARNING: using deprecated rpc_port param.\n";
685 try
686 {
687 endpoint = endpoint->at_port(vm["rpc_port"].as<std::uint16_t>());
688 if (endpoint->port() == 0)
689 throw std::domain_error("0");
690 }
691 catch (std::exception const& e)
692 {
693 std::cerr << "Invalid rpc_port = " << e.what() << "\n";
694 return -1;
695 }
696 }
697 else
698 return -1;
699 }
700
701 config->rpc_ip = std::move(*endpoint);
702 }
703
704 if (vm.count("quorum"))
705 {
706 try
707 {
708 config->VALIDATION_QUORUM = vm["quorum"].as<std::size_t>();
709 if (config->VALIDATION_QUORUM == std::size_t{})
710 {
711 throw std::domain_error("0");
712 }
713 }
714 catch (std::exception const& e)
715 {
716 std::cerr << "Invalid value specified for --quorum (" << e.what() << ")\n";
717 return -1;
718 }
719 }
720
721 // Construct the logs object at the configured severity
722 using namespace beast::severities;
723 Severity thresh = kInfo;
724
725 if (vm.count("quiet"))
726 thresh = kFatal;
727 else if (vm.count("verbose"))
728 thresh = kTrace;
729
730 auto logs = std::make_unique<Logs>(thresh);
731
732 // No arguments. Run server.
733 if (!vm.count("parameters"))
734 {
735 // TODO: this comment can be removed in a future release -
736 // say 1.7 or higher
737 if (config->had_trailing_comments())
738 {
739 JLOG(logs->journal("Application").warn()) << "Trailing comments were seen in your config file. "
740 << "The treatment of inline/trailing comments has changed "
741 "recently. "
742 << "Any `#` characters NOT intended to delimit comments should "
743 "be "
744 << "preceded by a \\";
745 }
746
747 // We want at least 1024 file descriptors. We'll
748 // tweak this further.
749 if (!adjustDescriptorLimit(1024, logs->journal("Application")))
750 return -1;
751
752 if (vm.count("debug"))
753 setDebugLogSink(logs->makeSink("Debug", beast::severities::kTrace));
754
755 auto app = make_Application(std::move(config), std::move(logs), std::make_unique<TimeKeeper>());
756
757 if (!app->setup(vm))
758 return -1;
759
760 // With our configuration parsed, ensure we have
761 // enough file descriptors available:
762 if (!adjustDescriptorLimit(app->fdRequired(), app->logs().journal("Application")))
763 return -1;
764
765 // Start the server
766 app->start(true /*start timers*/);
767
768 // Block until we get a stop RPC.
769 app->run();
770
771 return 0;
772 }
773
774 // We have an RPC command to process:
775 beast::setCurrentThreadName("rippled: rpc");
776 return RPCCall::fromCommandLine(*config, vm["parameters"].as<std::vector<std::string>>(), *logs);
777 // LCOV_EXCL_STOP
778}
779
780} // namespace xrpl
781
782int
783main(int argc, char** argv)
784{
785#if BOOST_OS_WINDOWS
786 {
787 // Work around for https://svn.boost.org/trac/boost/ticket/10657
788 // Reported against boost version 1.56.0. If an application's
789 // first call to GetTimeZoneInformation is from a coroutine, an
790 // unhandled exception is generated. A workaround is to call
791 // GetTimeZoneInformation at least once before launching any
792 // coroutines. At the time of this writing the _ftime call is
793 // used to initialize the timezone information.
794 struct _timeb t;
795#ifdef _INC_TIME_INL
796 _ftime_s(&t);
797#else
798 _ftime(&t);
799#endif
800 }
801#endif
802
803 atexit(&google::protobuf::ShutdownProtobufLibrary);
804
805 return xrpl::run(argc, argv);
806}
T atexit(T... args)
T begin(T... args)
T c_str(T... args)
static std::optional< Endpoint > from_string_checked(std::string const &s)
Create an Endpoint from a string.
A generic endpoint for log messages.
Definition Journal.h:41
Stream fatal() const
Definition Journal.h:325
Unit test runner interface.
Definition runner.h:24
void arg(std::string const &s)
Set the argument string.
Definition runner.h:46
Associates a unit test type with metadata.
Definition suite_info.h:20
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition base_uint.h:472
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition rpc.h:16
A class to run a subset of unit tests.
Manager for children running unit tests.
void add_failures(std::size_t failures)
T emplace_back(T... args)
T end(T... args)
T endl(T... args)
T for_each(T... args)
T is_same_v
T log(T... args)
T max(T... args)
A namespace for easy access to logging severity values.
Definition Journal.h:11
Severity
Severity level / threshold of a Journal message.
Definition Journal.h:13
void setCurrentThreadName(std::string_view newThreadName)
Changes the name of the caller thread.
STL namespace.
std::string const & getVersionString()
Server version.
Definition BuildInfo.cpp:51
int fromCommandLine(Config const &config, std::vector< std::string > const &vCmd, Logs &logs)
Definition RPCCall.cpp:1578
std::atomic< bool > envUseIPv4
Definition envconfig.cpp:9
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
int run(int argc, char **argv)
Definition Main.cpp:322
std::unique_ptr< beast::Journal::Sink > setDebugLogSink(std::unique_ptr< beast::Journal::Sink > sink)
Set the sink for the debug journal.
Definition Log.cpp:439
bool adjustDescriptorLimit(int needed, beast::Journal j)
Definition Main.cpp:59
std::unique_ptr< Application > make_Application(std::unique_ptr< Config > config, std::unique_ptr< Logs > logs, std::unique_ptr< TimeKeeper > timeKeeper)
DatabaseCon::Setup setup_DatabaseCon(Config const &c, std::optional< beast::Journal > j=std::nullopt)
static std::string const & systemName()
bool doVacuumDB(DatabaseCon::Setup const &setup, beast::Journal j)
doVacuumDB Creates, initialises, and performs cleanup on a database.
Definition Vacuum.cpp:8
void printHelp(po::options_description const &desc)
Definition Main.cpp:103
T push_back(T... args)
T reserve(T... args)
T size(T... args)
T stoi(T... args)
static std::string nodeDatabase()
static std::string importNodeDatabase()
T what(T... args)