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