rippled
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 <ripple/app/main/Application.h>
21 #include <ripple/app/main/DBInit.h>
22 #include <ripple/app/rdb/Vacuum.h>
23 #include <ripple/basics/Log.h>
24 #include <ripple/basics/StringUtilities.h>
25 #include <ripple/basics/contract.h>
26 #include <ripple/beast/clock/basic_seconds_clock.h>
27 #include <ripple/beast/core/CurrentThreadName.h>
28 #include <ripple/core/Config.h>
29 #include <ripple/core/ConfigSections.h>
30 #include <ripple/core/TimeKeeper.h>
31 #include <ripple/json/to_string.h>
32 #include <ripple/net/RPCCall.h>
33 #include <ripple/protocol/BuildInfo.h>
34 #include <ripple/resource/Fees.h>
35 #include <ripple/rpc/RPCHandler.h>
36 
37 #ifdef ENABLE_TESTS
38 #include <ripple/beast/unit_test/match.hpp>
39 #include <test/unit_test/multi_runner.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 namespace po = boost::program_options;
73 
74 namespace ripple {
75 
76 bool
78 {
79 #ifdef RLIMIT_NOFILE
80  // Get the current limit, then adjust it to what we need.
81  struct rlimit rl;
82 
83  int available = 0;
84 
85  if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
86  {
87  // If the limit is infinite, then we are good.
88  if (rl.rlim_cur == RLIM_INFINITY)
89  available = needed;
90  else
91  available = rl.rlim_cur;
92 
93  if (available < needed)
94  {
95  // Ignore the rlim_max, as the process may
96  // be configured to override it anyways. We
97  // ask for the number descriptors we need.
98  rl.rlim_cur = needed;
99 
100  if (setrlimit(RLIMIT_NOFILE, &rl) == 0)
101  available = rl.rlim_cur;
102  }
103  }
104 
105  if (needed > available)
106  {
107  j.fatal() << "Insufficient number of file descriptors: " << needed
108  << " are needed, but only " << available << " are available.";
109 
110  std::cerr << "Insufficient number of file descriptors: " << needed
111  << " are needed, but only " << available
112  << " are available.\n";
113 
114  return false;
115  }
116 #endif
117 
118  return true;
119 }
120 
121 void
122 printHelp(const po::options_description& desc)
123 {
124  std::cerr
125  << systemName() << "d [options] <command> <params>\n"
126  << desc << std::endl
127  << "Commands: \n"
128  " account_currencies <account> [<ledger>]\n"
129  " account_info <account>|<key> [<ledger>]\n"
130  " account_lines <account> <account>|\"\" [<ledger>]\n"
131  " account_channels <account> <account>|\"\" [<ledger>]\n"
132  " account_objects <account> [<ledger>]\n"
133  " account_offers <account>|<account_public_key> [<ledger>]\n"
134  " account_tx accountID [ledger_index_min [ledger_index_max "
135  "[limit "
136  "]]] [binary]\n"
137  " book_changes [<ledger hash|id>]\n"
138  " book_offers <taker_pays> <taker_gets> [<taker [<ledger> "
139  "[<limit> [<proof> [<marker>]]]]]\n"
140  " can_delete [<ledgerid>|<ledgerhash>|now|always|never]\n"
141  " channel_authorize <private_key> <channel_id> <drops>\n"
142  " channel_verify <public_key> <channel_id> <drops> <signature>\n"
143  " connect <ip> [<port>]\n"
144  " consensus_info\n"
145  " deposit_authorized <source_account> <destination_account> "
146  "[<ledger>]\n"
147  " download_shard [[<index> <url>]]\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  " node_to_shard [status|start|stop]\n"
164  " peers\n"
165  " ping\n"
166  " random\n"
167  " peer_reservations_add <public_key> [<description>]\n"
168  " peer_reservations_del <public_key>\n"
169  " peer_reservations_list\n"
170  " ripple ...\n"
171  " ripple_path_find <json> [<ledger>]\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]\n"
177  " stop\n"
178  " submit <tx_blob>|[<private_key> <tx_json>]\n"
179  " submit_multisigned <tx_json>\n"
180  " tx <id>\n"
181  " validation_create [<seed>|<pass_phrase>|<key>]\n"
182  " validator_info\n"
183  " validators\n"
184  " validator_list_sites\n"
185  " version\n"
186  " wallet_propose [<passphrase>]\n";
187 }
188 
189 //------------------------------------------------------------------------------
190 
191 #ifdef ENABLE_TESTS
192 /* simple unit test selector that allows a comma separated list
193  * of selectors
194  */
195 class multi_selector
196 {
197 private:
199 
200 public:
201  explicit multi_selector(std::string const& patterns = "")
202  {
204  boost::split(v, patterns, boost::algorithm::is_any_of(","));
205  selectors_.reserve(v.size());
206  std::for_each(v.begin(), v.end(), [this](std::string s) {
207  boost::trim(s);
208  if (selectors_.empty() || !s.empty())
209  selectors_.emplace_back(
210  beast::unit_test::selector::automatch, s);
211  });
212  }
213 
214  bool
215  operator()(beast::unit_test::suite_info const& s)
216  {
217  for (auto& sel : selectors_)
218  if (sel(s))
219  return true;
220  return false;
221  }
222 
224  size() const
225  {
226  return selectors_.size();
227  }
228 };
229 
230 namespace test {
232 }
233 
234 template <class Runner>
235 static bool
236 anyMissing(Runner& runner, multi_selector const& pred)
237 {
238  if (runner.tests() == 0)
239  {
240  runner.add_failures(1);
241  std::cout << "Failed: No tests run" << std::endl;
242  return true;
243  }
244  if (runner.suites() < pred.size())
245  {
246  auto const missing = pred.size() - runner.suites();
247  runner.add_failures(missing);
248  std::cout << "Failed: " << missing
249  << " filters did not match any existing test suites"
250  << std::endl;
251  return true;
252  }
253  return false;
254 }
255 
256 static int
257 runUnitTests(
258  std::string const& pattern,
259  std::string const& argument,
260  bool quiet,
261  bool log,
262  bool child,
263  bool ipv6,
264  std::size_t num_jobs,
265  int argc,
266  char** argv)
267 {
268  using namespace beast::unit_test;
269  using namespace ripple::test;
270 
271  ripple::test::envUseIPv4 = (!ipv6);
272 
273  if (!child && num_jobs == 1)
274  {
275  multi_runner_parent parent_runner;
276 
277  multi_runner_child child_runner{num_jobs, quiet, log};
278  child_runner.arg(argument);
279  multi_selector pred(pattern);
280  auto const any_failed =
281  child_runner.run_multi(pred) || anyMissing(child_runner, pred);
282 
283  if (any_failed)
284  return EXIT_FAILURE;
285  return EXIT_SUCCESS;
286  }
287  if (!child)
288  {
289  multi_runner_parent parent_runner;
291 
292  std::string const exe_name = argv[0];
294  {
295  args.reserve(argc);
296  for (int i = 1; i < argc; ++i)
297  args.emplace_back(argv[i]);
298  args.emplace_back("--unittest-child");
299  }
300 
301  for (std::size_t i = 0; i < num_jobs; ++i)
302  children.emplace_back(
303  boost::process::exe = exe_name, boost::process::args = args);
304 
305  int bad_child_exits = 0;
306  int terminated_child_exits = 0;
307  for (auto& c : children)
308  {
309  try
310  {
311  c.wait();
312  if (c.exit_code())
313  ++bad_child_exits;
314  }
315  catch (...)
316  {
317  // wait throws if process was terminated with a signal
318  ++bad_child_exits;
319  ++terminated_child_exits;
320  }
321  }
322 
323  parent_runner.add_failures(terminated_child_exits);
324  anyMissing(parent_runner, multi_selector(pattern));
325 
326  if (parent_runner.any_failed() || bad_child_exits)
327  return EXIT_FAILURE;
328  return EXIT_SUCCESS;
329  }
330  else
331  {
332  // child
333  multi_runner_child runner{num_jobs, quiet, log};
334  runner.arg(argument);
335  auto const anyFailed = runner.run_multi(multi_selector(pattern));
336 
337  if (anyFailed)
338  return EXIT_FAILURE;
339  return EXIT_SUCCESS;
340  }
341 }
342 
343 #endif // ENABLE_TESTS
344 //------------------------------------------------------------------------------
345 
346 int
347 run(int argc, char** argv)
348 {
349  using namespace std;
350 
352  "rippled: main " + BuildInfo::getVersionString());
353 
354  po::variables_map vm;
355 
356  std::string importText;
357  {
358  importText += "Import an existing node database (specified in the [";
359  importText += ConfigSection::importNodeDatabase();
360  importText += "] configuration file section) into the current ";
361  importText += "node database (specified in the [";
362  importText += ConfigSection::nodeDatabase();
363  importText += "] configuration file section).";
364  }
365 
366  // Set up option parsing.
367  //
368  po::options_description gen("General Options");
369  gen.add_options()(
370  "conf", po::value<std::string>(), "Specify the configuration file.")(
371  "debug", "Enable normally suppressed debug logging")(
372  "help,h", "Display this message.")(
373  "newnodeid", "Generate a new node identity for this server.")(
374  "nodeid",
375  po::value<std::string>(),
376  "Specify the node identity for this server.")(
377  "quorum",
378  po::value<std::size_t>(),
379  "Override the minimum validation quorum.")(
380  "reportingReadOnly", "Run in read-only reporting mode")(
381  "silent", "No output to the console after startup.")(
382  "standalone,a", "Run with no peers.")("verbose,v", "Verbose logging.")
383 
384  ("force_ledger_present_range",
385  po::value<std::string>(),
386  "Specify the range of present ledgers for testing purposes. Min and "
387  "max values are comma separated.")(
388  "version", "Display the build version.");
389 
390  po::options_description data("Ledger/Data Options");
391  data.add_options()("import", importText.c_str())(
392  "ledger",
393  po::value<std::string>(),
394  "Load the specified ledger and start from the value given.")(
395  "ledgerfile",
396  po::value<std::string>(),
397  "Load the specified ledger file.")(
398  "load", "Load the current ledger from the local DB.")(
399  "net", "Get the initial ledger from the network.")(
400  "nodetoshard", "Import node store into shards")(
401  "replay", "Replay a ledger close.")(
402  "start", "Start from a fresh Ledger.")(
403  "startReporting",
404  po::value<std::string>(),
405  "Start reporting 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  "full-name (lib.module.suite), module, or library "
434  "(checked in that "
435  "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  else
562  {
563  if (vm.count("unittest-jobs"))
564  {
565  // unittest jobs only makes sense with `unittest`
566  std::cerr << "rippled: '--unittest-jobs' specified without "
567  "'--unittest'.\n";
568  std::cerr << "To run the unit tests the '--unittest' option must "
569  "be present.\n";
570  return 1;
571  }
572  }
573 #endif // ENABLE_TESTS
574 
575  auto config = std::make_unique<Config>();
576 
577  auto configFile =
578  vm.count("conf") ? vm["conf"].as<std::string>() : std::string();
579 
580  // config file, quiet flag.
581  config->setup(
582  configFile,
583  bool(vm.count("quiet")),
584  bool(vm.count("silent")),
585  bool(vm.count("standalone")));
586 
587  if (vm.count("vacuum"))
588  {
589  if (config->standalone())
590  {
591  std::cerr << "vacuum not applicable in standalone mode.\n";
592  return -1;
593  }
594 
595  try
596  {
597  auto setup = setup_DatabaseCon(*config);
598  if (!doVacuumDB(setup))
599  return -1;
600  }
601  catch (std::exception const& e)
602  {
603  std::cerr << "exception " << e.what() << " in function " << __func__
604  << std::endl;
605  return -1;
606  }
607 
608  return 0;
609  }
610 
611  if (vm.contains("force_ledger_present_range"))
612  {
613  try
614  {
615  auto const r = [&vm]() -> std::vector<std::uint32_t> {
617  boost::split(
618  strVec,
619  vm["force_ledger_present_range"].as<std::string>(),
620  boost::algorithm::is_any_of(","));
622  for (auto& s : strVec)
623  {
624  boost::trim(s);
625  if (!s.empty())
626  result.push_back(std::stoi(s));
627  }
628  return result;
629  }();
630 
631  if (r.size() == 2)
632  {
633  if (r[0] > r[1])
634  {
635  throw std::runtime_error(
636  "Invalid force_ledger_present_range parameter");
637  }
638  config->FORCED_LEDGER_RANGE_PRESENT.emplace(r[0], r[1]);
639  }
640  else
641  {
642  throw std::runtime_error(
643  "Invalid force_ledger_present_range parameter");
644  }
645  }
646  catch (std::exception const& e)
647  {
648  std::cerr << "invalid 'force_ledger_present_range' parameter. The "
649  "parameter must be two numbers separated by a comma. "
650  "The first number must be <= the second."
651  << std::endl;
652  return -1;
653  }
654  }
655 
656  if (vm.count("start"))
657  {
658  config->START_UP = Config::FRESH;
659  }
660 
661  if (vm.count("startReporting"))
662  {
663  config->START_UP = Config::FRESH;
664  config->START_LEDGER = vm["startReporting"].as<std::string>();
665  }
666 
667  if (vm.count("reportingReadOnly"))
668  {
669  config->setReportingReadOnly(true);
670  }
671 
672  if (vm.count("import"))
673  config->doImport = true;
674 
675  if (vm.count("nodetoshard"))
676  config->nodeToShard = true;
677 
678  if (vm.count("ledger"))
679  {
680  config->START_LEDGER = vm["ledger"].as<std::string>();
681  if (vm.count("replay"))
682  config->START_UP = Config::REPLAY;
683  else
684  config->START_UP = Config::LOAD;
685  }
686  else if (vm.count("ledgerfile"))
687  {
688  config->START_LEDGER = vm["ledgerfile"].as<std::string>();
689  config->START_UP = Config::LOAD_FILE;
690  }
691  else if (vm.count("load") || config->FAST_LOAD)
692  {
693  config->START_UP = Config::LOAD;
694  }
695 
696  if (vm.count("net") && !config->FAST_LOAD)
697  {
698  if ((config->START_UP == Config::LOAD) ||
699  (config->START_UP == Config::REPLAY))
700  {
701  std::cerr << "Net and load/replay options are incompatible"
702  << std::endl;
703  return -1;
704  }
705 
706  config->START_UP = Config::NETWORK;
707  }
708 
709  if (vm.count("valid"))
710  {
711  config->START_VALID = true;
712  }
713 
714  // Override the RPC destination IP address. This must
715  // happen after the config file is loaded.
716  if (vm.count("rpc_ip"))
717  {
719  vm["rpc_ip"].as<std::string>());
720  if (!endpoint)
721  {
722  std::cerr << "Invalid rpc_ip = " << vm["rpc_ip"].as<std::string>()
723  << "\n";
724  return -1;
725  }
726 
727  if (endpoint->port() == 0)
728  {
729  std::cerr << "No port specified in rpc_ip.\n";
730  if (vm.count("rpc_port"))
731  {
732  std::cerr << "WARNING: using deprecated rpc_port param.\n";
733  try
734  {
735  endpoint =
736  endpoint->at_port(vm["rpc_port"].as<std::uint16_t>());
737  if (endpoint->port() == 0)
738  throw std::domain_error("0");
739  }
740  catch (std::exception const& e)
741  {
742  std::cerr << "Invalid rpc_port = " << e.what() << "\n";
743  return -1;
744  }
745  }
746  else
747  return -1;
748  }
749 
750  config->rpc_ip = std::move(*endpoint);
751  }
752 
753  if (vm.count("quorum"))
754  {
755  try
756  {
757  config->VALIDATION_QUORUM = vm["quorum"].as<std::size_t>();
758  if (config->VALIDATION_QUORUM == std::size_t{})
759  {
760  throw std::domain_error("0");
761  }
762  }
763  catch (std::exception const& e)
764  {
765  std::cerr << "Invalid value specified for --quorum (" << e.what()
766  << ")\n";
767  return -1;
768  }
769  }
770 
771  // Construct the logs object at the configured severity
772  using namespace beast::severities;
773  Severity thresh = kInfo;
774 
775  if (vm.count("quiet"))
776  thresh = kFatal;
777  else if (vm.count("verbose"))
778  thresh = kTrace;
779 
780  auto logs = std::make_unique<Logs>(thresh);
781 
782  // No arguments. Run server.
783  if (!vm.count("parameters"))
784  {
785  // TODO: this comment can be removed in a future release -
786  // say 1.7 or higher
787  if (config->had_trailing_comments())
788  {
789  JLOG(logs->journal("Application").warn())
790  << "Trailing comments were seen in your config file. "
791  << "The treatment of inline/trailing comments has changed "
792  "recently. "
793  << "Any `#` characters NOT intended to delimit comments should "
794  "be "
795  << "preceded by a \\";
796  }
797 
798  // We want at least 1024 file descriptors. We'll
799  // tweak this further.
800  if (!adjustDescriptorLimit(1024, logs->journal("Application")))
801  return -1;
802 
803  if (vm.count("debug"))
804  setDebugLogSink(logs->makeSink("Debug", beast::severities::kTrace));
805 
806  auto timeKeeper = make_TimeKeeper(logs->journal("TimeKeeper"));
807 
808  auto app = make_Application(
809  std::move(config), std::move(logs), std::move(timeKeeper));
810 
811  if (!app->setup(vm))
812  return -1;
813 
814  // With our configuration parsed, ensure we have
815  // enough file descriptors available:
817  app->fdRequired(), app->logs().journal("Application")))
818  return -1;
819 
820  // Start the server
821  app->start(true /*start timers*/);
822 
823  // Block until we get a stop RPC.
824  app->run();
825 
826  return 0;
827  }
828 
829  // We have an RPC command to process:
830  beast::setCurrentThreadName("rippled: rpc");
832  *config, vm["parameters"].as<std::vector<std::string>>(), *logs);
833 }
834 
835 } // namespace ripple
836 
837 int
838 main(int argc, char** argv)
839 {
840 #if BOOST_OS_WINDOWS
841  {
842  // Work around for https://svn.boost.org/trac/boost/ticket/10657
843  // Reported against boost version 1.56.0. If an application's
844  // first call to GetTimeZoneInformation is from a coroutine, an
845  // unhandled exception is generated. A workaround is to call
846  // GetTimeZoneInformation at least once before launching any
847  // coroutines. At the time of this writing the _ftime call is
848  // used to initialize the timezone information.
849  struct _timeb t;
850 #ifdef _INC_TIME_INL
851  _ftime_s(&t);
852 #else
853  _ftime(&t);
854 #endif
855  }
856 #endif
857 
858  atexit(&google::protobuf::ShutdownProtobufLibrary);
859 
860  return ripple::run(argc, argv);
861 }
beast::Journal::fatal
Stream fatal() const
Definition: Journal.h:338
beast::severities::kTrace
@ kTrace
Definition: Journal.h:34
std::for_each
T for_each(T... args)
std::domain_error
STL class.
std::string
STL class.
ripple::test::multi_runner_parent::add_failures
void add_failures(std::size_t failures)
Definition: multi_runner.cpp:497
utility
std::exception
STL class.
ripple::printHelp
void printHelp(const po::options_description &desc)
Definition: Main.cpp:122
std::vector::reserve
T reserve(T... args)
ripple::TxSearched::all
@ all
ripple::setup_DatabaseCon
DatabaseCon::Setup setup_DatabaseCon(Config const &c, std::optional< beast::Journal > j=std::nullopt)
Definition: DatabaseCon.cpp:106
std::vector
STL class.
beast::unit_test
Definition: main.cpp:31
std::vector::size
T size(T... args)
ripple::ConfigSection::importNodeDatabase
static std::string importNodeDatabase()
Definition: ConfigSections.h:43
ripple::Config::LOAD
@ LOAD
Definition: Config.h:156
beast::severities
A namespace for easy access to logging severity values.
Definition: Journal.h:29
std::cerr
iostream
std::vector::push_back
T push_back(T... args)
std::cout
stdexcept
std::stoi
T stoi(T... args)
std::atexit
T atexit(T... args)
std::log
T log(T... args)
ripple::Config::NETWORK
@ NETWORK
Definition: Config.h:156
std::string::c_str
T c_str(T... args)
ripple::setDebugLogSink
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
ripple::BuildInfo::getVersionString
std::string const & getVersionString()
Server version.
Definition: BuildInfo.cpp:65
std::runtime_error
STL class.
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
ripple::test::multi_runner_parent::any_failed
bool any_failed() const
Definition: multi_runner.cpp:479
std::atomic< bool >
beast::severities::kInfo
@ kInfo
Definition: Journal.h:36
ripple::RPCCall::fromCommandLine
int fromCommandLine(Config const &config, const std::vector< std::string > &vCmd, Logs &logs)
Definition: RPCCall.cpp:1681
ripple::test::envUseIPv4
std::atomic< bool > envUseIPv4
Definition: envconfig.cpp:36
beast::setCurrentThreadName
void setCurrentThreadName(std::string_view name)
Changes the name of the caller thread.
Definition: CurrentThreadName.cpp:119
std::vector::emplace_back
T emplace_back(T... args)
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::test
Definition: LedgerDeltaAcquire.h:35
ripple::Config::FRESH
@ FRESH
Definition: Config.h:156
cstdlib
std::endl
T endl(T... args)
beast::severities::Severity
Severity
Severity level / threshold of a Journal message.
Definition: Journal.h:31
std::vector::begin
T begin(T... args)
std
STL namespace.
ripple::Config::REPLAY
@ REPLAY
Definition: Config.h:156
ripple::make_TimeKeeper
std::unique_ptr< TimeKeeper > make_TimeKeeper(beast::Journal j)
Definition: TimeKeeper.cpp:119
ripple::test::multi_runner_child
A class to run a subset of unit tests.
Definition: multi_runner.h:254
ripple::systemName
static std::string const & systemName()
Definition: SystemParameters.h:34
std::size_t
std::vector::end
T end(T... args)
ripple::doVacuumDB
bool doVacuumDB(DatabaseCon::Setup const &setup)
doVacuumDB Creates, initialises, and performs cleanup on a database.
Definition: Vacuum.cpp:26
beast::severities::kFatal
@ kFatal
Definition: Journal.h:39
std::max
T max(T... args)
ripple::test::multi_runner_parent
Manager for children running unit tests.
Definition: multi_runner.h:219
ripple::adjustDescriptorLimit
bool adjustDescriptorLimit(int needed, beast::Journal j)
Definition: Main.cpp:77
ripple::Config::LOAD_FILE
@ LOAD_FILE
Definition: Config.h:156
std::data
T data(T... args)
beast::IP::Endpoint::from_string_checked
static std::optional< Endpoint > from_string_checked(std::string const &s)
Create an Endpoint from a string.
Definition: IPEndpoint.cpp:35
ripple::make_Application
std::unique_ptr< Application > make_Application(std::unique_ptr< Config > config, std::unique_ptr< Logs > logs, std::unique_ptr< TimeKeeper > timeKeeper)
Definition: Application.cpp:2195
ripple::PublisherStatus::available
@ available
ripple::ConfigSection::nodeDatabase
static std::string nodeDatabase()
Definition: ConfigSections.h:33
std::exception::what
T what(T... args)