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