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_definitions [<hash>]\n"
173  " server_info [counters]\n"
174  " server_state [counters]\n"
175  " sign <private_key> <tx_json> [offline]\n"
176  " sign_for <signer_address> <signer_private_key> <tx_json> "
177  "[offline]\n"
178  " stop\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  */
196 class multi_selector
197 {
198 private:
200 
201 public:
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 
231 namespace test {
233 }
234 
235 template <class Runner>
236 static bool
237 anyMissing(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 
257 static int
258 runUnitTests(
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::exe = exe_name, boost::process::args = args);
305 
306  int bad_child_exits = 0;
307  int terminated_child_exits = 0;
308  for (auto& c : children)
309  {
310  try
311  {
312  c.wait();
313  if (c.exit_code())
314  ++bad_child_exits;
315  }
316  catch (...)
317  {
318  // wait throws if process was terminated with a signal
319  ++bad_child_exits;
320  ++terminated_child_exits;
321  }
322  }
323 
324  parent_runner.add_failures(terminated_child_exits);
325  anyMissing(parent_runner, multi_selector(pattern));
326 
327  if (parent_runner.any_failed() || bad_child_exits)
328  return EXIT_FAILURE;
329  return EXIT_SUCCESS;
330  }
331  else
332  {
333  // child
334  multi_runner_child runner{num_jobs, quiet, log};
335  runner.arg(argument);
336  auto const anyFailed = runner.run_multi(multi_selector(pattern));
337 
338  if (anyFailed)
339  return EXIT_FAILURE;
340  return EXIT_SUCCESS;
341  }
342 }
343 
344 #endif // ENABLE_TESTS
345 //------------------------------------------------------------------------------
346 
347 int
348 run(int argc, char** argv)
349 {
350  using namespace std;
351 
353  "rippled: main " + BuildInfo::getVersionString());
354 
355  po::variables_map vm;
356 
357  std::string importText;
358  {
359  importText += "Import an existing node database (specified in the [";
360  importText += ConfigSection::importNodeDatabase();
361  importText += "] configuration file section) into the current ";
362  importText += "node database (specified in the [";
363  importText += ConfigSection::nodeDatabase();
364  importText += "] configuration file section).";
365  }
366 
367  // Set up option parsing.
368  //
369  po::options_description gen("General Options");
370  gen.add_options()(
371  "conf", po::value<std::string>(), "Specify the configuration file.")(
372  "debug", "Enable normally suppressed debug logging")(
373  "help,h", "Display this message.")(
374  "newnodeid", "Generate a new node identity for this server.")(
375  "nodeid",
376  po::value<std::string>(),
377  "Specify the node identity for this server.")(
378  "quorum",
379  po::value<std::size_t>(),
380  "Override the minimum validation quorum.")(
381  "reportingReadOnly", "Run in read-only reporting mode")(
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  "nodetoshard", "Import node store into shards")(
402  "replay", "Replay a ledger close.")(
403  "start", "Start from a fresh Ledger.")(
404  "startReporting",
405  po::value<std::string>(),
406  "Start reporting 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  "full-name (lib.module.suite), module, or library "
435  "(checked in that "
436  "order).")(
437  "unittest-arg",
438  po::value<std::string>()->implicit_value(""),
439  "Supplies an argument string to unit tests. If provided, this argument "
440  "is made available to each suite that runs. Interpretation of the "
441  "argument is handled individually by any suite that accesses it -- "
442  "as such, it typically only make sense to provide this when running "
443  "a single suite.")(
444  "unittest-ipv6",
445  "Use IPv6 localhost when running unittests (default is IPv4).")(
446  "unittest-log",
447  "Force unit test log message output. Only useful in combination with "
448  "--quiet, in which case log messages will print but suite/case names "
449  "will not.")(
450  "unittest-jobs",
451  po::value<std::size_t>(),
452  "Number of unittest jobs to run in parallel (child processes).");
453 #endif // ENABLE_TESTS
454 
455  // These are hidden options, not intended to be shown in the usage/help
456  // message
457  po::options_description hidden("Hidden Options");
458  hidden.add_options()(
459  "parameters",
460  po::value<vector<string>>(),
461  "Specify rpc command and parameters. This option must be repeated "
462  "for each command/param. Positional parameters also serve this "
463  "purpose, "
464  "so this option is not needed for users")
465 #ifdef ENABLE_TESTS
466  ("unittest-child",
467  "For internal use only when spawning child unit test processes.")
468 #else
469  ("unittest", "Disabled in this build.")(
470  "unittest-child", "Disabled in this build.")
471 #endif // ENABLE_TESTS
472  ("fg", "Deprecated: server always in foreground mode.");
473 
474  // Interpret positional arguments as --parameters.
475  po::positional_options_description p;
476  p.add("parameters", -1);
477 
478  po::options_description all;
479  all.add(gen)
480  .add(rpc)
481  .add(data)
482 #ifdef ENABLE_TESTS
483  .add(test)
484 #endif // ENABLE_TESTS
485  .add(hidden);
486 
487  po::options_description desc;
488  desc.add(gen)
489  .add(rpc)
490  .add(data)
491 #ifdef ENABLE_TESTS
492  .add(test)
493 #endif // ENABLE_TESTS
494  ;
495 
496  // Parse options, if no error.
497  try
498  {
499  po::store(
500  po::command_line_parser(argc, argv)
501  .options(all) // Parse options.
502  .positional(p) // Remainder as --parameters.
503  .run(),
504  vm);
505  po::notify(vm); // Invoke option notify functions.
506  }
507  catch (std::exception const& ex)
508  {
509  std::cerr << "rippled: " << ex.what() << std::endl;
510  std::cerr << "Try 'rippled --help' for a list of options." << std::endl;
511  return 1;
512  }
513 
514  if (vm.count("help"))
515  {
516  printHelp(desc);
517  return 0;
518  }
519 
520  if (vm.count("version"))
521  {
522  std::cout << "rippled version " << BuildInfo::getVersionString()
523  << std::endl;
524  return 0;
525  }
526 
527 #ifndef ENABLE_TESTS
528  if (vm.count("unittest") || vm.count("unittest-child"))
529  {
530  std::cerr << "rippled: Tests disabled in this build." << std::endl;
531  std::cerr << "Try 'rippled --help' for a list of options." << std::endl;
532  return 1;
533  }
534 #else
535  // Run the unit tests if requested.
536  // The unit tests will exit the application with an appropriate return code.
537  //
538  if (vm.count("unittest"))
539  {
540  std::string argument;
541 
542  if (vm.count("unittest-arg"))
543  argument = vm["unittest-arg"].as<std::string>();
544 
545  std::size_t numJobs = 1;
546  bool unittestChild = false;
547  if (vm.count("unittest-jobs"))
548  numJobs = std::max(numJobs, vm["unittest-jobs"].as<std::size_t>());
549  unittestChild = bool(vm.count("unittest-child"));
550 
551  return runUnitTests(
552  vm["unittest"].as<std::string>(),
553  argument,
554  bool(vm.count("quiet")),
555  bool(vm.count("unittest-log")),
556  unittestChild,
557  bool(vm.count("unittest-ipv6")),
558  numJobs,
559  argc,
560  argv);
561  }
562  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))
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("startReporting"))
663  {
664  config->START_UP = Config::FRESH;
665  config->START_LEDGER = vm["startReporting"].as<std::string>();
666  }
667 
668  if (vm.count("reportingReadOnly"))
669  {
670  config->setReportingReadOnly(true);
671  }
672 
673  if (vm.count("import"))
674  config->doImport = true;
675 
676  if (vm.count("nodetoshard"))
677  config->nodeToShard = true;
678 
679  if (vm.count("ledger"))
680  {
681  config->START_LEDGER = vm["ledger"].as<std::string>();
682  if (vm.count("replay"))
683  config->START_UP = Config::REPLAY;
684  else
685  config->START_UP = Config::LOAD;
686  }
687  else if (vm.count("ledgerfile"))
688  {
689  config->START_LEDGER = vm["ledgerfile"].as<std::string>();
690  config->START_UP = Config::LOAD_FILE;
691  }
692  else if (vm.count("load") || config->FAST_LOAD)
693  {
694  config->START_UP = Config::LOAD;
695  }
696 
697  if (vm.count("net") && !config->FAST_LOAD)
698  {
699  if ((config->START_UP == Config::LOAD) ||
700  (config->START_UP == Config::REPLAY))
701  {
702  std::cerr << "Net and load/replay options are incompatible"
703  << std::endl;
704  return -1;
705  }
706 
707  config->START_UP = Config::NETWORK;
708  }
709 
710  if (vm.count("valid"))
711  {
712  config->START_VALID = true;
713  }
714 
715  // Override the RPC destination IP address. This must
716  // happen after the config file is loaded.
717  if (vm.count("rpc_ip"))
718  {
720  vm["rpc_ip"].as<std::string>());
721  if (!endpoint)
722  {
723  std::cerr << "Invalid rpc_ip = " << vm["rpc_ip"].as<std::string>()
724  << "\n";
725  return -1;
726  }
727 
728  if (endpoint->port() == 0)
729  {
730  std::cerr << "No port specified in rpc_ip.\n";
731  if (vm.count("rpc_port"))
732  {
733  std::cerr << "WARNING: using deprecated rpc_port param.\n";
734  try
735  {
736  endpoint =
737  endpoint->at_port(vm["rpc_port"].as<std::uint16_t>());
738  if (endpoint->port() == 0)
739  throw std::domain_error("0");
740  }
741  catch (std::exception const& e)
742  {
743  std::cerr << "Invalid rpc_port = " << e.what() << "\n";
744  return -1;
745  }
746  }
747  else
748  return -1;
749  }
750 
751  config->rpc_ip = std::move(*endpoint);
752  }
753 
754  if (vm.count("quorum"))
755  {
756  try
757  {
758  config->VALIDATION_QUORUM = vm["quorum"].as<std::size_t>();
759  if (config->VALIDATION_QUORUM == std::size_t{})
760  {
761  throw std::domain_error("0");
762  }
763  }
764  catch (std::exception const& e)
765  {
766  std::cerr << "Invalid value specified for --quorum (" << e.what()
767  << ")\n";
768  return -1;
769  }
770  }
771 
772  // Construct the logs object at the configured severity
773  using namespace beast::severities;
774  Severity thresh = kInfo;
775 
776  if (vm.count("quiet"))
777  thresh = kFatal;
778  else if (vm.count("verbose"))
779  thresh = kTrace;
780 
781  auto logs = std::make_unique<Logs>(thresh);
782 
783  // No arguments. Run server.
784  if (!vm.count("parameters"))
785  {
786  // TODO: this comment can be removed in a future release -
787  // say 1.7 or higher
788  if (config->had_trailing_comments())
789  {
790  JLOG(logs->journal("Application").warn())
791  << "Trailing comments were seen in your config file. "
792  << "The treatment of inline/trailing comments has changed "
793  "recently. "
794  << "Any `#` characters NOT intended to delimit comments should "
795  "be "
796  << "preceded by a \\";
797  }
798 
799  // We want at least 1024 file descriptors. We'll
800  // tweak this further.
801  if (!adjustDescriptorLimit(1024, logs->journal("Application")))
802  return -1;
803 
804  if (vm.count("debug"))
805  setDebugLogSink(logs->makeSink("Debug", beast::severities::kTrace));
806 
807  auto app = make_Application(
808  std::move(config), std::move(logs), std::make_unique<TimeKeeper>());
809 
810  if (!app->setup(vm))
811  return -1;
812 
813  // With our configuration parsed, ensure we have
814  // enough file descriptors available:
816  app->fdRequired(), app->logs().journal("Application")))
817  return -1;
818 
819  // Start the server
820  app->start(true /*start timers*/);
821 
822  // Block until we get a stop RPC.
823  app->run();
824 
825  return 0;
826  }
827 
828  // We have an RPC command to process:
829  beast::setCurrentThreadName("rippled: rpc");
831  *config, vm["parameters"].as<std::vector<std::string>>(), *logs);
832 }
833 
834 } // namespace ripple
835 
836 int
837 main(int argc, char** argv)
838 {
839 #if BOOST_OS_WINDOWS
840  {
841  // Work around for https://svn.boost.org/trac/boost/ticket/10657
842  // Reported against boost version 1.56.0. If an application's
843  // first call to GetTimeZoneInformation is from a coroutine, an
844  // unhandled exception is generated. A workaround is to call
845  // GetTimeZoneInformation at least once before launching any
846  // coroutines. At the time of this writing the _ftime call is
847  // used to initialize the timezone information.
848  struct _timeb t;
849 #ifdef _INC_TIME_INL
850  _ftime_s(&t);
851 #else
852  _ftime(&t);
853 #endif
854  }
855 #endif
856 
857  atexit(&google::protobuf::ShutdownProtobufLibrary);
858 
859  return ripple::run(argc, argv);
860 }
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:158
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:158
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:1696
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:158
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:158
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:158
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)