Skip to content

Commit

Permalink
Improved ltx restore interface
Browse files Browse the repository at this point in the history
  • Loading branch information
SirTyson committed Jan 14, 2025
1 parent c42168a commit 6df429b
Show file tree
Hide file tree
Showing 12 changed files with 367 additions and 170 deletions.
11 changes: 10 additions & 1 deletion src/bucket/test/BucketTestUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,16 @@ LedgerManagerForBucketTests::transferLedgerEntriesToBucketList(
FIRST_PROTOCOL_SUPPORTING_PERSISTENT_EVICTION))
{
std::vector<LedgerKey> restoredKeys;
ltx.getRestoredHotArchiveKeys(restoredKeys);
auto restoredKeysMap = ltx.getRestoredHotArchiveKeys();
for (auto const& key : restoredKeysMap)
{
// Hot Archive does not track TTLs
if (key.type() == CONTRACT_DATA ||
key.type() == CONTRACT_CODE)
{
restoredKeys.emplace_back(key);
}
}
mApp.getBucketManager().addHotArchiveBatch(
mApp, lh, evictedState.archivedEntries, restoredKeys,
{});
Expand Down
11 changes: 10 additions & 1 deletion src/ledger/LedgerManagerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1794,7 +1794,16 @@ LedgerManagerImpl::transferLedgerEntriesToBucketList(
BucketBase::FIRST_PROTOCOL_SUPPORTING_PERSISTENT_EVICTION))
{
std::vector<LedgerKey> restoredKeys;
ltx.getRestoredHotArchiveKeys(restoredKeys);
auto const& restoredKeyMap = ltx.getRestoredHotArchiveKeys();
for (auto const& key : restoredKeyMap)
{
// TTL keys are not recorded in the hot archive BucketList
if (key.type() == CONTRACT_DATA ||
key.type() == CONTRACT_CODE)
{
restoredKeys.push_back(key);
}
}
mApp.getBucketManager().addHotArchiveBatch(
mApp, lh, evictedState.archivedEntries, restoredKeys, {});
}
Expand Down
149 changes: 109 additions & 40 deletions src/ledger/LedgerTxn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -503,17 +503,16 @@ LedgerTxn::Impl::commit() noexcept
maybeUpdateLastModifiedThenInvokeThenSeal([&](EntryMap const& entries) {
// getEntryIterator has the strong exception safety guarantee
// commitChild has the strong exception safety guarantee
mParent.commitChild(getEntryIterator(entries), mRestoredHotArchiveKeys,
mParent.commitChild(getEntryIterator(entries), mRestoredKeys,
mConsistency);
});
}

void
LedgerTxn::commitChild(EntryIterator iter,
UnorderedSet<LedgerKey> const& restoredHotArchiveKeys,
LedgerTxn::commitChild(EntryIterator iter, RestoredKeys const& restoredKeys,
LedgerTxnConsistency cons) noexcept
{
getImpl()->commitChild(std::move(iter), restoredHotArchiveKeys, cons);
getImpl()->commitChild(std::move(iter), restoredKeys, cons);
}

static LedgerTxnConsistency
Expand All @@ -531,9 +530,9 @@ joinConsistencyLevels(LedgerTxnConsistency c1, LedgerTxnConsistency c2)
}

void
LedgerTxn::Impl::commitChild(
EntryIterator iter, UnorderedSet<LedgerKey> const& restoredHotArchiveKeys,
LedgerTxnConsistency cons) noexcept
LedgerTxn::Impl::commitChild(EntryIterator iter,
RestoredKeys const& restoredKeys,
LedgerTxnConsistency cons) noexcept
{
// Assignment of xdrpp objects does not have the strong exception safety
// guarantee, so use std::unique_ptr<...>::swap to achieve it
Expand Down Expand Up @@ -638,15 +637,25 @@ LedgerTxn::Impl::commitChild(
printErrorAndAbort("unknown fatal error during commit to LedgerTxn");
}

for (auto const& key : restoredHotArchiveKeys)
for (auto const& key : restoredKeys.hotArchive)
{
auto [_, inserted] = mRestoredHotArchiveKeys.emplace(key);
auto [_, inserted] = mRestoredKeys.hotArchive.emplace(key);
if (!inserted)
{
printErrorAndAbort("restored hot archive entry already exists");
}
}

for (auto const& key : restoredKeys.liveBucketList)
{
auto [_, inserted] = mRestoredKeys.liveBucketList.emplace(key);
if (!inserted)
{
printErrorAndAbort(
"restored hlive BucketList entry already exists");
}
}

// std::unique_ptr<...>::swap does not throw
mHeader.swap(childHeader);
mChild = nullptr;
Expand Down Expand Up @@ -818,34 +827,88 @@ LedgerTxn::Impl::erase(InternalLedgerKey const& key)
}

void
LedgerTxn::removeFromHotArchive(LedgerKey const& key)
LedgerTxn::restoreFromHotArchive(LedgerEntry const& entry, uint32_t ttl)
{
getImpl()->removeFromHotArchive(key);
getImpl()->restoreFromHotArchive(*this, entry, ttl);
}

