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/ThreadUtilities.h>
26 #include <ripple/basics/contract.h>
27 #include <ripple/beast/clock/basic_seconds_clock.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 
353  po::variables_map vm;
354 
355  std::string importText;
356  {
357  importText += "Import an existing node database (specified in the [";
358  importText += ConfigSection::importNodeDatabase();
359  importText += "] configuration file section) into the current ";
360  importText += "node database (specified in the [";
361  importText += ConfigSection::nodeDatabase();
362  importText += "] configuration file section).";
363  }
364 
365  // Set up option parsing.
366  //
367  po::options_description gen("General Options");
368  gen.add_options()(
369  "conf", po::value<std::string>(), "Specify the configuration file.")(
370  "debug", "Enable normally suppressed debug logging")(
371  "help,h", "Display this message.")(
372  "newnodeid", "Generate a new node identity for this server.")(
373  "nodeid",
374  po::value<std::string>(),
375  "Specify the node identity for this server.")(
376  "quorum",
377  po::value<std::size_t>(),
378  "Override the minimum validation quorum.")(
379  "reportingReadOnly", "Run in read-only reporting mode")(
380  "silent", "No output to the console after startup.")(
381  "standalone,a", "Run with no peers.")("verbose,v", "Verbose logging.")
382 
383  ("force_ledger_present_range",
384  po::value<std::string>(),
385  "Specify the range of present ledgers for testing purposes. Min and "
386  "max values are comma separated.")(
387  "version", "Display the build version.");
388 
389  po::options_description data("Ledger/Data Options");
390  data.add_options()("import", importText.c_str())(
391  "ledger",
392  po::value<std::string>(),
393  "Load the specified ledger and start from the value given.")(
394  "ledgerfile",
395  po::value<std::string>(),
396  "Load the specified ledger file.")(
397  "load", "Load the current ledger from the local DB.")(
398  "net", "Get the initial ledger from the network.")(
399  "nodetoshard", "Import node store into shards")(
400  "replay", "Replay a ledger close.")(
401  "start", "Start from a fresh Ledger.")(
402  "startReporting",
403  po::value<std::string>(),
404  "Start reporting from a fresh Ledger.")(
405  "vacuum", "VACUUM the transaction db.")(
406  "valid", "Consider the initial ledger a valid network ledger.");
407 
408  po::options_description rpc("RPC Client Options");
409  rpc.add_options()(
410  "rpc",
411  "Perform rpc command - see below for available commands. "
412  "This is assumed if any positional parameters are provided.")(
413  "rpc_ip",
414  po::value<std::string>(),
415  "Specify the IP address for RPC command. "
416  "Format: <ip-address>[':'<port-number>]")(
417  "rpc_port",
418  po::value<std::uint16_t>(),
419  "DEPRECATED: include with rpc_ip instead. "
420  "Specify the port number for RPC command.");
421 
422 #ifdef ENABLE_TESTS
423  po::options_description test("Unit Test Options");
424  test.add_options()(
425  "quiet,q",
426  "Suppress test suite messages, "
427  "including suite/case name (at start) and test log messages.")(
428  "unittest,u",
429  po::value<std::string>()->implicit_value(""),
430  "Perform unit tests. The optional argument specifies one or "
431  "more comma-separated selectors. Each selector specifies a suite name, "
432  "full-name (lib.module.suite), module, or library "
433  "(checked in that "
434  "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  return 0;
523  }
524 
525 #ifndef ENABLE_TESTS
526  if (vm.count("unittest") || vm.count("unittest-child"))
527  {
528  std::cerr << "rippled: Tests disabled in this build." << std::endl;
529  std::cerr << "Try 'rippled --help' for a list of options." << std::endl;
530  return 1;
531  }
532 #else
533  // Run the unit tests if requested.
534  // The unit tests will exit the application with an appropriate return code.
535  //
536  if (vm.count("unittest"))
537  {
538  std::string argument;
539 
540  if (vm.count("unittest-arg"))
541  argument = vm["unittest-arg"].as<std::string>();
542 
543  std::size_t numJobs = 1;
544  bool unittestChild = false;
545  if (vm.count("unittest-jobs"))
546  numJobs = std::max(numJobs, vm["unittest-jobs"].as<std::size_t>());
547  unittestChild = bool(vm.count("unittest-child"));
548 
549  return runUnitTests(
550  vm["unittest"].as<std::string>(),
551  argument,
552  bool(vm.count("quiet")),
553  bool(vm.count("unittest-log")),
554  unittestChild,
555  bool(vm.count("unittest-ipv6")),
556  numJobs,
557  argc,
558  argv);
559  }
560  else
561  {
562  if (vm.count("unittest-jobs"))
563  {
564  // unittest jobs only makes sense with `unittest`
565  std::cerr << "rippled: '--unittest-jobs' specified without "
566  "'--unittest'.\n";
567  std::cerr << "To run the unit tests the '--unittest' option must "
568  "be present.\n";
569  return 1;
570  }
571  }
572 #endif // ENABLE_TESTS
573 
574  auto config = std::make_unique<Config>();
575 
576  auto configFile =
577  vm.count("conf") ? vm["conf"].as<std::string>() : std::string();
578 
579  // config file, quiet flag.
580  config->setup(
581  configFile,
582  bool(vm.count("quiet")),
583  bool(vm.count("silent")),
584  bool(vm.count("standalone")));
585 
586  if (vm.count("vacuum"))
587  {
588  if (config->standalone())
589  {
590  std::cerr << "vacuum not applicable in standalone mode.\n";
591  return -1;
592  }
593 
594  try
595  {
596  auto setup = setup_DatabaseCon(*config);
597  if (!doVacuumDB(setup))
598  return -1;
599  }
600  catch (std::exception const& e)
601  {
602  std::cerr << "exception " << e.what() << " in function " << __func__
603  << std::endl;
604  return -1;
605  }
606 
607  return 0;
608  }
609 
610  if (vm.contains("force_ledger_present_range"))
611  {
612  try
613  {
614  auto const r = [&vm]() -> std::vector<std::uint32_t> {
616  boost::split(
617  strVec,
618  vm["force_ledger_present_range"].as<std::string>(),
619  boost::algorithm::is_any_of(","));
621  for (auto& s : strVec)
622  {
623  boost::trim(s);
624  if (!s.empty())
625  result.push_back(std::stoi(s));
626  }
627  return result;
628  }();
629 
630  if (r.size() == 2)
631  {
632  if (r[0] > r[1])
633  {
634  throw std::runtime_error(
635  "Invalid force_ledger_present_range parameter");
636  }
637  config->FORCED_LEDGER_RANGE_PRESENT.emplace(r[0], r[1]);
638  }
639  else
640  {
641  throw std::runtime_error(
642  "Invalid force_ledger_present_range parameter");
643  }
644  }
645  catch (std::exception const& e)
646  {
647  std::cerr << "invalid 'force_ledger_present_range' parameter. The "
648  "parameter must be two numbers separated by a comma. "
649  "The first number must be <= the second."
650  << std::endl;
651  return -1;
652  }
653  }
654 
655  if (vm.count("start"))
656  {
657  config->START_UP = Config::FRESH;
658  }
659 
660  if (vm.count("startReporting"))
661  {
662  config->START_UP = Config::FRESH;
663  config->START_LEDGER = vm["startReporting"].as<std::string>();
664  }
665 
666  if (vm.count("reportingReadOnly"))
667  {
668  config->setReportingReadOnly(true);
669  }
670 
671  if (vm.count("import"))
672  config->doImport = true;
673 
674  if (vm.count("nodetoshard"))
675  config->nodeToShard = true;
676 
677  if (vm.count("ledger"))
678  {
679  config->START_LEDGER = vm["ledger"].as<std::string>();
680  if (vm.count("replay"))
681  config->START_UP = Config::REPLAY;
682  else
683  config->START_UP = Config::LOAD;
684  }
685  else if (vm.count("ledgerfile"))
686  {
687  config->START_LEDGER = vm["ledgerfile"].as<std::string>();
688  config->START_UP = Config::LOAD_FILE;
689  }
690  else if (vm.count("load") || config->FAST_LOAD)
691  {
692  config->START_UP = Config::LOAD;
693  }
694 
695  if (vm.count("net") && !config->FAST_LOAD)
696  {
697  if ((config->START_UP == Config::LOAD) ||
698  (config->START_UP == Config::REPLAY))
699  {
700  std::cerr << "Net and load/replay options are incompatible"
701  << std::endl;
702  return -1;
703  }
704 
705  config->START_UP = Config::NETWORK;
706  }
707 
708  if (vm.count("valid"))
709  {
710  config->START_VALID = true;
711  }
712 
713  // Override the RPC destination IP address. This must
714  // happen after the config file is loaded.
715  if (vm.count("rpc_ip"))
716  {
718  vm["rpc_ip"].as<std::string>());
719  if (!endpoint)
720  {
721  std::cerr << "Invalid rpc_ip = " << vm["rpc_ip"].as<std::string>()
722  << "\n";
723  return -1;
724  }
725 
726  if (endpoint->port() == 0)
727  {
728  std::cerr << "No port specified in rpc_ip.\n";
729  if (vm.count("rpc_port"))
730  {
731  std::cerr << "WARNING: using deprecated rpc_port param.\n";
732  try
733  {
734  endpoint =
735  endpoint->at_port(vm["rpc_port"].as<std::uint16_t>());
736  if (endpoint->port() == 0)
737  throw std::domain_error("0");
738  }
739  catch (std::exception const& e)
740  {
741  std::cerr << "Invalid rpc_port = " << e.what() << "\n";
742  return -1;
743  }
744  }
745  else
746  return -1;
747  }
748 
749  config->rpc_ip = std::move(*endpoint);
750  }
751 
752  if (vm.count("quorum"))
753  {
754  try
755  {
756  config->VALIDATION_QUORUM = vm["quorum"].as<std::size_t>();
757  if (config->VALIDATION_QUORUM == std::size_t{})
758  {
759  throw std::domain_error("0");
760  }
761  }
762  catch (std::exception const& e)
763  {
764  std::cerr << "Invalid value specified for --quorum (" << e.what()
765  << ")\n";
766  return -1;
767  }
768  }
769 
770  // Construct the logs object at the configured severity
771  using namespace beast::severities;
772  Severity thresh = kInfo;
773 
774  if (vm.count("quiet"))
775  thresh = kFatal;
776  else if (vm.count("verbose"))
777  thresh = kTrace;
778 
779  auto logs = std::make_unique<Logs>(thresh);
780 
781  // No arguments. Run server.
782  if (!vm.count("parameters"))
783  {
784  // TODO: this comment can be removed in a future release -
785  // say 1.7 or higher
786  if (config->had_trailing_comments())
787  {
788  JLOG(logs->journal("Application").warn())
789  << "Trailing comments were seen in your config file. "
790  << "The treatment of inline/trailing comments has changed "
791  "recently. "
792  << "Any `#` characters NOT intended to delimit comments should "
793  "be "
794  << "preceded by a \\";
795  }
796 
797  // We want at least 1024 file descriptors. We'll
798  // tweak this further.
799  if (!adjustDescriptorLimit(1024, logs->journal("Application")))
800  return -1;
801 
802  if (vm.count("debug"))
803  setDebugLogSink(logs->makeSink("Debug", beast::severities::kTrace));
804 
805  auto timeKeeper = make_TimeKeeper(logs->journal("TimeKeeper"));
806 
807  auto app = make_Application(
808  std::move(config), std::move(logs), std::move(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  this_thread::set_name("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::this_thread::set_name
void set_name(std::string s)
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:1675
ripple::test::envUseIPv4
std::atomic< bool > envUseIPv4
Definition: envconfig.cpp:36
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)