@@ -38,7 +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 > ,
41+ pinned_canonincalized : Vec < BlockHash > ,
4242}
4343
4444#[ cfg_attr( test, derive( PartialEq , Debug ) ) ]
@@ -226,7 +226,7 @@ impl<BlockHash: Hash, Key: Hash> NonCanonicalOverlay<BlockHash, Key> {
226226 pinned : Default :: default ( ) ,
227227 pinned_insertions : Default :: default ( ) ,
228228 values,
229- last_canon_pinned : None ,
229+ pinned_canonincalized : Default :: default ( ) ,
230230 } )
231231 }
232232
@@ -350,6 +350,18 @@ impl<BlockHash: Hash, Key: Hash> NonCanonicalOverlay<BlockHash, Key> {
350350 self . last_canonicalized . as_ref ( ) . map ( |& ( _, n) | n)
351351 }
352352
353+ /// Confirm that all changes made to commit sets are on disk. Allows for temporarily pinned
354+ /// blocks to be released.
355+ pub fn sync ( & mut self ) {
356+ let mut pinned = std:: mem:: take ( & mut self . pinned_canonincalized ) ;
357+ for hash in pinned. iter ( ) {
358+ self . unpin ( hash)
359+ }
360+ pinned. clear ( ) ;
361+ // Reuse the same memory buffer
362+ self . pinned_canonincalized = pinned;
363+ }
364+
353365 /// Select a top-level root and canonicalized it. Discards all sibling subtrees and the root.
354366 /// Add a set of changes of the canonicalized block to `CommitSet`
355367 /// Return the block number of the canonicalized block
@@ -371,13 +383,9 @@ impl<BlockHash: Hash, Key: Hash> NonCanonicalOverlay<BlockHash, Key> {
371383
372384 // No failures are possible beyond this point.
373385
374- // Unpin previously canonicalized block
375- if let Some ( prev_hash) = self . last_canon_pinned . take ( ) {
376- self . unpin ( & prev_hash) ;
377- }
378386 // Force pin canonicalized block so that it is no discarded immediately
379387 self . pin ( hash) ;
380- self . last_canon_pinned = Some ( hash. clone ( ) ) ;
388+ self . pinned_canonincalized . push ( hash. clone ( ) ) ;
381389
382390 let mut discarded_journals = Vec :: new ( ) ;
383391 let mut discarded_blocks = Vec :: new ( ) ;
@@ -720,16 +728,17 @@ mod tests {
720728 let mut commit = CommitSet :: default ( ) ;
721729 overlay. canonicalize ( & h1, & mut commit) . unwrap ( ) ;
722730 db. commit ( & commit) ;
723- assert ! ( contains( & overlay, 5 ) ) ;
731+ overlay. sync ( ) ;
732+ assert ! ( !contains( & overlay, 5 ) ) ;
724733 assert ! ( contains( & overlay, 7 ) ) ;
725734 assert_eq ! ( overlay. levels. len( ) , 1 ) ;
726- assert_eq ! ( overlay. parents. len( ) , 2 ) ;
735+ assert_eq ! ( overlay. parents. len( ) , 1 ) ;
727736 let mut commit = CommitSet :: default ( ) ;
728737 overlay. canonicalize ( & h2, & mut commit) . unwrap ( ) ;
729- assert ! ( !contains( & overlay, 5 ) ) ;
730738 db. commit ( & commit) ;
739+ overlay. sync ( ) ;
731740 assert_eq ! ( overlay. levels. len( ) , 0 ) ;
732- assert_eq ! ( overlay. parents. len( ) , 1 ) ;
741+ assert_eq ! ( overlay. parents. len( ) , 0 ) ;
733742 assert ! ( db. data_eq( & make_db( & [ 1 , 4 , 6 , 7 , 8 ] ) ) ) ;
734743 }
735744
@@ -746,8 +755,7 @@ mod tests {
746755 let mut commit = CommitSet :: default ( ) ;
747756 overlay. canonicalize ( & h_1, & mut commit) . unwrap ( ) ;
748757 db. commit ( & commit) ;
749- // explicitly unpin last block
750- overlay. unpin ( & h_1) ;
758+ overlay. sync ( ) ;
751759 assert ! ( !contains( & overlay, 1 ) ) ;
752760 }
753761
@@ -834,9 +842,8 @@ mod tests {
834842 // canonicalize 1. 2 and all its children should be discarded
835843 let mut commit = CommitSet :: default ( ) ;
836844 overlay. canonicalize ( & h_1, & mut commit) . unwrap ( ) ;
837- // explicitly unpin last block
838- overlay. unpin ( & h_1) ;
839845 db. commit ( & commit) ;
846+ overlay. sync ( ) ;
840847 assert_eq ! ( overlay. levels. len( ) , 2 ) ;
841848 assert_eq ! ( overlay. parents. len( ) , 6 ) ;
842849 assert ! ( !contains( & overlay, 1 ) ) ;
@@ -856,8 +863,8 @@ mod tests {
856863 // canonicalize 1_2. 1_1 and all its children should be discarded
857864 let mut commit = CommitSet :: default ( ) ;
858865 overlay. canonicalize ( & h_1_2, & mut commit) . unwrap ( ) ;
859- overlay. unpin ( & h_1_2) ;
860866 db. commit ( & commit) ;
867+ overlay. sync ( ) ;
861868 assert_eq ! ( overlay. levels. len( ) , 1 ) ;
862869 assert_eq ! ( overlay. parents. len( ) , 3 ) ;
863870 assert ! ( !contains( & overlay, 11 ) ) ;
@@ -873,8 +880,8 @@ mod tests {
873880 // canonicalize 1_2_2
874881 let mut commit = CommitSet :: default ( ) ;
875882 overlay. canonicalize ( & h_1_2_2, & mut commit) . unwrap ( ) ;
876- overlay. unpin ( & h_1_2_2) ;
877883 db. commit ( & commit) ;
884+ overlay. sync ( ) ;
878885 assert_eq ! ( overlay. levels. len( ) , 0 ) ;
879886 assert_eq ! ( overlay. parents. len( ) , 0 ) ;
880887 assert ! ( db. data_eq( & make_db( & [ 1 , 12 , 122 ] ) ) ) ;
@@ -958,6 +965,28 @@ mod tests {
958965 assert ! ( !contains( & overlay, 1 ) ) ;
959966 }
960967
968+ #[ test]
969+ fn pins_canonicalized ( ) {
970+ let mut db = make_db ( & [ ] ) ;
971+
972+ let ( h_1, c_1) = ( H256 :: random ( ) , make_changeset ( & [ 1 ] , & [ ] ) ) ;
973+ let ( h_2, c_2) = ( H256 :: random ( ) , make_changeset ( & [ 2 ] , & [ ] ) ) ;
974+
975+ let mut overlay = NonCanonicalOverlay :: < H256 , H256 > :: new ( & db) . unwrap ( ) ;
976+ db. commit ( & overlay. insert ( & h_1, 1 , & H256 :: default ( ) , c_1) . unwrap ( ) ) ;
977+ db. commit ( & overlay. insert ( & h_2, 2 , & h_1, c_2) . unwrap ( ) ) ;
978+
979+ let mut commit = CommitSet :: default ( ) ;
980+ overlay. canonicalize ( & h_1, & mut commit) . unwrap ( ) ;
981+ overlay. canonicalize ( & h_2, & mut commit) . unwrap ( ) ;
982+ assert ! ( contains( & overlay, 1 ) ) ;
983+ assert ! ( contains( & overlay, 2 ) ) ;
984+ db. commit ( & commit) ;
985+ overlay. sync ( ) ;
986+ assert ! ( !contains( & overlay, 1 ) ) ;
987+ assert ! ( !contains( & overlay, 2 ) ) ;
988+ }
989+
961990 #[ test]
962991 fn pin_keeps_parent ( ) {
963992 let mut db = make_db ( & [ ] ) ;
@@ -1019,8 +1048,8 @@ mod tests {
10191048
10201049 let mut commit = CommitSet :: default ( ) ;
10211050 overlay. canonicalize ( & h21, & mut commit) . unwrap ( ) ; // h11 should stay in the DB
1022- overlay. unpin ( & h21) ;
10231051 db. commit ( & commit) ;
1052+ overlay. sync ( ) ;
10241053 assert ! ( !contains( & overlay, 21 ) ) ;
10251054 }
10261055
0 commit comments