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