adding callback into TaggedCache

This commit is contained in:
Valentin Balaschenko
2026-03-20 13:41:57 +00:00
parent c6b9bf61dc
commit bbc98fd746
3 changed files with 83 additions and 45 deletions

View File

@@ -161,6 +161,21 @@ public:
fetch(key_type const& digest, Handler const& h);
// End CachedSLEs functions.
/** Fetch or create an entry and execute a callback while holding the lock.
The entry for the given key is fetched from the cache or created if it
doesn't exist. The callback is then invoked with a reference to the
entry while the cache mutex is still held, allowing safe modification
of the cached object.
@param key The key to fetch or create
@param callback Function to call with the entry under lock.
Signature: void(T&)
*/
template <class Callback>
void
fetch_and_modify(key_type const& key, Callback&& callback);
private:
SharedPointerType
initialFetch(key_type const& key, std::lock_guard<mutex_type> const& l);

View File

@@ -586,6 +586,31 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
}
// End CachedSLEs functions.
template <
class Key,
class T,
bool IsKeyCache,
class SharedWeakUnionPointer,
class SharedPointerType,
class Hash,
class KeyEqual,
class Mutex>
template <class Callback>
inline void
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
fetch_and_modify(key_type const& key, Callback&& callback)
{
static_assert(
!IsKeyCache, "fetch_and_modify is only supported for value caches, not key-only caches");
std::lock_guard lock(m_mutex);
auto entry = std::make_shared<T>();
canonicalize(key, entry, []() { return false; });
callback(*entry);
}
template <
class Key,
class T,

View File

@@ -412,32 +412,31 @@ LedgerHistory::builtLedger(
LedgerHash hash = ledger->header().hash;
XRPL_ASSERT(!hash.isZero(), "xrpl::LedgerHistory::builtLedger : nonzero hash");
auto entry = std::make_shared<cv_entry>();
m_consensus_validated.canonicalize_replace_client(index, entry);
if (entry->validated && !entry->built)
{
if (entry->validated.value() != hash)
m_consensus_validated.fetch_and_modify(index, [&](cv_entry& entry) {
if (entry.validated && !entry.built)
{
JLOG(j_.error()) << "MISMATCH: seq=" << index
<< " validated:" << entry->validated.value() << " then:" << hash;
handleMismatch(
hash,
entry->validated.value(),
consensusHash,
entry->validatedConsensusHash,
consensus);
if (entry.validated.value() != hash)
{
JLOG(j_.error()) << "MISMATCH: seq=" << index
<< " validated:" << entry.validated.value() << " then:" << hash;
handleMismatch(
hash,
entry.validated.value(),
consensusHash,
entry.validatedConsensusHash,
consensus);
}
else
{
// We validated a ledger and then built it locally
JLOG(j_.debug()) << "MATCH: seq=" << index << " late";
}
}
else
{
// We validated a ledger and then built it locally
JLOG(j_.debug()) << "MATCH: seq=" << index << " late";
}
}
entry->built.emplace(hash);
entry->builtConsensusHash.emplace(consensusHash);
entry->consensus.emplace(std::move(consensus));
entry.built.emplace(hash);
entry.builtConsensusHash.emplace(consensusHash);
entry.consensus.emplace(std::move(consensus));
});
}
void
@@ -449,31 +448,30 @@ LedgerHistory::validatedLedger(
LedgerHash hash = ledger->header().hash;
XRPL_ASSERT(!hash.isZero(), "xrpl::LedgerHistory::validatedLedger : nonzero hash");
auto entry = std::make_shared<cv_entry>();
m_consensus_validated.canonicalize_replace_client(index, entry);
if (entry->built && !entry->validated)
{
if (entry->built.value() != hash)
m_consensus_validated.fetch_and_modify(index, [&](cv_entry& entry) {
if (entry.built && !entry.validated)
{
JLOG(j_.error()) << "MISMATCH: seq=" << index << " built:" << entry->built.value()
<< " then:" << hash;
handleMismatch(
entry->built.value(),
hash,
entry->builtConsensusHash,
consensusHash,
entry->consensus.value());
if (entry.built.value() != hash)
{
JLOG(j_.error()) << "MISMATCH: seq=" << index << " built:" << entry.built.value()
<< " then:" << hash;
handleMismatch(
entry.built.value(),
hash,
entry.builtConsensusHash,
consensusHash,
entry.consensus.value());
}
else
{
// We built a ledger locally and then validated it
JLOG(j_.debug()) << "MATCH: seq=" << index;
}
}
else
{
// We built a ledger locally and then validated it
JLOG(j_.debug()) << "MATCH: seq=" << index;
}
}
entry->validated.emplace(hash);
entry->validatedConsensusHash = consensusHash;
entry.validated.emplace(hash);
entry.validatedConsensusHash = consensusHash;
});
}
/** Ensure m_ledgers_by_hash doesn't have the wrong hash for a particular index