Skip to content

Commit 32e5546

Browse files
committed
WIP - spike on hot archive adaptation
1 parent bbd2113 commit 32e5546

9 files changed

+368
-48
lines changed

src/ledger/LedgerManagerImpl.cpp

+56-8
Original file line numberDiff line numberDiff line change
@@ -1617,7 +1617,7 @@ LedgerManagerImpl::collectEntries(AppConnector& app, AbstractLedgerTxn& ltx,
16171617
return entryMap;
16181618
}
16191619

1620-
void
1620+
RestoredKeys
16211621
LedgerManagerImpl::applyThread(AppConnector& app, ThreadEntryMap& entryMap,
16221622
Thread const& thread, Config const& config,
16231623
SorobanNetworkConfig const& sorobanConfig,
@@ -1629,6 +1629,7 @@ LedgerManagerImpl::applyThread(AppConnector& app, ThreadEntryMap& entryMap,
16291629
// we accumulate the RO extensions until we need to apply them.
16301630
UnorderedMap<LedgerKey, uint32_t> readOnlyTtlExtensions;
16311631

1632+
RestoredKeys threadRestoredKeys;
16321633
for (auto const& txBundle : thread)
16331634
{
16341635
releaseAssertOrThrow(txBundle.getResPayload());
@@ -1676,7 +1677,7 @@ LedgerManagerImpl::applyThread(AppConnector& app, ThreadEntryMap& entryMap,
16761677
txBundle.getResPayload(), sorobanMetrics, txSubSeed,
16771678
txBundle.getEffects());
16781679

1679-
if (res.mSuccess)
1680+
if (res.getSuccess())
16801681
{
16811682
UnorderedMap<LedgerKey, bool> isReadOnlyTTLMap;
16821683
for (auto const& ro :
@@ -1699,7 +1700,7 @@ LedgerManagerImpl::applyThread(AppConnector& app, ThreadEntryMap& entryMap,
16991700
}
17001701

17011702
// now apply the entry changes to entryMap
1702-
for (auto const& entry : res.mModifiedEntryMap)
1703+
for (auto const& entry : res.getModifiedEntryMap())
17031704
{
17041705
auto const& lk = entry.first;
17051706
auto const& updatedLe = entry.second;
@@ -1738,6 +1739,18 @@ LedgerManagerImpl::applyThread(AppConnector& app, ThreadEntryMap& entryMap,
17381739
it->second = {updatedLe, true};
17391740
}
17401741
}
1742+
1743+
for (auto const& key : res.getRestoredKeys().hotArchive)
1744+
{
1745+
auto [_, inserted] = threadRestoredKeys.hotArchive.emplace(key);
1746+
releaseAssertOrThrow(inserted);
1747+
}
1748+
for (auto const& key : res.getRestoredKeys().liveBucketList)
1749+
{
1750+
auto [_, inserted] =
1751+
threadRestoredKeys.liveBucketList.emplace(key);
1752+
releaseAssertOrThrow(inserted);
1753+
}
17411754
}
17421755
else
17431756
{
@@ -1761,6 +1774,8 @@ LedgerManagerImpl::applyThread(AppConnector& app, ThreadEntryMap& entryMap,
17611774
it->second.isDirty = true;
17621775
}
17631776
}
1777+
1778+
return threadRestoredKeys;
17641779
}
17651780

17661781
ParallelLedgerInfo
@@ -1798,6 +1813,8 @@ LedgerManagerImpl::applySorobanStage(AppConnector& app, AbstractLedgerTxn& ltx,
17981813
entryMapsByThread.emplace_back(collectEntries(app, ltx, thread));
17991814
}
18001815

1816+
std::vector<std::future<RestoredKeys>> threadRestoredKeyFutures;
1817+
18011818
auto ledgerInfo = getParallelLedgerInfo(app, ltx);
18021819
std::vector<std::thread> threads;
18031820
for (size_t i = 0; i < stage.size(); ++i)
@@ -1806,19 +1823,44 @@ LedgerManagerImpl::applySorobanStage(AppConnector& app, AbstractLedgerTxn& ltx,
18061823

18071824
auto const& thread = stage.at(i);
18081825

1809-
threads.emplace_back(&LedgerManagerImpl::applyThread, this,
1810-
std::ref(app), std::ref(entryMapByThread),
1811-
std::ref(thread), config, sorobanConfig,
1812-
std::ref(ledgerInfo), sorobanBasePrngSeed,
1813-
std::ref(sorobanMetrics));
1826+
threadRestoredKeyFutures.emplace_back(std::async(
1827+
std::launch::async, &LedgerManagerImpl::applyThread, this,
1828+
std::ref(app), std::ref(entryMapByThread), std::ref(thread), config,
1829+
sorobanConfig, std::ref(ledgerInfo), sorobanBasePrngSeed,
1830+
std::ref(sorobanMetrics)));
18141831
}
18151832

18161833
for (auto& thread : threads)
18171834
{
18181835
thread.join();
18191836
}
18201837

1838+
std::vector<RestoredKeys> threadRestoredKeys;
1839+
for (auto& restoredKeysFutures : threadRestoredKeyFutures)
1840+
{
1841+
threadRestoredKeys.emplace_back(restoredKeysFutures.get());
1842+
}
1843+
18211844
LedgerTxn ltxInner(ltx);
1845+
for (auto const& restoredKeys : threadRestoredKeys)
1846+
{
1847+
// We filter out the TTL keys here because LedgerTxn will add the ttl
1848+
// key
1849+
for (auto const& key : restoredKeys.hotArchive)
1850+
{
1851+
if (key.type() != TTL)
1852+
{
1853+
ltxInner.addRestoredFromHotArchiveKey(key);
1854+
}
1855+
}
1856+
for (auto const& key : restoredKeys.liveBucketList)
1857+
{
1858+
if (key.type() != TTL)
1859+
{
1860+
ltxInner.addRestoredFromLiveBucketListKey(key);
1861+
}
1862+
}
1863+
}
18221864
for (auto const& thread : stage)
18231865
{
18241866
for (auto const& txBundle : thread)
@@ -1886,6 +1928,12 @@ LedgerManagerImpl::applySorobanStage(AppConnector& app, AbstractLedgerTxn& ltx,
18861928
auto newLiveUntil =
18871929
updatedEntry.data.ttl().liveUntilLedgerSeq;
18881930

1931+
1932+
// The only scenario where we accept a reduction in TTL
1933+
// is one where an entry was deleted, and then
1934+
// recreated. This can only happen if the key was in the
1935+
// readWrite set, so if it's not then this is just a
1936+
// parallel readOnly bump that we can ignore here.
18891937
if (newLiveUntil <= currLiveUntil &&
18901938
isInReadWriteSet.count(entry.first) == 0)
18911939
{

src/ledger/LedgerManagerImpl.h

+7-6
Original file line numberDiff line numberDiff line change
@@ -122,12 +122,13 @@ class LedgerManagerImpl : public LedgerManager
122122
ThreadEntryMap collectEntries(AppConnector& app, AbstractLedgerTxn& ltx,
123123
Thread const& txs);
124124

125-
void applyThread(AppConnector& app, ThreadEntryMap& entryMapByCluster,
126-
Thread const& thread, Config const& config,
127-
SorobanNetworkConfig const& sorobanConfig,
128-
ParallelLedgerInfo const& ledgerInfo,
129-
Hash const& sorobanBasePrngSeed,
130-
SorobanMetrics& sorobanMetrics);
125+
RestoredKeys applyThread(AppConnector& app,
126+
ThreadEntryMap& entryMapByCluster,
127+
Thread const& thread, Config const& config,
128+
SorobanNetworkConfig const& sorobanConfig,
129+
ParallelLedgerInfo const& ledgerInfo,
130+
Hash const& sorobanBasePrngSeed,
131+
SorobanMetrics& sorobanMetrics);
131132

132133
void applySorobanStage(AppConnector& app, AbstractLedgerTxn& ltx,
133134
ApplyStage const& stage,

src/ledger/LedgerTxn.cpp

+62
Original file line numberDiff line numberDiff line change
@@ -825,6 +825,68 @@ LedgerTxn::Impl::erase(InternalLedgerKey const& key)
825825
}
826826
}
827827

828+
void
829+
LedgerTxn::addRestoredFromHotArchiveKey(LedgerKey const& key)
830+
{
831+
getImpl()->addRestoredFromHotArchiveKey(key);
832+
}
833+
834+
void
835+
LedgerTxn::Impl::addRestoredFromHotArchiveKey(LedgerKey const& key)
836+
{
837+
throwIfSealed();
838+
throwIfChild();
839+
840+
if (!isPersistentEntry(key))
841+
{
842+
throw std::runtime_error("Key type not supported in Hot Archive");
843+
}
844+
845+
auto ttlKey = getTTLKey(key);
846+
847+
// Mark the keys as restored
848+
auto addKey = [this](LedgerKey const& key) {
849+
auto [_, inserted] = mRestoredKeys.hotArchive.insert(key);
850+
if (!inserted)
851+
{
852+
throw std::runtime_error("Key already removed from hot archive");
853+
}
854+
};
855+
addKey(key);
856+
addKey(ttlKey);
857+
}
858+
859+
void
860+
LedgerTxn::addRestoredFromLiveBucketListKey(LedgerKey const& key)
861+
{
862+
getImpl()->addRestoredFromLiveBucketListKey(key);
863+
}
864+
865+
void
866+
LedgerTxn::Impl::addRestoredFromLiveBucketListKey(LedgerKey const& key)
867+
{
868+
throwIfSealed();
869+
throwIfChild();
870+
871+
if (!isPersistentEntry(key))
872+
{
873+
throw std::runtime_error("Key type not supported for restoration");
874+
}
875+
876+
auto ttlKey = getTTLKey(key);
877+
878+
auto addKey = [this](LedgerKey const& key) {
879+
auto [_, inserted] = mRestoredKeys.liveBucketList.insert(key);
880+
if (!inserted)
881+
{
882+
throw std::runtime_error(
883+
"Key already restored from Live BucketList");
884+
}
885+
};
886+
addKey(key);
887+
addKey(ttlKey);
888+
}
889+
828890
void
829891
LedgerTxn::restoreFromHotArchive(LedgerEntry const& entry, uint32_t ttl)
830892
{

src/ledger/LedgerTxn.h

+4
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,8 @@ class AbstractLedgerTxn : public AbstractLedgerTxnParent
595595
uint32_t ttl) = 0;
596596
virtual void restoreFromLiveBucketList(LedgerKey const& key,
597597
uint32_t ttl) = 0;
598+
virtual void addRestoredFromHotArchiveKey(LedgerKey const& key) = 0;
599+
virtual void addRestoredFromLiveBucketListKey(LedgerKey const& key) = 0;
598600
virtual LedgerTxnEntry load(InternalLedgerKey const& key) = 0;
599601
virtual ConstLedgerTxnEntry
600602
loadWithoutRecord(InternalLedgerKey const& key) = 0;
@@ -742,6 +744,8 @@ class LedgerTxn : public AbstractLedgerTxn
742744
void erase(InternalLedgerKey const& key) override;
743745
void restoreFromHotArchive(LedgerEntry const& entry, uint32_t ttl) override;
744746
void restoreFromLiveBucketList(LedgerKey const& key, uint32_t ttl) override;
747+
void addRestoredFromHotArchiveKey(LedgerKey const& key) override;
748+
void addRestoredFromLiveBucketListKey(LedgerKey const& key) override;
745749

746750
UnorderedMap<LedgerKey, LedgerEntry> getAllOffers() override;
747751

src/ledger/LedgerTxnImpl.h

+12
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,18 @@ class LedgerTxn::Impl
361361
// - the entry cache may be, but is not guaranteed to be, cleared.
362362
void erase(InternalLedgerKey const& key);
363363

364+
// addRestoredFromHotArchiveKey has the basic exception safety guarantee. If
365+
// it throws an exception, then
366+
// - the prepared statement cache may be, but is not guaranteed to be,
367+
// modified
368+
void addRestoredFromHotArchiveKey(LedgerKey const& key);
369+
370+
// addRestoredFromLiveBucketListKey has the basic exception safety
371+
// guarantee. If it throws an exception, then
372+
// - the prepared statement cache may be, but is not guaranteed to be,
373+
// modified
374+
void addRestoredFromLiveBucketListKey(LedgerKey const& key);
375+
364376
// restoreFromHotArchive has the basic exception safety guarantee. If it
365377
// throws an exception, then
366378
// - the prepared statement cache may be, but is not guaranteed to be,

src/transactions/InvokeHostFunctionOpFrame.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -874,11 +874,11 @@ InvokeHostFunctionOpFrame::doApply(
874874
ttlEntry = ttlLtxe.current().data.ttl();
875875
}
876876
}
877-
// TODO:This can be removed if both parallel soroban and persistent eviction make it into the
878-
// same protocol.
879-
// If ttlLtxe doesn't exist, this is a new Soroban entry
880-
// Starting in protocol 23, we must check the Hot Archive for
881-
// new keys. If a new key is actually archived, fail the op.
877+
// TODO:This can be removed if both parallel soroban and
878+
// persistent eviction make it into the same protocol. If
879+
// ttlLtxe doesn't exist, this is a new Soroban entry Starting
880+
// in protocol 23, we must check the Hot Archive for new keys.
881+
// If a new key is actually archived, fail the op.
882882
if (isPersistentEntry(lk) &&
883883
protocolVersionStartsFrom(
884884
ltx.getHeader().ledgerVersion,

0 commit comments

Comments
 (0)