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 ripple {
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 ripple::test;
252
253 ripple::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 "rippled: main " + BuildInfo::getVersionString());
336
337 po::variables_map vm;
338
339 std::string importText;
340 {
341 importText += "Import an existing node database (specified in the [";
342 importText += ConfigSection::importNodeDatabase();
343 importText += "] configuration file section) into the current ";
344 importText += "node database (specified in the [";
345 importText += ConfigSection::nodeDatabase();
346 importText += "] configuration file section).";
347 }
348
349 // Set up option parsing.
350 //
351 po::options_description gen("General Options");
352 gen.add_options()(
353 "conf", po::value<std::string>(), "Specify the configuration file.")(
354 "debug", "Enable normally suppressed debug logging")(
355 "help,h", "Display this message.")(
356 "newnodeid", "Generate a new node identity for this server.")(
357 "nodeid",
358 po::value<std::string>(),
359 "Specify the node identity for this server.")(
360 "quorum",
361 po::value<std::size_t>(),
362 "Override the minimum validation quorum.")(
363 "silent", "No output to the console after startup.")(
364 "standalone,a", "Run with no peers.")("verbose,v", "Verbose logging.")
365
366 ("force_ledger_present_range",
367 po::value<std::string>(),
368 "Specify the range of present ledgers for testing purposes. Min and "
369 "max values are comma separated.")(
370 "version", "Display the build version.");
371
372 po::options_description data("Ledger/Data Options");
373 data.add_options()("import", importText.c_str())(
374 "ledger",
375 po::value<std::string>(),
376 "Load the specified ledger and start from the value given.")(
377 "ledgerfile",
378 po::value<std::string>(),
379 "Load the specified ledger file.")(
380 "load", "Load the current ledger from the local DB.")(
381 "net", "Get the initial ledger from the network.")(
382 "replay", "Replay a ledger close.")(
383 "trap_tx_hash",
384 po::value<std::string>(),
385 "Trap a specific transaction during replay.")(
386 "start", "Start from a fresh Ledger.")(
387 "vacuum", "VACUUM the transaction db.")(
388 "valid", "Consider the initial ledger a valid network ledger.");
389
390 po::options_description rpc("RPC Client Options");
391 rpc.add_options()(
392 "rpc",
393 "Perform rpc command - see below for available commands. "
394 "This is assumed if any positional parameters are provided.")(
395 "rpc_ip",
396 po::value<std::string>(),
397 "Specify the IP address for RPC command. "
398 "Format: <ip-address>[':'<port-number>]")(
399 "rpc_port",
400 po::value<std::uint16_t>(),
401 "DEPRECATED: include with rpc_ip instead. "
402 "Specify the port number for RPC command.");
403
404#ifdef ENABLE_TESTS
405 po::options_description test("Unit Test Options");
406 test.add_options()(
407 "quiet,q",
408 "Suppress test suite messages, "
409 "including suite/case name (at start) and test log messages.")(
410 "unittest,u",
411 po::value<std::string>()->implicit_value(""),
412 "Perform unit tests. The optional argument specifies one or "
413 "more comma-separated selectors. Each selector specifies a suite name, "
414 "suite name prefix, full-name (lib.module.suite), module, or library "
415 "(checked in that order).")(
416 "unittest-arg",
417 po::value<std::string>()->implicit_value(""),
418 "Supplies an argument string to unit tests. If provided, this argument "
419 "is made available to each suite that runs. Interpretation of the "
420 "argument is handled individually by any suite that accesses it -- "
421 "as such, it typically only make sense to provide this when running "
422 "a single suite.")(
423 "unittest-ipv6",
424 "Use IPv6 localhost when running unittests (default is IPv4).")(
425 "unittest-log",
426 "Force unit test log message output. Only useful in combination with "
427 "--quiet, in which case log messages will print but suite/case names "
428 "will not.")(
429 "unittest-jobs",
430 po::value<std::size_t>(),
431 "Number of unittest jobs to run in parallel (child processes).");
432#endif // ENABLE_TESTS
433
434 // These are hidden options, not intended to be shown in the usage/help
435 // message
436 po::options_description hidden("Hidden Options");
437 hidden.add_options()(
438 "parameters",
439 po::value<vector<string>>(),
440 "Specify rpc command and parameters. This option must be repeated "
441 "for each command/param. Positional parameters also serve this "
442 "purpose, "
443 "so this option is not needed for users")
444#ifdef ENABLE_TESTS
445 ("unittest-child",
446 "For internal use only when spawning child unit test processes.")
447#else
448 ("unittest", "Disabled in this build.")(
449 "unittest-child", "Disabled in this build.")
450#endif // ENABLE_TESTS
451 ("fg", "Deprecated: server always in foreground mode.");
452
453 // Interpret positional arguments as --parameters.
454 po::positional_options_description p;
455 p.add("parameters", -1);
456
457 po::options_description all;
458 all.add(gen)
459 .add(rpc)
460 .add(data)
461#ifdef ENABLE_TESTS
462 .add(test)
463#endif // ENABLE_TESTS
464 .add(hidden);
465
466 po::options_description desc;
467 desc.add(gen)
468 .add(rpc)
469 .add(data)
470#ifdef ENABLE_TESTS
471 .add(test)
472#endif // ENABLE_TESTS
473 ;
474
475 // Parse options, if no error.
476 try
477 {
478 po::store(
479 po::command_line_parser(argc, argv)
480 .options(all) // Parse options.
481 .positional(p) // Remainder as --parameters.
482 .run(),
483 vm);
484 po::notify(vm); // Invoke option notify functions.
485 }
486 catch (std::exception const& ex)
487 {
488 std::cerr << "rippled: " << ex.what() << std::endl;
489 std::cerr << "Try 'rippled --help' for a list of options." << std::endl;
490 return 1;
491 }
492
493 if (vm.count("help"))
494 {
495 printHelp(desc);
496 return 0;
497 }
498
499 if (vm.count("version"))
500 {
501 std::cout << "rippled version " << BuildInfo::getVersionString()
502 << std::endl;
503#ifdef GIT_COMMIT_HASH
504 std::cout << "Git commit hash: " << GIT_COMMIT_HASH << std::endl;
505#endif
506#ifdef GIT_BRANCH
507 std::cout << "Git build branch: " << GIT_BRANCH << std::endl;
508#endif
509 return 0;
510 }
511
512#ifndef ENABLE_TESTS
513 if (vm.count("unittest") || vm.count("unittest-child"))
514 {
515 std::cerr << "rippled: Tests disabled in this build." << std::endl;
516 std::cerr << "Try 'rippled --help' for a list of options." << std::endl;
517 return 1;
518 }
519#else
520 // Run the unit tests if requested.
521 // The unit tests will exit the application with an appropriate return code.
522 //
523 if (vm.count("unittest"))
524 {
525 std::string argument;
526
527 if (vm.count("unittest-arg"))
528 argument = vm["unittest-arg"].as<std::string>();
529
530 std::size_t numJobs = 1;
531 bool unittestChild = false;
532 if (vm.count("unittest-jobs"))
533 numJobs = std::max(numJobs, vm["unittest-jobs"].as<std::size_t>());
534 unittestChild = bool(vm.count("unittest-child"));
535
536 return runUnitTests(
537 vm["unittest"].as<std::string>(),
538 argument,
539 bool(vm.count("quiet")),
540 bool(vm.count("unittest-log")),
541 unittestChild,
542 bool(vm.count("unittest-ipv6")),
543 numJobs,
544 argc,
545 argv);
546 }
547 // LCOV_EXCL_START
548 else
549 {
550 if (vm.count("unittest-jobs"))
551 {
552 // unittest jobs only makes sense with `unittest`
553 std::cerr << "rippled: '--unittest-jobs' specified without "
554 "'--unittest'.\n";
555 std::cerr << "To run the unit tests the '--unittest' option must "
556 "be present.\n";
557 return 1;
558 }
559 }
560#endif // ENABLE_TESTS
561
562 auto config = std::make_unique<Config>();
563
564 auto configFile =
565 vm.count("conf") ? vm["conf"].as<std::string>() : std::string();
566
567 // config file, quiet flag.
568 config->setup(
569 configFile,
570 bool(vm.count("quiet")),
571 bool(vm.count("silent")),
572 bool(vm.count("standalone")));
573
574 if (vm.count("vacuum"))
575 {
576 if (config->standalone())
577 {
578 std::cerr << "vacuum not applicable in standalone mode.\n";
579 return -1;
580 }
581
582 try
583 {
584 auto setup = setup_DatabaseCon(*config);
585 if (!doVacuumDB(setup, config->journal()))
586 return -1;
587 }
588 catch (std::exception const& e)
589 {
590 std::cerr << "exception " << e.what() << " in function " << __func__
591 << std::endl;
592 return -1;
593 }
594
595 return 0;
596 }
597
598 if (vm.contains("force_ledger_present_range"))
599 {
600 try
601 {
602 auto const r = [&vm]() -> std::vector<std::uint32_t> {
604 boost::split(
605 strVec,
606 vm["force_ledger_present_range"].as<std::string>(),
607 boost::algorithm::is_any_of(","));
609 for (auto& s : strVec)
610 {
611 boost::trim(s);
612 if (!s.empty())
613 result.push_back(std::stoi(s));
614 }
615 return result;
616 }();
617
618 if (r.size() == 2)
619 {
620 if (r[0] > r[1])
621 {
622 throw std::runtime_error(
623 "Invalid force_ledger_present_range parameter");
624 }
625 config->FORCED_LEDGER_RANGE_PRESENT.emplace(r[0], r[1]);
626 }
627 else
628 {
629 throw std::runtime_error(
630 "Invalid force_ledger_present_range parameter");
631 }
632 }
633 catch (std::exception const& e)
634 {
635 std::cerr << "invalid 'force_ledger_present_range' parameter. The "
636 "parameter must be two numbers separated by a comma. "
637 "The first number must be <= the second."
638 << std::endl;
639 return -1;
640 }
641 }
642
643 if (vm.count("start"))
644 {
645 config->START_UP = Config::FRESH;
646 }
647
648 if (vm.count("import"))
649 config->doImport = true;
650
651 if (vm.count("ledger"))
652 {
653 config->START_LEDGER = vm["ledger"].as<std::string>();
654 if (vm.count("replay"))
655 {
656 config->START_UP = Config::REPLAY;
657 if (vm.count("trap_tx_hash"))
658 {
659 uint256 tmp = {};
660 auto hash = vm["trap_tx_hash"].as<std::string>();
661 if (tmp.parseHex(hash))
662 {
663 config->TRAP_TX_HASH = tmp;
664 }
665 else
666 {
667 std::cerr << "Trap parameter was ill-formed, expected "
668 "valid transaction hash but received: "
669 << hash << std::endl;
670 return -1;
671 }
672 }
673 }
674 else
675 config->START_UP = Config::LOAD;
676 }
677 else if (vm.count("ledgerfile"))
678 {
679 config->START_LEDGER = vm["ledgerfile"].as<std::string>();
680 config->START_UP = Config::LOAD_FILE;
681 }
682 else if (vm.count("load") || config->FAST_LOAD)
683 {
684 config->START_UP = Config::LOAD;
685 }
686
687 if (vm.count("trap_tx_hash") && vm.count("replay") == 0)
688 {
689 std::cerr << "Cannot use trap option without replay option"
690 << std::endl;
691 return -1;
692 }
693
694 if (vm.count("net") && !config->FAST_LOAD)
695 {
696 if ((config->START_UP == Config::LOAD) ||
697 (config->START_UP == Config::REPLAY))
698 {
699 std::cerr << "Net and load/replay options are incompatible"
700 << std::endl;
701 return -1;
702 }
703
704 config->START_UP = Config::NETWORK;
705 }
706
707 if (vm.count("valid"))
708 {
709 config->START_VALID = true;
710 }
711
712 // Override the RPC destination IP address. This must
713 // happen after the config file is loaded.
714 if (vm.count("rpc_ip"))
715 {
717 vm["rpc_ip"].as<std::string>());
718 if (!endpoint)
719 {
720 std::cerr << "Invalid rpc_ip = " << vm["rpc_ip"].as<std::string>()
721 << "\n";
722 return -1;
723 }
724
725 if (endpoint->port() == 0)
726 {
727 std::cerr << "No port specified in rpc_ip.\n";
728 if (vm.count("rpc_port"))
729 {
730 std::cerr << "WARNING: using deprecated rpc_port param.\n";
731 try
732 {
733 endpoint =
734 endpoint->at_port(vm["rpc_port"].as<std::uint16_t>());
735 if (endpoint->port() == 0)
736 throw std::domain_error("0");
737 }
738 catch (std::exception const& e)
739 {
740 std::cerr << "Invalid rpc_port = " << e.what() << "\n";
741 return -1;
742 }
743 }
744 else
745 return -1;
746 }
747
748 config->rpc_ip = std::move(*endpoint);
749 }
750
751 if (vm.count("quorum"))
752 {
753 try
754 {
755 config->VALIDATION_QUORUM = vm["quorum"].as<std::size_t>();
756 if (config->VALIDATION_QUORUM == std::size_t{})
757 {
758 throw std::domain_error("0");
759 }
760 }
761 catch (std::exception const& e)
762 {
763 std::cerr << "Invalid value specified for --quorum (" << e.what()
764 << ")\n";
765 return -1;
766 }
767 }
768
769 // Construct the logs object at the configured severity
770 using namespace beast::severities;
771 Severity thresh = kInfo;
772
773 if (vm.count("quiet"))
774 thresh = kFatal;
775 else if (vm.count("verbose"))
776 thresh = kTrace;
777
778 auto logs = std::make_unique<Logs>(thresh);
779
780 // No arguments. Run server.
781 if (!vm.count("parameters"))
782 {
783 // TODO: this comment can be removed in a future release -
784 // say 1.7 or higher
785 if (config->had_trailing_comments())
786 {
787 JLOG(logs->journal("Application").warn())
788 << "Trailing comments were seen in your config file. "
789 << "The treatment of inline/trailing comments has changed "
790 "recently. "
791 << "Any `#` characters NOT intended to delimit comments should "
792 "be "
793 << "preceded by a \\";
794 }
795
796 // We want at least 1024 file descriptors. We'll
797 // tweak this further.
798 if (!adjustDescriptorLimit(1024, logs->journal("Application")))
799 return -1;
800
801 if (vm.count("debug"))
802 setDebugLogSink(logs->makeSink("Debug", beast::severities::kTrace));
803
804 auto app = make_Application(
805 std::move(config), std::move(logs), std::make_unique<TimeKeeper>());
806
807 if (!app->setup(vm))
808 return -1;
809
810 // With our configuration parsed, ensure we have
811 // enough file descriptors available:
813 app->fdRequired(), app->logs().journal("Application")))
814 return -1;
815
816 // Start the server
817 app->start(true /*start timers*/);
818
819 // Block until we get a stop RPC.
820 app->run();
821
822 return 0;
823 }
824
825 // We have an RPC command to process:
826 beast::setCurrentThreadName("rippled: rpc");
828 *config, vm["parameters"].as<std::vector<std::string>>(), *logs);
829 // LCOV_EXCL_STOP
830}
831
832} // namespace ripple
833
834int
835main(int argc, char** argv)
836{
837#if BOOST_OS_WINDOWS
838 {
839 // Work around for https://svn.boost.org/trac/boost/ticket/10657
840 // Reported against boost version 1.56.0. If an application's
841 // first call to GetTimeZoneInformation is from a coroutine, an
842 // unhandled exception is generated. A workaround is to call
843 // GetTimeZoneInformation at least once before launching any
844 // coroutines. At the time of this writing the _ftime call is
845 // used to initialize the timezone information.
846 struct _timeb t;
847#ifdef _INC_TIME_INL
848 _ftime_s(&t);
849#else
850 _ftime(&t);
851#endif
852 }
853#endif
854
855 atexit(&google::protobuf::ShutdownProtobufLibrary);
856
857 return ripple::run(argc, argv);
858}
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.
std::string const & getVersionString()
Server version.
Definition BuildInfo.cpp:49
int fromCommandLine(Config const &config, std::vector< std::string > const &vCmd, Logs &logs)
Definition RPCCall.cpp:1626
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
static std::string const & systemName()
DatabaseCon::Setup setup_DatabaseCon(Config const &c, std::optional< beast::Journal > j=std::nullopt)
std::unique_ptr< Application > make_Application(std::unique_ptr< Config > config, std::unique_ptr< Logs > logs, std::unique_ptr< TimeKeeper > timeKeeper)
int run(int argc, char **argv)
Definition Main.cpp:330
bool adjustDescriptorLimit(int needed, beast::Journal j)
Definition Main.cpp:59
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 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
STL namespace.
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)