@@ -26,6 +26,7 @@ import (
2626 "github.com/oasisprotocol/oasis-core/go/runtime/host"
2727 storageApi "github.com/oasisprotocol/oasis-core/go/storage/api"
2828 "github.com/oasisprotocol/oasis-core/go/storage/mkvs/checkpoint"
29+ dbApi "github.com/oasisprotocol/oasis-core/go/storage/mkvs/db/api"
2930 mkvsDB "github.com/oasisprotocol/oasis-core/go/storage/mkvs/db/api"
3031 workerCommon "github.com/oasisprotocol/oasis-core/go/worker/common"
3132 "github.com/oasisprotocol/oasis-core/go/worker/common/committee"
@@ -1101,22 +1102,21 @@ func (n *Node) worker() { // nolint: gocyclo
11011102 pendingApply := & minRoundQueue {}
11021103 pendingFinalize := & minRoundQueue {}
11031104
1104- // Main processing loop. When a new block comes in, its state and io roots are inspected and their
1105- // writelogs fetched from peers in case we don't have them locally yet. Fetches are
1106- // asynchronous and, once complete, trigger local Apply operations. These are serialized
1107- // per round (all applies for a given round have to be complete before applying anything for following
1108- // rounds) using the fetched diffs and pending finalization priority queue. Once a round has all its write
1109- // logs applied, a Finalize for it is triggered, again serialized by round but otherwise asynchronous
1110- // (pendingFinalization and cachedLastRound).
1105+ // Main processing loop. When a new block arrives, its state and I/O roots are inspected.
1106+ // If missing locally, diffs are fetched from peers, possibly for many rounds in parallel,
1107+ // including all missing rounds since the last fully applied one. Fetched diffs are then applied
1108+ // in round order, ensuring no gaps. Once a round has all its roots applied, background finalization
1109+ // for that round is triggered asynchronously, not blocking concurrent fetching and diff application.
11111110mainLoop:
11121111 for {
1113- // Drain the Apply and Finalize queues first, before waiting for new events in the select
1114- // below. Applies are drained first, followed by finalizations (which are asynchronous
1115- // but serialized, i.e. only one Finalize can be in progress at a time).
1116-
1117- // Apply any writelogs that came in through fetchDiff, but only if they are for the round
1118- // after the last fully applied one (lastFullyAppliedRound).
1119- if len (* pendingApply ) > 0 && lastFullyAppliedRound + 1 == (* pendingApply )[0 ].GetRound () {
1112+ // Drain the Apply and Finalize queues first, before waiting for new events in the select below.
1113+
1114+ // Apply fetched writelogs, but only if they are for the round after the last fully applied one
1115+ // and current number of pending roots to be finalized is smaller than max allowed.
1116+ applyNext := pendingApply .Len () > 0 &&
1117+ lastFullyAppliedRound + 1 == (* pendingApply )[0 ].GetRound () &&
1118+ pendingFinalize .Len () < dbApi .MaxPendingVersions - 1 // -1 since one may be already finalizing.
1119+ if applyNext {
11201120 lastDiff := heap .Pop (pendingApply ).(* fetchedDiff )
11211121 // Apply the write log if one exists.
11221122 err = nil
@@ -1172,15 +1172,13 @@ mainLoop:
11721172 continue
11731173 }
11741174
1175- // Check if any new rounds were fully applied and need to be finalized. Only finalize
1176- // if it's the round after the one that was finalized last (cachedLastRound).
1177- // The finalization happens asynchronously with respect to this worker loop and any
1178- // applies that happen for subsequent rounds (which can proceed while earlier rounds are
1179- // still finalizing).
1175+ // Check if any new rounds were fully applied and need to be finalized.
1176+ // Only finalize if it's the round after the one that was finalized last.
1177+ // As a consequence at most one finalization can be happening at the time.
11801178 if len (* pendingFinalize ) > 0 && cachedLastRound + 1 == (* pendingFinalize )[0 ].GetRound () {
11811179 lastSummary := heap .Pop (pendingFinalize ).(* blockSummary )
11821180 wg .Add (1 )
1183- go func () {
1181+ go func () { // Don't block fetching and applying remaining rounds.
11841182 defer wg .Done ()
11851183 n .finalize (lastSummary )
11861184 }()
0 commit comments