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