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