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  for (auto& c : children)
301  {
302  try
303  {
304  c.wait();
305  if (c.exit_code())
306  ++bad_child_exits;
307  }
308  catch (...)
309  {
310  // wait throws if process was terminated with a signal
311  ++bad_child_exits;
312  }
313  }
314 
315  parent_runner.add_failures(bad_child_exits);
316  anyMissing(parent_runner, multi_selector(pattern));
317 
318  if (parent_runner.any_failed() || bad_child_exits)
319  return EXIT_FAILURE;
320  return EXIT_SUCCESS;
321  }
322  else
323  {
324  // child
325  multi_runner_child runner{num_jobs, quiet, log};
326  runner.arg(argument);
327  auto const anyFailed = runner.run_multi(multi_selector(pattern));
328 
329  if (anyFailed)
330  return EXIT_FAILURE;
331  return EXIT_SUCCESS;
332  }
333 }
334 
335 //------------------------------------------------------------------------------
336 
337 int
338 run(int argc, char** argv)
339 {
340  using namespace std;
341 
343  "rippled: main " + BuildInfo::getVersionString());
344 
345  po::variables_map vm;
346 
347  std::string importText;
348  {
349  importText += "Import an existing node database (specified in the [";
350  importText += ConfigSection::importNodeDatabase();
351  importText += "] configuration file section) into the current ";
352  importText += "node database (specified in the [";
353  importText += ConfigSection::nodeDatabase();
354  importText += "] configuration file section).";
355  }
356 
357  // Set up option parsing.
358  //
359  po::options_description gen("General Options");
360  gen.add_options()(
361  "conf", po::value<std::string>(), "Specify the configuration file.")(
362  "debug", "Enable normally suppressed debug logging")(
363  "help,h", "Display this message.")(
364  "quorum",
365  po::value<std::size_t>(),
366  "Override the minimum validation quorum.")(
367  "silent", "No output to the console after startup.")(
368  "standalone,a", "Run with no peers.")("verbose,v", "Verbose logging.")(
369  "version", "Display the build version.");
370 
371  po::options_description data("Ledger/Data Options");
372  data.add_options()("import", importText.c_str())(
373  "ledger",
374  po::value<std::string>(),
375  "Load the specified ledger and start from the value given.")(
376  "ledgerfile",
377  po::value<std::string>(),
378  "Load the specified ledger file.")(
379  "load", "Load the current ledger from the local DB.")(
380  "net", "Get the initial ledger from the network.")(
381  "nodetoshard", "Import node store into shards")(
382  "replay", "Replay a ledger close.")(
383  "start", "Start from a fresh Ledger.")(
384  "vacuum", "VACUUM the transaction db.")(
385  "valid", "Consider the initial ledger a valid network ledger.");
386 
387  po::options_description rpc("RPC Client Options");
388  rpc.add_options()(
389  "rpc",
390  "Perform rpc command - see below for available commands. "
391  "This is assumed if any positional parameters are provided.")(
392  "rpc_ip",
393  po::value<std::string>(),
394  "Specify the IP address for RPC command. "
395  "Format: <ip-address>[':'<port-number>]")(
396  "rpc_port",
397  po::value<std::uint16_t>(),
398  "DEPRECATED: include with rpc_ip instead. "
399  "Specify the port number for RPC command.");
400 
401  po::options_description test("Unit Test Options");
402  test.add_options()(
403  "quiet,q",
404  "Suppress test suite messages, "
405  "including suite/case name (at start) and test log messages.")(
406  "unittest,u",
407  po::value<std::string>()->implicit_value(""),
408  "Perform unit tests. The optional argument specifies one or "
409  "more comma-separated selectors. Each selector specifies a suite name, "
410  "full-name (lib.module.suite), module, or library "
411  "(checked in that "
412  "order).")(
413  "unittest-arg",
414  po::value<std::string>()->implicit_value(""),
415  "Supplies an argument string to unit tests. If provided, this argument "
416  "is made available to each suite that runs. Interpretation of the "
417  "argument is handled individually by any suite that accesses it -- "
418  "as such, it typically only make sense to provide this when running "
419  "a single suite.")(
420  "unittest-ipv6",
421  "Use IPv6 localhost when running unittests (default is IPv4).")(
422  "unittest-log",
423  "Force unit test log message output. Only useful in combination with "
424  "--quiet, in which case log messages will print but suite/case names "
425  "will not.")(
426  "unittest-jobs",
427  po::value<std::size_t>(),
428  "Number of unittest jobs to run in parallel (child processes).");
429 
430  // These are hidden options, not intended to be shown in the usage/help
431  // message
432  po::options_description hidden("Hidden Options");
433  hidden.add_options()(
434  "parameters",
435  po::value<vector<string>>(),
436  "Specify rpc command and parameters. This option must be repeated "
437  "for each command/param. Positional parameters also serve this "
438  "purpose, "
439  "so this option is not needed for users")(
440  "unittest-child",
441  "For internal use only when spawning child unit test processes.")(
442  "fg", "Deprecated: server always in foreground mode.");
443 
444  // Interpret positional arguments as --parameters.
445  po::positional_options_description p;
446  p.add("parameters", -1);
447 
448  po::options_description all;
449  all.add(gen).add(rpc).add(data).add(test).add(hidden);
450 
451  po::options_description desc;
452  desc.add(gen).add(rpc).add(data).add(test);
453 
454  // Parse options, if no error.
455  try
456  {
457  po::store(
458  po::command_line_parser(argc, argv)
459  .options(all) // Parse options.
460  .positional(p) // Remainder as --parameters.
461  .run(),
462  vm);
463  po::notify(vm); // Invoke option notify functions.
464  }
465  catch (std::exception const& ex)
466  {
467  std::cerr << "rippled: " << ex.what() << std::endl;
468  std::cerr << "Try 'rippled --help' for a list of options." << std::endl;
469  return 1;
470  }
471 
472  if (vm.count("help"))
473  {
474  printHelp(desc);
475  return 0;
476  }
477 
478  if (vm.count("version"))
479  {
480  std::cout << "rippled version " << BuildInfo::getVersionString()
481  << std::endl;
482  return 0;
483  }
484 
485  // Run the unit tests if requested.
486  // The unit tests will exit the application with an appropriate return code.
487  //
488  if (vm.count("unittest"))
489  {
490  std::string argument;
491 
492  if (vm.count("unittest-arg"))
493  argument = vm["unittest-arg"].as<std::string>();
494 
495  std::size_t numJobs = 1;
496  bool unittestChild = false;
497  if (vm.count("unittest-jobs"))
498  numJobs = std::max(numJobs, vm["unittest-jobs"].as<std::size_t>());
499  unittestChild = bool(vm.count("unittest-child"));
500 
501  return runUnitTests(
502  vm["unittest"].as<std::string>(),
503  argument,
504  bool(vm.count("quiet")),
505  bool(vm.count("unittest-log")),
506  unittestChild,
507  bool(vm.count("unittest-ipv6")),
508  numJobs,
509  argc,
510  argv);
511  }
512  else
513  {
514  if (vm.count("unittest-jobs"))
515  {
516  // unittest jobs only makes sense with `unittest`
517  std::cerr << "rippled: '--unittest-jobs' specified without "
518  "'--unittest'.\n";
519  std::cerr << "To run the unit tests the '--unittest' option must "
520  "be present.\n";
521  return 1;
522  }
523  }
524 
525  auto config = std::make_unique<Config>();
526 
527  auto configFile =
528  vm.count("conf") ? vm["conf"].as<std::string>() : std::string();
529 
530  // config file, quiet flag.
531  config->setup(
532  configFile,
533  bool(vm.count("quiet")),
534  bool(vm.count("silent")),
535  bool(vm.count("standalone")));
536 
537  if (vm.count("vacuum"))
538  {
539  if (config->standalone())
540  {
541  std::cerr << "vacuum not applicable in standalone mode.\n";
542  return -1;
543  }
544 
545  using namespace boost::filesystem;
546  DatabaseCon::Setup const dbSetup = setup_DatabaseCon(*config);
547  path dbPath = dbSetup.dataDir / TxDBName;
548 
549  try
550  {
551  uintmax_t const dbSize = file_size(dbPath);
552  assert(dbSize != static_cast<uintmax_t>(-1));
553 
554  if (auto available = space(dbPath.parent_path()).available;
555  available < dbSize)
556  {
557  std::cerr << "The database filesystem must have at least as "
558  "much free space as the size of "
559  << dbPath.string() << ", which is " << dbSize
560  << " bytes. Only " << available
561  << " bytes are available.\n";
562  return -1;
563  }
564 
565  auto txnDB = std::make_unique<DatabaseCon>(
566  dbSetup, TxDBName, TxDBPragma, TxDBInit);
567  auto& session = txnDB->getSession();
568  std::uint32_t pageSize;
569 
570  // Only the most trivial databases will fit in memory on typical
571  // (recommended) software. Force temp files to be written to disk
572  // regardless of the config settings.
573  session << boost::format(CommonDBPragmaTemp) % "file";
574  session << "PRAGMA page_size;", soci::into(pageSize);
575 
576  std::cout << "VACUUM beginning. page_size: " << pageSize
577  << std::endl;
578 
579  session << "VACUUM;";
580  assert(dbSetup.globalPragma);
581  for (auto const& p : *dbSetup.globalPragma)
582  session << p;
583  session << "PRAGMA page_size;", soci::into(pageSize);
584 
585  std::cout << "VACUUM finished. page_size: " << pageSize
586  << std::endl;
587  }
588  catch (std::exception const& e)
589  {
590  std::cerr << "exception " << e.what() << " in function " << __func__
591  << std::endl;
592  return -1;
593  }
594 
595  return 0;
596  }
597 
598  if (vm.count("start"))
599  config->START_UP = Config::FRESH;
600 
601  if (vm.count("import"))
602  config->doImport = true;
603 
604  if (vm.count("nodetoshard"))
605  config->nodeToShard = true;
606 
607  if (vm.count("ledger"))
608  {
609  config->START_LEDGER = vm["ledger"].as<std::string>();
610  if (vm.count("replay"))
611  config->START_UP = Config::REPLAY;
612  else
613  config->START_UP = Config::LOAD;
614  }
615  else if (vm.count("ledgerfile"))
616  {
617  config->START_LEDGER = vm["ledgerfile"].as<std::string>();
618  config->START_UP = Config::LOAD_FILE;
619  }
620  else if (vm.count("load"))
621  {
622  config->START_UP = Config::LOAD;
623  }
624 
625  if (vm.count("valid"))
626  {
627  config->START_VALID = true;
628  }
629 
630  if (vm.count("net"))
631  {
632  if ((config->START_UP == Config::LOAD) ||
633  (config->START_UP == Config::REPLAY))
634  {
635  std::cerr << "Net and load/replay options are incompatible"
636  << std::endl;
637  return -1;
638  }
639 
640  config->START_UP = Config::NETWORK;
641  }
642 
643  // Override the RPC destination IP address. This must
644  // happen after the config file is loaded.
645  if (vm.count("rpc_ip"))
646  {
648  vm["rpc_ip"].as<std::string>());
649  if (!endpoint)
650  {
651  std::cerr << "Invalid rpc_ip = " << vm["rpc_ip"].as<std::string>()
652  << "\n";
653  return -1;
654  }
655 
656  if (endpoint->port() == 0)
657  {
658  std::cerr << "No port specified in rpc_ip.\n";
659  if (vm.count("rpc_port"))
660  {
661  std::cerr << "WARNING: using deprecated rpc_port param.\n";
662  try
663  {
664  endpoint =
665  endpoint->at_port(vm["rpc_port"].as<std::uint16_t>());
666  if (endpoint->port() == 0)
667  throw std::domain_error("0");
668  }
669  catch (std::exception const& e)
670  {
671  std::cerr << "Invalid rpc_port = " << e.what() << "\n";
672  return -1;
673  }
674  }
675  else
676  return -1;
677  }
678 
679  config->rpc_ip = std::move(*endpoint);
680  }
681 
682  if (vm.count("quorum"))
683  {
684  try
685  {
686  config->VALIDATION_QUORUM = vm["quorum"].as<std::size_t>();
687  if (config->VALIDATION_QUORUM == std::size_t{})
688  {
689  throw std::domain_error("0");
690  }
691  }
692  catch (std::exception const& e)
693  {
694  std::cerr << "Invalid value specified for --quorum (" << e.what()
695  << ")\n";
696  return -1;
697  }
698  }
699 
700  // Construct the logs object at the configured severity
701  using namespace beast::severities;
702  Severity thresh = kInfo;
703 
704  if (vm.count("quiet"))
705  thresh = kFatal;
706  else if (vm.count("verbose"))
707  thresh = kTrace;
708 
709  auto logs = std::make_unique<Logs>(thresh);
710 
711  // No arguments. Run server.
712  if (!vm.count("parameters"))
713  {
714  // TODO: this comment can be removed in a future release -
715  // say 1.7 or higher
716  if (config->had_trailing_comments())
717  {
718  JLOG(logs->journal("Application").warn())
719  << "Trailing comments were seen in your config file. "
720  << "The treatment of inline/trailing comments has changed "
721  "recently. "
722  << "Any `#` characters NOT intended to delimit comments should "
723  "be "
724  << "preceded by a \\";
725  }
726 
727  // We want at least 1024 file descriptors. We'll
728  // tweak this further.
729  if (!adjustDescriptorLimit(1024, logs->journal("Application")))
730  return -1;
731 
732  if (vm.count("debug"))
733  setDebugLogSink(logs->makeSink("Debug", beast::severities::kTrace));
734 
735  auto timeKeeper = make_TimeKeeper(logs->journal("TimeKeeper"));
736 
737  auto app = make_Application(
738  std::move(config), std::move(logs), std::move(timeKeeper));
739 
740  if (!app->setup())
741  return -1;
742 
743  // With our configuration parsed, ensure we have
744  // enough file descriptors available:
746  app->fdRequired(), app->logs().journal("Application")))
747  return -1;
748 
749  // Start the server
750  app->doStart(true /*start timers*/);
751 
752  // Block until we get a stop RPC.
753  app->run();
754 
755  return 0;
756  }
757 
758  // We have an RPC command to process:
759  beast::setCurrentThreadName("rippled: rpc");
761  *config, vm["parameters"].as<std::vector<std::string>>(), *logs);
762 }
763 
764 } // namespace ripple
765 
766 // Must be outside the namespace for obvious reasons
767 //
768 int
769 main(int argc, char** argv)
770 {
771 #if BOOST_OS_WINDOWS
772  {
773  // Work around for https://svn.boost.org/trac/boost/ticket/10657
774  // Reported against boost version 1.56.0. If an application's
775  // first call to GetTimeZoneInformation is from a coroutine, an
776  // unhandled exception is generated. A workaround is to call
777  // GetTimeZoneInformation at least once before launching any
778  // coroutines. At the time of this writing the _ftime call is
779  // used to initialize the timezone information.
780  struct _timeb t;
781 #ifdef _INC_TIME_INL
782  _ftime_s(&t);
783 #else
784  _ftime(&t);
785 #endif
786  }
787 #endif
788 
789  atexit(&google::protobuf::ShutdownProtobufLibrary);
790 
791  auto const result(ripple::run(argc, argv));
792 
793  return result;
794 }
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)