@@ -38,6 +38,7 @@ pub struct NonCanonicalOverlay<BlockHash: Hash, Key: Hash> {
38
38
// would be deleted but kept around because block is pinned, ref counted.
39
39
pinned : HashMap < BlockHash , u32 > ,
40
40
pinned_insertions : HashMap < BlockHash , ( Vec < Key > , u32 ) > ,
41
+ last_canon_pinned : Option < BlockHash > ,
41
42
}
42
43
43
44
#[ cfg_attr( test, derive( PartialEq , Debug ) ) ]
@@ -225,6 +226,7 @@ impl<BlockHash: Hash, Key: Hash> NonCanonicalOverlay<BlockHash, Key> {
225
226
pinned : Default :: default ( ) ,
226
227
pinned_insertions : Default :: default ( ) ,
227
228
values,
229
+ last_canon_pinned : None ,
228
230
} )
229
231
}
230
232
@@ -367,6 +369,16 @@ impl<BlockHash: Hash, Key: Hash> NonCanonicalOverlay<BlockHash, Key> {
367
369
. position ( |overlay| overlay. hash == * hash)
368
370
. ok_or ( StateDbError :: InvalidBlock ) ?;
369
371
372
+ // No failures are possible beyond this point.
373
+
374
+ // Unpin previously canonicalized block
375
+ if let Some ( prev_hash) = self . last_canon_pinned . take ( ) {
376
+ self . unpin ( & prev_hash) ;
377
+ }
378
+ // Force pin canonicalized block so that it is no discarded immediately
379
+ self . pin ( hash) ;
380
+ self . last_canon_pinned = Some ( hash. clone ( ) ) ;
381
+
370
382
let mut discarded_journals = Vec :: new ( ) ;
371
383
let mut discarded_blocks = Vec :: new ( ) ;
372
384
for ( i, overlay) in level. blocks . into_iter ( ) . enumerate ( ) {
@@ -680,6 +692,7 @@ mod tests {
680
692
db. commit ( & overlay. insert ( & h2, 11 , & h1, make_changeset ( & [ 5 ] , & [ 3 ] ) ) . unwrap ( ) ) ;
681
693
let mut commit = CommitSet :: default ( ) ;
682
694
overlay. canonicalize ( & h1, & mut commit) . unwrap ( ) ;
695
+ overlay. unpin ( & h1) ;
683
696
db. commit ( & commit) ;
684
697
assert_eq ! ( overlay. levels. len( ) , 1 ) ;
685
698
@@ -707,15 +720,16 @@ mod tests {
707
720
let mut commit = CommitSet :: default ( ) ;
708
721
overlay. canonicalize ( & h1, & mut commit) . unwrap ( ) ;
709
722
db. commit ( & commit) ;
710
- assert ! ( ! contains( & overlay, 5 ) ) ;
723
+ assert ! ( contains( & overlay, 5 ) ) ;
711
724
assert ! ( contains( & overlay, 7 ) ) ;
712
725
assert_eq ! ( overlay. levels. len( ) , 1 ) ;
713
- assert_eq ! ( overlay. parents. len( ) , 1 ) ;
726
+ assert_eq ! ( overlay. parents. len( ) , 2 ) ;
714
727
let mut commit = CommitSet :: default ( ) ;
715
728
overlay. canonicalize ( & h2, & mut commit) . unwrap ( ) ;
729
+ assert ! ( !contains( & overlay, 5 ) ) ;
716
730
db. commit ( & commit) ;
717
731
assert_eq ! ( overlay. levels. len( ) , 0 ) ;
718
- assert_eq ! ( overlay. parents. len( ) , 0 ) ;
732
+ assert_eq ! ( overlay. parents. len( ) , 1 ) ;
719
733
assert ! ( db. data_eq( & make_db( & [ 1 , 4 , 6 , 7 , 8 ] ) ) ) ;
720
734
}
721
735
@@ -732,6 +746,8 @@ mod tests {
732
746
let mut commit = CommitSet :: default ( ) ;
733
747
overlay. canonicalize ( & h_1, & mut commit) . unwrap ( ) ;
734
748
db. commit ( & commit) ;
749
+ // explicitly unpin last block
750
+ overlay. unpin ( & h_1) ;
735
751
assert ! ( !contains( & overlay, 1 ) ) ;
736
752
}
737
753
@@ -818,6 +834,8 @@ mod tests {
818
834
// canonicalize 1. 2 and all its children should be discarded
819
835
let mut commit = CommitSet :: default ( ) ;
820
836
overlay. canonicalize ( & h_1, & mut commit) . unwrap ( ) ;
837
+ // explicitly unpin last block
838
+ overlay. unpin ( & h_1) ;
821
839
db. commit ( & commit) ;
822
840
assert_eq ! ( overlay. levels. len( ) , 2 ) ;
823
841
assert_eq ! ( overlay. parents. len( ) , 6 ) ;
@@ -838,6 +856,7 @@ mod tests {
838
856
// canonicalize 1_2. 1_1 and all its children should be discarded
839
857
let mut commit = CommitSet :: default ( ) ;
840
858
overlay. canonicalize ( & h_1_2, & mut commit) . unwrap ( ) ;
859
+ overlay. unpin ( & h_1_2) ;
841
860
db. commit ( & commit) ;
842
861
assert_eq ! ( overlay. levels. len( ) , 1 ) ;
843
862
assert_eq ! ( overlay. parents. len( ) , 3 ) ;
@@ -854,6 +873,7 @@ mod tests {
854
873
// canonicalize 1_2_2
855
874
let mut commit = CommitSet :: default ( ) ;
856
875
overlay. canonicalize ( & h_1_2_2, & mut commit) . unwrap ( ) ;
876
+ overlay. unpin ( & h_1_2_2) ;
857
877
db. commit ( & commit) ;
858
878
assert_eq ! ( overlay. levels. len( ) , 0 ) ;
859
879
assert_eq ! ( overlay. parents. len( ) , 0 ) ;
@@ -964,6 +984,7 @@ mod tests {
964
984
assert ! ( contains( & overlay, 1 ) ) ;
965
985
overlay. unpin ( & h_21) ;
966
986
assert ! ( !contains( & overlay, 1 ) ) ;
987
+ overlay. unpin ( & h_12) ;
967
988
assert ! ( overlay. pinned. is_empty( ) ) ;
968
989
}
969
990
@@ -998,6 +1019,7 @@ mod tests {
998
1019
999
1020
let mut commit = CommitSet :: default ( ) ;
1000
1021
overlay. canonicalize ( & h21, & mut commit) . unwrap ( ) ; // h11 should stay in the DB
1022
+ overlay. unpin ( & h21) ;
1001
1023
db. commit ( & commit) ;
1002
1024
assert ! ( !contains( & overlay, 21 ) ) ;
1003
1025
}
0 commit comments