7676
7777#include " LedgerManagerImpl.h"
7878#include < chrono>
79+ #include < future>
7980#include < memory>
8081#include < optional>
8182#include < regex>
@@ -318,7 +319,8 @@ LedgerManagerImpl::ApplyState::updateInMemorySorobanState(
318319 std::vector<LedgerKey> const & deadEntries, LedgerHeader const & lh,
319320 std::optional<SorobanNetworkConfig const > const & sorobanConfig)
320321{
321- assertWritablePhase ();
322+ releaseAssert (mPhase == Phase::SETTING_UP_STATE ||
323+ mPhase == Phase::COMMITTING );
322324 mInMemorySorobanState .updateState (initEntries, liveEntries, deadEntries, lh,
323325 sorobanConfig,
324326 getMetrics ().mSorobanMetrics );
@@ -2988,25 +2990,29 @@ LedgerManagerImpl::finalizeLedgerTxnChanges(
29882990 // `ledgerApplied` protects this call with a mutex
29892991 std::vector<LedgerEntry> initEntries, liveEntries;
29902992 std::vector<LedgerKey> deadEntries;
2993+
2994+ EvictedStateVectors evictedState;
2995+ std::vector<LedgerKey> restoredHotArchiveKeys;
2996+ std::future<void > hotArchiveBatchFuture;
2997+
29912998 // Any V20 features must be behind initialLedgerVers check, see comment
29922999 // in LedgerManagerImpl::ledgerApplied
29933000 if (protocolVersionStartsFrom (initialLedgerVers, SOROBAN_PROTOCOL_VERSION ))
29943001 {
3002+ bool hotArchiveBatchedAdded = false ;
3003+
29953004 // In `getAllTTLKeysWithoutSealing` it is important not to seal ltx,
29963005 // because it is still being modified by the eviction flow.
29973006 // `getAllTTLKeysWithoutSealing` must be called at the right time
29983007 // _after_ all operations have been applied, but _before_ evictions.
29993008 auto sorobanConfig = SorobanNetworkConfig::loadFromLedger (ltx);
3000- auto evictedState =
3001- mApp .getBucketManager ().resolveBackgroundEvictionScan (
3002- lclApplyView, ltx, ltx.getAllKeysWithoutSealing ());
3009+ evictedState = mApp .getBucketManager ().resolveBackgroundEvictionScan (
3010+ lclApplyView, ltx, ltx.getAllKeysWithoutSealing ());
30033011
30043012 if (protocolVersionStartsFrom (
30053013 initialLedgerVers,
30063014 LiveBucket::FIRST_PROTOCOL_SUPPORTING_PERSISTENT_EVICTION ))
30073015 {
3008- std::vector<LedgerKey> restoredHotArchiveKeys;
3009-
30103016 auto const & restoredHotArchiveKeyMap =
30113017 ltx.getRestoredHotArchiveKeys ();
30123018 for (auto const & [key, entry] : restoredHotArchiveKeyMap)
@@ -3033,12 +3039,10 @@ LedgerManagerImpl::finalizeLedgerTxnChanges(
30333039 p23_hot_archive_bug::addHotArchiveBatchWithP23HotArchiveFix (
30343040 ltx, mApp , lclApplyView, lh, evictedState.archivedEntries ,
30353041 restoredHotArchiveKeys);
3042+ hotArchiveBatchedAdded = true ;
30363043 }
30373044 else
30383045 {
3039- mApp .getBucketManager ().addHotArchiveBatch (
3040- mApp , lh, evictedState.archivedEntries ,
3041- restoredHotArchiveKeys);
30423046 // Validate evicted entries against Protocol 23 corruption
30433047 // data if configured
30443048 if (mApp .getProtocol23CorruptionDataVerifier ())
@@ -3050,6 +3054,12 @@ LedgerManagerImpl::finalizeLedgerTxnChanges(
30503054 }
30513055 }
30523056 }
3057+ else
3058+ {
3059+ // There is no hot archive support yet, so just mark the batch as
3060+ // already 'added' to avoid trying to add it later.
3061+ hotArchiveBatchedAdded = true ;
3062+ }
30533063
30543064 if (ledgerCloseMeta)
30553065 {
@@ -3066,6 +3076,19 @@ LedgerManagerImpl::finalizeLedgerTxnChanges(
30663076 // important to maintain as a protocol implementation detail.
30673077 SorobanNetworkConfig::maybeSnapshotSorobanStateSize (
30683078 lh.ledgerSeq , mApplyState .getSorobanInMemoryStateSize (), ltx, mApp );
3079+
3080+ if (!hotArchiveBatchedAdded)
3081+ {
3082+ hotArchiveBatchFuture =
3083+ std::async (std::launch::async,
3084+ [this , lh, evictedState = std::move (evictedState),
3085+ restoredHotArchiveKeys =
3086+ std::move (restoredHotArchiveKeys)]() mutable {
3087+ mApp .getBucketManager ().addHotArchiveBatch (
3088+ mApp , lh, evictedState.archivedEntries ,
3089+ restoredHotArchiveKeys);
3090+ });
3091+ }
30693092 }
30703093 std::optional<SorobanNetworkConfig> finalSorobanConfig;
30713094 // NB: We're looking for the most up-to-date config at this point, so we
@@ -3078,12 +3101,27 @@ LedgerManagerImpl::finalizeLedgerTxnChanges(
30783101 }
30793102 // NB: getAllEntries seals the ltx.
30803103 ltx.getAllEntries (initEntries, liveEntries, deadEntries);
3104+
3105+ // Launch async task to update in-memory Soroban state. This is independent
3106+ // from both addHotArchiveBatch and addLiveBatch, so all can run in
3107+ // parallel.
3108+ auto inMemoryStateUpdateFuture = std::async (
3109+ std::launch::async, [this , &initEntries, &liveEntries, &deadEntries, lh,
3110+ &finalSorobanConfig]() {
3111+ mApplyState .updateInMemorySorobanState (
3112+ initEntries, liveEntries, deadEntries, lh, finalSorobanConfig);
3113+ });
3114+
30813115 mApplyState .addAnyContractsToModuleCache (lh.ledgerVersion , initEntries);
30823116 mApplyState .addAnyContractsToModuleCache (lh.ledgerVersion , liveEntries);
30833117 mApp .getBucketManager ().addLiveBatch (mApp , lh, initEntries, liveEntries,
30843118 deadEntries);
3085- mApplyState .updateInMemorySorobanState (initEntries, liveEntries,
3086- deadEntries, lh, finalSorobanConfig);
3119+ // Wait for all async operations to complete before returning.
3120+ if (hotArchiveBatchFuture.valid ())
3121+ {
3122+ hotArchiveBatchFuture.get ();
3123+ }
3124+ inMemoryStateUpdateFuture.get ();
30873125 return finalSorobanConfig;
30883126}
30893127
0 commit comments