Advance ripple.app.rdb

This commit is contained in:
Devon White
2021-09-11 13:51:29 -04:00
committed by manojsdoshi
parent 767dd4ff3f
commit dac080f1c8
70 changed files with 3653 additions and 3867 deletions

View File

@@ -402,13 +402,18 @@ target_sources (rippled PRIVATE
src/ripple/app/paths/impl/DirectStep.cpp
src/ripple/app/paths/impl/PaySteps.cpp
src/ripple/app/paths/impl/XRPEndpointStep.cpp
src/ripple/app/rdb/backend/RelationalDBInterfacePostgres.cpp
src/ripple/app/rdb/backend/RelationalDBInterfaceSqlite.cpp
src/ripple/app/rdb/impl/RelationalDBInterface.cpp
src/ripple/app/rdb/impl/RelationalDBInterface_global.cpp
src/ripple/app/rdb/impl/RelationalDBInterface_nodes.cpp
src/ripple/app/rdb/impl/RelationalDBInterface_postgres.cpp
src/ripple/app/rdb/impl/RelationalDBInterface_shards.cpp
src/ripple/app/rdb/backend/detail/impl/Node.cpp
src/ripple/app/rdb/backend/detail/impl/Shard.cpp
src/ripple/app/rdb/backend/impl/PostgresDatabase.cpp
src/ripple/app/rdb/backend/impl/SQLiteDatabase.cpp
src/ripple/app/rdb/impl/Download.cpp
src/ripple/app/rdb/impl/PeerFinder.cpp
src/ripple/app/rdb/impl/RelationalDatabase.cpp
src/ripple/app/rdb/impl/ShardArchive.cpp
src/ripple/app/rdb/impl/State.cpp
src/ripple/app/rdb/impl/UnitaryShard.cpp
src/ripple/app/rdb/impl/Vacuum.cpp
src/ripple/app/rdb/impl/Wallet.cpp
src/ripple/app/tx/impl/ApplyContext.cpp
src/ripple/app/tx/impl/BookTip.cpp
src/ripple/app/tx/impl/CancelCheck.cpp

View File

@@ -14,7 +14,7 @@ Loop: ripple.app ripple.overlay
ripple.overlay ~= ripple.app
Loop: ripple.app ripple.peerfinder
ripple.peerfinder ~= ripple.app
ripple.app > ripple.peerfinder
Loop: ripple.app ripple.rpc
ripple.rpc > ripple.app

View File

@@ -29,8 +29,8 @@
#include <ripple/app/misc/HashRouter.h>
#include <ripple/app/misc/LoadFeeTrack.h>
#include <ripple/app/misc/NetworkOPs.h>
#include <ripple/app/rdb/backend/RelationalDBInterfacePostgres.h>
#include <ripple/app/rdb/backend/RelationalDBInterfaceSqlite.h>
#include <ripple/app/rdb/backend/PostgresDatabase.h>
#include <ripple/app/rdb/backend/SQLiteDatabase.h>
#include <ripple/basics/Log.h>
#include <ripple/basics/StringUtilities.h>
#include <ripple/basics/contract.h>
@@ -930,9 +930,11 @@ saveValidatedLedger(
return true;
}
auto res = dynamic_cast<RelationalDBInterfaceSqlite*>(
&app.getRelationalDBInterface())
->saveValidatedLedger(ledger, current);
auto const db = dynamic_cast<SQLiteDatabase*>(&app.getRelationalDatabase());
if (!db)
Throw<std::runtime_error>("Failed to get relational database");
auto const res = db->saveValidatedLedger(ledger, current);
// Clients can now trust the database for
// information about this ledger sequence.
@@ -1053,7 +1055,7 @@ std::tuple<std::shared_ptr<Ledger>, std::uint32_t, uint256>
getLatestLedger(Application& app)
{
const std::optional<LedgerInfo> info =
app.getRelationalDBInterface().getNewestLedgerInfo();
app.getRelationalDatabase().getNewestLedgerInfo();
if (!info)
return {std::shared_ptr<Ledger>(), {}, {}};
return {loadLedgerHelper(*info, app, true), info->seq, info->hash};
@@ -1063,7 +1065,7 @@ std::shared_ptr<Ledger>
loadByIndex(std::uint32_t ledgerIndex, Application& app, bool acquire)
{
if (std::optional<LedgerInfo> info =
app.getRelationalDBInterface().getLedgerInfoByIndex(ledgerIndex))
app.getRelationalDatabase().getLedgerInfoByIndex(ledgerIndex))
{
std::shared_ptr<Ledger> ledger = loadLedgerHelper(*info, app, acquire);
finishLoadByIndexOrHash(ledger, app.config(), app.journal("Ledger"));
@@ -1076,7 +1078,7 @@ std::shared_ptr<Ledger>
loadByHash(uint256 const& ledgerHash, Application& app, bool acquire)
{
if (std::optional<LedgerInfo> info =
app.getRelationalDBInterface().getLedgerInfoByHash(ledgerHash))
app.getRelationalDatabase().getLedgerInfoByHash(ledgerHash))
{
std::shared_ptr<Ledger> ledger = loadLedgerHelper(*info, app, acquire);
finishLoadByIndexOrHash(ledger, app.config(), app.journal("Ledger"));
@@ -1165,9 +1167,12 @@ flatFetchTransactions(ReadView const& ledger, Application& app)
return {};
}
auto nodestoreHashes = dynamic_cast<RelationalDBInterfacePostgres*>(
&app.getRelationalDBInterface())
->getTxHashes(ledger.info().seq);
auto const db =
dynamic_cast<PostgresDatabase*>(&app.getRelationalDatabase());
if (!db)
Throw<std::runtime_error>("Failed to get relational database");
auto nodestoreHashes = db->getTxHashes(ledger.info().seq);
return flatFetchTransactions(app, nodestoreHashes);
}

View File

@@ -34,8 +34,7 @@
#include <ripple/app/misc/TxQ.h>
#include <ripple/app/misc/ValidatorList.h>
#include <ripple/app/paths/PathRequests.h>
#include <ripple/app/rdb/RelationalDBInterface_postgres.h>
#include <ripple/app/rdb/backend/RelationalDBInterfacePostgres.h>
#include <ripple/app/rdb/backend/PostgresDatabase.h>
#include <ripple/app/tx/apply.h>
#include <ripple/basics/Log.h>
#include <ripple/basics/MathUtilities.h>
@@ -278,10 +277,10 @@ LedgerMaster::getValidatedLedgerAge()
#ifdef RIPPLED_REPORTING
if (app_.config().reporting())
return static_cast<RelationalDBInterfacePostgres*>(
&app_.getRelationalDBInterface())
return static_cast<PostgresDatabase*>(&app_.getRelationalDatabase())
->getValidatedLedgerAge();
#endif
std::chrono::seconds valClose{mValidLedgerSign.load()};
if (valClose == 0s)
{
@@ -309,8 +308,7 @@ LedgerMaster::isCaughtUp(std::string& reason)
#ifdef RIPPLED_REPORTING
if (app_.config().reporting())
return static_cast<RelationalDBInterfacePostgres*>(
&app_.getRelationalDBInterface())
return static_cast<PostgresDatabase*>(&app_.getRelationalDatabase())
->isCaughtUp(reason);
#endif
@@ -743,7 +741,7 @@ LedgerMaster::tryFill(std::shared_ptr<Ledger const> ledger)
mCompleteLedgers.insert(range(minHas, maxHas));
}
maxHas = minHas;
ledgerHashes = app_.getRelationalDBInterface().getHashesByIndex(
ledgerHashes = app_.getRelationalDatabase().getHashesByIndex(
(seq < 500) ? 0 : (seq - 499), seq);
it = ledgerHashes.find(seq);
@@ -927,8 +925,8 @@ LedgerMaster::setFullLedger(
{
// Check the SQL database's entry for the sequence before this
// ledger, if it's not this ledger's parent, invalidate it
uint256 prevHash = app_.getRelationalDBInterface().getHashByIndex(
ledger->info().seq - 1);
uint256 prevHash =
app_.getRelationalDatabase().getHashByIndex(ledger->info().seq - 1);
if (prevHash.isNonZero() && prevHash != ledger->info().parentHash)
clearLedger(ledger->info().seq - 1);
}
@@ -1664,7 +1662,7 @@ LedgerMaster::getValidatedLedger()
#ifdef RIPPLED_REPORTING
if (app_.config().reporting())
{
auto seq = app_.getRelationalDBInterface().getMaxLedgerSeq();
auto seq = app_.getRelationalDatabase().getMaxLedgerSeq();
if (!seq)
return {};
return getLedgerBySeq(*seq);
@@ -1700,8 +1698,7 @@ LedgerMaster::getCompleteLedgers()
{
#ifdef RIPPLED_REPORTING
if (app_.config().reporting())
return static_cast<RelationalDBInterfacePostgres*>(
&app_.getRelationalDBInterface())
return static_cast<PostgresDatabase*>(&app_.getRelationalDatabase())
->getCompleteLedgers();
#endif
std::lock_guard sl(mCompleteLock);
@@ -1746,7 +1743,7 @@ LedgerMaster::getHashBySeq(std::uint32_t index)
if (hash.isNonZero())
return hash;
return app_.getRelationalDBInterface().getHashByIndex(index);
return app_.getRelationalDatabase().getHashByIndex(index);
}
std::optional<LedgerHash>
@@ -1967,7 +1964,7 @@ LedgerMaster::fetchForHistory(
fillInProgress = mFillInProgress;
}
if (fillInProgress == 0 &&
app_.getRelationalDBInterface().getHashByIndex(seq - 1) ==
app_.getRelationalDatabase().getHashByIndex(seq - 1) ==
ledger->info().parentHash)
{
{
@@ -2363,7 +2360,7 @@ LedgerMaster::getFetchPackCacheSize() const
std::optional<LedgerIndex>
LedgerMaster::minSqlSeq()
{
return app_.getRelationalDBInterface().getMinLedgerSeq();
return app_.getRelationalDatabase().getMinLedgerSeq();
}
} // namespace ripple

View File

@@ -45,8 +45,8 @@
#include <ripple/app/misc/ValidatorKeys.h>
#include <ripple/app/misc/ValidatorSite.h>
#include <ripple/app/paths/PathRequests.h>
#include <ripple/app/rdb/RelationalDBInterface_global.h>
#include <ripple/app/rdb/backend/RelationalDBInterfacePostgres.h>
#include <ripple/app/rdb/Wallet.h>
#include <ripple/app/rdb/backend/PostgresDatabase.h>
#include <ripple/app/reporting/ReportingETL.h>
#include <ripple/app/tx/apply.h>
#include <ripple/basics/ByteUtilities.h>
@@ -219,7 +219,7 @@ public:
boost::asio::steady_timer sweepTimer_;
boost::asio::steady_timer entropyTimer_;
std::unique_ptr<RelationalDBInterface> mRelationalDBInterface;
std::unique_ptr<RelationalDatabase> mRelationalDatabase;
std::unique_ptr<DatabaseCon> mWalletDB;
std::unique_ptr<Overlay> overlay_;
@@ -877,11 +877,11 @@ public:
return *txQ_;
}
RelationalDBInterface&
getRelationalDBInterface() override
RelationalDatabase&
getRelationalDatabase() override
{
assert(mRelationalDBInterface.get() != nullptr);
return *mRelationalDBInterface;
assert(mRelationalDatabase.get() != nullptr);
return *mRelationalDatabase;
}
DatabaseCon&
@@ -907,14 +907,14 @@ public:
//--------------------------------------------------------------------------
bool
initRDBMS()
initRelationalDatabase()
{
assert(mWalletDB.get() == nullptr);
try
{
mRelationalDBInterface =
RelationalDBInterface::init(*this, *config_, *m_jobQueue);
mRelationalDatabase =
RelationalDatabase::init(*this, *config_, *m_jobQueue);
// wallet database
auto setup = setup_DatabaseCon(*config_, m_journal);
@@ -1041,7 +1041,7 @@ public:
doSweep()
{
if (!config_->standalone() &&
!getRelationalDBInterface().transactionDbHasSpace(*config_))
!getRelationalDatabase().transactionDbHasSpace(*config_))
{
signalStop();
}
@@ -1066,8 +1066,7 @@ public:
cachedSLEs_.sweep();
#ifdef RIPPLED_REPORTING
if (auto pg = dynamic_cast<RelationalDBInterfacePostgres*>(
&*mRelationalDBInterface))
if (auto pg = dynamic_cast<PostgresDatabase*>(&*mRelationalDatabase))
pg->sweep();
#endif
@@ -1162,7 +1161,7 @@ ApplicationImp::setup()
if (!config_->standalone())
timeKeeper_->run(config_->SNTP_SERVERS);
if (!initRDBMS() || !initNodeStore())
if (!initRelationalDatabase() || !initNodeStore())
return false;
if (shardStore_)
@@ -1619,8 +1618,7 @@ ApplicationImp::run()
ledgerCleaner_->stop();
if (reportingETL_)
reportingETL_->stop();
if (auto pg = dynamic_cast<RelationalDBInterfacePostgres*>(
&*mRelationalDBInterface))
if (auto pg = dynamic_cast<PostgresDatabase*>(&*mRelationalDatabase))
pg->stop();
m_nodeStore->stop();
perfLog_->stop();
@@ -2137,7 +2135,7 @@ ApplicationImp::nodeToShards()
void
ApplicationImp::setMaxDisallowedLedger()
{
auto seq = getRelationalDBInterface().getMaxLedgerSeq();
auto seq = getRelationalDatabase().getMaxLedgerSeq();
if (seq)
maxDisallowedLedger_ = *seq;

View File

@@ -99,7 +99,7 @@ class ValidatorList;
class ValidatorSite;
class Cluster;
class RelationalDBInterface;
class RelationalDatabase;
class DatabaseCon;
class SHAMapStore;
@@ -251,8 +251,8 @@ public:
openLedger() = 0;
virtual OpenLedger const&
openLedger() const = 0;
virtual RelationalDBInterface&
getRelationalDBInterface() = 0;
virtual RelationalDatabase&
getRelationalDatabase() = 0;
virtual std::chrono::milliseconds
getIOLatency() = 0;

View File

@@ -72,12 +72,22 @@ inline constexpr std::array<char const*, 5> LgrDBInit{
// Transaction database holds transactions and public keys
inline constexpr auto TxDBName{"transaction.db"};
inline constexpr std::array TxDBPragma
// In C++17 omitting the explicit template parameters caused
// a crash
inline constexpr std::array<char const*, 4> TxDBPragma
{
"PRAGMA page_size=4096;", "PRAGMA journal_size_limit=1582080;",
"PRAGMA max_page_count=2147483646;",
#if (ULONG_MAX > UINT_MAX) && !defined(NO_SQLITE_MMAP)
"PRAGMA mmap_size=17179869184;"
#else
// Provide an explicit `no-op` SQL statement
// in order to keep the size of the array
// constant regardless of the preprocessor
// condition evaluation
"PRAGMA sqlite_noop_statement;"
#endif
};
@@ -117,12 +127,22 @@ inline constexpr std::array<char const*, 8> TxDBInit{
// The Ledger Meta database maps ledger hashes to shard indexes
inline constexpr auto LgrMetaDBName{"ledger_meta.db"};
inline constexpr std::array LgrMetaDBPragma
// In C++17 omitting the explicit template parameters caused
// a crash
inline constexpr std::array<char const*, 4> LgrMetaDBPragma
{
"PRAGMA page_size=4096;", "PRAGMA journal_size_limit=1582080;",
"PRAGMA max_page_count=2147483646;",
#if (ULONG_MAX > UINT_MAX) && !defined(NO_SQLITE_MMAP)
"PRAGMA mmap_size=17179869184;"
#else
// Provide an explicit `no-op` SQL statement
// in order to keep the size of the array
// constant regardless of the preprocessor
// condition evaluation
"PRAGMA sqlite_noop_statement;"
#endif
};
@@ -141,12 +161,22 @@ inline constexpr std::array<char const*, 3> LgrMetaDBInit{
// Transaction Meta database maps transaction IDs to shard indexes
inline constexpr auto TxMetaDBName{"transaction_meta.db"};
inline constexpr std::array TxMetaDBPragma
// In C++17 omitting the explicit template parameters caused
// a crash
inline constexpr std::array<char const*, 4> TxMetaDBPragma
{
"PRAGMA page_size=4096;", "PRAGMA journal_size_limit=1582080;",
"PRAGMA max_page_count=2147483646;",
#if (ULONG_MAX > UINT_MAX) && !defined(NO_SQLITE_MMAP)
"PRAGMA mmap_size=17179869184;"
#else
// Provide an explicit `no-op` SQL statement
// in order to keep the size of the array
// constant regardless of the preprocessor
// condition evaluation
"PRAGMA sqlite_noop_statement;"
#endif
};

View File

@@ -19,7 +19,7 @@
#include <ripple/app/main/Application.h>
#include <ripple/app/main/DBInit.h>
#include <ripple/app/rdb/RelationalDBInterface_global.h>
#include <ripple/app/rdb/Vacuum.h>
#include <ripple/basics/Log.h>
#include <ripple/basics/StringUtilities.h>
#include <ripple/basics/contract.h>

View File

@@ -19,7 +19,7 @@
#include <ripple/app/main/Application.h>
#include <ripple/app/main/NodeIdentity.h>
#include <ripple/app/rdb/RelationalDBInterface_global.h>
#include <ripple/app/rdb/Wallet.h>
#include <ripple/basics/Log.h>
#include <ripple/core/Config.h>
#include <ripple/core/ConfigSections.h>

View File

@@ -37,9 +37,8 @@
#include <ripple/app/misc/ValidatorKeys.h>
#include <ripple/app/misc/ValidatorList.h>
#include <ripple/app/misc/impl/AccountTxPaging.h>
#include <ripple/app/rdb/RelationalDBInterface.h>
#include <ripple/app/rdb/backend/RelationalDBInterfacePostgres.h>
#include <ripple/app/rdb/backend/RelationalDBInterfaceSqlite.h>
#include <ripple/app/rdb/backend/PostgresDatabase.h>
#include <ripple/app/rdb/backend/SQLiteDatabase.h>
#include <ripple/app/reporting/ReportingETL.h>
#include <ripple/app/tx/apply.h>
#include <ripple/basics/PerfLog.h>
@@ -3366,8 +3365,9 @@ NetworkOPsImp::addAccountHistoryJob(SubAccountHistoryInfoWeak subInfo)
#ifdef RIPPLED_REPORTING
if (app_.config().reporting())
{
if (dynamic_cast<RelationalDBInterfacePostgres*>(
&app_.getRelationalDBInterface()))
// Use a dynamic_cast to return DatabaseType::None
// on failure.
if (dynamic_cast<PostgresDatabase*>(&app_.getRelationalDatabase()))
{
return DatabaseType::Postgres;
}
@@ -3375,16 +3375,18 @@ NetworkOPsImp::addAccountHistoryJob(SubAccountHistoryInfoWeak subInfo)
}
else
{
if (dynamic_cast<RelationalDBInterfaceSqlite*>(
&app_.getRelationalDBInterface()))
// Use a dynamic_cast to return DatabaseType::None
// on failure.
if (dynamic_cast<SQLiteDatabase*>(&app_.getRelationalDatabase()))
{
return DatabaseType::Sqlite;
}
return DatabaseType::None;
}
#else
if (dynamic_cast<RelationalDBInterfaceSqlite*>(
&app_.getRelationalDBInterface()))
// Use a dynamic_cast to return DatabaseType::None
// on failure.
if (dynamic_cast<SQLiteDatabase*>(&app_.getRelationalDatabase()))
{
return DatabaseType::Sqlite;
}
@@ -3470,17 +3472,16 @@ NetworkOPsImp::addAccountHistoryJob(SubAccountHistoryInfoWeak subInfo)
auto getMoreTxns =
[&](std::uint32_t minLedger,
std::uint32_t maxLedger,
std::optional<RelationalDBInterface::AccountTxMarker>
marker)
std::optional<RelationalDatabase::AccountTxMarker> marker)
-> std::optional<std::pair<
RelationalDBInterface::AccountTxs,
std::optional<RelationalDBInterface::AccountTxMarker>>> {
RelationalDatabase::AccountTxs,
std::optional<RelationalDatabase::AccountTxMarker>>> {
switch (dbType)
{
case Postgres: {
auto db = static_cast<RelationalDBInterfacePostgres*>(
&app_.getRelationalDBInterface());
RelationalDBInterface::AccountTxArgs args;
auto db = static_cast<PostgresDatabase*>(
&app_.getRelationalDatabase());
RelationalDatabase::AccountTxArgs args;
args.account = accountId;
LedgerRange range{minLedger, maxLedger};
args.ledger = range;
@@ -3496,7 +3497,7 @@ NetworkOPsImp::addAccountHistoryJob(SubAccountHistoryInfoWeak subInfo)
}
if (auto txns =
std::get_if<RelationalDBInterface::AccountTxs>(
std::get_if<RelationalDatabase::AccountTxs>(
&txResult.transactions);
txns)
{
@@ -3512,9 +3513,9 @@ NetworkOPsImp::addAccountHistoryJob(SubAccountHistoryInfoWeak subInfo)
}
}
case Sqlite: {
auto db = static_cast<RelationalDBInterfaceSqlite*>(
&app_.getRelationalDBInterface());
RelationalDBInterface::AccountTxPageOptions options{
auto db = static_cast<SQLiteDatabase*>(
&app_.getRelationalDatabase());
RelationalDatabase::AccountTxPageOptions options{
accountId, minLedger, maxLedger, marker, 0, true};
return db->newestAccountTxPage(options);
}
@@ -3575,7 +3576,7 @@ NetworkOPsImp::addAccountHistoryJob(SubAccountHistoryInfoWeak subInfo)
return;
}
std::optional<RelationalDBInterface::AccountTxMarker> marker{};
std::optional<RelationalDatabase::AccountTxMarker> marker{};
while (!subInfo.index_->stopHistorical_)
{
auto dbResult =

View File

@@ -20,8 +20,8 @@
#include <ripple/app/ledger/TransactionMaster.h>
#include <ripple/app/misc/NetworkOPs.h>
#include <ripple/app/misc/SHAMapStoreImp.h>
#include <ripple/app/rdb/RelationalDBInterface_global.h>
#include <ripple/app/rdb/backend/RelationalDBInterfaceSqlite.h>
#include <ripple/app/rdb/State.h>
#include <ripple/app/rdb/backend/SQLiteDatabase.h>
#include <ripple/beast/core/CurrentThreadName.h>
#include <ripple/core/ConfigSections.h>
#include <ripple/core/Pg.h>
@@ -620,19 +620,17 @@ SHAMapStoreImp::clearPrior(LedgerIndex lastRotated)
if (stopping())
return;
RelationalDBInterfaceSqlite* iface =
dynamic_cast<RelationalDBInterfaceSqlite*>(
&app_.getRelationalDBInterface());
SQLiteDatabase* const db =
dynamic_cast<SQLiteDatabase*>(&app_.getRelationalDatabase());
if (!db)
Throw<std::runtime_error>("Failed to get relational database");
clearSql(
lastRotated,
"Ledgers",
[&iface]() -> std::optional<LedgerIndex> {
return iface->getMinLedgerSeq();
},
[&iface](LedgerIndex min) -> void {
iface->deleteBeforeLedgerSeq(min);
});
[db]() -> std::optional<LedgerIndex> { return db->getMinLedgerSeq(); },
[db](LedgerIndex min) -> void { db->deleteBeforeLedgerSeq(min); });
if (stopping())
return;
@@ -642,11 +640,11 @@ SHAMapStoreImp::clearPrior(LedgerIndex lastRotated)
clearSql(
lastRotated,
"Transactions",
[&iface]() -> std::optional<LedgerIndex> {
return iface->getTransactionsMinLedgerSeq();
[&db]() -> std::optional<LedgerIndex> {
return db->getTransactionsMinLedgerSeq();
},
[&iface](LedgerIndex min) -> void {
iface->deleteTransactionsBeforeLedgerSeq(min);
[&db](LedgerIndex min) -> void {
db->deleteTransactionsBeforeLedgerSeq(min);
});
if (stopping())
return;
@@ -654,11 +652,11 @@ SHAMapStoreImp::clearPrior(LedgerIndex lastRotated)
clearSql(
lastRotated,
"AccountTransactions",
[&iface]() -> std::optional<LedgerIndex> {
return iface->getAccountTransactionsMinLedgerSeq();
[&db]() -> std::optional<LedgerIndex> {
return db->getAccountTransactionsMinLedgerSeq();
},
[&iface](LedgerIndex min) -> void {
iface->deleteAccountTransactionsBeforeLedgerSeq(min);
[&db](LedgerIndex min) -> void {
db->deleteAccountTransactionsBeforeLedgerSeq(min);
});
if (stopping())
return;

View File

@@ -22,8 +22,8 @@
#include <ripple/app/ledger/LedgerMaster.h>
#include <ripple/app/misc/SHAMapStore.h>
#include <ripple/app/rdb/RelationalDBInterface.h>
#include <ripple/app/rdb/RelationalDBInterface_global.h>
#include <ripple/app/rdb/RelationalDatabase.h>
#include <ripple/app/rdb/State.h>
#include <ripple/core/DatabaseCon.h>
#include <ripple/nodestore/DatabaseRotating.h>

View File

@@ -31,7 +31,7 @@ namespace ripple {
void
convertBlobsToTxResult(
RelationalDBInterface::AccountTxs& to,
RelationalDatabase::AccountTxs& to,
std::uint32_t ledger_index,
std::string const& status,
Blob const& rawTxn,

View File

@@ -20,7 +20,7 @@
#ifndef RIPPLE_APP_MISC_IMPL_ACCOUNTTXPAGING_H_INCLUDED
#define RIPPLE_APP_MISC_IMPL_ACCOUNTTXPAGING_H_INCLUDED
#include <ripple/app/rdb/RelationalDBInterface.h>
#include <ripple/app/rdb/RelationalDatabase.h>
#include <cstdint>
#include <string>
#include <utility>
@@ -31,7 +31,7 @@ namespace ripple {
void
convertBlobsToTxResult(
RelationalDBInterface::AccountTxs& to,
RelationalDatabase::AccountTxs& to,
std::uint32_t ledger_index,
std::string const& status,
Blob const& rawTxn,

View File

@@ -19,7 +19,7 @@
#include <ripple/app/main/Application.h>
#include <ripple/app/misc/AmendmentTable.h>
#include <ripple/app/rdb/RelationalDBInterface_global.h>
#include <ripple/app/rdb/Wallet.h>
#include <ripple/core/ConfigSections.h>
#include <ripple/protocol/Feature.h>
#include <ripple/protocol/STValidation.h>

View File

@@ -18,7 +18,7 @@
//==============================================================================
#include <ripple/app/misc/Manifest.h>
#include <ripple/app/rdb/RelationalDBInterface_global.h>
#include <ripple/app/rdb/Wallet.h>
#include <ripple/basics/Log.h>
#include <ripple/basics/StringUtilities.h>
#include <ripple/basics/base64.h>

View File

@@ -21,9 +21,8 @@
#include <ripple/app/main/Application.h>
#include <ripple/app/misc/HashRouter.h>
#include <ripple/app/misc/Transaction.h>
#include <ripple/app/rdb/RelationalDBInterface_postgres.h>
#include <ripple/app/rdb/backend/RelationalDBInterfacePostgres.h>
#include <ripple/app/rdb/backend/RelationalDBInterfaceSqlite.h>
#include <ripple/app/rdb/backend/PostgresDatabase.h>
#include <ripple/app/rdb/backend/SQLiteDatabase.h>
#include <ripple/app/tx/apply.h>
#include <ripple/basics/Log.h>
#include <ripple/basics/safe_cast.h>
@@ -134,9 +133,15 @@ Transaction::load(
Transaction::Locator
Transaction::locate(uint256 const& id, Application& app)
{
return dynamic_cast<RelationalDBInterfacePostgres*>(
&app.getRelationalDBInterface())
->locateTransaction(id);
auto const db =
dynamic_cast<PostgresDatabase*>(&app.getRelationalDatabase());
if (!db)
{
Throw<std::runtime_error>("Failed to get relational database");
}
return db->locateTransaction(id);
}
std::variant<
@@ -148,9 +153,14 @@ Transaction::load(
std::optional<ClosedInterval<uint32_t>> const& range,
error_code_i& ec)
{
return dynamic_cast<RelationalDBInterfaceSqlite*>(
&app.getRelationalDBInterface())
->getTransaction(id, range, ec);
auto const db = dynamic_cast<SQLiteDatabase*>(&app.getRelationalDatabase());
if (!db)
{
Throw<std::runtime_error>("Failed to get relational database");
}
return db->getTransaction(id, range, ec);
}
// options 1 to include the date of the transaction

View File

@@ -0,0 +1,79 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2021 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_APP_RDB_DOWNLOAD_H_INCLUDED
#define RIPPLE_APP_RDB_DOWNLOAD_H_INCLUDED
#include <ripple/app/ledger/Ledger.h>
#include <ripple/app/misc/Manifest.h>
#include <ripple/core/Config.h>
#include <ripple/core/DatabaseCon.h>
#include <ripple/overlay/PeerReservationTable.h>
#include <ripple/peerfinder/impl/Store.h>
#include <boost/filesystem.hpp>
namespace ripple {
/**
* @brief openDatabaseBodyDb Opens a database that will store the contents of a
* file being downloaded, returns its descriptor, and starts a new
* download process or continues an existing one.
* @param setup Path to the database and other opening parameters.
* @param path Path of the new file to download.
* @return Pair containing a unique pointer to the database and the amount of
* bytes already downloaded if a download is being continued.
*/
std::pair<std::unique_ptr<DatabaseCon>, std::optional<std::uint64_t>>
openDatabaseBodyDb(
DatabaseCon::Setup const& setup,
boost::filesystem::path const& path);
/**
* @brief databaseBodyDoPut Saves a new fragment of a downloaded file.
* @param session Session with the database.
* @param data Downloaded fragment of file data to save.
* @param path Path to the file currently being downloaded.
* @param fileSize Size of the portion of the file already downloaded.
* @param part The index of the most recently updated database row.
* @param maxRowSizePad A constant padding value that accounts for other data
* stored in each row of the database.
* @return Index of the most recently updated database row.
*/
std::uint64_t
databaseBodyDoPut(
soci::session& session,
std::string const& data,
std::string const& path,
std::uint64_t fileSize,
std::uint64_t part,
std::uint16_t maxRowSizePad);
/**
* @brief databaseBodyFinish Finishes the download process and writes the file
* to disk.
* @param session Session with the database.
* @param fout Opened file into which the downloaded data from the database will
* be written.
*/
void
databaseBodyFinish(soci::session& session, std::ofstream& fout);
} // namespace ripple
#endif

View File

@@ -0,0 +1,76 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2021 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_APP_RDB_PEERFINDER_H_INCLUDED
#define RIPPLE_APP_RDB_PEERFINDER_H_INCLUDED
#include <ripple/core/Config.h>
#include <ripple/core/DatabaseCon.h>
#include <ripple/peerfinder/impl/Store.h>
namespace ripple {
/**
* @brief initPeerFinderDB Opens a session with the peer finder database.
* @param session Session with the peer finder database.
* @param config Path to the database and other opening parameters.
* @param j Journal.
*/
void
initPeerFinderDB(
soci::session& session,
BasicConfig const& config,
beast::Journal j);
/**
* @brief updatePeerFinderDB Updates the peer finder database to a new version.
* @param session Session with the database.
* @param currentSchemaVersion New version of the database.
* @param j Journal.
*/
void
updatePeerFinderDB(
soci::session& session,
int currentSchemaVersion,
beast::Journal j);
/**
* @brief readPeerFinderDB Reads all entries from the peer finder database and
* invokes the given callback for each entry.
* @param session Session with the database.
* @param func Callback to invoke for each entry.
*/
void
readPeerFinderDB(
soci::session& session,
std::function<void(std::string const&, int)> const& func);
/**
* @brief savePeerFinderDB Saves a new entry to the peer finder database.
* @param session Session with the database.
* @param v Entry to save which contains information about a new peer.
*/
void
savePeerFinderDB(
soci::session& session,
std::vector<PeerFinder::Store::Entry> const& v);
} // namespace ripple
#endif

View File

@@ -0,0 +1,102 @@
# Relational Database Interface
The guiding principles of the Relational Database Interface are summarized below:
* All hard-coded SQL statements should be stored in the [files](#source-files) under the `ripple/app/rdb` directory. With the exception of test modules, no hard-coded SQL should be added to any other file in rippled.
* The base class `RelationalDatabase` is inherited by derived classes that each provide an interface for operating on distinct relational database systems.
* For future use, the shard store will be used if the node store is absent.
## Overview
Firstly, the interface `RelationalDatabase` is inherited by the classes `SQLiteDatabase` and `PostgresDatabase` which are used to operate the software's main data store (for storing transactions, accounts, ledgers, etc.). Secondly, the files under the `detail` directory provide supplementary functions that are used by these derived classes to access the underlying databases. Lastly, the remaining files in the interface (located at the top level of the module) are used by varied parts of the software to access any secondary relational databases.
## Configuration
The config section `[relational_db]` has a property named `backend` whose value designates which database implementation will be used for node or shard databases. Presently the only valid value for this property is `sqlite`:
```
[relational_db]
backend=sqlite
```
## Source Files
The Relational Database Interface consists of the following directory structure (as of November 2021):
```
src/ripple/app/rdb/
├── backend
│   ├── detail
│   │   ├── impl
│   │   │   ├── Node.cpp
│   │   │   └── Shard.cpp
│   │   ├── Node.h
│   │   └── Shard.h
│   ├── impl
│   │   ├── PostgresDatabase.cpp
│   │   └── SQLiteDatabase.cpp
│   ├── PostgresDatabase.h
│   └── SQLiteDatabase.h
├── impl
│   ├── Download.cpp
│   ├── PeerFinder.cpp
│   ├── RelationalDatabase.cpp
│   ├── ShardArchive.cpp
│   ├── State.cpp
│   ├── UnitaryShard.cpp
│   ├── Vacuum.cpp
│   └── Wallet.cpp
├── Download.h
├── PeerFinder.h
├── RelationalDatabase.h
├── README.md
├── ShardArchive.h
├── State.h
├── UnitaryShard.h
├── Vacuum.h
└── Wallet.h
```
### File Contents
| File | Contents |
| ----------- | ----------- |
| `Node.[h\|cpp]` | Defines/Implements methods used by `SQLiteDatabase` for interacting with SQLite node databases|
| `Shard.[h\|cpp]` | Defines/Implements methods used by `SQLiteDatabase` for interacting with SQLite shard databases |
| <nobr>`PostgresDatabase.[h\|cpp]`</nobr> | Defines/Implements the class `PostgresDatabase`/`PostgresDatabaseImp` which inherits from `RelationalDatabase` and is used to operate on the main stores |
|`SQLiteDatabase.[h\|cpp]`| Defines/Implements the class `SQLiteDatabase`/`SQLiteDatabaseImp` which inherits from `RelationalDatabase` and is used to operate on the main stores |
| `Download.[h\|cpp]` | Defines/Implements methods for persisting file downloads to a SQLite database |
| `PeerFinder.[h\|cpp]` | Defines/Implements methods for interacting with the PeerFinder SQLite database |
|`RelationalDatabase.cpp`| Implements the static method `RelationalDatabase::init` which is used to initialize an instance of `RelationalDatabase` |
| `RelationalDatabase.h` | Defines the abstract class `RelationalDatabase`, the primary class of the Relational Database Interface |
| `ShardArchive.[h\|cpp]` | Defines/Implements methods used by `ShardArchiveHandler` for interacting with SQLite databases containing metadata regarding shard downloads |
| `State.[h\|cpp]` | Defines/Implements methods for interacting with the State SQLite database which concerns ledger deletion and database rotation |
| `UnitaryShard.[h\|cpp]` | Defines/Implements methods used by a unitary instance of `Shard` for interacting with the various SQLite databases thereof. These files are distinct from `Shard.[h\|cpp]` which contain methods used by `SQLiteDatabaseImp` |
| `Vacuum.[h\|cpp]` | Defines/Implements a method for performing the `VACUUM` operation on SQLite databases |
| `Wallet.[h\|cpp]` | Defines/Implements methods for interacting with Wallet SQLite databases |
## Classes
The abstract class `RelationalDatabase` is the primary class of the Relational Database Interface and is defined in the eponymous header file. This class provides a static method `init()` which, when invoked, creates a concrete instance of a derived class whose type is specified by the system configuration. All other methods in the class are virtual. Presently there exist two classes that derive from `RelationalDatabase`, namely `SQLiteDatabase` and `PostgresDatabase`.
## Database Methods
The Relational Database Interface provides three categories of methods for interacting with databases:
* Free functions for interacting with SQLite databases used by various components of the software. These methods feature a `soci::session` parameter which facilitates connecting to SQLite databases, and are defined and implemented in the following files:
* `Download.[h\|cpp]`
* `PeerFinder.[h\|cpp]`
* `ShardArchive.[h\|cpp]`
* `State.[h\|cpp]`
* `UnitaryShard.[h\|cpp]`
* `Vacuum.[h\|cpp]`
* `Wallet.[h\|cpp]`
* Free functions used exclusively by `SQLiteDatabaseImp` for interacting with SQLite databases owned by the node store or shard store. Unlike the free functions in the files listed above, these are not intended to be invoked directly by clients. Rather, these methods are invoked by derived instances of `RelationalDatabase`. These methods are defined in the following files:
* `Node.[h|cpp]`
* `Shard.[h|cpp]`
* Member functions of `RelationalDatabase`, `SQLiteDatabase`, and `PostgresDatabase` which are used to access the main stores (node store, shard store). The `SQLiteDatabase` class will access the node store by default, but will use shard databases if the node store is not present and the shard store is available. The class `PostgresDatabase` uses only the node store.

View File

@@ -1,288 +0,0 @@
# Relational Database Interface
Here are main principles of Relational DB interface:
1) All SQL hard code is in the files described below in Files section.
No hard-coded SQL should be added to any other file in rippled, except related
to tests for specific SQL implementations.
2) Pure interface class `RelationalDBInterface` can have several
implementations for different relational database types.
3) For future use, if the node database is absent, then shard databases will
be used.
## Configuration
Section `[relational_db]` of the configuration file contains parameter
`backend`. The value of this parameter is the name of relational database
implementation used for node or shard databases. At the present, the only valid
value of this parameter is `sqlite`.
## Files
The following source files are related to Relational DB interface:
- `ripple/app/rdb/RelationalDBInterface.h` - definition of main pure class of
the interface, `RelationalDBInterface`;
- `ripple/app/rdb/impl/RelationalDBInterface.cpp` - implementation of static
method `init()` of the class `RelationalDBInterface`;
- `ripple/app/rdb/backend/RelationalDBInterfaceSqlite.h` - definition of pure
class `RelationalDBInterfaceSqlite` derived from `RelationalDBInterface`;
this is base class for sqlite implementation of the interface;
- `ripple/app/rdb/backend/RelationalDBInterfaceSqlite.cpp` - implementation of
`RelationalDBInterfaceSqlite`-derived class for the case of sqlite databases;
- `ripple/app/rdb/backend/RelationalDBInterfacePostgres.h` - definition of pure
class `RelationalDBInterfacePostgres` derived from `RelationalDBInterface`;
this is base class for postgres implementation of the interface;
- `ripple/app/rdb/backend/RelationalDBInterfacePostgres.cpp` - implementation
of `RelationalDBInterfacePostgres`-derived class for the case of postgres
databases;
- `ripple/app/rdb/RelationalDBInterface_global.h` - definitions of global
methods for all sqlite databases except of node and shard;
- `ripple/app/rdb/impl/RelationalDBInterface_global.cpp` - implementations of
global methods for all sqlite databases except of node and shard;
- `ripple/app/rdb/RelationalDBInterface_nodes.h` - definitions of global
methods for sqlite node databases;
- `ripple/app/rdb/impl/RelationalDBInterface_nodes.cpp` - implementations of
global methods for sqlite node databases;
- `ripple/app/rdb/RelationalDBInterface_shards.h` - definitions of global
methods for sqlite shard databases;
- `ripple/app/rdb/impl/RelationalDBInterface_shards.cpp` - implementations of
global methods for sqlite shard databases;
- `ripple/app/rdb/RelationalDBInterface_postgres.h` - definitions of internal
methods for postgres databases;
- `ripple/app/rdb/impl/RelationalDBInterface_postgres.cpp` - implementations of
internal methods for postgres databases;
## Classes
The main class of the interface is `class RelationalDBInterface`. It is defined
in the file `RelationalDBInterface.h`. This class has static method `init()`
which allow to create proper `RelationalDBInterface`-derived class specified
in the config. All other methods are pure virtual. These methods do not use
database as a parameter. It assumed that implementation of class derived from
`RelationalDBInterface` holds all database pointers inside and uses appropriate
databases (nodes or shards) to get return values required by each method.
At the present, there are two implementations of the derived classes -
`class RelationalDBInterfaceSqlite` for sqlite database (it is located in the
file `RelationalDBInterfaceSqlite.cpp`) and
`class RelationalDBInterfacePostgres` for postgres database (it is located in
the file `RelationalDBInterfacePostgres.cpp`)
## Methods
There are 3 types of methods for SQL interface:
1) Global methods for work with all databases except of node. In particular,
methods related to shards datavases only. These methods are sqlite-specific.
They use `soci::session` as database pointer parameter. Defined and
implemented in files `RelationalDBInterface_global.*` and
`RelationalDBInterface_shard.*`.
2) Global methods for work with node databases, and also with shard databases.
For sqlite case, these methods are internal for `RelationalDBInterfaceSqlite`
implementation of the class `RelationalDBInterface`. They use `soci::session`
as database pointer parameter. Defined and implemented in files
`RelationalDBInterface_nodes.*`. For postgres case, these methods are internal
for `RelationalDBInterfacePostgres` implementation of the class
`RelationalDBInterface`. They use `std::shared_ptr<PgPool>` as database pointer
parameter. Defined and implemented in files `RelationalDBInterface_postgres.*`.
3) Virtual methods of class `RelationalDBInterface` and also derived classes
`RelationalDBInterfaceSqlite` and `RelationalDBInterfacePostgres`.
Calling such a method resulted in calling corresponding method from
`RelationalDBInterface`-derived class. For sqlite case, such a method tries to
retrieve information from node database, and if this database not exists - then
from shard databases. For both node and shard databases, calls to global
methods of type 2) performed. For postgres case, such a method retrieves
information only from node database by calling a global method of type 2).
## Methods lists
### Type 1 methods
#### Files RelationalDBInterface_global.*
Wallet DB methods:
```
makeWalletDB
makeTestWalletDB
getManifests
saveManifests
addValidatorManifest
getNodeIdentity
getPeerReservationTable
insertPeerReservation
deletePeerReservation
createFeatureVotes
readAmendments
voteAmendment
```
State DB methods:
```
initStateDB
getCanDelete
setCanDelete
getSavedState
setSavedState
setLastRotated
```
DatabaseBody DB methods:
```
openDatabaseBodyDb
databaseBodyDoPut
databaseBodyFinish
```
Vacuum DB method:
```
doVacuumDB
```
PeerFinder DB methods:
```
initPeerFinderDB
updatePeerFinderDB
readPeerFinderDB
savePeerFinderDB
```
#### Files RelationalDBInterface_shards.*
Shards DB methods:
```
makeShardCompleteLedgerDBs
makeShardIncompleteLedgerDBs
updateLedgerDBs
```
Shard acquire DB methods:
```
makeAcquireDB
insertAcquireDBIndex
selectAcquireDBLedgerSeqs
selectAcquireDBLedgerSeqsHash
updateAcquireDB
```
Shard archive DB methods:
```
makeArchiveDB
readArchiveDB
insertArchiveDB
deleteFromArchiveDB
dropArchiveDB
```
### Type 2 methods
#### Files RelationalDBInterface_nodes.*
```
makeLedgerDBs
getMinLedgerSeq
getMaxLedgerSeq
deleteByLedgerSeq
deleteBeforeLedgerSeq
getRows
getRowsMinMax
saveValidatedLedger
getLedgerInfoByIndex
getOldestLedgerInfo
getNewestLedgerInfo
getLimitedOldestLedgerInfo
getLimitedNewestLedgerInfo
getLedgerInfoByHash
getHashByIndex
getHashesByIndex
getHashesByIndex
getTxHistory
getOldestAccountTxs
getNewestAccountTxs
getOldestAccountTxsB
getNewestAccountTxsB
oldestAccountTxPage
newestAccountTxPage
getTransaction
DbHasSpace
```
#### Files RelationalDBInterface_postgres.*
```
getMinLedgerSeq
getMaxLedgerSeq
getCompleteLedgers
getValidatedLedgerAge
getNewestLedgerInfo
getLedgerInfoByIndex
getLedgerInfoByHash
getHashByIndex
getHashesByIndex
getTxHashes
getAccountTx
locateTransaction
writeLedgerAndTransactions
getTxHistory
```
### Type 3 methods
#### Files RelationalDBInterface.*
```
init
getMinLedgerSeq
getMaxLedgerSeq
getLedgerInfoByIndex
getNewestLedgerInfo
getLedgerInfoByHash
getHashByIndex
getHashesByIndex
getTxHistory
ledgerDbHasSpace
transactionDbHasSpace
```
#### Files backend/RelationalDBInterfaceSqlite.*
```
getTransactionsMinLedgerSeq
getAccountTransactionsMinLedgerSeq
deleteTransactionByLedgerSeq
deleteBeforeLedgerSeq
deleteTransactionsBeforeLedgerSeq
deleteAccountTransactionsBeforeLedgerSeq
getTransactionCount
getAccountTransactionCount
getLedgerCountMinMax
saveValidatedLedger
getLimitedOldestLedgerInfo
getLimitedNewestLedgerInfo
getOldestAccountTxs
getNewestAccountTxs
getOldestAccountTxsB
getNewestAccountTxsB
oldestAccountTxPage
newestAccountTxPage
oldestAccountTxPageB
newestAccountTxPageB
getTransaction
getKBUsedAll
getKBUsedLedger
getKBUsedTransaction
```
#### Files backend/RelationalDBInterfacePostgres.*
```
sweep
getCompleteLedgers
getValidatedLedgerAge
writeLedgerAndTransactions
getTxHashes
getAccountTx
locateTransaction
```

View File

@@ -1,333 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2020 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_CORE_RELATIONALDBINTERFACE_GLOBAL_H_INCLUDED
#define RIPPLE_CORE_RELATIONALDBINTERFACE_GLOBAL_H_INCLUDED
#include <ripple/app/ledger/Ledger.h>
#include <ripple/app/misc/Manifest.h>
#include <ripple/core/Config.h>
#include <ripple/core/DatabaseCon.h>
#include <ripple/overlay/PeerReservationTable.h>
#include <ripple/peerfinder/impl/Store.h>
#include <boost/filesystem.hpp>
namespace ripple {
/* Wallet DB */
/**
* @brief makeWalletDB Opens wallet DB and returns it.
* @param setup Path to database and other opening parameters.
* @return Unique pointer to database descriptor.
*/
std::unique_ptr<DatabaseCon>
makeWalletDB(DatabaseCon::Setup const& setup);
/**
* @brief makeTestWalletDB Opens test wallet DB with arbitrary name.
* @param setup Path to database and other opening parameters.
* @param dbname Name of database.
* @return Unique pointer to database descriptor.
*/
std::unique_ptr<DatabaseCon>
makeTestWalletDB(DatabaseCon::Setup const& setup, std::string const& dbname);
/**
* @brief getManifests Loads manifest from wallet DB and stores it in the cache.
* @param session Session with database.
* @param dbTable Name of table in the database to extract manifest from.
* @param mCache Cache to store manifest.
* @param j Journal.
*/
void
getManifests(
soci::session& session,
std::string const& dbTable,
ManifestCache& mCache,
beast::Journal j);
/**
* @brief saveManifests Saves all given manifests to database.
* @param session Session with database.
* @param dbTable Name of database table to save manifest into.
* @param isTrusted Callback returned true if key is trusted.
* @param map Map to save which points public keys to manifests.
* @param j Journal.
*/
void
saveManifests(
soci::session& session,
std::string const& dbTable,
std::function<bool(PublicKey const&)> const& isTrusted,
hash_map<PublicKey, Manifest> const& map,
beast::Journal j);
/**
* @brief addValidatorManifest Saves manifest of validator to database.
* @param session Session with database.
* @param serialized Manifest of validator in raw format.
*/
void
addValidatorManifest(soci::session& session, std::string const& serialized);
/**
* @brief getNodeIdentity Returns public and private keys of this node.
* @param session Session with database.
* @return Pair of public and private keys.
*/
std::pair<PublicKey, SecretKey>
getNodeIdentity(soci::session& session);
/**
* @brief getPeerReservationTable Returns peer reservation table.
* @param session Session with database.
* @param j Journal.
* @return Peer reservation hash table.
*/
std::unordered_set<PeerReservation, beast::uhash<>, KeyEqual>
getPeerReservationTable(soci::session& session, beast::Journal j);
/**
* @brief insertPeerReservation Adds entry to peer reservation table.
* @param session Session with database.
* @param nodeId public key of node.
* @param description Description of node.
*/
void
insertPeerReservation(
soci::session& session,
PublicKey const& nodeId,
std::string const& description);
/**
* @brief deletePeerReservation Deletes entry from peer reservation table.
* @param session Session with database.
* @param nodeId Public key of node to remove.
*/
void
deletePeerReservation(soci::session& session, PublicKey const& nodeId);
/**
* @brief createFeatureVotes Creates FeatureVote table if it is not exists.
* @param session Session with walletDB database.
* @return true if the table already exists
*/
bool
createFeatureVotes(soci::session& session);
// For historical reasons the up-vote and down-vote integer representations
// are unintuitive.
enum class AmendmentVote : int { up = 0, down = 1 };
/**
* @brief readAmendments Read all amendments from FeatureVotes table.
* @param session Session with walletDB database.
* @param callback Callback called for each amendment passing its hash, name
* and the flag if it should be vetoed as callback parameters
*/
void
readAmendments(
soci::session& session,
std::function<void(
boost::optional<std::string> amendment_hash,
boost::optional<std::string> amendment_name,
boost::optional<AmendmentVote> vote)> const& callback);
/**
* @brief voteAmendment Set veto value for particular amendment.
* @param session Session with walletDB database.
* @param amendment Hash of amendment.
* @param name Name of amendment.
* @param vote Whether to vote in favor of this amendment.
*/
void
voteAmendment(
soci::session& session,
uint256 const& amendment,
std::string const& name,
AmendmentVote vote);
/* State DB */
struct SavedState
{
std::string writableDb;
std::string archiveDb;
LedgerIndex lastRotated;
};
/**
* @brief initStateDB Opens DB session with State DB.
* @param session Structure to open session in.
* @param config Path to database and other opening parameters.
* @param dbName Name of database.
*/
void
initStateDB(
soci::session& session,
BasicConfig const& config,
std::string const& dbName);
/**
* @brief getCanDelete Returns ledger sequence which can be deleted.
* @param session Session with database.
* @return Ledger sequence.
*/
LedgerIndex
getCanDelete(soci::session& session);
/**
* @brief setCanDelete Updates ledger sequence which can be deleted.
* @param session Session with database.
* @param canDelete Ledger sequence to save.
* @return Previous value of ledger sequence whic can be deleted.
*/
LedgerIndex
setCanDelete(soci::session& session, LedgerIndex canDelete);
/**
* @brief getSavedState Returns saved state.
* @param session Session with database.
* @return The SavedState structure which contains names of
* writable DB, archive DB and last rotated ledger sequence.
*/
SavedState
getSavedState(soci::session& session);
/**
* @brief setSavedState Saves given state.
* @param session Session with database.
* @param state The SavedState structure which contains names of
* writable DB, archive DB and last rotated ledger sequence.
*/
void
setSavedState(soci::session& session, SavedState const& state);
/**
* @brief setLastRotated Updates last rotated ledger sequence.
* @param session Session with database.
* @param seq New value of last rotated ledger sequence.
*/
void
setLastRotated(soci::session& session, LedgerIndex seq);
/* DatabaseBody DB */
/**
* @brief openDatabaseBodyDb Opens file download DB and returns its descriptor.
* Start new download process or continue existing one.
* @param setup Path to database and other opening parameters.
* @param path Path of new file to download.
* @return Pair of unique pointer to database and current downloaded size
* if download process continues.
*/
std::pair<std::unique_ptr<DatabaseCon>, std::optional<std::uint64_t>>
openDatabaseBodyDb(
DatabaseCon::Setup const& setup,
boost::filesystem::path const& path);
/**
* @brief databaseBodyDoPut Saves new fragment of downloaded file.
* @param session Session with database.
* @param data Downloaded piece to file data tp save.
* @param path Path of downloading file.
* @param fileSize Size of downloaded piece of file.
* @param part Sequence number of downloaded file part.
* @param maxRowSizePad Maximum size of file part to save.
* @return Number of saved parts. Downloaded piece may be splitted
* into several parts of size not large that maxRowSizePad.
*/
std::uint64_t
databaseBodyDoPut(
soci::session& session,
std::string const& data,
std::string const& path,
std::uint64_t fileSize,
std::uint64_t part,
std::uint16_t maxRowSizePad);
/**
* @brief databaseBodyFinish Finishes download process and writes file to disk.
* @param session Session with database.
* @param fout Opened file to write downloaded data from database.
*/
void
databaseBodyFinish(soci::session& session, std::ofstream& fout);
/* Vacuum DB */
/**
* @brief doVacuumDB Creates, initialises DB, and performs its cleanup.
* @param setup Path to database and other opening parameters.
* @return True if vacuum process completed successfully.
*/
bool
doVacuumDB(DatabaseCon::Setup const& setup);
/* PeerFinder DB */
/**
* @brief initPeerFinderDB Opens session with peer finder database.
* @param session Structure to open session in.
* @param config Path to database and other opening parameters.
* @param j Journal.
*/
void
initPeerFinderDB(
soci::session& session,
BasicConfig const& config,
beast::Journal j);
/**
* @brief updatePeerFinderDB Update peer finder DB to new version.
* @param session Session with database.
* @param currentSchemaVersion New version of database.
* @param j Journal.
*/
void
updatePeerFinderDB(
soci::session& session,
int currentSchemaVersion,
beast::Journal j);
/**
* @brief readPeerFinderDB Read all entries from peer finder DB and call
* given callback for each entry.
* @param session Session with database.
* @param func Callback to call for each entry.
*/
void
readPeerFinderDB(
soci::session& session,
std::function<void(std::string const&, int)> const& func);
/**
* @brief savePeerFinderDB Save new entry to peer finder DB.
* @param session Session with database.
* @param v Entry to save which contains information about new peer.
*/
void
savePeerFinderDB(
soci::session& session,
std::vector<PeerFinder::Store::Entry> const& v);
} // namespace ripple
#endif

View File

@@ -1,248 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2021 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_CORE_RELATIONALDBINTERFACE_POSTGRES_H_INCLUDED
#define RIPPLE_CORE_RELATIONALDBINTERFACE_POSTGRES_H_INCLUDED
#include <ripple/app/ledger/Ledger.h>
#include <ripple/app/main/Application.h>
#include <ripple/app/misc/Transaction.h>
#include <ripple/app/rdb/RelationalDBInterface.h>
#include <ripple/core/Pg.h>
#include <variant>
#include <vector>
namespace ripple {
class PgPool;
using AccountTxMarker = RelationalDBInterface::AccountTxMarker;
using AccountTxArgs = RelationalDBInterface::AccountTxArgs;
using AccountTxResult = RelationalDBInterface::AccountTxResult;
using AccountTransactionsData = RelationalDBInterface::AccountTransactionsData;
/**
* @brief getMinLedgerSeq Returns minimum ledger sequence
* from Postgres database
* @param pgPool Link to postgres database
* @param app Application
* @param j Journal
* @return Minimum ledger sequence if any, none if no ledgers
*/
std::optional<LedgerIndex>
getMinLedgerSeq(std::shared_ptr<PgPool> const& pgPool, beast::Journal j);
/**
* @brief getMaxLedgerSeq Returns maximum ledger sequence
* from Postgres database
* @param pgPool Link to postgres database
* @param app Application
* @return Maximum ledger sequence if any, none if no ledgers
*/
std::optional<LedgerIndex>
getMaxLedgerSeq(std::shared_ptr<PgPool> const& pgPool);
/**
* @brief getCompleteLedgers Returns string which contains
* list of completed ledgers
* @param pgPool Link to postgres database
* @param app Application
* @return String with completed ledgers
*/
std::string
getCompleteLedgers(std::shared_ptr<PgPool> const& pgPool);
/**
* @brief getValidatedLedgerAge Returns age of last
* validated ledger
* @param pgPool Link to postgres database
* @param app Application
* @param j Journal
* @return Age of last validated ledger
*/
std::chrono::seconds
getValidatedLedgerAge(std::shared_ptr<PgPool> const& pgPool, beast::Journal j);
/**
* @brief getNewestLedgerInfo Load latest ledger info from Postgres
* @param pgPool Link to postgres database
* @param app reference to Application
* @return Ledger info
*/
std::optional<LedgerInfo>
getNewestLedgerInfo(std::shared_ptr<PgPool> const& pgPool, Application& app);
/**
* @brief getLedgerInfoByIndex Load ledger info by index (AKA sequence)
* from Postgres
* @param pgPool Link to postgres database
* @param ledgerIndex the ledger index (or sequence) to load
* @param app reference to Application
* @return Ledger info
*/
std::optional<LedgerInfo>
getLedgerInfoByIndex(
std::shared_ptr<PgPool> const& pgPool,
std::uint32_t ledgerIndex,
Application& app);
/**
* @brief getLedgerInfoByHash Load ledger info by hash from Postgres
* @param pgPool Link to postgres database
* @param hash Hash of the ledger to load
* @param app reference to Application
* @return Ledger info
*/
std::optional<LedgerInfo>
getLedgerInfoByHash(
std::shared_ptr<PgPool> const& pgPool,
uint256 const& ledgerHash,
Application& app);
/**
* @brief getHashByIndex Given a ledger sequence,
* return the ledger hash
* @param pgPool Link to postgres database
* @param ledgerIndex Ledger sequence
* @param app Application
* @return Hash of ledger
*/
uint256
getHashByIndex(
std::shared_ptr<PgPool> const& pgPool,
std::uint32_t ledgerIndex,
Application& app);
/**
* @brief getHashesByIndex Given a ledger sequence,
* return the ledger hash and the parent hash
* @param pgPool Link to postgres database
* @param ledgerIndex Ledger sequence
* @param[out] ledgerHash Hash of ledger
* @param[out] parentHash Hash of parent ledger
* @param app Application
* @return True if the data was found
*/
bool
getHashesByIndex(
std::shared_ptr<PgPool> const& pgPool,
std::uint32_t ledgerIndex,
uint256& ledgerHash,
uint256& parentHash,
Application& app);
/**
* @brief getHashesByIndex Given a contiguous range of sequences,
* return a map of sequence -> (hash, parent hash)
* @param pgPool Link to postgres database
* @param minSeq Lower bound of range
* @param maxSeq Upper bound of range
* @param app Application
* @return Mapping of all found ledger sequences to their hash and parent hash
*/
std::map<std::uint32_t, LedgerHashPair>
getHashesByIndex(
std::shared_ptr<PgPool> const& pgPool,
std::uint32_t minSeq,
std::uint32_t maxSeq,
Application& app);
/**
* @brief getTxHashes Returns vector of tx hashes by given ledger
* sequence
* @param pgPool Link to postgres database
* @param seq Ledger sequence
* @param app Application
* @return Vector of tx hashes
*/
std::vector<uint256>
getTxHashes(
std::shared_ptr<PgPool> const& pgPool,
LedgerIndex seq,
Application& app);
/**
* @brief locateTransaction Returns information used to locate
* a transaction. Function is specific to postgres backend.
* @param pgPool Link to postgres database
* @param id Hash of the transaction.
* @param app Application
* @return Information used to locate a transaction. Contains a nodestore
* hash and ledger sequence pair if the transaction was found.
* Otherwise, contains the range of ledgers present in the database
* at the time of search.
*/
Transaction::Locator
locateTransaction(
std::shared_ptr<PgPool> const& pgPool,
uint256 const& id,
Application& app);
/**
* @brief getTxHistory Returns most recent 20 transactions starting
* from given number or entry.
* @param pgPool Link to postgres database
* @param startIndex First number of returned entry.
* @param app Application
* @param j Journal
* @return Vector of sharded pointers to transactions sorted in
* descending order by ledger sequence.
*/
std::vector<std::shared_ptr<Transaction>>
getTxHistory(
std::shared_ptr<PgPool> const& pgPool,
LedgerIndex startIndex,
Application& app,
beast::Journal j);
/**
* @brief getAccountTx Get last account transactions specifies by
* passed argumenrs structure.
* @param pgPool Link to postgres database
* @param args Arguments which specify account and whose tx to return.
* @param app Application
* @param j Journal
* @return Vector of account transactions and RPC status of responce.
*/
std::pair<AccountTxResult, RPC::Status>
getAccountTx(
std::shared_ptr<PgPool> const& pgPool,
AccountTxArgs const& args,
Application& app,
beast::Journal j);
/**
* @brief writeLedgerAndTransactions Write new ledger and transaction
* data to Postgres.
* @param pgPool Pool of Postgres connections
* @param info Ledger info to write.
* @param accountTxData Transaction data to write
* @param j Journal (for logging)
* @return True if success, false if failure.
*/
bool
writeLedgerAndTransactions(
std::shared_ptr<PgPool> const& pgPool,
LedgerInfo const& info,
std::vector<AccountTransactionsData> const& accountTxData,
beast::Journal& j);
} // namespace ripple
#endif

View File

@@ -1,257 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2020 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_CORE_RELATIONALDBINTERFACE_SHARDS_H_INCLUDED
#define RIPPLE_CORE_RELATIONALDBINTERFACE_SHARDS_H_INCLUDED
#include <ripple/app/ledger/Ledger.h>
#include <ripple/app/rdb/RelationalDBInterface.h>
#include <ripple/core/Config.h>
#include <ripple/protocol/RippleLedgerHash.h>
#include <boost/filesystem.hpp>
namespace ripple {
struct DatabasePair
{
std::unique_ptr<DatabaseCon> ledgerDb;
std::unique_ptr<DatabaseCon> transactionDb;
};
/* Shard DB */
/**
* @brief makeMetaDBs Opens ledger and transaction 'meta' databases which
* map ledger hashes and transaction IDs to the index of the shard
* that holds the ledger or transaction.
* @param config Config object.
* @param setup Path to database and opening parameters.
* @param checkpointerSetup Database checkpointer setup.
* @return Struct DatabasePair which contains unique pointers to the ledger
* and transaction databases.
*/
DatabasePair
makeMetaDBs(
Config const& config,
DatabaseCon::Setup const& setup,
DatabaseCon::CheckpointerSetup const& checkpointerSetup);
/**
* @brief saveLedgerMeta Stores (transaction ID -> shard index) and
* (ledger hash -> shard index) mappings in the meta databases.
* @param ledger The ledger.
* @param app Application object.
* @param lgrMetaSession Session to ledger meta database.
* @param txnMetaSession Session to transaction meta database.
* @param shardIndex The index of the shard that contains this ledger.
* @return True on success.
*/
bool
saveLedgerMeta(
std::shared_ptr<Ledger const> const& ledger,
Application& app,
soci::session& lgrMetaSession,
soci::session& txnMetaSession,
std::uint32_t shardIndex);
/**
* @brief getShardIndexforLedger Queries the ledger meta database to
* retrieve the index of the shard that contains this ledger.
* @param session Session to the database.
* @param hash Hash of the ledger.
* @return The index of the shard on success, otherwise an unseated value.
*/
std::optional<std::uint32_t>
getShardIndexforLedger(soci::session& session, LedgerHash const& hash);
/**
* @brief getShardIndexforTransaction Queries the transaction meta database to
* retrieve the index of the shard that contains this transaction.
* @param session Session to the database.
* @param id ID of the transaction.
* @return The index of the shard on success, otherwise an unseated value.
*/
std::optional<std::uint32_t>
getShardIndexforTransaction(soci::session& session, TxID const& id);
/**
* @brief makeShardCompleteLedgerDBs Opens shard databases for already
* verified shard and returns its descriptors.
* @param config Config object.
* @param setup Path to database and other opening parameters.
* @return Pair of unique pointers to opened ledger and transaction databases.
*/
DatabasePair
makeShardCompleteLedgerDBs(
Config const& config,
DatabaseCon::Setup const& setup);
/**
* @brief makeShardIncompleteLedgerDBs Opens shard databases for not
* fully downloaded or verified shard and returns its descriptors.
* @param config Config object.
* @param setup Path to database and other opening parameters.
* @param checkpointerSetup Checkpointer parameters.
* @return Pair of unique pointers to opened ledger and transaction databases.
*/
DatabasePair
makeShardIncompleteLedgerDBs(
Config const& config,
DatabaseCon::Setup const& setup,
DatabaseCon::CheckpointerSetup const& checkpointerSetup);
/**
* @brief updateLedgerDBs Save given ledger to shard databases.
* @param txdb Session with transaction DB.
* @param lgrdb Sessiob with ledger DB.
* @param ledger Ledger to save.
* @param index Index of the shard which the ledger belonfs to.
* @param stop Link to atomic flag which can stop the process if raised.
* @param j Journal
* @return True if ledger was successfully saved.
*/
bool
updateLedgerDBs(
soci::session& txdb,
soci::session& lgrdb,
std::shared_ptr<Ledger const> const& ledger,
std::uint32_t index,
std::atomic<bool>& stop,
beast::Journal j);
/* Shard acquire DB */
/**
* @brief makeAcquireDB Opens shard acquire DB and returns its descriptor.
* @param setup Path to DB and other opening parameters.
* @param checkpointerSetup Checkpointer parameters.
* @return Uniqye pointer to opened database.
*/
std::unique_ptr<DatabaseCon>
makeAcquireDB(
DatabaseCon::Setup const& setup,
DatabaseCon::CheckpointerSetup const& checkpointerSetup);
/**
* @brief insertAcquireDBIndex Adds new shard index to shard acquire DB.
* @param session Session with database.
* @param index Index to add.
*/
void
insertAcquireDBIndex(soci::session& session, std::uint32_t index);
/**
* @brief selectAcquireDBLedgerSeqs Returns set of acquired ledgers for
* given shard.
* @param session Session with database.
* @param index Shard index.
* @return Pair which contains true if such as index found in database,
* and string which contains set of ledger sequences.
* If set of sequences was not saved than none is returned.
*/
std::pair<bool, std::optional<std::string>>
selectAcquireDBLedgerSeqs(soci::session& session, std::uint32_t index);
struct AcquireShardSeqsHash
{
std::optional<std::string> sequences;
std::optional<std::string> hash;
};
/**
* @brief selectAcquireDBLedgerSeqsHash Returns set of acquired ledgers and
* hash for given shard.
* @param session Session with database.
* @param index Shard index.
* @return Pair which contains true of such an index found in database,
* and the AcquireShardSeqsHash structure which contains string
* with ledger sequences set and string with last ledger hash.
* If set of sequences or hash were not saved than none is returned.
*/
std::pair<bool, AcquireShardSeqsHash>
selectAcquireDBLedgerSeqsHash(soci::session& session, std::uint32_t index);
/**
* @brief updateAcquireDB Updates information in acquire DB.
* @param session Session with database.
* @param ledger Ledger to save into database.
* @param index Shard index.
* @param lastSeq Last acqyured ledger sequence.
* @param seqs Current set or acquired ledger sequences if it's not empty.
*/
void
updateAcquireDB(
soci::session& session,
std::shared_ptr<Ledger const> const& ledger,
std::uint32_t index,
std::uint32_t lastSeq,
std::optional<std::string> const& seqs);
/* Archive DB */
/**
* @brief makeArchiveDB Opens shard archive DB and returns its descriptor.
* @param dir Path to database to open.
* @param dbName Name of database.
* @return Unique pointer to opened database.
*/
std::unique_ptr<DatabaseCon>
makeArchiveDB(boost::filesystem::path const& dir, std::string const& dbName);
/**
* @brief readArchiveDB Read entries from shard archive database and calls
* fiven callback for each entry.
* @param db Session with database.
* @param func Callback to call for each entry.
*/
void
readArchiveDB(
DatabaseCon& db,
std::function<void(std::string const&, int)> const& func);
/**
* @brief insertArchiveDB Adds entry to shard archive database.
* @param db Session with database.
* @param shardIndex Shard index to add.
* @param url Shard download url to add.
*/
void
insertArchiveDB(
DatabaseCon& db,
std::uint32_t shardIndex,
std::string const& url);
/**
* @brief deleteFromArchiveDB Deletes entry from shard archive DB.
* @param db Session with database.
* @param shardIndex Shard index to remove from DB.
*/
void
deleteFromArchiveDB(DatabaseCon& db, std::uint32_t shardIndex);
/**
* @brief dropArchiveDB Removes table in shard archive DB.
* @param db Session with database.
*/
void
dropArchiveDB(DatabaseCon& db);
} // namespace ripple
#endif

View File

@@ -17,8 +17,8 @@
*/
//==============================================================================
#ifndef RIPPLE_CORE_RELATIONALDBINTERFACE_H_INCLUDED
#define RIPPLE_CORE_RELATIONALDBINTERFACE_H_INCLUDED
#ifndef RIPPLE_APP_RDB_RELATIONALDATABASE_H_INCLUDED
#define RIPPLE_APP_RDB_RELATIONALDATABASE_H_INCLUDED
#include <ripple/app/ledger/Ledger.h>
#include <ripple/app/main/Application.h>
@@ -45,7 +45,7 @@ struct LedgerRange
uint32_t max;
};
class RelationalDBInterface
class RelationalDatabase
{
public:
struct CountMinMax
@@ -135,56 +135,61 @@ public:
};
/**
* @brief init Creates and returns appropriate interface based on config.
* @brief init Creates and returns an appropriate RelationalDatabase
* instance based on configuration.
* @param app Application object.
* @param config Config object.
* @param jobQueue JobQueue object.
* @return Unique pointer to the interface.
*/
static std::unique_ptr<RelationalDBInterface>
static std::unique_ptr<RelationalDatabase>
init(Application& app, Config const& config, JobQueue& jobQueue);
virtual ~RelationalDBInterface() = default;
virtual ~RelationalDatabase() = default;
/**
* @brief getMinLedgerSeq Returns minimum ledger sequence in Ledgers table.
* @return Ledger sequence or none if no ledgers exist.
* @brief getMinLedgerSeq Returns the minimum ledger sequence in the Ledgers
* table.
* @return Ledger sequence or no value if no ledgers exist.
*/
virtual std::optional<LedgerIndex>
getMinLedgerSeq() = 0;
/**
* @brief getMaxLedgerSeq Returns maximum ledger sequence in Ledgers table.
* @brief getMaxLedgerSeq Returns the maximum ledger sequence in the Ledgers
* table.
* @return Ledger sequence or none if no ledgers exist.
*/
virtual std::optional<LedgerIndex>
getMaxLedgerSeq() = 0;
/**
* @brief getLedgerInfoByIndex Returns ledger by its sequence.
* @brief getLedgerInfoByIndex Returns a ledger by its sequence.
* @param ledgerSeq Ledger sequence.
* @return Ledger or none if ledger not found.
* @return The ledger if found, otherwise no value.
*/
virtual std::optional<LedgerInfo>
getLedgerInfoByIndex(LedgerIndex ledgerSeq) = 0;
/**
* @brief getNewestLedgerInfo Returns info of newest saved ledger.
* @return Ledger info or none if ledger not found.
* @brief getNewestLedgerInfo Returns the info of the newest saved ledger.
* @return Ledger info if found, otherwise no value.
*/
virtual std::optional<LedgerInfo>
getNewestLedgerInfo() = 0;
/**
* @brief getLedgerInfoByHash Returns info of ledger with given hash.
* @brief getLedgerInfoByHash Returns the info of the ledger with given
* hash.
* @param ledgerHash Hash of the ledger.
* @return Ledger or none if ledger not found.
* @return Ledger if found, otherwise no value.
*/
virtual std::optional<LedgerInfo>
getLedgerInfoByHash(uint256 const& ledgerHash) = 0;
/**
* @brief getHashByIndex Returns hash of ledger with given sequence.
* @brief getHashByIndex Returns the hash of the ledger with the given
* sequence.
* @param ledgerIndex Ledger sequence.
* @return Hash of the ledger.
*/
@@ -192,39 +197,40 @@ public:
getHashByIndex(LedgerIndex ledgerIndex) = 0;
/**
* @brief getHashesByIndex Returns hash of the ledger and hash of parent
* ledger for the ledger of given sequence.
* @brief getHashesByIndex Returns the hashes of the ledger and its parent
* as specified by the ledgerIndex.
* @param ledgerIndex Ledger sequence.
* @return Struct LedgerHashPair which contain hashes of the ledger and
* its parent ledger.
* @return Struct LedgerHashPair which contains hashes of the ledger and
* its parent.
*/
virtual std::optional<LedgerHashPair>
getHashesByIndex(LedgerIndex ledgerIndex) = 0;
/**
* @brief getHashesByIndex Returns hash of the ledger and hash of parent
* ledger for all ledgers with sequences from given minimum limit
* to given maximum limit.
* @brief getHashesByIndex Returns hashes of each ledger and its parent for
* all ledgers within the provided range.
* @param minSeq Minimum ledger sequence.
* @param maxSeq Maximum ledger sequence.
* @return Map which points sequence number of found ledger to the struct
* LedgerHashPair which contains ledger hash and its parent hash.
* @return Container that maps the sequence number of a found ledger to the
* struct LedgerHashPair which contains the hashes of the ledger and
* its parent.
*/
virtual std::map<LedgerIndex, LedgerHashPair>
getHashesByIndex(LedgerIndex minSeq, LedgerIndex maxSeq) = 0;
/**
* @brief getTxHistory Returns most recent 20 transactions starting from
* given number or entry.
* @brief getTxHistory Returns the 20 most recent transactions starting from
* the given number.
* @param startIndex First number of returned entry.
* @return Vector of sharded pointers to transactions sorted in
* @return Vector of shared pointers to transactions sorted in
* descending order by ledger sequence.
*/
virtual std::vector<std::shared_ptr<Transaction>>
getTxHistory(LedgerIndex startIndex) = 0;
/**
* @brief ledgerDbHasSpace Checks if ledger database has available space.
* @brief ledgerDbHasSpace Checks if the ledger database has available
* space.
* @param config Config object.
* @return True if space is available.
*/
@@ -232,7 +238,7 @@ public:
ledgerDbHasSpace(Config const& config) = 0;
/**
* @brief transactionDbHasSpace Checks if transaction database has
* @brief transactionDbHasSpace Checks if the transaction database has
* available space.
* @param config Config object.
* @return True if space is available.

View File

@@ -0,0 +1,78 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2021 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_APP_RDB_SHARDARCHIVE_H_INCLUDED
#define RIPPLE_APP_RDB_SHARDARCHIVE_H_INCLUDED
#include <ripple/core/DatabaseCon.h>
#include <boost/filesystem.hpp>
namespace ripple {
/**
* @brief makeArchiveDB Opens the shard archive database and returns its
* descriptor.
* @param dir Path to the database to open.
* @param dbName Name of the database.
* @return Unique pointer to the opened database.
*/
std::unique_ptr<DatabaseCon>
makeArchiveDB(boost::filesystem::path const& dir, std::string const& dbName);
/**
* @brief readArchiveDB Reads entries from the shard archive database and
* invokes the given callback for each entry.
* @param db Session with the database.
* @param func Callback to invoke for each entry.
*/
void
readArchiveDB(
DatabaseCon& db,
std::function<void(std::string const&, int)> const& func);
/**
* @brief insertArchiveDB Adds an entry to the shard archive database.
* @param db Session with the database.
* @param shardIndex Shard index to add.
* @param url Shard download url to add.
*/
void
insertArchiveDB(
DatabaseCon& db,
std::uint32_t shardIndex,
std::string const& url);
/**
* @brief deleteFromArchiveDB Deletes an entry from the shard archive database.
* @param db Session with the database.
* @param shardIndex Shard index to remove from the database.
*/
void
deleteFromArchiveDB(DatabaseCon& db, std::uint32_t shardIndex);
/**
* @brief dropArchiveDB Removes a table in the shard archive database.
* @param db Session with the database.
*/
void
dropArchiveDB(DatabaseCon& db);
} // namespace ripple
#endif

View File

@@ -0,0 +1,98 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2021 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_APP_RDB_STATE_H_INCLUDED
#define RIPPLE_APP_RDB_STATE_H_INCLUDED
#include <ripple/app/ledger/Ledger.h>
#include <ripple/app/misc/Manifest.h>
#include <ripple/core/Config.h>
#include <ripple/core/DatabaseCon.h>
#include <ripple/overlay/PeerReservationTable.h>
#include <ripple/peerfinder/impl/Store.h>
#include <boost/filesystem.hpp>
namespace ripple {
struct SavedState
{
std::string writableDb;
std::string archiveDb;
LedgerIndex lastRotated;
};
/**
* @brief initStateDB Opens a session with the State database.
* @param session Provides a session with the database.
* @param config Path to the database and other opening parameters.
* @param dbName Name of the database.
*/
void
initStateDB(
soci::session& session,
BasicConfig const& config,
std::string const& dbName);
/**
* @brief getCanDelete Returns the ledger sequence which can be deleted.
* @param session Session with the database.
* @return Ledger sequence.
*/
LedgerIndex
getCanDelete(soci::session& session);
/**
* @brief setCanDelete Updates the ledger sequence which can be deleted.
* @param session Session with the database.
* @param canDelete Ledger sequence to save.
* @return Previous value of the ledger sequence which can be deleted.
*/
LedgerIndex
setCanDelete(soci::session& session, LedgerIndex canDelete);
/**
* @brief getSavedState Returns the saved state.
* @param session Session with the database.
* @return The SavedState structure which contains the names of the writable
* database, the archive database and the last rotated ledger sequence.
*/
SavedState
getSavedState(soci::session& session);
/**
* @brief setSavedState Saves the given state.
* @param session Session with the database.
* @param state The SavedState structure which contains the names of the
* writable database, the archive database and the last rotated ledger
* sequence.
*/
void
setSavedState(soci::session& session, SavedState const& state);
/**
* @brief setLastRotated Updates the last rotated ledger sequence.
* @param session Session with the database.
* @param seq New value of the last rotated ledger sequence.
*/
void
setLastRotated(soci::session& session, LedgerIndex seq);
} // namespace ripple
#endif

View File

@@ -0,0 +1,155 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2021 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_APP_RDB_UNITARYSHARD_H_INCLUDED
#define RIPPLE_APP_RDB_UNITARYSHARD_H_INCLUDED
#include <ripple/app/ledger/Ledger.h>
#include <ripple/app/rdb/RelationalDatabase.h>
#include <ripple/core/Config.h>
#include <ripple/protocol/RippleLedgerHash.h>
#include <boost/filesystem.hpp>
namespace ripple {
struct DatabasePair
{
std::unique_ptr<DatabaseCon> ledgerDb;
std::unique_ptr<DatabaseCon> transactionDb;
};
/**
* @brief makeShardCompleteLedgerDBs Opens shard databases for verified shards
* and returns their descriptors.
* @param config Config object.
* @param setup Path to the databases and other opening parameters.
* @return Pair of unique pointers to the opened ledger and transaction
* databases.
*/
DatabasePair
makeShardCompleteLedgerDBs(
Config const& config,
DatabaseCon::Setup const& setup);
/**
* @brief makeShardIncompleteLedgerDBs Opens shard databases for partially
* downloaded or unverified shards and returns their descriptors.
* @param config Config object.
* @param setup Path to the databases and other opening parameters.
* @param checkpointerSetup Checkpointer parameters.
* @return Pair of unique pointers to the opened ledger and transaction
* databases.
*/
DatabasePair
makeShardIncompleteLedgerDBs(
Config const& config,
DatabaseCon::Setup const& setup,
DatabaseCon::CheckpointerSetup const& checkpointerSetup);
/**
* @brief updateLedgerDBs Saves the given ledger to shard databases.
* @param txdb Session with the transaction databases.
* @param lgrdb Session with the ledger databases.
* @param ledger Ledger to save.
* @param index Index of the shard that owns the ledger.
* @param stop Reference to an atomic flag that can stop the process if raised.
* @param j Journal
* @return True if the ledger was successfully saved.
*/
bool
updateLedgerDBs(
soci::session& txdb,
soci::session& lgrdb,
std::shared_ptr<Ledger const> const& ledger,
std::uint32_t index,
std::atomic<bool>& stop,
beast::Journal j);
/**
* @brief makeAcquireDB Opens the shard acquire database and returns its
* descriptor.
* @param setup Path to the database and other opening parameters.
* @param checkpointerSetup Checkpointer parameters.
* @return Unique pointer to the opened database.
*/
std::unique_ptr<DatabaseCon>
makeAcquireDB(
DatabaseCon::Setup const& setup,
DatabaseCon::CheckpointerSetup const& checkpointerSetup);
/**
* @brief insertAcquireDBIndex Adds a new shard index to the shard acquire
* database.
* @param session Session with the database.
* @param index Index to add.
*/
void
insertAcquireDBIndex(soci::session& session, std::uint32_t index);
/**
* @brief selectAcquireDBLedgerSeqs Returns the set of acquired ledgers for
* the given shard.
* @param session Session with the database.
* @param index Shard index.
* @return Pair which contains true if such an index was found in the database,
* and a string which contains the set of ledger sequences.
* If no sequences were saved then the optional will have no value.
*/
std::pair<bool, std::optional<std::string>>
selectAcquireDBLedgerSeqs(soci::session& session, std::uint32_t index);
struct AcquireShardSeqsHash
{
std::optional<std::string> sequences;
std::optional<std::string> hash;
};
/**
* @brief selectAcquireDBLedgerSeqsHash Returns the set of acquired ledger
* sequences and the last ledger hash for the shard with the provided
* index.
* @param session Session with the database.
* @param index Shard index.
* @return Pair which contains true if such an index was found in the database
* and the AcquireShardSeqsHash structure which contains a string with
* the ledger sequences and a string with last ledger hash. If the set
* of sequences or hash were not saved then no value is returned.
*/
std::pair<bool, AcquireShardSeqsHash>
selectAcquireDBLedgerSeqsHash(soci::session& session, std::uint32_t index);
/**
* @brief updateAcquireDB Updates information in the acquire DB.
* @param session Session with the database.
* @param ledger Ledger to save into the database.
* @param index Shard index.
* @param lastSeq Last acquired ledger sequence.
* @param seqs Current set of acquired ledger sequences if it's not empty.
*/
void
updateAcquireDB(
soci::session& session,
std::shared_ptr<Ledger const> const& ledger,
std::uint32_t index,
std::uint32_t lastSeq,
std::optional<std::string> const& seqs);
} // namespace ripple
#endif

View File

@@ -0,0 +1,37 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2021 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_APP_RDB_VACUUM_H_INCLUDED
#define RIPPLE_APP_RDB_VACUUM_H_INCLUDED
#include <ripple/core/DatabaseCon.h>
namespace ripple {
/**
* @brief doVacuumDB Creates, initialises, and performs cleanup on a database.
* @param setup Path to the database and other opening parameters.
* @return True if the vacuum process completed successfully.
*/
bool
doVacuumDB(DatabaseCon::Setup const& setup);
} // namespace ripple
#endif

170
src/ripple/app/rdb/Wallet.h Normal file
View File

@@ -0,0 +1,170 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2021 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_APP_RDB_WALLET_H_INCLUDED
#define RIPPLE_APP_RDB_WALLET_H_INCLUDED
#include <ripple/app/ledger/Ledger.h>
#include <ripple/app/misc/Manifest.h>
#include <ripple/core/Config.h>
#include <ripple/core/DatabaseCon.h>
#include <ripple/overlay/PeerReservationTable.h>
#include <ripple/peerfinder/impl/Store.h>
namespace ripple {
/**
* @brief makeWalletDB Opens the wallet database and returns it.
* @param setup Path to the database and other opening parameters.
* @return Unique pointer to the database descriptor.
*/
std::unique_ptr<DatabaseCon>
makeWalletDB(DatabaseCon::Setup const& setup);
/**
* @brief makeTestWalletDB Opens a test wallet database with an arbitrary name.
* @param setup Path to the database and other opening parameters.
* @param dbname Name of the database.
* @return Unique pointer to the database descriptor.
*/
std::unique_ptr<DatabaseCon>
makeTestWalletDB(DatabaseCon::Setup const& setup, std::string const& dbname);
/**
* @brief getManifests Loads a manifest from the wallet database and stores it
* in the cache.
* @param session Session with the database.
* @param dbTable Name of the database table from which the manifest will be
* extracted.
* @param mCache Cache for storing the manifest.
* @param j Journal.
*/
void
getManifests(
soci::session& session,
std::string const& dbTable,
ManifestCache& mCache,
beast::Journal j);
/**
* @brief saveManifests Saves all given manifests to the database.
* @param session Session with the database.
* @param dbTable Name of the database table that will store the manifest.
* @param isTrusted Callback that returns true if the key is trusted.
* @param map Maps public keys to manifests.
* @param j Journal.
*/
void
saveManifests(
soci::session& session,
std::string const& dbTable,
std::function<bool(PublicKey const&)> const& isTrusted,
hash_map<PublicKey, Manifest> const& map,
beast::Journal j);
/**
* @brief addValidatorManifest Saves the manifest of a validator to the
* database.
* @param session Session with the database.
* @param serialized Manifest of the validator in raw format.
*/
void
addValidatorManifest(soci::session& session, std::string const& serialized);
/**
* @brief getNodeIdentity Returns the public and private keys of this node.
* @param session Session with the database.
* @return Pair of public and private keys.
*/
std::pair<PublicKey, SecretKey>
getNodeIdentity(soci::session& session);
/**
* @brief getPeerReservationTable Returns the peer reservation table.
* @param session Session with the database.
* @param j Journal.
* @return Peer reservation hash table.
*/
std::unordered_set<PeerReservation, beast::uhash<>, KeyEqual>
getPeerReservationTable(soci::session& session, beast::Journal j);
/**
* @brief insertPeerReservation Adds an entry to the peer reservation table.
* @param session Session with the database.
* @param nodeId Public key of the node.
* @param description Description of the node.
*/
void
insertPeerReservation(
soci::session& session,
PublicKey const& nodeId,
std::string const& description);
/**
* @brief deletePeerReservation Deletes an entry from the peer reservation
* table.
* @param session Session with the database.
* @param nodeId Public key of the node to remove.
*/
void
deletePeerReservation(soci::session& session, PublicKey const& nodeId);
/**
* @brief createFeatureVotes Creates the FeatureVote table if it does not exist.
* @param session Session with the wallet database.
* @return true if the table already exists
*/
bool
createFeatureVotes(soci::session& session);
// For historical reasons the up-vote and down-vote integer representations
// are unintuitive.
enum class AmendmentVote : int { up = 0, down = 1 };
/**
* @brief readAmendments Reads all amendments from the FeatureVotes table.
* @param session Session with the wallet database.
* @param callback Callback called for each amendment with its hash, name and
* optionally a flag denoting whether the amendment should be vetoed.
*/
void
readAmendments(
soci::session& session,
std::function<void(
boost::optional<std::string> amendment_hash,
boost::optional<std::string> amendment_name,
boost::optional<AmendmentVote> vote)> const& callback);
/**
* @brief voteAmendment Set the veto value for a particular amendment.
* @param session Session with the wallet database.
* @param amendment Hash of the amendment.
* @param name Name of the amendment.
* @param vote Whether to vote in favor of this amendment.
*/
void
voteAmendment(
soci::session& session,
uint256 const& amendment,
std::string const& name,
AmendmentVote vote);
} // namespace ripple
#endif

View File

@@ -17,55 +17,47 @@
*/
//==============================================================================
#ifndef RIPPLE_CORE_RELATIONALDBINTERFACEPOSTGRES_H_INCLUDED
#define RIPPLE_CORE_RELATIONALDBINTERFACEPOSTGRES_H_INCLUDED
#ifndef RIPPLE_APP_RDB_BACKEND_POSTGRESDATABASE_H_INCLUDED
#define RIPPLE_APP_RDB_BACKEND_POSTGRESDATABASE_H_INCLUDED
#include <ripple/app/rdb/RelationalDBInterface.h>
#include <ripple/app/rdb/RelationalDatabase.h>
namespace ripple {
class RelationalDBInterfacePostgres : public RelationalDBInterface
class PostgresDatabase : public RelationalDatabase
{
public:
/** There is only one implementation of this interface:
* RelationalDBInterfacePostgresImp. It wraps a stoppable object (PgPool)
* that does not follow RAII, and it does not go through the effort of
* following RAII either. The owner of the only object of that type
* (ApplicationImp) holds it by the type of its interface instead of its
* implementation, and thus the lifetime management methods need to be
* part of the interface.
*/
virtual void
stop() = 0;
/**
* @brief sweep Sweep the database. Method is specific for postgres backend.
* @brief sweep Sweeps the database.
*/
virtual void
sweep() = 0;
/**
* @brief getCompleteLedgers Returns string which contains list of
* completed ledgers. Method is specific for postgres backend.
* @return String with completed ledger numbers
* @brief getCompleteLedgers Returns a string which contains a list of
* completed ledgers.
* @return String with completed ledger sequences
*/
virtual std::string
getCompleteLedgers() = 0;
/**
* @brief getValidatedLedgerAge Returns age of last
* validated ledger. Method is specific for postgres backend.
* @return Age of last validated ledger in seconds
* @brief getValidatedLedgerAge Returns the age of the last validated
* ledger.
* @return Age of the last validated ledger in seconds
*/
virtual std::chrono::seconds
getValidatedLedgerAge() = 0;
/**
* @brief writeLedgerAndTransactions Write new ledger and transaction data
* into database. Method is specific for Postgres backend.
* @brief writeLedgerAndTransactions Writes new ledger and transaction data
* into the database.
* @param info Ledger info to write.
* @param accountTxData Transaction data to write
* @return True if success, false if failure.
* @return True on success, false on failure.
*/
virtual bool
writeLedgerAndTransactions(
@@ -73,32 +65,30 @@ public:
std::vector<AccountTransactionsData> const& accountTxData) = 0;
/**
* @brief getTxHashes Returns vector of tx hashes by given ledger
* sequence. Method is specific to postgres backend.
* @brief getTxHashes Returns a vector of the hashes of transactions
* belonging to the ledger with the provided sequence.
* @param seq Ledger sequence
* @return Vector of tx hashes
* @return Vector of transaction hashes
*/
virtual std::vector<uint256>
getTxHashes(LedgerIndex seq) = 0;
/**
* @brief getAccountTx Get last account transactions specifies by
* passed argumenrs structure. Function if specific to postgres
* backend.
* @param args Arguments which specify account and whose tx to return.
* @param app Application
* @param j Journal
* @return Vector of account transactions and RPC status of responce.
* @brief getAccountTx Get the last account transactions specified by the
* AccountTxArgs struct.
* @param args Arguments which specify the account and which transactions to
* return.
* @return Vector of account transactions and the RPC status response.
*/
virtual std::pair<AccountTxResult, RPC::Status>
getAccountTx(AccountTxArgs const& args) = 0;
/**
* @brief locateTransaction Returns information used to locate
* a transaction. Function is specific to postgres backend.
* a transaction.
* @param id Hash of the transaction.
* @return Information used to locate a transaction. Contains a nodestore
* hash and ledger sequence pair if the transaction was found.
* hash and a ledger sequence pair if the transaction was found.
* Otherwise, contains the range of ledgers present in the database
* at the time of search.
*/
@@ -110,9 +100,9 @@ public:
* network
* @param[out] reason if the database is not caught up, reason contains a
* helpful message describing why
* @return false if the most recently written
* ledger has a close time over 3 minutes ago, or if there are
* no ledgers in the database. true otherwise
* @return false if the most recently written ledger has a close time
* over 3 minutes ago, or if there are no ledgers in the
* database. true otherwise
*/
virtual bool
isCaughtUp(std::string& reason) = 0;

View File

@@ -1,298 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2020 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 <ripple/app/ledger/AcceptedLedger.h>
#include <ripple/app/ledger/LedgerMaster.h>
#include <ripple/app/ledger/LedgerToJson.h>
#include <ripple/app/ledger/TransactionMaster.h>
#include <ripple/app/main/Application.h>
#include <ripple/app/misc/Manifest.h>
#include <ripple/app/misc/impl/AccountTxPaging.h>
#include <ripple/app/rdb/RelationalDBInterface_nodes.h>
#include <ripple/app/rdb/RelationalDBInterface_postgres.h>
#include <ripple/app/rdb/backend/RelationalDBInterfacePostgres.h>
#include <ripple/basics/BasicConfig.h>
#include <ripple/basics/StringUtilities.h>
#include <ripple/core/DatabaseCon.h>
#include <ripple/core/Pg.h>
#include <ripple/core/SociDB.h>
#include <ripple/json/to_string.h>
#include <ripple/nodestore/DatabaseShard.h>
#include <boost/algorithm/string.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <soci/sqlite3/soci-sqlite3.h>
namespace ripple {
class RelationalDBInterfacePostgresImp : public RelationalDBInterfacePostgres
{
public:
RelationalDBInterfacePostgresImp(
Application& app,
Config const& config,
JobQueue& jobQueue)
: app_(app)
, j_(app_.journal("PgPool"))
, pgPool_(
#ifdef RIPPLED_REPORTING
make_PgPool(config.section("ledger_tx_tables"), j_)
#endif
)
{
assert(config.reporting());
#ifdef RIPPLED_REPORTING
if (config.reporting() && !config.reportingReadOnly()) // use pg
{
initSchema(pgPool_);
}
#endif
}
void
stop() override
{
#ifdef RIPPLED_REPORTING
pgPool_->stop();
#endif
}
void
sweep() override;
std::optional<LedgerIndex>
getMinLedgerSeq() override;
std::optional<LedgerIndex>
getMaxLedgerSeq() override;
std::string
getCompleteLedgers() override;
std::chrono::seconds
getValidatedLedgerAge() override;
bool
writeLedgerAndTransactions(
LedgerInfo const& info,
std::vector<AccountTransactionsData> const& accountTxData) override;
std::optional<LedgerInfo>
getLedgerInfoByIndex(LedgerIndex ledgerSeq) override;
std::optional<LedgerInfo>
getNewestLedgerInfo() override;
std::optional<LedgerInfo>
getLedgerInfoByHash(uint256 const& ledgerHash) override;
uint256
getHashByIndex(LedgerIndex ledgerIndex) override;
std::optional<LedgerHashPair>
getHashesByIndex(LedgerIndex ledgerIndex) override;
std::map<LedgerIndex, LedgerHashPair>
getHashesByIndex(LedgerIndex minSeq, LedgerIndex maxSeq) override;
std::vector<uint256>
getTxHashes(LedgerIndex seq) override;
std::vector<std::shared_ptr<Transaction>>
getTxHistory(LedgerIndex startIndex) override;
std::pair<AccountTxResult, RPC::Status>
getAccountTx(AccountTxArgs const& args) override;
Transaction::Locator
locateTransaction(uint256 const& id) override;
bool
ledgerDbHasSpace(Config const& config) override;
bool
transactionDbHasSpace(Config const& config) override;
bool
isCaughtUp(std::string& reason) override;
private:
Application& app_;
beast::Journal j_;
std::shared_ptr<PgPool> pgPool_;
bool
dbHasSpace(Config const& config);
};
void
RelationalDBInterfacePostgresImp::sweep()
{
#ifdef RIPPLED_REPORTING
pgPool_->idleSweeper();
#endif
}
std::optional<LedgerIndex>
RelationalDBInterfacePostgresImp::getMinLedgerSeq()
{
return ripple::getMinLedgerSeq(pgPool_, j_);
}
std::optional<LedgerIndex>
RelationalDBInterfacePostgresImp::getMaxLedgerSeq()
{
return ripple::getMaxLedgerSeq(pgPool_);
}
std::string
RelationalDBInterfacePostgresImp::getCompleteLedgers()
{
return ripple::getCompleteLedgers(pgPool_);
}
std::chrono::seconds
RelationalDBInterfacePostgresImp::getValidatedLedgerAge()
{
return ripple::getValidatedLedgerAge(pgPool_, j_);
}
bool
RelationalDBInterfacePostgresImp::writeLedgerAndTransactions(
LedgerInfo const& info,
std::vector<AccountTransactionsData> const& accountTxData)
{
return ripple::writeLedgerAndTransactions(pgPool_, info, accountTxData, j_);
}
std::optional<LedgerInfo>
RelationalDBInterfacePostgresImp::getLedgerInfoByIndex(LedgerIndex ledgerSeq)
{
return ripple::getLedgerInfoByIndex(pgPool_, ledgerSeq, app_);
}
std::optional<LedgerInfo>
RelationalDBInterfacePostgresImp::getNewestLedgerInfo()
{
return ripple::getNewestLedgerInfo(pgPool_, app_);
}
std::optional<LedgerInfo>
RelationalDBInterfacePostgresImp::getLedgerInfoByHash(uint256 const& ledgerHash)
{
return ripple::getLedgerInfoByHash(pgPool_, ledgerHash, app_);
}
uint256
RelationalDBInterfacePostgresImp::getHashByIndex(LedgerIndex ledgerIndex)
{
return ripple::getHashByIndex(pgPool_, ledgerIndex, app_);
}
std::optional<LedgerHashPair>
RelationalDBInterfacePostgresImp::getHashesByIndex(LedgerIndex ledgerIndex)
{
LedgerHashPair p;
if (!ripple::getHashesByIndex(
pgPool_, ledgerIndex, p.ledgerHash, p.parentHash, app_))
return {};
return p;
}
std::map<LedgerIndex, LedgerHashPair>
RelationalDBInterfacePostgresImp::getHashesByIndex(
LedgerIndex minSeq,
LedgerIndex maxSeq)
{
return ripple::getHashesByIndex(pgPool_, minSeq, maxSeq, app_);
}
std::vector<uint256>
RelationalDBInterfacePostgresImp::getTxHashes(LedgerIndex seq)
{
return ripple::getTxHashes(pgPool_, seq, app_);
}
std::vector<std::shared_ptr<Transaction>>
RelationalDBInterfacePostgresImp::getTxHistory(LedgerIndex startIndex)
{
return ripple::getTxHistory(pgPool_, startIndex, app_, j_);
}
std::pair<AccountTxResult, RPC::Status>
RelationalDBInterfacePostgresImp::getAccountTx(AccountTxArgs const& args)
{
return ripple::getAccountTx(pgPool_, args, app_, j_);
}
Transaction::Locator
RelationalDBInterfacePostgresImp::locateTransaction(uint256 const& id)
{
return ripple::locateTransaction(pgPool_, id, app_);
}
bool
RelationalDBInterfacePostgresImp::dbHasSpace(Config const& config)
{
/* Postgres server could be running on a different machine. */
return true;
}
bool
RelationalDBInterfacePostgresImp::ledgerDbHasSpace(Config const& config)
{
return dbHasSpace(config);
}
bool
RelationalDBInterfacePostgresImp::transactionDbHasSpace(Config const& config)
{
return dbHasSpace(config);
}
std::unique_ptr<RelationalDBInterface>
getRelationalDBInterfacePostgres(
Application& app,
Config const& config,
JobQueue& jobQueue)
{
return std::make_unique<RelationalDBInterfacePostgresImp>(
app, config, jobQueue);
}
bool
RelationalDBInterfacePostgresImp::isCaughtUp(std::string& reason)
{
#ifdef RIPPLED_REPORTING
using namespace std::chrono_literals;
auto age = PgQuery(pgPool_)("SELECT age()");
if (!age || age.isNull())
{
reason = "No ledgers in database";
return false;
}
if (std::chrono::seconds{age.asInt()} > 3min)
{
reason = "No recently-published ledger";
return false;
}
#endif
return true;
}
} // namespace ripple

View File

@@ -1,302 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2020 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_CORE_RELATIONALDBINTERFACESQLITE_H_INCLUDED
#define RIPPLE_CORE_RELATIONALDBINTERFACESQLITE_H_INCLUDED
#include <ripple/app/rdb/RelationalDBInterface.h>
namespace ripple {
class RelationalDBInterfaceSqlite : public RelationalDBInterface
{
public:
/**
* @brief getTransactionsMinLedgerSeq Returns minimum ledger sequence
* among records in the Transactions table.
* @return Ledger sequence or none if no ledgers exist.
*/
virtual std::optional<LedgerIndex>
getTransactionsMinLedgerSeq() = 0;
/**
* @brief getAccountTransactionsMinLedgerSeq Returns minimum ledger
* sequence among records in the AccountTransactions table.
* @return Ledger sequence or none if no ledgers exist.
*/
virtual std::optional<LedgerIndex>
getAccountTransactionsMinLedgerSeq() = 0;
/**
* @brief deleteTransactionByLedgerSeq Deletes transactions from ledger
* with given sequence.
* @param ledgerSeq Ledger sequence.
*/
virtual void
deleteTransactionByLedgerSeq(LedgerIndex ledgerSeq) = 0;
/**
* @brief deleteBeforeLedgerSeq Deletes all ledgers with given sequence
* and all sequences below it.
* @param ledgerSeq Ledger sequence.
*/
virtual void
deleteBeforeLedgerSeq(LedgerIndex ledgerSeq) = 0;
/**
* @brief deleteTransactionsBeforeLedgerSeq Deletes all transactions with
* given ledger sequence and all sequences below it.
* @param ledgerSeq Ledger sequence.
*/
virtual void
deleteTransactionsBeforeLedgerSeq(LedgerIndex ledgerSeq) = 0;
/**
* @brief deleteAccountTransactionsBeforeLedgerSeq Deletes all account
* transactions with given ledger sequence and all sequences
* below it.
* @param ledgerSeq Ledger sequence.
*/
virtual void
deleteAccountTransactionsBeforeLedgerSeq(LedgerIndex ledgerSeq) = 0;
/**
* @brief getTransactionCount Returns number of transactions.
* @return Number of transactions.
*/
virtual std::size_t
getTransactionCount() = 0;
/**
* @brief getAccountTransactionCount Returns number of account
* transactions.
* @return Number of account transactions.
*/
virtual std::size_t
getAccountTransactionCount() = 0;
/**
* @brief getLedgerCountMinMax Returns minumum ledger sequence,
* maximum ledger sequence and total number of saved ledgers.
* @return Struct CountMinMax which contain minimum sequence,
* maximum sequence and number of ledgers.
*/
virtual struct CountMinMax
getLedgerCountMinMax() = 0;
/**
* @brief saveValidatedLedger Saves ledger into database.
* @param ledger The ledger.
* @param current True if ledger is current.
* @return True is saving was successfull.
*/
virtual bool
saveValidatedLedger(
std::shared_ptr<Ledger const> const& ledger,
bool current) = 0;
/**
* @brief getLimitedOldestLedgerInfo Returns info of oldest ledger
* from ledgers with sequences greater or equal to given.
* @param ledgerFirstIndex Minimum ledger sequence.
* @return Ledger info or none if ledger not found.
*/
virtual std::optional<LedgerInfo>
getLimitedOldestLedgerInfo(LedgerIndex ledgerFirstIndex) = 0;
/**
* @brief getLimitedNewestLedgerInfo Returns info of newest ledger
* from ledgers with sequences greater or equal to given.
* @param ledgerFirstIndex Minimum ledger sequence.
* @return Ledger info or none if ledger not found.
*/
virtual std::optional<LedgerInfo>
getLimitedNewestLedgerInfo(LedgerIndex ledgerFirstIndex) = 0;
/**
* @brief getOldestAccountTxs Returns oldest transactions for given
* account which match given criteria starting from given offset.
* @param options Struct AccountTxOptions which contain criteria to match:
* the account, minimum and maximum ledger numbers to search,
* offset of first entry to return, number of transactions to return,
* flag if this number unlimited.
* @return Vector of pairs of found transactions and their metadata
* sorted in ascending order by account sequence.
*/
virtual AccountTxs
getOldestAccountTxs(AccountTxOptions const& options) = 0;
/**
* @brief getNewestAccountTxs Returns newest transactions for given
* account which match given criteria starting from given offset.
* @param options Struct AccountTxOptions which contain criteria to match:
* the account, minimum and maximum ledger numbers to search,
* offset of first entry to return, number of transactions to return,
* flag if this number unlimited.
* @return Vector of pairs of found transactions and their metadata
* sorted in descending order by account sequence.
*/
virtual AccountTxs
getNewestAccountTxs(AccountTxOptions const& options) = 0;
/**
* @brief getOldestAccountTxsB Returns oldest transactions in binary form
* for given account which match given criteria starting from given
* offset.
* @param options Struct AccountTxOptions which contain criteria to match:
* the account, minimum and maximum ledger numbers to search,
* offset of first entry to return, number of transactions to return,
* flag if this number unlimited.
* @return Vector of tuples of found transactions, their metadata and
* account sequences sorted in ascending order by account sequence.
*/
virtual MetaTxsList
getOldestAccountTxsB(AccountTxOptions const& options) = 0;
/**
* @brief getNewestAccountTxsB Returns newest transactions in binary form
* for given account which match given criteria starting from given
* offset.
* @param options Struct AccountTxOptions which contain criteria to match:
* the account, minimum and maximum ledger numbers to search,
* offset of first entry to return, number of transactions to return,
* flag if this number unlimited.
* @return Vector of tuples of found transactions, their metadata and
* account sequences sorted in descending order by account
* sequence.
*/
virtual MetaTxsList
getNewestAccountTxsB(AccountTxOptions const& options) = 0;
/**
* @brief oldestAccountTxPage Returns oldest transactions for given
* account which match given criteria starting from given marker.
* @param options Struct AccountTxPageOptions which contain criteria to
* match: the account, minimum and maximum ledger numbers to search,
* marker of first returned entry, number of transactions to return,
* flag if this number unlimited.
* @return Vector of pairs of found transactions and their metadata
* sorted in ascending order by account sequence and marker
* for next search if search not finished.
*/
virtual std::pair<AccountTxs, std::optional<AccountTxMarker>>
oldestAccountTxPage(AccountTxPageOptions const& options) = 0;
/**
* @brief newestAccountTxPage Returns newest transactions for given
* account which match given criteria starting from given marker.
* @param options Struct AccountTxPageOptions which contain criteria to
* match: the account, minimum and maximum ledger numbers to search,
* marker of first returned entry, number of transactions to return,
* flag if this number unlimited.
* @return Vector of pairs of found transactions and their metadata
* sorted in descending order by account sequence and marker
* for next search if search not finished.
*/
virtual std::pair<AccountTxs, std::optional<AccountTxMarker>>
newestAccountTxPage(AccountTxPageOptions const& options) = 0;
/**
* @brief oldestAccountTxPageB Returns oldest transactions in binary form
* for given account which match given criteria starting from given
* marker.
* @param options Struct AccountTxPageOptions which contain criteria to
* match: the account, minimum and maximum ledger numbers to search,
* marker of first returned entry, number of transactions to return,
* flag if this number unlimited.
* @return Vector of tuples of found transactions, their metadata and
* account sequences sorted in ascending order by account
* sequence and marker for next search if search not finished.
*/
virtual std::pair<MetaTxsList, std::optional<AccountTxMarker>>
oldestAccountTxPageB(AccountTxPageOptions const& options) = 0;
/**
* @brief newestAccountTxPageB Returns newest transactions in binary form
* for given account which match given criteria starting from given
* marker.
* @param options Struct AccountTxPageOptions which contain criteria to
* match: the account, minimum and maximum ledger numbers to search,
* marker of first returned entry, number of transactions to return,
* flag if this number unlimited.
* @return Vector of tuples of found transactions, their metadata and
* account sequences sorted in descending order by account
* sequence and marker for next search if search not finished.
*/
virtual std::pair<MetaTxsList, std::optional<AccountTxMarker>>
newestAccountTxPageB(AccountTxPageOptions const& options) = 0;
/**
* @brief getTransaction Returns transaction with given hash. If not found
* and range given then check if all ledgers from the range are
* present in the database.
* @param id Hash of the transaction.
* @param range Range of ledgers to check, if present.
* @param ec Default value of error code.
* @return Transaction and its metadata if found, TxSearched::all if range
* given and all ledgers from range are present in the database,
* TxSearched::some if range given and not all ledgers are present,
* TxSearched::unknown if range not given or deserializing error
* occured. In the last case error code returned via ec link
* parameter, in other cases default error code not changed.
*/
virtual std::variant<AccountTx, TxSearched>
getTransaction(
uint256 const& id,
std::optional<ClosedInterval<uint32_t>> const& range,
error_code_i& ec) = 0;
/**
* @brief getKBUsedAll Returns space used by all databases.
* @return Space in kilobytes.
*/
virtual uint32_t
getKBUsedAll() = 0;
/**
* @brief getKBUsedLedger Returns space used by ledger database.
* @return Space in kilobytes.
*/
virtual uint32_t
getKBUsedLedger() = 0;
/**
* @brief getKBUsedTransaction Returns space used by transaction
* database.
* @return Space in kilobytes.
*/
virtual uint32_t
getKBUsedTransaction() = 0;
/**
* @brief Closes the ledger database
*/
virtual void
closeLedgerDB() = 0;
/**
* @brief Closes the transaction database
*/
virtual void
closeTransactionDB() = 0;
};
} // namespace ripple
#endif

View File

@@ -0,0 +1,313 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2020 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_APP_RDB_BACKEND_SQLITEDATABASE_H_INCLUDED
#define RIPPLE_APP_RDB_BACKEND_SQLITEDATABASE_H_INCLUDED
#include <ripple/app/rdb/RelationalDatabase.h>
namespace ripple {
class SQLiteDatabase : public RelationalDatabase
{
public:
/**
* @brief getTransactionsMinLedgerSeq Returns the minimum ledger sequence
* stored in the Transactions table.
* @return Ledger sequence or no value if no ledgers exist.
*/
virtual std::optional<LedgerIndex>
getTransactionsMinLedgerSeq() = 0;
/**
* @brief getAccountTransactionsMinLedgerSeq Returns the minimum ledger
* sequence stored in the AccountTransactions table.
* @return Ledger sequence or no value if no ledgers exist.
*/
virtual std::optional<LedgerIndex>
getAccountTransactionsMinLedgerSeq() = 0;
/**
* @brief deleteTransactionByLedgerSeq Deletes transactions from the ledger
* with the given sequence.
* @param ledgerSeq Ledger sequence.
*/
virtual void
deleteTransactionByLedgerSeq(LedgerIndex ledgerSeq) = 0;
/**
* @brief deleteBeforeLedgerSeq Deletes all ledgers with a sequence number
* less than or equal to the given ledger sequence.
* @param ledgerSeq Ledger sequence.
*/
virtual void
deleteBeforeLedgerSeq(LedgerIndex ledgerSeq) = 0;
/**
* @brief deleteTransactionsBeforeLedgerSeq Deletes all transactions with
* a sequence number less than or equal to the given ledger
* sequence.
* @param ledgerSeq Ledger sequence.
*/
virtual void
deleteTransactionsBeforeLedgerSeq(LedgerIndex ledgerSeq) = 0;
/**
* @brief deleteAccountTransactionsBeforeLedgerSeq Deletes all account
* transactions with a sequence number less than or equal to the
* given ledger sequence.
* @param ledgerSeq Ledger sequence.
*/
virtual void
deleteAccountTransactionsBeforeLedgerSeq(LedgerIndex ledgerSeq) = 0;
/**
* @brief getTransactionCount Returns the number of transactions.
* @return Number of transactions.
*/
virtual std::size_t
getTransactionCount() = 0;
/**
* @brief getAccountTransactionCount Returns the number of account
* transactions.
* @return Number of account transactions.
*/
virtual std::size_t
getAccountTransactionCount() = 0;
/**
* @brief getLedgerCountMinMax Returns the minimum ledger sequence,
* maximum ledger sequence and total number of saved ledgers.
* @return Struct CountMinMax which contains the minimum sequence,
* maximum sequence and number of ledgers.
*/
virtual struct CountMinMax
getLedgerCountMinMax() = 0;
/**
* @brief saveValidatedLedger Saves a ledger into the database.
* @param ledger The ledger.
* @param current True if the ledger is current.
* @return True if saving was successful.
*/
virtual bool
saveValidatedLedger(
std::shared_ptr<Ledger const> const& ledger,
bool current) = 0;
/**
* @brief getLimitedOldestLedgerInfo Returns the info of the oldest ledger
* whose sequence number is greater than or equal to the given
* sequence number.
* @param ledgerFirstIndex Minimum ledger sequence.
* @return Ledger info if found, otherwise no value.
*/
virtual std::optional<LedgerInfo>
getLimitedOldestLedgerInfo(LedgerIndex ledgerFirstIndex) = 0;
/**
* @brief getLimitedNewestLedgerInfo Returns the info of the newest ledger
* whose sequence number is greater than or equal to the given
* sequence number.
* @param ledgerFirstIndex Minimum ledger sequence.
* @return Ledger info if found, otherwise no value.
*/
virtual std::optional<LedgerInfo>
getLimitedNewestLedgerInfo(LedgerIndex ledgerFirstIndex) = 0;
/**
* @brief getOldestAccountTxs Returns the oldest transactions for the
* account that matches the given criteria starting from the provided
* offset.
* @param options Struct AccountTxOptions which contains the criteria to
* match: the account, ledger search range, the offset of the first
* entry to return, the number of transactions to return, a flag if
* this number is unlimited.
* @return Vector of pairs of found transactions and their metadata
* sorted in ascending order by account sequence.
*/
virtual AccountTxs
getOldestAccountTxs(AccountTxOptions const& options) = 0;
/**
* @brief getNewestAccountTxs Returns the newest transactions for the
* account that matches the given criteria starting from the provided
* offset.
* @param options Struct AccountTxOptions which contains the criteria to
* match: the account, the ledger search range, the offset of the
* first entry to return, the number of transactions to return, a
* flag if this number unlimited.
* @return Vector of pairs of found transactions and their metadata
* sorted in descending order by account sequence.
*/
virtual AccountTxs
getNewestAccountTxs(AccountTxOptions const& options) = 0;
/**
* @brief getOldestAccountTxsB Returns the oldest transactions in binary
* form for the account that matches the given criteria starting from
* the provided offset.
* @param options Struct AccountTxOptions which contains the criteria to
* match: the account, the ledger search range, the offset of the
* first entry to return, the number of transactions to return, a
* flag if this number unlimited.
* @return Vector of tuples of found transactions, their metadata and
* account sequences sorted in ascending order by account sequence.
*/
virtual MetaTxsList
getOldestAccountTxsB(AccountTxOptions const& options) = 0;
/**
* @brief getNewestAccountTxsB Returns the newest transactions in binary
* form for the account that matches the given criteria starting from
* the provided offset.
* @param options Struct AccountTxOptions which contains the criteria to
* match: the account, the ledger search range, the offset of the
* first entry to return, the number of transactions to return, a
* flag if this number is unlimited.
* @return Vector of tuples of found transactions, their metadata and
* account sequences sorted in descending order by account
* sequence.
*/
virtual MetaTxsList
getNewestAccountTxsB(AccountTxOptions const& options) = 0;
/**
* @brief oldestAccountTxPage Returns the oldest transactions for the
* account that matches the given criteria starting from the
* provided marker.
* @param options Struct AccountTxPageOptions which contains the criteria to
* match: the account, the ledger search range, the marker of first
* returned entry, the number of transactions to return, a flag if
* this number is unlimited.
* @return Vector of pairs of found transactions and their metadata
* sorted in ascending order by account sequence and a marker
* for the next search if the search was not finished.
*/
virtual std::pair<AccountTxs, std::optional<AccountTxMarker>>
oldestAccountTxPage(AccountTxPageOptions const& options) = 0;
/**
* @brief newestAccountTxPage Returns the newest transactions for the
* account that matches the given criteria starting from the provided
* marker.
* @param options Struct AccountTxPageOptions which contains the criteria to
* match: the account, the ledger search range, the marker of the
* first returned entry, the number of transactions to return, a flag
* if this number unlimited.
* @return Vector of pairs of found transactions and their metadata
* sorted in descending order by account sequence and a marker
* for the next search if the search was not finished.
*/
virtual std::pair<AccountTxs, std::optional<AccountTxMarker>>
newestAccountTxPage(AccountTxPageOptions const& options) = 0;
/**
* @brief oldestAccountTxPageB Returns the oldest transactions in binary
* form for the account that matches the given criteria starting from
* the provided marker.
* @param options Struct AccountTxPageOptions which contains criteria to
* match: the account, the ledger search range, the marker of the
* first returned entry, the number of transactions to return, a flag
* if this number unlimited.
* @return Vector of tuples of found transactions, their metadata and
* account sequences sorted in ascending order by account
* sequence and a marker for the next search if the search was not
* finished.
*/
virtual std::pair<MetaTxsList, std::optional<AccountTxMarker>>
oldestAccountTxPageB(AccountTxPageOptions const& options) = 0;
/**
* @brief newestAccountTxPageB Returns the newest transactions in binary
* form for the account that matches the given criteria starting from
* the provided marker.
* @param options Struct AccountTxPageOptions which contains the criteria to
* match: the account, the ledger search range, the marker of the
* first returned entry, the number of transactions to return, a flag
* if this number is unlimited.
* @return Vector of tuples of found transactions, their metadata and
* account sequences sorted in descending order by account
* sequence and a marker for the next search if the search was not
* finished.
*/
virtual std::pair<MetaTxsList, std::optional<AccountTxMarker>>
newestAccountTxPageB(AccountTxPageOptions const& options) = 0;
/**
* @brief getTransaction Returns the transaction with the given hash. If a
* range is provided but the transaction is not found, then check if
* all ledgers in the range are present in the database.
* @param id Hash of the transaction.
* @param range Range of ledgers to check, if present.
* @param ec Default error code value.
* @return Transaction and its metadata if found, otherwise TxSearched::all
* if a range is provided and all ledgers from the range are present
* in the database, TxSearched::some if a range is provided and not
* all ledgers are present, TxSearched::unknown if the range is not
* provided or a deserializing error occurred. In the last case the
* error code is returned via the ec parameter, in other cases the
* default error code is not changed.
*/
virtual std::variant<AccountTx, TxSearched>
getTransaction(
uint256 const& id,
std::optional<ClosedInterval<uint32_t>> const& range,
error_code_i& ec) = 0;
/**
* @brief getKBUsedAll Returns the amount of space used by all databases.
* @return Space in kilobytes.
*/
virtual uint32_t
getKBUsedAll() = 0;
/**
* @brief getKBUsedLedger Returns the amount of space space used by the
* ledger database.
* @return Space in kilobytes.
*/
virtual uint32_t
getKBUsedLedger() = 0;
/**
* @brief getKBUsedTransaction Returns the amount of space used by the
* transaction database.
* @return Space in kilobytes.
*/
virtual uint32_t
getKBUsedTransaction() = 0;
/**
* @brief Closes the ledger database
*/
virtual void
closeLedgerDB() = 0;
/**
* @brief Closes the transaction database
*/
virtual void
closeTransactionDB() = 0;
};
} // namespace ripple
#endif

View File

@@ -17,18 +17,19 @@
*/
//==============================================================================
#ifndef RIPPLE_CORE_RELATIONALDBINTERFACE_NODES_H_INCLUDED
#define RIPPLE_CORE_RELATIONALDBINTERFACE_NODES_H_INCLUDED
#ifndef RIPPLE_APP_RDB_BACKEND_DETAIL_NODE_H_INCLUDED
#define RIPPLE_APP_RDB_BACKEND_DETAIL_NODE_H_INCLUDED
#include <ripple/app/ledger/Ledger.h>
#include <ripple/app/misc/Manifest.h>
#include <ripple/app/rdb/RelationalDBInterface.h>
#include <ripple/app/rdb/RelationalDatabase.h>
#include <ripple/core/Config.h>
#include <ripple/overlay/PeerReservationTable.h>
#include <ripple/peerfinder/impl/Store.h>
#include <boost/filesystem.hpp>
namespace ripple {
namespace detail {
/* Need to change TableTypeCount if TableType is modified. */
enum class TableType { Ledgers, Transactions, AccountTransactions };
@@ -116,7 +117,7 @@ getRows(soci::session& session, TableType type);
* @return Struct CountMinMax which contain minimum sequence,
* maximum sequence and number of rows.
*/
RelationalDBInterface::CountMinMax
RelationalDatabase::CountMinMax
getRowsMinMax(soci::session& session, TableType type);
/**
@@ -232,7 +233,7 @@ getHashesByIndex(
* @param maxSeq Maximum ledger sequence.
* @param j Journal.
* @return Map which points sequence number of found ledger to the struct
* LedgerHashPair which contauns ledger hash and its parent hash.
* LedgerHashPair which contains ledger hash and its parent hash.
*/
std::map<LedgerIndex, LedgerHashPair>
getHashesByIndex(
@@ -283,12 +284,12 @@ getTxHistory(
* skipped. We need to skip some quantity of transactions if option
* offset is > 0 in the options structure.
*/
std::pair<RelationalDBInterface::AccountTxs, int>
std::pair<RelationalDatabase::AccountTxs, int>
getOldestAccountTxs(
soci::session& session,
Application& app,
LedgerMaster& ledgerMaster,
RelationalDBInterface::AccountTxOptions const& options,
RelationalDatabase::AccountTxOptions const& options,
std::optional<int> const& limit_used,
beast::Journal j);
@@ -314,12 +315,12 @@ getOldestAccountTxs(
* skipped. We need to skip some quantity of transactions if option
* offset is > 0 in the options structure.
*/
std::pair<RelationalDBInterface::AccountTxs, int>
std::pair<RelationalDatabase::AccountTxs, int>
getNewestAccountTxs(
soci::session& session,
Application& app,
LedgerMaster& ledgerMaster,
RelationalDBInterface::AccountTxOptions const& options,
RelationalDatabase::AccountTxOptions const& options,
std::optional<int> const& limit_used,
beast::Journal j);
@@ -345,11 +346,11 @@ getNewestAccountTxs(
* skipped. We need to skip some quantity of transactions if option
* offset is > 0 in the options structure.
*/
std::pair<std::vector<RelationalDBInterface::txnMetaLedgerType>, int>
std::pair<std::vector<RelationalDatabase::txnMetaLedgerType>, int>
getOldestAccountTxsB(
soci::session& session,
Application& app,
RelationalDBInterface::AccountTxOptions const& options,
RelationalDatabase::AccountTxOptions const& options,
std::optional<int> const& limit_used,
beast::Journal j);
@@ -375,11 +376,11 @@ getOldestAccountTxsB(
* skipped. We need to skip some quantity of transactions if option
* offset is > 0 in the options structure.
*/
std::pair<std::vector<RelationalDBInterface::txnMetaLedgerType>, int>
std::pair<std::vector<RelationalDatabase::txnMetaLedgerType>, int>
getNewestAccountTxsB(
soci::session& session,
Application& app,
RelationalDBInterface::AccountTxOptions const& options,
RelationalDatabase::AccountTxOptions const& options,
std::optional<int> const& limit_used,
beast::Journal j);
@@ -404,7 +405,7 @@ getNewestAccountTxsB(
* sequence and marker for next search if search not finished.
* Also number of transactions processed during this call.
*/
std::pair<std::optional<RelationalDBInterface::AccountTxMarker>, int>
std::pair<std::optional<RelationalDatabase::AccountTxMarker>, int>
oldestAccountTxPage(
soci::session& session,
AccountIDCache const& idCache,
@@ -412,7 +413,7 @@ oldestAccountTxPage(
std::function<
void(std::uint32_t, std::string const&, Blob&&, Blob&&)> const&
onTransaction,
RelationalDBInterface::AccountTxPageOptions const& options,
RelationalDatabase::AccountTxPageOptions const& options,
int limit_used,
std::uint32_t page_length);
@@ -437,7 +438,7 @@ oldestAccountTxPage(
* sequence and marker for next search if search not finished.
* Also number of transactions processed during this call.
*/
std::pair<std::optional<RelationalDBInterface::AccountTxMarker>, int>
std::pair<std::optional<RelationalDatabase::AccountTxMarker>, int>
newestAccountTxPage(
soci::session& session,
AccountIDCache const& idCache,
@@ -445,7 +446,7 @@ newestAccountTxPage(
std::function<
void(std::uint32_t, std::string const&, Blob&&, Blob&&)> const&
onTransaction,
RelationalDBInterface::AccountTxPageOptions const& options,
RelationalDatabase::AccountTxPageOptions const& options,
int limit_used,
std::uint32_t page_length);
@@ -465,7 +466,7 @@ newestAccountTxPage(
* occured. In the last case error code modified in ec link
* parameter, in other cases default error code remained.
*/
std::variant<RelationalDBInterface::AccountTx, TxSearched>
std::variant<RelationalDatabase::AccountTx, TxSearched>
getTransaction(
soci::session& session,
Application& app,
@@ -483,6 +484,7 @@ getTransaction(
bool
dbHasSpace(soci::session& session, Config const& config, beast::Journal j);
} // namespace detail
} // namespace ripple
#endif

View File

@@ -0,0 +1,90 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2020 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_APP_RDB_BACKEND_DETAIL_SHARD_H_INCLUDED
#define RIPPLE_APP_RDB_BACKEND_DETAIL_SHARD_H_INCLUDED
#include <ripple/app/ledger/Ledger.h>
#include <ripple/app/rdb/RelationalDatabase.h>
#include <ripple/app/rdb/UnitaryShard.h>
#include <ripple/core/Config.h>
#include <ripple/protocol/RippleLedgerHash.h>
#include <boost/filesystem.hpp>
namespace ripple {
namespace detail {
/**
* @brief makeMetaDBs Opens ledger and transaction 'meta' databases which
* map ledger hashes and transaction IDs to the index of the shard
* that holds the ledger or transaction.
* @param config Config object.
* @param setup Path to database and opening parameters.
* @param checkpointerSetup Database checkpointer setup.
* @return Struct DatabasePair which contains unique pointers to the ledger
* and transaction databases.
*/
DatabasePair
makeMetaDBs(
Config const& config,
DatabaseCon::Setup const& setup,
DatabaseCon::CheckpointerSetup const& checkpointerSetup);
/**
* @brief saveLedgerMeta Stores (transaction ID -> shard index) and
* (ledger hash -> shard index) mappings in the meta databases.
* @param ledger The ledger.
* @param app Application object.
* @param lgrMetaSession Session to ledger meta database.
* @param txnMetaSession Session to transaction meta database.
* @param shardIndex The index of the shard that contains this ledger.
* @return True on success.
*/
bool
saveLedgerMeta(
std::shared_ptr<Ledger const> const& ledger,
Application& app,
soci::session& lgrMetaSession,
soci::session& txnMetaSession,
std::uint32_t shardIndex);
/**
* @brief getShardIndexforLedger Queries the ledger meta database to
* retrieve the index of the shard that contains this ledger.
* @param session Session to the database.
* @param hash Hash of the ledger.
* @return The index of the shard on success, otherwise an unseated value.
*/
std::optional<std::uint32_t>
getShardIndexforLedger(soci::session& session, LedgerHash const& hash);
/**
* @brief getShardIndexforTransaction Queries the transaction meta database to
* retrieve the index of the shard that contains this transaction.
* @param session Session to the database.
* @param id ID of the transaction.
* @return The index of the shard on success, otherwise an unseated value.
*/
std::optional<std::uint32_t>
getShardIndexforTransaction(soci::session& session, TxID const& id);
} // namespace detail
} // namespace ripple
#endif

View File

@@ -23,8 +23,8 @@
#include <ripple/app/ledger/PendingSaves.h>
#include <ripple/app/ledger/TransactionMaster.h>
#include <ripple/app/misc/Manifest.h>
#include <ripple/app/rdb/RelationalDBInterface.h>
#include <ripple/app/rdb/RelationalDBInterface_nodes.h>
#include <ripple/app/rdb/RelationalDatabase.h>
#include <ripple/app/rdb/backend/detail/Node.h>
#include <ripple/basics/BasicConfig.h>
#include <ripple/basics/StringUtilities.h>
#include <ripple/core/DatabaseCon.h>
@@ -35,10 +35,11 @@
#include <soci/sqlite3/soci-sqlite3.h>
namespace ripple {
namespace detail {
/**
* @brief to_string Returns name of table by table ID.
* @param type Table ID.
* @brief to_string Returns the name of a table according to its TableType.
* @param type An enum denoting the table's type.
* @return Name of the table.
*/
static std::string
@@ -47,6 +48,7 @@ to_string(TableType type)
static_assert(
TableTypeCount == 3,
"Need to modify switch statement if enum is modified");
switch (type)
{
case TableType::Ledgers:
@@ -56,7 +58,7 @@ to_string(TableType type)
case TableType::AccountTransactions:
return "AccountTransactions";
default:
assert(0);
assert(false);
return "Unknown";
}
}
@@ -166,10 +168,10 @@ getRows(soci::session& session, TableType type)
return rows;
}
RelationalDBInterface::CountMinMax
RelationalDatabase::CountMinMax
getRowsMinMax(soci::session& session, TableType type)
{
RelationalDBInterface::CountMinMax res;
RelationalDatabase::CountMinMax res;
session << "SELECT COUNT(*) AS rows, "
"MIN(LedgerSeq) AS first, "
"MAX(LedgerSeq) AS last "
@@ -378,12 +380,12 @@ saveValidatedLedger(
}
/**
* @brief getLedgerInfo Returns info of ledger with special condition
* given as SQL query.
* @param session Session with database.
* @param sqlSuffix Special condition for found the ledger.
* @brief getLedgerInfo Returns the info of the ledger retrieved from the
* database by using the provided SQL query suffix.
* @param session Session with the database.
* @param sqlSuffix SQL string used to specify the sought ledger.
* @param j Journal.
* @return Ledger info or none if ledger not found.
* @return Ledger info or no value if the ledger was not found.
*/
static std::optional<LedgerInfo>
getLedgerInfo(
@@ -674,21 +676,22 @@ getTxHistory(
}
/**
* @brief transactionsSQL Returns SQL query to select oldest or newest
* transactions in decoded or binary form for given account which
* match given criteria starting from given offset.
* @brief transactionsSQL Returns a SQL query for selecting the oldest or newest
* transactions in decoded or binary form for the account that matches
* the given criteria starting from the provided offset.
* @param app Application object.
* @param selection List of table fields to select from database.
* @param options Struct AccountTxOptions which contain criteria to match:
* the account, minimum and maximum ledger numbers to search,
* offset of first entry to return, number of transactions to return,
* flag if this number unlimited.
* @param selection List of table fields to select from the database.
* @param options Struct AccountTxOptions which contains the criteria to match:
* the account, the ledger search range, the offset of the first entry to
* return, the number of transactions to return, and a flag if this
* number is unlimited.
* @param limit_used Number of transactions already returned in calls
* to another shard databases, if shard databases are used.
* None if node database is used.
* to other shard databases, if shard databases are used.
* No value if the node database is used.
* @param descending True for descending order, false for ascending.
* @param binary True for binary form, false for decoded.
* @param count True for count number of transaction, false for select it.
* @param count True for counting the number of transactions, false for
* selecting them.
* @param j Journal.
* @return SQL query string.
*/
@@ -696,7 +699,7 @@ static std::string
transactionsSQL(
Application& app,
std::string selection,
RelationalDBInterface::AccountTxOptions const& options,
RelationalDatabase::AccountTxOptions const& options,
std::optional<int> const& limit_used,
bool descending,
bool binary,
@@ -781,39 +784,40 @@ transactionsSQL(
}
/**
* @brief getAccountTxs Returns oldest or newest transactions for given
* account which match given criteria starting from given offset.
* @param session Session with database.
* @brief getAccountTxs Returns the oldest or newest transactions for the
* account that matches the given criteria starting from the provided
* offset.
* @param session Session with the database.
* @param app Application object.
* @param ledgerMaster LedgerMaster object.
* @param options Struct AccountTxOptions which contain criteria to match:
* the account, minimum and maximum ledger numbers to search,
* offset of first entry to return, number of transactions to return,
* flag if this number unlimited.
* @param options Struct AccountTxOptions which contains the criteria to match:
* the account, the ledger search range, the offset of the first entry to
* return, the number of transactions to return, and a flag if this
* number is unlimited.
* @param limit_used Number of transactions already returned in calls
* to another shard databases, if shard databases are used.
* None if node database is used.
* to other shard databases, if shard databases are used.
* No value if the node database is used.
* @param descending True for descending order, false for ascending.
* @param j Journal.
* @return Vector of pairs of found transactions and its metadata
* sorted in given order by account sequence.
* Also the number of transactions processed or skipped.
* If this number is >= 0, then it means number of transactions
* processed, if it is < 0, then -number means number of transactions
* skipped. We need to skip some quantity of transactions if option
* offset is > 0 in the options structure.
* @return Vector of pairs of found transactions and their metadata sorted by
* account sequence in the specified order along with the number of
* transactions processed or skipped. If this number is >= 0, then it
* represents the number of transactions processed, if it is < 0, then
* -number represents the number of transactions skipped. We need to
* skip some number of transactions if option offset is > 0 in the
* options structure.
*/
static std::pair<RelationalDBInterface::AccountTxs, int>
static std::pair<RelationalDatabase::AccountTxs, int>
getAccountTxs(
soci::session& session,
Application& app,
LedgerMaster& ledgerMaster,
RelationalDBInterface::AccountTxOptions const& options,
RelationalDatabase::AccountTxOptions const& options,
std::optional<int> const& limit_used,
bool descending,
beast::Journal j)
{
RelationalDBInterface::AccountTxs ret;
RelationalDatabase::AccountTxs ret;
std::string sql = transactionsSQL(
app,
@@ -883,7 +887,7 @@ getAccountTxs(
if (!total && limit_used)
{
RelationalDBInterface::AccountTxOptions opt = options;
RelationalDatabase::AccountTxOptions opt = options;
opt.offset = 0;
std::string sql1 = transactionsSQL(
app, "COUNT(*)", opt, limit_used, descending, false, false, j);
@@ -897,12 +901,12 @@ getAccountTxs(
return {ret, total};
}
std::pair<RelationalDBInterface::AccountTxs, int>
std::pair<RelationalDatabase::AccountTxs, int>
getOldestAccountTxs(
soci::session& session,
Application& app,
LedgerMaster& ledgerMaster,
RelationalDBInterface::AccountTxOptions const& options,
RelationalDatabase::AccountTxOptions const& options,
std::optional<int> const& limit_used,
beast::Journal j)
{
@@ -910,12 +914,12 @@ getOldestAccountTxs(
session, app, ledgerMaster, options, limit_used, false, j);
}
std::pair<RelationalDBInterface::AccountTxs, int>
std::pair<RelationalDatabase::AccountTxs, int>
getNewestAccountTxs(
soci::session& session,
Application& app,
LedgerMaster& ledgerMaster,
RelationalDBInterface::AccountTxOptions const& options,
RelationalDatabase::AccountTxOptions const& options,
std::optional<int> const& limit_used,
beast::Journal j)
{
@@ -924,38 +928,38 @@ getNewestAccountTxs(
}
/**
* @brief getAccountTxsB Returns oldest or newset transactions in binary
* form for given account which match given criteria starting from
* given offset.
* @param session Session with database.
* @brief getAccountTxsB Returns the oldest or newest transactions in binary
* form for the account that matches given criteria starting from
* the provided offset.
* @param session Session with the database.
* @param app Application object.
* @param options Struct AccountTxOptions which contain criteria to match:
* the account, minimum and maximum ledger numbers to search,
* offset of first entry to return, number of transactions to return,
* flag if this number unlimited.
* @param limit_used Number or transactions already returned in calls
* to another shard databases, if shard databases are used.
* None if node database is used.
* @param options Struct AccountTxOptions which contains the criteria to match:
* the account, the ledger search range, the offset of the first entry to
* return, the number of transactions to return, and a flag if this
* number is unlimited.
* @param limit_used Number of transactions already returned in calls to other
* shard databases, if shard databases are used. No value if the node
* database is used.
* @param descending True for descending order, false for ascending.
* @param j Journal.
* @return Vector of tuples of found transactions, its metadata and
* account sequences sorted in given order by account
* sequence. Also number of transactions processed or skipped.
* If this number is >= 0, then it means number of transactions
* processed, if it is < 0, then -number means number of transactions
* skipped. We need to skip some quantity of transactions if option
* offset is > 0 in the options structure.
* @return Vector of tuples each containing (the found transactions, their
* metadata, and their account sequences) sorted by account sequence in
* the specified order along with the number of transactions processed
* or skipped. If this number is >= 0, then it represents the number of
* transactions processed, if it is < 0, then -number represents the
* number of transactions skipped. We need to skip some number of
* transactions if option offset is > 0 in the options structure.
*/
static std::pair<std::vector<RelationalDBInterface::txnMetaLedgerType>, int>
static std::pair<std::vector<RelationalDatabase::txnMetaLedgerType>, int>
getAccountTxsB(
soci::session& session,
Application& app,
RelationalDBInterface::AccountTxOptions const& options,
RelationalDatabase::AccountTxOptions const& options,
std::optional<int> const& limit_used,
bool descending,
beast::Journal j)
{
std::vector<RelationalDBInterface::txnMetaLedgerType> ret;
std::vector<RelationalDatabase::txnMetaLedgerType> ret;
std::string sql = transactionsSQL(
app,
@@ -1004,7 +1008,7 @@ getAccountTxsB(
if (!total && limit_used)
{
RelationalDBInterface::AccountTxOptions opt = options;
RelationalDatabase::AccountTxOptions opt = options;
opt.offset = 0;
std::string sql1 = transactionsSQL(
app, "COUNT(*)", opt, limit_used, descending, true, false, j);
@@ -1018,22 +1022,22 @@ getAccountTxsB(
return {ret, total};
}
std::pair<std::vector<RelationalDBInterface::txnMetaLedgerType>, int>
std::pair<std::vector<RelationalDatabase::txnMetaLedgerType>, int>
getOldestAccountTxsB(
soci::session& session,
Application& app,
RelationalDBInterface::AccountTxOptions const& options,
RelationalDatabase::AccountTxOptions const& options,
std::optional<int> const& limit_used,
beast::Journal j)
{
return getAccountTxsB(session, app, options, limit_used, false, j);
}
std::pair<std::vector<RelationalDBInterface::txnMetaLedgerType>, int>
std::pair<std::vector<RelationalDatabase::txnMetaLedgerType>, int>
getNewestAccountTxsB(
soci::session& session,
Application& app,
RelationalDBInterface::AccountTxOptions const& options,
RelationalDatabase::AccountTxOptions const& options,
std::optional<int> const& limit_used,
beast::Journal j)
{
@@ -1041,28 +1045,28 @@ getNewestAccountTxsB(
}
/**
* @brief accountTxPage Searches oldest or newest transactions for given
* account which match given criteria starting from given marker
* and calls callback for each found transaction.
* @param session Session with database.
* @brief accountTxPage Searches for the oldest or newest transactions for the
* account that matches the given criteria starting from the provided
* marker and invokes the callback parameter for each found transaction.
* @param session Session with the database.
* @param idCache Account ID cache.
* @param onUnsavedLedger Callback function to call on each found unsaved
* ledger within given range.
* @param onTransaction Callback function to call on eahc found transaction.
* @param options Struct AccountTxPageOptions which contain criteria to
* match: the account, minimum and maximum ledger numbers to search,
* marker of first returned entry, number of transactions to return,
* flag if this number unlimited.
* @param limit_used Number or transactions already returned in calls
* to another shard databases.
* ledger within the given range.
* @param onTransaction Callback function to call on each found transaction.
* @param options Struct AccountTxPageOptions which contains the criteria to
* match: the account, the ledger search range, the marker of the first
* returned entry, the number of transactions to return, and a flag if
* this number unlimited.
* @param limit_used Number of transactions already returned in calls
* to other shard databases.
* @param page_length Total number of transactions to return.
* @param forward True for ascending order, false for descending.
* @return Vector of tuples of found transactions, its metadata and
* account sequences sorted in given order by account
* sequence and marker for next search if search not finished.
* Also number of transactions processed during this call.
* @return Vector of tuples of found transactions, their metadata and account
* sequences sorted in the specified order by account sequence, a marker
* for the next search if the search was not finished and the number of
* transactions processed during this call.
*/
static std::pair<std::optional<RelationalDBInterface::AccountTxMarker>, int>
static std::pair<std::optional<RelationalDatabase::AccountTxMarker>, int>
accountTxPage(
soci::session& session,
AccountIDCache const& idCache,
@@ -1070,7 +1074,7 @@ accountTxPage(
std::function<
void(std::uint32_t, std::string const&, Blob&&, Blob&&)> const&
onTransaction,
RelationalDBInterface::AccountTxPageOptions const& options,
RelationalDatabase::AccountTxPageOptions const& options,
int limit_used,
std::uint32_t page_length,
bool forward)
@@ -1105,7 +1109,7 @@ accountTxPage(
findSeq = options.marker->txnSeq;
}
std::optional<RelationalDBInterface::AccountTxMarker> newmarker;
std::optional<RelationalDatabase::AccountTxMarker> newmarker;
if (limit_used > 0)
newmarker = options.marker;
@@ -1243,7 +1247,7 @@ accountTxPage(
return {newmarker, total};
}
std::pair<std::optional<RelationalDBInterface::AccountTxMarker>, int>
std::pair<std::optional<RelationalDatabase::AccountTxMarker>, int>
oldestAccountTxPage(
soci::session& session,
AccountIDCache const& idCache,
@@ -1251,7 +1255,7 @@ oldestAccountTxPage(
std::function<
void(std::uint32_t, std::string const&, Blob&&, Blob&&)> const&
onTransaction,
RelationalDBInterface::AccountTxPageOptions const& options,
RelationalDatabase::AccountTxPageOptions const& options,
int limit_used,
std::uint32_t page_length)
{
@@ -1266,7 +1270,7 @@ oldestAccountTxPage(
true);
}
std::pair<std::optional<RelationalDBInterface::AccountTxMarker>, int>
std::pair<std::optional<RelationalDatabase::AccountTxMarker>, int>
newestAccountTxPage(
soci::session& session,
AccountIDCache const& idCache,
@@ -1274,7 +1278,7 @@ newestAccountTxPage(
std::function<
void(std::uint32_t, std::string const&, Blob&&, Blob&&)> const&
onTransaction,
RelationalDBInterface::AccountTxPageOptions const& options,
RelationalDatabase::AccountTxPageOptions const& options,
int limit_used,
std::uint32_t page_length)
{
@@ -1289,7 +1293,7 @@ newestAccountTxPage(
false);
}
std::variant<RelationalDBInterface::AccountTx, TxSearched>
std::variant<RelationalDatabase::AccountTx, TxSearched>
getTransaction(
soci::session& session,
Application& app,
@@ -1435,4 +1439,5 @@ dbHasSpace(soci::session& session, Config const& config, beast::Journal j)
return true;
}
} // namespace detail
} // namespace ripple

View File

@@ -0,0 +1,147 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2020 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 <ripple/app/ledger/AcceptedLedger.h>
#include <ripple/app/ledger/LedgerMaster.h>
#include <ripple/app/rdb/backend/detail/Shard.h>
#include <ripple/basics/StringUtilities.h>
#include <ripple/core/DatabaseCon.h>
#include <ripple/core/SociDB.h>
#include <ripple/json/to_string.h>
namespace ripple {
namespace detail {
DatabasePair
makeMetaDBs(
Config const& config,
DatabaseCon::Setup const& setup,
DatabaseCon::CheckpointerSetup const& checkpointerSetup)
{
// ledger meta database
auto lgrMetaDB{std::make_unique<DatabaseCon>(
setup,
LgrMetaDBName,
LgrMetaDBPragma,
LgrMetaDBInit,
checkpointerSetup)};
if (!config.useTxTables())
return {std::move(lgrMetaDB), nullptr};
// transaction meta database
auto txMetaDB{std::make_unique<DatabaseCon>(
setup, TxMetaDBName, TxMetaDBPragma, TxMetaDBInit, checkpointerSetup)};
return {std::move(lgrMetaDB), std::move(txMetaDB)};
}
bool
saveLedgerMeta(
std::shared_ptr<Ledger const> const& ledger,
Application& app,
soci::session& lgrMetaSession,
soci::session& txnMetaSession,
std::uint32_t const shardIndex)
{
std::string_view constexpr lgrSQL =
R"sql(INSERT OR REPLACE INTO LedgerMeta VALUES
(:ledgerHash,:shardIndex);)sql";
auto const hash = to_string(ledger->info().hash);
lgrMetaSession << lgrSQL, soci::use(hash), soci::use(shardIndex);
if (!app.config().useTxTables())
return true;
auto const aLedger = [&app, ledger]() -> std::shared_ptr<AcceptedLedger> {
try
{
auto aLedger =
app.getAcceptedLedgerCache().fetch(ledger->info().hash);
if (!aLedger)
{
aLedger = std::make_shared<AcceptedLedger>(ledger, app);
app.getAcceptedLedgerCache().canonicalize_replace_client(
ledger->info().hash, aLedger);
}
return aLedger;
}
catch (std::exception const&)
{
JLOG(app.journal("Ledger").warn())
<< "An accepted ledger was missing nodes";
}
return {};
}();
if (!aLedger)
return false;
soci::transaction tr(txnMetaSession);
for (auto const& acceptedLedgerTx : *aLedger)
{
std::string_view constexpr txnSQL =
R"sql(INSERT OR REPLACE INTO TransactionMeta VALUES
(:transactionID,:shardIndex);)sql";
auto const transactionID =
to_string(acceptedLedgerTx->getTransactionID());
txnMetaSession << txnSQL, soci::use(transactionID),
soci::use(shardIndex);
}
tr.commit();
return true;
}
std::optional<std::uint32_t>
getShardIndexforLedger(soci::session& session, LedgerHash const& hash)
{
std::uint32_t shardIndex;
session << "SELECT ShardIndex FROM LedgerMeta WHERE LedgerHash = '" << hash
<< "';",
soci::into(shardIndex);
if (!session.got_data())
return std::nullopt;
return shardIndex;
}
std::optional<std::uint32_t>
getShardIndexforTransaction(soci::session& session, TxID const& id)
{
std::uint32_t shardIndex;
session << "SELECT ShardIndex FROM TransactionMeta WHERE TransID = '" << id
<< "';",
soci::into(shardIndex);
if (!session.got_data())
return std::nullopt;
return shardIndex;
}
} // namespace detail
} // namespace ripple

View File

@@ -0,0 +1,152 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2021 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 <ripple/app/rdb/Download.h>
#include <soci/sqlite3/soci-sqlite3.h>
namespace ripple {
std::pair<std::unique_ptr<DatabaseCon>, std::optional<std::uint64_t>>
openDatabaseBodyDb(
DatabaseCon::Setup const& setup,
boost::filesystem::path const& path)
{
// SOCI requires boost::optional (not std::optional) as the parameter.
boost::optional<std::string> pathFromDb;
boost::optional<std::uint64_t> size;
auto conn = std::make_unique<DatabaseCon>(
setup, "Download", DownloaderDBPragma, DatabaseBodyDBInit);
auto& session = *conn->checkoutDb();
session << "SELECT Path FROM Download WHERE Part=0;",
soci::into(pathFromDb);
// Try to reuse preexisting
// database.
if (pathFromDb)
{
// Can't resuse - database was
// from a different file download.
if (pathFromDb != path.string())
{
session << "DROP TABLE Download;";
}
// Continuing a file download.
else
{
session << "SELECT SUM(LENGTH(Data)) FROM Download;",
soci::into(size);
}
}
return {std::move(conn), (size ? *size : std::optional<std::uint64_t>())};
}
std::uint64_t
databaseBodyDoPut(
soci::session& session,
std::string const& data,
std::string const& path,
std::uint64_t fileSize,
std::uint64_t part,
std::uint16_t maxRowSizePad)
{
std::uint64_t rowSize = 0;
soci::indicator rti;
std::uint64_t remainingInRow = 0;
auto be =
dynamic_cast<soci::sqlite3_session_backend*>(session.get_backend());
BOOST_ASSERT(be);
// This limits how large we can make the blob
// in each row. Also subtract a pad value to
// account for the other values in the row.
auto const blobMaxSize =
sqlite_api::sqlite3_limit(be->conn_, SQLITE_LIMIT_LENGTH, -1) -
maxRowSizePad;
std::string newpath;
auto rowInit = [&] {
session << "INSERT INTO Download VALUES (:path, zeroblob(0), 0, :part)",
soci::use(newpath), soci::use(part);
remainingInRow = blobMaxSize;
rowSize = 0;
};
session << "SELECT Path,Size,Part FROM Download ORDER BY Part DESC "
"LIMIT 1",
soci::into(newpath), soci::into(rowSize), soci::into(part, rti);
if (!session.got_data())
{
newpath = path;
rowInit();
}
else
remainingInRow = blobMaxSize - rowSize;
auto insert = [&session, &rowSize, &part, &fs = fileSize](
auto const& data) {
std::uint64_t updatedSize = rowSize + data.size();
session << "UPDATE Download SET Data = CAST(Data || :data AS blob), "
"Size = :size WHERE Part = :part;",
soci::use(data), soci::use(updatedSize), soci::use(part);
fs += data.size();
};
size_t currentBase = 0;
while (currentBase + remainingInRow < data.size())
{
if (remainingInRow)
{
insert(data.substr(currentBase, remainingInRow));
currentBase += remainingInRow;
}
++part;
rowInit();
}
insert(data.substr(currentBase));
return part;
}
void
databaseBodyFinish(soci::session& session, std::ofstream& fout)
{
soci::rowset<std::string> rs =
(session.prepare << "SELECT Data FROM Download ORDER BY PART ASC;");
// iteration through the resultset:
for (auto it = rs.begin(); it != rs.end(); ++it)
fout.write(it->data(), it->size());
}
} // namespace ripple

View File

@@ -0,0 +1,271 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2021 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 <ripple/app/rdb/PeerFinder.h>
namespace ripple {
void
initPeerFinderDB(
soci::session& session,
BasicConfig const& config,
beast::Journal j)
{
DBConfig m_sociConfig(config, "peerfinder");
m_sociConfig.open(session);
JLOG(j.info()) << "Opening database at '" << m_sociConfig.connectionString()
<< "'";
soci::transaction tr(session);
session << "PRAGMA encoding=\"UTF-8\";";
session << "CREATE TABLE IF NOT EXISTS SchemaVersion ( "
" name TEXT PRIMARY KEY, "
" version INTEGER"
");";
session << "CREATE TABLE IF NOT EXISTS PeerFinder_BootstrapCache ( "
" id INTEGER PRIMARY KEY AUTOINCREMENT, "
" address TEXT UNIQUE NOT NULL, "
" valence INTEGER"
");";
session << "CREATE INDEX IF NOT EXISTS "
" PeerFinder_BootstrapCache_Index ON "
"PeerFinder_BootstrapCache "
" ( "
" address "
" ); ";
tr.commit();
}
void
updatePeerFinderDB(
soci::session& session,
int currentSchemaVersion,
beast::Journal j)
{
soci::transaction tr(session);
// get version
int version(0);
{
// SOCI requires a boost::optional (not std::optional) parameter.
boost::optional<int> vO;
session << "SELECT "
" version "
"FROM SchemaVersion WHERE "
" name = 'PeerFinder';",
soci::into(vO);
version = vO.value_or(0);
JLOG(j.info()) << "Opened version " << version << " database";
}
{
if (version < currentSchemaVersion)
{
JLOG(j.info()) << "Updating database to version "
<< currentSchemaVersion;
}
else if (version > currentSchemaVersion)
{
Throw<std::runtime_error>(
"The PeerFinder database version is higher than expected");
}
}
if (version < 4)
{
//
// Remove the "uptime" column from the bootstrap table
//
session << "CREATE TABLE IF NOT EXISTS "
"PeerFinder_BootstrapCache_Next ( "
" id INTEGER PRIMARY KEY AUTOINCREMENT, "
" address TEXT UNIQUE NOT NULL, "
" valence INTEGER"
");";
session << "CREATE INDEX IF NOT EXISTS "
" PeerFinder_BootstrapCache_Next_Index ON "
" PeerFinder_BootstrapCache_Next "
" ( address ); ";
std::size_t count;
session << "SELECT COUNT(*) FROM PeerFinder_BootstrapCache;",
soci::into(count);
std::vector<PeerFinder::Store::Entry> list;
{
list.reserve(count);
std::string s;
int valence;
soci::statement st =
(session.prepare << "SELECT "
" address, "
" valence "
"FROM PeerFinder_BootstrapCache;",
soci::into(s),
soci::into(valence));
st.execute();
while (st.fetch())
{
PeerFinder::Store::Entry entry;
entry.endpoint = beast::IP::Endpoint::from_string(s);
if (!is_unspecified(entry.endpoint))
{
entry.valence = valence;
list.push_back(entry);
}
else
{
JLOG(j.error()) << "Bad address string '" << s
<< "' in Bootcache table";
}
}
}
if (!list.empty())
{
std::vector<std::string> s;
std::vector<int> valence;
s.reserve(list.size());
valence.reserve(list.size());
for (auto iter(list.cbegin()); iter != list.cend(); ++iter)
{
s.emplace_back(to_string(iter->endpoint));
valence.emplace_back(iter->valence);
}
session << "INSERT INTO PeerFinder_BootstrapCache_Next ( "
" address, "
" valence "
") VALUES ( "
" :s, :valence"
");",
soci::use(s), soci::use(valence);
}
session << "DROP TABLE IF EXISTS PeerFinder_BootstrapCache;";
session << "DROP INDEX IF EXISTS PeerFinder_BootstrapCache_Index;";
session << "ALTER TABLE PeerFinder_BootstrapCache_Next "
" RENAME TO PeerFinder_BootstrapCache;";
session << "CREATE INDEX IF NOT EXISTS "
" PeerFinder_BootstrapCache_Index ON "
"PeerFinder_BootstrapCache "
" ( "
" address "
" ); ";
}
if (version < 3)
{
//
// Remove legacy endpoints from the schema
//
session << "DROP TABLE IF EXISTS LegacyEndpoints;";
session << "DROP TABLE IF EXISTS PeerFinderLegacyEndpoints;";
session << "DROP TABLE IF EXISTS PeerFinder_LegacyEndpoints;";
session << "DROP TABLE IF EXISTS PeerFinder_LegacyEndpoints_Index;";
}
{
int const v(currentSchemaVersion);
session << "INSERT OR REPLACE INTO SchemaVersion ("
" name "
" ,version "
") VALUES ( "
" 'PeerFinder', :version "
");",
soci::use(v);
}
tr.commit();
}
void
readPeerFinderDB(
soci::session& session,
std::function<void(std::string const&, int)> const& func)
{
std::string s;
int valence;
soci::statement st =
(session.prepare << "SELECT "
" address, "
" valence "
"FROM PeerFinder_BootstrapCache;",
soci::into(s),
soci::into(valence));
st.execute();
while (st.fetch())
{
func(s, valence);
}
}
void
savePeerFinderDB(
soci::session& session,
std::vector<PeerFinder::Store::Entry> const& v)
{
soci::transaction tr(session);
session << "DELETE FROM PeerFinder_BootstrapCache;";
if (!v.empty())
{
std::vector<std::string> s;
std::vector<int> valence;
s.reserve(v.size());
valence.reserve(v.size());
for (auto const& e : v)
{
s.emplace_back(to_string(e.endpoint));
valence.emplace_back(e.valence);
}
session << "INSERT INTO PeerFinder_BootstrapCache ( "
" address, "
" valence "
") VALUES ( "
" :s, :valence "
");",
soci::use(s), soci::use(valence);
}
tr.commit();
}
} // namespace ripple

View File

@@ -1,836 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2020 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 <ripple/app/ledger/AcceptedLedger.h>
#include <ripple/app/ledger/LedgerMaster.h>
#include <ripple/app/ledger/LedgerToJson.h>
#include <ripple/app/ledger/TransactionMaster.h>
#include <ripple/app/misc/Manifest.h>
#include <ripple/app/rdb/RelationalDBInterface_global.h>
#include <ripple/basics/BasicConfig.h>
#include <ripple/basics/StringUtilities.h>
#include <ripple/core/DatabaseCon.h>
#include <ripple/core/SociDB.h>
#include <ripple/json/to_string.h>
#include <boost/algorithm/string.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <soci/sqlite3/soci-sqlite3.h>
namespace ripple {
/* Wallet DB */
std::unique_ptr<DatabaseCon>
makeWalletDB(DatabaseCon::Setup const& setup)
{
// wallet database
return std::make_unique<DatabaseCon>(
setup, WalletDBName, std::array<char const*, 0>(), WalletDBInit);
}
std::unique_ptr<DatabaseCon>
makeTestWalletDB(DatabaseCon::Setup const& setup, std::string const& dbname)
{
// wallet database
return std::make_unique<DatabaseCon>(
setup, dbname.data(), std::array<char const*, 0>(), WalletDBInit);
}
void
getManifests(
soci::session& session,
std::string const& dbTable,
ManifestCache& mCache,
beast::Journal j)
{
// Load manifests stored in database
std::string const sql = "SELECT RawData FROM " + dbTable + ";";
soci::blob sociRawData(session);
soci::statement st = (session.prepare << sql, soci::into(sociRawData));
st.execute();
while (st.fetch())
{
std::string serialized;
convert(sociRawData, serialized);
if (auto mo = deserializeManifest(serialized))
{
if (!mo->verify())
{
JLOG(j.warn()) << "Unverifiable manifest in db";
continue;
}
mCache.applyManifest(std::move(*mo));
}
else
{
JLOG(j.warn()) << "Malformed manifest in database";
}
}
}
static void
saveManifest(
soci::session& session,
std::string const& dbTable,
std::string const& serialized)
{
// soci does not support bulk insertion of blob data
// Do not reuse blob because manifest ecdsa signatures vary in length
// but blob write length is expected to be >= the last write
soci::blob rawData(session);
convert(serialized, rawData);
session << "INSERT INTO " << dbTable << " (RawData) VALUES (:rawData);",
soci::use(rawData);
}
void
saveManifests(
soci::session& session,
std::string const& dbTable,
std::function<bool(PublicKey const&)> const& isTrusted,
hash_map<PublicKey, Manifest> const& map,
beast::Journal j)
{
soci::transaction tr(session);
session << "DELETE FROM " << dbTable;
for (auto const& v : map)
{
// Save all revocation manifests,
// but only save trusted non-revocation manifests.
if (!v.second.revoked() && !isTrusted(v.second.masterKey))
{
JLOG(j.info()) << "Untrusted manifest in cache not saved to db";
continue;
}
saveManifest(session, dbTable, v.second.serialized);
}
tr.commit();
}
void
addValidatorManifest(soci::session& session, std::string const& serialized)
{
soci::transaction tr(session);
saveManifest(session, "ValidatorManifests", serialized);
tr.commit();
}
std::pair<PublicKey, SecretKey>
getNodeIdentity(soci::session& session)
{
{
// SOCI requires boost::optional (not std::optional) as the parameter.
boost::optional<std::string> pubKO, priKO;
soci::statement st =
(session.prepare
<< "SELECT PublicKey, PrivateKey FROM NodeIdentity;",
soci::into(pubKO),
soci::into(priKO));
st.execute();
while (st.fetch())
{
auto const sk = parseBase58<SecretKey>(
TokenType::NodePrivate, priKO.value_or(""));
auto const pk = parseBase58<PublicKey>(
TokenType::NodePublic, pubKO.value_or(""));
// Only use if the public and secret keys are a pair
if (sk && pk && (*pk == derivePublicKey(KeyType::secp256k1, *sk)))
return {*pk, *sk};
}
}
// If a valid identity wasn't found, we randomly generate a new one:
auto [newpublicKey, newsecretKey] = randomKeyPair(KeyType::secp256k1);
session << str(
boost::format("INSERT INTO NodeIdentity (PublicKey,PrivateKey) "
"VALUES ('%s','%s');") %
toBase58(TokenType::NodePublic, newpublicKey) %
toBase58(TokenType::NodePrivate, newsecretKey));
return {newpublicKey, newsecretKey};
}
std::unordered_set<PeerReservation, beast::uhash<>, KeyEqual>
getPeerReservationTable(soci::session& session, beast::Journal j)
{
std::unordered_set<PeerReservation, beast::uhash<>, KeyEqual> table;
// These values must be boost::optionals (not std) because SOCI expects
// boost::optionals.
boost::optional<std::string> valPubKey, valDesc;
// We should really abstract the table and column names into constants,
// but no one else does. Because it is too tedious? It would be easy if we
// had a jOOQ for C++.
soci::statement st =
(session.prepare
<< "SELECT PublicKey, Description FROM PeerReservations;",
soci::into(valPubKey),
soci::into(valDesc));
st.execute();
while (st.fetch())
{
if (!valPubKey || !valDesc)
{
// This represents a `NULL` in a `NOT NULL` column. It should be
// unreachable.
continue;
}
auto const optNodeId =
parseBase58<PublicKey>(TokenType::NodePublic, *valPubKey);
if (!optNodeId)
{
JLOG(j.warn()) << "load: not a public key: " << valPubKey;
continue;
}
table.insert(PeerReservation{*optNodeId, *valDesc});
}
return table;
}
void
insertPeerReservation(
soci::session& session,
PublicKey const& nodeId,
std::string const& description)
{
session << "INSERT INTO PeerReservations (PublicKey, Description) "
"VALUES (:nodeId, :desc) "
"ON CONFLICT (PublicKey) DO UPDATE SET "
"Description=excluded.Description",
soci::use(toBase58(TokenType::NodePublic, nodeId)),
soci::use(description);
}
void
deletePeerReservation(soci::session& session, PublicKey const& nodeId)
{
session << "DELETE FROM PeerReservations WHERE PublicKey = :nodeId",
soci::use(toBase58(TokenType::NodePublic, nodeId));
}
bool
createFeatureVotes(soci::session& session)
{
soci::transaction tr(session);
std::string sql =
"SELECT count(*) FROM sqlite_master "
"WHERE type='table' AND name='FeatureVotes'";
// SOCI requires boost::optional (not std::optional) as the parameter.
boost::optional<int> featureVotesCount;
session << sql, soci::into(featureVotesCount);
bool exists = static_cast<bool>(*featureVotesCount);
// Create FeatureVotes table in WalletDB if it doesn't exist
if (!exists)
{
session << "CREATE TABLE FeatureVotes ( "
"AmendmentHash CHARACTER(64) NOT NULL, "
"AmendmentName TEXT, "
"Veto INTEGER NOT NULL );";
tr.commit();
}
return exists;
}
void
readAmendments(
soci::session& session,
std::function<void(
boost::optional<std::string> amendment_hash,
boost::optional<std::string> amendment_name,
boost::optional<AmendmentVote> vote)> const& callback)
{
// lambda that converts the internally stored int to an AmendmentVote.
auto intToVote = [](boost::optional<int> const& dbVote)
-> boost::optional<AmendmentVote> {
return safe_cast<AmendmentVote>(dbVote.value_or(1));
};
soci::transaction tr(session);
std::string sql =
"SELECT AmendmentHash, AmendmentName, Veto FROM FeatureVotes";
// SOCI requires boost::optional (not std::optional) as parameters.
boost::optional<std::string> amendment_hash;
boost::optional<std::string> amendment_name;
boost::optional<int> vote_to_veto;
soci::statement st =
(session.prepare << sql,
soci::into(amendment_hash),
soci::into(amendment_name),
soci::into(vote_to_veto));
st.execute();
while (st.fetch())
{
callback(amendment_hash, amendment_name, intToVote(vote_to_veto));
}
}
void
voteAmendment(
soci::session& session,
uint256 const& amendment,
std::string const& name,
AmendmentVote vote)
{
soci::transaction tr(session);
std::string sql =
"INSERT INTO FeatureVotes (AmendmentHash, AmendmentName, Veto) VALUES "
"('";
sql += to_string(amendment);
sql += "', '" + name;
sql += "', '" + std::to_string(safe_cast<int>(vote)) + "');";
session << sql;
tr.commit();
}
/* State DB */
void
initStateDB(
soci::session& session,
BasicConfig const& config,
std::string const& dbName)
{
open(session, config, dbName);
session << "PRAGMA synchronous=FULL;";
session << "CREATE TABLE IF NOT EXISTS DbState ("
" Key INTEGER PRIMARY KEY,"
" WritableDb TEXT,"
" ArchiveDb TEXT,"
" LastRotatedLedger INTEGER"
");";
session << "CREATE TABLE IF NOT EXISTS CanDelete ("
" Key INTEGER PRIMARY KEY,"
" CanDeleteSeq INTEGER"
");";
std::int64_t count = 0;
{
// SOCI requires boost::optional (not std::optional) as the parameter.
boost::optional<std::int64_t> countO;
session << "SELECT COUNT(Key) FROM DbState WHERE Key = 1;",
soci::into(countO);
if (!countO)
Throw<std::runtime_error>(
"Failed to fetch Key Count from DbState.");
count = *countO;
}
if (!count)
{
session << "INSERT INTO DbState VALUES (1, '', '', 0);";
}
{
// SOCI requires boost::optional (not std::optional) as the parameter.
boost::optional<std::int64_t> countO;
session << "SELECT COUNT(Key) FROM CanDelete WHERE Key = 1;",
soci::into(countO);
if (!countO)
Throw<std::runtime_error>(
"Failed to fetch Key Count from CanDelete.");
count = *countO;
}
if (!count)
{
session << "INSERT INTO CanDelete VALUES (1, 0);";
}
}
LedgerIndex
getCanDelete(soci::session& session)
{
LedgerIndex seq;
session << "SELECT CanDeleteSeq FROM CanDelete WHERE Key = 1;",
soci::into(seq);
;
return seq;
}
LedgerIndex
setCanDelete(soci::session& session, LedgerIndex canDelete)
{
session << "UPDATE CanDelete SET CanDeleteSeq = :canDelete WHERE Key = 1;",
soci::use(canDelete);
return canDelete;
}
SavedState
getSavedState(soci::session& session)
{
SavedState state;
session << "SELECT WritableDb, ArchiveDb, LastRotatedLedger"
" FROM DbState WHERE Key = 1;",
soci::into(state.writableDb), soci::into(state.archiveDb),
soci::into(state.lastRotated);
return state;
}
void
setSavedState(soci::session& session, SavedState const& state)
{
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
setLastRotated(soci::session& session, LedgerIndex seq)
{
session << "UPDATE DbState SET LastRotatedLedger = :seq"
" WHERE Key = 1;",
soci::use(seq);
}
/* DatabaseBody DB */
std::pair<std::unique_ptr<DatabaseCon>, std::optional<std::uint64_t>>
openDatabaseBodyDb(
DatabaseCon::Setup const& setup,
boost::filesystem::path const& path)
{
// SOCI requires boost::optional (not std::optional) as the parameter.
boost::optional<std::string> pathFromDb;
boost::optional<std::uint64_t> size;
auto conn = std::make_unique<DatabaseCon>(
setup, "Download", DownloaderDBPragma, DatabaseBodyDBInit);
auto& session = *conn->checkoutDb();
session << "SELECT Path FROM Download WHERE Part=0;",
soci::into(pathFromDb);
// Try to reuse preexisting
// database.
if (pathFromDb)
{
// Can't resuse - database was
// from a different file download.
if (pathFromDb != path.string())
{
session << "DROP TABLE Download;";
}
// Continuing a file download.
else
{
session << "SELECT SUM(LENGTH(Data)) FROM Download;",
soci::into(size);
}
}
return {std::move(conn), (size ? *size : std::optional<std::uint64_t>())};
}
std::uint64_t
databaseBodyDoPut(
soci::session& session,
std::string const& data,
std::string const& path,
std::uint64_t fileSize,
std::uint64_t part,
std::uint16_t maxRowSizePad)
{
std::uint64_t rowSize = 0;
soci::indicator rti;
std::uint64_t remainingInRow = 0;
auto be =
dynamic_cast<soci::sqlite3_session_backend*>(session.get_backend());
BOOST_ASSERT(be);
// This limits how large we can make the blob
// in each row. Also subtract a pad value to
// account for the other values in the row.
auto const blobMaxSize =
sqlite_api::sqlite3_limit(be->conn_, SQLITE_LIMIT_LENGTH, -1) -
maxRowSizePad;
std::string newpath;
auto rowInit = [&] {
session << "INSERT INTO Download VALUES (:path, zeroblob(0), 0, :part)",
soci::use(newpath), soci::use(part);
remainingInRow = blobMaxSize;
rowSize = 0;
};
session << "SELECT Path,Size,Part FROM Download ORDER BY Part DESC "
"LIMIT 1",
soci::into(newpath), soci::into(rowSize), soci::into(part, rti);
if (!session.got_data())
{
newpath = path;
rowInit();
}
else
remainingInRow = blobMaxSize - rowSize;
auto insert = [&session, &rowSize, &part, &fs = fileSize](
auto const& data) {
std::uint64_t updatedSize = rowSize + data.size();
session << "UPDATE Download SET Data = CAST(Data || :data AS blob), "
"Size = :size WHERE Part = :part;",
soci::use(data), soci::use(updatedSize), soci::use(part);
fs += data.size();
};
size_t currentBase = 0;
while (currentBase + remainingInRow < data.size())
{
if (remainingInRow)
{
insert(data.substr(currentBase, remainingInRow));
currentBase += remainingInRow;
}
++part;
rowInit();
}
insert(data.substr(currentBase));
return part;
}
void
databaseBodyFinish(soci::session& session, std::ofstream& fout)
{
soci::rowset<std::string> rs =
(session.prepare << "SELECT Data FROM Download ORDER BY PART ASC;");
// iteration through the resultset:
for (auto it = rs.begin(); it != rs.end(); ++it)
fout.write(it->data(), it->size());
}
/* Vacuum DB */
bool
doVacuumDB(DatabaseCon::Setup const& setup)
{
boost::filesystem::path dbPath = setup.dataDir / TxDBName;
uintmax_t const dbSize = file_size(dbPath);
assert(dbSize != static_cast<uintmax_t>(-1));
if (auto available = space(dbPath.parent_path()).available;
available < dbSize)
{
std::cerr << "The database filesystem must have at least as "
"much free space as the size of "
<< dbPath.string() << ", which is " << dbSize
<< " bytes. Only " << available << " bytes are available.\n";
return false;
}
auto txnDB =
std::make_unique<DatabaseCon>(setup, TxDBName, TxDBPragma, TxDBInit);
auto& session = txnDB->getSession();
std::uint32_t pageSize;
// Only the most trivial databases will fit in memory on typical
// (recommended) software. Force temp files to be written to disk
// regardless of the config settings.
session << boost::format(CommonDBPragmaTemp) % "file";
session << "PRAGMA page_size;", soci::into(pageSize);
std::cout << "VACUUM beginning. page_size: " << pageSize << std::endl;
session << "VACUUM;";
assert(setup.globalPragma);
for (auto const& p : *setup.globalPragma)
session << p;
session << "PRAGMA page_size;", soci::into(pageSize);
std::cout << "VACUUM finished. page_size: " << pageSize << std::endl;
return true;
}
/* PeerFinder DB */
void
initPeerFinderDB(
soci::session& session,
BasicConfig const& config,
beast::Journal j)
{
DBConfig m_sociConfig(config, "peerfinder");
m_sociConfig.open(session);
JLOG(j.info()) << "Opening database at '" << m_sociConfig.connectionString()
<< "'";
soci::transaction tr(session);
session << "PRAGMA encoding=\"UTF-8\";";
session << "CREATE TABLE IF NOT EXISTS SchemaVersion ( "
" name TEXT PRIMARY KEY, "
" version INTEGER"
");";
session << "CREATE TABLE IF NOT EXISTS PeerFinder_BootstrapCache ( "
" id INTEGER PRIMARY KEY AUTOINCREMENT, "
" address TEXT UNIQUE NOT NULL, "
" valence INTEGER"
");";
session << "CREATE INDEX IF NOT EXISTS "
" PeerFinder_BootstrapCache_Index ON "
"PeerFinder_BootstrapCache "
" ( "
" address "
" ); ";
tr.commit();
}
void
updatePeerFinderDB(
soci::session& session,
int currentSchemaVersion,
beast::Journal j)
{
soci::transaction tr(session);
// get version
int version(0);
{
// SOCI requires a boost::optional (not std::optional) parameter.
boost::optional<int> vO;
session << "SELECT "
" version "
"FROM SchemaVersion WHERE "
" name = 'PeerFinder';",
soci::into(vO);
version = vO.value_or(0);
JLOG(j.info()) << "Opened version " << version << " database";
}
{
if (version < currentSchemaVersion)
{
JLOG(j.info()) << "Updating database to version "
<< currentSchemaVersion;
}
else if (version > currentSchemaVersion)
{
Throw<std::runtime_error>(
"The PeerFinder database version is higher than expected");
}
}
if (version < 4)
{
//
// Remove the "uptime" column from the bootstrap table
//
session << "CREATE TABLE IF NOT EXISTS "
"PeerFinder_BootstrapCache_Next ( "
" id INTEGER PRIMARY KEY AUTOINCREMENT, "
" address TEXT UNIQUE NOT NULL, "
" valence INTEGER"
");";
session << "CREATE INDEX IF NOT EXISTS "
" PeerFinder_BootstrapCache_Next_Index ON "
" PeerFinder_BootstrapCache_Next "
" ( address ); ";
std::size_t count;
session << "SELECT COUNT(*) FROM PeerFinder_BootstrapCache;",
soci::into(count);
std::vector<PeerFinder::Store::Entry> list;
{
list.reserve(count);
std::string s;
int valence;
soci::statement st =
(session.prepare << "SELECT "
" address, "
" valence "
"FROM PeerFinder_BootstrapCache;",
soci::into(s),
soci::into(valence));
st.execute();
while (st.fetch())
{
PeerFinder::Store::Entry entry;
entry.endpoint = beast::IP::Endpoint::from_string(s);
if (!is_unspecified(entry.endpoint))
{
entry.valence = valence;
list.push_back(entry);
}
else
{
JLOG(j.error()) << "Bad address string '" << s
<< "' in Bootcache table";
}
}
}
if (!list.empty())
{
std::vector<std::string> s;
std::vector<int> valence;
s.reserve(list.size());
valence.reserve(list.size());
for (auto iter(list.cbegin()); iter != list.cend(); ++iter)
{
s.emplace_back(to_string(iter->endpoint));
valence.emplace_back(iter->valence);
}
session << "INSERT INTO PeerFinder_BootstrapCache_Next ( "
" address, "
" valence "
") VALUES ( "
" :s, :valence"
");",
soci::use(s), soci::use(valence);
}
session << "DROP TABLE IF EXISTS PeerFinder_BootstrapCache;";
session << "DROP INDEX IF EXISTS PeerFinder_BootstrapCache_Index;";
session << "ALTER TABLE PeerFinder_BootstrapCache_Next "
" RENAME TO PeerFinder_BootstrapCache;";
session << "CREATE INDEX IF NOT EXISTS "
" PeerFinder_BootstrapCache_Index ON "
"PeerFinder_BootstrapCache "
" ( "
" address "
" ); ";
}
if (version < 3)
{
//
// Remove legacy endpoints from the schema
//
session << "DROP TABLE IF EXISTS LegacyEndpoints;";
session << "DROP TABLE IF EXISTS PeerFinderLegacyEndpoints;";
session << "DROP TABLE IF EXISTS PeerFinder_LegacyEndpoints;";
session << "DROP TABLE IF EXISTS PeerFinder_LegacyEndpoints_Index;";
}
{
int const v(currentSchemaVersion);
session << "INSERT OR REPLACE INTO SchemaVersion ("
" name "
" ,version "
") VALUES ( "
" 'PeerFinder', :version "
");",
soci::use(v);
}
tr.commit();
}
void
readPeerFinderDB(
soci::session& session,
std::function<void(std::string const&, int)> const& func)
{
std::string s;
int valence;
soci::statement st =
(session.prepare << "SELECT "
" address, "
" valence "
"FROM PeerFinder_BootstrapCache;",
soci::into(s),
soci::into(valence));
st.execute();
while (st.fetch())
{
func(s, valence);
}
}
void
savePeerFinderDB(
soci::session& session,
std::vector<PeerFinder::Store::Entry> const& v)
{
soci::transaction tr(session);
session << "DELETE FROM PeerFinder_BootstrapCache;";
if (!v.empty())
{
std::vector<std::string> s;
std::vector<int> valence;
s.reserve(v.size());
valence.reserve(v.size());
for (auto const& e : v)
{
s.emplace_back(to_string(e.endpoint));
valence.emplace_back(e.valence);
}
session << "INSERT INTO PeerFinder_BootstrapCache ( "
" address, "
" valence "
") VALUES ( "
" :s, :valence "
");",
soci::use(s), soci::use(valence);
}
tr.commit();
}
} // namespace ripple

View File

@@ -18,26 +18,20 @@
//==============================================================================
#include <ripple/app/main/Application.h>
#include <ripple/app/rdb/RelationalDBInterface.h>
#include <ripple/app/rdb/RelationalDatabase.h>
#include <ripple/core/ConfigSections.h>
#include <ripple/nodestore/DatabaseShard.h>
namespace ripple {
extern std::unique_ptr<RelationalDBInterface>
getRelationalDBInterfaceSqlite(
Application& app,
Config const& config,
JobQueue& jobQueue);
extern std::unique_ptr<RelationalDatabase>
getSQLiteDatabase(Application& app, Config const& config, JobQueue& jobQueue);
extern std::unique_ptr<RelationalDBInterface>
getRelationalDBInterfacePostgres(
Application& app,
Config const& config,
JobQueue& jobQueue);
extern std::unique_ptr<RelationalDatabase>
getPostgresDatabase(Application& app, Config const& config, JobQueue& jobQueue);
std::unique_ptr<RelationalDBInterface>
RelationalDBInterface::init(
std::unique_ptr<RelationalDatabase>
RelationalDatabase::init(
Application& app,
Config const& config,
JobQueue& jobQueue)
@@ -73,14 +67,14 @@ RelationalDBInterface::init(
if (use_sqlite)
{
return getRelationalDBInterfaceSqlite(app, config, jobQueue);
return getSQLiteDatabase(app, config, jobQueue);
}
else if (use_postgres)
{
return getRelationalDBInterfacePostgres(app, config, jobQueue);
return getPostgresDatabase(app, config, jobQueue);
}
return std::unique_ptr<RelationalDBInterface>();
return std::unique_ptr<RelationalDatabase>();
}
} // namespace ripple

View File

@@ -0,0 +1,68 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2021 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 <ripple/app/rdb/ShardArchive.h>
namespace ripple {
std::unique_ptr<DatabaseCon>
makeArchiveDB(boost::filesystem::path const& dir, std::string const& dbName)
{
return std::make_unique<DatabaseCon>(
dir, dbName, DownloaderDBPragma, ShardArchiveHandlerDBInit);
}
void
readArchiveDB(
DatabaseCon& db,
std::function<void(std::string const&, int)> const& func)
{
soci::rowset<soci::row> rs =
(db.getSession().prepare << "SELECT * FROM State;");
for (auto it = rs.begin(); it != rs.end(); ++it)
{
func(it->get<std::string>(1), it->get<int>(0));
}
}
void
insertArchiveDB(
DatabaseCon& db,
std::uint32_t shardIndex,
std::string const& url)
{
db.getSession() << "INSERT INTO State VALUES (:index, :url);",
soci::use(shardIndex), soci::use(url);
}
void
deleteFromArchiveDB(DatabaseCon& db, std::uint32_t shardIndex)
{
db.getSession() << "DELETE FROM State WHERE ShardIndex = :index;",
soci::use(shardIndex);
}
void
dropArchiveDB(DatabaseCon& db)
{
db.getSession() << "DROP TABLE State;";
}
} // namespace ripple

View File

@@ -0,0 +1,130 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2021 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 <ripple/app/rdb/State.h>
namespace ripple {
void
initStateDB(
soci::session& session,
BasicConfig const& config,
std::string const& dbName)
{
open(session, config, dbName);
session << "PRAGMA synchronous=FULL;";
session << "CREATE TABLE IF NOT EXISTS DbState ("
" Key INTEGER PRIMARY KEY,"
" WritableDb TEXT,"
" ArchiveDb TEXT,"
" LastRotatedLedger INTEGER"
");";
session << "CREATE TABLE IF NOT EXISTS CanDelete ("
" Key INTEGER PRIMARY KEY,"
" CanDeleteSeq INTEGER"
");";
std::int64_t count = 0;
{
// SOCI requires boost::optional (not std::optional) as the parameter.
boost::optional<std::int64_t> countO;
session << "SELECT COUNT(Key) FROM DbState WHERE Key = 1;",
soci::into(countO);
if (!countO)
Throw<std::runtime_error>(
"Failed to fetch Key Count from DbState.");
count = *countO;
}
if (!count)
{
session << "INSERT INTO DbState VALUES (1, '', '', 0);";
}
{
// SOCI requires boost::optional (not std::optional) as the parameter.
boost::optional<std::int64_t> countO;
session << "SELECT COUNT(Key) FROM CanDelete WHERE Key = 1;",
soci::into(countO);
if (!countO)
Throw<std::runtime_error>(
"Failed to fetch Key Count from CanDelete.");
count = *countO;
}
if (!count)
{
session << "INSERT INTO CanDelete VALUES (1, 0);";
}
}
LedgerIndex
getCanDelete(soci::session& session)
{
LedgerIndex seq;
session << "SELECT CanDeleteSeq FROM CanDelete WHERE Key = 1;",
soci::into(seq);
;
return seq;
}
LedgerIndex
setCanDelete(soci::session& session, LedgerIndex canDelete)
{
session << "UPDATE CanDelete SET CanDeleteSeq = :canDelete WHERE Key = 1;",
soci::use(canDelete);
return canDelete;
}
SavedState
getSavedState(soci::session& session)
{
SavedState state;
session << "SELECT WritableDb, ArchiveDb, LastRotatedLedger"
" FROM DbState WHERE Key = 1;",
soci::into(state.writableDb), soci::into(state.archiveDb),
soci::into(state.lastRotated);
return state;
}
void
setSavedState(soci::session& session, SavedState const& state)
{
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
setLastRotated(soci::session& session, LedgerIndex seq)
{
session << "UPDATE DbState SET LastRotatedLedger = :seq"
" WHERE Key = 1;",
soci::use(seq);
}
} // namespace ripple

View File

@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2020 Ripple Labs Inc.
Copyright (c) 2021 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
@@ -10,151 +10,20 @@
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
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 <ripple/app/ledger/AcceptedLedger.h>
#include <ripple/app/ledger/LedgerMaster.h>
#include <ripple/app/ledger/LedgerToJson.h>
#include <ripple/app/rdb/RelationalDBInterface.h>
#include <ripple/app/rdb/RelationalDBInterface_shards.h>
#include <ripple/basics/BasicConfig.h>
#include <ripple/app/rdb/UnitaryShard.h>
#include <ripple/basics/StringUtilities.h>
#include <ripple/core/DatabaseCon.h>
#include <ripple/core/SociDB.h>
#include <ripple/json/to_string.h>
#include <boost/algorithm/string.hpp>
#include <boost/format.hpp>
#include <boost/range/adaptor/transformed.hpp>
namespace ripple {
DatabasePair
makeMetaDBs(
Config const& config,
DatabaseCon::Setup const& setup,
DatabaseCon::CheckpointerSetup const& checkpointerSetup)
{
// ledger meta database
auto lgrMetaDB{std::make_unique<DatabaseCon>(
setup,
LgrMetaDBName,
LgrMetaDBPragma,
LgrMetaDBInit,
checkpointerSetup)};
if (config.useTxTables())
{
// transaction meta database
auto txMetaDB{std::make_unique<DatabaseCon>(
setup,
TxMetaDBName,
TxMetaDBPragma,
TxMetaDBInit,
checkpointerSetup)};
return {std::move(lgrMetaDB), std::move(txMetaDB)};
}
return {std::move(lgrMetaDB), nullptr};
}
bool
saveLedgerMeta(
std::shared_ptr<Ledger const> const& ledger,
Application& app,
soci::session& lgrMetaSession,
soci::session& txnMetaSession,
std::uint32_t const shardIndex)
{
std::string_view constexpr lgrSQL =
R"sql(INSERT OR REPLACE INTO LedgerMeta VALUES
(:ledgerHash,:shardIndex);)sql";
auto const hash = to_string(ledger->info().hash);
lgrMetaSession << lgrSQL, soci::use(hash), soci::use(shardIndex);
if (app.config().useTxTables())
{
auto const aLedger = [&app,
ledger]() -> std::shared_ptr<AcceptedLedger> {
try
{
auto aLedger =
app.getAcceptedLedgerCache().fetch(ledger->info().hash);
if (!aLedger)
{
aLedger = std::make_shared<AcceptedLedger>(ledger, app);
app.getAcceptedLedgerCache().canonicalize_replace_client(
ledger->info().hash, aLedger);
}
return aLedger;
}
catch (std::exception const&)
{
JLOG(app.journal("Ledger").warn())
<< "An accepted ledger was missing nodes";
}
return {};
}();
if (!aLedger)
return false;
soci::transaction tr(txnMetaSession);
for (auto const& acceptedLedgerTx : *aLedger)
{
std::string_view constexpr txnSQL =
R"sql(INSERT OR REPLACE INTO TransactionMeta VALUES
(:transactionID,:shardIndex);)sql";
auto const transactionID =
to_string(acceptedLedgerTx->getTransactionID());
txnMetaSession << txnSQL, soci::use(transactionID),
soci::use(shardIndex);
}
tr.commit();
}
return true;
}
std::optional<std::uint32_t>
getShardIndexforLedger(soci::session& session, LedgerHash const& hash)
{
std::uint32_t shardIndex;
session << "SELECT ShardIndex FROM LedgerMeta WHERE LedgerHash = '" << hash
<< "';",
soci::into(shardIndex);
if (!session.got_data())
return std::nullopt;
return shardIndex;
}
std::optional<std::uint32_t>
getShardIndexforTransaction(soci::session& session, TxID const& id)
{
std::uint32_t shardIndex;
session << "SELECT ShardIndex FROM TransactionMeta WHERE TransID = '" << id
<< "';",
soci::into(shardIndex);
if (!session.got_data())
return std::nullopt;
return shardIndex;
}
DatabasePair
makeShardCompleteLedgerDBs(
Config const& config,
@@ -333,8 +202,6 @@ updateLedgerDBs(
return true;
}
/* Shard acquire db */
std::unique_ptr<DatabaseCon>
makeAcquireDB(
DatabaseCon::Setup const& setup,
@@ -446,50 +313,4 @@ updateAcquireDB(
}
}
/* Archive DB */
std::unique_ptr<DatabaseCon>
makeArchiveDB(boost::filesystem::path const& dir, std::string const& dbName)
{
return std::make_unique<DatabaseCon>(
dir, dbName, DownloaderDBPragma, ShardArchiveHandlerDBInit);
}
void
readArchiveDB(
DatabaseCon& db,
std::function<void(std::string const&, int)> const& func)
{
soci::rowset<soci::row> rs =
(db.getSession().prepare << "SELECT * FROM State;");
for (auto it = rs.begin(); it != rs.end(); ++it)
{
func(it->get<std::string>(1), it->get<int>(0));
}
}
void
insertArchiveDB(
DatabaseCon& db,
std::uint32_t shardIndex,
std::string const& url)
{
db.getSession() << "INSERT INTO State VALUES (:index, :url);",
soci::use(shardIndex), soci::use(url);
}
void
deleteFromArchiveDB(DatabaseCon& db, std::uint32_t shardIndex)
{
db.getSession() << "DELETE FROM State WHERE ShardIndex = :index;",
soci::use(shardIndex);
}
void
dropArchiveDB(DatabaseCon& db)
{
db.getSession() << "DROP TABLE State;";
}
} // namespace ripple

View File

@@ -0,0 +1,67 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2021 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 <ripple/app/rdb/Vacuum.h>
#include <boost/format.hpp>
namespace ripple {
bool
doVacuumDB(DatabaseCon::Setup const& setup)
{
boost::filesystem::path dbPath = setup.dataDir / TxDBName;
uintmax_t const dbSize = file_size(dbPath);
assert(dbSize != static_cast<uintmax_t>(-1));
if (auto available = space(dbPath.parent_path()).available;
available < dbSize)
{
std::cerr << "The database filesystem must have at least as "
"much free space as the size of "
<< dbPath.string() << ", which is " << dbSize
<< " bytes. Only " << available << " bytes are available.\n";
return false;
}
auto txnDB =
std::make_unique<DatabaseCon>(setup, TxDBName, TxDBPragma, TxDBInit);
auto& session = txnDB->getSession();
std::uint32_t pageSize;
// Only the most trivial databases will fit in memory on typical
// (recommended) hardware. Force temp files to be written to disk
// regardless of the config settings.
session << boost::format(CommonDBPragmaTemp) % "file";
session << "PRAGMA page_size;", soci::into(pageSize);
std::cout << "VACUUM beginning. page_size: " << pageSize << std::endl;
session << "VACUUM;";
assert(setup.globalPragma);
for (auto const& p : *setup.globalPragma)
session << p;
session << "PRAGMA page_size;", soci::into(pageSize);
std::cout << "VACUUM finished. page_size: " << pageSize << std::endl;
return true;
}
} // namespace ripple

View File

@@ -0,0 +1,292 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2021 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 <ripple/app/rdb/Wallet.h>
#include <boost/format.hpp>
namespace ripple {
std::unique_ptr<DatabaseCon>
makeWalletDB(DatabaseCon::Setup const& setup)
{
// wallet database
return std::make_unique<DatabaseCon>(
setup, WalletDBName, std::array<char const*, 0>(), WalletDBInit);
}
std::unique_ptr<DatabaseCon>
makeTestWalletDB(DatabaseCon::Setup const& setup, std::string const& dbname)
{
// wallet database
return std::make_unique<DatabaseCon>(
setup, dbname.data(), std::array<char const*, 0>(), WalletDBInit);
}
void
getManifests(
soci::session& session,
std::string const& dbTable,
ManifestCache& mCache,
beast::Journal j)
{
// Load manifests stored in database
std::string const sql = "SELECT RawData FROM " + dbTable + ";";
soci::blob sociRawData(session);
soci::statement st = (session.prepare << sql, soci::into(sociRawData));
st.execute();
while (st.fetch())
{
std::string serialized;
convert(sociRawData, serialized);
if (auto mo = deserializeManifest(serialized))
{
if (!mo->verify())
{
JLOG(j.warn()) << "Unverifiable manifest in db";
continue;
}
mCache.applyManifest(std::move(*mo));
}
else
{
JLOG(j.warn()) << "Malformed manifest in database";
}
}
}
static void
saveManifest(
soci::session& session,
std::string const& dbTable,
std::string const& serialized)
{
// soci does not support bulk insertion of blob data
// Do not reuse blob because manifest ecdsa signatures vary in length
// but blob write length is expected to be >= the last write
soci::blob rawData(session);
convert(serialized, rawData);
session << "INSERT INTO " << dbTable << " (RawData) VALUES (:rawData);",
soci::use(rawData);
}
void
saveManifests(
soci::session& session,
std::string const& dbTable,
std::function<bool(PublicKey const&)> const& isTrusted,
hash_map<PublicKey, Manifest> const& map,
beast::Journal j)
{
soci::transaction tr(session);
session << "DELETE FROM " << dbTable;
for (auto const& v : map)
{
// Save all revocation manifests,
// but only save trusted non-revocation manifests.
if (!v.second.revoked() && !isTrusted(v.second.masterKey))
{
JLOG(j.info()) << "Untrusted manifest in cache not saved to db";
continue;
}
saveManifest(session, dbTable, v.second.serialized);
}
tr.commit();
}
void
addValidatorManifest(soci::session& session, std::string const& serialized)
{
soci::transaction tr(session);
saveManifest(session, "ValidatorManifests", serialized);
tr.commit();
}
std::pair<PublicKey, SecretKey>
getNodeIdentity(soci::session& session)
{
{
// SOCI requires boost::optional (not std::optional) as the parameter.
boost::optional<std::string> pubKO, priKO;
soci::statement st =
(session.prepare
<< "SELECT PublicKey, PrivateKey FROM NodeIdentity;",
soci::into(pubKO),
soci::into(priKO));
st.execute();
while (st.fetch())
{
auto const sk = parseBase58<SecretKey>(
TokenType::NodePrivate, priKO.value_or(""));
auto const pk = parseBase58<PublicKey>(
TokenType::NodePublic, pubKO.value_or(""));
// Only use if the public and secret keys are a pair
if (sk && pk && (*pk == derivePublicKey(KeyType::secp256k1, *sk)))
return {*pk, *sk};
}
}
// If a valid identity wasn't found, we randomly generate a new one:
auto [newpublicKey, newsecretKey] = randomKeyPair(KeyType::secp256k1);
session << str(
boost::format("INSERT INTO NodeIdentity (PublicKey,PrivateKey) "
"VALUES ('%s','%s');") %
toBase58(TokenType::NodePublic, newpublicKey) %
toBase58(TokenType::NodePrivate, newsecretKey));
return {newpublicKey, newsecretKey};
}
std::unordered_set<PeerReservation, beast::uhash<>, KeyEqual>
getPeerReservationTable(soci::session& session, beast::Journal j)
{
std::unordered_set<PeerReservation, beast::uhash<>, KeyEqual> table;
// These values must be boost::optionals (not std) because SOCI expects
// boost::optionals.
boost::optional<std::string> valPubKey, valDesc;
// We should really abstract the table and column names into constants,
// but no one else does. Because it is too tedious? It would be easy if we
// had a jOOQ for C++.
soci::statement st =
(session.prepare
<< "SELECT PublicKey, Description FROM PeerReservations;",
soci::into(valPubKey),
soci::into(valDesc));
st.execute();
while (st.fetch())
{
if (!valPubKey || !valDesc)
{
// This represents a `NULL` in a `NOT NULL` column. It should be
// unreachable.
continue;
}
auto const optNodeId =
parseBase58<PublicKey>(TokenType::NodePublic, *valPubKey);
if (!optNodeId)
{
JLOG(j.warn()) << "load: not a public key: " << valPubKey;
continue;
}
table.insert(PeerReservation{*optNodeId, *valDesc});
}
return table;
}
void
insertPeerReservation(
soci::session& session,
PublicKey const& nodeId,
std::string const& description)
{
session << "INSERT INTO PeerReservations (PublicKey, Description) "
"VALUES (:nodeId, :desc) "
"ON CONFLICT (PublicKey) DO UPDATE SET "
"Description=excluded.Description",
soci::use(toBase58(TokenType::NodePublic, nodeId)),
soci::use(description);
}
void
deletePeerReservation(soci::session& session, PublicKey const& nodeId)
{
session << "DELETE FROM PeerReservations WHERE PublicKey = :nodeId",
soci::use(toBase58(TokenType::NodePublic, nodeId));
}
bool
createFeatureVotes(soci::session& session)
{
soci::transaction tr(session);
std::string sql =
"SELECT count(*) FROM sqlite_master "
"WHERE type='table' AND name='FeatureVotes'";
// SOCI requires boost::optional (not std::optional) as the parameter.
boost::optional<int> featureVotesCount;
session << sql, soci::into(featureVotesCount);
bool exists = static_cast<bool>(*featureVotesCount);
// Create FeatureVotes table in WalletDB if it doesn't exist
if (!exists)
{
session << "CREATE TABLE FeatureVotes ( "
"AmendmentHash CHARACTER(64) NOT NULL, "
"AmendmentName TEXT, "
"Veto INTEGER NOT NULL );";
tr.commit();
}
return exists;
}
void
readAmendments(
soci::session& session,
std::function<void(
boost::optional<std::string> amendment_hash,
boost::optional<std::string> amendment_name,
boost::optional<AmendmentVote> vote)> const& callback)
{
// lambda that converts the internally stored int to an AmendmentVote.
auto intToVote = [](boost::optional<int> const& dbVote)
-> boost::optional<AmendmentVote> {
return safe_cast<AmendmentVote>(dbVote.value_or(1));
};
soci::transaction tr(session);
std::string sql =
"SELECT AmendmentHash, AmendmentName, Veto FROM FeatureVotes";
// SOCI requires boost::optional (not std::optional) as parameters.
boost::optional<std::string> amendment_hash;
boost::optional<std::string> amendment_name;
boost::optional<int> vote_to_veto;
soci::statement st =
(session.prepare << sql,
soci::into(amendment_hash),
soci::into(amendment_name),
soci::into(vote_to_veto));
st.execute();
while (st.fetch())
{
callback(amendment_hash, amendment_name, intToVote(vote_to_veto));
}
}
void
voteAmendment(
soci::session& session,
uint256 const& amendment,
std::string const& name,
AmendmentVote vote)
{
soci::transaction tr(session);
std::string sql =
"INSERT INTO FeatureVotes (AmendmentHash, AmendmentName, Veto) VALUES "
"('";
sql += to_string(amendment);
sql += "', '" + name;
sql += "', '" + std::to_string(safe_cast<int>(vote)) + "');";
session << sql;
tr.commit();
}
} // namespace ripple

View File

@@ -17,7 +17,7 @@
*/
//==============================================================================
#include <ripple/app/rdb/backend/RelationalDBInterfacePostgres.h>
#include <ripple/app/rdb/backend/PostgresDatabase.h>
#include <ripple/app/reporting/ReportingETL.h>
#include <ripple/beast/core/CurrentThreadName.h>
@@ -167,8 +167,7 @@ ReportingETL::loadInitialLedger(uint32_t startingSequence)
if (app_.config().reporting())
{
#ifdef RIPPLED_REPORTING
dynamic_cast<RelationalDBInterfacePostgres*>(
&app_.getRelationalDBInterface())
dynamic_cast<PostgresDatabase*>(&app_.getRelationalDatabase())
->writeLedgerAndTransactions(ledger->info(), accountTxData);
#endif
}
@@ -595,69 +594,69 @@ ReportingETL::runETLPipeline(uint32_t startSequence)
loadQueue.push({});
}};
std::thread loader{
[this, &lastPublishedSequence, &loadQueue, &writeConflict]() {
beast::setCurrentThreadName("rippled: ReportingETL load");
size_t totalTransactions = 0;
double totalTime = 0;
while (!writeConflict)
{
std::optional<std::pair<
std::shared_ptr<Ledger>,
std::vector<AccountTransactionsData>>>
result{loadQueue.pop()};
// if result is an empty optional, the transformer thread has
// stopped and the loader should stop as well
if (!result)
break;
if (isStopping())
continue;
std::thread loader{[this,
&lastPublishedSequence,
&loadQueue,
&writeConflict]() {
beast::setCurrentThreadName("rippled: ReportingETL load");
size_t totalTransactions = 0;
double totalTime = 0;
while (!writeConflict)
{
std::optional<std::pair<
std::shared_ptr<Ledger>,
std::vector<AccountTransactionsData>>>
result{loadQueue.pop()};
// if result is an empty optional, the transformer thread has
// stopped and the loader should stop as well
if (!result)
break;
if (isStopping())
continue;
auto& ledger = result->first;
auto& accountTxData = result->second;
auto& ledger = result->first;
auto& accountTxData = result->second;
auto start = std::chrono::system_clock::now();
// write to the key-value store
flushLedger(ledger);
auto start = std::chrono::system_clock::now();
// write to the key-value store
flushLedger(ledger);
auto mid = std::chrono::system_clock::now();
auto mid = std::chrono::system_clock::now();
// write to RDBMS
// if there is a write conflict, some other process has already
// written this ledger and has taken over as the ETL writer
#ifdef RIPPLED_REPORTING
if (!dynamic_cast<RelationalDBInterfacePostgres*>(
&app_.getRelationalDBInterface())
->writeLedgerAndTransactions(
ledger->info(), accountTxData))
writeConflict = true;
if (!dynamic_cast<PostgresDatabase*>(&app_.getRelationalDatabase())
->writeLedgerAndTransactions(
ledger->info(), accountTxData))
writeConflict = true;
#endif
auto end = std::chrono::system_clock::now();
auto end = std::chrono::system_clock::now();
if (!writeConflict)
{
publishLedger(ledger);
lastPublishedSequence = ledger->info().seq;
}
// print some performance numbers
auto kvTime = ((mid - start).count()) / 1000000000.0;
auto relationalTime = ((end - mid).count()) / 1000000000.0;
size_t numTxns = accountTxData.size();
totalTime += kvTime;
totalTransactions += numTxns;
JLOG(journal_.info())
<< "Load phase of etl : "
<< "Successfully published ledger! Ledger info: "
<< detail::toString(ledger->info())
<< ". txn count = " << numTxns
<< ". key-value write time = " << kvTime
<< ". relational write time = " << relationalTime
<< ". key-value tps = " << numTxns / kvTime
<< ". relational tps = " << numTxns / relationalTime
<< ". total key-value tps = "
<< totalTransactions / totalTime;
if (!writeConflict)
{
publishLedger(ledger);
lastPublishedSequence = ledger->info().seq;
}
}};
// print some performance numbers
auto kvTime = ((mid - start).count()) / 1000000000.0;
auto relationalTime = ((end - mid).count()) / 1000000000.0;
size_t numTxns = accountTxData.size();
totalTime += kvTime;
totalTransactions += numTxns;
JLOG(journal_.info())
<< "Load phase of etl : "
<< "Successfully published ledger! Ledger info: "
<< detail::toString(ledger->info())
<< ". txn count = " << numTxns
<< ". key-value write time = " << kvTime
<< ". relational write time = " << relationalTime
<< ". key-value tps = " << numTxns / kvTime
<< ". relational tps = " << numTxns / relationalTime
<< ". total key-value tps = " << totalTransactions / totalTime;
}
}};
// wait for all of the threads to stop
loader.join();

View File

@@ -21,7 +21,7 @@
#define RIPPLE_APP_REPORTING_REPORTINGETL_H_INCLUDED
#include <ripple/app/main/Application.h>
#include <ripple/app/rdb/RelationalDBInterface.h>
#include <ripple/app/rdb/RelationalDatabase.h>
#include <ripple/app/reporting/ETLHelpers.h>
#include <ripple/app/reporting/ETLSource.h>
#include <ripple/core/JobQueue.h>
@@ -50,7 +50,7 @@
#include <chrono>
namespace ripple {
using AccountTransactionsData = RelationalDBInterface::AccountTransactionsData;
using AccountTransactionsData = RelationalDatabase::AccountTransactionsData;
/**
* This class is responsible for continuously extracting data from a

View File

@@ -17,7 +17,7 @@
*/
//==============================================================================
#include <ripple/app/rdb/RelationalDBInterface_global.h>
#include <ripple/app/rdb/Download.h>
namespace ripple {

View File

@@ -20,7 +20,7 @@
#include <ripple/app/ledger/InboundLedgers.h>
#include <ripple/app/ledger/LedgerMaster.h>
#include <ripple/app/misc/NetworkOPs.h>
#include <ripple/app/rdb/backend/RelationalDBInterfaceSqlite.h>
#include <ripple/app/rdb/backend/SQLiteDatabase.h>
#include <ripple/basics/ByteUtilities.h>
#include <ripple/basics/RangeSet.h>
#include <ripple/basics/chrono.h>
@@ -799,14 +799,12 @@ DatabaseShardImp::doImportDatabase()
std::optional<LedgerInfo> info;
if (sortOrder == std::string("asc"))
{
info = dynamic_cast<RelationalDBInterfaceSqlite*>(
&app_.getRelationalDBInterface())
info = dynamic_cast<SQLiteDatabase*>(&app_.getRelationalDatabase())
->getLimitedOldestLedgerInfo(earliestLedgerSeq());
}
else
{
info = dynamic_cast<RelationalDBInterfaceSqlite*>(
&app_.getRelationalDBInterface())
info = dynamic_cast<SQLiteDatabase*>(&app_.getRelationalDatabase())
->getLimitedNewestLedgerInfo(earliestLedgerSeq());
}
if (info)
@@ -925,7 +923,7 @@ DatabaseShardImp::doImportDatabase()
// Verify SQLite ledgers are in the node store
{
auto const ledgerHashes{
app_.getRelationalDBInterface().getHashesByIndex(
app_.getRelationalDatabase().getHashesByIndex(
firstSeq, lastSeq)};
if (ledgerHashes.size() != maxLedgers(shardIndex))
continue;
@@ -2026,6 +2024,13 @@ DatabaseShardImp::callForLedgerSQLByLedgerSeq(
LedgerIndex ledgerSeq,
std::function<bool(soci::session& session)> const& callback)
{
if (ledgerSeq < earliestLedgerSeq_)
{
JLOG(j_.warn()) << "callForLedgerSQLByLedgerSeq ledger seq too early: "
<< ledgerSeq;
return false;
}
return callForLedgerSQLByShardIndex(seqToShardIndex(ledgerSeq), callback);
}

View File

@@ -19,8 +19,7 @@
#include <ripple/app/ledger/InboundLedger.h>
#include <ripple/app/main/DBInit.h>
#include <ripple/app/rdb/RelationalDBInterface_global.h>
#include <ripple/app/rdb/RelationalDBInterface_shards.h>
#include <ripple/app/rdb/backend/detail/Shard.h>
#include <ripple/basics/StringUtilities.h>
#include <ripple/core/ConfigSections.h>
#include <ripple/nodestore/Manager.h>
@@ -28,9 +27,6 @@
#include <ripple/nodestore/impl/Shard.h>
#include <ripple/protocol/digest.h>
#include <boost/algorithm/string.hpp>
#include <boost/range/adaptor/transformed.hpp>
namespace ripple {
namespace NodeStore {

View File

@@ -21,7 +21,7 @@
#define RIPPLE_NODESTORE_SHARD_H_INCLUDED
#include <ripple/app/ledger/Ledger.h>
#include <ripple/app/rdb/RelationalDBInterface.h>
#include <ripple/app/rdb/RelationalDatabase.h>
#include <ripple/basics/BasicConfig.h>
#include <ripple/basics/KeyCache.h>
#include <ripple/basics/MathUtilities.h>

View File

@@ -22,8 +22,8 @@
#include <ripple/app/misc/NetworkOPs.h>
#include <ripple/app/misc/ValidatorList.h>
#include <ripple/app/misc/ValidatorSite.h>
#include <ripple/app/rdb/RelationalDBInterface.h>
#include <ripple/app/rdb/RelationalDBInterface_global.h>
#include <ripple/app/rdb/RelationalDatabase.h>
#include <ripple/app/rdb/Wallet.h>
#include <ripple/basics/base64.h>
#include <ripple/basics/make_SSLContext.h>
#include <ripple/basics/random.h>

View File

@@ -19,8 +19,8 @@
#include <ripple/overlay/PeerReservationTable.h>
#include <ripple/app/rdb/RelationalDBInterface.h>
#include <ripple/app/rdb/RelationalDBInterface_global.h>
#include <ripple/app/rdb/RelationalDatabase.h>
#include <ripple/app/rdb/Wallet.h>
#include <ripple/basics/Log.h>
#include <ripple/json/json_value.h>
#include <ripple/protocol/PublicKey.h>

View File

@@ -20,7 +20,7 @@
#ifndef RIPPLE_PEERFINDER_STORESQDB_H_INCLUDED
#define RIPPLE_PEERFINDER_STORESQDB_H_INCLUDED
#include <ripple/app/rdb/RelationalDBInterface_global.h>
#include <ripple/app/rdb/PeerFinder.h>
#include <ripple/basics/contract.h>
#include <ripple/core/SociDB.h>
#include <ripple/peerfinder/impl/Store.h>

View File

@@ -21,8 +21,8 @@
#include <ripple/app/main/Application.h>
#include <ripple/app/misc/NetworkOPs.h>
#include <ripple/app/misc/Transaction.h>
#include <ripple/app/rdb/backend/RelationalDBInterfacePostgres.h>
#include <ripple/app/rdb/backend/RelationalDBInterfaceSqlite.h>
#include <ripple/app/rdb/backend/PostgresDatabase.h>
#include <ripple/app/rdb/backend/SQLiteDatabase.h>
#include <ripple/core/Pg.h>
#include <ripple/json/json_reader.h>
#include <ripple/json/json_value.h>
@@ -42,14 +42,14 @@
namespace ripple {
using TxnsData = RelationalDBInterface::AccountTxs;
using TxnsDataBinary = RelationalDBInterface::MetaTxsList;
using TxnDataBinary = RelationalDBInterface::txnMetaLedgerType;
using AccountTxArgs = RelationalDBInterface::AccountTxArgs;
using AccountTxResult = RelationalDBInterface::AccountTxResult;
using TxnsData = RelationalDatabase::AccountTxs;
using TxnsDataBinary = RelationalDatabase::MetaTxsList;
using TxnDataBinary = RelationalDatabase::txnMetaLedgerType;
using AccountTxArgs = RelationalDatabase::AccountTxArgs;
using AccountTxResult = RelationalDatabase::AccountTxResult;
using LedgerShortcut = RelationalDBInterface::LedgerShortcut;
using LedgerSpecifier = RelationalDBInterface::LedgerSpecifier;
using LedgerShortcut = RelationalDatabase::LedgerShortcut;
using LedgerSpecifier = RelationalDatabase::LedgerSpecifier;
// parses args into a ledger specifier, or returns a grpc status object on error
std::variant<std::optional<LedgerSpecifier>, grpc::Status>
@@ -257,9 +257,15 @@ doAccountTxHelp(RPC::Context& context, AccountTxArgs const& args)
{
context.loadType = Resource::feeMediumBurdenRPC;
if (context.app.config().reporting())
return dynamic_cast<RelationalDBInterfacePostgres*>(
&context.app.getRelationalDBInterface())
->getAccountTx(args);
{
auto const db = dynamic_cast<PostgresDatabase*>(
&context.app.getRelationalDatabase());
if (!db)
Throw<std::runtime_error>("Failed to get relational database");
return db->getAccountTx(args);
}
AccountTxResult result;
@@ -274,7 +280,7 @@ doAccountTxHelp(RPC::Context& context, AccountTxArgs const& args)
result.marker = args.marker;
RelationalDBInterface::AccountTxPageOptions options = {
RelationalDatabase::AccountTxPageOptions options = {
args.account,
result.ledgerRange.min,
result.ledgerRange.max,
@@ -282,21 +288,23 @@ doAccountTxHelp(RPC::Context& context, AccountTxArgs const& args)
args.limit,
isUnlimited(context.role)};
auto const db =
dynamic_cast<SQLiteDatabase*>(&context.app.getRelationalDatabase());
if (!db)
Throw<std::runtime_error>("Failed to get relational database");
if (args.binary)
{
if (args.forward)
{
auto [tx, marker] = dynamic_cast<RelationalDBInterfaceSqlite*>(
&context.app.getRelationalDBInterface())
->oldestAccountTxPageB(options);
auto [tx, marker] = db->oldestAccountTxPageB(options);
result.transactions = tx;
result.marker = marker;
}
else
{
auto [tx, marker] = dynamic_cast<RelationalDBInterfaceSqlite*>(
&context.app.getRelationalDBInterface())
->newestAccountTxPageB(options);
auto [tx, marker] = db->newestAccountTxPageB(options);
result.transactions = tx;
result.marker = marker;
}
@@ -305,17 +313,13 @@ doAccountTxHelp(RPC::Context& context, AccountTxArgs const& args)
{
if (args.forward)
{
auto [tx, marker] = dynamic_cast<RelationalDBInterfaceSqlite*>(
&context.app.getRelationalDBInterface())
->oldestAccountTxPage(options);
auto [tx, marker] = db->oldestAccountTxPage(options);
result.transactions = tx;
result.marker = marker;
}
else
{
auto [tx, marker] = dynamic_cast<RelationalDBInterfaceSqlite*>(
&context.app.getRelationalDBInterface())
->newestAccountTxPage(options);
auto [tx, marker] = db->newestAccountTxPage(options);
result.transactions = tx;
result.marker = marker;
}

View File

@@ -21,7 +21,7 @@
#include <ripple/app/main/Application.h>
#include <ripple/app/misc/NetworkOPs.h>
#include <ripple/app/misc/Transaction.h>
#include <ripple/app/rdb/backend/RelationalDBInterfaceSqlite.h>
#include <ripple/app/rdb/backend/SQLiteDatabase.h>
#include <ripple/ledger/ReadView.h>
#include <ripple/net/RPCErr.h>
#include <ripple/protocol/ErrorCodes.h>
@@ -152,7 +152,7 @@ doAccountTxOld(RPC::JsonContext& context)
ret[jss::account] = context.app.accountIDCache().toBase58(*raAccount);
Json::Value& jvTxns = (ret[jss::transactions] = Json::arrayValue);
RelationalDBInterface::AccountTxOptions options = {
RelationalDatabase::AccountTxOptions options = {
*raAccount,
uLedgerMin,
uLedgerMax,
@@ -162,15 +162,15 @@ doAccountTxOld(RPC::JsonContext& context)
if (bBinary)
{
std::vector<RelationalDBInterface::txnMetaLedgerType> txns;
std::vector<RelationalDatabase::txnMetaLedgerType> txns;
if (bDescending)
txns = dynamic_cast<RelationalDBInterfaceSqlite*>(
&context.app.getRelationalDBInterface())
txns = dynamic_cast<SQLiteDatabase*>(
&context.app.getRelationalDatabase())
->getNewestAccountTxsB(options);
else
txns = dynamic_cast<RelationalDBInterfaceSqlite*>(
&context.app.getRelationalDBInterface())
txns = dynamic_cast<SQLiteDatabase*>(
&context.app.getRelationalDatabase())
->getOldestAccountTxsB(options);
for (auto it = txns.begin(), end = txns.end(); it != end; ++it)
@@ -189,15 +189,15 @@ doAccountTxOld(RPC::JsonContext& context)
}
else
{
RelationalDBInterface::AccountTxs txns;
RelationalDatabase::AccountTxs txns;
if (bDescending)
txns = dynamic_cast<RelationalDBInterfaceSqlite*>(
&context.app.getRelationalDBInterface())
txns = dynamic_cast<SQLiteDatabase*>(
&context.app.getRelationalDatabase())
->getNewestAccountTxs(options);
else
txns = dynamic_cast<RelationalDBInterfaceSqlite*>(
&context.app.getRelationalDBInterface())
txns = dynamic_cast<SQLiteDatabase*>(
&context.app.getRelationalDatabase())
->getOldestAccountTxs(options);
for (auto it = txns.begin(), end = txns.end(); it != end; ++it)

View File

@@ -22,7 +22,7 @@
#include <ripple/app/ledger/LedgerMaster.h>
#include <ripple/app/main/Application.h>
#include <ripple/app/misc/NetworkOPs.h>
#include <ripple/app/rdb/backend/RelationalDBInterfaceSqlite.h>
#include <ripple/app/rdb/backend/SQLiteDatabase.h>
#include <ripple/basics/UptimeClock.h>
#include <ripple/json/json_value.h>
#include <ripple/ledger/CachedSLEs.h>
@@ -75,23 +75,23 @@ getCountsJson(Application& app, int minObjectCount)
if (!app.config().reporting() && app.config().useTxTables())
{
auto dbKB = dynamic_cast<RelationalDBInterfaceSqlite*>(
&app.getRelationalDBInterface())
->getKBUsedAll();
auto const db =
dynamic_cast<SQLiteDatabase*>(&app.getRelationalDatabase());
if (!db)
Throw<std::runtime_error>("Failed to get relational database");
auto dbKB = db->getKBUsedAll();
if (dbKB > 0)
ret[jss::dbKBTotal] = dbKB;
dbKB = dynamic_cast<RelationalDBInterfaceSqlite*>(
&app.getRelationalDBInterface())
->getKBUsedLedger();
dbKB = db->getKBUsedLedger();
if (dbKB > 0)
ret[jss::dbKBLedger] = dbKB;
dbKB = dynamic_cast<RelationalDBInterfaceSqlite*>(
&app.getRelationalDBInterface())
->getKBUsedTransaction();
dbKB = db->getKBUsedTransaction();
if (dbKB > 0)
ret[jss::dbKBTransaction] = dbKB;

View File

@@ -20,7 +20,7 @@
#include <ripple/app/ledger/LedgerMaster.h>
#include <ripple/app/main/Application.h>
#include <ripple/app/misc/Transaction.h>
#include <ripple/app/rdb/RelationalDBInterface.h>
#include <ripple/app/rdb/RelationalDatabase.h>
#include <ripple/core/DatabaseCon.h>
#include <ripple/core/Pg.h>
#include <ripple/core/SociDB.h>
@@ -54,8 +54,7 @@ doTxHistory(RPC::JsonContext& context)
if ((startIndex > 10000) && (!isUnlimited(context.role)))
return rpcError(rpcNO_PERMISSION);
auto trans =
context.app.getRelationalDBInterface().getTxHistory(startIndex);
auto trans = context.app.getRelationalDatabase().getTxHistory(startIndex);
Json::Value obj;
Json::Value& txs = obj[jss::txs];

View File

@@ -21,7 +21,7 @@
#include <ripple/app/ledger/OpenLedger.h>
#include <ripple/app/misc/Transaction.h>
#include <ripple/app/paths/TrustLine.h>
#include <ripple/app/rdb/RelationalDBInterface.h>
#include <ripple/app/rdb/RelationalDatabase.h>
#include <ripple/ledger/View.h>
#include <ripple/net/RPCErr.h>
#include <ripple/protocol/AccountID.h>
@@ -537,7 +537,7 @@ isValidated(
{
assert(hash->isNonZero());
uint256 valHash =
app.getRelationalDBInterface().getHashByIndex(seq);
app.getRelationalDatabase().getHashByIndex(seq);
if (valHash == ledger.info().hash)
{
// SQL database doesn't match ledger chain

View File

@@ -18,7 +18,7 @@
//==============================================================================
#include <ripple/app/misc/NetworkOPs.h>
#include <ripple/app/rdb/RelationalDBInterface_shards.h>
#include <ripple/app/rdb/ShardArchive.h>
#include <ripple/basics/Archive.h>
#include <ripple/basics/BasicConfig.h>
#include <ripple/core/ConfigSections.h>

View File

@@ -20,7 +20,7 @@
#include <ripple/app/main/DBInit.h>
#include <ripple/app/misc/Manifest.h>
#include <ripple/app/misc/ValidatorList.h>
#include <ripple/app/rdb/RelationalDBInterface_global.h>
#include <ripple/app/rdb/Wallet.h>
#include <ripple/basics/StringUtilities.h>
#include <ripple/basics/base64.h>
#include <ripple/basics/contract.h>

View File

@@ -19,7 +19,7 @@
#include <ripple/app/main/Application.h>
#include <ripple/app/misc/SHAMapStore.h>
#include <ripple/app/rdb/backend/RelationalDBInterfaceSqlite.h>
#include <ripple/app/rdb/backend/SQLiteDatabase.h>
#include <ripple/core/ConfigSections.h>
#include <ripple/protocol/jss.h>
#include <test/jtx.h>
@@ -65,7 +65,7 @@ class SHAMapStore_test : public beast::unit_test::suite
auto const seq = json[jss::result][jss::ledger_index].asUInt();
std::optional<LedgerInfo> oinfo =
env.app().getRelationalDBInterface().getLedgerInfoByIndex(seq);
env.app().getRelationalDatabase().getLedgerInfoByIndex(seq);
if (!oinfo)
return false;
const LedgerInfo& info = oinfo.value();
@@ -120,8 +120,7 @@ class SHAMapStore_test : public beast::unit_test::suite
ledgerCheck(jtx::Env& env, int const rows, int const first)
{
const auto [actualRows, actualFirst, actualLast] =
dynamic_cast<RelationalDBInterfaceSqlite*>(
&env.app().getRelationalDBInterface())
dynamic_cast<SQLiteDatabase*>(&env.app().getRelationalDatabase())
->getLedgerCountMinMax();
BEAST_EXPECT(actualRows == rows);
@@ -133,8 +132,7 @@ class SHAMapStore_test : public beast::unit_test::suite
transactionCheck(jtx::Env& env, int const rows)
{
BEAST_EXPECT(
dynamic_cast<RelationalDBInterfaceSqlite*>(
&env.app().getRelationalDBInterface())
dynamic_cast<SQLiteDatabase*>(&env.app().getRelationalDatabase())
->getTransactionCount() == rows);
}
@@ -142,8 +140,7 @@ class SHAMapStore_test : public beast::unit_test::suite
accountTransactionCheck(jtx::Env& env, int const rows)
{
BEAST_EXPECT(
dynamic_cast<RelationalDBInterfaceSqlite*>(
&env.app().getRelationalDBInterface())
dynamic_cast<SQLiteDatabase*>(&env.app().getRelationalDatabase())
->getAccountTransactionCount() == rows);
}

View File

@@ -21,7 +21,7 @@
#include <ripple/app/ledger/LedgerToJson.h>
#include <ripple/app/misc/LoadFeeTrack.h>
#include <ripple/app/misc/SHAMapStore.h>
#include <ripple/app/rdb/backend/RelationalDBInterfaceSqlite.h>
#include <ripple/app/rdb/backend/SQLiteDatabase.h>
#include <ripple/basics/Slice.h>
#include <ripple/basics/random.h>
#include <ripple/beast/hash/hash_append.h>
@@ -1762,9 +1762,9 @@ class DatabaseShard_test : public TestBase
}
void
testRelationalDBInterfaceSqlite(std::uint64_t const seedValue)
testSQLiteDatabase(std::uint64_t const seedValue)
{
testcase("Relational DB Interface SQLite");
testcase("SQLite Database");
using namespace test::jtx;
@@ -1782,8 +1782,8 @@ class DatabaseShard_test : public TestBase
BEAST_EXPECT(shardStore->getShardInfo()->finalized().empty());
BEAST_EXPECT(shardStore->getShardInfo()->incompleteToString().empty());
auto rdb = dynamic_cast<RelationalDBInterfaceSqlite*>(
&env.app().getRelationalDBInterface());
auto rdb =
dynamic_cast<SQLiteDatabase*>(&env.app().getRelationalDatabase());
BEAST_EXPECT(rdb);
@@ -1796,7 +1796,7 @@ class DatabaseShard_test : public TestBase
return;
}
// Close these databases to force the RelationalDBInterfaceSqlite
// Close these databases to force the SQLiteDatabase
// to use the shard databases and lookup tables.
rdb->closeLedgerDB();
rdb->closeTransactionDB();
@@ -1814,7 +1814,7 @@ class DatabaseShard_test : public TestBase
for (auto const& ledger : data.ledgers_)
{
// Compare each test ledger to the data retrieved
// from the RelationalDBInterfaceSqlite class
// from the SQLiteDatabase class
if (shardStore->seqToShardIndex(ledger->seq()) <
shardStore->earliestShardIndex() ||
@@ -1829,8 +1829,7 @@ class DatabaseShard_test : public TestBase
for (auto const& transaction : ledger->txs)
{
// Compare each test transaction to the data
// retrieved from the RelationalDBInterfaceSqlite
// class
// retrieved from the SQLiteDatabase class
error_code_i error{rpcSUCCESS};
@@ -1885,7 +1884,7 @@ public:
testPrepareWithHistoricalPaths(seedValue());
testOpenShardManagement(seedValue());
testShardInfo(seedValue());
testRelationalDBInterfaceSqlite(seedValue());
testSQLiteDatabase(seedValue());
}
};

View File

@@ -17,7 +17,7 @@
*/
//==============================================================================
#include <ripple/app/rdb/RelationalDBInterface_shards.h>
#include <ripple/app/rdb/ShardArchive.h>
#include <ripple/beast/utility/temp_dir.h>
#include <ripple/core/ConfigSections.h>
#include <ripple/nodestore/DummyScheduler.h>

View File

@@ -17,7 +17,7 @@
*/
//==============================================================================
#include <ripple/app/rdb/backend/RelationalDBInterfaceSqlite.h>
#include <ripple/app/rdb/backend/SQLiteDatabase.h>
#include <ripple/protocol/ErrorCodes.h>
#include <ripple/protocol/jss.h>
#include <test/jtx.h>
@@ -119,8 +119,7 @@ class Transaction_test : public beast::unit_test::suite
const auto deletedLedger = (startLegSeq + endLegSeq) / 2;
{
// Remove one of the ledgers from the database directly
dynamic_cast<RelationalDBInterfaceSqlite*>(
&env.app().getRelationalDBInterface())
dynamic_cast<SQLiteDatabase*>(&env.app().getRelationalDatabase())
->deleteTransactionByLedgerSeq(deletedLedger);
}

View File

@@ -19,7 +19,7 @@
#include <ripple/app/ledger/LedgerMaster.h>
#include <ripple/app/misc/TxQ.h>
#include <ripple/app/rdb/backend/RelationalDBInterfaceSqlite.h>
#include <ripple/app/rdb/backend/SQLiteDatabase.h>
#include <ripple/basics/mulDiv.h>
#include <ripple/protocol/ErrorCodes.h>
#include <ripple/protocol/jss.h>
@@ -769,8 +769,7 @@ class Tx_test : public beast::unit_test::suite
const auto deletedLedger = (startLegSeq + endLegSeq) / 2;
{
// Remove one of the ledgers from the database directly
dynamic_cast<RelationalDBInterfaceSqlite*>(
&env.app().getRelationalDBInterface())
dynamic_cast<SQLiteDatabase*>(&env.app().getRelationalDatabase())
->deleteTransactionByLedgerSeq(deletedLedger);
}