rippled
Config.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/basics/FileUtilities.h>
21 #include <ripple/basics/Log.h>
22 #include <ripple/basics/contract.h>
23 #include <ripple/beast/core/LexicalCast.h>
24 #include <ripple/core/Config.h>
25 #include <ripple/core/ConfigSections.h>
26 #include <ripple/json/json_reader.h>
27 #include <ripple/net/HTTPClient.h>
28 #include <ripple/protocol/Feature.h>
29 #include <ripple/protocol/SystemParameters.h>
30 #include <boost/algorithm/string.hpp>
31 #include <boost/beast/core/string.hpp>
32 #include <boost/format.hpp>
33 #include <boost/regex.hpp>
34 #include <boost/system/error_code.hpp>
35 #include <algorithm>
36 #include <fstream>
37 #include <iostream>
38 #include <iterator>
39 
40 namespace ripple {
41 
44  // FIXME: We should document each of these items, explaining exactly
45  // what
46  // they control and whether there exists an explicit config
47  // option that can be used to override the default.
48  {SizedItem::sweepInterval, {{10, 30, 60, 90, 120}}},
49  {SizedItem::treeCacheSize, {{128000, 256000, 512000, 768000, 2048000}}},
50  {SizedItem::treeCacheAge, {{30, 60, 90, 120, 900}}},
51  {SizedItem::ledgerSize, {{32, 128, 256, 384, 768}}},
52  {SizedItem::ledgerAge, {{30, 90, 180, 240, 900}}},
53  {SizedItem::ledgerFetch, {{2, 3, 4, 5, 8}}},
54  {SizedItem::nodeCacheSize, {{16384, 32768, 131072, 262144, 524288}}},
55  {SizedItem::nodeCacheAge, {{60, 90, 120, 900, 1800}}},
56  {SizedItem::hashNodeDBCache, {{4, 12, 24, 64, 128}}},
57  {SizedItem::txnDBCache, {{4, 12, 24, 64, 128}}},
58  {SizedItem::lgrDBCache, {{4, 8, 16, 32, 128}}},
59  }};
60 
61 // Ensure that the order of entries in the table corresponds to the
62 // order of entries in the enum:
63 static_assert(
64  []() constexpr->bool {
65  std::underlying_type_t<SizedItem> idx = 0;
66 
67  for (auto const& i : sizedItems)
68  {
69  if (static_cast<std::underlying_type_t<SizedItem>>(i.first) != idx)
70  return false;
71 
72  ++idx;
73  }
74 
75  return true;
76  }(),
77  "Mismatch between sized item enum & array indices");
78 
79 //
80 // TODO: Check permissions on config file before using it.
81 //
82 
83 #define SECTION_DEFAULT_NAME ""
84 
86 parseIniFile(std::string const& strInput, const bool bTrim)
87 {
88  std::string strData(strInput);
90  IniFileSections secResult;
91 
92  // Convert DOS format to unix.
93  boost::algorithm::replace_all(strData, "\r\n", "\n");
94 
95  // Convert MacOS format to unix.
96  boost::algorithm::replace_all(strData, "\r", "\n");
97 
98  boost::algorithm::split(vLines, strData, boost::algorithm::is_any_of("\n"));
99 
100  // Set the default Section name.
101  std::string strSection = SECTION_DEFAULT_NAME;
102 
103  // Initialize the default Section.
104  secResult[strSection] = IniFileSections::mapped_type();
105 
106  // Parse each line.
107  for (auto& strValue : vLines)
108  {
109  if (bTrim)
110  boost::algorithm::trim(strValue);
111 
112  if (strValue.empty() || strValue[0] == '#')
113  {
114  // Blank line or comment, do nothing.
115  }
116  else if (strValue[0] == '[' && strValue[strValue.length() - 1] == ']')
117  {
118  // New Section.
119  strSection = strValue.substr(1, strValue.length() - 2);
120  secResult.emplace(strSection, IniFileSections::mapped_type{});
121  }
122  else
123  {
124  // Another line for Section.
125  if (!strValue.empty())
126  secResult[strSection].push_back(strValue);
127  }
128  }
129 
130  return secResult;
131 }
132 
133 IniFileSections::mapped_type*
134 getIniFileSection(IniFileSections& secSource, std::string const& strSection)
135 {
136  IniFileSections::iterator it;
137  IniFileSections::mapped_type* smtResult;
138  it = secSource.find(strSection);
139  if (it == secSource.end())
140  smtResult = nullptr;
141  else
142  smtResult = &(it->second);
143  return smtResult;
144 }
145 
146 bool
148  IniFileSections& secSource,
149  std::string const& strSection,
150  std::string& strValue,
151  beast::Journal j)
152 {
153  IniFileSections::mapped_type* pmtEntries =
154  getIniFileSection(secSource, strSection);
155  bool bSingle = pmtEntries && 1 == pmtEntries->size();
156 
157  if (bSingle)
158  {
159  strValue = (*pmtEntries)[0];
160  }
161  else if (pmtEntries)
162  {
163  JLOG(j.warn()) << boost::str(
164  boost::format("Section [%s]: requires 1 line not %d lines.") %
165  strSection % pmtEntries->size());
166  }
167 
168  return bSingle;
169 }
170 
171 //------------------------------------------------------------------------------
172 //
173 // Config (DEPRECATED)
174 //
175 //------------------------------------------------------------------------------
176 
177 char const* const Config::configFileName = "rippled.cfg";
178 char const* const Config::databaseDirName = "db";
179 char const* const Config::validatorsFileName = "validators.txt";
180 
181 static std::string
182 getEnvVar(char const* name)
183 {
184  std::string value;
185 
186  auto const v = getenv(name);
187 
188  if (v != nullptr)
189  value = v;
190 
191  return value;
192 }
193 
194 constexpr FeeUnit32 Config::TRANSACTION_FEE_BASE;
195 
196 void
197 Config::setupControl(bool bQuiet, bool bSilent, bool bStandalone)
198 {
199  QUIET = bQuiet || bSilent;
200  SILENT = bSilent;
201  RUN_STANDALONE = bStandalone;
202 }
203 
204 void
205 Config::setup(
206  std::string const& strConf,
207  bool bQuiet,
208  bool bSilent,
209  bool bStandalone)
210 {
211  boost::filesystem::path dataDir;
212  std::string strDbPath, strConfFile;
213 
214  // Determine the config and data directories.
215  // If the config file is found in the current working
216  // directory, use the current working directory as the
217  // config directory and that with "db" as the data
218  // directory.
219 
220  setupControl(bQuiet, bSilent, bStandalone);
221 
222  strDbPath = databaseDirName;
223 
224  if (!strConf.empty())
225  strConfFile = strConf;
226  else
227  strConfFile = configFileName;
228 
229  if (!strConf.empty())
230  {
231  // --conf=<path> : everything is relative that file.
232  CONFIG_FILE = strConfFile;
233  CONFIG_DIR = boost::filesystem::absolute(CONFIG_FILE);
234  CONFIG_DIR.remove_filename();
235  dataDir = CONFIG_DIR / strDbPath;
236  }
237  else
238  {
239  CONFIG_DIR = boost::filesystem::current_path();
240  CONFIG_FILE = CONFIG_DIR / strConfFile;
241  dataDir = CONFIG_DIR / strDbPath;
242 
243  // Construct XDG config and data home.
244  // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
245  std::string strHome = getEnvVar("HOME");
246  std::string strXdgConfigHome = getEnvVar("XDG_CONFIG_HOME");
247  std::string strXdgDataHome = getEnvVar("XDG_DATA_HOME");
248 
249  if (boost::filesystem::exists(CONFIG_FILE)
250  // Can we figure out XDG dirs?
251  || (strHome.empty() &&
252  (strXdgConfigHome.empty() || strXdgDataHome.empty())))
253  {
254  // Current working directory is fine, put dbs in a subdir.
255  }
256  else
257  {
258  if (strXdgConfigHome.empty())
259  {
260  // $XDG_CONFIG_HOME was not set, use default based on $HOME.
261  strXdgConfigHome = strHome + "/.config";
262  }
263 
264  if (strXdgDataHome.empty())
265  {
266  // $XDG_DATA_HOME was not set, use default based on $HOME.
267  strXdgDataHome = strHome + "/.local/share";
268  }
269 
270  CONFIG_DIR = strXdgConfigHome + "/" + systemName();
271  CONFIG_FILE = CONFIG_DIR / strConfFile;
272  dataDir = strXdgDataHome + "/" + systemName();
273 
274  if (!boost::filesystem::exists(CONFIG_FILE))
275  {
276  CONFIG_DIR = "/etc/opt/" + systemName();
277  CONFIG_FILE = CONFIG_DIR / strConfFile;
278  dataDir = "/var/opt/" + systemName();
279  }
280  }
281  }
282 
283  // Update default values
284  load();
285  {
286  // load() may have set a new value for the dataDir
287  std::string const dbPath(legacy("database_path"));
288  if (!dbPath.empty())
289  dataDir = boost::filesystem::path(dbPath);
290  else if (RUN_STANDALONE)
291  dataDir.clear();
292  }
293 
294  if (!dataDir.empty())
295  {
296  boost::system::error_code ec;
297  boost::filesystem::create_directories(dataDir, ec);
298 
299  if (ec)
300  Throw<std::runtime_error>(
301  boost::str(boost::format("Can not create %s") % dataDir));
302 
303  legacy("database_path", boost::filesystem::absolute(dataDir).string());
304  }
305 
306  HTTPClient::initializeSSLContext(*this, j_);
307 
308  if (RUN_STANDALONE)
309  LEDGER_HISTORY = 0;
310 }
311 
312 void
313 Config::load()
314 {
315  // NOTE: this writes to cerr because we want cout to be reserved
316  // for the writing of the json response (so that stdout can be part of a
317  // pipeline, for instance)
318  if (!QUIET)
319  std::cerr << "Loading: " << CONFIG_FILE << "\n";
320 
321  boost::system::error_code ec;
322  auto const fileContents = getFileContents(ec, CONFIG_FILE);
323 
324  if (ec)
325  {
326  std::cerr << "Failed to read '" << CONFIG_FILE << "'." << ec.value()
327  << ": " << ec.message() << std::endl;
328  return;
329  }
330 
331  loadFromString(fileContents);
332 }
333 
334 void
335 Config::loadFromString(std::string const& fileContents)
336 {
337  IniFileSections secConfig = parseIniFile(fileContents, true);
338 
339  build(secConfig);
340 
341  if (auto s = getIniFileSection(secConfig, SECTION_IPS))
342  IPS = *s;
343 
344  if (auto s = getIniFileSection(secConfig, SECTION_IPS_FIXED))
345  IPS_FIXED = *s;
346 
347  if (auto s = getIniFileSection(secConfig, SECTION_SNTP))
348  SNTP_SERVERS = *s;
349 
350  {
351  std::string dbPath;
352  if (getSingleSection(secConfig, "database_path", dbPath, j_))
353  {
354  boost::filesystem::path p(dbPath);
355  legacy("database_path", boost::filesystem::absolute(p).string());
356  }
357  }
358 
359  std::string strTemp;
360 
361  if (getSingleSection(secConfig, SECTION_PEER_PRIVATE, strTemp, j_))
362  PEER_PRIVATE = beast::lexicalCastThrow<bool>(strTemp);
363 
364  if (getSingleSection(secConfig, SECTION_PEERS_MAX, strTemp, j_))
365  PEERS_MAX = beast::lexicalCastThrow<std::size_t>(strTemp);
366 
367  if (getSingleSection(secConfig, SECTION_NODE_SIZE, strTemp, j_))
368  {
369  if (boost::iequals(strTemp, "tiny"))
370  NODE_SIZE = 0;
371  else if (boost::iequals(strTemp, "small"))
372  NODE_SIZE = 1;
373  else if (boost::iequals(strTemp, "medium"))
374  NODE_SIZE = 2;
375  else if (boost::iequals(strTemp, "large"))
376  NODE_SIZE = 3;
377  else if (boost::iequals(strTemp, "huge"))
378  NODE_SIZE = 4;
379  else
380  NODE_SIZE = std::min<std::size_t>(
381  4, beast::lexicalCastThrow<std::size_t>(strTemp));
382  }
383 
384  if (getSingleSection(secConfig, SECTION_SIGNING_SUPPORT, strTemp, j_))
385  signingEnabled_ = beast::lexicalCastThrow<bool>(strTemp);
386 
387  if (getSingleSection(secConfig, SECTION_ELB_SUPPORT, strTemp, j_))
388  ELB_SUPPORT = beast::lexicalCastThrow<bool>(strTemp);
389 
390  if (getSingleSection(secConfig, SECTION_WEBSOCKET_PING_FREQ, strTemp, j_))
391  WEBSOCKET_PING_FREQ =
392  std::chrono::seconds{beast::lexicalCastThrow<int>(strTemp)};
393 
394  getSingleSection(secConfig, SECTION_SSL_VERIFY_FILE, SSL_VERIFY_FILE, j_);
395  getSingleSection(secConfig, SECTION_SSL_VERIFY_DIR, SSL_VERIFY_DIR, j_);
396 
397  if (getSingleSection(secConfig, SECTION_SSL_VERIFY, strTemp, j_))
398  SSL_VERIFY = beast::lexicalCastThrow<bool>(strTemp);
399 
400  if (exists(SECTION_VALIDATION_SEED) && exists(SECTION_VALIDATOR_TOKEN))
401  Throw<std::runtime_error>("Cannot have both [" SECTION_VALIDATION_SEED
402  "] "
403  "and [" SECTION_VALIDATOR_TOKEN
404  "] config sections");
405 
406  if (getSingleSection(secConfig, SECTION_NETWORK_QUORUM, strTemp, j_))
407  NETWORK_QUORUM = beast::lexicalCastThrow<std::size_t>(strTemp);
408 
409  if (getSingleSection(secConfig, SECTION_FEE_ACCOUNT_RESERVE, strTemp, j_))
410  FEE_ACCOUNT_RESERVE = beast::lexicalCastThrow<std::uint64_t>(strTemp);
411 
412  if (getSingleSection(secConfig, SECTION_FEE_OWNER_RESERVE, strTemp, j_))
413  FEE_OWNER_RESERVE = beast::lexicalCastThrow<std::uint64_t>(strTemp);
414 
415  if (getSingleSection(secConfig, SECTION_FEE_DEFAULT, strTemp, j_))
416  FEE_DEFAULT = beast::lexicalCastThrow<std::uint64_t>(strTemp);
417 
418  if (getSingleSection(secConfig, SECTION_LEDGER_HISTORY, strTemp, j_))
419  {
420  if (boost::iequals(strTemp, "full"))
421  LEDGER_HISTORY = 1000000000u;
422  else if (boost::iequals(strTemp, "none"))
423  LEDGER_HISTORY = 0;
424  else
425  LEDGER_HISTORY = beast::lexicalCastThrow<std::uint32_t>(strTemp);
426  }
427 
428  if (getSingleSection(secConfig, SECTION_FETCH_DEPTH, strTemp, j_))
429  {
430  if (boost::iequals(strTemp, "none"))
431  FETCH_DEPTH = 0;
432  else if (boost::iequals(strTemp, "full"))
433  FETCH_DEPTH = 1000000000u;
434  else
435  FETCH_DEPTH = beast::lexicalCastThrow<std::uint32_t>(strTemp);
436 
437  if (FETCH_DEPTH < 10)
438  FETCH_DEPTH = 10;
439  }
440 
441  if (getSingleSection(secConfig, SECTION_PATH_SEARCH_OLD, strTemp, j_))
442  PATH_SEARCH_OLD = beast::lexicalCastThrow<int>(strTemp);
443  if (getSingleSection(secConfig, SECTION_PATH_SEARCH, strTemp, j_))
444  PATH_SEARCH = beast::lexicalCastThrow<int>(strTemp);
445  if (getSingleSection(secConfig, SECTION_PATH_SEARCH_FAST, strTemp, j_))
446  PATH_SEARCH_FAST = beast::lexicalCastThrow<int>(strTemp);
447  if (getSingleSection(secConfig, SECTION_PATH_SEARCH_MAX, strTemp, j_))
448  PATH_SEARCH_MAX = beast::lexicalCastThrow<int>(strTemp);
449 
450  if (getSingleSection(secConfig, SECTION_DEBUG_LOGFILE, strTemp, j_))
451  DEBUG_LOGFILE = strTemp;
452 
453  if (getSingleSection(secConfig, SECTION_WORKERS, strTemp, j_))
454  WORKERS = beast::lexicalCastThrow<std::size_t>(strTemp);
455 
456  if (getSingleSection(secConfig, SECTION_COMPRESSION, strTemp, j_))
457  COMPRESSION = beast::lexicalCastThrow<bool>(strTemp);
458 
459  // Do not load trusted validator configuration for standalone mode
460  if (!RUN_STANDALONE)
461  {
462  // If a file was explicitly specified, then throw if the
463  // path is malformed or if the file does not exist or is
464  // not a file.
465  // If the specified file is not an absolute path, then look
466  // for it in the same directory as the config file.
467  // If no path was specified, then look for validators.txt
468  // in the same directory as the config file, but don't complain
469  // if we can't find it.
470  boost::filesystem::path validatorsFile;
471 
472  if (getSingleSection(secConfig, SECTION_VALIDATORS_FILE, strTemp, j_))
473  {
474  validatorsFile = strTemp;
475 
476  if (validatorsFile.empty())
477  Throw<std::runtime_error>(
478  "Invalid path specified in [" SECTION_VALIDATORS_FILE "]");
479 
480  if (!validatorsFile.is_absolute() && !CONFIG_DIR.empty())
481  validatorsFile = CONFIG_DIR / validatorsFile;
482 
483  if (!boost::filesystem::exists(validatorsFile))
484  Throw<std::runtime_error>(
485  "The file specified in [" SECTION_VALIDATORS_FILE
486  "] "
487  "does not exist: " +
488  validatorsFile.string());
489 
490  else if (
491  !boost::filesystem::is_regular_file(validatorsFile) &&
492  !boost::filesystem::is_symlink(validatorsFile))
493  Throw<std::runtime_error>(
494  "Invalid file specified in [" SECTION_VALIDATORS_FILE
495  "]: " +
496  validatorsFile.string());
497  }
498  else if (!CONFIG_DIR.empty())
499  {
500  validatorsFile = CONFIG_DIR / validatorsFileName;
501 
502  if (!validatorsFile.empty())
503  {
504  if (!boost::filesystem::exists(validatorsFile))
505  validatorsFile.clear();
506  else if (
507  !boost::filesystem::is_regular_file(validatorsFile) &&
508  !boost::filesystem::is_symlink(validatorsFile))
509  validatorsFile.clear();
510  }
511  }
512 
513  if (!validatorsFile.empty() &&
514  boost::filesystem::exists(validatorsFile) &&
515  (boost::filesystem::is_regular_file(validatorsFile) ||
516  boost::filesystem::is_symlink(validatorsFile)))
517  {
518  boost::system::error_code ec;
519  auto const data = getFileContents(ec, validatorsFile);
520  if (ec)
521  {
522  Throw<std::runtime_error>(
523  "Failed to read '" + validatorsFile.string() + "'." +
524  std::to_string(ec.value()) + ": " + ec.message());
525  }
526 
527  auto iniFile = parseIniFile(data, true);
528 
529  auto entries = getIniFileSection(iniFile, SECTION_VALIDATORS);
530 
531  if (entries)
532  section(SECTION_VALIDATORS).append(*entries);
533 
534  auto valKeyEntries =
535  getIniFileSection(iniFile, SECTION_VALIDATOR_KEYS);
536 
537  if (valKeyEntries)
538  section(SECTION_VALIDATOR_KEYS).append(*valKeyEntries);
539 
540  auto valSiteEntries =
541  getIniFileSection(iniFile, SECTION_VALIDATOR_LIST_SITES);
542 
543  if (valSiteEntries)
544  section(SECTION_VALIDATOR_LIST_SITES).append(*valSiteEntries);
545 
546  auto valListKeys =
547  getIniFileSection(iniFile, SECTION_VALIDATOR_LIST_KEYS);
548 
549  if (valListKeys)
550  section(SECTION_VALIDATOR_LIST_KEYS).append(*valListKeys);
551 
552  if (!entries && !valKeyEntries && !valListKeys)
553  Throw<std::runtime_error>(
554  "The file specified in [" SECTION_VALIDATORS_FILE
555  "] "
556  "does not contain a [" SECTION_VALIDATORS
557  "], "
558  "[" SECTION_VALIDATOR_KEYS
559  "] or "
560  "[" SECTION_VALIDATOR_LIST_KEYS
561  "]"
562  " section: " +
563  validatorsFile.string());
564  }
565 
566  // Consolidate [validator_keys] and [validators]
567  section(SECTION_VALIDATORS)
568  .append(section(SECTION_VALIDATOR_KEYS).lines());
569 
570  if (!section(SECTION_VALIDATOR_LIST_SITES).lines().empty() &&
571  section(SECTION_VALIDATOR_LIST_KEYS).lines().empty())
572  {
573  Throw<std::runtime_error>(
574  "[" + std::string(SECTION_VALIDATOR_LIST_KEYS) +
575  "] config section is missing");
576  }
577  }
578 
579  {
580  auto const part = section("features");
581  for (auto const& s : part.values())
582  {
583  if (auto const f = getRegisteredFeature(s))
584  features.insert(*f);
585  else
586  Throw<std::runtime_error>(
587  "Unknown feature: " + s + " in config file.");
588  }
589  }
590 
591  // This doesn't properly belong here, but check to make sure that the
592  // value specified for network_quorum is achievable:
593  {
594  auto pm = PEERS_MAX;
595 
596  // FIXME this apparently magic value is actually defined as a constant
597  // elsewhere (see defaultMaxPeers) but we handle this check here.
598  if (pm == 0)
599  pm = 21;
600 
601  if (NETWORK_QUORUM > pm)
602  {
603  Throw<std::runtime_error>(
604  "The minimum number of required peers (network_quorum) exceeds "
605  "the maximum number of allowed peers (peers_max)");
606  }
607  }
608 }
609 
610 boost::filesystem::path
611 Config::getDebugLogFile() const
612 {
613  auto log_file = DEBUG_LOGFILE;
614 
615  if (!log_file.empty() && !log_file.is_absolute())
616  {
617  // Unless an absolute path for the log file is specified, the
618  // path is relative to the config file directory.
619  log_file = boost::filesystem::absolute(log_file, CONFIG_DIR);
620  }
621 
622  if (!log_file.empty())
623  {
624  auto log_dir = log_file.parent_path();
625 
626  if (!boost::filesystem::is_directory(log_dir))
627  {
628  boost::system::error_code ec;
629  boost::filesystem::create_directories(log_dir, ec);
630 
631  // If we fail, we warn but continue so that the calling code can
632  // decide how to handle this situation.
633  if (ec)
634  {
635  std::cerr << "Unable to create log file path " << log_dir
636  << ": " << ec.message() << '\n';
637  }
638  }
639  }
640 
641  return log_file;
642 }
643 
644 int
645 Config::getValueFor(SizedItem item, boost::optional<std::size_t> node) const
646 {
647  auto const index = static_cast<std::underlying_type_t<SizedItem>>(item);
648  assert(index < sizedItems.size());
649  assert(!node || *node <= 4);
650  return sizedItems.at(index).second.at(node.value_or(NODE_SIZE));
651 }
652 
653 } // namespace ripple
ripple::sizedItems
constexpr std::array< std::pair< SizedItem, std::array< int, 5 > >, 11 > sizedItems
Definition: Config.cpp:43
fstream
std::string
STL class.
ripple::SizedItem
SizedItem
Definition: Config.h:47
ripple::SizedItem::nodeCacheSize
@ nodeCacheSize
std::vector< std::string >
std::map::find
T find(T... args)
std::string::size
T size(T... args)
std::chrono::seconds
iterator
std::map::emplace
T emplace(T... args)
ripple::SizedItem::treeCacheAge
@ treeCacheAge
beast::Journal::warn
Stream warn() const
Definition: Journal.h:327
std::cerr
ripple::SizedItem::nodeCacheAge
@ nodeCacheAge
ripple::SizedItem::hashNodeDBCache
@ hashNodeDBCache
iostream
ripple::SizedItem::ledgerFetch
@ ledgerFetch
algorithm
std::underlying_type_t
std::to_string
T to_string(T... args)
std::array
STL class.
ripple::SizedItem::lgrDBCache
@ lgrDBCache
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
std::map
STL class.
ripple::getFileContents
std::string getFileContents(boost::system::error_code &ec, boost::filesystem::path const &sourcePath, boost::optional< std::size_t > maxSize=boost::none)
Definition: FileUtilities.cpp:25
ripple::SizedItem::txnDBCache
@ txnDBCache
ripple::parseIniFile
IniFileSections parseIniFile(std::string const &strInput, const bool bTrim)
Definition: Config.cpp:86
std::string::substr
T substr(T... args)
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::getSingleSection
bool getSingleSection(IniFileSections &secSource, std::string const &strSection, std::string &strValue, beast::Journal j)
Definition: Config.cpp:147
std::endl
T endl(T... args)
ripple::getEnvVar
static std::string getEnvVar(char const *name)
Definition: Config.cpp:182
ripple::SizedItem::treeCacheSize
@ treeCacheSize
ripple::SizedItem::sweepInterval
@ sweepInterval
std::string::empty
T empty(T... args)
ripple::SizedItem::ledgerSize
@ ledgerSize
std::map::end
T end(T... args)
ripple::getIniFileSection
IniFileSections::mapped_type * getIniFileSection(IniFileSections &secSource, std::string const &strSection)
Definition: Config.cpp:134
ripple::SizedItem::ledgerAge
@ ledgerAge
ripple::IniFileSections
std::map< std::string, std::vector< std::string > > IniFileSections
Definition: BasicConfig.h:36
ripple::getRegisteredFeature
boost::optional< uint256 > getRegisteredFeature(std::string const &name)
Definition: Feature.cpp:140