468 for (
auto& line : strVec)
471 if (
std::count(line.begin(), line.end(),
':') != 1)
477 if (result.
size() == line.size())
490 boost::filesystem::path
const p(dbPath);
491 legacy(
"database_path", boost::filesystem::absolute(p).
string());
499 if (strTemp ==
"main")
503 else if (strTemp ==
"testnet")
507 else if (strTemp ==
"devnet")
513 NETWORK_ID = beast::lexicalCastThrow<uint32_t>(strTemp);
522 PEERS_MAX = beast::lexicalCastThrow<std::size_t>(strTemp);
529 peers_in_max = beast::lexicalCastThrow<std::size_t>(strTemp);
530 if (*peers_in_max > 1000)
532 Throw<std::runtime_error>(
"Invalid value specified in [" SECTION_PEERS_IN_MAX
533 "] section; the value must be less or equal than 1000");
540 peers_out_max = beast::lexicalCastThrow<std::size_t>(strTemp);
541 if (*peers_out_max < 10 || *peers_out_max > 1000)
543 Throw<std::runtime_error>(
"Invalid value specified in [" SECTION_PEERS_OUT_MAX
544 "] section; the value must be in range 10-1000");
549 if ((peers_in_max && !peers_out_max) || (peers_out_max && !peers_in_max))
551 Throw<std::runtime_error>(
"Both sections [" SECTION_PEERS_IN_MAX
553 "and [" SECTION_PEERS_OUT_MAX
"] must be configured");
556 if (peers_in_max && peers_out_max)
565 if (boost::iequals(strTemp,
"tiny"))
569 else if (boost::iequals(strTemp,
"small"))
573 else if (boost::iequals(strTemp,
"medium"))
577 else if (boost::iequals(strTemp,
"large"))
581 else if (boost::iequals(strTemp,
"huge"))
595 ELB_SUPPORT = beast::lexicalCastThrow<bool>(strTemp);
601 SSL_VERIFY = beast::lexicalCastThrow<bool>(strTemp);
605 if (boost::iequals(strTemp,
"all"))
609 else if (boost::iequals(strTemp,
"trusted"))
613 else if (boost::iequals(strTemp,
"drop_untrusted"))
619 Throw<std::runtime_error>(
"Invalid value specified in [" SECTION_RELAY_VALIDATIONS
626 if (boost::iequals(strTemp,
"all"))
630 else if (boost::iequals(strTemp,
"trusted"))
634 else if (boost::iequals(strTemp,
"drop_untrusted"))
640 Throw<std::runtime_error>(
"Invalid value specified in [" SECTION_RELAY_PROPOSALS
645 if (
exists(SECTION_VALIDATION_SEED) &&
exists(SECTION_VALIDATOR_TOKEN))
647 Throw<std::runtime_error>(
"Cannot have both [" SECTION_VALIDATION_SEED
648 "] and [" SECTION_VALIDATOR_TOKEN
"] config sections");
663 if (boost::iequals(strTemp,
"full"))
667 else if (boost::iequals(strTemp,
"none"))
679 if (boost::iequals(strTemp,
"none"))
683 else if (boost::iequals(strTemp,
"full"))
689 FETCH_DEPTH = beast::lexicalCastThrow<std::uint32_t>(strTemp);
697 if (
exists(SECTION_VALIDATION_SEED) ||
exists(SECTION_VALIDATOR_TOKEN))
703 PATH_SEARCH = beast::lexicalCastThrow<int>(strTemp);
716 if (SWEEP_INTERVAL < 10 || SWEEP_INTERVAL > 600)
718 Throw<std::runtime_error>(
"Invalid " SECTION_SWEEP_INTERVAL
719 ": must be between 10 and 600 inclusive");
725 WORKERS = beast::lexicalCastThrow<int>(strTemp);
727 if (WORKERS < 1 || WORKERS > 1024)
729 Throw<std::runtime_error>(
"Invalid " SECTION_WORKERS
730 ": must be between 1 and 1024 inclusive.");
736 IO_WORKERS = beast::lexicalCastThrow<int>(strTemp);
738 if (IO_WORKERS < 1 || IO_WORKERS > 1024)
740 Throw<std::runtime_error>(
"Invalid " SECTION_IO_WORKERS
741 ": must be between 1 and 1024 inclusive.");
749 if (PREFETCH_WORKERS < 1 || PREFETCH_WORKERS > 1024)
751 Throw<std::runtime_error>(
"Invalid " SECTION_PREFETCH_WORKERS
752 ": must be between 1 and 1024 inclusive.");
757 COMPRESSION = beast::lexicalCastThrow<bool>(strTemp);
762 if (
exists(SECTION_REDUCE_RELAY))
764 auto sec =
section(SECTION_REDUCE_RELAY);
772 if (sec.exists(
"vp_base_squelch_enable") && sec.exists(
"vp_enable"))
774 Throw<std::runtime_error>(
"Invalid " SECTION_REDUCE_RELAY
775 " cannot specify both vp_base_squelch_enable and vp_enable "
777 "vp_enable was deprecated and replaced by "
778 "vp_base_squelch_enable");
781 if (sec.exists(
"vp_base_squelch_enable"))
785 else if (sec.exists(
"vp_enable"))
800 sec.value_or(
"vp_base_squelch_max_selected_peers", 5);
803 Throw<std::runtime_error>(
"Invalid " SECTION_REDUCE_RELAY
804 " vp_base_squelch_max_selected_peers must be "
805 "greater than or equal to 3");
815 Throw<std::runtime_error>(
"Invalid " SECTION_REDUCE_RELAY
816 ", tx_min_peers must be greater than or equal to 10"
817 ", tx_relay_percentage must be greater than or equal to 10 "
818 "and less than or equal to 100");
832 Throw<std::runtime_error>(
833 "Invalid " SECTION_SERVER_DOMAIN
834 ": the domain name does not appear to meet the requirements.");
840 if (
exists(SECTION_OVERLAY))
842 auto const sec =
section(SECTION_OVERLAY);
848 if (
auto val = sec.get(
"max_unknown_time"))
853 Throw<std::runtime_error>(
"Invalid value 'max_unknown_time' in " SECTION_OVERLAY
854 ": must be of the form '<number>' representing seconds.");
859 Throw<std::runtime_error>(
860 "Invalid value 'max_unknown_time' in " SECTION_OVERLAY
861 ": the time must be between 300 and 1800 seconds, inclusive.");
866 if (
auto val = sec.get(
"max_diverged_time"))
871 Throw<std::runtime_error>(
"Invalid value 'max_diverged_time' in " SECTION_OVERLAY
872 ": must be of the form '<number>' representing seconds.");
877 Throw<std::runtime_error>(
"Invalid value 'max_diverged_time' in " SECTION_OVERLAY
878 ": the time must be between 60 and 900 seconds, inclusive.");
885 boost::regex
const re(
"^\\s*(\\d+)\\s*(minutes|hours|days|weeks)\\s*(\\s+.*)?$");
887 if (!boost::regex_match(strTemp,
match, re))
889 Throw<std::runtime_error>(
"Invalid " SECTION_AMENDMENT_MAJORITY_TIME
890 ", must be: [0-9]+ [minutes|hours|days|weeks]");
895 if (boost::iequals(
match[2],
"minutes"))
899 else if (boost::iequals(
match[2],
"hours"))
903 else if (boost::iequals(
match[2],
"days"))
907 else if (boost::iequals(
match[2],
"weeks"))
914 Throw<std::runtime_error>(
"Invalid " SECTION_AMENDMENT_MAJORITY_TIME
915 ", the minimum amount of time an amendment must hold a "
916 "majority is 15 minutes");
934 boost::filesystem::path validatorsFile;
938 validatorsFile = strTemp;
940 if (validatorsFile.empty())
942 Throw<std::runtime_error>(
"Invalid path specified in [" SECTION_VALIDATORS_FILE
946 if (!validatorsFile.is_absolute() && !
CONFIG_DIR.empty())
949 if (!boost::filesystem::exists(validatorsFile))
951 Throw<std::runtime_error>(
952 "The file specified in [" SECTION_VALIDATORS_FILE
955 validatorsFile.string());
958 !boost::filesystem::is_regular_file(validatorsFile) &&
959 !boost::filesystem::is_symlink(validatorsFile))
961 Throw<std::runtime_error>(
962 "Invalid file specified in [" SECTION_VALIDATORS_FILE
"]: " +
963 validatorsFile.string());
970 if (!validatorsFile.empty())
972 if (!boost::filesystem::exists(validatorsFile))
974 validatorsFile.clear();
977 !boost::filesystem::is_regular_file(validatorsFile) &&
978 !boost::filesystem::is_symlink(validatorsFile))
980 validatorsFile.clear();
985 if (!validatorsFile.empty() && boost::filesystem::exists(validatorsFile) &&
986 (boost::filesystem::is_regular_file(validatorsFile) ||
987 boost::filesystem::is_symlink(validatorsFile)))
989 boost::system::error_code ec;
993 Throw<std::runtime_error>(
994 "Failed to read '" + validatorsFile.string() +
"'." +
1002 if (entries !=
nullptr)
1007 if (valKeyEntries !=
nullptr)
1012 if (valSiteEntries !=
nullptr)
1013 section(SECTION_VALIDATOR_LIST_SITES).
append(*valSiteEntries);
1017 if (valListKeys !=
nullptr)
1020 auto valListThreshold =
getIniFileSection(iniFile, SECTION_VALIDATOR_LIST_THRESHOLD);
1022 if (valListThreshold !=
nullptr)
1023 section(SECTION_VALIDATOR_LIST_THRESHOLD).
append(*valListThreshold);
1025 if ((entries ==
nullptr) && (valKeyEntries ==
nullptr) && (valListKeys ==
nullptr))
1027 Throw<std::runtime_error>(
1028 "The file specified in [" SECTION_VALIDATORS_FILE
1030 "does not contain a [" SECTION_VALIDATORS
1032 "[" SECTION_VALIDATOR_KEYS
1034 "[" SECTION_VALIDATOR_LIST_KEYS
1037 validatorsFile.string());
1042 auto const& listThreshold =
section(SECTION_VALIDATOR_LIST_THRESHOLD);
1043 if (listThreshold.lines().empty())
1047 if (listThreshold.values().size() == 1)
1049 auto strTemp = listThreshold.values()[0];
1050 auto const listThreshold = beast::lexicalCastThrow<std::size_t>(strTemp);
1051 if (listThreshold == 0)
1055 if (listThreshold >
section(SECTION_VALIDATOR_LIST_KEYS).values().size())
1057 Throw<std::runtime_error>(
1058 "Value in config section "
1059 "[" SECTION_VALIDATOR_LIST_THRESHOLD
1060 "] exceeds the number of configured list keys");
1062 return listThreshold;
1065 Throw<std::runtime_error>(
1067 "[" SECTION_VALIDATOR_LIST_THRESHOLD
"] should contain single value only");
1073 if (!
section(SECTION_VALIDATOR_LIST_SITES).lines().empty() &&
1074 section(SECTION_VALIDATOR_LIST_KEYS).lines().empty())
1076 Throw<std::runtime_error>(
1077 "[" +
std::string(SECTION_VALIDATOR_LIST_KEYS) +
"] config section is missing");
1082 auto const part =
section(
"features");
1083 for (
auto const& s : part.values())
1091 Throw<std::runtime_error>(
"Unknown feature: " + s +
" in config file.");
1108 Throw<std::runtime_error>(
1109 "The minimum number of required peers (network_quorum) exceeds "
1110 "the maximum number of allowed peers (peers_max)");
1188 Throw<std::runtime_error>(
"database_path must be set.");
1193 auto const& sqlite = c.
section(
"sqlite");
1202 bool showRiskWarning =
false;
1204 if (
set(safety_level,
"safety_level", sqlite))
1206 if (boost::iequals(safety_level,
"low"))
1209 journal_mode =
"memory";
1210 synchronous =
"off";
1211 temp_store =
"memory";
1212 showRiskWarning =
true;
1214 else if (!boost::iequals(safety_level,
"high"))
1216 Throw<std::runtime_error>(
"Invalid safety_level value: " + safety_level);
1223 if (
set(journal_mode,
"journal_mode", sqlite) && !safety_level.
empty())
1225 Throw<std::runtime_error>(
1226 "Configuration file may not define both "
1227 "\"safety_level\" and \"journal_mode\"");
1229 bool const higherRisk =
1230 boost::iequals(journal_mode,
"memory") || boost::iequals(journal_mode,
"off");
1231 showRiskWarning = showRiskWarning || higherRisk;
1232 if (higherRisk || boost::iequals(journal_mode,
"delete") ||
1233 boost::iequals(journal_mode,
"truncate") ||
1234 boost::iequals(journal_mode,
"persist") || boost::iequals(journal_mode,
"wal"))
1236 result->emplace_back(
1241 Throw<std::runtime_error>(
"Invalid journal_mode value: " + journal_mode);
1247 if (
set(synchronous,
"synchronous", sqlite) && !safety_level.
empty())
1249 Throw<std::runtime_error>(
1250 "Configuration file may not define both "
1251 "\"safety_level\" and \"synchronous\"");
1253 bool const higherRisk = boost::iequals(synchronous,
"off");
1254 showRiskWarning = showRiskWarning || higherRisk;
1255 if (higherRisk || boost::iequals(synchronous,
"normal") ||
1256 boost::iequals(synchronous,
"full") || boost::iequals(synchronous,
"extra"))
1262 Throw<std::runtime_error>(
"Invalid synchronous value: " + synchronous);
1268 if (
set(temp_store,
"temp_store", sqlite) && !safety_level.
empty())
1270 Throw<std::runtime_error>(
1271 "Configuration file may not define both "
1272 "\"safety_level\" and \"temp_store\"");
1274 bool const higherRisk = boost::iequals(temp_store,
"memory");
1275 showRiskWarning = showRiskWarning || higherRisk;
1276 if (higherRisk || boost::iequals(temp_store,
"default") ||
1277 boost::iequals(temp_store,
"file"))
1283 Throw<std::runtime_error>(
"Invalid temp_store value: " + temp_store);
1289 JLOG(j->warn()) <<
"reducing the data integrity guarantees from the "
1290 "default [sqlite] behavior is not recommended for "
1291 "nodes storing large amounts of history, because of the "
1292 "difficulty inherent in rebuilding corrupted data.";
1295 result->size() == 3,
"xrpl::setup_DatabaseCon::globalPragma : result size is 3");
1305 setPragma(setup.
lgrPragma[0],
"journal_size_limit", 1582080);
1309 int64_t journal_size_limit = 1582080;
1312 auto& s = c.
section(
"sqlite");
1313 set(journal_size_limit,
"journal_size_limit", s);
1314 set(page_size,
"page_size", s);
1315 if (page_size < 512 || page_size > 65536)
1316 Throw<std::runtime_error>(
"Invalid page_size. Must be between 512 and 65536.");
1318 if ((page_size & (page_size - 1)) != 0)
1319 Throw<std::runtime_error>(
"Invalid page_size. Must be a power of 2.");
1322 setPragma(setup.
txPragma[0],
"page_size", page_size);
1323 setPragma(setup.
txPragma[1],
"journal_size_limit", journal_size_limit);
1324 setPragma(setup.
txPragma[2],
"max_page_count", 4294967294);
1325 setPragma(setup.
txPragma[3],
"mmap_size", 17179869184);