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