mirror of
https://github.com/XRPLF/rippled.git
synced 2026-08-03 04:01:01 +00:00
Rescue nodes from the tree node cache, too
This commit is contained in:
@@ -262,6 +262,45 @@ SHAMapStoreImp::fdRequired() const
|
||||
return fdRequired_;
|
||||
}
|
||||
|
||||
void
|
||||
SHAMapStoreImp::rescueNode(SHAMapTreeNode const& node)
|
||||
{
|
||||
XRPL_ASSERT(node.cowid() == 0, "SHAMapStoreImp::copyNode : rescued node must be clean");
|
||||
// Reachable from the validated state map in memory, but present in
|
||||
// neither backend: its only on-disk copy lived in a backend removed by
|
||||
// an earlier rotation, and it was never rewritten because it is clean
|
||||
// (cowid == 0, so flushDirty skips it). Persist the in-memory body
|
||||
// directly into the writable backend so it survives this rotation
|
||||
// instead of later surfacing as an unresolvable SHAMapMissingNode.
|
||||
|
||||
auto const nodeType = node.getType();
|
||||
auto const objectType = std::invoke([nodeType] {
|
||||
switch (nodeType)
|
||||
{
|
||||
case SHAMapNodeType::TnAccountState:
|
||||
return NodeObjectType::AccountNode;
|
||||
case SHAMapNodeType::TnTransactionNm:
|
||||
return NodeObjectType::TransactionNode;
|
||||
default:
|
||||
return NodeObjectType::Unknown;
|
||||
}
|
||||
});
|
||||
|
||||
auto const hash = node.getHash().asUInt256();
|
||||
if (objectType == NodeObjectType::Unknown)
|
||||
{
|
||||
JLOG(journal_.warn()) << "copyNode: unable to re-store node with unknown type, hash="
|
||||
<< hash << " type=" << static_cast<int>(nodeType);
|
||||
return;
|
||||
}
|
||||
Serializer s;
|
||||
node.serializeWithPrefix(s);
|
||||
dbRotating_->store(objectType, std::move(s.modData()), hash, 0);
|
||||
|
||||
JLOG(journal_.warn()) << "copyNode: re-stored node missing from both backends, hash=" << hash
|
||||
<< " type=" << static_cast<int>(nodeType);
|
||||
}
|
||||
|
||||
bool
|
||||
SHAMapStoreImp::copyNode(std::uint64_t& nodeCount, SHAMapTreeNode const& node)
|
||||
{
|
||||
@@ -270,24 +309,7 @@ SHAMapStoreImp::copyNode(std::uint64_t& nodeCount, SHAMapTreeNode const& node)
|
||||
node.getHash().asUInt256(), 0, NodeStore::FetchType::Synchronous, true);
|
||||
if (!obj)
|
||||
{
|
||||
XRPL_ASSERT(node.cowid() == 0, "SHAMapStoreImp::copyNode : rescued node must be clean");
|
||||
// Reachable from the validated state map in memory, but present in
|
||||
// neither backend: its only on-disk copy lived in a backend removed by
|
||||
// an earlier rotation, and it was never rewritten because it is clean
|
||||
// (cowid == 0, so flushDirty skips it). Persist the in-memory body
|
||||
// directly into the writable backend so it survives this rotation
|
||||
// instead of later surfacing as an unresolvable SHAMapMissingNode.
|
||||
auto const hash = node.getHash().asUInt256();
|
||||
Serializer s;
|
||||
node.serializeWithPrefix(s);
|
||||
dbRotating_->store(NodeObjectType::AccountNode, std::move(s.modData()), hash, 0);
|
||||
{
|
||||
auto const& cached = treeNodeCache_->fetch(hash);
|
||||
JLOG(journal_.warn()) << "copyNode: re-stored node missing from both backends, hash="
|
||||
<< hash << " type=" << static_cast<int>(node.getType())
|
||||
<< ". Node is " << (cached ? "" : "not ")
|
||||
<< "in the tree node cache";
|
||||
}
|
||||
rescueNode(node);
|
||||
}
|
||||
if ((++nodeCount % checkHealthInterval_) == 0u)
|
||||
{
|
||||
@@ -648,8 +670,7 @@ SHAMapStoreImp::freshenCaches()
|
||||
{
|
||||
if (freshenCache(*treeNodeCache_))
|
||||
return;
|
||||
if (freshenCache(app_.getMasterTransaction().getCache()))
|
||||
return;
|
||||
freshenCache(app_.getMasterTransaction().getCache());
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <concepts>
|
||||
#include <condition_variable>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
@@ -177,6 +178,9 @@ public:
|
||||
minimumOnline() const override;
|
||||
|
||||
private:
|
||||
// Force write a node to the writable backend during rotation so it doesn't get lost
|
||||
void
|
||||
rescueNode(SHAMapTreeNode const& node);
|
||||
// callback for visitNodes
|
||||
bool
|
||||
copyNode(std::uint64_t& nodeCount, SHAMapTreeNode const& node);
|
||||
@@ -196,7 +200,18 @@ private:
|
||||
|
||||
for (auto const& key : cache.getKeys())
|
||||
{
|
||||
dbRotating_->fetchNodeObject(key, 0, NodeStore::FetchType::Synchronous, true);
|
||||
[[maybe_unused]]
|
||||
auto const obj =
|
||||
dbRotating_->fetchNodeObject(key, 0, NodeStore::FetchType::Synchronous, true);
|
||||
if constexpr (std::derived_from<typename CacheInstance::mapped_type, SHAMapTreeNode>)
|
||||
{
|
||||
if (!obj)
|
||||
{
|
||||
auto const node = cache.fetch(key);
|
||||
if (node)
|
||||
rescueNode(*node);
|
||||
}
|
||||
}
|
||||
if (!(++check % checkHealthInterval_) && healthWait() == HealthResult::Stopping)
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user