@@ -407,30 +407,12 @@ impl CandidateForest {
407
407
/// in the cache, the block value is not updated and the returned future
408
408
/// resolves successfully.
409
409
pub fn cache_block ( & self , block : Block ) -> impl Future < Item = ( ) , Error = chain:: Error > {
410
- let header = block. header ( ) ;
411
- let block_hash = header. hash ( ) ;
410
+ let block_hash = block. id ( ) ;
412
411
let mut inner = self . inner . clone ( ) ;
413
412
future:: poll_fn ( move || Ok ( inner. poll_lock ( ) ) ) . and_then ( move |mut forest| {
414
- use std:: collections:: hash_map:: Entry :: * ;
415
-
416
- match forest. candidate_map . entry ( block_hash) {
417
- Occupied ( mut entry) => match & entry. get ( ) . data {
418
- CandidateData :: Header ( header) => {
419
- debug_assert ! ( header. hash( ) == block_hash) ;
420
- entry. insert ( Candidate :: from_block ( block) ) ;
421
- Ok ( ( ) )
422
- }
423
- CandidateData :: Block ( block) => {
424
- debug_assert ! ( block. header( ) . hash( ) == block_hash) ;
425
- Ok ( ( ) )
426
- }
427
- CandidateData :: Applied ( header) => {
428
- debug_assert ! ( header. hash( ) == block_hash) ;
429
- Ok ( ( ) )
430
- }
431
- } ,
432
- Vacant ( _) => Err ( chain:: ErrorKind :: BlockNotRequested ( block_hash) . into ( ) ) ,
433
- }
413
+ forest
414
+ . cache_requested_block ( block_hash, block)
415
+ . map_err ( |_block| chain:: ErrorKind :: BlockNotRequested ( block_hash) . into ( ) )
434
416
} )
435
417
}
436
418
@@ -509,13 +491,13 @@ impl CandidateForestThickets {
509
491
use std:: collections:: hash_map:: Entry :: * ;
510
492
511
493
let block_hash = block. id ( ) ;
512
- let mut block_avalanche = vec ! [ block] ;
513
494
if self . roots . contains_key ( & block_hash) {
514
495
let candidate = self . apply_candidate ( block_hash) ;
515
496
debug_assert ! (
516
497
!candidate. has_block( ) ,
517
498
"a chain pull root candidate should not cache a block" ,
518
499
) ;
500
+ let mut block_avalanche = vec ! [ block] ;
519
501
let mut child_hashes = candidate. children ;
520
502
while let Some ( child_hash) = child_hashes. pop ( ) {
521
503
match self . candidate_map . entry ( child_hash) {
@@ -549,14 +531,47 @@ impl CandidateForestThickets {
549
531
Vacant ( _) => panic ! ( "referential integrity failure in CandidateForest" ) ,
550
532
}
551
533
}
534
+ block_avalanche
552
535
} else {
553
- assert ! (
554
- !self . candidate_map. contains_key( & block_hash) ,
555
- "missed chain pull root candidate {} that got committed to storage" ,
556
- block_hash,
557
- ) ;
536
+ match self . cache_requested_block ( block_hash, block) {
537
+ Ok ( ( ) ) => {
538
+ // The task that applies the block has won the lock before
539
+ // other tasks that should apply preceding blocks.
540
+ // The block is cached for later, return an empty vector.
541
+ Vec :: default ( )
542
+ }
543
+ Err ( block) => {
544
+ // The block is not part of a chain pull.
545
+ // Pass it through so that it gets applied to storage
546
+ // or fails to validate against the parent that should be
547
+ // already stored.
548
+ vec ! [ block]
549
+ }
550
+ }
551
+ }
552
+ }
553
+
554
+ fn cache_requested_block ( & mut self , block_hash : HeaderHash , block : Block ) -> Result < ( ) , Block > {
555
+ use std:: collections:: hash_map:: Entry :: * ;
556
+
557
+ match self . candidate_map . entry ( block_hash) {
558
+ Vacant ( _) => Err ( block) ,
559
+ Occupied ( mut entry) => {
560
+ match & entry. get ( ) . data {
561
+ CandidateData :: Header ( header) => {
562
+ debug_assert ! ( header. hash( ) == block_hash) ;
563
+ entry. insert ( Candidate :: from_block ( block) ) ;
564
+ }
565
+ CandidateData :: Block ( block) => {
566
+ debug_assert ! ( block. header( ) . hash( ) == block_hash) ;
567
+ }
568
+ CandidateData :: Applied ( header) => {
569
+ debug_assert ! ( header. hash( ) == block_hash) ;
570
+ }
571
+ }
572
+ Ok ( ( ) )
573
+ }
558
574
}
559
- block_avalanche
560
575
}
561
576
562
577
// Removes the root from, then walks up the tree and
0 commit comments