void
LedgerTxn::Impl::removeFromHotArchive(LedgerKey const& key)
LedgerTxn::Impl::restoreFromHotArchive(LedgerTxn& self,
LedgerEntry const& entry, uint32_t ttl)
{
throwIfSealed();
throwIfChild();

if (!isPersistentEntry(key))
if (!isPersistentEntry(entry.data))
{
throw std::runtime_error("Key type not supported in Hot Archive");
}
auto ttlKey = getTTLKey(entry);

// Restore entry by creating it on the live BucketList
create(self, entry);

// Also create the corresponding TTL entry
LedgerEntry ttlEntry;
ttlEntry.data.type(TTL);
ttlEntry.data.ttl().liveUntilLedgerSeq = ttl;
ttlEntry.data.ttl().keyHash = ttlKey.ttl().keyHash;
create(self, ttlEntry);

// Mark the keys as restored
auto addKey = [this](LedgerKey const& key) {
auto [_, inserted] = mRestoredKeys.hotArchive.insert(key);
if (!inserted)
{
throw std::runtime_error("Key already removed from hot archive");
}
};
addKey(LedgerEntryKey(entry));
addKey(ttlKey);
}

void
LedgerTxn::restoreFromLiveBucketList(LedgerKey const& key, uint32_t ttl)
{
getImpl()->restoreFromLiveBucketList(*this, key, ttl);
}

void
LedgerTxn::Impl::restoreFromLiveBucketList(LedgerTxn& self,
LedgerKey const& key, uint32_t ttl)
{
throwIfSealed();
throwIfChild();

auto restoredEntry = mEntry.find(key);
if (restoredEntry == mEntry.end() || !restoredEntry->second.isInit())
if (!isPersistentEntry(key))
{
throw std::runtime_error(
"Restored entry must be created before Hot Archive removal");
throw std::runtime_error("Key type not supported for restoration");
}

auto [_, inserted] = mRestoredHotArchiveKeys.insert(key);
if (!inserted)
auto ttlKey = getTTLKey(key);

// Note: key should have already been loaded via loadWithoutRecord by
// caller, so this read should already be in the cache.
auto ttlLtxe = load(self, ttlKey);
if (!ttlLtxe)
{
throw std::runtime_error("Key already removed from hot archive");
throw std::runtime_error("Entry restored from live BucketList but does "
"not exist in the live BucketList.");
}

ttlLtxe.current().data.ttl().liveUntilLedgerSeq = ttl;

// Mark the keys as restored
auto addKey = [this](LedgerKey const& key) {
auto [_, inserted] = mRestoredKeys.liveBucketList.insert(key);
if (!inserted)
{
throw std::runtime_error(
"Key already restored from Live BucketList");
}
};
addKey(key);
addKey(ttlKey);
}

void
Expand Down Expand Up @@ -1516,22 +1579,28 @@ LedgerTxn::Impl::getAllEntries(std::vector<LedgerEntry>& initEntries,
deadEntries.swap(resDead);
}

void
LedgerTxn::getRestoredHotArchiveKeys(
std::vector<LedgerKey>& restoredHotArchiveKeys)
UnorderedSet<LedgerKey> const&
LedgerTxn::getRestoredHotArchiveKeys() const
{
getImpl()->getRestoredHotArchiveKeys(restoredHotArchiveKeys);
return getImpl()->getRestoredHotArchiveKeys();
}

void
LedgerTxn::Impl::getRestoredHotArchiveKeys(
std::vector<LedgerKey>& restoredHotArchiveKeys)
UnorderedSet<LedgerKey> const&
LedgerTxn::Impl::getRestoredHotArchiveKeys() const
{
restoredHotArchiveKeys.reserve(mRestoredHotArchiveKeys.size());
for (auto const& key : mRestoredHotArchiveKeys)
{
restoredHotArchiveKeys.emplace_back(key);
}
return mRestoredKeys.hotArchive;
}

UnorderedSet<LedgerKey> const&
LedgerTxn::getRestoredLiveBucketListKeys() const
{
return getImpl()->getRestoredLiveBucketListKeys();
}

UnorderedSet<LedgerKey> const&
LedgerTxn::Impl::getRestoredLiveBucketListKeys() const
{
return mRestoredKeys.liveBucketList;
}

LedgerKeySet
Expand Down Expand Up @@ -2021,7 +2090,8 @@ LedgerTxn::Impl::rollback() noexcept
}

mEntry.clear();
mRestoredHotArchiveKeys.clear();
mRestoredKeys.hotArchive.clear();
mRestoredKeys.liveBucketList.clear();
mMultiOrderBook.clear();
mActive.clear();
mActiveHeader.reset();
Expand Down Expand Up @@ -2624,11 +2694,10 @@ LedgerTxnRoot::Impl::throwIfChild() const
}

void
LedgerTxnRoot::commitChild(
EntryIterator iter, UnorderedSet<LedgerKey> const& restoredHotArchiveKeys,
LedgerTxnConsistency cons) noexcept
LedgerTxnRoot::commitChild(EntryIterator iter, RestoredKeys const& restoredKeys,
LedgerTxnConsistency cons) noexcept
{
mImpl->commitChild(std::move(iter), restoredHotArchiveKeys, cons);
mImpl->commitChild(std::move(iter), restoredKeys, cons);
}

static void
Expand Down Expand Up @@ -2684,9 +2753,9 @@ LedgerTxnRoot::Impl::bulkApply(BulkLedgerEntryChangeAccumulator& bleca,
}

void
LedgerTxnRoot::Impl::commitChild(
EntryIterator iter, UnorderedSet<LedgerKey> const& restoredHotArchiveKeys,
LedgerTxnConsistency cons) noexcept
LedgerTxnRoot::Impl::commitChild(EntryIterator iter,
RestoredKeys const& restoredHotArchiveKeys,
LedgerTxnConsistency cons) noexcept
{
ZoneScoped;

Expand Down
Loading

0 comments on commit 6df429b

Please sign in to comment.