Use soci in some places:

* Brings the soci subtree into rippled.
* Validator, peerfinder, and SHAMapStore use new soci backend.
* Optional postgresql backend for soci (if POSTGRESQL_ROOT env var is set).
This commit is contained in:
seelabs
2015-01-22 15:04:30 -08:00
committed by Vinnie Falco
parent c7cfd23580
commit d0ef2f7dd8
28 changed files with 1412 additions and 663 deletions

View File

@@ -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 <BeastConfig.h>
#include <ripple/app/data/SociDB.h>
// 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<std::string>& search_paths ()
{
static std::vector<std::string> empty;
return empty;
};
void register_backend (std::string const&, std::string const&){};
void register_backend (std::string const&, backend_factory const&){};
std::vector<std::string> list_all ()
{
return {};
};
void unload (std::string const&){};
void unload_all (){};
} // namespace dynamic_backends
} // namespace soci

View File

@@ -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 <BeastConfig.h>
#include <ripple/core/ConfigSections.h>
#include <ripple/app/data/SociDB.h>
#include <ripple/core/Config.h>
#include <beast/cxx14/memory.h> // <memory>
#include <backends/sqlite3/soci-sqlite3.h>
#if ENABLE_SOCI_POSTGRESQL
#include <backends/postgresql/soci-postgresql.h>
#endif
#include <boost/filesystem.hpp>
namespace ripple {
namespace detail {
std::pair<std::string, soci::backend_factory const&>
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<std::string, soci::backend_factory const&>
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 <std::string> (configSection, "host", ""));
if (!host.empty())
{
throw std::runtime_error (
"Missing required value in config for postgresql backend: host");
}
std::string const user(get <std::string> (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 <std::string> (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<std::string, soci::backend_factory const&>
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<std::string, soci::backend_factory const&> 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);
}
}

View File

@@ -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 <core/soci.h>
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<std::string, soci::backend_factory const&> 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

View File

@@ -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 <BeastConfig.h>
#include <ripple/app/data/SociDB.h>
#include <ripple/core/ConfigSections.h>
#include <ripple/basics/TestSuite.h>
#include <ripple/basics/BasicConfig.h>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
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<std::pair<const char*, const char*>> 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<std::string> const stringData (
{"String1", "String2", "String3"});
std::vector<int> const intData ({1, 2, 3});
auto checkValues = [this, &stringData, &intData](soci::session& s)
{
// Check values in db
std::vector<std::string> stringResult (20 * stringData.size ());
std::vector<int> 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

View File

@@ -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
{

View File

@@ -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 <Application> app (make_Application (deprecatedLogs()));
using namespace beast::unit_test;

View File

@@ -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

View File

@@ -18,92 +18,85 @@
//==============================================================================
#include <BeastConfig.h>
#include <ripple/app/misc/SHAMapStoreImp.h>
#include <ripple/app/ledger/LedgerMaster.h>
#include <ripple/app/main/Application.h>
#include <ripple/core/ConfigSections.h>
#include <boost/format.hpp>
#include <beast/cxx14/memory.h> // <memory>
#include <boost/format.hpp>
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<std::mutex> lock (mutex_);
std::lock_guard <std::mutex> 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<std::mutex> lock (mutex_);
{
std::lock_guard <std::mutex> 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 <std::mutex> lock (mutex_);
std::lock_guard<std::mutex> 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 <std::mutex> lock (mutex_);
std::lock_guard<std::mutex> 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 <std::mutex> 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<std::mutex> 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 <std::mutex> 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<std::mutex> 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<SHAMapStoreImp> (s, parent, scheduler,
journal, nodeStoreJournal, transactionMaster);
return std::make_unique<SHAMapStoreImp>(s, parent, scheduler,
journal, nodeStoreJournal, transactionMaster,
config);
}
}

View File

@@ -23,9 +23,9 @@
#include <ripple/app/data/DatabaseCon.h>
#include <ripple/app/misc/SHAMapStore.h>
#include <ripple/app/misc/NetworkOPs.h>
#include <ripple/app/data/SociDB.h>
#include <ripple/nodestore/impl/Tuning.h>
#include <ripple/nodestore/DatabaseRotating.h>
#include <beast/module/sqdb/sqdb.h>
#include <iostream>
#include <condition_variable>
#include <thread>