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