@@ -25,7 +25,9 @@ pub enum PostProcessorCommand {
25
25
}
26
26
27
27
pub enum PostProcessorEvent {
28
- EmptyQueue ,
28
+ Started ,
29
+ Terminated ,
30
+ Expired ,
29
31
}
30
32
31
33
pub struct PostProcessorController {
@@ -39,8 +41,7 @@ pub async fn download_and_pipeline_blocks(
39
41
start_block : u64 ,
40
42
end_block : u64 ,
41
43
start_sequencing_blocks_at_height : u64 ,
42
- blocks_post_processor_pre_sequence : Option < & PostProcessorController > ,
43
- blocks_post_processor_post_sequence : Option < & PostProcessorController > ,
44
+ blocks_post_processor : Option < & PostProcessorController > ,
44
45
speed : usize ,
45
46
ctx : & Context ,
46
47
) -> Result < ( ) , String > {
@@ -101,7 +102,7 @@ pub async fn download_and_pipeline_blocks(
101
102
rx_thread_pool. push ( rx) ;
102
103
}
103
104
104
- for rx in rx_thread_pool. into_iter ( ) {
105
+ for ( thread_index , rx ) in rx_thread_pool. into_iter ( ) . enumerate ( ) {
105
106
let block_compressed_tx_moved = block_compressed_tx. clone ( ) ;
106
107
let moved_ctx: Context = moved_ctx. clone ( ) ;
107
108
let moved_bitcoin_network = moved_bitcoin_network. clone ( ) ;
@@ -131,18 +132,16 @@ pub async fn download_and_pipeline_blocks(
131
132
compressed_block,
132
133
) ) ) ;
133
134
}
135
+ moved_ctx
136
+ . try_log ( |logger| debug ! ( logger, "Exiting processing thread {thread_index}" ) ) ;
134
137
} )
135
138
. expect ( "unable to spawn thread" ) ;
136
139
thread_pool_handles. push ( handle) ;
137
140
}
138
141
139
142
let cloned_ctx = ctx. clone ( ) ;
140
143
141
- let blocks_post_processor_post_sequence_commands_tx = blocks_post_processor_post_sequence
142
- . as_ref ( )
143
- . and_then ( |p| Some ( p. commands_tx . clone ( ) ) ) ;
144
-
145
- let blocks_post_processor_pre_sequence_commands_tx = blocks_post_processor_pre_sequence
144
+ let blocks_post_processor_commands_tx = blocks_post_processor
146
145
. as_ref ( )
147
146
. and_then ( |p| Some ( p. commands_tx . clone ( ) ) ) ;
148
147
@@ -151,19 +150,52 @@ pub async fn download_and_pipeline_blocks(
151
150
let mut inbox = HashMap :: new ( ) ;
152
151
let mut inbox_cursor = start_sequencing_blocks_at_height. max ( start_block) ;
153
152
let mut blocks_processed = 0 ;
154
- let mut pre_seq_processor_started = false ;
155
- let mut post_seq_processor_started = false ;
153
+ let mut processor_started = false ;
154
+ let mut stop_runloop = false ;
156
155
157
156
loop {
157
+ if stop_runloop {
158
+ cloned_ctx. try_log ( |logger| {
159
+ info ! (
160
+ logger,
161
+ "#{blocks_processed} blocks successfully sent to processor"
162
+ )
163
+ } ) ;
164
+ break ;
165
+ }
166
+
158
167
// Dequeue all the blocks available
159
168
let mut new_blocks = vec ! [ ] ;
160
- while let Ok ( Some ( ( block_height, block, compacted_block) ) ) =
161
- block_compressed_rx. try_recv ( )
162
- {
163
- blocks_processed += 1 ;
164
- new_blocks. push ( ( block_height, block, compacted_block) ) ;
165
- if new_blocks. len ( ) >= 10_000 {
166
- break ;
169
+ while let Ok ( message) = block_compressed_rx. try_recv ( ) {
170
+ match message {
171
+ Some ( ( block_height, block, compacted_block) ) => {
172
+ blocks_processed += 1 ;
173
+ new_blocks. push ( ( block_height, block, compacted_block) ) ;
174
+ // Max batch size: 10_000 blocks
175
+ if new_blocks. len ( ) >= 10_000 {
176
+ break ;
177
+ }
178
+ }
179
+ None => {
180
+ stop_runloop = true ;
181
+ }
182
+ }
183
+ }
184
+
185
+ if blocks_processed == number_of_blocks_to_process {
186
+ stop_runloop = true ;
187
+ }
188
+
189
+ // Early "continue"
190
+ if new_blocks. is_empty ( ) {
191
+ sleep ( Duration :: from_millis ( 500 ) ) ;
192
+ continue ;
193
+ }
194
+
195
+ if let Some ( ref blocks_tx) = blocks_post_processor_commands_tx {
196
+ if !processor_started {
197
+ processor_started = true ;
198
+ let _ = blocks_tx. send ( PostProcessorCommand :: Start ) ;
167
199
}
168
200
}
169
201
@@ -176,18 +208,15 @@ pub async fn download_and_pipeline_blocks(
176
208
}
177
209
}
178
210
179
- if !ooo_compacted_blocks. is_empty ( ) {
180
- if let Some ( ref blocks_tx) = blocks_post_processor_pre_sequence_commands_tx {
181
- if !pre_seq_processor_started {
182
- pre_seq_processor_started = true ;
183
- let _ = blocks_tx. send ( PostProcessorCommand :: Start ) ;
184
- }
185
-
211
+ // Early "continue"
212
+ if inbox. is_empty ( ) {
213
+ if let Some ( ref blocks_tx) = blocks_post_processor_commands_tx {
186
214
let _ = blocks_tx. send ( PostProcessorCommand :: ProcessBlocks (
187
215
ooo_compacted_blocks,
188
216
vec ! [ ] ,
189
217
) ) ;
190
218
}
219
+ continue ;
191
220
}
192
221
193
222
// In order processing: construct the longest sequence of known blocks
@@ -199,24 +228,8 @@ pub async fn download_and_pipeline_blocks(
199
228
inbox_cursor += 1 ;
200
229
}
201
230
202
- if blocks. is_empty ( ) {
203
- if blocks_processed == number_of_blocks_to_process {
204
- cloned_ctx. try_log ( |logger| {
205
- info ! (
206
- logger,
207
- "#{blocks_processed} blocks successfully sent to processor"
208
- )
209
- } ) ;
210
- break ;
211
- } else {
212
- sleep ( Duration :: from_secs ( 1 ) ) ;
213
- }
214
- } else {
215
- if let Some ( ref blocks_tx) = blocks_post_processor_post_sequence_commands_tx {
216
- if !post_seq_processor_started {
217
- post_seq_processor_started = true ;
218
- let _ = blocks_tx. send ( PostProcessorCommand :: Start ) ;
219
- }
231
+ if !blocks. is_empty ( ) {
232
+ if let Some ( ref blocks_tx) = blocks_post_processor_commands_tx {
220
233
let _ = blocks_tx. send ( PostProcessorCommand :: ProcessBlocks (
221
234
compacted_blocks,
222
235
blocks,
@@ -248,7 +261,7 @@ pub async fn download_and_pipeline_blocks(
248
261
}
249
262
250
263
ctx. try_log ( |logger| {
251
- info ! (
264
+ debug ! (
252
265
logger,
253
266
"Pipeline successfully fed with sequence of blocks ({} to {})" , start_block, end_block
254
267
)
@@ -258,26 +271,33 @@ pub async fn download_and_pipeline_blocks(
258
271
let _ = tx. send ( None ) ;
259
272
}
260
273
274
+ ctx. try_log ( |logger| debug ! ( logger, "Enqueued pipeline termination commands" ) ) ;
275
+
261
276
for handle in thread_pool_handles. into_iter ( ) {
262
277
let _ = handle. join ( ) ;
263
278
}
264
279
265
- if let Some ( post_processor) = blocks_post_processor_pre_sequence {
266
- loop {
267
- if let Ok ( PostProcessorEvent :: EmptyQueue ) = post_processor. events_rx . recv ( ) {
268
- break ;
269
- }
270
- }
271
- }
280
+ ctx. try_log ( |logger| debug ! ( logger, "Pipeline successfully terminated" ) ) ;
272
281
273
- if let Some ( post_processor) = blocks_post_processor_post_sequence {
282
+ if let Some ( post_processor) = blocks_post_processor {
283
+ if let Ok ( PostProcessorEvent :: Started ) = post_processor. events_rx . recv ( ) {
284
+ ctx. try_log ( |logger| debug ! ( logger, "Block post processing started" ) ) ;
285
+ let _ = post_processor
286
+ . commands_tx
287
+ . send ( PostProcessorCommand :: Terminate ) ;
288
+ }
274
289
loop {
275
- if let Ok ( PostProcessorEvent :: EmptyQueue ) = post_processor. events_rx . recv ( ) {
276
- break ;
290
+ if let Ok ( signal) = post_processor. events_rx . recv ( ) {
291
+ match signal {
292
+ PostProcessorEvent :: Terminated | PostProcessorEvent :: Expired => break ,
293
+ PostProcessorEvent :: Started => unreachable ! ( ) ,
294
+ }
277
295
}
278
296
}
279
297
}
280
298
299
+ let _ = block_compressed_tx. send ( None ) ;
300
+
281
301
let _ = storage_thread. join ( ) ;
282
302
let _ = set. shutdown ( ) ;
283
303
0 commit comments