mirror of
https://github.com/Xahau/xahaud.git
synced 2025-11-30 15:35:49 +00:00
Add Shard Family
This commit is contained in:
committed by
manojsdoshi
parent
91e857874f
commit
86e8f2e232
@@ -637,12 +637,14 @@ target_sources (rippled PRIVATE
|
||||
main sources:
|
||||
subdir: shamap
|
||||
#]===============================]
|
||||
src/ripple/shamap/impl/NodeFamily.cpp
|
||||
src/ripple/shamap/impl/SHAMap.cpp
|
||||
src/ripple/shamap/impl/SHAMapDelta.cpp
|
||||
src/ripple/shamap/impl/SHAMapItem.cpp
|
||||
src/ripple/shamap/impl/SHAMapNodeID.cpp
|
||||
src/ripple/shamap/impl/SHAMapSync.cpp
|
||||
src/ripple/shamap/impl/SHAMapTreeNode.cpp
|
||||
src/ripple/shamap/impl/ShardFamily.cpp
|
||||
#[===============================[
|
||||
test sources:
|
||||
subdir: app
|
||||
|
||||
@@ -300,7 +300,7 @@ RCLConsensus::Adaptor::onClose(
|
||||
auto initialLedger = app_.openLedger().current();
|
||||
|
||||
auto initialSet =
|
||||
std::make_shared<SHAMap>(SHAMapType::TRANSACTION, app_.family());
|
||||
std::make_shared<SHAMap>(SHAMapType::TRANSACTION, app_.getNodeFamily());
|
||||
initialSet->setUnbacked();
|
||||
|
||||
// Build SHAMap containing all transactions in our open ledger
|
||||
|
||||
@@ -248,7 +248,7 @@ Ledger::Ledger(
|
||||
{
|
||||
info_.hash = calculateLedgerHash(info_);
|
||||
if (acquire)
|
||||
family.missing_node(info_.hash, info_.seq);
|
||||
family.missingNode(info_.hash, info_.seq);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1077,7 +1077,7 @@ loadLedgerHelper(std::string const& sqlSuffix, Application& app, bool acquire)
|
||||
loaded,
|
||||
acquire,
|
||||
app.config(),
|
||||
app.family(),
|
||||
app.getNodeFamily(),
|
||||
app.journal("Ledger"));
|
||||
|
||||
if (!loaded)
|
||||
|
||||
@@ -98,7 +98,7 @@ InboundLedger::init(ScopedLockType& collectionLock)
|
||||
ScopedLockType sl(mLock);
|
||||
collectionLock.unlock();
|
||||
|
||||
tryDB(app_.family().db());
|
||||
tryDB(app_.getNodeFamily().db());
|
||||
if (mFailed)
|
||||
return;
|
||||
|
||||
@@ -107,7 +107,7 @@ InboundLedger::init(ScopedLockType& collectionLock)
|
||||
auto shardStore = app_.getShardStore();
|
||||
if (mReason == Reason::SHARD)
|
||||
{
|
||||
if (!shardStore || !app_.shardFamily())
|
||||
if (!shardStore)
|
||||
{
|
||||
JLOG(m_journal.error())
|
||||
<< "Acquiring shard with no shard store available";
|
||||
@@ -120,7 +120,7 @@ InboundLedger::init(ScopedLockType& collectionLock)
|
||||
mHaveState = false;
|
||||
mLedger.reset();
|
||||
|
||||
tryDB(app_.shardFamily()->db());
|
||||
tryDB(app_.getShardFamily()->db());
|
||||
if (mFailed)
|
||||
return;
|
||||
}
|
||||
@@ -203,9 +203,9 @@ InboundLedger::checkLocal()
|
||||
if (mLedger)
|
||||
tryDB(mLedger->stateMap().family().db());
|
||||
else if (mReason == Reason::SHARD)
|
||||
tryDB(app_.shardFamily()->db());
|
||||
tryDB(app_.getShardFamily()->db());
|
||||
else
|
||||
tryDB(app_.family().db());
|
||||
tryDB(app_.getNodeFamily().db());
|
||||
if (mFailed || mComplete)
|
||||
{
|
||||
done();
|
||||
@@ -306,8 +306,8 @@ InboundLedger::tryDB(NodeStore::Database& srcDB)
|
||||
mLedger = std::make_shared<Ledger>(
|
||||
deserializePrefixedHeader(makeSlice(data)),
|
||||
app_.config(),
|
||||
mReason == Reason::SHARD ? *app_.shardFamily()
|
||||
: app_.family());
|
||||
mReason == Reason::SHARD ? *app_.getShardFamily()
|
||||
: app_.getNodeFamily());
|
||||
if (mLedger->info().hash != mHash ||
|
||||
(mSeq != 0 && mSeq != mLedger->info().seq))
|
||||
{
|
||||
@@ -564,8 +564,8 @@ InboundLedger::trigger(std::shared_ptr<Peer> const& peer, TriggerReason reason)
|
||||
if (!mHaveHeader)
|
||||
{
|
||||
tryDB(
|
||||
mReason == Reason::SHARD ? app_.shardFamily()->db()
|
||||
: app_.family().db());
|
||||
mReason == Reason::SHARD ? app_.getShardFamily()->db()
|
||||
: app_.getNodeFamily().db());
|
||||
if (mFailed)
|
||||
{
|
||||
JLOG(m_journal.warn()) << " failed local for " << mHash;
|
||||
@@ -866,7 +866,8 @@ InboundLedger::takeHeader(std::string const& data)
|
||||
if (mComplete || mFailed || mHaveHeader)
|
||||
return true;
|
||||
|
||||
auto* f = mReason == Reason::SHARD ? app_.shardFamily() : &app_.family();
|
||||
auto* f = mReason == Reason::SHARD ? app_.getShardFamily()
|
||||
: &app_.getNodeFamily();
|
||||
mLedger = std::make_shared<Ledger>(
|
||||
deserializeHeader(makeSlice(data)), app_.config(), *f);
|
||||
if (mLedger->info().hash != mHash ||
|
||||
|
||||
@@ -75,7 +75,7 @@ public:
|
||||
, m_gotSet(std::move(gotSet))
|
||||
{
|
||||
m_zeroSet.mSet = std::make_shared<SHAMap>(
|
||||
SHAMapType::TRANSACTION, uint256(), app_.family());
|
||||
SHAMapType::TRANSACTION, uint256(), app_.getNodeFamily());
|
||||
m_zeroSet.mSet->setUnbacked();
|
||||
}
|
||||
|
||||
|
||||
@@ -735,18 +735,19 @@ LedgerMaster::tryFill(Job& job, std::shared_ptr<Ledger const> ledger)
|
||||
void
|
||||
LedgerMaster::getFetchPack(LedgerIndex missing, InboundLedger::Reason reason)
|
||||
{
|
||||
LedgerIndex ledgerIndex{missing + 1};
|
||||
if (reason == InboundLedger::Reason::SHARD)
|
||||
{
|
||||
// Do not acquire a ledger sequence greater
|
||||
// than the last ledger in the shard
|
||||
auto const shardStore{app_.getShardStore()};
|
||||
auto const shardIndex{shardStore->seqToShardIndex(missing)};
|
||||
ledgerIndex =
|
||||
std::min(ledgerIndex, shardStore->lastLedgerSeq(shardIndex));
|
||||
}
|
||||
LedgerIndex const ledgerIndex([&]() {
|
||||
if (reason == InboundLedger::Reason::SHARD)
|
||||
{
|
||||
// Do not acquire a ledger sequence greater
|
||||
// than the last ledger in the shard
|
||||
auto const shardStore{app_.getShardStore()};
|
||||
auto const shardIndex{shardStore->seqToShardIndex(missing)};
|
||||
return std::min(missing + 1, shardStore->lastLedgerSeq(shardIndex));
|
||||
}
|
||||
return missing + 1;
|
||||
}());
|
||||
|
||||
auto haveHash{getLedgerHashForHistory(ledgerIndex, reason)};
|
||||
auto const haveHash{getLedgerHashForHistory(ledgerIndex, reason)};
|
||||
if (!haveHash || haveHash->isZero())
|
||||
{
|
||||
if (reason == InboundLedger::Reason::SHARD)
|
||||
|
||||
@@ -43,8 +43,8 @@ TransactionAcquire::TransactionAcquire(Application& app, uint256 const& hash)
|
||||
: PeerSet(app, hash, TX_ACQUIRE_TIMEOUT, app.journal("TransactionAcquire"))
|
||||
, mHaveRoot(false)
|
||||
{
|
||||
mMap =
|
||||
std::make_shared<SHAMap>(SHAMapType::TRANSACTION, hash, app_.family());
|
||||
mMap = std::make_shared<SHAMap>(
|
||||
SHAMapType::TRANSACTION, hash, app_.getNodeFamily());
|
||||
mMap->setUnbacked();
|
||||
}
|
||||
|
||||
|
||||
@@ -29,10 +29,10 @@
|
||||
#include <ripple/app/main/Application.h>
|
||||
#include <ripple/app/main/BasicApp.h>
|
||||
#include <ripple/app/main/DBInit.h>
|
||||
#include <ripple/app/main/GRPCServer.h>
|
||||
#include <ripple/app/main/LoadManager.h>
|
||||
#include <ripple/app/main/NodeIdentity.h>
|
||||
#include <ripple/app/main/NodeStoreScheduler.h>
|
||||
#include <ripple/app/main/Tuning.h>
|
||||
#include <ripple/app/misc/AmendmentTable.h>
|
||||
#include <ripple/app/misc/HashRouter.h>
|
||||
#include <ripple/app/misc/LoadFeeTrack.h>
|
||||
@@ -64,8 +64,9 @@
|
||||
#include <ripple/resource/Fees.h>
|
||||
#include <ripple/rpc/ShardArchiveHandler.h>
|
||||
#include <ripple/rpc/impl/RPCHelpers.h>
|
||||
#include <ripple/shamap/NodeFamily.h>
|
||||
#include <ripple/shamap/ShardFamily.h>
|
||||
|
||||
#include <ripple/app/main/GRPCServer.h>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
@@ -77,174 +78,6 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace detail {
|
||||
|
||||
class AppFamily : public Family
|
||||
{
|
||||
private:
|
||||
Application& app_;
|
||||
TreeNodeCache treecache_;
|
||||
FullBelowCache fullbelow_;
|
||||
NodeStore::Database& db_;
|
||||
bool const shardBacked_;
|
||||
beast::Journal const j_;
|
||||
|
||||
// missing node handler
|
||||
LedgerIndex maxSeq = 0;
|
||||
std::mutex maxSeqLock;
|
||||
|
||||
void
|
||||
acquire(uint256 const& hash, std::uint32_t seq)
|
||||
{
|
||||
if (hash.isNonZero())
|
||||
{
|
||||
auto j = app_.journal("Ledger");
|
||||
|
||||
JLOG(j.error()) << "Missing node in " << to_string(hash);
|
||||
|
||||
app_.getInboundLedgers().acquire(
|
||||
hash,
|
||||
seq,
|
||||
shardBacked_ ? InboundLedger::Reason::SHARD
|
||||
: InboundLedger::Reason::GENERIC);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
AppFamily(AppFamily const&) = delete;
|
||||
AppFamily&
|
||||
operator=(AppFamily const&) = delete;
|
||||
|
||||
AppFamily(
|
||||
Application& app,
|
||||
NodeStore::Database& db,
|
||||
CollectorManager& collectorManager)
|
||||
: app_(app)
|
||||
, treecache_(
|
||||
"TreeNodeCache",
|
||||
65536,
|
||||
std::chrono::minutes{1},
|
||||
stopwatch(),
|
||||
app.journal("TaggedCache"))
|
||||
, fullbelow_(
|
||||
"full_below",
|
||||
stopwatch(),
|
||||
collectorManager.collector(),
|
||||
fullBelowTargetSize,
|
||||
fullBelowExpiration)
|
||||
, db_(db)
|
||||
, shardBacked_(dynamic_cast<NodeStore::DatabaseShard*>(&db) != nullptr)
|
||||
, j_(app.journal("SHAMap"))
|
||||
{
|
||||
}
|
||||
|
||||
beast::Journal const&
|
||||
journal() override
|
||||
{
|
||||
return j_;
|
||||
}
|
||||
|
||||
FullBelowCache&
|
||||
fullbelow() override
|
||||
{
|
||||
return fullbelow_;
|
||||
}
|
||||
|
||||
FullBelowCache const&
|
||||
fullbelow() const override
|
||||
{
|
||||
return fullbelow_;
|
||||
}
|
||||
|
||||
TreeNodeCache&
|
||||
treecache() override
|
||||
{
|
||||
return treecache_;
|
||||
}
|
||||
|
||||
TreeNodeCache const&
|
||||
treecache() const override
|
||||
{
|
||||
return treecache_;
|
||||
}
|
||||
|
||||
NodeStore::Database&
|
||||
db() override
|
||||
{
|
||||
return db_;
|
||||
}
|
||||
|
||||
NodeStore::Database const&
|
||||
db() const override
|
||||
{
|
||||
return db_;
|
||||
}
|
||||
|
||||
bool
|
||||
isShardBacked() const override
|
||||
{
|
||||
return shardBacked_;
|
||||
}
|
||||
|
||||
void
|
||||
missing_node(std::uint32_t seq) override
|
||||
{
|
||||
auto j = app_.journal("Ledger");
|
||||
|
||||
JLOG(j.error()) << "Missing node in " << seq;
|
||||
|
||||
// prevent recursive invocation
|
||||
std::unique_lock<std::mutex> lock(maxSeqLock);
|
||||
|
||||
if (maxSeq == 0)
|
||||
{
|
||||
maxSeq = seq;
|
||||
|
||||
do
|
||||
{
|
||||
// Try to acquire the most recent missing ledger
|
||||
seq = maxSeq;
|
||||
|
||||
lock.unlock();
|
||||
|
||||
// This can invoke the missing node handler
|
||||
acquire(app_.getLedgerMaster().getHashBySeq(seq), seq);
|
||||
|
||||
lock.lock();
|
||||
} while (maxSeq != seq);
|
||||
}
|
||||
else if (maxSeq < seq)
|
||||
{
|
||||
// We found a more recent ledger with a
|
||||
// missing node
|
||||
maxSeq = seq;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
missing_node(uint256 const& hash, std::uint32_t seq) override
|
||||
{
|
||||
acquire(hash, seq);
|
||||
}
|
||||
|
||||
void
|
||||
reset() override
|
||||
{
|
||||
{
|
||||
std::lock_guard lock(maxSeqLock);
|
||||
maxSeq = 0;
|
||||
}
|
||||
fullbelow_.reset();
|
||||
treecache_.reset();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// VFALCO TODO Move the function definitions into the class declaration
|
||||
class ApplicationImp : public Application, public RootStoppable, public BasicApp
|
||||
{
|
||||
@@ -343,9 +176,9 @@ public:
|
||||
// These are Stoppable-related
|
||||
std::unique_ptr<JobQueue> m_jobQueue;
|
||||
std::unique_ptr<NodeStore::Database> m_nodeStore;
|
||||
detail::AppFamily family_;
|
||||
NodeFamily nodeFamily_;
|
||||
std::unique_ptr<NodeStore::DatabaseShard> shardStore_;
|
||||
std::unique_ptr<detail::AppFamily> shardFamily_;
|
||||
std::unique_ptr<ShardFamily> shardFamily_;
|
||||
std::unique_ptr<RPC::ShardArchiveHandler> shardArchiveHandler_;
|
||||
// VFALCO TODO Make OrderBookDB abstract
|
||||
OrderBookDB m_orderBookDB;
|
||||
@@ -476,7 +309,7 @@ public:
|
||||
|
||||
, m_nodeStore(m_shaMapStore->makeNodeStore("NodeStore.main", 4))
|
||||
|
||||
, family_(*this, *m_nodeStore, *m_collectorManager)
|
||||
, nodeFamily_(*this, *m_collectorManager)
|
||||
|
||||
// The shard store is optional and make_ShardStore can return null.
|
||||
, shardStore_(make_ShardStore(
|
||||
@@ -671,13 +504,15 @@ public:
|
||||
}
|
||||
|
||||
Family&
|
||||
family() override
|
||||
getNodeFamily() override
|
||||
{
|
||||
return family_;
|
||||
return nodeFamily_;
|
||||
}
|
||||
|
||||
// The shard store is an optional feature. If the sever is configured for
|
||||
// shards, this function will return a valid pointer, otherwise a nullptr.
|
||||
Family*
|
||||
shardFamily() override
|
||||
getShardFamily() override
|
||||
{
|
||||
return shardFamily_.get();
|
||||
}
|
||||
@@ -779,6 +614,8 @@ public:
|
||||
return *m_nodeStore;
|
||||
}
|
||||
|
||||
// The shard store is an optional feature. If the sever is configured for
|
||||
// shards, this function will return a valid pointer, otherwise a nullptr.
|
||||
NodeStore::DatabaseShard*
|
||||
getShardStore() override
|
||||
{
|
||||
@@ -1127,11 +964,6 @@ public:
|
||||
config_->getValueFor(SizedItem::ledgerSize),
|
||||
seconds{config_->getValueFor(SizedItem::ledgerAge)});
|
||||
|
||||
family().treecache().setTargetSize(
|
||||
config_->getValueFor(SizedItem::treeCacheSize));
|
||||
family().treecache().setTargetAge(
|
||||
seconds{config_->getValueFor(SizedItem::treeCacheAge)});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1372,9 +1204,9 @@ public:
|
||||
// VFALCO TODO fix the dependency inversion using an observer,
|
||||
// have listeners register for "onSweep ()" notification.
|
||||
|
||||
family().fullbelow().sweep();
|
||||
nodeFamily_.sweep();
|
||||
if (shardFamily_)
|
||||
shardFamily_->fullbelow().sweep();
|
||||
shardFamily_->sweep();
|
||||
getMasterTransaction().sweep();
|
||||
getNodeStore().sweep();
|
||||
if (shardStore_)
|
||||
@@ -1384,9 +1216,6 @@ public:
|
||||
getValidations().expire();
|
||||
getInboundLedgers().sweep();
|
||||
m_acceptedLedgerCache.sweep();
|
||||
family().treecache().sweep();
|
||||
if (shardFamily_)
|
||||
shardFamily_->treecache().sweep();
|
||||
cachedSLEs_.expire();
|
||||
|
||||
// Set timer to do another sweep later.
|
||||
@@ -1491,14 +1320,8 @@ ApplicationImp::setup()
|
||||
|
||||
if (shardStore_)
|
||||
{
|
||||
shardFamily_ = std::make_unique<detail::AppFamily>(
|
||||
*this, *shardStore_, *m_collectorManager);
|
||||
|
||||
using namespace std::chrono;
|
||||
shardFamily_->treecache().setTargetSize(
|
||||
config_->getValueFor(SizedItem::treeCacheSize));
|
||||
shardFamily_->treecache().setTargetAge(
|
||||
seconds{config_->getValueFor(SizedItem::treeCacheAge)});
|
||||
shardFamily_ =
|
||||
std::make_unique<ShardFamily>(*this, *m_collectorManager);
|
||||
|
||||
if (!shardStore_->init())
|
||||
return false;
|
||||
@@ -1906,7 +1729,7 @@ ApplicationImp::startGenesisLedger()
|
||||
: std::vector<uint256>{};
|
||||
|
||||
std::shared_ptr<Ledger> const genesis = std::make_shared<Ledger>(
|
||||
create_genesis, *config_, initialAmendments, family());
|
||||
create_genesis, *config_, initialAmendments, nodeFamily_);
|
||||
m_ledgerMaster->storeLedger(genesis);
|
||||
|
||||
auto const next =
|
||||
@@ -2037,7 +1860,7 @@ ApplicationImp::loadLedgerFromFile(std::string const& name)
|
||||
}
|
||||
|
||||
auto loadLedger =
|
||||
std::make_shared<Ledger>(seq, closeTime, *config_, family());
|
||||
std::make_shared<Ledger>(seq, closeTime, *config_, nodeFamily_);
|
||||
loadLedger->setTotalDrops(totalDrops);
|
||||
|
||||
for (Json::UInt index = 0; index < ledger.get().size(); ++index)
|
||||
|
||||
@@ -147,9 +147,9 @@ public:
|
||||
virtual CollectorManager&
|
||||
getCollectorManager() = 0;
|
||||
virtual Family&
|
||||
family() = 0;
|
||||
getNodeFamily() = 0;
|
||||
virtual Family*
|
||||
shardFamily() = 0;
|
||||
getShardFamily() = 0;
|
||||
virtual TimeKeeper&
|
||||
timeKeeper() = 0;
|
||||
virtual JobQueue&
|
||||
|
||||
@@ -319,8 +319,8 @@ SHAMapStoreImp::run()
|
||||
LedgerIndex lastRotated = state_db_.getState().lastRotated;
|
||||
netOPs_ = &app_.getOPs();
|
||||
ledgerMaster_ = &app_.getLedgerMaster();
|
||||
fullBelowCache_ = &app_.family().fullbelow();
|
||||
treeNodeCache_ = &app_.family().treecache();
|
||||
fullBelowCache_ = &(*app_.getNodeFamily().getFullBelowCache(0));
|
||||
treeNodeCache_ = &(*app_.getNodeFamily().getTreeNodeCache(0));
|
||||
transactionDb_ = &app_.getTxnDB();
|
||||
ledgerDb_ = &app_.getLedgerDB();
|
||||
|
||||
|
||||
@@ -475,7 +475,7 @@ DatabaseShardImp::fetchLedger(uint256 const& hash, std::uint32_t seq)
|
||||
auto ledger{std::make_shared<Ledger>(
|
||||
deserializePrefixedHeader(makeSlice(nObj->getData())),
|
||||
app_.config(),
|
||||
*app_.shardFamily())};
|
||||
*app_.getShardFamily())};
|
||||
|
||||
if (ledger->info().seq != seq)
|
||||
{
|
||||
@@ -600,7 +600,7 @@ DatabaseShardImp::validate()
|
||||
shard->finalize(true, boost::none);
|
||||
}
|
||||
|
||||
app_.shardFamily()->reset();
|
||||
app_.getShardFamily()->reset();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -742,7 +742,6 @@ DatabaseShardImp::import(Database& source)
|
||||
}
|
||||
|
||||
// Create the new shard
|
||||
app_.shardFamily()->reset();
|
||||
auto shard{std::make_unique<Shard>(app_, *this, shardIndex, j_)};
|
||||
if (!shard->open(scheduler_, *ctx_))
|
||||
continue;
|
||||
|
||||
@@ -184,7 +184,7 @@ Shard::open(Scheduler& scheduler, nudb::context& ctx)
|
||||
}
|
||||
|
||||
if (boost::icl::length(storedSeqs) == maxLedgers_)
|
||||
// All ledgers have been acquired, shard is complete
|
||||
// All ledgers have been acquired, shard backend is complete
|
||||
backendComplete_ = true;
|
||||
}
|
||||
}
|
||||
@@ -238,7 +238,7 @@ Shard::prepare()
|
||||
if (backendComplete_)
|
||||
{
|
||||
JLOG(j_.warn()) << "shard " << index_
|
||||
<< " prepare called when shard is complete";
|
||||
<< " prepare called when shard backend is complete";
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -417,7 +417,7 @@ Shard::finalize(
|
||||
{
|
||||
std::unique_lock lock(mutex_);
|
||||
if (!backendComplete_)
|
||||
return fail("incomplete");
|
||||
return fail("backend incomplete");
|
||||
|
||||
/*
|
||||
TODO MP
|
||||
@@ -535,7 +535,7 @@ Shard::finalize(
|
||||
ledger = std::make_shared<Ledger>(
|
||||
deserializePrefixedHeader(makeSlice(nObj->getData())),
|
||||
app_.config(),
|
||||
*app_.shardFamily());
|
||||
*app_.getShardFamily());
|
||||
if (ledger->info().seq != seq)
|
||||
return fail("invalid ledger sequence");
|
||||
if (ledger->info().hash != hash)
|
||||
|
||||
@@ -214,7 +214,7 @@ private:
|
||||
std::unique_ptr<DatabaseCon> txSQLiteDB_;
|
||||
|
||||
// Tracking information used only when acquiring a shard from the network.
|
||||
// If the shard is complete, this member will be null.
|
||||
// If the shard is final, this member will be null.
|
||||
std::unique_ptr<AcquireInfo> acquireInfo_;
|
||||
|
||||
beast::Journal const j_;
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <ripple/protocol/ErrorCodes.h>
|
||||
#include <ripple/protocol/jss.h>
|
||||
#include <ripple/rpc/Context.h>
|
||||
#include <ripple/shamap/ShardFamily.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -103,9 +104,11 @@ getCountsJson(Application& app, int minObjectCount)
|
||||
ret[jss::AL_hit_rate] = app.getAcceptedLedgerCache().getHitRate();
|
||||
|
||||
ret[jss::fullbelow_size] =
|
||||
static_cast<int>(app.family().fullbelow().size());
|
||||
ret[jss::treenode_cache_size] = app.family().treecache().getCacheSize();
|
||||
ret[jss::treenode_track_size] = app.family().treecache().getTrackSize();
|
||||
static_cast<int>(app.getNodeFamily().getFullBelowCache(0)->size());
|
||||
ret[jss::treenode_cache_size] =
|
||||
app.getNodeFamily().getTreeNodeCache(0)->getCacheSize();
|
||||
ret[jss::treenode_track_size] =
|
||||
app.getNodeFamily().getTreeNodeCache(0)->getTrackSize();
|
||||
|
||||
std::string uptime;
|
||||
auto s = UptimeClock::now();
|
||||
@@ -125,13 +128,13 @@ getCountsJson(Application& app, int minObjectCount)
|
||||
|
||||
if (auto shardStore = app.getShardStore())
|
||||
{
|
||||
auto shardFamily{dynamic_cast<ShardFamily*>(app.getShardFamily())};
|
||||
auto const [cacheSz, trackSz] = shardFamily->getTreeNodeCacheSize();
|
||||
Json::Value& jv = (ret[jss::shards] = Json::objectValue);
|
||||
jv[jss::fullbelow_size] =
|
||||
static_cast<int>(app.shardFamily()->fullbelow().size());
|
||||
jv[jss::treenode_cache_size] =
|
||||
app.shardFamily()->treecache().getCacheSize();
|
||||
jv[jss::treenode_track_size] =
|
||||
app.shardFamily()->treecache().getTrackSize();
|
||||
|
||||
jv[jss::fullbelow_size] = shardFamily->getFullBelowCacheSize();
|
||||
jv[jss::treenode_cache_size] = cacheSz;
|
||||
jv[jss::treenode_track_size] = trackSz;
|
||||
ret[jss::write_load] = shardStore->getWriteLoad();
|
||||
ret[jss::node_hit_rate] = shardStore->getCacheHitRate();
|
||||
jv[jss::node_writes] = shardStore->getStoreCount();
|
||||
|
||||
@@ -32,37 +32,54 @@ namespace ripple {
|
||||
class Family
|
||||
{
|
||||
public:
|
||||
Family(Family const&) = delete;
|
||||
Family(Family&&) = delete;
|
||||
|
||||
Family&
|
||||
operator=(Family const&) = delete;
|
||||
|
||||
Family&
|
||||
operator=(Family&&) = delete;
|
||||
|
||||
explicit Family() = default;
|
||||
virtual ~Family() = default;
|
||||
|
||||
virtual beast::Journal const&
|
||||
journal() = 0;
|
||||
|
||||
virtual FullBelowCache&
|
||||
fullbelow() = 0;
|
||||
|
||||
virtual FullBelowCache const&
|
||||
fullbelow() const = 0;
|
||||
|
||||
virtual TreeNodeCache&
|
||||
treecache() = 0;
|
||||
|
||||
virtual TreeNodeCache const&
|
||||
treecache() const = 0;
|
||||
|
||||
virtual NodeStore::Database&
|
||||
db() = 0;
|
||||
|
||||
virtual NodeStore::Database const&
|
||||
db() const = 0;
|
||||
|
||||
virtual beast::Journal const&
|
||||
journal() = 0;
|
||||
|
||||
/** Return a pointer to the Family Full Below Cache
|
||||
|
||||
@param ledgerSeq ledger sequence determines a corresponding shard cache
|
||||
@note ledgerSeq is used by ShardFamily and ignored by NodeFamily
|
||||
*/
|
||||
virtual std::shared_ptr<FullBelowCache>
|
||||
getFullBelowCache(std::uint32_t ledgerSeq) = 0;
|
||||
|
||||
/** Return a pointer to the Family Tree Node Cache
|
||||
|
||||
@param ledgerSeq ledger sequence determines a corresponding shard cache
|
||||
@note ledgerSeq is used by ShardFamily and ignored by NodeFamily
|
||||
*/
|
||||
virtual std::shared_ptr<TreeNodeCache>
|
||||
getTreeNodeCache(std::uint32_t ledgerSeq) = 0;
|
||||
|
||||
virtual void
|
||||
sweep() = 0;
|
||||
|
||||
virtual bool
|
||||
isShardBacked() const = 0;
|
||||
|
||||
virtual void
|
||||
missing_node(std::uint32_t refNum) = 0;
|
||||
missingNode(std::uint32_t refNum) = 0;
|
||||
|
||||
virtual void
|
||||
missing_node(uint256 const& refHash, std::uint32_t refNum) = 0;
|
||||
missingNode(uint256 const& refHash, std::uint32_t refNum) = 0;
|
||||
|
||||
virtual void
|
||||
reset() = 0;
|
||||
|
||||
112
src/ripple/shamap/NodeFamily.h
Normal file
112
src/ripple/shamap/NodeFamily.h
Normal file
@@ -0,0 +1,112 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_SHAMAP_NODEFAMILY_H_INCLUDED
|
||||
#define RIPPLE_SHAMAP_NODEFAMILY_H_INCLUDED
|
||||
|
||||
#include <ripple/app/main/CollectorManager.h>
|
||||
#include <ripple/shamap/Family.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class Application;
|
||||
|
||||
class NodeFamily : public Family
|
||||
{
|
||||
public:
|
||||
NodeFamily() = delete;
|
||||
NodeFamily(NodeFamily const&) = delete;
|
||||
NodeFamily(NodeFamily&&) = delete;
|
||||
|
||||
NodeFamily&
|
||||
operator=(NodeFamily const&) = delete;
|
||||
|
||||
NodeFamily&
|
||||
operator=(NodeFamily&&) = delete;
|
||||
|
||||
NodeFamily(Application& app, CollectorManager& cm);
|
||||
|
||||
NodeStore::Database&
|
||||
db() override
|
||||
{
|
||||
return db_;
|
||||
}
|
||||
|
||||
NodeStore::Database const&
|
||||
db() const override
|
||||
{
|
||||
return db_;
|
||||
}
|
||||
|
||||
beast::Journal const&
|
||||
journal() override
|
||||
{
|
||||
return j_;
|
||||
}
|
||||
|
||||
bool
|
||||
isShardBacked() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<FullBelowCache> getFullBelowCache(std::uint32_t) override
|
||||
{
|
||||
return fbCache_;
|
||||
}
|
||||
|
||||
std::shared_ptr<TreeNodeCache> getTreeNodeCache(std::uint32_t) override
|
||||
{
|
||||
return tnCache_;
|
||||
}
|
||||
|
||||
void
|
||||
sweep() override;
|
||||
|
||||
void
|
||||
reset() override;
|
||||
|
||||
void
|
||||
missingNode(std::uint32_t seq) override;
|
||||
|
||||
void
|
||||
missingNode(uint256 const& hash, std::uint32_t seq) override
|
||||
{
|
||||
acquire(hash, seq);
|
||||
}
|
||||
|
||||
private:
|
||||
Application& app_;
|
||||
NodeStore::Database& db_;
|
||||
beast::Journal const j_;
|
||||
|
||||
std::shared_ptr<FullBelowCache> fbCache_;
|
||||
std::shared_ptr<TreeNodeCache> tnCache_;
|
||||
|
||||
// Missing node handler
|
||||
LedgerIndex maxSeq_{0};
|
||||
std::mutex maxSeqMutex_;
|
||||
|
||||
void
|
||||
acquire(uint256 const& hash, std::uint32_t seq);
|
||||
};
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
124
src/ripple/shamap/ShardFamily.h
Normal file
124
src/ripple/shamap/ShardFamily.h
Normal file
@@ -0,0 +1,124 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_SHAMAP_SHARDFAMILY_H_INCLUDED
|
||||
#define RIPPLE_SHAMAP_SHARDFAMILY_H_INCLUDED
|
||||
|
||||
#include <ripple/app/main/CollectorManager.h>
|
||||
#include <ripple/shamap/Family.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class Application;
|
||||
|
||||
class ShardFamily : public Family
|
||||
{
|
||||
public:
|
||||
ShardFamily() = delete;
|
||||
ShardFamily(ShardFamily const&) = delete;
|
||||
ShardFamily(ShardFamily&&) = delete;
|
||||
|
||||
ShardFamily&
|
||||
operator=(ShardFamily const&) = delete;
|
||||
|
||||
ShardFamily&
|
||||
operator=(ShardFamily&&) = delete;
|
||||
|
||||
ShardFamily(Application& app, CollectorManager& cm);
|
||||
|
||||
NodeStore::Database&
|
||||
db() override
|
||||
{
|
||||
return db_;
|
||||
}
|
||||
|
||||
NodeStore::Database const&
|
||||
db() const override
|
||||
{
|
||||
return db_;
|
||||
}
|
||||
|
||||
beast::Journal const&
|
||||
journal() override
|
||||
{
|
||||
return j_;
|
||||
}
|
||||
|
||||
bool
|
||||
isShardBacked() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
std::shared_ptr<FullBelowCache>
|
||||
getFullBelowCache(std::uint32_t ledgerSeq) override;
|
||||
|
||||
/** Return the number of entries in the cache */
|
||||
int
|
||||
getFullBelowCacheSize();
|
||||
|
||||
std::shared_ptr<TreeNodeCache>
|
||||
getTreeNodeCache(std::uint32_t ledgerSeq) override;
|
||||
|
||||
/** Return a pair where the first item is the number of items cached
|
||||
and the second item is the number of entries in the cached
|
||||
*/
|
||||
std::pair<int, int>
|
||||
getTreeNodeCacheSize();
|
||||
|
||||
void
|
||||
sweep() override;
|
||||
|
||||
void
|
||||
reset() override;
|
||||
|
||||
void
|
||||
missingNode(std::uint32_t seq) override;
|
||||
|
||||
void
|
||||
missingNode(uint256 const& hash, std::uint32_t seq) override
|
||||
{
|
||||
acquire(hash, seq);
|
||||
}
|
||||
|
||||
private:
|
||||
Application& app_;
|
||||
NodeStore::Database& db_;
|
||||
CollectorManager& cm_;
|
||||
beast::Journal const j_;
|
||||
|
||||
std::unordered_map<std::uint32_t, std::shared_ptr<FullBelowCache>> fbCache_;
|
||||
std::mutex fbCacheMutex_;
|
||||
|
||||
std::unordered_map<std::uint32_t, std::shared_ptr<TreeNodeCache>> tnCache_;
|
||||
std::mutex tnCacheMutex_;
|
||||
int const tnTargetSize_;
|
||||
std::chrono::seconds const tnTargetAge_;
|
||||
|
||||
// Missing node handler
|
||||
LedgerIndex maxSeq_{0};
|
||||
std::mutex maxSeqMutex_;
|
||||
|
||||
void
|
||||
acquire(uint256 const& hash, std::uint32_t seq);
|
||||
};
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
@@ -21,12 +21,9 @@
|
||||
#define RIPPLE_SHAMAP_TREENODECACHE_H_INCLUDED
|
||||
|
||||
#include <ripple/shamap/SHAMapTreeNode.h>
|
||||
#include <ripple/shamap/TreeNodeCache.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class SHAMapAbstractNode;
|
||||
|
||||
using TreeNodeCache = TaggedCache<uint256, SHAMapAbstractNode>;
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
108
src/ripple/shamap/impl/NodeFamily.cpp
Normal file
108
src/ripple/shamap/impl/NodeFamily.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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/LedgerMaster.h>
|
||||
#include <ripple/app/main/Application.h>
|
||||
#include <ripple/app/main/Tuning.h>
|
||||
#include <ripple/shamap/NodeFamily.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
NodeFamily::NodeFamily(Application& app, CollectorManager& cm)
|
||||
: app_(app)
|
||||
, db_(app.getNodeStore())
|
||||
, j_(app.journal("NodeFamily"))
|
||||
, fbCache_(std::make_shared<FullBelowCache>(
|
||||
"Node family full below cache",
|
||||
stopwatch(),
|
||||
cm.collector(),
|
||||
fullBelowTargetSize,
|
||||
fullBelowExpiration))
|
||||
, tnCache_(std::make_shared<TreeNodeCache>(
|
||||
"Node family tree node cache",
|
||||
app.config().getValueFor(SizedItem::treeCacheSize),
|
||||
std::chrono::seconds(
|
||||
app.config().getValueFor(SizedItem::treeCacheAge)),
|
||||
stopwatch(),
|
||||
j_))
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
NodeFamily::sweep()
|
||||
{
|
||||
fbCache_->sweep();
|
||||
tnCache_->sweep();
|
||||
}
|
||||
|
||||
void
|
||||
NodeFamily::reset()
|
||||
{
|
||||
{
|
||||
std::lock_guard lock(maxSeqMutex_);
|
||||
maxSeq_ = 0;
|
||||
}
|
||||
|
||||
fbCache_->reset();
|
||||
tnCache_->reset();
|
||||
}
|
||||
|
||||
void
|
||||
NodeFamily::missingNode(std::uint32_t seq)
|
||||
{
|
||||
JLOG(j_.error()) << "Missing node in " << seq;
|
||||
|
||||
std::unique_lock<std::mutex> lock(maxSeqMutex_);
|
||||
if (maxSeq_ == 0)
|
||||
{
|
||||
maxSeq_ = seq;
|
||||
|
||||
do
|
||||
{
|
||||
// Try to acquire the most recent missing ledger
|
||||
seq = maxSeq_;
|
||||
|
||||
lock.unlock();
|
||||
|
||||
// This can invoke the missing node handler
|
||||
acquire(app_.getLedgerMaster().getHashBySeq(seq), seq);
|
||||
|
||||
lock.lock();
|
||||
} while (maxSeq_ != seq);
|
||||
}
|
||||
else if (maxSeq_ < seq)
|
||||
{
|
||||
// We found a more recent ledger with a missing node
|
||||
maxSeq_ = seq;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NodeFamily::acquire(uint256 const& hash, std::uint32_t seq)
|
||||
{
|
||||
if (hash.isNonZero())
|
||||
{
|
||||
JLOG(j_.error()) << "Missing node in " << to_string(hash);
|
||||
|
||||
app_.getInboundLedgers().acquire(
|
||||
hash, seq, InboundLedger::Reason::GENERIC);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ripple
|
||||
@@ -164,7 +164,7 @@ SHAMap::fetchNodeFromDB(SHAMapHash const& hash) const
|
||||
}
|
||||
else if (full_)
|
||||
{
|
||||
f_.missing_node(ledgerSeq_);
|
||||
f_.missingNode(ledgerSeq_);
|
||||
const_cast<bool&>(full_) = false;
|
||||
}
|
||||
}
|
||||
@@ -332,10 +332,10 @@ SHAMap::descend(
|
||||
assert(!parent->isEmptyBranch(branch));
|
||||
|
||||
SHAMapAbstractNode* child = parent->getChildPointer(branch);
|
||||
auto const& childHash = parent->getChildHash(branch);
|
||||
|
||||
if (!child)
|
||||
{
|
||||
auto const& childHash = parent->getChildHash(branch);
|
||||
std::shared_ptr<SHAMapAbstractNode> childNode =
|
||||
fetchNodeNT(childHash, filter);
|
||||
|
||||
@@ -1115,7 +1115,7 @@ SHAMap::dump(bool hash) const
|
||||
std::shared_ptr<SHAMapAbstractNode>
|
||||
SHAMap::getCache(SHAMapHash const& hash) const
|
||||
{
|
||||
auto ret = f_.treecache().fetch(hash.as_uint256());
|
||||
auto ret = f_.getTreeNodeCache(ledgerSeq_)->fetch(hash.as_uint256());
|
||||
assert(!ret || !ret->getSeq());
|
||||
return ret;
|
||||
}
|
||||
@@ -1129,7 +1129,8 @@ SHAMap::canonicalize(
|
||||
assert(node->getSeq() == 0);
|
||||
assert(node->getNodeHash() == hash);
|
||||
|
||||
f_.treecache().canonicalize_replace_client(hash.as_uint256(), node);
|
||||
f_.getTreeNodeCache(ledgerSeq_)
|
||||
->canonicalize_replace_client(hash.as_uint256(), node);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -198,7 +198,9 @@ SHAMap::gmn_ProcessNodes(MissingNodes& mn, MissingNodes::StackEntry& se)
|
||||
fullBelow = false;
|
||||
}
|
||||
else if (
|
||||
!backed_ || !f_.fullbelow().touch_if_exists(childHash.as_uint256()))
|
||||
!backed_ ||
|
||||
!f_.getFullBelowCache(ledgerSeq_)
|
||||
->touch_if_exists(childHash.as_uint256()))
|
||||
{
|
||||
SHAMapNodeID childID = nodeID.getChildNodeID(branch);
|
||||
bool pending = false;
|
||||
@@ -243,7 +245,10 @@ SHAMap::gmn_ProcessNodes(MissingNodes& mn, MissingNodes::StackEntry& se)
|
||||
{ // No partial node encountered below this node
|
||||
node->setFullBelowGen(mn.generation_);
|
||||
if (backed_)
|
||||
f_.fullbelow().insert(node->getNodeHash().as_uint256());
|
||||
{
|
||||
f_.getFullBelowCache(ledgerSeq_)
|
||||
->insert(node->getNodeHash().as_uint256());
|
||||
}
|
||||
}
|
||||
|
||||
node = nullptr;
|
||||
@@ -323,7 +328,7 @@ SHAMap::getMissingNodes(int max, SHAMapSyncFilter* filter)
|
||||
max,
|
||||
filter,
|
||||
f_.db().getDesiredAsyncReadCount(ledgerSeq_),
|
||||
f_.fullbelow().getGeneration());
|
||||
f_.getFullBelowCache(ledgerSeq_)->getGeneration());
|
||||
|
||||
if (!root_->isInner() ||
|
||||
std::static_pointer_cast<SHAMapInnerNode>(root_)->isFullBelow(
|
||||
@@ -599,7 +604,7 @@ SHAMap::addKnownNode(
|
||||
return SHAMapAddNode::duplicate();
|
||||
}
|
||||
|
||||
std::uint32_t generation = f_.fullbelow().getGeneration();
|
||||
auto const generation = f_.getFullBelowCache(ledgerSeq_)->getGeneration();
|
||||
auto newNode = SHAMapAbstractNode::makeFromWire(rawNode);
|
||||
SHAMapNodeID iNodeID;
|
||||
auto iNode = root_.get();
|
||||
@@ -618,8 +623,11 @@ SHAMap::addKnownNode(
|
||||
}
|
||||
|
||||
auto childHash = inner->getChildHash(branch);
|
||||
if (f_.fullbelow().touch_if_exists(childHash.as_uint256()))
|
||||
if (f_.getFullBelowCache(ledgerSeq_)
|
||||
->touch_if_exists(childHash.as_uint256()))
|
||||
{
|
||||
return SHAMapAddNode::duplicate();
|
||||
}
|
||||
|
||||
auto prevNode = inner;
|
||||
std::tie(iNode, iNodeID) = descend(inner, iNodeID, branch, filter);
|
||||
|
||||
195
src/ripple/shamap/impl/ShardFamily.cpp
Normal file
195
src/ripple/shamap/impl/ShardFamily.cpp
Normal file
@@ -0,0 +1,195 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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/LedgerMaster.h>
|
||||
#include <ripple/app/main/Application.h>
|
||||
#include <ripple/app/main/Tuning.h>
|
||||
#include <ripple/nodestore/DatabaseShard.h>
|
||||
#include <ripple/shamap/ShardFamily.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
static NodeStore::Database&
|
||||
getShardStore(Application& app)
|
||||
{
|
||||
auto const dbPtr = app.getShardStore();
|
||||
assert(dbPtr);
|
||||
return *dbPtr;
|
||||
}
|
||||
|
||||
ShardFamily::ShardFamily(Application& app, CollectorManager& cm)
|
||||
: app_(app)
|
||||
, db_(getShardStore(app))
|
||||
, cm_(cm)
|
||||
, j_(app.journal("ShardFamily"))
|
||||
, tnTargetSize_(app.config().getValueFor(SizedItem::treeCacheSize))
|
||||
, tnTargetAge_(app.config().getValueFor(SizedItem::treeCacheAge))
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<FullBelowCache>
|
||||
ShardFamily::getFullBelowCache(std::uint32_t ledgerSeq)
|
||||
{
|
||||
auto const shardIndex{app_.getShardStore()->seqToShardIndex(ledgerSeq)};
|
||||
std::lock_guard lock(fbCacheMutex_);
|
||||
if (auto const it{fbCache_.find(shardIndex)}; it != fbCache_.end())
|
||||
return it->second;
|
||||
|
||||
// Create a cache for the corresponding shard
|
||||
auto fbCache{std::make_shared<FullBelowCache>(
|
||||
"Shard family full below cache shard " + std::to_string(shardIndex),
|
||||
stopwatch(),
|
||||
cm_.collector(),
|
||||
fullBelowTargetSize,
|
||||
fullBelowExpiration)};
|
||||
return fbCache_.emplace(shardIndex, std::move(fbCache)).first->second;
|
||||
}
|
||||
|
||||
int
|
||||
ShardFamily::getFullBelowCacheSize()
|
||||
{
|
||||
size_t sz{0};
|
||||
std::lock_guard lock(fbCacheMutex_);
|
||||
for (auto const& e : fbCache_)
|
||||
sz += e.second->size();
|
||||
return sz;
|
||||
}
|
||||
|
||||
std::shared_ptr<TreeNodeCache>
|
||||
ShardFamily::getTreeNodeCache(std::uint32_t ledgerSeq)
|
||||
{
|
||||
auto const shardIndex{app_.getShardStore()->seqToShardIndex(ledgerSeq)};
|
||||
std::lock_guard lock(tnCacheMutex_);
|
||||
if (auto const it{tnCache_.find(shardIndex)}; it != tnCache_.end())
|
||||
return it->second;
|
||||
|
||||
// Create a cache for the corresponding shard
|
||||
auto tnCache{std::make_shared<TreeNodeCache>(
|
||||
"Shard family tree node cache shard " + std::to_string(shardIndex),
|
||||
tnTargetSize_,
|
||||
tnTargetAge_,
|
||||
stopwatch(),
|
||||
j_)};
|
||||
return tnCache_.emplace(shardIndex, std::move(tnCache)).first->second;
|
||||
}
|
||||
|
||||
std::pair<int, int>
|
||||
ShardFamily::getTreeNodeCacheSize()
|
||||
{
|
||||
int cacheSz{0};
|
||||
int trackSz{0};
|
||||
std::lock_guard lock(tnCacheMutex_);
|
||||
for (auto const& e : tnCache_)
|
||||
{
|
||||
cacheSz += e.second->getCacheSize();
|
||||
trackSz += e.second->getTrackSize();
|
||||
}
|
||||
return {cacheSz, trackSz};
|
||||
}
|
||||
|
||||
void
|
||||
ShardFamily::sweep()
|
||||
{
|
||||
{
|
||||
std::lock_guard lock(fbCacheMutex_);
|
||||
for (auto it = fbCache_.cbegin(); it != fbCache_.cend();)
|
||||
{
|
||||
it->second->sweep();
|
||||
|
||||
// Remove cache if empty
|
||||
if (it->second->size() == 0)
|
||||
it = fbCache_.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
std::lock_guard lock(tnCacheMutex_);
|
||||
for (auto it = tnCache_.cbegin(); it != tnCache_.cend();)
|
||||
{
|
||||
it->second->sweep();
|
||||
|
||||
// Remove cache if empty
|
||||
if (it->second->getTrackSize() == 0)
|
||||
it = tnCache_.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ShardFamily::reset()
|
||||
{
|
||||
{
|
||||
std::lock_guard lock(maxSeqMutex_);
|
||||
maxSeq_ = 0;
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard lock(fbCacheMutex_);
|
||||
fbCache_.clear();
|
||||
}
|
||||
|
||||
std::lock_guard lock(tnCacheMutex_);
|
||||
tnCache_.clear();
|
||||
}
|
||||
|
||||
void
|
||||
ShardFamily::missingNode(std::uint32_t seq)
|
||||
{
|
||||
JLOG(j_.error()) << "Missing node in ledger sequence " << seq;
|
||||
|
||||
std::unique_lock<std::mutex> lock(maxSeqMutex_);
|
||||
if (maxSeq_ == 0)
|
||||
{
|
||||
maxSeq_ = seq;
|
||||
|
||||
do
|
||||
{
|
||||
// Try to acquire the most recent missing ledger
|
||||
seq = maxSeq_;
|
||||
|
||||
lock.unlock();
|
||||
|
||||
// This can invoke the missing node handler
|
||||
acquire(app_.getLedgerMaster().getHashBySeq(seq), seq);
|
||||
|
||||
lock.lock();
|
||||
} while (maxSeq_ != seq);
|
||||
}
|
||||
else if (maxSeq_ < seq)
|
||||
{
|
||||
// We found a more recent ledger with a missing node
|
||||
maxSeq_ = seq;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ShardFamily::acquire(uint256 const& hash, std::uint32_t seq)
|
||||
{
|
||||
if (hash.isNonZero())
|
||||
{
|
||||
JLOG(j_.error()) << "Missing node in " << to_string(hash);
|
||||
|
||||
app_.getInboundLedgers().acquire(
|
||||
hash, seq, InboundLedger::Reason::SHARD);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ripple
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
create_genesis,
|
||||
env.app().config(),
|
||||
std::vector<uint256>{},
|
||||
env.app().family());
|
||||
env.app().getNodeFamily());
|
||||
}
|
||||
auto res = std::make_shared<Ledger>(
|
||||
*prev, prev->info().closeTime + closeOffset);
|
||||
|
||||
@@ -77,7 +77,10 @@ class RCLValidations_test : public beast::unit_test::suite
|
||||
jtx::Env env(*this);
|
||||
Config config;
|
||||
auto prev = std::make_shared<Ledger const>(
|
||||
create_genesis, config, std::vector<uint256>{}, env.app().family());
|
||||
create_genesis,
|
||||
config,
|
||||
std::vector<uint256>{},
|
||||
env.app().getNodeFamily());
|
||||
history.push_back(prev);
|
||||
for (auto i = 0; i < (2 * maxAncestors + 1); ++i)
|
||||
{
|
||||
@@ -237,7 +240,10 @@ class RCLValidations_test : public beast::unit_test::suite
|
||||
auto& j = env.journal;
|
||||
Config config;
|
||||
auto prev = std::make_shared<Ledger const>(
|
||||
create_genesis, config, std::vector<uint256>{}, env.app().family());
|
||||
create_genesis,
|
||||
config,
|
||||
std::vector<uint256>{},
|
||||
env.app().getNodeFamily());
|
||||
history.push_back(prev);
|
||||
for (auto i = 0; i < (maxAncestors + 10); ++i)
|
||||
{
|
||||
|
||||
@@ -60,7 +60,7 @@ struct Regression_test : public beast::unit_test::suite
|
||||
create_genesis,
|
||||
env.app().config(),
|
||||
std::vector<uint256>{},
|
||||
env.app().family());
|
||||
env.app().getNodeFamily());
|
||||
auto expectedDrops = INITIAL_XRP;
|
||||
BEAST_EXPECT(closed->info().drops == expectedDrops);
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ class SkipList_test : public beast::unit_test::suite
|
||||
create_genesis,
|
||||
config,
|
||||
std::vector<uint256>{},
|
||||
env.app().family());
|
||||
env.app().getNodeFamily());
|
||||
history.push_back(prev);
|
||||
for (auto i = 0; i < 1023; ++i)
|
||||
{
|
||||
|
||||
@@ -134,7 +134,10 @@ class View_test : public beast::unit_test::suite
|
||||
Env env(*this);
|
||||
Config config;
|
||||
std::shared_ptr<Ledger const> const genesis = std::make_shared<Ledger>(
|
||||
create_genesis, config, std::vector<uint256>{}, env.app().family());
|
||||
create_genesis,
|
||||
config,
|
||||
std::vector<uint256>{},
|
||||
env.app().getNodeFamily());
|
||||
auto const ledger = std::make_shared<Ledger>(
|
||||
*genesis, env.app().timeKeeper().closeTime());
|
||||
wipe(*ledger);
|
||||
@@ -388,7 +391,10 @@ class View_test : public beast::unit_test::suite
|
||||
Env env(*this);
|
||||
Config config;
|
||||
std::shared_ptr<Ledger const> const genesis = std::make_shared<Ledger>(
|
||||
create_genesis, config, std::vector<uint256>{}, env.app().family());
|
||||
create_genesis,
|
||||
config,
|
||||
std::vector<uint256>{},
|
||||
env.app().getNodeFamily());
|
||||
auto const ledger = std::make_shared<Ledger>(
|
||||
*genesis, env.app().timeKeeper().closeTime());
|
||||
auto setup123 = [&ledger, this]() {
|
||||
@@ -769,7 +775,7 @@ class View_test : public beast::unit_test::suite
|
||||
create_genesis,
|
||||
config,
|
||||
std::vector<uint256>{},
|
||||
env.app().family());
|
||||
env.app().getNodeFamily());
|
||||
auto const ledger = std::make_shared<Ledger>(
|
||||
*genesis, env.app().timeKeeper().closeTime());
|
||||
wipe(*ledger);
|
||||
|
||||
@@ -118,7 +118,7 @@ public:
|
||||
using namespace beast::severities;
|
||||
test::SuiteJournal journal("FetchPack_test", *this);
|
||||
|
||||
TestFamily f(journal);
|
||||
TestNodeFamily f(journal);
|
||||
std::shared_ptr<Table> t1(std::make_shared<Table>(SHAMapType::FREE, f));
|
||||
|
||||
pass();
|
||||
|
||||
@@ -91,7 +91,7 @@ public:
|
||||
using namespace beast::severities;
|
||||
test::SuiteJournal journal("SHAMapSync_test", *this);
|
||||
|
||||
TestFamily f(journal), f2(journal);
|
||||
TestNodeFamily f(journal), f2(journal);
|
||||
SHAMap source(SHAMapType::FREE, f);
|
||||
SHAMap destination(SHAMapType::FREE, f2);
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ public:
|
||||
else
|
||||
testcase("add/traverse unbacked");
|
||||
|
||||
tests::TestFamily f(journal);
|
||||
tests::TestNodeFamily f(journal);
|
||||
|
||||
// h3 and h4 differ only in the leaf, same terminal node (level 19)
|
||||
uint256 h1, h2, h3, h4, h5;
|
||||
@@ -327,7 +327,7 @@ public:
|
||||
"292891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6c"
|
||||
"a8");
|
||||
|
||||
tests::TestFamily tf{journal};
|
||||
tests::TestNodeFamily tf{journal};
|
||||
SHAMap map{SHAMapType::FREE, tf};
|
||||
if (!backed)
|
||||
map.setUnbacked();
|
||||
|
||||
@@ -29,22 +29,31 @@
|
||||
namespace ripple {
|
||||
namespace tests {
|
||||
|
||||
class TestFamily : public Family
|
||||
class TestNodeFamily : public Family
|
||||
{
|
||||
private:
|
||||
std::unique_ptr<NodeStore::Database> db_;
|
||||
|
||||
std::shared_ptr<FullBelowCache> fbCache_;
|
||||
std::shared_ptr<TreeNodeCache> tnCache_;
|
||||
|
||||
TestStopwatch clock_;
|
||||
NodeStore::DummyScheduler scheduler_;
|
||||
TreeNodeCache treecache_;
|
||||
FullBelowCache fullbelow_;
|
||||
RootStoppable parent_;
|
||||
std::unique_ptr<NodeStore::Database> db_;
|
||||
bool shardBacked_;
|
||||
beast::Journal j_;
|
||||
|
||||
beast::Journal const j_;
|
||||
|
||||
public:
|
||||
TestFamily(beast::Journal j)
|
||||
: treecache_("TreeNodeCache", 65536, std::chrono::minutes{1}, clock_, j)
|
||||
, fullbelow_("full_below", clock_)
|
||||
TestNodeFamily(beast::Journal j)
|
||||
: fbCache_(std::make_shared<FullBelowCache>(
|
||||
"App family full below cache",
|
||||
clock_))
|
||||
, tnCache_(std::make_shared<TreeNodeCache>(
|
||||
"App family tree node cache",
|
||||
65536,
|
||||
std::chrono::minutes{1},
|
||||
clock_,
|
||||
j))
|
||||
, parent_("TestRootStoppable")
|
||||
, j_(j)
|
||||
{
|
||||
@@ -53,44 +62,6 @@ public:
|
||||
testSection.set("Path", "SHAMap_test");
|
||||
db_ = NodeStore::Manager::instance().make_Database(
|
||||
"test", scheduler_, 1, parent_, testSection, j);
|
||||
shardBacked_ =
|
||||
dynamic_cast<NodeStore::DatabaseShard*>(db_.get()) != nullptr;
|
||||
}
|
||||
|
||||
beast::manual_clock<std::chrono::steady_clock>
|
||||
clock()
|
||||
{
|
||||
return clock_;
|
||||
}
|
||||
|
||||
beast::Journal const&
|
||||
journal() override
|
||||
{
|
||||
return j_;
|
||||
}
|
||||
|
||||
FullBelowCache&
|
||||
fullbelow() override
|
||||
{
|
||||
return fullbelow_;
|
||||
}
|
||||
|
||||
FullBelowCache const&
|
||||
fullbelow() const override
|
||||
{
|
||||
return fullbelow_;
|
||||
}
|
||||
|
||||
TreeNodeCache&
|
||||
treecache() override
|
||||
{
|
||||
return treecache_;
|
||||
}
|
||||
|
||||
TreeNodeCache const&
|
||||
treecache() const override
|
||||
{
|
||||
return treecache_;
|
||||
}
|
||||
|
||||
NodeStore::Database&
|
||||
@@ -105,20 +76,43 @@ public:
|
||||
return *db_;
|
||||
}
|
||||
|
||||
bool
|
||||
isShardBacked() const override
|
||||
beast::Journal const&
|
||||
journal() override
|
||||
{
|
||||
return shardBacked_;
|
||||
return j_;
|
||||
}
|
||||
|
||||
std::shared_ptr<FullBelowCache> getFullBelowCache(std::uint32_t) override
|
||||
{
|
||||
return fbCache_;
|
||||
}
|
||||
|
||||
std::shared_ptr<TreeNodeCache> getTreeNodeCache(std::uint32_t) override
|
||||
{
|
||||
return tnCache_;
|
||||
}
|
||||
|
||||
void
|
||||
missing_node(std::uint32_t refNum) override
|
||||
sweep() override
|
||||
{
|
||||
fbCache_->sweep();
|
||||
tnCache_->sweep();
|
||||
}
|
||||
|
||||
bool
|
||||
isShardBacked() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
missingNode(std::uint32_t refNum) override
|
||||
{
|
||||
Throw<std::runtime_error>("missing node");
|
||||
}
|
||||
|
||||
void
|
||||
missing_node(uint256 const& refHash, std::uint32_t refNum) override
|
||||
missingNode(uint256 const& refHash, std::uint32_t refNum) override
|
||||
{
|
||||
Throw<std::runtime_error>("missing node");
|
||||
}
|
||||
@@ -126,8 +120,14 @@ public:
|
||||
void
|
||||
reset() override
|
||||
{
|
||||
fullbelow_.reset();
|
||||
treecache_.reset();
|
||||
fbCache_->reset();
|
||||
tnCache_->reset();
|
||||
}
|
||||
|
||||
beast::manual_clock<std::chrono::steady_clock>
|
||||
clock()
|
||||
{
|
||||
return clock_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user