diff --git a/Builds/VisualStudio2013/RippleD.vcxproj b/Builds/VisualStudio2013/RippleD.vcxproj
index 0254c344e2..04faa80ab4 100644
--- a/Builds/VisualStudio2013/RippleD.vcxproj
+++ b/Builds/VisualStudio2013/RippleD.vcxproj
@@ -1926,6 +1926,9 @@
+
+ True
+
True
diff --git a/Builds/VisualStudio2013/RippleD.vcxproj.filters b/Builds/VisualStudio2013/RippleD.vcxproj.filters
index 6560fd77ca..785b82b19a 100644
--- a/Builds/VisualStudio2013/RippleD.vcxproj.filters
+++ b/Builds/VisualStudio2013/RippleD.vcxproj.filters
@@ -2844,6 +2844,9 @@
ripple\core
+
+ ripple\core\tests
+
ripple\core\tests
diff --git a/doc/rippled-example.cfg b/doc/rippled-example.cfg
index 9e8e6e870f..9c00ecebc8 100644
--- a/doc/rippled-example.cfg
+++ b/doc/rippled-example.cfg
@@ -698,7 +698,8 @@
# There are 4 book-keeping SQLite database that the server creates and
# maintains. If you omit this configuration setting, it will default to
# creating a directory called "db" located in the same place as your
-# rippled.cfg file.
+# rippled.cfg file. Partial pathnames will be considered relative to
+# the location of the rippled executable.
#
#
#
diff --git a/src/ripple/app/data/DatabaseCon.cpp b/src/ripple/app/data/DatabaseCon.cpp
index b13ad94435..0f77a3ef4b 100644
--- a/src/ripple/app/data/DatabaseCon.cpp
+++ b/src/ripple/app/data/DatabaseCon.cpp
@@ -58,7 +58,7 @@ setup_DatabaseCon (Config const& c)
setup.onlineDelete = c.nodeDatabase["online_delete"].getIntValue();
setup.startUp = c.START_UP;
setup.standAlone = c.RUN_STANDALONE;
- setup.dataDir = c.DATA_DIR;
+ setup.dataDir = c.legacy ("database_path");
return setup;
}
diff --git a/src/ripple/app/main/Application.cpp b/src/ripple/app/main/Application.cpp
index d9c2211c72..585399a152 100644
--- a/src/ripple/app/main/Application.cpp
+++ b/src/ripple/app/main/Application.cpp
@@ -887,7 +887,8 @@ public:
{
// VFALCO TODO Move all this into doSweep
- boost::filesystem::space_info space = boost::filesystem::space (getConfig ().DATA_DIR);
+ boost::filesystem::space_info space =
+ boost::filesystem::space (getConfig ().legacy ("database_path"));
// VFALCO TODO Give this magic constant a name and move it into a well documented header
//
diff --git a/src/ripple/app/misc/SHAMapStoreImp.cpp b/src/ripple/app/misc/SHAMapStoreImp.cpp
index 83531abf44..27b0f9768f 100644
--- a/src/ripple/app/misc/SHAMapStoreImp.cpp
+++ b/src/ripple/app/misc/SHAMapStoreImp.cpp
@@ -700,7 +700,7 @@ setup_SHAMapStore (Config const& c)
setup.ledgerHistory = c.LEDGER_HISTORY;
setup.nodeDatabase = c.nodeDatabase;
setup.ephemeralNodeDatabase = c.ephemeralNodeDatabase;
- setup.databasePath = c.DATABASE_PATH;
+ setup.databasePath = c.legacy("database_path");
if (c.nodeDatabase["delete_batch"].isNotEmpty())
setup.deleteBatch = c.nodeDatabase["delete_batch"].getIntValue();
if (c.nodeDatabase["backOff"].isNotEmpty())
diff --git a/src/ripple/basics/BasicConfig.h b/src/ripple/basics/BasicConfig.h
index 358927a65e..e8be781372 100644
--- a/src/ripple/basics/BasicConfig.h
+++ b/src/ripple/basics/BasicConfig.h
@@ -76,6 +76,38 @@ public:
return values_;
}
+ /**
+ * Set the legacy value for this section.
+ */
+ void
+ legacy (std::string value)
+ {
+ if (lines_.empty ())
+ lines_.emplace_back (std::move (value));
+ else
+ {
+ assert (lines_.size () == 1);
+ lines_[0] = std::move (value);
+ }
+ }
+
+ /**
+ * Get the legacy value for this section.
+ *
+ * @return The retrieved value. A section with an empty legacy value returns
+ an empty string.
+ */
+ std::string
+ legacy () const
+ {
+ if (lines_.empty ())
+ return "";
+ else if (lines_.size () > 1)
+ throw std::runtime_error (
+ "A legacy value must have exactly one line. Section: " + name_);
+ return lines_[0];
+ }
+
/** Set a key/value pair.
The previous value is discarded.
*/
@@ -150,6 +182,29 @@ public:
overwrite (std::string const& section, std::string const& key,
std::string const& value);
+ /**
+ * Set a value that is not a key/value pair.
+ *
+ * The value is stored as the section's first value and may be retrieved
+ * through section::legacy.
+ *
+ * @param section Name of the section to modify.
+ * @param value Contents of the legacy value.
+ */
+ void
+ legacy(std::string const& section, std::string value);
+
+ /**
+ * Get the legacy value of a section. A section with a
+ * single-line value may be retrieved as a legacy value.
+ *
+ * @param sectionName Retrieve the contents of this section's
+ * legacy value.
+ * @returun Contents of the legacy value.
+ */
+ std::string
+ legacy(std::string const& sectionName) const;
+
friend
std::ostream&
operator<< (std::ostream& ss, BasicConfig const& c);
@@ -157,15 +212,6 @@ public:
protected:
void
build (IniFileSections const& ifs);
-
- /** Insert a legacy single section as a key/value pair.
- Does nothing if the section does not exist, or does not contain
- a single line that is not a key/value pair.
- @deprecated
- */
- void
- remap (std::string const& legacy_section,
- std::string const& key, std::string const& new_section);
};
//------------------------------------------------------------------------------
diff --git a/src/ripple/basics/impl/BasicConfig.cpp b/src/ripple/basics/impl/BasicConfig.cpp
index 7d2de96ceb..36b24ca679 100644
--- a/src/ripple/basics/impl/BasicConfig.cpp
+++ b/src/ripple/basics/impl/BasicConfig.cpp
@@ -106,24 +106,6 @@ BasicConfig::section (std::string const& name) const
return iter->second;
}
-void
-BasicConfig::remap (std::string const& legacy_section,
- std::string const& key, std::string const& new_section)
-{
- auto const iter = map_.find (legacy_section);
- if (iter == map_.end())
- return;
- if (iter->second.size() != 0)
- return;
- if (iter->second.lines().size() != 1)
- return;
- auto result = map_.emplace(std::piecewise_construct,
- std::make_tuple(new_section), std::make_tuple(new_section));
- auto& s = result.first->second;
- s.append (iter->second.lines().front());
- s.set (key, iter->second.lines().front());
-}
-
void
BasicConfig::overwrite (std::string const& section, std::string const& key,
std::string const& value)
@@ -133,6 +115,18 @@ BasicConfig::overwrite (std::string const& section, std::string const& key,
result.first->second.set (key, value);
}
+void
+BasicConfig::legacy(std::string const& section, std::string value)
+{
+ map_[section].legacy(std::move(value));
+}
+
+std::string
+BasicConfig::legacy(std::string const& sectionName) const
+{
+ return section (sectionName).legacy ();
+}
+
void
BasicConfig::build (IniFileSections const& ifs)
{
diff --git a/src/ripple/core/Config.h b/src/ripple/core/Config.h
index 2a4771f6a2..1207a1aed5 100644
--- a/src/ripple/core/Config.h
+++ b/src/ripple/core/Config.h
@@ -87,10 +87,10 @@ struct SizedItem
int sizes[5];
};
-// VFALCO NOTE This entire derived class is deprecated
-// For new config information use the style implied
-// in the base class. For existing config information
-// try to refactor code to use the new style.
+// This entire derived class is deprecated.
+// For new config information use the style implied
+// in the base class. For existing config information
+// try to refactor code to use the new style.
//
class Config : public BasicConfig
{
@@ -121,20 +121,17 @@ public:
/** Returns the directory from which the configuration file was loaded. */
beast::File getConfigDir () const;
- /** Returns the directory in which the current database files are located. */
- beast::File getDatabaseDir () const;
-
/** Returns the full path and filename of the debug log file. */
boost::filesystem::path getDebugLogFile () const;
- // LEGACY FIELDS, REMOVE ASAP
+ // DEPRECATED
boost::filesystem::path CONFIG_FILE; // used by UniqueNodeList
private:
boost::filesystem::path CONFIG_DIR;
boost::filesystem::path DEBUG_LOGFILE;
+
+ void load ();
public:
- // VFALCO TODO Make this private and fix callers to go through getDatabaseDir()
- boost::filesystem::path DATA_DIR;
//--------------------------------------------------------------------------
@@ -152,10 +149,6 @@ public:
/** List of Validators entries from rippled.cfg */
std::vector validators;
-private:
- /** The folder where new module databases should be located */
- beast::File m_moduleDbPath;
-
public:
//--------------------------------------------------------------------------
/** Returns the location were databases should be located
@@ -164,7 +157,7 @@ public:
stored in a file named after the module (e.g. "peerfinder.sqlite") that
is inside that directory.
*/
- beast::File const& getModuleDatabasePath ();
+ beast::File getModuleDatabasePath () const;
//--------------------------------------------------------------------------
@@ -234,9 +227,6 @@ public:
std::string START_LEDGER;
- // Database
- std::string DATABASE_PATH;
-
// Network parameters
int TRANSACTION_FEE_BASE; // The number of fee units a reference transaction costs
@@ -312,10 +302,16 @@ public:
int getSize (SizedItemName) const;
void setup (std::string const& strConf, bool bQuiet);
- void load ();
+
+ /**
+ * Load the conig from the contents of the sting.
+ *
+ * @param fileContents String representing the config contents.
+ */
+ void loadFromString (std::string const& fileContents);
};
-// VFALCO DEPRECATED
+// DEPRECATED
extern Config& getConfig();
} // ripple
diff --git a/src/ripple/core/ConfigSections.h b/src/ripple/core/ConfigSections.h
index 1d6b7e18a3..7c2d42b780 100644
--- a/src/ripple/core/ConfigSections.h
+++ b/src/ripple/core/ConfigSections.h
@@ -34,7 +34,6 @@ struct ConfigSection
#define SECTION_ACCOUNT_PROBE_MAX "account_probe_max"
#define SECTION_AMENDMENTS "amendments"
#define SECTION_CLUSTER_NODES "cluster_nodes"
-#define SECTION_DATABASE_PATH "database_path"
#define SECTION_DEBUG_LOGFILE "debug_logfile"
#define SECTION_ELB_SUPPORT "elb_support"
#define SECTION_FEE_DEFAULT "fee_default"
diff --git a/src/ripple/core/impl/Config.cpp b/src/ripple/core/impl/Config.cpp
index 45ad36514f..69c53ea547 100644
--- a/src/ripple/core/impl/Config.cpp
+++ b/src/ripple/core/impl/Config.cpp
@@ -284,6 +284,7 @@ getEnvVar (char const* name)
void Config::setup (std::string const& strConf, bool bQuiet)
{
+ boost::filesystem::path dataDir;
boost::system::error_code ec;
std::string strDbPath, strConfFile;
@@ -309,13 +310,13 @@ void Config::setup (std::string const& strConf, bool bQuiet)
CONFIG_FILE = strConfFile;
CONFIG_DIR = boost::filesystem::absolute (CONFIG_FILE);
CONFIG_DIR.remove_filename ();
- DATA_DIR = CONFIG_DIR / strDbPath;
+ dataDir = CONFIG_DIR / strDbPath;
}
else
{
CONFIG_DIR = boost::filesystem::current_path ();
CONFIG_FILE = CONFIG_DIR / strConfFile;
- DATA_DIR = CONFIG_DIR / strDbPath;
+ dataDir = CONFIG_DIR / strDbPath;
// Construct XDG config and data home.
// http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
@@ -345,7 +346,7 @@ void Config::setup (std::string const& strConf, bool bQuiet)
CONFIG_DIR = strXdgConfigHome + "/" + systemName ();
CONFIG_FILE = CONFIG_DIR / strConfFile;
- DATA_DIR = strXdgDataHome + "/" + systemName ();
+ dataDir = strXdgDataHome + "/" + systemName ();
boost::filesystem::create_directories (CONFIG_DIR, ec);
@@ -358,274 +359,257 @@ void Config::setup (std::string const& strConf, bool bQuiet)
// Update default values
load ();
+ {
+ // load() may have set a new value for the dataDir
+ std::string const dbPath (legacy ("database_path"));
+ if (!dbPath.empty ())
+ {
+ dataDir = boost::filesystem::path (dbPath);
+ }
+ }
- boost::filesystem::create_directories (DATA_DIR, ec);
+ boost::filesystem::create_directories (dataDir, ec);
if (ec)
- throw std::runtime_error (boost::str (boost::format ("Can not create %s") % DATA_DIR));
+ throw std::runtime_error (
+ boost::str (boost::format ("Can not create %s") % dataDir));
- // Create the new unified database
- m_moduleDbPath = getDatabaseDir();
-
- // This code is temporarily disabled, and modules will fall back to using
- // per-module databases (e.g. "peerfinder.sqlite") under the module db path
- //
- //if (m_moduleDbPath.isDirectory ())
- // m_moduleDbPath = m_moduleDbPath.getChildFile("rippled.sqlite");
+ legacy ("database_path", boost::filesystem::absolute (dataDir).string ());
}
void Config::load ()
{
if (!QUIET)
- std::cerr << "Loading: " << CONFIG_FILE << std::endl;
+ std::cerr << "Loading: " << CONFIG_FILE << "\n";
- std::ifstream ifsConfig (CONFIG_FILE.c_str (), std::ios::in);
+ std::ifstream ifsConfig (CONFIG_FILE.c_str (), std::ios::in);
if (!ifsConfig)
{
std::cerr << "Failed to open '" << CONFIG_FILE << "'." << std::endl;
+ return;
}
- else
- {
- std::string file_contents;
- file_contents.assign ((std::istreambuf_iterator (ifsConfig)),
- std::istreambuf_iterator ());
- if (ifsConfig.bad ())
+ std::string fileContents;
+ fileContents.assign ((std::istreambuf_iterator(ifsConfig)),
+ std::istreambuf_iterator());
+
+ if (ifsConfig.bad ())
+ {
+ std::cerr << "Failed to read '" << CONFIG_FILE << "'." << std::endl;
+ return;
+ }
+
+ loadFromString (fileContents);
+}
+
+void Config::loadFromString (std::string const& fileContents)
+{
+ IniFileSections secConfig = parseIniFile (fileContents, true);
+
+ build (secConfig);
+
+ if (auto s = getIniFileSection (secConfig, SECTION_VALIDATORS))
+ validators = *s;
+
+ if (auto s = getIniFileSection (secConfig, SECTION_CLUSTER_NODES))
+ CLUSTER_NODES = *s;
+
+ if (auto s = getIniFileSection (secConfig, SECTION_IPS))
+ IPS = *s;
+
+ if (auto s = getIniFileSection (secConfig, SECTION_IPS_FIXED))
+ IPS_FIXED = *s;
+
+ if (auto s = getIniFileSection (secConfig, SECTION_SNTP))
+ SNTP_SERVERS = *s;
+
+ if (auto s = getIniFileSection (secConfig, SECTION_RPC_STARTUP))
+ {
+ RPC_STARTUP = Json::arrayValue;
+
+ for (auto const& strJson : *s)
{
- std::cerr << "Failed to read '" << CONFIG_FILE << "'." << std::endl;
+ Json::Reader jrReader;
+ Json::Value jvCommand;
+
+ if (!jrReader.parse (strJson, jvCommand))
+ throw std::runtime_error (
+ boost::str (boost::format (
+ "Couldn't parse [" SECTION_RPC_STARTUP "] command: %s") % strJson));
+
+ RPC_STARTUP.append (jvCommand);
}
+ }
+
+ {
+ std::string dbPath;
+ if (getSingleSection (secConfig, "database_path", dbPath))
+ {
+ boost::filesystem::path p(dbPath);
+ legacy("database_path",
+ boost::filesystem::absolute (p).string ());
+ }
+ }
+
+ (void) getSingleSection (secConfig, SECTION_VALIDATORS_SITE, VALIDATORS_SITE);
+
+ std::string strTemp;
+ if (getSingleSection (secConfig, SECTION_PEER_PRIVATE, strTemp))
+ PEER_PRIVATE = beast::lexicalCastThrow (strTemp);
+
+ if (getSingleSection (secConfig, SECTION_PEERS_MAX, strTemp))
+ PEERS_MAX = beast::lexicalCastThrow (strTemp);
+
+ if (auto s = getIniFileSection (secConfig, SECTION_RPC_ADMIN_ALLOW))
+ {
+ std::vector parsedAddresses;
+ parseAddresses (parsedAddresses, (*s).cbegin(), (*s).cend());
+ RPC_ADMIN_ALLOW.insert (RPC_ADMIN_ALLOW.end(),
+ parsedAddresses.cbegin (), parsedAddresses.cend ());
+ }
+
+ insightSettings = parseKeyValueSection (secConfig, SECTION_INSIGHT);
+
+ nodeDatabase = parseKeyValueSection (
+ secConfig, ConfigSection::nodeDatabase ());
+
+ ephemeralNodeDatabase = parseKeyValueSection (
+ secConfig, ConfigSection::tempNodeDatabase ());
+
+ importNodeDatabase = parseKeyValueSection (
+ secConfig, ConfigSection::importNodeDatabase ());
+
+ if (getSingleSection (secConfig, SECTION_NODE_SIZE, strTemp))
+ {
+ if (strTemp == "tiny")
+ NODE_SIZE = 0;
+ else if (strTemp == "small")
+ NODE_SIZE = 1;
+ else if (strTemp == "medium")
+ NODE_SIZE = 2;
+ else if (strTemp == "large")
+ NODE_SIZE = 3;
+ else if (strTemp == "huge")
+ NODE_SIZE = 4;
else
{
- IniFileSections secConfig = parseIniFile (file_contents, true);
- std::string strTemp;
+ NODE_SIZE = beast::lexicalCastThrow (strTemp);
- build (secConfig);
-
- // XXX Leak
- IniFileSections::mapped_type* smtTmp;
-
- smtTmp = getIniFileSection (secConfig, SECTION_VALIDATORS);
-
- if (smtTmp)
- {
- validators = *smtTmp;
- }
-
- smtTmp = getIniFileSection (secConfig, SECTION_CLUSTER_NODES);
-
- if (smtTmp)
- {
- CLUSTER_NODES = *smtTmp;
- }
-
- smtTmp = getIniFileSection (secConfig, SECTION_IPS);
-
- if (smtTmp)
- {
- IPS = *smtTmp;
- }
-
- smtTmp = getIniFileSection (secConfig, SECTION_IPS_FIXED);
-
- if (smtTmp)
- {
- IPS_FIXED = *smtTmp;
- }
-
- smtTmp = getIniFileSection (secConfig, SECTION_SNTP);
-
- if (smtTmp)
- {
- SNTP_SERVERS = *smtTmp;
- }
-
- smtTmp = getIniFileSection (secConfig, SECTION_RPC_STARTUP);
-
- if (smtTmp)
- {
- RPC_STARTUP = Json::arrayValue;
-
- for (auto const& strJson : *smtTmp)
- {
- Json::Reader jrReader;
- Json::Value jvCommand;
-
- if (!jrReader.parse (strJson, jvCommand))
- throw std::runtime_error (
- boost::str (boost::format (
- "Couldn't parse [" SECTION_RPC_STARTUP "] command: %s") % strJson));
-
- RPC_STARTUP.append (jvCommand);
- }
- }
-
- if (getSingleSection (secConfig, SECTION_DATABASE_PATH, DATABASE_PATH))
- DATA_DIR = DATABASE_PATH;
-
- (void) getSingleSection (secConfig, SECTION_VALIDATORS_SITE, VALIDATORS_SITE);
-
- if (getSingleSection (secConfig, SECTION_PEER_PRIVATE, strTemp))
- PEER_PRIVATE = beast::lexicalCastThrow (strTemp);
-
- if (getSingleSection (secConfig, SECTION_PEERS_MAX, strTemp))
- PEERS_MAX = beast::lexicalCastThrow (strTemp);
-
- smtTmp = getIniFileSection (secConfig, SECTION_RPC_ADMIN_ALLOW);
-
- if (smtTmp)
- {
- std::vector parsedAddresses;
- //parseAddresses, std::vector::const_iterator>
- // (parsedAddresses, (*smtTmp).cbegin(), (*smtTmp).cend());
- parseAddresses (parsedAddresses, (*smtTmp).cbegin(), (*smtTmp).cend());
- RPC_ADMIN_ALLOW.insert (RPC_ADMIN_ALLOW.end(),
- parsedAddresses.cbegin (), parsedAddresses.cend ());
- }
-
- insightSettings = parseKeyValueSection (secConfig, SECTION_INSIGHT);
-
- nodeDatabase = parseKeyValueSection (
- secConfig, ConfigSection::nodeDatabase ());
-
- ephemeralNodeDatabase = parseKeyValueSection (
- secConfig, ConfigSection::tempNodeDatabase ());
-
- importNodeDatabase = parseKeyValueSection (
- secConfig, ConfigSection::importNodeDatabase ());
-
- if (getSingleSection (secConfig, SECTION_NODE_SIZE, strTemp))
- {
- if (strTemp == "tiny")
- NODE_SIZE = 0;
- else if (strTemp == "small")
- NODE_SIZE = 1;
- else if (strTemp == "medium")
- NODE_SIZE = 2;
- else if (strTemp == "large")
- NODE_SIZE = 3;
- else if (strTemp == "huge")
- NODE_SIZE = 4;
- else
- {
- NODE_SIZE = beast::lexicalCastThrow (strTemp);
-
- if (NODE_SIZE < 0)
- NODE_SIZE = 0;
- else if (NODE_SIZE > 4)
- NODE_SIZE = 4;
- }
- }
-
- if (getSingleSection (secConfig, SECTION_ELB_SUPPORT, strTemp))
- ELB_SUPPORT = beast::lexicalCastThrow (strTemp);
-
- if (getSingleSection (secConfig, SECTION_WEBSOCKET_PING_FREQ, strTemp))
- WEBSOCKET_PING_FREQ = beast::lexicalCastThrow (strTemp);
-
- getSingleSection (secConfig, SECTION_SSL_VERIFY_FILE, SSL_VERIFY_FILE);
- getSingleSection (secConfig, SECTION_SSL_VERIFY_DIR, SSL_VERIFY_DIR);
-
- if (getSingleSection (secConfig, SECTION_SSL_VERIFY, strTemp))
- SSL_VERIFY = beast::lexicalCastThrow (strTemp);
-
- if (getSingleSection (secConfig, SECTION_VALIDATION_SEED, strTemp))
- {
- VALIDATION_SEED.setSeedGeneric (strTemp);
-
- if (VALIDATION_SEED.isValid ())
- {
- VALIDATION_PUB = RippleAddress::createNodePublic (VALIDATION_SEED);
- VALIDATION_PRIV = RippleAddress::createNodePrivate (VALIDATION_SEED);
- }
- }
-
- if (getSingleSection (secConfig, SECTION_NODE_SEED, strTemp))
- {
- NODE_SEED.setSeedGeneric (strTemp);
-
- if (NODE_SEED.isValid ())
- {
- NODE_PUB = RippleAddress::createNodePublic (NODE_SEED);
- NODE_PRIV = RippleAddress::createNodePrivate (NODE_SEED);
- }
- }
-
- if (getSingleSection (secConfig, SECTION_NETWORK_QUORUM, strTemp))
- NETWORK_QUORUM = beast::lexicalCastThrow (strTemp);
-
- if (getSingleSection (secConfig, SECTION_VALIDATION_QUORUM, strTemp))
- VALIDATION_QUORUM = std::max (0, beast::lexicalCastThrow (strTemp));
-
- if (getSingleSection (secConfig, SECTION_FEE_ACCOUNT_RESERVE, strTemp))
- FEE_ACCOUNT_RESERVE = beast::lexicalCastThrow (strTemp);
-
- if (getSingleSection (secConfig, SECTION_FEE_OWNER_RESERVE, strTemp))
- FEE_OWNER_RESERVE = beast::lexicalCastThrow (strTemp);
-
- if (getSingleSection (secConfig, SECTION_FEE_OFFER, strTemp))
- FEE_OFFER = beast::lexicalCastThrow (strTemp);
-
- if (getSingleSection (secConfig, SECTION_FEE_DEFAULT, strTemp))
- FEE_DEFAULT = beast::lexicalCastThrow (strTemp);
-
- if (getSingleSection (secConfig, SECTION_FEE_OPERATION, strTemp))
- FEE_CONTRACT_OPERATION = beast::lexicalCastThrow (strTemp);
-
- if (getSingleSection (secConfig, SECTION_LEDGER_HISTORY, strTemp))
- {
- boost::to_lower (strTemp);
-
- if (strTemp == "full")
- LEDGER_HISTORY = 1000000000u;
- else if (strTemp == "none")
- LEDGER_HISTORY = 0;
- else
- LEDGER_HISTORY = beast::lexicalCastThrow (strTemp);
- }
-
- if (getSingleSection (secConfig, SECTION_FETCH_DEPTH, strTemp))
- {
- boost::to_lower (strTemp);
-
- if (strTemp == "none")
- FETCH_DEPTH = 0;
- else if (strTemp == "full")
- FETCH_DEPTH = 1000000000u;
- else
- FETCH_DEPTH = beast::lexicalCastThrow (strTemp);
-
- if (FETCH_DEPTH < 10)
- FETCH_DEPTH = 10;
- }
-
- if (getSingleSection (secConfig, SECTION_PATH_SEARCH_OLD, strTemp))
- PATH_SEARCH_OLD = beast::lexicalCastThrow (strTemp);
- if (getSingleSection (secConfig, SECTION_PATH_SEARCH, strTemp))
- PATH_SEARCH = beast::lexicalCastThrow (strTemp);
- if (getSingleSection (secConfig, SECTION_PATH_SEARCH_FAST, strTemp))
- PATH_SEARCH_FAST = beast::lexicalCastThrow (strTemp);
- if (getSingleSection (secConfig, SECTION_PATH_SEARCH_MAX, strTemp))
- PATH_SEARCH_MAX = beast::lexicalCastThrow (strTemp);
-
- if (getSingleSection (secConfig, SECTION_ACCOUNT_PROBE_MAX, strTemp))
- ACCOUNT_PROBE_MAX = beast::lexicalCastThrow (strTemp);
-
- (void) getSingleSection (secConfig, SECTION_SMS_FROM, SMS_FROM);
- (void) getSingleSection (secConfig, SECTION_SMS_KEY, SMS_KEY);
- (void) getSingleSection (secConfig, SECTION_SMS_SECRET, SMS_SECRET);
- (void) getSingleSection (secConfig, SECTION_SMS_TO, SMS_TO);
- (void) getSingleSection (secConfig, SECTION_SMS_URL, SMS_URL);
-
- if (getSingleSection (secConfig, SECTION_VALIDATORS_FILE, strTemp))
- {
- VALIDATORS_FILE = strTemp;
- }
-
- if (getSingleSection (secConfig, SECTION_DEBUG_LOGFILE, strTemp))
- DEBUG_LOGFILE = strTemp;
+ if (NODE_SIZE < 0)
+ NODE_SIZE = 0;
+ else if (NODE_SIZE > 4)
+ NODE_SIZE = 4;
}
}
+
+ if (getSingleSection (secConfig, SECTION_ELB_SUPPORT, strTemp))
+ ELB_SUPPORT = beast::lexicalCastThrow (strTemp);
+
+ if (getSingleSection (secConfig, SECTION_WEBSOCKET_PING_FREQ, strTemp))
+ WEBSOCKET_PING_FREQ = beast::lexicalCastThrow (strTemp);
+
+ getSingleSection (secConfig, SECTION_SSL_VERIFY_FILE, SSL_VERIFY_FILE);
+ getSingleSection (secConfig, SECTION_SSL_VERIFY_DIR, SSL_VERIFY_DIR);
+
+ if (getSingleSection (secConfig, SECTION_SSL_VERIFY, strTemp))
+ SSL_VERIFY = beast::lexicalCastThrow (strTemp);
+
+ if (getSingleSection (secConfig, SECTION_VALIDATION_SEED, strTemp))
+ {
+ VALIDATION_SEED.setSeedGeneric (strTemp);
+
+ if (VALIDATION_SEED.isValid ())
+ {
+ VALIDATION_PUB = RippleAddress::createNodePublic (VALIDATION_SEED);
+ VALIDATION_PRIV = RippleAddress::createNodePrivate (VALIDATION_SEED);
+ }
+ }
+
+ if (getSingleSection (secConfig, SECTION_NODE_SEED, strTemp))
+ {
+ NODE_SEED.setSeedGeneric (strTemp);
+
+ if (NODE_SEED.isValid ())
+ {
+ NODE_PUB = RippleAddress::createNodePublic (NODE_SEED);
+ NODE_PRIV = RippleAddress::createNodePrivate (NODE_SEED);
+ }
+ }
+
+ if (getSingleSection (secConfig, SECTION_NETWORK_QUORUM, strTemp))
+ NETWORK_QUORUM = beast::lexicalCastThrow (strTemp);
+
+ if (getSingleSection (secConfig, SECTION_VALIDATION_QUORUM, strTemp))
+ VALIDATION_QUORUM = std::max (0, beast::lexicalCastThrow (strTemp));
+
+ if (getSingleSection (secConfig, SECTION_FEE_ACCOUNT_RESERVE, strTemp))
+ FEE_ACCOUNT_RESERVE = beast::lexicalCastThrow (strTemp);
+
+ if (getSingleSection (secConfig, SECTION_FEE_OWNER_RESERVE, strTemp))
+ FEE_OWNER_RESERVE = beast::lexicalCastThrow (strTemp);
+
+ if (getSingleSection (secConfig, SECTION_FEE_OFFER, strTemp))
+ FEE_OFFER = beast::lexicalCastThrow (strTemp);
+
+ if (getSingleSection (secConfig, SECTION_FEE_DEFAULT, strTemp))
+ FEE_DEFAULT = beast::lexicalCastThrow (strTemp);
+
+ if (getSingleSection (secConfig, SECTION_FEE_OPERATION, strTemp))
+ FEE_CONTRACT_OPERATION = beast::lexicalCastThrow (strTemp);
+
+ if (getSingleSection (secConfig, SECTION_LEDGER_HISTORY, strTemp))
+ {
+ boost::to_lower (strTemp);
+
+ if (strTemp == "full")
+ LEDGER_HISTORY = 1000000000u;
+ else if (strTemp == "none")
+ LEDGER_HISTORY = 0;
+ else
+ LEDGER_HISTORY = beast::lexicalCastThrow (strTemp);
+ }
+
+ if (getSingleSection (secConfig, SECTION_FETCH_DEPTH, strTemp))
+ {
+ boost::to_lower (strTemp);
+
+ if (strTemp == "none")
+ FETCH_DEPTH = 0;
+ else if (strTemp == "full")
+ FETCH_DEPTH = 1000000000u;
+ else
+ FETCH_DEPTH = beast::lexicalCastThrow (strTemp);
+
+ if (FETCH_DEPTH < 10)
+ FETCH_DEPTH = 10;
+ }
+
+ if (getSingleSection (secConfig, SECTION_PATH_SEARCH_OLD, strTemp))
+ PATH_SEARCH_OLD = beast::lexicalCastThrow (strTemp);
+ if (getSingleSection (secConfig, SECTION_PATH_SEARCH, strTemp))
+ PATH_SEARCH = beast::lexicalCastThrow (strTemp);
+ if (getSingleSection (secConfig, SECTION_PATH_SEARCH_FAST, strTemp))
+ PATH_SEARCH_FAST = beast::lexicalCastThrow (strTemp);
+ if (getSingleSection (secConfig, SECTION_PATH_SEARCH_MAX, strTemp))
+ PATH_SEARCH_MAX = beast::lexicalCastThrow (strTemp);
+
+ if (getSingleSection (secConfig, SECTION_ACCOUNT_PROBE_MAX, strTemp))
+ ACCOUNT_PROBE_MAX = beast::lexicalCastThrow (strTemp);
+
+ (void) getSingleSection (secConfig, SECTION_SMS_FROM, SMS_FROM);
+ (void) getSingleSection (secConfig, SECTION_SMS_KEY, SMS_KEY);
+ (void) getSingleSection (secConfig, SECTION_SMS_SECRET, SMS_SECRET);
+ (void) getSingleSection (secConfig, SECTION_SMS_TO, SMS_TO);
+ (void) getSingleSection (secConfig, SECTION_SMS_URL, SMS_URL);
+
+ if (getSingleSection (secConfig, SECTION_VALIDATORS_FILE, strTemp))
+ {
+ VALIDATORS_FILE = strTemp;
+ }
+
+ if (getSingleSection (secConfig, SECTION_DEBUG_LOGFILE, strTemp))
+ DEBUG_LOGFILE = strTemp;
}
int Config::getSize (SizedItemName item) const
@@ -702,19 +686,12 @@ boost::filesystem::path Config::getDebugLogFile () const
return log_file;
}
-//------------------------------------------------------------------------------
-//
-// VFALCO NOTE Clean members area
-//
-
Config& getConfig ()
{
static Config config;
return config;
}
-//------------------------------------------------------------------------------
-
beast::File Config::getConfigDir () const
{
beast::String const s (CONFIG_FILE.native().c_str ());
@@ -723,14 +700,6 @@ beast::File Config::getConfigDir () const
return beast::File::nonexistent ();
}
-beast::File Config::getDatabaseDir () const
-{
- beast::String const s (DATA_DIR.native().c_str());
- if (s.isNotEmpty ())
- return beast::File (s);
- return beast::File::nonexistent ();
-}
-
beast::File Config::getValidatorsFile () const
{
beast::String const s (VALIDATORS_FILE.native().c_str());
@@ -744,9 +713,14 @@ beast::URL Config::getValidatorsURL () const
return beast::parse_URL (VALIDATORS_SITE).second;
}
-beast::File const& Config::getModuleDatabasePath ()
+beast::File Config::getModuleDatabasePath () const
{
- return m_moduleDbPath;
+ boost::filesystem::path dbPath (legacy ("database_path"));
+
+ beast::String const s (dbPath.native ().c_str ());
+ if (s.isNotEmpty ())
+ return beast::File (s);
+ return beast::File::nonexistent ();
}
} // ripple
diff --git a/src/ripple/core/tests/Config.test.cpp b/src/ripple/core/tests/Config.test.cpp
new file mode 100644
index 0000000000..573b14f3a4
--- /dev/null
+++ b/src/ripple/core/tests/Config.test.cpp
@@ -0,0 +1,356 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of rippled: https://github.com/ripple/rippled
+ Copyright (c) 2012-2015 Ripple Labs Inc.
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace ripple {
+namespace detail {
+std::string configContents (std::string const& dbPath)
+{
+ static boost::format configContentsTemplate (R"rippleConfig(
+[server]
+port_rpc
+port_peer
+port_wss_admin
+
+[port_rpc]
+port = 5005
+ip = 127.0.0.1
+admin = allow
+protocol = https
+
+[port_peer]
+port = 51235
+ip = 0.0.0.0
+protocol = peer
+
+[port_wss_admin]
+port = 6006
+ip = 127.0.0.1
+admin = allow
+protocol = wss
+
+#[port_ws_public]
+#port = 5005
+#ip = 127.0.0.1
+#protocol = wss
+
+#-------------------------------------------------------------------------------
+
+[node_size]
+medium
+
+# This is primary persistent datastore for rippled. This includes transaction
+# metadata, account states, and ledger headers. Helpful information can be
+# found here: https://ripple.com/wiki/NodeBackEnd
+# delete old ledgers while maintaining at least 2000. Do not require an
+# external administrative command to initiate deletion.
+[node_db]
+type=memory
+path=/Users/dummy/ripple/config/db/rocksdb
+open_files=2000
+filter_bits=12
+cache_mb=256
+file_size_mb=8
+file_size_mult=2
+
+%1%
+%2%
+
+# This needs to be an absolute directory reference, not a relative one.
+# Modify this value as required.
+[debug_logfile]
+/Users/dummy/ripple/config/log/debug.log
+
+[sntp_servers]
+time.windows.com
+time.apple.com
+time.nist.gov
+pool.ntp.org
+
+# Where to find some other servers speaking the Ripple protocol.
+#
+[ips]
+r.ripple.com 51235
+
+# The latest validators can be obtained from
+# https://ripple.com/ripple.txt
+#
+[validators]
+n949f75evCHwgyP4fPVgaHqNHxUVN15PsJEZ3B3HnXPcPjcZAoy7 RL1
+n9MD5h24qrQqiyBC8aeqqCWvpiBiYQ3jxSr91uiDvmrkyHRdYLUj RL2
+n9L81uNCaPgtUJfaHh89gmdvXKAmSt5Gdsw2g1iPWaPkAHW5Nm4C RL3
+n9KiYM9CgngLvtRCQHZwgC2gjpdaZcCcbt3VboxiNFcKuwFVujzS RL4
+n9LdgEtkmGB9E2h3K4Vp7iGUaKuq23Zr32ehxiU8FWY7xoxbWTSA RL5
+
+# Ditto.
+[validation_quorum]
+3
+
+# Turn down default logging to save disk space in the long run.
+# Valid values here are trace, debug, info, warning, error, and fatal
+[rpc_startup]
+{ "command": "log_level", "severity": "warning" }
+
+# Defaults to 1 ("yes") so that certificates will be validated. To allow the use
+# of self-signed certificates for development or internal use, set to 0 ("no").
+[ssl_verify]
+0
+
+[sqdb]
+backend=sqlite
+)rippleConfig");
+
+ if (!dbPath.empty ())
+ return boost::str (configContentsTemplate % "[database_path]" % dbPath);
+ else
+ return boost::str (configContentsTemplate % "" % "");
+}
+
+/**
+ Write a config file and remove when done.
+ */
+class ConfigGuard
+{
+private:
+ using path = boost::filesystem::path;
+ path subDir_;
+ path configFile_;
+ path dataDir_;
+
+ bool rmSubDir_{false};
+ bool rmDataDir_{false};
+
+ Config config_;
+
+public:
+ ConfigGuard (std::string subDir, std::string const& dbPath)
+ : subDir_ (std::move (subDir)), dataDir_ (dbPath)
+ {
+ using namespace boost::filesystem;
+
+ if (dbPath.empty ())
+ {
+ dataDir_ = subDir_ / path (Config::Helpers::getDatabaseDirName ());
+ }
+
+ configFile_ = subDir_ / path (Config::Helpers::getConfigFileName ());
+ {
+ if (!exists (subDir_))
+ {
+ create_directory (subDir_);
+ rmSubDir_ = true;
+ }
+ else if (is_directory (subDir_))
+ rmSubDir_ = false;
+ else
+ {
+ // Cannot run the test someone created a file where we want to
+ // put out directory
+ throw std::runtime_error ("Cannot create directory: " +
+ subDir_.string ());
+ }
+ }
+
+ if (!exists (configFile_))
+ {
+ std::ofstream o (configFile_.string ());
+ o << configContents (dbPath);
+ }
+ else
+ {
+ throw std::runtime_error (
+ "Refusing to overwrite existing config file: " +
+ configFile_.string ());
+ }
+
+ rmDataDir_ = !exists (dataDir_);
+ config_.setup (configFile_.string (), /*bQuiet*/ false);
+ }
+ Config& config ()
+ {
+ return config_;
+ }
+ bool dataDirExists () const
+ {
+ return boost::filesystem::is_directory (dataDir_);
+ }
+ bool configFileExists () const
+ {
+ return boost::filesystem::is_regular_file (configFile_);
+ }
+ ~ConfigGuard ()
+ {
+ try
+ {
+ using namespace boost::filesystem;
+ if (!is_regular_file (configFile_))
+ std::cerr << "Expected " << configFile_.string ()
+ << " to be an existing file.\n";
+ else
+ remove (configFile_.string ());
+
+ auto rmDir = [](path const& toRm)
+ {
+ if (is_directory (toRm) && is_empty (toRm))
+ remove (toRm);
+ else
+ std::cerr << "Expected " << toRm.string ()
+ << " to be an empty existing directory.\n";
+ };
+
+ if (rmDataDir_)
+ rmDir (dataDir_);
+ else
+ std::cerr << "Skipping rm dir: " << dataDir_.string () << "\n";
+
+ if (rmSubDir_)
+ rmDir (subDir_);
+ else
+ std::cerr << "Skipping rm dir: " << subDir_.string () << "\n";
+ }
+ catch (std::exception& e)
+ {
+ // if we throw here, just let it die.
+ std::cerr << "Error in CreateConfigGuard: " << e.what () << "\n";
+ };
+ }
+};
+} // detail
+class Config_test final : public TestSuite
+{
+private:
+ using path = boost::filesystem::path;
+
+public:
+ void testLegacy ()
+ {
+ testcase ("legacy");
+
+ Config c;
+
+ std::string toLoad(R"rippleConfig(
+[server]
+port_rpc
+port_peer
+port_wss_admin
+
+[ssl_verify]
+0
+
+[validation_quorum]
+3
+)rippleConfig");
+
+ c.loadFromString (toLoad);
+
+ expect (c.legacy ("ssl_verify") == "0");
+ expectException ([&c] {c.legacy ("server");}); // not a single line
+
+ // set a legacy value
+ expect (c.legacy ("not_in_file") == "");
+ c.legacy ("not_in_file", "new_value");
+ expect (c.legacy ("not_in_file") == "new_value");
+ }
+ void testDbPath ()
+ {
+ testcase ("database_path");
+
+ using namespace boost::filesystem;
+ {
+ boost::format cc ("[database_path]\n%1%\n");
+
+ auto const cwd = current_path ();
+ path const dataDirRel ("test_data_dir");
+ path const dataDirAbs (cwd / dataDirRel);
+ {
+ // Dummy test - do we get back what we put in
+ Config c;
+ c.loadFromString (boost::str (cc % dataDirAbs.string ()));
+ expect (c.legacy ("database_path") == dataDirAbs.string ());
+ }
+ {
+ // Rel paths should convert to abs paths
+ Config c;
+ c.loadFromString (boost::str (cc % dataDirRel.string ()));
+ expect (c.legacy ("database_path") == dataDirAbs.string ());
+ }
+ {
+ // No db sectcion.
+ // N.B. Config::setup will give database_path a default,
+ // load will not.
+ Config c;
+ c.loadFromString ("");
+ expect (c.legacy ("database_path") == "");
+ }
+ }
+ {
+ // read from file absolute path
+ auto const cwd = current_path ();
+ path const dataDirRel ("test_data_dir");
+ path const dataDirAbs (cwd / path ("test_db") / dataDirRel);
+ detail::ConfigGuard g ("test_db", dataDirAbs.string ());
+ auto& c (g.config ());
+ expect (g.dataDirExists ());
+ expect (g.configFileExists ());
+ expect (c.legacy ("database_path") == dataDirAbs.string (),
+ "dbPath Abs Path File");
+ }
+ {
+ // read from file relative path
+ std::string const dbPath ("my_db");
+ detail::ConfigGuard g ("test_db", dbPath);
+ auto& c (g.config ());
+ std::string const nativeDbPath = absolute (path (dbPath)).string ();
+ expect (g.dataDirExists ());
+ expect (g.configFileExists ());
+ expect (c.legacy ("database_path") == nativeDbPath,
+ "dbPath Rel Path File");
+ }
+ {
+ // read from file no path
+ detail::ConfigGuard g ("test_db", "");
+ auto& c (g.config ());
+ std::string const nativeDbPath =
+ absolute (path ("test_db") /
+ path (Config::Helpers::getDatabaseDirName ()))
+ .string ();
+ expect (g.dataDirExists ());
+ expect (g.configFileExists ());
+ expect (c.legacy ("database_path") == nativeDbPath,
+ "dbPath No Path");
+ }
+ }
+ void run ()
+ {
+ testLegacy ();
+ testDbPath ();
+ }
+};
+
+BEAST_DEFINE_TESTSUITE (Config, core, ripple);
+
+} // ripple
diff --git a/src/ripple/unity/core.cpp b/src/ripple/unity/core.cpp
index 010adda39e..033e90b08a 100644
--- a/src/ripple/unity/core.cpp
+++ b/src/ripple/unity/core.cpp
@@ -27,3 +27,4 @@
#include
#include
+#include