@@ -38,6 +38,7 @@ pub struct NonCanonicalOverlay<BlockHash: Hash, Key: Hash> {
3838 // would be deleted but kept around because block is pinned, ref counted.
3939 pinned : HashMap < BlockHash , u32 > ,
4040 pinned_insertions : HashMap < BlockHash , ( Vec < Key > , u32 ) > ,
41+ last_canon_pinned : Option < BlockHash > ,
4142}
4243
4344#[ cfg_attr( test, derive( PartialEq , Debug ) ) ]
@@ -225,6 +226,7 @@ impl<BlockHash: Hash, Key: Hash> NonCanonicalOverlay<BlockHash, Key> {
225226 pinned : Default :: default ( ) ,
226227 pinned_insertions : Default :: default ( ) ,
227228 values,
229+ last_canon_pinned : None ,
228230 } )
229231 }
230232
@@ -367,6 +369,16 @@ impl<BlockHash: Hash, Key: Hash> NonCanonicalOverlay<BlockHash, Key> {
367369 . position ( |overlay| overlay. hash == * hash)
368370 . ok_or ( StateDbError :: InvalidBlock ) ?;
369371
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+
370382 let mut discarded_journals = Vec :: new ( ) ;
371383 let mut discarded_blocks = Vec :: new ( ) ;
372384 for ( i, overlay) in level. blocks . into_iter ( ) . enumerate ( ) {
@@ -680,6 +692,7 @@ mod tests {
680692 db. commit ( & overlay. insert ( & h2, 11 , & h1, make_changeset ( & [ 5 ] , & [ 3 ] ) ) . unwrap ( ) ) ;
681693 let mut commit = CommitSet :: default ( ) ;
682694 overlay. canonicalize ( & h1, & mut commit) . unwrap ( ) ;
695+ overlay. unpin ( & h1) ;
683696 db. commit ( & commit) ;
684697 assert_eq ! ( overlay. levels. len( ) , 1 ) ;
685698
@@ -707,15 +720,16 @@ mod tests {
707720 let mut commit = CommitSet :: default ( ) ;
708721 overlay. canonicalize ( & h1, & mut commit) . unwrap ( ) ;
709722 db. commit ( & commit) ;
710- assert ! ( ! contains( & overlay, 5 ) ) ;
723+ assert ! ( contains( & overlay, 5 ) ) ;
711724 assert ! ( contains( & overlay, 7 ) ) ;
712725 assert_eq ! ( overlay. levels. len( ) , 1 ) ;
713- assert_eq ! ( overlay. parents. len( ) , 1 ) ;
726+ assert_eq ! ( overlay. parents. len( ) , 2 ) ;
714727 let mut commit = CommitSet :: default ( ) ;
715728 overlay. canonicalize ( & h2, & mut commit) . unwrap ( ) ;
729+ assert ! ( !contains( & overlay, 5 ) ) ;
716730 db. commit ( & commit) ;
717731 assert_eq ! ( overlay. levels. len( ) , 0 ) ;
718- assert_eq ! ( overlay. parents. len( ) , 0 ) ;
732+ assert_eq ! ( overlay. parents. len( ) , 1 ) ;
719733 assert ! ( db. data_eq( & make_db( & [ 1 , 4 , 6 , 7 , 8 ] ) ) ) ;
720734 }
721735
@@ -732,6 +746,8 @@ mod tests {
732746 let mut commit = CommitSet :: default ( ) ;
733747 overlay. canonicalize ( & h_1, & mut commit) . unwrap ( ) ;
734748 db. commit ( & commit) ;
749+ // explicitly unpin last block
750+ overlay. unpin ( & h_1) ;
735751 assert ! ( !contains( & overlay, 1 ) ) ;
736752 }
737753
@@ -818,6 +834,8 @@ mod tests {
818834 // canonicalize 1. 2 and all its children should be discarded
819835 let mut commit = CommitSet :: default ( ) ;
820836 overlay. canonicalize ( & h_1, & mut commit) . unwrap ( ) ;
837+ // explicitly unpin last block
838+ overlay. unpin ( & h_1) ;
821839 db. commit ( & commit) ;
822840 assert_eq ! ( overlay. levels. len( ) , 2 ) ;
823841 assert_eq ! ( overlay. parents. len( ) , 6 ) ;
@@ -838,6 +856,7 @@ mod tests {
838856 // canonicalize 1_2. 1_1 and all its children should be discarded
839857 let mut commit = CommitSet :: default ( ) ;
840858 overlay. canonicalize ( & h_1_2, & mut commit) . unwrap ( ) ;
859+ overlay. unpin ( & h_1_2) ;
841860 db. commit ( & commit) ;
842861 assert_eq ! ( overlay. levels. len( ) , 1 ) ;
843862 assert_eq ! ( overlay. parents. len( ) , 3 ) ;
@@ -854,6 +873,7 @@ mod tests {
854873 // canonicalize 1_2_2
855874 let mut commit = CommitSet :: default ( ) ;
856875 overlay. canonicalize ( & h_1_2_2, & mut commit) . unwrap ( ) ;
876+ overlay. unpin ( & h_1_2_2) ;
857877 db. commit ( & commit) ;
858878 assert_eq ! ( overlay. levels. len( ) , 0 ) ;
859879 assert_eq ! ( overlay. parents. len( ) , 0 ) ;
@@ -964,6 +984,7 @@ mod tests {
964984 assert ! ( contains( & overlay, 1 ) ) ;
965985 overlay. unpin ( & h_21) ;
966986 assert ! ( !contains( & overlay, 1 ) ) ;
987+ overlay. unpin ( & h_12) ;
967988 assert ! ( overlay. pinned. is_empty( ) ) ;
968989 }
969990
@@ -998,6 +1019,7 @@ mod tests {
9981019
9991020 let mut commit = CommitSet :: default ( ) ;
10001021 overlay. canonicalize ( & h21, & mut commit) . unwrap ( ) ; // h11 should stay in the DB
1022+ overlay. unpin ( & h21) ;
10011023 db. commit ( & commit) ;
10021024 assert ! ( !contains( & overlay, 21 ) ) ;
10031025 }
0 commit comments