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 " submit <tx_blob>|[<private_key> <tx_json>]\n"
182 " submit_multisigned <tx_json>\n"
183 " tx <id>\n"
184 " validation_create [<seed>|<pass_phrase>|<key>]\n"
185 " validator_info\n"
186 " validators\n"
187 " validator_list_sites\n"
188 " version\n"
189 " wallet_propose [<passphrase>]\n";
190}
191
192//------------------------------------------------------------------------------
193
194#ifdef ENABLE_TESTS
195/* simple unit test selector that allows a comma separated list
196 * of selectors
197 */
198class multi_selector
199{
200private:
202
203public:
204 explicit multi_selector(std::string const& patterns = "")
205 {
207 boost::split(v, patterns, boost::algorithm::is_any_of(","));
208 selectors_.reserve(v.size());
209 std::for_each(v.begin(), v.end(), [this](std::string s) {
210 boost::trim(s);
211 if (selectors_.empty() || !s.empty())
212 selectors_.emplace_back(
213 beast::unit_test::selector::automatch, s);
214 });
215 }
216
217 bool
218 operator()(beast::unit_test::suite_info const& s)
219 {
220 for (auto& sel : selectors_)
221 if (sel(s))
222 return true;
223 return false;
224 }
225
227 size() const
228 {
229 return selectors_.size();
230 }
231};
232
233namespace test {
235}
236
237template <class Runner>
238static bool
239anyMissing(Runner& runner, multi_selector const& pred)
240{
241 if (runner.tests() == 0)
242 {
243 runner.add_failures(1);
244 std::cout << "Failed: No tests run" << std::endl;
245 return true;
246 }
247 if (runner.suites() < pred.size())
248 {
249 auto const missing = pred.size() - runner.suites();
250 runner.add_failures(missing);
251 std::cout << "Failed: " << missing
252 << " filters did not match any existing test suites"
253 << std::endl;
254 return true;
255 }
256 return false;
257}
258
259static int
260runUnitTests(
261 std::string const& pattern,
262 std::string const& argument,
263 bool quiet,
264 bool log,
265 bool child,
266 bool ipv6,
267 std::size_t num_jobs,
268 int argc,
269 char** argv)
270{
271 using namespace beast::unit_test;
272 using namespace ripple::test;
273
274 ripple::test::envUseIPv4 = (!ipv6);
275
276 if (!child && num_jobs == 1)
277 {
278 multi_runner_parent parent_runner;
279
280 multi_runner_child child_runner{num_jobs, quiet, log};
281 child_runner.arg(argument);
282 multi_selector pred(pattern);
283 auto const any_failed =
284 child_runner.run_multi(pred) || anyMissing(child_runner, pred);
285
286 if (any_failed)
287 return EXIT_FAILURE;
288 return EXIT_SUCCESS;
289 }
290 if (!child)
291 {
292 multi_runner_parent parent_runner;
294
295 std::string const exe_name = argv[0];
297 {
298 args.reserve(argc);
299 for (int i = 1; i < argc; ++i)
300 args.emplace_back(argv[i]);
301 args.emplace_back("--unittest-child");
302 }
303
304 for (std::size_t i = 0; i < num_jobs; ++i)
305 children.emplace_back(
306 boost::process::exe = exe_name, boost::process::args = args);
307
308 int bad_child_exits = 0;
309 int terminated_child_exits = 0;
310 for (auto& c : children)
311 {
312 try
313 {
314 c.wait();
315 if (c.exit_code())
316 ++bad_child_exits;
317 }
318 catch (...)
319 {
320 // wait throws if process was terminated with a signal
321 ++bad_child_exits;
322 ++terminated_child_exits;
323 }
324 }
325
326 parent_runner.add_failures(terminated_child_exits);
327 anyMissing(parent_runner, multi_selector(pattern));
328
329 if (parent_runner.any_failed() || bad_child_exits)
330 return EXIT_FAILURE;
331 return EXIT_SUCCESS;
332 }
333 else
334 {
335 // child
336 multi_runner_child runner{num_jobs, quiet, log};
337 runner.arg(argument);
338 auto const anyFailed = runner.run_multi(multi_selector(pattern));
339
340 if (anyFailed)
341 return EXIT_FAILURE;
342 return EXIT_SUCCESS;
343 }
344}
345
346#endif // ENABLE_TESTS
347//------------------------------------------------------------------------------
348
349int
350run(int argc, char** argv)
351{
352 using namespace std;
353
355 "rippled: main " + BuildInfo::getVersionString());
356
357 po::variables_map vm;
358
359 std::string importText;
360 {
361 importText += "Import an existing node database (specified in the [";
362 importText += ConfigSection::importNodeDatabase();
363 importText += "] configuration file section) into the current ";
364 importText += "node database (specified in the [";
365 importText += ConfigSection::nodeDatabase();
366 importText += "] configuration file section).";
367 }
368
369 // Set up option parsing.
370 //
371 po::options_description gen("General Options");
372 gen.add_options()(
373 "conf", po::value<std::string>(), "Specify the configuration file.")(
374 "debug", "Enable normally suppressed debug logging")(
375 "help,h", "Display this message.")(
376 "newnodeid", "Generate a new node identity for this server.")(
377 "nodeid",
378 po::value<std::string>(),
379 "Specify the node identity for this server.")(
380 "quorum",
381 po::value<std::size_t>(),
382 "Override the minimum validation quorum.")(
383 "silent", "No output to the console after startup.")(
384 "standalone,a", "Run with no peers.")("verbose,v", "Verbose logging.")
385
386 ("force_ledger_present_range",
387 po::value<std::string>(),
388 "Specify the range of present ledgers for testing purposes. Min and "
389 "max values are comma separated.")(
390 "version", "Display the build version.");
391
392 po::options_description data("Ledger/Data Options");
393 data.add_options()("import", importText.c_str())(
394 "ledger",
395 po::value<std::string>(),
396 "Load the specified ledger and start from the value given.")(
397 "ledgerfile",
398 po::value<std::string>(),
399 "Load the specified ledger file.")(
400 "load", "Load the current ledger from the local DB.")(
401 "net", "Get the initial ledger from the network.")(
402 "replay", "Replay a ledger close.")(
403 "trap_tx_hash",
404 po::value<std::string>(),
405 "Trap a specific transaction during replay.")(
406 "start", "Start from a fresh Ledger.")(
407 "vacuum", "VACUUM the transaction db.")(
408 "valid", "Consider the initial ledger a valid network ledger.");
409
410 po::options_description rpc("RPC Client Options");
411 rpc.add_options()(
412 "rpc",
413 "Perform rpc command - see below for available commands. "
414 "This is assumed if any positional parameters are provided.")(
415 "rpc_ip",
416 po::value<std::string>(),
417 "Specify the IP address for RPC command. "
418 "Format: <ip-address>[':'<port-number>]")(
419 "rpc_port",
420 po::value<std::uint16_t>(),
421 "DEPRECATED: include with rpc_ip instead. "
422 "Specify the port number for RPC command.");
423
424#ifdef ENABLE_TESTS
425 po::options_description test("Unit Test Options");
426 test.add_options()(
427 "quiet,q",
428 "Suppress test suite messages, "
429 "including suite/case name (at start) and test log messages.")(
430 "unittest,u",
431 po::value<std::string>()->implicit_value(""),
432 "Perform unit tests. The optional argument specifies one or "
433 "more comma-separated selectors. Each selector specifies a suite name, "
434 "suite name prefix, full-name (lib.module.suite), module, or library "
435 "(checked in that order).")(
436 "unittest-arg",
437 po::value<std::string>()->implicit_value(""),
438 "Supplies an argument string to unit tests. If provided, this argument "
439 "is made available to each suite that runs. Interpretation of the "
440 "argument is handled individually by any suite that accesses it -- "
441 "as such, it typically only make sense to provide this when running "
442 "a single suite.")(
443 "unittest-ipv6",
444 "Use IPv6 localhost when running unittests (default is IPv4).")(
445 "unittest-log",
446 "Force unit test log message output. Only useful in combination with "
447 "--quiet, in which case log messages will print but suite/case names "
448 "will not.")(
449 "unittest-jobs",
450 po::value<std::size_t>(),
451 "Number of unittest jobs to run in parallel (child processes).");
452#endif // ENABLE_TESTS
453
454 // These are hidden options, not intended to be shown in the usage/help
455 // message
456 po::options_description hidden("Hidden Options");
457 hidden.add_options()(
458 "parameters",
459 po::value<vector<string>>(),
460 "Specify rpc command and parameters. This option must be repeated "
461 "for each command/param. Positional parameters also serve this "
462 "purpose, "
463 "so this option is not needed for users")
464#ifdef ENABLE_TESTS
465 ("unittest-child",
466 "For internal use only when spawning child unit test processes.")
467#else
468 ("unittest", "Disabled in this build.")(
469 "unittest-child", "Disabled in this build.")
470#endif // ENABLE_TESTS
471 ("fg", "Deprecated: server always in foreground mode.");
472
473 // Interpret positional arguments as --parameters.
474 po::positional_options_description p;
475 p.add("parameters", -1);
476
477 po::options_description all;
478 all.add(gen)
479 .add(rpc)
480 .add(data)
481#ifdef ENABLE_TESTS
482 .add(test)
483#endif // ENABLE_TESTS
484 .add(hidden);
485
486 po::options_description desc;
487 desc.add(gen)
488 .add(rpc)
489 .add(data)
490#ifdef ENABLE_TESTS
491 .add(test)
492#endif // ENABLE_TESTS
493 ;
494
495 // Parse options, if no error.
496 try
497 {
498 po::store(
499 po::command_line_parser(argc, argv)
500 .options(all) // Parse options.
501 .positional(p) // Remainder as --parameters.
502 .run(),
503 vm);
504 po::notify(vm); // Invoke option notify functions.
505 }
506 catch (std::exception const& ex)
507 {
508 std::cerr << "rippled: " << ex.what() << std::endl;
509 std::cerr << "Try 'rippled --help' for a list of options." << std::endl;
510 return 1;
511 }
512
513 if (vm.count("help"))
514 {
515 printHelp(desc);
516 return 0;
517 }
518
519 if (vm.count("version"))
520 {
521 std::cout << "rippled version " << BuildInfo::getVersionString()
522 << std::endl;
523 return 0;
524 }
525
526#ifndef ENABLE_TESTS
527 if (vm.count("unittest") || vm.count("unittest-child"))
528 {
529 std::cerr << "rippled: Tests disabled in this build." << std::endl;
530 std::cerr << "Try 'rippled --help' for a list of options." << std::endl;
531 return 1;
532 }
533#else
534 // Run the unit tests if requested.
535 // The unit tests will exit the application with an appropriate return code.
536 //
537 if (vm.count("unittest"))
538 {
539 std::string argument;
540
541 if (vm.count("unittest-arg"))
542 argument = vm["unittest-arg"].as<std::string>();
543
544 std::size_t numJobs = 1;
545 bool unittestChild = false;
546 if (vm.count("unittest-jobs"))
547 numJobs = std::max(numJobs, vm["unittest-jobs"].as<std::size_t>());
548 unittestChild = bool(vm.count("unittest-child"));
549
550 return runUnitTests(
551 vm["unittest"].as<std::string>(),
552 argument,
553 bool(vm.count("quiet")),
554 bool(vm.count("unittest-log")),
555 unittestChild,
556 bool(vm.count("unittest-ipv6")),
557 numJobs,
558 argc,
559 argv);
560 }
561 // LCOV_EXCL_START
562 else
563 {
564 if (vm.count("unittest-jobs"))
565 {
566 // unittest jobs only makes sense with `unittest`
567 std::cerr << "rippled: '--unittest-jobs' specified without "
568 "'--unittest'.\n";
569 std::cerr << "To run the unit tests the '--unittest' option must "
570 "be present.\n";
571 return 1;
572 }
573 }
574#endif // ENABLE_TESTS
575
576 auto config = std::make_unique<Config>();
577
578 auto configFile =
579 vm.count("conf") ? vm["conf"].as<std::string>() : std::string();
580
581 // config file, quiet flag.
582 config->setup(
583 configFile,
584 bool(vm.count("quiet")),
585 bool(vm.count("silent")),
586 bool(vm.count("standalone")));
587
588 if (vm.count("vacuum"))
589 {
590 if (config->standalone())
591 {
592 std::cerr << "vacuum not applicable in standalone mode.\n";
593 return -1;
594 }
595
596 try
597 {
598 auto setup = setup_DatabaseCon(*config);
599 if (!doVacuumDB(setup, config->journal()))
600 return -1;
601 }
602 catch (std::exception const& e)
603 {
604 std::cerr << "exception " << e.what() << " in function " << __func__
605 << std::endl;
606 return -1;
607 }
608
609 return 0;
610 }
611
612 if (vm.contains("force_ledger_present_range"))
613 {
614 try
615 {
616 auto const r = [&vm]() -> std::vector<std::uint32_t> {
618 boost::split(
619 strVec,
620 vm["force_ledger_present_range"].as<std::string>(),
621 boost::algorithm::is_any_of(","));
623 for (auto& s : strVec)
624 {
625 boost::trim(s);
626 if (!s.empty())
627 result.push_back(std::stoi(s));
628 }
629 return result;
630 }();
631
632 if (r.size() == 2)
633 {
634 if (r[0] > r[1])
635 {
636 throw std::runtime_error(
637 "Invalid force_ledger_present_range parameter");
638 }
639 config->FORCED_LEDGER_RANGE_PRESENT.emplace(r[0], r[1]);
640 }
641 else
642 {
643 throw std::runtime_error(
644 "Invalid force_ledger_present_range parameter");
645 }
646 }
647 catch (std::exception const& e)
648 {
649 std::cerr << "invalid 'force_ledger_present_range' parameter. The "
650 "parameter must be two numbers separated by a comma. "
651 "The first number must be <= the second."
652 << std::endl;
653 return -1;
654 }
655 }
656
657 if (vm.count("start"))
658 {
659 config->START_UP = Config::FRESH;
660 }
661
662 if (vm.count("import"))
663 config->doImport = true;
664
665 if (vm.count("ledger"))
666 {
667 config->START_LEDGER = vm["ledger"].as<std::string>();
668 if (vm.count("replay"))
669 {
670 config->START_UP = Config::REPLAY;
671 if (vm.count("trap_tx_hash"))
672 {
673 uint256 tmp = {};
674 auto hash = vm["trap_tx_hash"].as<std::string>();
675 if (tmp.parseHex(hash))
676 {
677 config->TRAP_TX_HASH = tmp;
678 }
679 else
680 {
681 std::cerr << "Trap parameter was ill-formed, expected "
682 "valid transaction hash but received: "
683 << hash << std::endl;
684 return -1;
685 }
686 }
687 }
688 else
689 config->START_UP = Config::LOAD;
690 }
691 else if (vm.count("ledgerfile"))
692 {
693 config->START_LEDGER = vm["ledgerfile"].as<std::string>();
694 config->START_UP = Config::LOAD_FILE;
695 }
696 else if (vm.count("load") || config->FAST_LOAD)
697 {
698 config->START_UP = Config::LOAD;
699 }
700
701 if (vm.count("trap_tx_hash") && vm.count("replay") == 0)
702 {
703 std::cerr << "Cannot use trap option without replay option"
704 << std::endl;
705 return -1;
706 }
707
708 if (vm.count("net") && !config->FAST_LOAD)
709 {
710 if ((config->START_UP == Config::LOAD) ||
711 (config->START_UP == Config::REPLAY))
712 {
713 std::cerr << "Net and load/replay options are incompatible"
714 << std::endl;
715 return -1;
716 }
717
718 config->START_UP = Config::NETWORK;
719 }
720
721 if (vm.count("valid"))
722 {
723 config->START_VALID = true;
724 }
725
726 // Override the RPC destination IP address. This must
727 // happen after the config file is loaded.
728 if (vm.count("rpc_ip"))
729 {
731 vm["rpc_ip"].as<std::string>());
732 if (!endpoint)
733 {
734 std::cerr << "Invalid rpc_ip = " << vm["rpc_ip"].as<std::string>()
735 << "\n";
736 return -1;
737 }
738
739 if (endpoint->port() == 0)
740 {
741 std::cerr << "No port specified in rpc_ip.\n";
742 if (vm.count("rpc_port"))
743 {
744 std::cerr << "WARNING: using deprecated rpc_port param.\n";
745 try
746 {
747 endpoint =
748 endpoint->at_port(vm["rpc_port"].as<std::uint16_t>());
749 if (endpoint->port() == 0)
750 throw std::domain_error("0");
751 }
752 catch (std::exception const& e)
753 {
754 std::cerr << "Invalid rpc_port = " << e.what() << "\n";
755 return -1;
756 }
757 }
758 else
759 return -1;
760 }
761
762 config->rpc_ip = std::move(*endpoint);
763 }
764
765 if (vm.count("quorum"))
766 {
767 try
768 {
769 config->VALIDATION_QUORUM = vm["quorum"].as<std::size_t>();
770 if (config->VALIDATION_QUORUM == std::size_t{})
771 {
772 throw std::domain_error("0");
773 }
774 }
775 catch (std::exception const& e)
776 {
777 std::cerr << "Invalid value specified for --quorum (" << e.what()
778 << ")\n";
779 return -1;
780 }
781 }
782
783 // Construct the logs object at the configured severity
784 using namespace beast::severities;
785 Severity thresh = kInfo;
786
787 if (vm.count("quiet"))
788 thresh = kFatal;
789 else if (vm.count("verbose"))
790 thresh = kTrace;
791
792 auto logs = std::make_unique<Logs>(thresh);
793
794 // No arguments. Run server.
795 if (!vm.count("parameters"))
796 {
797 // TODO: this comment can be removed in a future release -
798 // say 1.7 or higher
799 if (config->had_trailing_comments())
800 {
801 JLOG(logs->journal("Application").warn())
802 << "Trailing comments were seen in your config file. "
803 << "The treatment of inline/trailing comments has changed "
804 "recently. "
805 << "Any `#` characters NOT intended to delimit comments should "
806 "be "
807 << "preceded by a \\";
808 }
809
810 // We want at least 1024 file descriptors. We'll
811 // tweak this further.
812 if (!adjustDescriptorLimit(1024, logs->journal("Application")))
813 return -1;
814
815 if (vm.count("debug"))
816 setDebugLogSink(logs->makeSink("Debug", beast::severities::kTrace));
817
818 auto app = make_Application(
819 std::move(config), std::move(logs), std::make_unique<TimeKeeper>());
820
821 if (!app->setup(vm))
822 return -1;
823
824 // With our configuration parsed, ensure we have
825 // enough file descriptors available:
827 app->fdRequired(), app->logs().journal("Application")))
828 return -1;
829
830 // Start the server
831 app->start(true /*start timers*/);
832
833 // Block until we get a stop RPC.
834 app->run();
835
836 return 0;
837 }
838
839 // We have an RPC command to process:
840 beast::setCurrentThreadName("rippled: rpc");
842 *config, vm["parameters"].as<std::vector<std::string>>(), *logs);
843 // LCOV_EXCL_STOP
844}
845
846} // namespace ripple
847
848int
849main(int argc, char** argv)
850{
851#if BOOST_OS_WINDOWS
852 {
853 // Work around for https://svn.boost.org/trac/boost/ticket/10657
854 // Reported against boost version 1.56.0. If an application's
855 // first call to GetTimeZoneInformation is from a coroutine, an
856 // unhandled exception is generated. A workaround is to call
857 // GetTimeZoneInformation at least once before launching any
858 // coroutines. At the time of this writing the _ftime call is
859 // used to initialize the timezone information.
860 struct _timeb t;
861#ifdef _INC_TIME_INL
862 _ftime_s(&t);
863#else
864 _ftime(&t);
865#endif
866 }
867#endif
868
869 atexit(&google::protobuf::ShutdownProtobufLibrary);
870
871 return ripple::run(argc, argv);
872}
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:1586
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:350
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)