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  "version", "Display the build version.");
384 
385  po::options_description data("Ledger/Data Options");
386  data.add_options()("import", importText.c_str())(
387  "ledger",
388  po::value<std::string>(),
389  "Load the specified ledger and start from the value given.")(
390  "ledgerfile",
391  po::value<std::string>(),
392  "Load the specified ledger file.")(
393  "load", "Load the current ledger from the local DB.")(
394  "net", "Get the initial ledger from the network.")(
395  "nodetoshard", "Import node store into shards")(
396  "replay", "Replay a ledger close.")(
397  "start", "Start from a fresh Ledger.")(
398  "startReporting",
399  po::value<std::string>(),
400  "Start reporting from a fresh Ledger.")(
401  "vacuum", "VACUUM the transaction db.")(
402  "valid", "Consider the initial ledger a valid network ledger.");
403 
404  po::options_description rpc("RPC Client Options");
405  rpc.add_options()(
406  "rpc",
407  "Perform rpc command - see below for available commands. "
408  "This is assumed if any positional parameters are provided.")(
409  "rpc_ip",
410  po::value<std::string>(),
411  "Specify the IP address for RPC command. "
412  "Format: <ip-address>[':'<port-number>]")(
413  "rpc_port",
414  po::value<std::uint16_t>(),
415  "DEPRECATED: include with rpc_ip instead. "
416  "Specify the port number for RPC command.");
417 
418 #ifdef ENABLE_TESTS
419  po::options_description test("Unit Test Options");
420  test.add_options()(
421  "quiet,q",
422  "Suppress test suite messages, "
423  "including suite/case name (at start) and test log messages.")(
424  "unittest,u",
425  po::value<std::string>()->implicit_value(""),
426  "Perform unit tests. The optional argument specifies one or "
427  "more comma-separated selectors. Each selector specifies a suite name, "
428  "full-name (lib.module.suite), module, or library "
429  "(checked in that "
430  "order).")(
431  "unittest-arg",
432  po::value<std::string>()->implicit_value(""),
433  "Supplies an argument string to unit tests. If provided, this argument "
434  "is made available to each suite that runs. Interpretation of the "
435  "argument is handled individually by any suite that accesses it -- "
436  "as such, it typically only make sense to provide this when running "
437  "a single suite.")(
438  "unittest-ipv6",
439  "Use IPv6 localhost when running unittests (default is IPv4).")(
440  "unittest-log",
441  "Force unit test log message output. Only useful in combination with "
442  "--quiet, in which case log messages will print but suite/case names "
443  "will not.")(
444  "unittest-jobs",
445  po::value<std::size_t>(),
446  "Number of unittest jobs to run in parallel (child processes).");
447 #endif // ENABLE_TESTS
448 
449  // These are hidden options, not intended to be shown in the usage/help
450  // message
451  po::options_description hidden("Hidden Options");
452  hidden.add_options()(
453  "parameters",
454  po::value<vector<string>>(),
455  "Specify rpc command and parameters. This option must be repeated "
456  "for each command/param. Positional parameters also serve this "
457  "purpose, "
458  "so this option is not needed for users")
459 #ifdef ENABLE_TESTS
460  ("unittest-child",
461  "For internal use only when spawning child unit test processes.")
462 #else
463  ("unittest", "Disabled in this build.")(
464  "unittest-child", "Disabled in this build.")
465 #endif // ENABLE_TESTS
466  ("fg", "Deprecated: server always in foreground mode.");
467 
468  // Interpret positional arguments as --parameters.
469  po::positional_options_description p;
470  p.add("parameters", -1);
471 
472  po::options_description all;
473  all.add(gen)
474  .add(rpc)
475  .add(data)
476 #ifdef ENABLE_TESTS
477  .add(test)
478 #endif // ENABLE_TESTS
479  .add(hidden);
480 
481  po::options_description desc;
482  desc.add(gen)
483  .add(rpc)
484  .add(data)
485 #ifdef ENABLE_TESTS
486  .add(test)
487 #endif // ENABLE_TESTS
488  ;
489 
490  // Parse options, if no error.
491  try
492  {
493  po::store(
494  po::command_line_parser(argc, argv)
495  .options(all) // Parse options.
496  .positional(p) // Remainder as --parameters.
497  .run(),
498  vm);
499  po::notify(vm); // Invoke option notify functions.
500  }
501  catch (std::exception const& ex)
502  {
503  std::cerr << "rippled: " << ex.what() << std::endl;
504  std::cerr << "Try 'rippled --help' for a list of options." << std::endl;
505  return 1;
506  }
507 
508  if (vm.count("help"))
509  {
510  printHelp(desc);
511  return 0;
512  }
513 
514  if (vm.count("version"))
515  {
516  std::cout << "rippled version " << BuildInfo::getVersionString()
517  << std::endl;
518  return 0;
519  }
520 
521 #ifndef ENABLE_TESTS
522  if (vm.count("unittest") || vm.count("unittest-child"))
523  {
524  std::cerr << "rippled: Tests disabled in this build." << std::endl;
525  std::cerr << "Try 'rippled --help' for a list of options." << std::endl;
526  return 1;
527  }
528 #else
529  // Run the unit tests if requested.
530  // The unit tests will exit the application with an appropriate return code.
531  //
532  if (vm.count("unittest"))
533  {
534  std::string argument;
535 
536  if (vm.count("unittest-arg"))
537  argument = vm["unittest-arg"].as<std::string>();
538 
539  std::size_t numJobs = 1;
540  bool unittestChild = false;
541  if (vm.count("unittest-jobs"))
542  numJobs = std::max(numJobs, vm["unittest-jobs"].as<std::size_t>());
543  unittestChild = bool(vm.count("unittest-child"));
544 
545  return runUnitTests(
546  vm["unittest"].as<std::string>(),
547  argument,
548  bool(vm.count("quiet")),
549  bool(vm.count("unittest-log")),
550  unittestChild,
551  bool(vm.count("unittest-ipv6")),
552  numJobs,
553  argc,
554  argv);
555  }
556  else
557  {
558  if (vm.count("unittest-jobs"))
559  {
560  // unittest jobs only makes sense with `unittest`
561  std::cerr << "rippled: '--unittest-jobs' specified without "
562  "'--unittest'.\n";
563  std::cerr << "To run the unit tests the '--unittest' option must "
564  "be present.\n";
565  return 1;
566  }
567  }
568 #endif // ENABLE_TESTS
569 
570  auto config = std::make_unique<Config>();
571 
572  auto configFile =
573  vm.count("conf") ? vm["conf"].as<std::string>() : std::string();
574 
575  // config file, quiet flag.
576  config->setup(
577  configFile,
578  bool(vm.count("quiet")),
579  bool(vm.count("silent")),
580  bool(vm.count("standalone")));
581 
582  if (vm.count("vacuum"))
583  {
584  if (config->standalone())
585  {
586  std::cerr << "vacuum not applicable in standalone mode.\n";
587  return -1;
588  }
589 
590  try
591  {
592  auto setup = setup_DatabaseCon(*config);
593  if (!doVacuumDB(setup))
594  return -1;
595  }
596  catch (std::exception const& e)
597  {
598  std::cerr << "exception " << e.what() << " in function " << __func__
599  << std::endl;
600  return -1;
601  }
602 
603  return 0;
604  }
605 
606  if (vm.count("start"))
607  {
608  config->START_UP = Config::FRESH;
609  }
610 
611  if (vm.count("startReporting"))
612  {
613  config->START_UP = Config::FRESH;
614  config->START_LEDGER = vm["startReporting"].as<std::string>();
615  }
616 
617  if (vm.count("reportingReadOnly"))
618  {
619  config->setReportingReadOnly(true);
620  }
621 
622  if (vm.count("import"))
623  config->doImport = true;
624 
625  if (vm.count("nodetoshard"))
626  config->nodeToShard = true;
627 
628  if (vm.count("ledger"))
629  {
630  config->START_LEDGER = vm["ledger"].as<std::string>();
631  if (vm.count("replay"))
632  config->START_UP = Config::REPLAY;
633  else
634  config->START_UP = Config::LOAD;
635  }
636  else if (vm.count("ledgerfile"))
637  {
638  config->START_LEDGER = vm["ledgerfile"].as<std::string>();
639  config->START_UP = Config::LOAD_FILE;
640  }
641  else if (vm.count("load") || config->FAST_LOAD)
642  {
643  config->START_UP = Config::LOAD;
644  }
645 
646  if (vm.count("net") && !config->FAST_LOAD)
647  {
648  if ((config->START_UP == Config::LOAD) ||
649  (config->START_UP == Config::REPLAY))
650  {
651  std::cerr << "Net and load/replay options are incompatible"
652  << std::endl;
653  return -1;
654  }
655 
656  config->START_UP = Config::NETWORK;
657  }
658 
659  if (vm.count("valid"))
660  {
661  config->START_VALID = true;
662  }
663 
664  // Override the RPC destination IP address. This must
665  // happen after the config file is loaded.
666  if (vm.count("rpc_ip"))
667  {
669  vm["rpc_ip"].as<std::string>());
670  if (!endpoint)
671  {
672  std::cerr << "Invalid rpc_ip = " << vm["rpc_ip"].as<std::string>()
673  << "\n";
674  return -1;
675  }
676 
677  if (endpoint->port() == 0)
678  {
679  std::cerr << "No port specified in rpc_ip.\n";
680  if (vm.count("rpc_port"))
681  {
682  std::cerr << "WARNING: using deprecated rpc_port param.\n";
683  try
684  {
685  endpoint =
686  endpoint->at_port(vm["rpc_port"].as<std::uint16_t>());
687  if (endpoint->port() == 0)
688  throw std::domain_error("0");
689  }
690  catch (std::exception const& e)
691  {
692  std::cerr << "Invalid rpc_port = " << e.what() << "\n";
693  return -1;
694  }
695  }
696  else
697  return -1;
698  }
699 
700  config->rpc_ip = std::move(*endpoint);
701  }
702 
703  if (vm.count("quorum"))
704  {
705  try
706  {
707  config->VALIDATION_QUORUM = vm["quorum"].as<std::size_t>();
708  if (config->VALIDATION_QUORUM == std::size_t{})
709  {
710  throw std::domain_error("0");
711  }
712  }
713  catch (std::exception const& e)
714  {
715  std::cerr << "Invalid value specified for --quorum (" << e.what()
716  << ")\n";
717  return -1;
718  }
719  }
720 
721  // Construct the logs object at the configured severity
722  using namespace beast::severities;
723  Severity thresh = kInfo;
724 
725  if (vm.count("quiet"))
726  thresh = kFatal;
727  else if (vm.count("verbose"))
728  thresh = kTrace;
729 
730  auto logs = std::make_unique<Logs>(thresh);
731 
732  // No arguments. Run server.
733  if (!vm.count("parameters"))
734  {
735  // TODO: this comment can be removed in a future release -
736  // say 1.7 or higher
737  if (config->had_trailing_comments())
738  {
739  JLOG(logs->journal("Application").warn())
740  << "Trailing comments were seen in your config file. "
741  << "The treatment of inline/trailing comments has changed "
742  "recently. "
743  << "Any `#` characters NOT intended to delimit comments should "
744  "be "
745  << "preceded by a \\";
746  }
747 
748  // We want at least 1024 file descriptors. We'll
749  // tweak this further.
750  if (!adjustDescriptorLimit(1024, logs->journal("Application")))
751  return -1;
752 
753  if (vm.count("debug"))
754  setDebugLogSink(logs->makeSink("Debug", beast::severities::kTrace));
755 
756  auto timeKeeper = make_TimeKeeper(logs->journal("TimeKeeper"));
757 
758  auto app = make_Application(
759  std::move(config), std::move(logs), std::move(timeKeeper));
760 
761  if (!app->setup(vm))
762  return -1;
763 
764  // With our configuration parsed, ensure we have
765  // enough file descriptors available:
767  app->fdRequired(), app->logs().journal("Application")))
768  return -1;
769 
770  // Start the server
771  app->start(true /*start timers*/);
772 
773  // Block until we get a stop RPC.
774  app->run();
775 
776  return 0;
777  }
778 
779  // We have an RPC command to process:
780  beast::setCurrentThreadName("rippled: rpc");
782  *config, vm["parameters"].as<std::vector<std::string>>(), *logs);
783 }
784 
785 } // namespace ripple
786 
787 int
788 main(int argc, char** argv)
789 {
790 #if BOOST_OS_WINDOWS
791  {
792  // Work around for https://svn.boost.org/trac/boost/ticket/10657
793  // Reported against boost version 1.56.0. If an application's
794  // first call to GetTimeZoneInformation is from a coroutine, an
795  // unhandled exception is generated. A workaround is to call
796  // GetTimeZoneInformation at least once before launching any
797  // coroutines. At the time of this writing the _ftime call is
798  // used to initialize the timezone information.
799  struct _timeb t;
800 #ifdef _INC_TIME_INL
801  _ftime_s(&t);
802 #else
803  _ftime(&t);
804 #endif
805  }
806 #endif
807 
808  atexit(&google::protobuf::ShutdownProtobufLibrary);
809 
810  return ripple::run(argc, argv);
811 }
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: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:153
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:153
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: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:1670
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:153
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:153
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:153
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:2181
ripple::PublisherStatus::available
@ available
ripple::ConfigSection::nodeDatabase
static std::string nodeDatabase()
Definition: ConfigSections.h:33
std::exception::what
T what(T... args)