@@ -5,7 +5,7 @@ use sc_consensus::import_queue::ImportQueueService;
5
5
use sc_consensus:: IncomingBlock ;
6
6
use sc_consensus_subspace:: archiver:: { decode_block, encode_block, SegmentHeadersStore } ;
7
7
use sc_service:: Error ;
8
- use sc_tracing:: tracing:: { debug, trace} ;
8
+ use sc_tracing:: tracing:: { debug, info , trace} ;
9
9
use sp_consensus:: BlockOrigin ;
10
10
use sp_runtime:: generic:: SignedBlock ;
11
11
use sp_runtime:: traits:: { Block as BlockT , Header , NumberFor , One } ;
@@ -35,7 +35,7 @@ pub(super) async fn import_blocks_from_dsn<Block, AS, Client, PG, IQS>(
35
35
client : & Client ,
36
36
piece_getter : & PG ,
37
37
import_queue_service : & mut IQS ,
38
- last_processed_segment_index : & mut SegmentIndex ,
38
+ last_completed_segment_index : & mut SegmentIndex ,
39
39
last_processed_block_number : & mut NumberFor < Block > ,
40
40
erasure_coding : & ErasureCoding ,
41
41
) -> Result < u64 , Error >
70
70
let mut imported_blocks = 0 ;
71
71
let mut reconstructor = Arc :: new ( Mutex :: new ( Reconstructor :: new ( erasure_coding. clone ( ) ) ) ) ;
72
72
// Start from the first unprocessed segment and process all segments known so far
73
- let segment_indices_iter = ( * last_processed_segment_index + SegmentIndex :: ONE )
73
+ let segment_indices_iter = ( * last_completed_segment_index + SegmentIndex :: ONE )
74
74
..=segment_headers_store
75
75
. max_segment_index ( )
76
76
. expect ( "Exists, we have inserted segment headers above; qed" ) ;
@@ -105,20 +105,56 @@ where
105
105
// so it can't change. Resetting the reconstructor loses any partial blocks, so we
106
106
// only reset if the (possibly partial) last block has been processed.
107
107
if * last_processed_block_number >= last_archived_maybe_partial_block_number {
108
- * last_processed_segment_index = segment_index;
108
+ debug ! (
109
+ target: LOG_TARGET ,
110
+ %segment_index,
111
+ %last_processed_block_number,
112
+ %last_archived_maybe_partial_block_number,
113
+ %last_archived_block_partial,
114
+ "Already processed last (possibly partial) block in segment, resetting reconstructor" ,
115
+ ) ;
116
+ * last_completed_segment_index = segment_index;
109
117
// Reset reconstructor instance
110
118
reconstructor = Arc :: new ( Mutex :: new ( Reconstructor :: new ( erasure_coding. clone ( ) ) ) ) ;
111
119
continue ;
112
120
}
113
121
// Just one partial unprocessed block and this was the last segment available, so nothing to
114
- // import
122
+ // import. (But we also haven't finished this segment yet, because of the partial block.)
115
123
if last_archived_maybe_partial_block_number == * last_processed_block_number + One :: one ( )
116
124
&& last_archived_block_partial
117
- && segment_indices_iter. peek ( ) . is_none ( )
118
125
{
119
- // Reset reconstructor instance
120
- reconstructor = Arc :: new ( Mutex :: new ( Reconstructor :: new ( erasure_coding. clone ( ) ) ) ) ;
121
- continue ;
126
+ if segment_indices_iter. peek ( ) . is_none ( ) {
127
+ // We haven't fully processed this segment yet, because it ends with a partial block.
128
+ * last_completed_segment_index = segment_index. saturating_sub ( SegmentIndex :: ONE ) ;
129
+
130
+ // We don't need to reset the reconstructor here. We've finished getting blocks, so
131
+ // we're about to return and drop the reconstructor and its partial block anyway.
132
+ // (Normally, we'd need that partial block to avoid a block gap. But we should be close
133
+ // enough to the tip that normal syncing will fill any gaps.)
134
+ debug ! (
135
+ target: LOG_TARGET ,
136
+ %segment_index,
137
+ %last_processed_block_number,
138
+ %last_archived_maybe_partial_block_number,
139
+ %last_archived_block_partial,
140
+ "No more segments, snap sync is about to finish" ,
141
+ ) ;
142
+ continue ;
143
+ } else {
144
+ // Downloading an entire segment for one partial block should be rare, but if it
145
+ // happens a lot we want to see it in the logs.
146
+ //
147
+ // TODO: if this happens a lot, check for network/DSN sync bugs - we should be able
148
+ // to sync to near the tip reliably, so we don't have to keep reconstructor state.
149
+ info ! (
150
+ target: LOG_TARGET ,
151
+ %segment_index,
152
+ %last_processed_block_number,
153
+ %last_archived_maybe_partial_block_number,
154
+ %last_archived_block_partial,
155
+ "Downloading entire segment for one partial block" ,
156
+ ) ;
157
+ }
122
158
}
123
159
124
160
let segment_pieces = download_segment_pieces ( segment_index, piece_getter)
@@ -239,7 +275,12 @@ where
239
275
import_queue_service. import_blocks ( BlockOrigin :: NetworkInitialSync , blocks_to_import) ;
240
276
}
241
277
242
- * last_processed_segment_index = segment_index;
278
+ // Segments are only fully processed when all their blocks are fully processed.
279
+ if last_archived_block_partial {
280
+ * last_completed_segment_index = segment_index. saturating_sub ( SegmentIndex :: ONE ) ;
281
+ } else {
282
+ * last_completed_segment_index = segment_index;
283
+ }
243
284
}
244
285
245
286
Ok ( imported_blocks)
0 commit comments