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