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 platform 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#ifdef GIT_COMMIT_HASH
525 std::cout << "Git commit hash: " << GIT_COMMIT_HASH << std::endl;
526#endif
527#ifdef GIT_BRANCH
528 std::cout << "Git build branch: " << GIT_BRANCH << std::endl;
529#endif
530 return 0;
531 }
532
533#ifndef ENABLE_TESTS
534 if (vm.count("unittest") || vm.count("unittest-child"))
535 {
536 std::cerr << "rippled: Tests disabled in this build." << std::endl;
537 std::cerr << "Try 'rippled --help' for a list of options." << std::endl;
538 return 1;
539 }
540#else
541 // Run the unit tests if requested.
542 // The unit tests will exit the application with an appropriate return code.
543 //
544 if (vm.count("unittest"))
545 {
546 std::string argument;
547
548 if (vm.count("unittest-arg"))
549 argument = vm["unittest-arg"].as<std::string>();
550
551 std::size_t numJobs = 1;
552 bool unittestChild = false;
553 if (vm.count("unittest-jobs"))
554 numJobs = std::max(numJobs, vm["unittest-jobs"].as<std::size_t>());
555 unittestChild = bool(vm.count("unittest-child"));
556
557 return runUnitTests(
558 vm["unittest"].as<std::string>(),
559 argument,
560 bool(vm.count("quiet")),
561 bool(vm.count("unittest-log")),
562 unittestChild,
563 bool(vm.count("unittest-ipv6")),
564 numJobs,
565 argc,
566 argv);
567 }
568 // LCOV_EXCL_START
569 else
570 {
571 if (vm.count("unittest-jobs"))
572 {
573 // unittest jobs only makes sense with `unittest`
574 std::cerr << "rippled: '--unittest-jobs' specified without "
575 "'--unittest'.\n";
576 std::cerr << "To run the unit tests the '--unittest' option must "
577 "be present.\n";
578 return 1;
579 }
580 }
581#endif // ENABLE_TESTS
582
583 auto config = std::make_unique<Config>();
584
585 auto configFile =
586 vm.count("conf") ? vm["conf"].as<std::string>() : std::string();
587
588 // config file, quiet flag.
589 config->setup(
590 configFile,
591 bool(vm.count("quiet")),
592 bool(vm.count("silent")),
593 bool(vm.count("standalone")));
594
595 if (vm.count("vacuum"))
596 {
597 if (config->standalone())
598 {
599 std::cerr << "vacuum not applicable in standalone mode.\n";
600 return -1;
601 }
602
603 try
604 {
605 auto setup = setup_DatabaseCon(*config);
606 if (!doVacuumDB(setup, config->journal()))
607 return -1;
608 }
609 catch (std::exception const& e)
610 {
611 std::cerr << "exception " << e.what() << " in function " << __func__
612 << std::endl;
613 return -1;
614 }
615
616 return 0;
617 }
618
619 if (vm.contains("force_ledger_present_range"))
620 {
621 try
622 {
623 auto const r = [&vm]() -> std::vector<std::uint32_t> {
625 boost::split(
626 strVec,
627 vm["force_ledger_present_range"].as<std::string>(),
628 boost::algorithm::is_any_of(","));
630 for (auto& s : strVec)
631 {
632 boost::trim(s);
633 if (!s.empty())
634 result.push_back(std::stoi(s));
635 }
636 return result;
637 }();
638
639 if (r.size() == 2)
640 {
641 if (r[0] > r[1])
642 {
643 throw std::runtime_error(
644 "Invalid force_ledger_present_range parameter");
645 }
646 config->FORCED_LEDGER_RANGE_PRESENT.emplace(r[0], r[1]);
647 }
648 else
649 {
650 throw std::runtime_error(
651 "Invalid force_ledger_present_range parameter");
652 }
653 }
654 catch (std::exception const& e)
655 {
656 std::cerr << "invalid 'force_ledger_present_range' parameter. The "
657 "parameter must be two numbers separated by a comma. "
658 "The first number must be <= the second."
659 << std::endl;
660 return -1;
661 }
662 }
663
664 if (vm.count("start"))
665 {
666 config->START_UP = Config::FRESH;
667 }
668
669 if (vm.count("import"))
670 config->doImport = true;
671
672 if (vm.count("ledger"))
673 {
674 config->START_LEDGER = vm["ledger"].as<std::string>();
675 if (vm.count("replay"))
676 {
677 config->START_UP = Config::REPLAY;
678 if (vm.count("trap_tx_hash"))
679 {
680 uint256 tmp = {};
681 auto hash = vm["trap_tx_hash"].as<std::string>();
682 if (tmp.parseHex(hash))
683 {
684 config->TRAP_TX_HASH = tmp;
685 }
686 else
687 {
688 std::cerr << "Trap parameter was ill-formed, expected "
689 "valid transaction hash but received: "
690 << hash << std::endl;
691 return -1;
692 }
693 }
694 }
695 else
696 config->START_UP = Config::LOAD;
697 }
698 else if (vm.count("ledgerfile"))
699 {
700 config->START_LEDGER = vm["ledgerfile"].as<std::string>();
701 config->START_UP = Config::LOAD_FILE;
702 }
703 else if (vm.count("load") || config->FAST_LOAD)
704 {
705 config->START_UP = Config::LOAD;
706 }
707
708 if (vm.count("trap_tx_hash") && vm.count("replay") == 0)
709 {
710 std::cerr << "Cannot use trap option without replay option"
711 << std::endl;
712 return -1;
713 }
714
715 if (vm.count("net") && !config->FAST_LOAD)
716 {
717 if ((config->START_UP == Config::LOAD) ||
718 (config->START_UP == Config::REPLAY))
719 {
720 std::cerr << "Net and load/replay options are incompatible"
721 << std::endl;
722 return -1;
723 }
724
725 config->START_UP = Config::NETWORK;
726 }
727
728 if (vm.count("valid"))
729 {
730 config->START_VALID = true;
731 }
732
733 // Override the RPC destination IP address. This must
734 // happen after the config file is loaded.
735 if (vm.count("rpc_ip"))
736 {
738 vm["rpc_ip"].as<std::string>());
739 if (!endpoint)
740 {
741 std::cerr << "Invalid rpc_ip = " << vm["rpc_ip"].as<std::string>()
742 << "\n";
743 return -1;
744 }
745
746 if (endpoint->port() == 0)
747 {
748 std::cerr << "No port specified in rpc_ip.\n";
749 if (vm.count("rpc_port"))
750 {
751 std::cerr << "WARNING: using deprecated rpc_port param.\n";
752 try
753 {
754 endpoint =
755 endpoint->at_port(vm["rpc_port"].as<std::uint16_t>());
756 if (endpoint->port() == 0)
757 throw std::domain_error("0");
758 }
759 catch (std::exception const& e)
760 {
761 std::cerr << "Invalid rpc_port = " << e.what() << "\n";
762 return -1;
763 }
764 }
765 else
766 return -1;
767 }
768
769 config->rpc_ip = std::move(*endpoint);
770 }
771
772 if (vm.count("quorum"))
773 {
774 try
775 {
776 config->VALIDATION_QUORUM = vm["quorum"].as<std::size_t>();
777 if (config->VALIDATION_QUORUM == std::size_t{})
778 {
779 throw std::domain_error("0");
780 }
781 }
782 catch (std::exception const& e)
783 {
784 std::cerr << "Invalid value specified for --quorum (" << e.what()
785 << ")\n";
786 return -1;
787 }
788 }
789
790 // Construct the logs object at the configured severity
791 using namespace beast::severities;
792 Severity thresh = kInfo;
793
794 if (vm.count("quiet"))
795 thresh = kFatal;
796 else if (vm.count("verbose"))
797 thresh = kTrace;
798
799 auto logs = std::make_unique<Logs>(thresh);
800
801 // No arguments. Run server.
802 if (!vm.count("parameters"))
803 {
804 // TODO: this comment can be removed in a future release -
805 // say 1.7 or higher
806 if (config->had_trailing_comments())
807 {
808 JLOG(logs->journal("Application").warn())
809 << "Trailing comments were seen in your config file. "
810 << "The treatment of inline/trailing comments has changed "
811 "recently. "
812 << "Any `#` characters NOT intended to delimit comments should "
813 "be "
814 << "preceded by a \\";
815 }
816
817 // We want at least 1024 file descriptors. We'll
818 // tweak this further.
819 if (!adjustDescriptorLimit(1024, logs->journal("Application")))
820 return -1;
821
822 if (vm.count("debug"))
823 setDebugLogSink(logs->makeSink("Debug", beast::severities::kTrace));
824
825 auto app = make_Application(
826 std::move(config), std::move(logs), std::make_unique<TimeKeeper>());
827
828 if (!app->setup(vm))
829 return -1;
830
831 // With our configuration parsed, ensure we have
832 // enough file descriptors available:
834 app->fdRequired(), app->logs().journal("Application")))
835 return -1;
836
837 // Start the server
838 app->start(true /*start timers*/);
839
840 // Block until we get a stop RPC.
841 app->run();
842
843 return 0;
844 }
845
846 // We have an RPC command to process:
847 beast::setCurrentThreadName("rippled: rpc");
849 *config, vm["parameters"].as<std::vector<std::string>>(), *logs);
850 // LCOV_EXCL_STOP
851}
852
853} // namespace ripple
854
855int
856main(int argc, char** argv)
857{
858#if BOOST_OS_WINDOWS
859 {
860 // Work around for https://svn.boost.org/trac/boost/ticket/10657
861 // Reported against boost version 1.56.0. If an application's
862 // first call to GetTimeZoneInformation is from a coroutine, an
863 // unhandled exception is generated. A workaround is to call
864 // GetTimeZoneInformation at least once before launching any
865 // coroutines. At the time of this writing the _ftime call is
866 // used to initialize the timezone information.
867 struct _timeb t;
868#ifdef _INC_TIME_INL
869 _ftime_s(&t);
870#else
871 _ftime(&t);
872#endif
873 }
874#endif
875
876 atexit(&google::protobuf::ShutdownProtobufLibrary);
877
878 return ripple::run(argc, argv);
879}
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)