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