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