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