diff --git a/Builds/VisualStudio2013/RippleD.vcxproj b/Builds/VisualStudio2013/RippleD.vcxproj index a772a4eec0..042aea9eb5 100644 --- a/Builds/VisualStudio2013/RippleD.vcxproj +++ b/Builds/VisualStudio2013/RippleD.vcxproj @@ -795,85 +795,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - True - - - True - - - True - - - True - - - True - - - True - - - True - - - True - - - True - - - True - - - True - - - True - - - - - True - @@ -1535,6 +1456,20 @@ + + True + True + ..\..\src\soci\src\core;..\..\src\sqlite;%(AdditionalIncludeDirectories) + ..\..\src\soci\src\core;..\..\src\sqlite;%(AdditionalIncludeDirectories) + + + True + True + ..\..\src\soci\src\core;..\..\src\sqlite;%(AdditionalIncludeDirectories) + ..\..\src\soci\src\core;..\..\src\sqlite;%(AdditionalIncludeDirectories) + + + True True @@ -1543,6 +1478,12 @@ + + True + True + ..\..\src\soci\src\core;..\..\src\sqlite;%(AdditionalIncludeDirectories) + ..\..\src\soci\src\core;..\..\src\sqlite;%(AdditionalIncludeDirectories) + True True @@ -4382,8 +4323,182 @@ + + + + True + + + True + + + + + True + + + True + + + True + + + + + True + + + True + + + True + + + True + + + True + + + + + + + True + + + + + + + + + + + + + True + + + + + True + + + + + True + + + + + + + True + + + + + + + True + + + + + True + + + + + True + + + + + + + True + + + + + True + + + + + + + True + + + + + + + True + + + + + + + True + + + + + + + + + + + True + + + + + + + True + + + + + True + + + + + + + + + + + + + + + True + + + + + + + + + True + + + + + diff --git a/Builds/VisualStudio2013/RippleD.vcxproj.filters b/Builds/VisualStudio2013/RippleD.vcxproj.filters index db4b3ac713..8a60aa5d16 100644 --- a/Builds/VisualStudio2013/RippleD.vcxproj.filters +++ b/Builds/VisualStudio2013/RippleD.vcxproj.filters @@ -139,18 +139,6 @@ {FEAEA931-9FBB-1723-2676-9115C88A7A91} - - {C0E15D88-0464-5647-4456-2B7D1D035D96} - - - {9D06F3E0-B69D-2375-0CDB-EFADCCB10AA7} - - - {4A5C6976-0040-11F9-2847-EF7966479B6D} - - - {DE6FE26E-81A4-F99F-CCA4-6E59C53026D1} - {81C8331F-4768-BDE6-D058-29BDEE8F322C} @@ -280,6 +268,9 @@ {44B63F90-BC60-A7C7-24A1-632A358E285B} + + {29C76FB9-636F-FBFC-3CFA-2979281BC279} + {17F94278-7CDE-3EBE-7CD3-372F08902314} @@ -550,9 +541,21 @@ {5A1D8022-39F2-67E1-FFBE-EA7D5BF9FBDB} + + {AA927DBA-1AF8-6600-04B7-D1C1EBFB4103} + + + {5D2927A9-CC6E-DDE0-1654-5316177082DD} + + + {75E6832F-A6F7-8360-FA3A-7427A06A9959} + {D4BF99B9-6486-2124-6103-825710EDD595} + + {FA8496D0-0D5F-AC6F-3422-DEAB4BA19ACA} + {EE7AC8C9-27EB-C05E-C986-EECB0174B997} @@ -1377,105 +1380,6 @@ beast\module\core\time - - beast\module\sqdb\api - - - beast\module\sqdb\api - - - beast\module\sqdb\api - - - beast\module\sqdb\api - - - beast\module\sqdb\api - - - beast\module\sqdb\api - - - beast\module\sqdb\api - - - beast\module\sqdb\api - - - beast\module\sqdb\detail - - - beast\module\sqdb\detail - - - beast\module\sqdb\detail - - - beast\module\sqdb\detail - - - beast\module\sqdb\detail - - - beast\module\sqdb\detail - - - beast\module\sqdb\detail - - - beast\module\sqdb\detail - - - beast\module\sqdb\detail - - - beast\module\sqdb\detail - - - beast\module\sqdb\detail - - - beast\module\sqdb\source - - - beast\module\sqdb\source - - - beast\module\sqdb\source - - - beast\module\sqdb\source - - - beast\module\sqdb\source - - - beast\module\sqdb\source - - - beast\module\sqdb\source - - - beast\module\sqdb\source - - - beast\module\sqdb\source - - - beast\module\sqdb\source - - - beast\module\sqdb\source - - - beast\module\sqdb\source - - - beast\module\sqdb - - - beast\module\sqdb - beast\module\sqlite @@ -2286,12 +2190,24 @@ ripple\app\data + + ripple\app\data + + + ripple\app\data + + + ripple\app\data + ripple\app\data ripple\app\data + + ripple\app\data\tests + ripple\app\impl @@ -5148,9 +5064,228 @@ snappy\snappy + + soci\src\backends\postgresql + + + soci\src\backends\sqlite3 + + + soci\src\backends\sqlite3 + + + soci\src\backends\sqlite3 + + + soci\src\backends\sqlite3 + + + soci\src\backends\sqlite3 + + + soci\src\backends\sqlite3 + + + soci\src\backends\sqlite3 + + + soci\src\backends\sqlite3 + + + soci\src\backends\sqlite3 + + + soci\src\backends\sqlite3 + + + soci\src\backends\sqlite3 + + + soci\src\backends\sqlite3 + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + + + soci\src\core + soci\src\core + + sqlite + websocketpp\websocketpp\base64 diff --git a/src/ripple/app/data/DummySociDynamicBackend.cpp b/src/ripple/app/data/DummySociDynamicBackend.cpp new file mode 100644 index 0000000000..37bef26cbc --- /dev/null +++ b/src/ripple/app/data/DummySociDynamicBackend.cpp @@ -0,0 +1,59 @@ +//------------------------------------------------------------------------------ +/* + 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. +*/ +//============================================================================== + +/** Stub functions for soci dynamic backends. + + Ripple does not use dynamic backends, and inclduing soci's + dynamic backends compilcates the build (it requires a generated + header file and some macros to be defines.) +*/ + +#include + +#include + +// dummy soci-backend +namespace soci { +namespace dynamic_backends { +// used internally by session +backend_factory const& get (std::string const& name) +{ + throw std::runtime_error ("Not Supported"); + backend_factory* nullBF{nullptr}; + return *nullBF; // deref nullptr - but we already threw +}; + +// provided for advanced user-level management +std::vector& search_paths () +{ + static std::vector empty; + return empty; +}; +void register_backend (std::string const&, std::string const&){}; +void register_backend (std::string const&, backend_factory const&){}; +std::vector list_all () +{ + return {}; +}; +void unload (std::string const&){}; +void unload_all (){}; + +} // namespace dynamic_backends +} // namespace soci + diff --git a/src/ripple/app/data/SociDB.cpp b/src/ripple/app/data/SociDB.cpp new file mode 100644 index 0000000000..2a79487999 --- /dev/null +++ b/src/ripple/app/data/SociDB.cpp @@ -0,0 +1,173 @@ +//------------------------------------------------------------------------------ +/* + 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. +*/ +//============================================================================== + +/** An embedded database wrapper with an intuitive, type-safe interface. + + This collection of classes let's you access embedded SQLite databases + using C++ syntax that is very similar to regular SQL. + + This module requires the @ref beast_sqlite external module. +*/ + +#include + +#include +#include +#include +#include // +#include +#if ENABLE_SOCI_POSTGRESQL +#include +#endif +#include + +namespace ripple { +namespace detail { + +std::pair +getSociSqliteInit (std::string const& name, + std::string const& dir, + std::string const& ext) +{ + if (dir.empty () || name.empty ()) + { + throw std::runtime_error ( + "Sqlite databases must specify a dir and a name. Name: " + + name + " Dir: " + dir); + } + boost::filesystem::path file (dir); + if (is_directory (file)) + file /= name + ext; + return std::make_pair (file.string (), std::ref(soci::sqlite3)); +} + +#if ENABLE_SOCI_POSTGRESQL +std::pair +getSociPostgresqlInit (Section const& configSection, + std::string const& name) +{ + if (name.empty ()) + { + throw std::runtime_error ( + "Missing required value for postgresql backend: database name"); + } + + std::string const host(get (configSection, "host", "")); + if (!host.empty()) + { + throw std::runtime_error ( + "Missing required value in config for postgresql backend: host"); + } + + std::string const user(get (configSection, "user", "")); + if (user.empty ()) + { + throw std::runtime_error ( + "Missing required value in config for postgresql backend: user"); + } + + int const port = [&configSection] + { + std::string const portAsString ( + get (configSection, "port", "")); + if (portAsString.empty ()) + { + throw std::runtime_error ( + "Missing required value in config for postgresql backend: " + "user"); + } + try + { + return std::stoi (portAsString); + } + catch (...) + { + throw std::runtime_error ( + "The port value in the config for the postgresql backend must " + "be an integer. Got: " + + portAsString); + } + }(); + + std::stringstream s; + s << "host=" << host << " port=" << port << " dbname=" << name + << " user=" << user; + return std::make_pair (s.str (), std::ref(soci::postgresql)); +} +#endif // ENABLE_SOCI_POSTGRESQL + +std::pair +getSociInit (BasicConfig const& config, + std::string const& dbName) +{ + static const std::string sectionName ("sqdb"); + static const std::string keyName ("backend"); + auto const& section = config.section (sectionName); + std::string const backendName(get(section, keyName, std::string("sqlite"))); + + if (backendName == "sqlite") + { + std::string const path = config.legacy ("database_path"); + std::string const ext = + (dbName == "validators" || dbName == "peerfinder") ? ".sqlite" + : ".db"; + return detail::getSociSqliteInit(dbName, path, ext); + } +#if ENABLE_SOCI_POSTGRESQL + else if (backendName == "postgresql") + { + return detail::getSociPostgresqlInit(section, dbName); + } +#endif + else + { + throw std::runtime_error ("Unsupported soci backend: " + backendName); + } +} +} // detail + +SociConfig::SociConfig(std::pair init) + :connectionString_(std::move(init.first)), + backendFactory_(init.second){} + +SociConfig::SociConfig(BasicConfig const& config, + std::string const& dbName) + : SociConfig(detail::getSociInit(config, dbName)) +{ +} + +std::string SociConfig::connectionString () const +{ + return connectionString_; +} + +void SociConfig::open(soci::session& s) const +{ + s.open (backendFactory_, connectionString ()); +} + +void open(soci::session& s, + BasicConfig const& config, + std::string const& dbName) +{ + SociConfig c(config, dbName); + c.open(s); +} +} + diff --git a/src/ripple/app/data/SociDB.h b/src/ripple/app/data/SociDB.h new file mode 100644 index 0000000000..8c4e1566c5 --- /dev/null +++ b/src/ripple/app/data/SociDB.h @@ -0,0 +1,79 @@ +//------------------------------------------------------------------------------ +/* + 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. +*/ +//============================================================================== + +#ifndef RIPPLE_SOCIDB_H_INCLUDED +#define RIPPLE_SOCIDB_H_INCLUDED + +/** An embedded database wrapper with an intuitive, type-safe interface. + + This collection of classes let's you access embedded SQLite databases + using C++ syntax that is very similar to regular SQL. + + This module requires the @ref beast_sqlite external module. +*/ + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning( \ + disable : 4355) // 'this' : used in base member initializer list +#endif + +#include + +namespace ripple { +class BasicConfig; + +/** + * SociConfig is used when a client wants to delay opening a soci::session after + * parsing the config parameters. If a client want to open a session immediately, + * use the free function "open" below. + */ +class SociConfig final +{ + std::string connectionString_; + soci::backend_factory const& backendFactory_; + SociConfig(std::pair init); +public: + SociConfig(BasicConfig const& config, + std::string const& dbName); + std::string connectionString () const; + void open(soci::session& s) const; +}; + +/** + * Open a soci session. + * + * @param s Session to open. + * @param config Parameters to pick the soci backend and how to connect to that + * backend. + * @param dbName Name of the database. This has different meaning for different backends. + * Sometimes it is part of a filename (sqlite3), othertimes it is a + * database name (postgresql). + */ +void open(soci::session& s, + BasicConfig const& config, + std::string const& dbName); + +} + +#if _MSC_VER +#pragma warning(pop) +#endif + +#endif diff --git a/src/ripple/app/data/tests/SociDB.test.cpp b/src/ripple/app/data/tests/SociDB.test.cpp new file mode 100644 index 0000000000..e10a44b826 --- /dev/null +++ b/src/ripple/app/data/tests/SociDB.test.cpp @@ -0,0 +1,197 @@ +//------------------------------------------------------------------------------ +/* + 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 + +namespace ripple { +class SociDB_test final : public TestSuite +{ +private: + static void setupSQLiteConfig (BasicConfig& config, + boost::filesystem::path const& dbPath) + { + config.overwrite ("sqdb", "backend", "sqlite"); + auto value = dbPath.string (); + if (!value.empty ()) + config.legacy ("database_path", value); + } + + static void setupPostgresqlConfig (BasicConfig& config, + std::string const& host, + std::string const& user, + std::string const& port) + { + config.overwrite ("sqdb", "backend", "postgresql"); + if (!host.empty ()) + config.overwrite ("sqdb", "host", host); + if (!user.empty ()) + config.overwrite ("sqdb", "user", user); + if (!port.empty ()) + config.overwrite ("sqdb", "port", port); + } + + static void cleanupDatabaseDir (boost::filesystem::path const& dbPath) + { + using namespace boost::filesystem; + if (!exists (dbPath) || !is_directory (dbPath) || !is_empty (dbPath)) + return; + remove (dbPath); + } + + static void setupDatabaseDir (boost::filesystem::path const& dbPath) + { + using namespace boost::filesystem; + if (!exists (dbPath)) + { + create_directory (dbPath); + return; + } + + if (!is_directory (dbPath)) + { + // someone created a file where we want to put out directory + throw std::runtime_error ("Cannot create directory: " + + dbPath.string ()); + } + } + static boost::filesystem::path getDatabasePath () + { + return boost::filesystem::current_path () / "socidb_test_databases"; + } + +public: + SociDB_test () + { + try + { + setupDatabaseDir (getDatabasePath ()); + } + catch (...) + { + } + } + ~SociDB_test () + { + try + { + cleanupDatabaseDir (getDatabasePath ()); + } + catch (...) + { + } + } + void testSQLiteFileNames () + { + // confirm that files are given the correct exensions + testcase ("sqliteFileNames"); + BasicConfig c; + setupSQLiteConfig (c, getDatabasePath ()); + std::vector> const d ( + {{"peerfinder", ".sqlite"}, + {"state", ".db"}, + {"random", ".db"}, + {"validators", ".sqlite"}}); + + for (auto const& i : d) + { + SociConfig sc (c, i.first); + expect (boost::ends_with (sc.connectionString (), + std::string (i.first) + i.second)); + } + } + void testSQLiteSession () + { + testcase ("open"); + BasicConfig c; + setupSQLiteConfig (c, getDatabasePath ()); + SociConfig sc (c, "SociTestDB"); + std::vector const stringData ( + {"String1", "String2", "String3"}); + std::vector const intData ({1, 2, 3}); + auto checkValues = [this, &stringData, &intData](soci::session& s) + { + // Check values in db + std::vector stringResult (20 * stringData.size ()); + std::vector intResult (20 * intData.size ()); + s << "SELECT StringData, IntData FROM SociTestTable", + soci::into (stringResult), soci::into (intResult); + expect (stringResult.size () == stringData.size () && + intResult.size () == intData.size ()); + for (int i = 0; i < stringResult.size (); ++i) + { + auto si = std::distance (stringData.begin (), + std::find (stringData.begin (), + stringData.end (), + stringResult[i])); + auto ii = std::distance ( + intData.begin (), + std::find (intData.begin (), intData.end (), intResult[i])); + expect (si == ii && si < stringResult.size ()); + } + }; + + { + soci::session s; + sc.open (s); + s << "CREATE TABLE IF NOT EXISTS SociTestTable (" + " Key INTEGER PRIMARY KEY," + " StringData TEXT," + " IntData INTEGER" + ");"; + + s << "INSERT INTO SociTestTable (StringData, IntData) VALUES " + "(:stringData, :intData);", + soci::use (stringData), soci::use (intData); + checkValues (s); + } + { + // Check values in db after session was closed + soci::session s; + sc.open (s); + checkValues (s); + } + { + using namespace boost::filesystem; + // Remove the database + path dbPath (sc.connectionString ()); + if (is_regular_file (dbPath)) + remove (dbPath); + } + } + void testSQLite () + { + testSQLiteFileNames (); + testSQLiteSession (); + } + void run () + { + testSQLite (); + } +}; + +BEAST_DEFINE_TESTSUITE (SociDB, app, ripple); + +} // ripple diff --git a/src/ripple/app/main/Application.cpp b/src/ripple/app/main/Application.cpp index d4520f9c33..c582b811c2 100644 --- a/src/ripple/app/main/Application.cpp +++ b/src/ripple/app/main/Application.cpp @@ -329,7 +329,7 @@ public: , m_shaMapStore (make_SHAMapStore (setup_SHAMapStore ( getConfig()), *this, m_nodeStoreScheduler, m_logs.journal ("SHAMapStore"), m_logs.journal ("NodeObject"), - m_txMaster)) + m_txMaster, getConfig())) , m_nodeStore (m_shaMapStore->makeDatabase ("NodeStore.main", 4)) @@ -394,7 +394,7 @@ public: , m_sntpClient (SNTPClient::New (*this)) , m_validators (Validators::make_Manager(*this, get_io_service(), - getConfig ().getModuleDatabasePath (), m_logs.journal("UVL"))) + m_logs.journal("UVL"), getConfig ())) , m_amendmentTable (make_AmendmentTable (weeks(2), MAJORITY_FRACTION, @@ -797,9 +797,8 @@ public: // // if (!getConfig ().RUN_STANDALONE) m_overlay = make_Overlay (setup_Overlay(getConfig()), *m_jobQueue, - *serverHandler_, *m_resourceManager, - getConfig ().getModuleDatabasePath (), *m_resolver, - get_io_service()); + *serverHandler_, *m_resourceManager, *m_resolver, get_io_service(), + getConfig()); add (*m_overlay); // add to PropertyStream { diff --git a/src/ripple/app/main/Main.cpp b/src/ripple/app/main/Main.cpp index cb703613ef..9650d90f28 100644 --- a/src/ripple/app/main/Main.cpp +++ b/src/ripple/app/main/Main.cpp @@ -161,13 +161,14 @@ void printHelp (const po::options_description& desc) static void -setupConfigForUnitTests (Config* config) +setupConfigForUnitTests (Config& config) { config->overwrite (ConfigSection::nodeDatabase (), "type", "memory"); config->overwrite (ConfigSection::nodeDatabase (), "path", "main"); config->deprecatedClearSection (ConfigSection::tempNodeDatabase ()); config->deprecatedClearSection (ConfigSection::importNodeDatabase ()); + config.legacy("database_path", "DummyForUnitTests"); } static int runShutdownTests () @@ -201,7 +202,7 @@ static int runUnitTests (std::string const& pattern, std::string const& argument) { // Config needs to be set up before creating Application - setupConfigForUnitTests (&getConfig ()); + setupConfigForUnitTests (getConfig ()); // VFALCO TODO Remove dependence on constructing Application object std::unique_ptr app (make_Application (deprecatedLogs())); using namespace beast::unit_test; diff --git a/src/ripple/app/misc/SHAMapStore.h b/src/ripple/app/misc/SHAMapStore.h index 5a1977ddaa..a07ec0d3e7 100644 --- a/src/ripple/app/misc/SHAMapStore.h +++ b/src/ripple/app/misc/SHAMapStore.h @@ -85,7 +85,8 @@ make_SHAMapStore(SHAMapStore::Setup const& s, NodeStore::Scheduler& scheduler, beast::Journal journal, beast::Journal nodeStoreJournal, - TransactionMaster& transactionMaster); + TransactionMaster& transactionMaster, + BasicConfig const& conf); } #endif diff --git a/src/ripple/app/misc/SHAMapStoreImp.cpp b/src/ripple/app/misc/SHAMapStoreImp.cpp index 570a91f45e..c223771eb0 100644 --- a/src/ripple/app/misc/SHAMapStoreImp.cpp +++ b/src/ripple/app/misc/SHAMapStoreImp.cpp @@ -18,92 +18,85 @@ //============================================================================== #include + #include #include #include #include #include #include // +#include namespace ripple { - -void -SHAMapStoreImp::SavedStateDB::init (std::string const& databasePath, - std::string const& dbName) +void SHAMapStoreImp::SavedStateDB::init (BasicConfig const& config, + std::string const& dbName) { - boost::filesystem::path pathName = databasePath; - pathName /= dbName; + std::lock_guard lock (mutex_); - std::lock_guard lock (mutex_); + open(session_, config, dbName); - auto error = session_.open (pathName.string()); - checkError (error); + session_ << "PRAGMA synchronous=FULL;"; - session_.once (error) << "PRAGMA synchronous=FULL;"; - checkError (error); + session_ << + "CREATE TABLE IF NOT EXISTS DbState (" + " Key INTEGER PRIMARY KEY," + " WritableDb TEXT," + " ArchiveDb TEXT," + " LastRotatedLedger INTEGER" + ");" + ; - session_.once (error) << - "CREATE TABLE IF NOT EXISTS DbState (" - " Key INTEGER PRIMARY KEY," - " WritableDb TEXT," - " ArchiveDb TEXT," - " LastRotatedLedger INTEGER" - ");" - ; - checkError (error); - - session_.once (error) << - "CREATE TABLE IF NOT EXISTS CanDelete (" - " Key INTEGER PRIMARY KEY," - " CanDeleteSeq INTEGER" - ");" - ; + session_ << + "CREATE TABLE IF NOT EXISTS CanDelete (" + " Key INTEGER PRIMARY KEY," + " CanDeleteSeq INTEGER" + ");" + ; std::int64_t count = 0; - beast::sqdb::statement st = (session_.prepare << + soci::statement st = (session_.prepare << "SELECT COUNT(Key) FROM DbState WHERE Key = 1;" - , beast::sqdb::into (count) + , soci::into (count) ); - st.execute_and_fetch (error); - checkError (error); + st.execute (); + if (!st.fetch ()) + { + throw std::runtime_error("Failed to fetch Key Count from DbState."); + } if (!count) { - session_.once (error) << + session_ << "INSERT INTO DbState VALUES (1, '', '', 0);"; - checkError (error); } st = (session_.prepare << - "SELECT COUNT(Key) FROM CanDelete WHERE Key = 1;" - , beast::sqdb::into (count) - ); - st.execute_and_fetch (error); - checkError (error); + "SELECT COUNT(Key) FROM CanDelete WHERE Key = 1;" + , soci::into (count) + ); + st.execute (); + if (!st.fetch ()) + { + throw std::runtime_error ("Failed to fetch Key Count from CanDelete."); + } if (!count) { - session_.once (error) << + session_ << "INSERT INTO CanDelete VALUES (1, 0);"; - checkError (error); } } LedgerIndex SHAMapStoreImp::SavedStateDB::getCanDelete() { - beast::Error error; LedgerIndex seq; + std::lock_guard lock (mutex_); - { - std::lock_guard lock (mutex_); - - session_.once (error) << - "SELECT CanDeleteSeq FROM CanDelete WHERE Key = 1;" - , beast::sqdb::into (seq); - ; - } - checkError (error); + session_ << + "SELECT CanDeleteSeq FROM CanDelete WHERE Key = 1;" + , soci::into (seq); + ; return seq; } @@ -111,16 +104,12 @@ SHAMapStoreImp::SavedStateDB::getCanDelete() LedgerIndex SHAMapStoreImp::SavedStateDB::setCanDelete (LedgerIndex canDelete) { - beast::Error error; - { - std::lock_guard lock (mutex_); + std::lock_guard lock (mutex_); - session_.once (error) << - "UPDATE CanDelete SET CanDeleteSeq = ? WHERE Key = 1;" - , beast::sqdb::use (canDelete) - ; - } - checkError (error); + session_ << + "UPDATE CanDelete SET CanDeleteSeq = :canDelete WHERE Key = 1;" + , soci::use (canDelete) + ; return canDelete; } @@ -128,21 +117,16 @@ SHAMapStoreImp::SavedStateDB::setCanDelete (LedgerIndex canDelete) SHAMapStoreImp::SavedState SHAMapStoreImp::SavedStateDB::getState() { - beast::Error error; SavedState state; - { - std::lock_guard lock (mutex_); + std::lock_guard lock (mutex_); - session_.once (error) << - "SELECT WritableDb, ArchiveDb, LastRotatedLedger" - " FROM DbState WHERE Key = 1;" - , beast::sqdb::into (state.writableDb) - , beast::sqdb::into (state.archiveDb) - , beast::sqdb::into (state.lastRotated) - ; - } - checkError (error); + session_ << + "SELECT WritableDb, ArchiveDb, LastRotatedLedger" + " FROM DbState WHERE Key = 1;" + , soci::into (state.writableDb), soci::into (state.archiveDb) + , soci::into (state.lastRotated) + ; return state; } @@ -150,48 +134,28 @@ SHAMapStoreImp::SavedStateDB::getState() void SHAMapStoreImp::SavedStateDB::setState (SavedState const& state) { - beast::Error error; - - { - std::lock_guard lock (mutex_); - session_.once (error) << - "UPDATE DbState" - " SET WritableDb = ?," - " ArchiveDb = ?," - " LastRotatedLedger = ?" - " WHERE Key = 1;" - , beast::sqdb::use (state.writableDb) - , beast::sqdb::use (state.archiveDb) - , beast::sqdb::use (state.lastRotated) - ; - } - checkError (error); + std::lock_guard lock (mutex_); + session_ << + "UPDATE DbState" + " SET WritableDb = :writableDb," + " ArchiveDb = :archiveDb," + " LastRotatedLedger = :lastRotated" + " WHERE Key = 1;" + , soci::use (state.writableDb) + , soci::use (state.archiveDb) + , soci::use (state.lastRotated) + ; } void SHAMapStoreImp::SavedStateDB::setLastRotated (LedgerIndex seq) { - beast::Error error; - { - std::lock_guard lock (mutex_); - session_.once (error) << - "UPDATE DbState SET LastRotatedLedger = ?" - " WHERE Key = 1;" - , beast::sqdb::use (seq) - ; - } - checkError (error); -} - -void -SHAMapStoreImp::SavedStateDB::checkError (beast::Error const& error) -{ - if (error) - { - journal_.fatal << "state database error: " << error.code() - << ": " << error.getReasonText(); - throw std::runtime_error ("State database error."); - } + std::lock_guard lock (mutex_); + session_ << + "UPDATE DbState SET LastRotatedLedger = :seq" + " WHERE Key = 1;" + , soci::use (seq) + ; } SHAMapStoreImp::SHAMapStoreImp (Setup const& setup, @@ -199,7 +163,8 @@ SHAMapStoreImp::SHAMapStoreImp (Setup const& setup, NodeStore::Scheduler& scheduler, beast::Journal journal, beast::Journal nodeStoreJournal, - TransactionMaster& transactionMaster) + TransactionMaster& transactionMaster, + BasicConfig const& config) : SHAMapStore (parent) , setup_ (setup) , scheduler_ (scheduler) @@ -223,7 +188,7 @@ SHAMapStoreImp::SHAMapStoreImp (Setup const& setup, std::to_string (setup_.ledgerHistory) + ")"); } - state_db_.init (setup_.databasePath, dbName_); + state_db_.init (config, dbName_); dbPaths(); } @@ -718,10 +683,12 @@ make_SHAMapStore (SHAMapStore::Setup const& s, NodeStore::Scheduler& scheduler, beast::Journal journal, beast::Journal nodeStoreJournal, - TransactionMaster& transactionMaster) + TransactionMaster& transactionMaster, + BasicConfig const& config) { - return std::make_unique (s, parent, scheduler, - journal, nodeStoreJournal, transactionMaster); + return std::make_unique(s, parent, scheduler, + journal, nodeStoreJournal, transactionMaster, + config); } } diff --git a/src/ripple/app/misc/SHAMapStoreImp.h b/src/ripple/app/misc/SHAMapStoreImp.h index 8163ca59a3..3bafa80fbc 100644 --- a/src/ripple/app/misc/SHAMapStoreImp.h +++ b/src/ripple/app/misc/SHAMapStoreImp.h @@ -23,9 +23,9 @@ #include #include #include +#include #include #include -#include #include #include #include diff --git a/src/ripple/core/ConfigSections.h b/src/ripple/core/ConfigSections.h index 7c2d42b780..e3cde6de71 100644 --- a/src/ripple/core/ConfigSections.h +++ b/src/ripple/core/ConfigSections.h @@ -20,6 +20,8 @@ #ifndef RIPPLE_CORE_CONFIGSECTIONS_H_INCLUDED #define RIPPLE_CORE_CONFIGSECTIONS_H_INCLUDED +#include + namespace ripple { // VFALCO DEPRECATED in favor of the BasicConfig interface diff --git a/src/ripple/core/tests/Config.test.cpp b/src/ripple/core/tests/Config.test.cpp index 573b14f3a4..23b0f27e93 100644 --- a/src/ripple/core/tests/Config.test.cpp +++ b/src/ripple/core/tests/Config.test.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include diff --git a/src/ripple/overlay/impl/OverlayImpl.cpp b/src/ripple/overlay/impl/OverlayImpl.cpp index 43b8f0959f..af7c93dfd3 100644 --- a/src/ripple/overlay/impl/OverlayImpl.cpp +++ b/src/ripple/overlay/impl/OverlayImpl.cpp @@ -121,9 +121,9 @@ OverlayImpl::OverlayImpl ( Stoppable& parent, ServerHandler& serverHandler, Resource::Manager& resourceManager, - beast::File const& pathToDbFileOrDirectory, Resolver& resolver, - boost::asio::io_service& io_service) + boost::asio::io_service& io_service, + BasicConfig const& config) : Overlay (parent) , io_service_ (io_service) , work_ (boost::in_place(std::ref(io_service_))) @@ -133,8 +133,7 @@ OverlayImpl::OverlayImpl ( , serverHandler_(serverHandler) , m_resourceManager (resourceManager) , m_peerFinder (PeerFinder::make_Manager (*this, io_service, - pathToDbFileOrDirectory, get_seconds_clock(), - deprecatedLogs().journal("PeerFinder"))) + get_seconds_clock(), deprecatedLogs().journal("PeerFinder"), config)) , m_resolver (resolver) , next_id_(1) { @@ -752,12 +751,12 @@ make_Overlay ( beast::Stoppable& parent, ServerHandler& serverHandler, Resource::Manager& resourceManager, - beast::File const& pathToDbFileOrDirectory, Resolver& resolver, - boost::asio::io_service& io_service) + boost::asio::io_service& io_service, + BasicConfig const& config) { return std::make_unique (setup, parent, serverHandler, - resourceManager, pathToDbFileOrDirectory, resolver, io_service); + resourceManager, resolver, io_service, config); } } diff --git a/src/ripple/overlay/impl/OverlayImpl.h b/src/ripple/overlay/impl/OverlayImpl.h index cf412ab133..45ce13dfd1 100644 --- a/src/ripple/overlay/impl/OverlayImpl.h +++ b/src/ripple/overlay/impl/OverlayImpl.h @@ -44,6 +44,7 @@ namespace ripple { class PeerImp; +class BasicConfig; class OverlayImpl : public Overlay { @@ -122,8 +123,8 @@ private: public: OverlayImpl (Setup const& setup, Stoppable& parent, ServerHandler& serverHandler, Resource::Manager& resourceManager, - beast::File const& pathToDbFileOrDirectory, - Resolver& resolver, boost::asio::io_service& io_service); + Resolver& resolver, boost::asio::io_service& io_service, + BasicConfig const& config); ~OverlayImpl(); diff --git a/src/ripple/overlay/make_Overlay.h b/src/ripple/overlay/make_Overlay.h index 0408249ea0..12aaa7f5b7 100644 --- a/src/ripple/overlay/make_Overlay.h +++ b/src/ripple/overlay/make_Overlay.h @@ -41,9 +41,9 @@ make_Overlay ( beast::Stoppable& parent, ServerHandler& serverHandler, Resource::Manager& resourceManager, - beast::File const& pathToDbFileOrDirectory, Resolver& resolver, - boost::asio::io_service& io_service); + boost::asio::io_service& io_service, + BasicConfig const& config); } // ripple diff --git a/src/ripple/peerfinder/impl/Manager.cpp b/src/ripple/peerfinder/impl/Manager.cpp index 6770ea9866..d8f1a2e8c8 100644 --- a/src/ripple/peerfinder/impl/Manager.cpp +++ b/src/ripple/peerfinder/impl/Manager.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include // @@ -37,33 +38,31 @@ class ManagerImp public: boost::asio::io_service &io_service_; boost::optional work_; - beast::File m_databaseFile; clock_type& m_clock; beast::Journal m_journal; StoreSqdb m_store; Checker checker_; Logic m_logic; + SociConfig m_sociConfig; //-------------------------------------------------------------------------- ManagerImp ( Stoppable& stoppable, boost::asio::io_service& io_service, - beast::File const& pathToDbFileOrDirectory, clock_type& clock, - beast::Journal journal) + beast::Journal journal, + BasicConfig const& config) : Manager (stoppable) , io_service_(io_service) , work_(boost::in_place(std::ref(io_service_))) - , m_databaseFile (pathToDbFileOrDirectory) , m_clock (clock) , m_journal (journal) , m_store (journal) , checker_ (io_service_) , m_logic (clock, m_store, checker_, journal) + , m_sociConfig (config, "peerfinder") { - if (m_databaseFile.isDirectory ()) - m_databaseFile = m_databaseFile.getChildFile("peerfinder.sqlite"); } ~ManagerImp() @@ -214,12 +213,8 @@ public: void onPrepare () { - beast::Error error (m_store.open (m_databaseFile)); - if (error) - m_journal.fatal << - "Failed to open '" << m_databaseFile.getFullPathName() << "'"; - if (! error) - m_logic.load (); + m_store.open (m_sociConfig); + m_logic.load (); } void @@ -255,10 +250,10 @@ Manager::Manager (Stoppable& parent) std::unique_ptr make_Manager (beast::Stoppable& parent, boost::asio::io_service& io_service, - beast::File const& databaseFile, clock_type& clock, beast::Journal journal) + clock_type& clock, beast::Journal journal, BasicConfig const& config) { return std::make_unique ( - parent, io_service, databaseFile, clock, journal); + parent, io_service, clock, journal, config); } } diff --git a/src/ripple/peerfinder/impl/StoreSqdb.h b/src/ripple/peerfinder/impl/StoreSqdb.h index 81163a758b..91864daee6 100644 --- a/src/ripple/peerfinder/impl/StoreSqdb.h +++ b/src/ripple/peerfinder/impl/StoreSqdb.h @@ -20,7 +20,7 @@ #ifndef RIPPLE_PEERFINDER_STORESQDB_H_INCLUDED #define RIPPLE_PEERFINDER_STORESQDB_H_INCLUDED -#include +#include #include namespace ripple { @@ -32,8 +32,7 @@ class StoreSqdb { private: beast::Journal m_journal; - beast::sqdb::session m_session; - + soci::session m_session; public: enum { @@ -50,19 +49,15 @@ public: { } - beast::Error open (beast::File const& file) + void open (SociConfig const& sociConfig) { - beast::Error error (m_session.open (file.getFullPathName ())); + sociConfig.open (m_session); - m_journal.info << "Opening database at '" << file.getFullPathName() << "'"; + m_journal.info << "Opening database at '" << sociConfig.connectionString () + << "'"; - if (! error) - error = init (); - - if (! error) - error = update (); - - return error; + init (); + update (); } // Loads the bootstrap cache, calling the callback for each entry @@ -70,42 +65,34 @@ public: std::size_t load (load_callback const& cb) { std::size_t n (0); - beast::Error error; std::string s; int valence; - beast::sqdb::statement st = (m_session.prepare << + soci::statement st = (m_session.prepare << "SELECT " " address, " " valence " "FROM PeerFinder_BootstrapCache " - , beast::sqdb::into (s) - , beast::sqdb::into (valence) + , soci::into (s) + , soci::into (valence) ); - if (st.execute_and_fetch (error)) + st.execute (); + while (st.fetch ()) { - do + beast::IP::Endpoint const endpoint ( + beast::IP::Endpoint::from_string (s)); + + if (!is_unspecified (endpoint)) { - beast::IP::Endpoint const endpoint ( - beast::IP::Endpoint::from_string (s)); - - if (! is_unspecified (endpoint)) - { - cb (endpoint, valence); - ++n; - } - else - { - m_journal.error << - "Bad address string '" << s << "' in Bootcache table"; - } + cb (endpoint, valence); + ++n; + } + else + { + m_journal.error << + "Bad address string '" << s << "' in Bootcache table"; } - while (st.fetch (error)); } - - if (error) - report (error, __FILE__, __LINE__); - return n; } @@ -113,306 +100,237 @@ public: // void save (std::vector const& v) { - beast::Error error; - beast::sqdb::transaction tr (m_session); - m_session.once (error) << + soci::transaction tr (m_session); + m_session << "DELETE FROM PeerFinder_BootstrapCache"; - if (! error) + std::string s; + int valence; + + soci::statement st = (m_session.prepare << + "INSERT INTO PeerFinder_BootstrapCache ( " + " address, " + " valence " + ") VALUES ( " + " :s, :valence " + ");" + , soci::use (s) + , soci::use (valence) + ); + + for (auto const& e : v) { - std::string s; - int valence; - - beast::sqdb::statement st = (m_session.prepare << - "INSERT INTO PeerFinder_BootstrapCache ( " - " address, " - " valence " - ") VALUES ( " - " ?, ? " - ");" - , beast::sqdb::use (s) - , beast::sqdb::use (valence) - ); - - for (auto const& e : v) - { - s = to_string (e.endpoint); - valence = e.valence; - st.execute_and_fetch (error); - if (error) - break; - } + s = to_string (e.endpoint); + valence = e.valence; + st.execute (); + st.fetch (); } - if (! error) - error = tr.commit(); - - if (error) - { - tr.rollback (); - report (error, __FILE__, __LINE__); - } + tr.commit (); } // Convert any existing entries from an older schema to the // current one, if appropriate. - // - beast::Error update () + void update () { - beast::Error error; - - beast::sqdb::transaction tr (m_session); - + soci::transaction tr (m_session); // get version int version (0); - if (! error) { - m_session.once (error) << + m_session << "SELECT " " version " "FROM SchemaVersion WHERE " " name = 'PeerFinder'" - ,beast::sqdb::into (version) + , soci::into (version) ; - if (! error) - { - if (!m_session.got_data()) - version = 0; + if (!m_session.got_data ()) + version = 0; - m_journal.info << - "Opened version " << version << " database"; - } + m_journal.info << + "Opened version " << version << " database"; } - if (!error) { if (version < currentSchemaVersion) m_journal.info << "Updating database to version " << currentSchemaVersion; else if (version > currentSchemaVersion) - error.fail (__FILE__, __LINE__, + { + throw std::runtime_error ( "The PeerFinder database version is higher than expected"); + } } - if (! error && version < 4) + if (version < 4) { // // Remove the "uptime" column from the bootstrap table // - if (! error) - m_session.once (error) << - "CREATE TABLE IF NOT EXISTS PeerFinder_BootstrapCache_Next ( " - " id INTEGER PRIMARY KEY AUTOINCREMENT, " - " address TEXT UNIQUE NOT NULL, " - " valence INTEGER" - ");" - ; - - if (! error) - m_session.once (error) << - "CREATE INDEX IF NOT EXISTS " - " PeerFinder_BootstrapCache_Next_Index ON " - " PeerFinder_BootstrapCache_Next " - " ( address ); " - ; - - std::size_t count; - if (! error) - m_session.once (error) << - "SELECT COUNT(*) FROM PeerFinder_BootstrapCache " - ,beast::sqdb::into (count) - ; - - std::vector list; - - if (! error) - { - list.reserve (count); - std::string s; - int valence; - beast::sqdb::statement st = (m_session.prepare << - "SELECT " - " address, " - " valence " - "FROM PeerFinder_BootstrapCache " - , beast::sqdb::into (s) - , beast::sqdb::into (valence) - ); - - if (st.execute_and_fetch (error)) - { - do - { - Store::Entry entry; - entry.endpoint = beast::IP::Endpoint::from_string (s); - if (! is_unspecified (entry.endpoint)) - { - entry.valence = valence; - list.push_back (entry); - } - else - { - m_journal.error << - "Bad address string '" << s << "' in Bootcache table"; - } - } - while (st.fetch (error)); - } - } - - if (! error) - { - std::string s; - int valence; - beast::sqdb::statement st = (m_session.prepare << - "INSERT INTO PeerFinder_BootstrapCache_Next ( " - " address, " - " valence " - ") VALUES ( " - " ?, ?" - ");" - , beast::sqdb::use (s) - , beast::sqdb::use (valence) - ); - - for (auto iter (list.cbegin()); - !error && iter != list.cend(); ++iter) - { - s = to_string (iter->endpoint); - valence = iter->valence; - st.execute_and_fetch (error); - } - - } - - if (! error) - m_session.once (error) << - "DROP TABLE IF EXISTS PeerFinder_BootstrapCache"; - - if (! error) - m_session.once (error) << - "DROP INDEX IF EXISTS PeerFinder_BootstrapCache_Index"; - - if (! error) - m_session.once (error) << - "ALTER TABLE PeerFinder_BootstrapCache_Next " - " RENAME TO PeerFinder_BootstrapCache"; - - if (! error) - m_session.once (error) << - "CREATE INDEX IF NOT EXISTS " - " PeerFinder_BootstrapCache_Index ON PeerFinder_BootstrapCache " - " ( " - " address " - " ); " - ; - } - - if (! error && version < 3) - { - // - // Remove legacy endpoints from the schema - // - - if (! error) - m_session.once (error) << - "DROP TABLE IF EXISTS LegacyEndpoints"; - - if (! error) - m_session.once (error) << - "DROP TABLE IF EXISTS PeerFinderLegacyEndpoints"; - - if (! error) - m_session.once (error) << - "DROP TABLE IF EXISTS PeerFinder_LegacyEndpoints"; - - if (! error) - m_session.once (error) << - "DROP TABLE IF EXISTS PeerFinder_LegacyEndpoints_Index"; - } - - if (! error) - { - int const version (currentSchemaVersion); - m_session.once (error) << - "INSERT OR REPLACE INTO SchemaVersion (" - " name " - " ,version " - ") VALUES ( " - " 'PeerFinder', ? " - ")" - ,beast::sqdb::use(version); - } - - if (! error) - error = tr.commit(); - - if (error) - { - tr.rollback(); - report (error, __FILE__, __LINE__); - } - - return error; - } - -private: - beast::Error init () - { - beast::Error error; - beast::sqdb::transaction tr (m_session); - - if (! error) - m_session.once (error) << - "PRAGMA encoding=\"UTF-8\""; - - if (! error) - m_session.once (error) << - "CREATE TABLE IF NOT EXISTS SchemaVersion ( " - " name TEXT PRIMARY KEY, " - " version INTEGER" - ");" - ; - - if (! error) - m_session.once (error) << - "CREATE TABLE IF NOT EXISTS PeerFinder_BootstrapCache ( " + m_session << + "CREATE TABLE IF NOT EXISTS PeerFinder_BootstrapCache_Next ( " " id INTEGER PRIMARY KEY AUTOINCREMENT, " " address TEXT UNIQUE NOT NULL, " " valence INTEGER" ");" ; - if (! error) - m_session.once (error) << + m_session << "CREATE INDEX IF NOT EXISTS " - " PeerFinder_BootstrapCache_Index ON PeerFinder_BootstrapCache " + " PeerFinder_BootstrapCache_Next_Index ON " + " PeerFinder_BootstrapCache_Next " + " ( address ); " + ; + + std::size_t count; + m_session << + "SELECT COUNT(*) FROM PeerFinder_BootstrapCache " + , soci::into (count) + ; + + std::vector list; + + { + list.reserve (count); + std::string s; + int valence; + soci::statement st = (m_session.prepare << + "SELECT " + " address, " + " valence " + "FROM PeerFinder_BootstrapCache " + , soci::into (s) + , soci::into (valence) + ); + + st.execute (); + while (st.fetch ()) + { + Store::Entry entry; + entry.endpoint = beast::IP::Endpoint::from_string (s); + if (!is_unspecified (entry.endpoint)) + { + entry.valence = valence; + list.push_back (entry); + } + else + { + m_journal.error << + "Bad address string '" << s << "' in Bootcache table"; + } + } + } + + { + std::string s; + int valence; + soci::statement st = (m_session.prepare << + "INSERT INTO PeerFinder_BootstrapCache_Next ( " + " address, " + " valence " + ") VALUES ( " + " :s, :valence" + ");" + , soci::use (s) + , soci::use (valence) + ); + + for (auto iter (list.cbegin ()); + iter != list.cend (); ++iter) + { + s = to_string (iter->endpoint); + valence = iter->valence; + st.execute (); + st.fetch (); + } + } + + m_session << + "DROP TABLE IF EXISTS PeerFinder_BootstrapCache"; + + m_session << + "DROP INDEX IF EXISTS PeerFinder_BootstrapCache_Index"; + + m_session << + "ALTER TABLE PeerFinder_BootstrapCache_Next " + " RENAME TO PeerFinder_BootstrapCache"; + + m_session << + "CREATE INDEX IF NOT EXISTS " + " PeerFinder_BootstrapCache_Index ON " + "PeerFinder_BootstrapCache " " ( " " address " " ); " ; - - if (! error) - error = tr.commit(); - - if (error) - { - tr.rollback (); - report (error, __FILE__, __LINE__); } - return error; + if (version < 3) + { + // + // Remove legacy endpoints from the schema + // + + m_session << + "DROP TABLE IF EXISTS LegacyEndpoints"; + + m_session << + "DROP TABLE IF EXISTS PeerFinderLegacyEndpoints"; + + m_session << + "DROP TABLE IF EXISTS PeerFinder_LegacyEndpoints"; + + m_session << + "DROP TABLE IF EXISTS PeerFinder_LegacyEndpoints_Index"; + } + + { + int const version (currentSchemaVersion); + m_session << + "INSERT OR REPLACE INTO SchemaVersion (" + " name " + " ,version " + ") VALUES ( " + " 'PeerFinder', :version " + ")" + , soci::use (version); + } + + tr.commit (); } - void report (beast::Error const& error, char const* fileName, int lineNumber) +private: + void init () { - if (error) - { - m_journal.error << - "Failure: '"<< error.getReasonText() << "' " << - " at " << beast::Debug::getSourceLocation (fileName, lineNumber); - } + soci::transaction tr (m_session); + m_session << "PRAGMA encoding=\"UTF-8\""; + + m_session << + "CREATE TABLE IF NOT EXISTS SchemaVersion ( " + " name TEXT PRIMARY KEY, " + " version INTEGER" + ");" + ; + + m_session << + "CREATE TABLE IF NOT EXISTS PeerFinder_BootstrapCache ( " + " id INTEGER PRIMARY KEY AUTOINCREMENT, " + " address TEXT UNIQUE NOT NULL, " + " valence INTEGER" + ");" + ; + + m_session << + "CREATE INDEX IF NOT EXISTS " + " PeerFinder_BootstrapCache_Index ON " + "PeerFinder_BootstrapCache " + " ( " + " address " + " ); " + ; + + tr.commit (); } }; diff --git a/src/ripple/peerfinder/make_Manager.h b/src/ripple/peerfinder/make_Manager.h index aaf6d507fe..9cc8e681e9 100644 --- a/src/ripple/peerfinder/make_Manager.h +++ b/src/ripple/peerfinder/make_Manager.h @@ -30,8 +30,7 @@ namespace PeerFinder { /** Create a new Manager. */ std::unique_ptr make_Manager (beast::Stoppable& parent, boost::asio::io_service& io_service, - beast::File const& pathToDbFileOrDirectory, - clock_type& clock, beast::Journal journal); + clock_type& clock, beast::Journal journal, BasicConfig const& config); } } diff --git a/src/ripple/unity/beast.cpp b/src/ripple/unity/beast.cpp index 046e41ab91..0bf92635ce 100644 --- a/src/ripple/unity/beast.cpp +++ b/src/ripple/unity/beast.cpp @@ -30,7 +30,6 @@ // Include this to get all the basic includes included, to prevent errors #include #include -#include #include #include diff --git a/src/ripple/unity/soci.cpp b/src/ripple/unity/soci.cpp new file mode 100644 index 0000000000..f889dfdd01 --- /dev/null +++ b/src/ripple/unity/soci.cpp @@ -0,0 +1,51 @@ +//------------------------------------------------------------------------------ +/* + 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 + +// Core soci +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include diff --git a/src/ripple/unity/soci_ripple.cpp b/src/ripple/unity/soci_ripple.cpp new file mode 100644 index 0000000000..9a9af2ad1d --- /dev/null +++ b/src/ripple/unity/soci_ripple.cpp @@ -0,0 +1,24 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2012, 2013 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 diff --git a/src/ripple/unity/socipostgresql.cpp b/src/ripple/unity/socipostgresql.cpp new file mode 100644 index 0000000000..b8e00c50eb --- /dev/null +++ b/src/ripple/unity/socipostgresql.cpp @@ -0,0 +1,48 @@ +//------------------------------------------------------------------------------ +/* + 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. +*/ +//============================================================================== + +#if ENABLE_SOCI_POSTGRESQL + +#if BEAST_INCLUDE_BEASTCONFIG +#include +#endif + +#include + +#if BEAST_MSVC +#define SOCI_LIB_PREFIX "" +#define SOCI_LIB_SUFFIX ".dll" +#else +#define SOCI_LIB_PREFIX "lib" +#define SOCI_LIB_SUFFIX ".so" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // ENABLE_SOCI_POSTGRESQL diff --git a/src/ripple/validators/impl/Manager.cpp b/src/ripple/validators/impl/Manager.cpp index 0b45680575..4b854db965 100644 --- a/src/ripple/validators/impl/Manager.cpp +++ b/src/ripple/validators/impl/Manager.cpp @@ -206,24 +206,21 @@ public: boost::asio::basic_waitable_timer< std::chrono::steady_clock> timer_; beast::Journal journal_; - beast::File dbFile_; StoreSqdb store_; Logic logic_; + SociConfig sociConfig_; ManagerImp (Stoppable& parent, boost::asio::io_service& io_service, - beast::File const& pathToDbFileOrDirectory, beast::Journal journal) + beast::Journal journal, BasicConfig const& config) : Stoppable ("Validators::Manager", parent) , io_service_(io_service) , strand_(io_service_) , timer_(io_service_) , journal_ (journal) - , dbFile_ (pathToDbFileOrDirectory) , store_ (journal_) , logic_ (store_, journal_) + , sociConfig_ (config, "validators") { - if (dbFile_.isDirectory ()) - dbFile_ = dbFile_.getChildFile("validators.sqlite"); - } ~ManagerImp() @@ -293,12 +290,8 @@ public: void init() { - beast::Error error (store_.open (dbFile_)); - - if (! error) - { - logic_.load (); - } + store_.open (sociConfig_); + logic_.load (); } void @@ -331,12 +324,11 @@ Manager::Manager () std::unique_ptr make_Manager(beast::Stoppable& parent, boost::asio::io_service& io_service, - beast::File const& pathToDbFileOrDirectory, - beast::Journal journal) + beast::Journal journal, + BasicConfig const& config) { - return std::make_unique (parent, - io_service, pathToDbFileOrDirectory, journal); -} - + return std::make_unique(parent, + io_service, journal, config); +} } } diff --git a/src/ripple/validators/impl/StoreSqdb.cpp b/src/ripple/validators/impl/StoreSqdb.cpp index ed97d49ad2..9efbb244db 100644 --- a/src/ripple/validators/impl/StoreSqdb.cpp +++ b/src/ripple/validators/impl/StoreSqdb.cpp @@ -35,19 +35,12 @@ StoreSqdb::~StoreSqdb () { } -beast::Error -StoreSqdb::open (beast::File const& file) +void +StoreSqdb::open (SociConfig const& sociConfig) { - beast::Error error (m_session.open (file.getFullPathName ())); + sociConfig.open (m_session); - m_journal.info << - "Opening " << file.getFullPathName(); - - if (error) - m_journal.error << - "Failed opening database: " << error.what(); - - return error; + m_journal.info << "Opening " << sociConfig.connectionString (); } } diff --git a/src/ripple/validators/impl/StoreSqdb.h b/src/ripple/validators/impl/StoreSqdb.h index 863438b1a0..4df8dbb614 100644 --- a/src/ripple/validators/impl/StoreSqdb.h +++ b/src/ripple/validators/impl/StoreSqdb.h @@ -22,9 +22,8 @@ #include #include -#include -#include #include +#include namespace ripple { namespace Validators { @@ -34,7 +33,7 @@ class StoreSqdb : public Store { private: beast::Journal m_journal; - beast::sqdb::session m_session; + soci::session m_session; public: enum @@ -48,8 +47,8 @@ public: ~StoreSqdb(); - beast::Error - open (beast::File const& file); + void + open (SociConfig const& sociConfig); }; } diff --git a/src/ripple/validators/make_Manager.h b/src/ripple/validators/make_Manager.h index 07ca2cb47b..8e53b2d2e8 100644 --- a/src/ripple/validators/make_Manager.h +++ b/src/ripple/validators/make_Manager.h @@ -28,13 +28,14 @@ #include namespace ripple { +class BasicConfig; namespace Validators { std::unique_ptr make_Manager (beast::Stoppable& stoppableParent, boost::asio::io_service& io_service, - beast::File const& pathToDbFileOrDirectory, - beast::Journal journal); + beast::Journal journal, + BasicConfig const& config); } } diff --git a/src/sqlite/sqlite3.h b/src/sqlite/sqlite3.h new file mode 100644 index 0000000000..54740f0237 --- /dev/null +++ b/src/sqlite/sqlite3.h @@ -0,0 +1 @@ +#include