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>] [strict]\n"
129  " account_info <account>|<seed>|<pass_phrase>|<key> [<ledger>] "
130  "[strict]\n"
131  " account_lines <account> <account>|\"\" [<ledger>]\n"
132  " account_channels <account> <account>|\"\" [<ledger>]\n"
133  " account_objects <account> [<ledger>] [strict]\n"
134  " account_offers <account>|<account_public_key> [<ledger>] "
135  "[strict]\n"
136  " account_tx accountID [ledger_min [ledger_max [limit "
137  "[offset]]]] [binary] [count] [descending]\n"
138  " book_changes [<ledger hash|id>]\n"
139  " book_offers <taker_pays> <taker_gets> [<taker [<ledger> "
140  "[<limit> [<proof> [<marker>]]]]]\n"
141  " can_delete [<ledgerid>|<ledgerhash>|now|always|never]\n"
142  " channel_authorize <private_key> <channel_id> <drops>\n"
143  " channel_verify <public_key> <channel_id> <drops> <signature>\n"
144  " connect <ip> [<port>]\n"
145  " consensus_info\n"
146  " deposit_authorized <source_account> <destination_account> "
147  "[<ledger>]\n"
148  " download_shard [[<index> <url>]]\n"
149  " feature [<feature> [accept|reject]]\n"
150  " fetch_info [clear]\n"
151  " gateway_balances [<ledger>] <issuer_account> [ <hotwallet> [ "
152  "<hotwallet> ]]\n"
153  " get_counts\n"
154  " json <method> <json>\n"
155  " ledger [<id>|current|closed|validated] [full]\n"
156  " ledger_accept\n"
157  " ledger_cleaner\n"
158  " ledger_closed\n"
159  " ledger_current\n"
160  " ledger_request <ledger>\n"
161  " log_level [[<partition>] <severity>]\n"
162  " logrotate\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  " validators\n"
183  " validator_list_sites\n"
184  " version\n"
185  " wallet_propose [<passphrase>]\n";
186 }
187 
188 //------------------------------------------------------------------------------
189 
190 #ifdef ENABLE_TESTS
191 /* simple unit test selector that allows a comma separated list
192  * of selectors
193  */
194 class multi_selector
195 {
196 private:
198 
199 public:
200  explicit multi_selector(std::string const& patterns = "")
201  {
203  boost::split(v, patterns, boost::algorithm::is_any_of(","));
204  selectors_.reserve(v.size());
205  std::for_each(v.begin(), v.end(), [this](std::string s) {
206  boost::trim(s);
207  if (selectors_.empty() || !s.empty())
208  selectors_.emplace_back(
209  beast::unit_test::selector::automatch, s);
210  });
211  }
212 
213  bool
214  operator()(beast::unit_test::suite_info const& s)
215  {
216  for (auto& sel : selectors_)
217  if (sel(s))
218  return true;
219  return false;
220  }
221 
223  size() const
224  {
225  return selectors_.size();
226  }
227 };
228 
229 namespace test {
231 }
232 
233 template <class Runner>
234 static bool
235 anyMissing(Runner& runner, multi_selector const& pred)
236 {
237  if (runner.tests() == 0)
238  {
239  runner.add_failures(1);
240  std::cout << "Failed: No tests run" << std::endl;
241  return true;
242  }
243  if (runner.suites() < pred.size())
244  {
245  auto const missing = pred.size() - runner.suites();
246  runner.add_failures(missing);
247  std::cout << "Failed: " << missing
248  << " filters did not match any existing test suites"
249  << std::endl;
250  return true;
251  }
252  return false;
253 }
254 
255 static int
256 runUnitTests(
257  std::string const& pattern,
258  std::string const& argument,
259  bool quiet,
260  bool log,
261  bool child,
262  bool ipv6,
263  std::size_t num_jobs,
264  int argc,
265  char** argv)
266 {
267  using namespace beast::unit_test;
268  using namespace ripple::test;
269 
270  ripple::test::envUseIPv4 = (!ipv6);
271 
272  if (!child && num_jobs == 1)
273  {
274  multi_runner_parent parent_runner;
275 
276  multi_runner_child child_runner{num_jobs, quiet, log};
277  child_runner.arg(argument);
278  multi_selector pred(pattern);
279  auto const any_failed =
280  child_runner.run_multi(pred) || anyMissing(child_runner, pred);
281 
282  if (any_failed)
283  return EXIT_FAILURE;
284  return EXIT_SUCCESS;
285  }
286  if (!child)
287  {
288  multi_runner_parent parent_runner;
290 
291  std::string const exe_name = argv[0];
293  {
294  args.reserve(argc);
295  for (int i = 1; i < argc; ++i)
296  args.emplace_back(argv[i]);
297  args.emplace_back("--unittest-child");
298  }
299 
300  for (std::size_t i = 0; i < num_jobs; ++i)
301  children.emplace_back(
302  boost::process::exe = exe_name, boost::process::args = args);
303 
304  int bad_child_exits = 0;
305  int terminated_child_exits = 0;
306  for (auto& c : children)
307  {
308  try
309  {
310  c.wait();
311  if (c.exit_code())
312  ++bad_child_exits;
313  }
314  catch (...)
315  {
316  // wait throws if process was terminated with a signal
317  ++bad_child_exits;
318  ++terminated_child_exits;
319  }
320  }
321 
322  parent_runner.add_failures(terminated_child_exits);
323  anyMissing(parent_runner, multi_selector(pattern));
324 
325  if (parent_runner.any_failed() || bad_child_exits)
326  return EXIT_FAILURE;
327  return EXIT_SUCCESS;
328  }
329  else
330  {
331  // child
332  multi_runner_child runner{num_jobs, quiet, log};
333  runner.arg(argument);
334  auto const anyFailed = runner.run_multi(multi_selector(pattern));
335 
336  if (anyFailed)
337  return EXIT_FAILURE;
338  return EXIT_SUCCESS;
339  }
340 }
341 
342 #endif // ENABLE_TESTS
343 //------------------------------------------------------------------------------
344 
345 int
346 run(int argc, char** argv)
347 {
348  using namespace std;
349 
351  "rippled: main " + BuildInfo::getVersionString());
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  "quorum",
373  po::value<std::size_t>(),
374  "Override the minimum validation quorum.")(
375  "reportingReadOnly", "Run in read-only reporting mode")(
376  "silent", "No output to the console after startup.")(
377  "standalone,a", "Run with no peers.")("verbose,v", "Verbose logging.")(
378  "version", "Display the build version.");
379 
380  po::options_description data("Ledger/Data Options");
381  data.add_options()("import", importText.c_str())(
382  "ledger",
383  po::value<std::string>(),
384  "Load the specified ledger and start from the value given.")(
385  "ledgerfile",
386  po::value<std::string>(),
387  "Load the specified ledger file.")(
388  "load", "Load the current ledger from the local DB.")(
389  "net", "Get the initial ledger from the network.")(
390  "nodetoshard", "Import node store into shards")(
391  "replay", "Replay a ledger close.")(
392  "start", "Start from a fresh Ledger.")(
393  "startReporting",
394  po::value<std::string>(),
395  "Start reporting from a fresh Ledger.")(
396  "vacuum", "VACUUM the transaction db.")(
397  "valid", "Consider the initial ledger a valid network ledger.");
398 
399  po::options_description rpc("RPC Client Options");
400  rpc.add_options()(
401  "rpc",
402  "Perform rpc command - see below for available commands. "
403  "This is assumed if any positional parameters are provided.")(
404  "rpc_ip",
405  po::value<std::string>(),
406  "Specify the IP address for RPC command. "
407  "Format: <ip-address>[':'<port-number>]")(
408  "rpc_port",
409  po::value<std::uint16_t>(),
410  "DEPRECATED: include with rpc_ip instead. "
411  "Specify the port number for RPC command.");
412 
413 #ifdef ENABLE_TESTS
414  po::options_description test("Unit Test Options");
415  test.add_options()(
416  "quiet,q",
417  "Suppress test suite messages, "
418  "including suite/case name (at start) and test log messages.")(
419  "unittest,u",
420  po::value<std::string>()->implicit_value(""),
421  "Perform unit tests. The optional argument specifies one or "
422  "more comma-separated selectors. Each selector specifies a suite name, "
423  "full-name (lib.module.suite), module, or library "
424  "(checked in that "
425  "order).")(
426  "unittest-arg",
427  po::value<std::string>()->implicit_value(""),
428  "Supplies an argument string to unit tests. If provided, this argument "
429  "is made available to each suite that runs. Interpretation of the "
430  "argument is handled individually by any suite that accesses it -- "
431  "as such, it typically only make sense to provide this when running "
432  "a single suite.")(
433  "unittest-ipv6",
434  "Use IPv6 localhost when running unittests (default is IPv4).")(
435  "unittest-log",
436  "Force unit test log message output. Only useful in combination with "
437  "--quiet, in which case log messages will print but suite/case names "
438  "will not.")(
439  "unittest-jobs",
440  po::value<std::size_t>(),
441  "Number of unittest jobs to run in parallel (child processes).");
442 #endif // ENABLE_TESTS
443 
444  // These are hidden options, not intended to be shown in the usage/help
445  // message
446  po::options_description hidden("Hidden Options");
447  hidden.add_options()(
448  "parameters",
449  po::value<vector<string>>(),
450  "Specify rpc command and parameters. This option must be repeated "
451  "for each command/param. Positional parameters also serve this "
452  "purpose, "
453  "so this option is not needed for users")
454 #ifdef ENABLE_TESTS
455  ("unittest-child",
456  "For internal use only when spawning child unit test processes.")
457 #else
458  ("unittest", "Disabled in this build.")(
459  "unittest-child", "Disabled in this build.")
460 #endif // ENABLE_TESTS
461  ("fg", "Deprecated: server always in foreground mode.");
462 
463  // Interpret positional arguments as --parameters.
464  po::positional_options_description p;
465  p.add("parameters", -1);
466 
467  po::options_description all;
468  all.add(gen)
469  .add(rpc)
470  .add(data)
471 #ifdef ENABLE_TESTS
472  .add(test)
473 #endif // ENABLE_TESTS
474  .add(hidden);
475 
476  po::options_description desc;
477  desc.add(gen)
478  .add(rpc)
479  .add(data)
480 #ifdef ENABLE_TESTS
481  .add(test)
482 #endif // ENABLE_TESTS
483  ;
484 
485  // Parse options, if no error.
486  try
487  {
488  po::store(
489  po::command_line_parser(argc, argv)
490  .options(all) // Parse options.
491  .positional(p) // Remainder as --parameters.
492  .run(),
493  vm);
494  po::notify(vm); // Invoke option notify functions.
495  }
496  catch (std::exception const& ex)
497  {
498  std::cerr << "rippled: " << ex.what() << std::endl;
499  std::cerr << "Try 'rippled --help' for a list of options." << std::endl;
500  return 1;
501  }
502 
503  if (vm.count("help"))
504  {
505  printHelp(desc);
506  return 0;
507  }
508 
509  if (vm.count("version"))
510  {
511  std::cout << "rippled version " << BuildInfo::getVersionString()
512  << std::endl;
513  return 0;
514  }
515 
516 #ifndef ENABLE_TESTS
517  if (vm.count("unittest") || vm.count("unittest-child"))
518  {
519  std::cerr << "rippled: Tests disabled in this build." << std::endl;
520  std::cerr << "Try 'rippled --help' for a list of options." << std::endl;
521  return 1;
522  }
523 #else
524  // Run the unit tests if requested.
525  // The unit tests will exit the application with an appropriate return code.
526  //
527  if (vm.count("unittest"))
528  {
529  std::string argument;
530 
531  if (vm.count("unittest-arg"))
532  argument = vm["unittest-arg"].as<std::string>();
533 
534  std::size_t numJobs = 1;
535  bool unittestChild = false;
536  if (vm.count("unittest-jobs"))
537  numJobs = std::max(numJobs, vm["unittest-jobs"].as<std::size_t>());
538  unittestChild = bool(vm.count("unittest-child"));
539 
540  return runUnitTests(
541  vm["unittest"].as<std::string>(),
542  argument,
543  bool(vm.count("quiet")),
544  bool(vm.count("unittest-log")),
545  unittestChild,
546  bool(vm.count("unittest-ipv6")),
547  numJobs,
548  argc,
549  argv);
550  }
551  else
552  {
553  if (vm.count("unittest-jobs"))
554  {
555  // unittest jobs only makes sense with `unittest`
556  std::cerr << "rippled: '--unittest-jobs' specified without "
557  "'--unittest'.\n";
558  std::cerr << "To run the unit tests the '--unittest' option must "
559  "be present.\n";
560  return 1;
561  }
562  }
563 #endif // ENABLE_TESTS
564 
565  auto config = std::make_unique<Config>();
566 
567  auto configFile =
568  vm.count("conf") ? vm["conf"].as<std::string>() : std::string();
569 
570  // config file, quiet flag.
571  config->setup(
572  configFile,
573  bool(vm.count("quiet")),
574  bool(vm.count("silent")),
575  bool(vm.count("standalone")));
576 
577  if (vm.count("vacuum"))
578  {
579  if (config->standalone())
580  {
581  std::cerr << "vacuum not applicable in standalone mode.\n";
582  return -1;
583  }
584 
585  try
586  {
587  auto setup = setup_DatabaseCon(*config);
588  if (!doVacuumDB(setup))
589  return -1;
590  }
591  catch (std::exception const& e)
592  {
593  std::cerr << "exception " << e.what() << " in function " << __func__
594  << std::endl;
595  return -1;
596  }
597 
598  return 0;
599  }
600 
601  if (vm.count("start"))
602  {
603  config->START_UP = Config::FRESH;
604  }
605 
606  if (vm.count("startReporting"))
607  {
608  config->START_UP = Config::FRESH;
609  config->START_LEDGER = vm["startReporting"].as<std::string>();
610  }
611 
612  if (vm.count("reportingReadOnly"))
613  {
614  config->setReportingReadOnly(true);
615  }
616 
617  if (vm.count("import"))
618  config->doImport = true;
619 
620  if (vm.count("nodetoshard"))
621  config->nodeToShard = true;
622 
623  if (vm.count("ledger"))
624  {
625  config->START_LEDGER = vm["ledger"].as<std::string>();
626  if (vm.count("replay"))
627  config->START_UP = Config::REPLAY;
628  else
629  config->START_UP = Config::LOAD;
630  }
631  else if (vm.count("ledgerfile"))
632  {
633  config->START_LEDGER = vm["ledgerfile"].as<std::string>();
634  config->START_UP = Config::LOAD_FILE;
635  }
636  else if (vm.count("load") || config->FAST_LOAD)
637  {
638  config->START_UP = Config::LOAD;
639  }
640 
641  if (vm.count("net") && !config->FAST_LOAD)
642  {
643  if ((config->START_UP == Config::LOAD) ||
644  (config->START_UP == Config::REPLAY))
645  {
646  std::cerr << "Net and load/replay options are incompatible"
647  << std::endl;
648  return -1;
649  }
650 
651  config->START_UP = Config::NETWORK;
652  }
653 
654  if (vm.count("valid"))
655  {
656  config->START_VALID = true;
657  }
658 
659  // Override the RPC destination IP address. This must
660  // happen after the config file is loaded.
661  if (vm.count("rpc_ip"))
662  {
664  vm["rpc_ip"].as<std::string>());
665  if (!endpoint)
666  {
667  std::cerr << "Invalid rpc_ip = " << vm["rpc_ip"].as<std::string>()
668  << "\n";
669  return -1;
670  }
671 
672  if (endpoint->port() == 0)
673  {
674  std::cerr << "No port specified in rpc_ip.\n";
675  if (vm.count("rpc_port"))
676  {
677  std::cerr << "WARNING: using deprecated rpc_port param.\n";
678  try
679  {
680  endpoint =
681  endpoint->at_port(vm["rpc_port"].as<std::uint16_t>());
682  if (endpoint->port() == 0)
683  throw std::domain_error("0");
684  }
685  catch (std::exception const& e)
686  {
687  std::cerr << "Invalid rpc_port = " << e.what() << "\n";
688  return -1;
689  }
690  }
691  else
692  return -1;
693  }
694 
695  config->rpc_ip = std::move(*endpoint);
696  }
697 
698  if (vm.count("quorum"))
699  {
700  try
701  {
702  config->VALIDATION_QUORUM = vm["quorum"].as<std::size_t>();
703  if (config->VALIDATION_QUORUM == std::size_t{})
704  {
705  throw std::domain_error("0");
706  }
707  }
708  catch (std::exception const& e)
709  {
710  std::cerr << "Invalid value specified for --quorum (" << e.what()
711  << ")\n";
712  return -1;
713  }
714  }
715 
716  // Construct the logs object at the configured severity
717  using namespace beast::severities;
718  Severity thresh = kInfo;
719 
720  if (vm.count("quiet"))
721  thresh = kFatal;
722  else if (vm.count("verbose"))
723  thresh = kTrace;
724 
725  auto logs = std::make_unique<Logs>(thresh);
726 
727  // No arguments. Run server.
728  if (!vm.count("parameters"))
729  {
730  // TODO: this comment can be removed in a future release -
731  // say 1.7 or higher
732  if (config->had_trailing_comments())
733  {
734  JLOG(logs->journal("Application").warn())
735  << "Trailing comments were seen in your config file. "
736  << "The treatment of inline/trailing comments has changed "
737  "recently. "
738  << "Any `#` characters NOT intended to delimit comments should "
739  "be "
740  << "preceded by a \\";
741  }
742 
743  // We want at least 1024 file descriptors. We'll
744  // tweak this further.
745  if (!adjustDescriptorLimit(1024, logs->journal("Application")))
746  return -1;
747 
748  if (vm.count("debug"))
749  setDebugLogSink(logs->makeSink("Debug", beast::severities::kTrace));
750 
751  auto timeKeeper = make_TimeKeeper(logs->journal("TimeKeeper"));
752 
753  auto app = make_Application(
754  std::move(config), std::move(logs), std::move(timeKeeper));
755 
756  if (!app->setup())
757  return -1;
758 
759  // With our configuration parsed, ensure we have
760  // enough file descriptors available:
762  app->fdRequired(), app->logs().journal("Application")))
763  return -1;
764 
765  // Start the server
766  app->start(true /*start timers*/);
767 
768  // Block until we get a stop RPC.
769  app->run();
770 
771  return 0;
772  }
773 
774  // We have an RPC command to process:
775  beast::setCurrentThreadName("rippled: rpc");
777  *config, vm["parameters"].as<std::vector<std::string>>(), *logs);
778 }
779 
780 } // namespace ripple
781 
782 int
783 main(int argc, char** argv)
784 {
785 #if BOOST_OS_WINDOWS
786  {
787  // Work around for https://svn.boost.org/trac/boost/ticket/10657
788  // Reported against boost version 1.56.0. If an application's
789  // first call to GetTimeZoneInformation is from a coroutine, an
790  // unhandled exception is generated. A workaround is to call
791  // GetTimeZoneInformation at least once before launching any
792  // coroutines. At the time of this writing the _ftime call is
793  // used to initialize the timezone information.
794  struct _timeb t;
795 #ifdef _INC_TIME_INL
796  _ftime_s(&t);
797 #else
798  _ftime(&t);
799 #endif
800  }
801 #endif
802 
803  atexit(&google::protobuf::ShutdownProtobufLibrary);
804 
805  return ripple::run(argc, argv);
806 }
beast::Journal::fatal
Stream fatal() const
Definition: Journal.h:339
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:502
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:132
beast::severities
A namespace for easy access to logging severity values.
Definition: Journal.h:29
std::cerr
iostream
std::cout
stdexcept
std::atexit
T atexit(T... args)
std::log
T log(T... args)
ripple::Config::NETWORK
@ NETWORK
Definition: Config.h:132
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
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:484
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:1684
ripple::test::envUseIPv4
std::atomic< bool > envUseIPv4
Definition: envconfig.cpp:34
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:132
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:132
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:132
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:2155
ripple::PublisherStatus::available
@ available
ripple::ConfigSection::nodeDatabase
static std::string nodeDatabase()
Definition: ConfigSections.h:33
std::exception::what
T what(T... args)