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 );
@@ -2986,25 +2988,29 @@ LedgerManagerImpl::finalizeLedgerTxnChanges(
29862988 // `ledgerApplied` protects this call with a mutex
29872989 std::vector<LedgerEntry> initEntries, liveEntries;
29882990 std::vector<LedgerKey> deadEntries;
2991+
2992+ EvictedStateVectors evictedState;
2993+ std::vector<LedgerKey> restoredHotArchiveKeys;
2994+ std::future<void > hotArchiveBatchFuture;
2995+
29892996 // Any V20 features must be behind initialLedgerVers check, see comment
29902997 // in LedgerManagerImpl::ledgerApplied
29912998 if (protocolVersionStartsFrom (initialLedgerVers, SOROBAN_PROTOCOL_VERSION ))
29922999 {
3000+ bool hotArchiveBatchedAdded = false ;
3001+
29933002 // In `getAllTTLKeysWithoutSealing` it is important not to seal ltx,
29943003 // because it is still being modified by the eviction flow.
29953004 // `getAllTTLKeysWithoutSealing` must be called at the right time
29963005 // _after_ all operations have been applied, but _before_ evictions.
29973006 auto sorobanConfig = SorobanNetworkConfig::loadFromLedger (ltx);
2998- auto evictedState =
2999- mApp .getBucketManager ().resolveBackgroundEvictionScan (
3000- lclApplyView, ltx, ltx.getAllKeysWithoutSealing ());
3007+ evictedState = mApp .getBucketManager ().resolveBackgroundEvictionScan (
3008+ lclApplyView, ltx, ltx.getAllKeysWithoutSealing ());
30013009
30023010 if (protocolVersionStartsFrom (
30033011 initialLedgerVers,
30043012 LiveBucket::FIRST_PROTOCOL_SUPPORTING_PERSISTENT_EVICTION ))
30053013 {
3006- std::vector<LedgerKey> restoredHotArchiveKeys;
3007-
30083014 auto const & restoredHotArchiveKeyMap =
30093015 ltx.getRestoredHotArchiveKeys ();
30103016 for (auto const & [key, entry] : restoredHotArchiveKeyMap)
@@ -3031,12 +3037,10 @@ LedgerManagerImpl::finalizeLedgerTxnChanges(
30313037 p23_hot_archive_bug::addHotArchiveBatchWithP23HotArchiveFix (
30323038 ltx, mApp , lclApplyView, lh, evictedState.archivedEntries ,
30333039 restoredHotArchiveKeys);
3040+ hotArchiveBatchedAdded = true ;
30343041 }
30353042 else
30363043 {
3037- mApp .getBucketManager ().addHotArchiveBatch (
3038- mApp , lh, evictedState.archivedEntries ,
3039- restoredHotArchiveKeys);
30403044 // Validate evicted entries against Protocol 23 corruption
30413045 // data if configured
30423046 if (mApp .getProtocol23CorruptionDataVerifier ())
@@ -3048,6 +3052,12 @@ LedgerManagerImpl::finalizeLedgerTxnChanges(
30483052 }
30493053 }
30503054 }
3055+ else
3056+ {
3057+ // There is no hot archive support yet, so just mark the batch as
3058+ // already 'added' to avoid trying to add it later.
3059+ hotArchiveBatchedAdded = true ;
3060+ }
30513061
30523062 if (ledgerCloseMeta)
30533063 {
@@ -3064,6 +3074,19 @@ LedgerManagerImpl::finalizeLedgerTxnChanges(
30643074 // important to maintain as a protocol implementation detail.
30653075 SorobanNetworkConfig::maybeSnapshotSorobanStateSize (
30663076 lh.ledgerSeq , mApplyState .getSorobanInMemoryStateSize (), ltx, mApp );
3077+
3078+ if (!hotArchiveBatchedAdded)
3079+ {
3080+ hotArchiveBatchFuture =
3081+ std::async (std::launch::async,
3082+ [this , lh, evictedState = std::move (evictedState),
3083+ restoredHotArchiveKeys =
3084+ std::move (restoredHotArchiveKeys)]() mutable {
3085+ mApp .getBucketManager ().addHotArchiveBatch (
3086+ mApp , lh, evictedState.archivedEntries ,
3087+ restoredHotArchiveKeys);
3088+ });
3089+ }
30673090 }
30683091 std::optional<SorobanNetworkConfig> finalSorobanConfig;
30693092 // NB: We're looking for the most up-to-date config at this point, so we
@@ -3076,12 +3099,27 @@ LedgerManagerImpl::finalizeLedgerTxnChanges(
30763099 }
30773100 // NB: getAllEntries seals the ltx.
30783101 ltx.getAllEntries (initEntries, liveEntries, deadEntries);
3102+
3103+ // Launch async task to update in-memory Soroban state. This is independent
3104+ // from both addHotArchiveBatch and addLiveBatch, so all can run in
3105+ // parallel.
3106+ auto inMemoryStateUpdateFuture = std::async (
3107+ std::launch::async, [this , &initEntries, &liveEntries, &deadEntries, lh,
3108+ &finalSorobanConfig]() {
3109+ mApplyState .updateInMemorySorobanState (
3110+ initEntries, liveEntries, deadEntries, lh, finalSorobanConfig);
3111+ });
3112+
30793113 mApplyState .addAnyContractsToModuleCache (lh.ledgerVersion , initEntries);
30803114 mApplyState .addAnyContractsToModuleCache (lh.ledgerVersion , liveEntries);
30813115 mApp .getBucketManager ().addLiveBatch (mApp , lh, initEntries, liveEntries,
30823116 deadEntries);
3083- mApplyState .updateInMemorySorobanState (initEntries, liveEntries,
3084- deadEntries, lh, finalSorobanConfig);
3117+ // Wait for all async operations to complete before returning.
3118+ if (hotArchiveBatchFuture.valid ())
3119+ {
3120+ hotArchiveBatchFuture.get ();
3121+ }
3122+ inMemoryStateUpdateFuture.get ();
30853123 return finalSorobanConfig;
30863124}
30873125
0 commit comments