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