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