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