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