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/basics/Log.h>
23 #include <ripple/basics/StringUtilities.h>
24 #include <ripple/basics/contract.h>
25 #include <ripple/beast/clock/basic_seconds_clock.h>
26 #include <ripple/beast/core/CurrentThreadName.h>
27 #include <ripple/core/Config.h>
28 #include <ripple/core/ConfigSections.h>
29 #include <ripple/core/DatabaseCon.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 #include <beast/unit_test/match.hpp>
38 #include <test/unit_test/multi_runner.h>
39 
40 #include <google/protobuf/stubs/common.h>
41 
42 #include <boost/filesystem.hpp>
43 #include <boost/predef.h>
44 #include <boost/process.hpp>
45 #include <boost/program_options.hpp>
46 
47 #include <cstdlib>
48 #include <iostream>
49 #include <stdexcept>
50 #include <utility>
51 
52 #if BOOST_OS_WINDOWS
53 #include <sys/timeb.h>
54 #include <sys/types.h>
55 #endif
56 
57 // Do we know the plaform we're compiling on? If you're adding new platforms
58 // modify this check accordingly.
59 #if !BOOST_OS_LINUX && !BOOST_OS_WINDOWS && !BOOST_OS_MACOS
60 #error Supported platforms are: Linux, Windows and MacOS
61 #endif
62 
63 // Ensure that precisely one platform is detected.
64 #if (BOOST_OS_LINUX && (BOOST_OS_WINDOWS || BOOST_OS_MACOS)) || \
65  (BOOST_OS_MACOS && (BOOST_OS_WINDOWS || BOOST_OS_LINUX)) || \
66  (BOOST_OS_WINDOWS && (BOOST_OS_LINUX || BOOST_OS_MACOS))
67 #error Multiple supported platforms appear active at once
68 #endif
69 
70 namespace po = boost::program_options;
71 
72 namespace ripple {
73 
74 bool
76 {
77 #ifdef RLIMIT_NOFILE
78  // Get the current limit, then adjust it to what we need.
79  struct rlimit rl;
80 
81  int available = 0;
82 
83  if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
84  {
85  // If the limit is infinite, then we are good.
86  if (rl.rlim_cur == RLIM_INFINITY)
87  available = needed;
88  else
89  available = rl.rlim_cur;
90 
91  if (available < needed)
92  {
93  // Ignore the rlim_max, as the process may
94  // be configured to override it anyways. We
95  // ask for the number descriptors we need.
96  rl.rlim_cur = needed;
97 
98  if (setrlimit(RLIMIT_NOFILE, &rl) == 0)
99  available = rl.rlim_cur;
100  }
101  }
102 
103  if (needed > available)
104  {
105  j.fatal() << "Insufficient number of file descriptors: " << needed
106  << " are needed, but only " << available << " are available.";
107 
108  std::cerr << "Insufficient number of file descriptors: " << needed
109  << " are needed, but only " << available
110  << " are available.\n";
111 
112  return false;
113  }
114 #endif
115 
116  return true;
117 }
118 
119 void
120 printHelp(const po::options_description& desc)
121 {
122  std::cerr
123  << systemName() << "d [options] <command> <params>\n"
124  << desc << std::endl
125  << "Commands: \n"
126  " account_currencies <account> [<ledger>] [strict]\n"
127  " account_info <account>|<seed>|<pass_phrase>|<key> [<ledger>] "
128  "[strict]\n"
129  " account_lines <account> <account>|\"\" [<ledger>]\n"
130  " account_channels <account> <account>|\"\" [<ledger>]\n"
131  " account_objects <account> [<ledger>] [strict]\n"
132  " account_offers <account>|<account_public_key> [<ledger>] "
133  "[strict]\n"
134  " account_tx accountID [ledger_min [ledger_max [limit "
135  "[offset]]]] [binary] [count] [descending]\n"
136  " book_offers <taker_pays> <taker_gets> [<taker [<ledger> "
137  "[<limit> [<proof> [<marker>]]]]]\n"
138  " can_delete [<ledgerid>|<ledgerhash>|now|always|never]\n"
139  " channel_authorize <private_key> <channel_id> <drops>\n"
140  " channel_verify <public_key> <channel_id> <drops> <signature>\n"
141  " connect <ip> [<port>]\n"
142  " consensus_info\n"
143  " deposit_authorized <source_account> <destination_account> "
144  "[<ledger>]\n"
145  " download_shard [[<index> <url>]]\n"
146  " feature [<feature> [accept|reject]]\n"
147  " fetch_info [clear]\n"
148  " gateway_balances [<ledger>] <issuer_account> [ <hotwallet> [ "
149  "<hotwallet> ]]\n"
150  " get_counts\n"
151  " json <method> <json>\n"
152  " ledger [<id>|current|closed|validated] [full]\n"
153  " ledger_accept\n"
154  " ledger_cleaner\n"
155  " ledger_closed\n"
156  " ledger_current\n"
157  " ledger_request <ledger>\n"
158  " log_level [[<partition>] <severity>]\n"
159  " logrotate \n"
160  " peers\n"
161  " ping\n"
162  " random\n"
163  " peer_reservations_add <public_key> [<description>]\n"
164  " peer_reservations_del <public_key>\n"
165  " peer_reservations_list\n"
166  " ripple ...\n"
167  " ripple_path_find <json> [<ledger>]\n"
168  " server_info [counters]\n"
169  " server_state [counters]\n"
170  " sign <private_key> <tx_json> [offline]\n"
171  " sign_for <signer_address> <signer_private_key> <tx_json> "
172  "[offline]\n"
173  " stop\n"
174  " submit <tx_blob>|[<private_key> <tx_json>]\n"
175  " submit_multisigned <tx_json>\n"
176  " tx <id>\n"
177  " validation_create [<seed>|<pass_phrase>|<key>]\n"
178  " validators\n"
179  " validator_list_sites\n"
180  " version\n"
181  " wallet_propose [<passphrase>]\n";
182 }
183 
184 //------------------------------------------------------------------------------
185 
186 /* simple unit test selector that allows a comma separated list
187  * of selectors
188  */
189 class multi_selector
190 {
191 private:
193 
194 public:
195  explicit multi_selector(std::string const& patterns = "")
196  {
198  boost::split(v, patterns, boost::algorithm::is_any_of(","));
199  selectors_.reserve(v.size());
200  std::for_each(v.begin(), v.end(), [this](std::string s) {
201  boost::trim(s);
202  if (selectors_.empty() || !s.empty())
203  selectors_.emplace_back(
204  beast::unit_test::selector::automatch, s);
205  });
206  }
207 
208  bool
209  operator()(beast::unit_test::suite_info const& s)
210  {
211  for (auto& sel : selectors_)
212  if (sel(s))
213  return true;
214  return false;
215  }
216 
218  size() const
219  {
220  return selectors_.size();
221  }
222 };
223 
224 namespace test {
226 }
227 
228 template <class Runner>
229 static bool
230 anyMissing(Runner& runner, multi_selector const& pred)
231 {
232  if (runner.tests() == 0)
233  {
234  runner.add_failures(1);
235  std::cout << "Failed: No tests run" << std::endl;
236  return true;
237  }
238  if (runner.suites() < pred.size())
239  {
240  auto const missing = pred.size() - runner.suites();
241  runner.add_failures(missing);
242  std::cout << "Failed: " << missing
243  << " filters did not match any existing test suites"
244  << std::endl;
245  return true;
246  }
247  return false;
248 }
249 
250 static int
251 runUnitTests(
252  std::string const& pattern,
253  std::string const& argument,
254  bool quiet,
255  bool log,
256  bool child,
257  bool ipv6,
258  std::size_t num_jobs,
259  int argc,
260  char** argv)
261 {
262  using namespace beast::unit_test;
263  using namespace ripple::test;
264 
265  ripple::test::envUseIPv4 = (!ipv6);
266 
267  if (!child && num_jobs == 1)
268  {
269  multi_runner_parent parent_runner;
270 
271  multi_runner_child child_runner{num_jobs, quiet, log};
272  child_runner.arg(argument);
273  multi_selector pred(pattern);
274  auto const any_failed =
275  child_runner.run_multi(pred) || anyMissing(child_runner, pred);
276 
277  if (any_failed)
278  return EXIT_FAILURE;
279  return EXIT_SUCCESS;
280  }
281  if (!child)
282  {
283  multi_runner_parent parent_runner;
285 
286  std::string const exe_name = argv[0];
288  {
289  args.reserve(argc);
290  for (int i = 1; i < argc; ++i)
291  args.emplace_back(argv[i]);
292  args.emplace_back("--unittest-child");
293  }
294 
295  for (std::size_t i = 0; i < num_jobs; ++i)
296  children.emplace_back(
297  boost::process::exe = exe_name, boost::process::args = args);
298 
299  int bad_child_exits = 0;
300  int terminated_child_exits = 0;
301  for (auto& c : children)
302  {
303  try
304  {
305  c.wait();
306  if (c.exit_code())
307  ++bad_child_exits;
308  }
309  catch (...)
310  {
311  // wait throws if process was terminated with a signal
312  ++bad_child_exits;
313  ++terminated_child_exits;
314  }
315  }
316 
317  parent_runner.add_failures(terminated_child_exits);
318  anyMissing(parent_runner, multi_selector(pattern));
319 
320  if (parent_runner.any_failed() || bad_child_exits)
321  return EXIT_FAILURE;
322  return EXIT_SUCCESS;
323  }
324  else
325  {
326  // child
327  multi_runner_child runner{num_jobs, quiet, log};
328  runner.arg(argument);
329  auto const anyFailed = runner.run_multi(multi_selector(pattern));
330 
331  if (anyFailed)
332  return EXIT_FAILURE;
333  return EXIT_SUCCESS;
334  }
335 }
336 
337 //------------------------------------------------------------------------------
338 
339 int
340 run(int argc, char** argv)
341 {
342  using namespace std;
343 
345  "rippled: main " + BuildInfo::getVersionString());
346 
347  po::variables_map vm;
348 
349  std::string importText;
350  {
351  importText += "Import an existing node database (specified in the [";
352  importText += ConfigSection::importNodeDatabase();
353  importText += "] configuration file section) into the current ";
354  importText += "node database (specified in the [";
355  importText += ConfigSection::nodeDatabase();
356  importText += "] configuration file section).";
357  }
358 
359  // Set up option parsing.
360  //
361  po::options_description gen("General Options");
362  gen.add_options()(
363  "conf", po::value<std::string>(), "Specify the configuration file.")(
364  "debug", "Enable normally suppressed debug logging")(
365  "help,h", "Display this message.")(
366  "quorum",
367  po::value<std::size_t>(),
368  "Override the minimum validation quorum.")(
369  "silent", "No output to the console after startup.")(
370  "standalone,a", "Run with no peers.")("verbose,v", "Verbose logging.")(
371  "version", "Display the build version.");
372 
373  po::options_description data("Ledger/Data Options");
374  data.add_options()("import", importText.c_str())(
375  "ledger",
376  po::value<std::string>(),
377  "Load the specified ledger and start from the value given.")(
378  "ledgerfile",
379  po::value<std::string>(),
380  "Load the specified ledger file.")(
381  "load", "Load the current ledger from the local DB.")(
382  "net", "Get the initial ledger from the network.")(
383  "nodetoshard", "Import node store into shards")(
384  "replay", "Replay a ledger close.")(
385  "start", "Start from a fresh Ledger.")(
386  "vacuum", "VACUUM the transaction db.")(
387  "valid", "Consider the initial ledger a valid network ledger.");
388 
389  po::options_description rpc("RPC Client Options");
390  rpc.add_options()(
391  "rpc",
392  "Perform rpc command - see below for available commands. "
393  "This is assumed if any positional parameters are provided.")(
394  "rpc_ip",
395  po::value<std::string>(),
396  "Specify the IP address for RPC command. "
397  "Format: <ip-address>[':'<port-number>]")(
398  "rpc_port",
399  po::value<std::uint16_t>(),
400  "DEPRECATED: include with rpc_ip instead. "
401  "Specify the port number for RPC command.");
402 
403  po::options_description test("Unit Test Options");
404  test.add_options()(
405  "quiet,q",
406  "Suppress test suite messages, "
407  "including suite/case name (at start) and test log messages.")(
408  "unittest,u",
409  po::value<std::string>()->implicit_value(""),
410  "Perform unit tests. The optional argument specifies one or "
411  "more comma-separated selectors. Each selector specifies a suite name, "
412  "full-name (lib.module.suite), module, or library "
413  "(checked in that "
414  "order).")(
415  "unittest-arg",
416  po::value<std::string>()->implicit_value(""),
417  "Supplies an argument string to unit tests. If provided, this argument "
418  "is made available to each suite that runs. Interpretation of the "
419  "argument is handled individually by any suite that accesses it -- "
420  "as such, it typically only make sense to provide this when running "
421  "a single suite.")(
422  "unittest-ipv6",
423  "Use IPv6 localhost when running unittests (default is IPv4).")(
424  "unittest-log",
425  "Force unit test log message output. Only useful in combination with "
426  "--quiet, in which case log messages will print but suite/case names "
427  "will not.")(
428  "unittest-jobs",
429  po::value<std::size_t>(),
430  "Number of unittest jobs to run in parallel (child processes).");
431 
432  // These are hidden options, not intended to be shown in the usage/help
433  // message
434  po::options_description hidden("Hidden Options");
435  hidden.add_options()(
436  "parameters",
437  po::value<vector<string>>(),
438  "Specify rpc command and parameters. This option must be repeated "
439  "for each command/param. Positional parameters also serve this "
440  "purpose, "
441  "so this option is not needed for users")(
442  "unittest-child",
443  "For internal use only when spawning child unit test processes.")(
444  "fg", "Deprecated: server always in foreground mode.");
445 
446  // Interpret positional arguments as --parameters.
447  po::positional_options_description p;
448  p.add("parameters", -1);
449 
450  po::options_description all;
451  all.add(gen).add(rpc).add(data).add(test).add(hidden);
452 
453  po::options_description desc;
454  desc.add(gen).add(rpc).add(data).add(test);
455 
456  // Parse options, if no error.
457  try
458  {
459  po::store(
460  po::command_line_parser(argc, argv)
461  .options(all) // Parse options.
462  .positional(p) // Remainder as --parameters.
463  .run(),
464  vm);
465  po::notify(vm); // Invoke option notify functions.
466  }
467  catch (std::exception const& ex)
468  {
469  std::cerr << "rippled: " << ex.what() << std::endl;
470  std::cerr << "Try 'rippled --help' for a list of options." << std::endl;
471  return 1;
472  }
473 
474  if (vm.count("help"))
475  {
476  printHelp(desc);
477  return 0;
478  }
479 
480  if (vm.count("version"))
481  {
482  std::cout << "rippled version " << BuildInfo::getVersionString()
483  << std::endl;
484  return 0;
485  }
486 
487  // Run the unit tests if requested.
488  // The unit tests will exit the application with an appropriate return code.
489  //
490  if (vm.count("unittest"))
491  {
492  std::string argument;
493 
494  if (vm.count("unittest-arg"))
495  argument = vm["unittest-arg"].as<std::string>();
496 
497  std::size_t numJobs = 1;
498  bool unittestChild = false;
499  if (vm.count("unittest-jobs"))
500  numJobs = std::max(numJobs, vm["unittest-jobs"].as<std::size_t>());
501  unittestChild = bool(vm.count("unittest-child"));
502 
503  return runUnitTests(
504  vm["unittest"].as<std::string>(),
505  argument,
506  bool(vm.count("quiet")),
507  bool(vm.count("unittest-log")),
508  unittestChild,
509  bool(vm.count("unittest-ipv6")),
510  numJobs,
511  argc,
512  argv);
513  }
514  else
515  {
516  if (vm.count("unittest-jobs"))
517  {
518  // unittest jobs only makes sense with `unittest`
519  std::cerr << "rippled: '--unittest-jobs' specified without "
520  "'--unittest'.\n";
521  std::cerr << "To run the unit tests the '--unittest' option must "
522  "be present.\n";
523  return 1;
524  }
525  }
526 
527  auto config = std::make_unique<Config>();
528 
529  auto configFile =
530  vm.count("conf") ? vm["conf"].as<std::string>() : std::string();
531 
532  // config file, quiet flag.
533  config->setup(
534  configFile,
535  bool(vm.count("quiet")),
536  bool(vm.count("silent")),
537  bool(vm.count("standalone")));
538 
539  if (vm.count("vacuum"))
540  {
541  if (config->standalone())
542  {
543  std::cerr << "vacuum not applicable in standalone mode.\n";
544  return -1;
545  }
546 
547  using namespace boost::filesystem;
548  DatabaseCon::Setup const dbSetup = setup_DatabaseCon(*config);
549  path dbPath = dbSetup.dataDir / TxDBName;
550 
551  try
552  {
553  uintmax_t const dbSize = file_size(dbPath);
554  assert(dbSize != static_cast<uintmax_t>(-1));
555 
556  if (auto available = space(dbPath.parent_path()).available;
557  available < dbSize)
558  {
559  std::cerr << "The database filesystem must have at least as "
560  "much free space as the size of "
561  << dbPath.string() << ", which is " << dbSize
562  << " bytes. Only " << available
563  << " bytes are available.\n";
564  return -1;
565  }
566 
567  auto txnDB = std::make_unique<DatabaseCon>(
568  dbSetup, TxDBName, TxDBPragma, TxDBInit);
569  auto& session = txnDB->getSession();
570  std::uint32_t pageSize;
571 
572  // Only the most trivial databases will fit in memory on typical
573  // (recommended) software. Force temp files to be written to disk
574  // regardless of the config settings.
575  session << boost::format(CommonDBPragmaTemp) % "file";
576  session << "PRAGMA page_size;", soci::into(pageSize);
577 
578  std::cout << "VACUUM beginning. page_size: " << pageSize
579  << std::endl;
580 
581  session << "VACUUM;";
582  assert(dbSetup.globalPragma);
583  for (auto const& p : *dbSetup.globalPragma)
584  session << p;
585  session << "PRAGMA page_size;", soci::into(pageSize);
586 
587  std::cout << "VACUUM finished. page_size: " << pageSize
588  << std::endl;
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  config->START_UP = Config::FRESH;
602 
603  if (vm.count("import"))
604  config->doImport = true;
605 
606  if (vm.count("nodetoshard"))
607  config->nodeToShard = true;
608 
609  if (vm.count("ledger"))
610  {
611  config->START_LEDGER = vm["ledger"].as<std::string>();
612  if (vm.count("replay"))
613  config->START_UP = Config::REPLAY;
614  else
615  config->START_UP = Config::LOAD;
616  }
617  else if (vm.count("ledgerfile"))
618  {
619  config->START_LEDGER = vm["ledgerfile"].as<std::string>();
620  config->START_UP = Config::LOAD_FILE;
621  }
622  else if (vm.count("load"))
623  {
624  config->START_UP = Config::LOAD;
625  }
626 
627  if (vm.count("valid"))
628  {
629  config->START_VALID = true;
630  }
631 
632  if (vm.count("net"))
633  {
634  if ((config->START_UP == Config::LOAD) ||
635  (config->START_UP == Config::REPLAY))
636  {
637  std::cerr << "Net and load/replay options are incompatible"
638  << std::endl;
639  return -1;
640  }
641 
642  config->START_UP = Config::NETWORK;
643  }
644 
645  // Override the RPC destination IP address. This must
646  // happen after the config file is loaded.
647  if (vm.count("rpc_ip"))
648  {
650  vm["rpc_ip"].as<std::string>());
651  if (!endpoint)
652  {
653  std::cerr << "Invalid rpc_ip = " << vm["rpc_ip"].as<std::string>()
654  << "\n";
655  return -1;
656  }
657 
658  if (endpoint->port() == 0)
659  {
660  std::cerr << "No port specified in rpc_ip.\n";
661  if (vm.count("rpc_port"))
662  {
663  std::cerr << "WARNING: using deprecated rpc_port param.\n";
664  try
665  {
666  endpoint =
667  endpoint->at_port(vm["rpc_port"].as<std::uint16_t>());
668  if (endpoint->port() == 0)
669  throw std::domain_error("0");
670  }
671  catch (std::exception const& e)
672  {
673  std::cerr << "Invalid rpc_port = " << e.what() << "\n";
674  return -1;
675  }
676  }
677  else
678  return -1;
679  }
680 
681  config->rpc_ip = std::move(*endpoint);
682  }
683 
684  if (vm.count("quorum"))
685  {
686  try
687  {
688  config->VALIDATION_QUORUM = vm["quorum"].as<std::size_t>();
689  if (config->VALIDATION_QUORUM == std::size_t{})
690  {
691  throw std::domain_error("0");
692  }
693  }
694  catch (std::exception const& e)
695  {
696  std::cerr << "Invalid value specified for --quorum (" << e.what()
697  << ")\n";
698  return -1;
699  }
700  }
701 
702  // Construct the logs object at the configured severity
703  using namespace beast::severities;
704  Severity thresh = kInfo;
705 
706  if (vm.count("quiet"))
707  thresh = kFatal;
708  else if (vm.count("verbose"))
709  thresh = kTrace;
710 
711  auto logs = std::make_unique<Logs>(thresh);
712 
713  // No arguments. Run server.
714  if (!vm.count("parameters"))
715  {
716  // TODO: this comment can be removed in a future release -
717  // say 1.7 or higher
718  if (config->had_trailing_comments())
719  {
720  JLOG(logs->journal("Application").warn())
721  << "Trailing comments were seen in your config file. "
722  << "The treatment of inline/trailing comments has changed "
723  "recently. "
724  << "Any `#` characters NOT intended to delimit comments should "
725  "be "
726  << "preceded by a \\";
727  }
728 
729  // We want at least 1024 file descriptors. We'll
730  // tweak this further.
731  if (!adjustDescriptorLimit(1024, logs->journal("Application")))
732  return -1;
733 
734  if (vm.count("debug"))
735  setDebugLogSink(logs->makeSink("Debug", beast::severities::kTrace));
736 
737  auto timeKeeper = make_TimeKeeper(logs->journal("TimeKeeper"));
738 
739  auto app = make_Application(
740  std::move(config), std::move(logs), std::move(timeKeeper));
741 
742  if (!app->setup())
743  return -1;
744 
745  // With our configuration parsed, ensure we have
746  // enough file descriptors available:
748  app->fdRequired(), app->logs().journal("Application")))
749  return -1;
750 
751  // Start the server
752  app->doStart(true /*start timers*/);
753 
754  // Block until we get a stop RPC.
755  app->run();
756 
757  return 0;
758  }
759 
760  // We have an RPC command to process:
761  beast::setCurrentThreadName("rippled: rpc");
763  *config, vm["parameters"].as<std::vector<std::string>>(), *logs);
764 }
765 
766 } // namespace ripple
767 
768 // Must be outside the namespace for obvious reasons
769 //
770 int
771 main(int argc, char** argv)
772 {
773 #if BOOST_OS_WINDOWS
774  {
775  // Work around for https://svn.boost.org/trac/boost/ticket/10657
776  // Reported against boost version 1.56.0. If an application's
777  // first call to GetTimeZoneInformation is from a coroutine, an
778  // unhandled exception is generated. A workaround is to call
779  // GetTimeZoneInformation at least once before launching any
780  // coroutines. At the time of this writing the _ftime call is
781  // used to initialize the timezone information.
782  struct _timeb t;
783 #ifdef _INC_TIME_INL
784  _ftime_s(&t);
785 #else
786  _ftime(&t);
787 #endif
788  }
789 #endif
790 
791  atexit(&google::protobuf::ShutdownProtobufLibrary);
792 
793  auto const result(ripple::run(argc, argv));
794 
795  return result;
796 }
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::experimental::filesystem::file_size
T file_size(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:501
utility
std::exception
STL class.
ripple::printHelp
void printHelp(const po::options_description &desc)
Definition: Main.cpp:120
std::vector::reserve
T reserve(T... args)
ripple::TxSearched::all
@ all
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:124
beast::severities
A namespace for easy access to logging severity values.
Definition: Journal.h:29
std::cerr
iostream
std::cout
ripple::TxDBName
constexpr auto TxDBName
Definition: DBInit.h:73
stdexcept
std::atexit
T atexit(T... args)
std::log
T log(T... args)
ripple::Config::NETWORK
@ NETWORK
Definition: Config.h:124
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:61
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:483
std::uintmax_t
ripple::CommonDBPragmaTemp
constexpr char const * CommonDBPragmaTemp
Definition: DBInit.h:34
std::atomic< bool >
beast::severities::kInfo
@ kInfo
Definition: Journal.h:36
std::experimental::filesystem::space
T space(T... args)
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:34
beast::setCurrentThreadName
void setCurrentThreadName(std::string_view name)
Changes the name of the caller thread.
Definition: CurrentThreadName.cpp:119
ripple::setup_DatabaseCon
DatabaseCon::Setup setup_DatabaseCon(Config const &c, boost::optional< beast::Journal > j=boost::none)
Definition: DatabaseCon.cpp:106
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: NegativeUNLVote.h:38
ripple::Config::FRESH
@ FRESH
Definition: Config.h:124
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:124
ripple::make_TimeKeeper
std::unique_ptr< TimeKeeper > make_TimeKeeper(beast::Journal j)
Definition: TimeKeeper.cpp:119
ripple::TxDBPragma
constexpr std::array TxDBPragma
Definition: DBInit.h:76
ripple::test::multi_runner_child
A class to run a subset of unit tests.
Definition: multi_runner.h:253
ripple::systemName
static std::string const & systemName()
Definition: SystemParameters.h:34
std::size_t
std::vector::end
T end(T... args)
ripple::TxDBInit
constexpr std::array< char const *, 8 > TxDBInit
Definition: DBInit.h:84
beast::severities::kFatal
@ kFatal
Definition: Journal.h:39
beast::IP::Endpoint::from_string_checked
static boost::optional< Endpoint > from_string_checked(std::string const &s)
Create an Endpoint from a string.
Definition: IPEndpoint.cpp:35
std::max
T max(T... args)
ripple::test::multi_runner_parent
Manager for children running unit tests.
Definition: multi_runner.h:218
ripple::adjustDescriptorLimit
bool adjustDescriptorLimit(int needed, beast::Journal j)
Definition: Main.cpp:75
ripple::Config::LOAD_FILE
@ LOAD_FILE
Definition: Config.h:124
std::data
T data(T... args)
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:2197
ripple::ConfigSection::nodeDatabase
static std::string nodeDatabase()
Definition: ConfigSections.h:33
std::exception::what
T what(T... args)