From 3025238e598f0696986eac0396e1a4d6e22c1180 Mon Sep 17 00:00:00 2001 From: jeff washington Date: Mon, 19 Dec 2022 15:01:05 -0600 Subject: [PATCH] introduce ShrinkInProgress --- runtime/src/account_storage.rs | 68 +++++++++ runtime/src/accounts_db.rs | 234 ++++++++++++++++++++---------- runtime/src/snapshot_minimizer.rs | 7 +- 3 files changed, 231 insertions(+), 78 deletions(-) diff --git a/runtime/src/account_storage.rs b/runtime/src/account_storage.rs index 7d28d020b672f1..bfdc3a1cb82475 100644 --- a/runtime/src/account_storage.rs +++ b/runtime/src/account_storage.rs @@ -80,6 +80,42 @@ impl AccountStorage { .insert(store.append_vec_id(), store) .is_none()); } + + /// called when shrinking begins on a slot and append vec. + /// When 'ShrinkInProgress' is dropped by caller, the old store will be removed from the storage map. + pub(crate) fn shrinking_in_progress( + &self, + slot: Slot, + new_store: Arc, + ) -> ShrinkInProgress<'_> { + let slot_storages: SlotStores = self.get_slot_stores(slot).unwrap_or_else(|| + // DashMap entry.or_insert() returns a RefMut, essentially a write lock, + // which is dropped after this block ends, minimizing time held by the lock. + // However, we still want to persist the reference to the `SlotStores` behind + // the lock, hence we clone it out, (`SlotStores` is an Arc so is cheap to clone). + self + .map + .entry(slot) + .or_insert(Arc::new(RwLock::new(HashMap::new()))) + .clone()); + + let shrinking_store = Arc::clone(slot_storages.read().unwrap().iter().next().unwrap().1); + + let previous_id = shrinking_store.append_vec_id(); + let new_id = new_store.append_vec_id(); + let mut storages = slot_storages.write().unwrap(); + assert!(storages.remove(&previous_id).is_some()); + // insert 'new_store' into 'map' + assert!(storages.insert(new_id, Arc::clone(&new_store)).is_none()); + + ShrinkInProgress { + storage: self, + slot, + new_store, + old_store: shrinking_store, + } + } + #[cfg(test)] pub(crate) fn insert_empty_at_slot(&self, slot: Slot) { self.map @@ -92,6 +128,38 @@ impl AccountStorage { } } +/// exists while there is a shrink in progress +/// keeps track of the 'new_store' being created and the 'old_store' being replaced. +pub(crate) struct ShrinkInProgress<'a> { + storage: &'a AccountStorage, + /// newly shrunk store with a subset of contents from 'old_store' + new_store: Arc, + /// old store which will be shrunk and replaced + old_store: Arc, + slot: Slot, +} + +/// called when the shrink is no longer in progress. This means we can release the old append vec and update the map of slot -> append vec +impl<'a> Drop for ShrinkInProgress<'a> { + fn drop(&mut self) { + // the slot must be in the map + let slot_storages: SlotStores = self.storage.get_slot_stores(self.slot).unwrap(); + + let mut storages = slot_storages.write().unwrap(); + // the id must be in the hashmap + assert!(storages.remove(&self.old_store.append_vec_id()).is_some()); + } +} + +impl<'a> ShrinkInProgress<'a> { + pub(crate) fn new_storage(&self) -> &Arc { + &self.new_store + } + pub(crate) fn old_storage(&self) -> &Arc { + &self.old_store + } +} + #[derive(Debug, Eq, PartialEq, Copy, Clone, Deserialize, Serialize, AbiExample, AbiEnumVisitor)] pub enum AccountStorageStatus { Available = 0, diff --git a/runtime/src/accounts_db.rs b/runtime/src/accounts_db.rs index 13af26790387ce..f3bc11ddc44b34 100644 --- a/runtime/src/accounts_db.rs +++ b/runtime/src/accounts_db.rs @@ -21,7 +21,7 @@ use { crate::{ account_info::{AccountInfo, Offset, StorageLocation, StoredSize}, - account_storage::{AccountStorage, AccountStorageStatus}, + account_storage::{AccountStorage, AccountStorageStatus, ShrinkInProgress}, accounts_background_service::{DroppedSlotsSender, SendDroppedBankCallback}, accounts_cache::{AccountsCache, CachedAccount, SlotCache}, accounts_hash::{ @@ -205,12 +205,27 @@ impl CurrentAncientAppendVec { slot_and_append_vec: Some((slot, append_vec)), } } - fn create_ancient_append_vec(&mut self, slot: Slot, db: &AccountsDb) { - *self = Self::new(slot, db.create_ancient_append_vec(slot)); + + #[must_use] + fn create_ancient_append_vec<'a>( + &mut self, + slot: Slot, + db: &'a AccountsDb, + ) -> ShrinkInProgress<'a> { + let shrink_in_progress = db.create_ancient_append_vec(slot); + *self = Self::new(slot, Arc::clone(shrink_in_progress.new_storage())); + shrink_in_progress } - fn create_if_necessary(&mut self, slot: Slot, db: &AccountsDb) { + #[must_use] + fn create_if_necessary<'a>( + &mut self, + slot: Slot, + db: &'a AccountsDb, + ) -> Option> { if self.slot_and_append_vec.is_none() { - self.create_ancient_append_vec(slot, db); + Some(self.create_ancient_append_vec(slot, db)) + } else { + None } } @@ -3838,6 +3853,7 @@ impl AccountsDb { shrink_collect: &ShrinkCollect, slot: Slot, stats: &ShrinkStats, + shrink_in_progress: Option, ) -> usize { // Purge old, overwritten storage entries let (remaining_stores, dead_storages) = self.mark_dirty_dead_stores( @@ -3846,6 +3862,7 @@ impl AccountsDb { // If all accounts are zero lamports, then we want to mark the entire OLD append vec as dirty. // otherwise, we'll call 'add_uncleaned_pubkeys_after_shrink' just on the unref'd keys below. shrink_collect.all_are_zero_lamports, + shrink_in_progress, ); if !shrink_collect.all_are_zero_lamports { @@ -3900,7 +3917,7 @@ impl AccountsDb { let mut remove_old_stores_shrink_us = 0; let mut store_accounts_timing = StoreAccountsTiming::default(); if shrink_collect.aligned_total_bytes > 0 { - let (shrunken_store, time) = + let (shrink_in_progress, time) = measure!(self.get_store_for_shrink(slot, shrink_collect.aligned_total_bytes)); create_and_insert_store_elapsed_us = time.as_us(); @@ -3914,7 +3931,7 @@ impl AccountsDb { INCLUDE_SLOT_IN_HASH_IRRELEVANT_APPEND_VEC_OPERATION, ), None::>, - Some(&shrunken_store), + Some(shrink_in_progress.new_storage()), None, StoreReclaims::Ignore, ); @@ -3928,8 +3945,13 @@ impl AccountsDb { // those here self.shrink_candidate_slots.lock().unwrap().remove(&slot); - let (remaining_stores, remove_old_stores_shrink) = - measure!(self.remove_old_stores_shrink(&shrink_collect, slot, &self.shrink_stats)); + let (remaining_stores, remove_old_stores_shrink) = measure!(self + .remove_old_stores_shrink( + &shrink_collect, + slot, + &self.shrink_stats, + Some(shrink_in_progress) + )); remove_old_stores_shrink_us = remove_old_stores_shrink.as_us(); if remaining_stores > 1 { inc_new_counter_info!("accounts_db_shrink_extra_stores", 1); @@ -4000,23 +4022,38 @@ impl AccountsDb { slot: Slot, should_retain: impl Fn(&AccountStorageEntry) -> bool, add_dirty_stores: bool, + shrink_in_progress: Option, ) -> (usize, SnapshotStorage) { let mut dead_storages = Vec::default(); + + let mut not_retaining_store = |store: &Arc| { + if add_dirty_stores { + self.dirty_stores + .insert((slot, store.append_vec_id()), store.clone()); + } + dead_storages.push(store.clone()); + }; + let remaining_stores = if let Some(slot_stores) = self.storage.get_slot_stores(slot) { - let mut list = slot_stores.write().unwrap(); - list.retain(|_key, store| { - if !should_retain(store) { - if add_dirty_stores { - self.dirty_stores - .insert((slot, store.append_vec_id()), store.clone()); + if let Some(shrink_in_progress) = shrink_in_progress { + let store = shrink_in_progress.old_storage().clone(); + not_retaining_store(&store); + drop(shrink_in_progress); + slot_stores.read().unwrap().len() + } else { + let mut list = slot_stores.write().unwrap(); + list.retain(|_key, store| { + if !should_retain(store) { + if shrink_in_progress.is_none() { + not_retaining_store(store); + } + false + } else { + true } - dead_storages.push(store.clone()); - false - } else { - true - } - }); - list.len() + }); + list.len() + } } else { 0 }; @@ -4057,7 +4094,7 @@ impl AccountsDb { &self, slot: Slot, aligned_total: u64, - ) -> Arc { + ) -> ShrinkInProgress<'_> { let shrunken_store = self .try_recycle_store(slot, aligned_total, aligned_total + 1024) .unwrap_or_else(|| { @@ -4068,8 +4105,7 @@ impl AccountsDb { .unwrap_or_else(|| (&self.paths, "shrink")); self.create_store(slot, aligned_total, from, shrink_paths) }); - self.insert_store(slot, Arc::clone(&shrunken_store)); - shrunken_store + self.storage.shrinking_in_progress(slot, shrunken_store) } // Reads all accounts in given slot's AppendVecs and filter only to alive, @@ -4231,16 +4267,15 @@ impl AccountsDb { } /// create and return new ancient append vec - fn create_ancient_append_vec(&self, slot: Slot) -> Arc { - let new_ancient_storage = - self.get_store_for_shrink(slot, get_ancient_append_vec_capacity()); + fn create_ancient_append_vec(&self, slot: Slot) -> ShrinkInProgress<'_> { + let shrink_in_progress = self.get_store_for_shrink(slot, get_ancient_append_vec_capacity()); info!( "ancient_append_vec: creating initial ancient append vec: {}, size: {}, id: {}", slot, get_ancient_append_vec_capacity(), - new_ancient_storage.append_vec_id(), + shrink_in_progress.new_storage().append_vec_id(), ); - new_ancient_storage + shrink_in_progress } #[cfg(test)] @@ -4482,7 +4517,7 @@ impl AccountsDb { return; // skipping slot with no useful accounts to write } - let (_, time) = measure!(current_ancient.create_if_necessary(slot, self)); + let (shrink_in_progress, time) = measure!(current_ancient.create_if_necessary(slot, self)); let mut create_and_insert_store_elapsed_us = time.as_us(); let available_bytes = current_ancient.append_vec().accounts.remaining_bytes(); // split accounts in 'slot' into: @@ -4532,7 +4567,8 @@ impl AccountsDb { .remove_old_stores_shrink( &shrink_collect, slot, - &self.shrink_ancient_stats.shrink_stats + &self.shrink_ancient_stats.shrink_stats, + shrink_in_progress, )); // we should not try to shrink any of the stores from this slot anymore. All shrinking for this slot is now handled by ancient append vec code. @@ -9620,7 +9656,7 @@ pub mod tests { let slot0 = 0; let slot1 = 1; let available_bytes = 1_000_000; - let mut current_ancient = CurrentAncientAppendVec::default(); + let mut current_ancient; // setup 'to_store' let pubkey = Pubkey::new(&[1; 32]); @@ -9659,7 +9695,9 @@ pub mod tests { let to_store = AccountsToStore::new(available_bytes, &map, alive_total_bytes, slot0); // Done: setup 'to_store' - current_ancient.create_ancient_append_vec(slot0, &db); + // there has to be an existing append vec at this slot for a new current ancient at the slot to make sense + let _existing_append_vec = db.create_and_insert_store(slot0, 1000, "test"); + current_ancient = CurrentAncientAppendVec::create_ancient_append_vec(slot0, &db); let mut ancient_slot_pubkeys = AncientSlotPubkeys::default(); assert!(ancient_slot_pubkeys.inner.is_none()); // same slot as current_ancient, so no-op @@ -9671,7 +9709,9 @@ pub mod tests { ); assert!(ancient_slot_pubkeys.inner.is_none()); // different slot than current_ancient, so update 'ancient_slot_pubkeys' - current_ancient.create_ancient_append_vec(slot1, &db); + // there has to be an existing append vec at this slot for a new current ancient at the slot to make sense + let _existing_append_vec = db.create_and_insert_store(slot1, 1000, "test"); + current_ancient = CurrentAncientAppendVec::create_ancient_append_vec(slot1, &db); let slot2 = 2; ancient_slot_pubkeys.maybe_unref_accounts_already_in_ancient( slot2, @@ -16453,6 +16493,7 @@ pub mod tests { false }, add_dirty_stores, + None, ); assert_eq!(0, called.load(Ordering::Relaxed)); assert_eq!(0, remaining_stores); @@ -16467,6 +16508,7 @@ pub mod tests { true // retain }, add_dirty_stores, + None, ); assert_eq!(1, called.load(Ordering::Relaxed)); assert_eq!(1, remaining_stores); @@ -16480,6 +16522,7 @@ pub mod tests { false // don't retain }, add_dirty_stores, + None, ); assert_eq!(1, called.load(Ordering::Relaxed)); assert!(db @@ -16789,8 +16832,13 @@ pub mod tests { }; let db = AccountsDb::new_single_for_tests(); + // there has to be an existing append vec at this slot for a new current ancient at the slot to make sense + let _existing_append_vec = db.create_and_insert_store(slot1_ancient, 1000, "test"); + let ancient = db.create_ancient_append_vec(slot1_ancient); + let _existing_append_vec = db.create_and_insert_store(slot1_plus_ancient, 1000, "test"); let ancient_1_plus = db.create_ancient_append_vec(slot1_plus_ancient); + let _existing_append_vec = db.create_and_insert_store(slot3_ancient, 1000, "test"); let ancient3 = db.create_ancient_append_vec(slot3_ancient); let temp_dir = TempDir::new().unwrap(); let path = temp_dir.path(); @@ -16810,7 +16858,7 @@ pub mod tests { assert_eq!(Vec::::default(), ancient_slots); // now test with an ancient append vec - let raw_storages = vec![vec![ancient.clone()]]; + let raw_storages = vec![vec![ancient.new_storage().clone()]]; let snapshot_storages = SortedStorages::new(&raw_storages); let one_epoch_old_slot = 0; let ancient_slots = @@ -16822,7 +16870,10 @@ pub mod tests { assert_eq!(vec![slot1_ancient], ancient_slots); // now test with an ancient append vec and then a non-ancient append vec - let raw_storages = vec![vec![ancient.clone()], vec![non_ancient_storage.clone()]]; + let raw_storages = vec![ + vec![ancient.new_storage().clone()], + vec![non_ancient_storage.clone()], + ]; let snapshot_storages = SortedStorages::new(&raw_storages); let one_epoch_old_slot = 0; let ancient_slots = @@ -16835,9 +16886,9 @@ pub mod tests { // ancient, non-ancient, ancient let raw_storages = vec![ - vec![ancient.clone()], + vec![ancient.new_storage().clone()], vec![non_ancient_storage.clone()], - vec![ancient3.clone()], + vec![ancient3.new_storage().clone()], ]; let snapshot_storages = SortedStorages::new(&raw_storages); let one_epoch_old_slot = 0; @@ -16852,12 +16903,12 @@ pub mod tests { if sparse { // ancient, ancient, non-ancient, ancient let raw_storages = vec![ - vec![ancient], - vec![ancient_1_plus], + vec![Arc::clone(ancient.new_storage())], + vec![Arc::clone(ancient_1_plus.new_storage())], vec![non_ancient_storage], - vec![ancient3], + vec![Arc::clone(ancient3.new_storage())], ]; - let snapshot_storages = SortedStorages::new(&raw_storages); + let snapshot_storages = SortedStorages::new(&raw_storages[..]); let one_epoch_old_slot = 0; let ancient_slots = SplitAncientStorages::get_ancient_slots(one_epoch_old_slot, &snapshot_storages); @@ -16961,14 +17012,14 @@ pub mod tests { } #[test] - #[should_panic(expected = "called `Option::unwrap()` on a `None` value")] + #[should_panic(expected = "not implemented")] fn test_current_ancient_slot_assert() { let current_ancient = CurrentAncientAppendVec::default(); _ = current_ancient.slot(); } #[test] - #[should_panic(expected = "called `Option::unwrap()` on a `None` value")] + #[should_panic(expected = "not implemented")] fn test_current_ancient_append_vec_assert() { let current_ancient = CurrentAncientAppendVec::default(); _ = current_ancient.append_vec(); @@ -16984,7 +17035,8 @@ pub mod tests { let db = AccountsDb::new_single_for_tests(); let size = 1000; let append_vec = db.create_and_insert_store(slot, size, "test"); - let mut current_ancient = CurrentAncientAppendVec::new(slot, append_vec.clone()); + let mut current_ancient = + CurrentAncientAppendVec::new_slot_append_vec(slot, append_vec.clone()); assert_eq!(current_ancient.slot(), slot); assert_eq!(current_ancient.append_vec_id(), append_vec.append_vec_id()); assert_eq!( @@ -16992,7 +17044,7 @@ pub mod tests { append_vec.append_vec_id() ); - current_ancient.create_if_necessary(slot2, &db); + current_ancient = current_ancient.create_if_necessary(slot2, &db); assert_eq!(current_ancient.slot(), slot); assert_eq!(current_ancient.append_vec_id(), append_vec.append_vec_id()); } @@ -17000,14 +17052,17 @@ pub mod tests { { // create_if_necessary let db = AccountsDb::new_single_for_tests(); - let mut current_ancient = CurrentAncientAppendVec::default(); - current_ancient.create_if_necessary(slot2, &db); + // there has to be an existing append vec at this slot for a new current ancient at the slot to make sense + let _existing_append_vec = db.create_and_insert_store(slot2, 1000, "test"); + + let current_ancient = CurrentAncientAppendVec::default(); + let mut current_ancient = current_ancient.create_if_necessary(slot2, &db); let id = current_ancient.append_vec_id(); assert_eq!(current_ancient.slot(), slot2); assert!(is_ancient(¤t_ancient.append_vec().accounts)); let slot3 = 3; // should do nothing - current_ancient.create_if_necessary(slot3, &db); + current_ancient = current_ancient.create_if_necessary(slot3, &db); assert_eq!(current_ancient.slot(), slot2); assert_eq!(current_ancient.append_vec_id(), id); assert!(is_ancient(¤t_ancient.append_vec().accounts)); @@ -17016,12 +17071,20 @@ pub mod tests { { // create_ancient_append_vec let db = AccountsDb::new_single_for_tests(); - let mut current_ancient = CurrentAncientAppendVec::default(); - current_ancient.create_ancient_append_vec(slot2, &db); + let size = 1000; + // there has to be an existing append vec at this slot for a new current ancient at the slot to make sense + let _existing_append_vec = db.create_and_insert_store(slot2, 1000, "test"); + + let mut current_ancient; + current_ancient = CurrentAncientAppendVec::create_ancient_append_vec(slot2, &db); let id = current_ancient.append_vec_id(); assert_eq!(current_ancient.slot(), slot2); assert!(is_ancient(¤t_ancient.append_vec().accounts)); - current_ancient.create_ancient_append_vec(slot3, &db); + + // there has to be an existing append vec at this slot for a new current ancient at the slot to make sense + let _existing_append_vec = db.create_and_insert_store(slot3, size, "test"); + + current_ancient = CurrentAncientAppendVec::create_ancient_append_vec(slot3, &db); assert_eq!(current_ancient.slot(), slot3); assert!(is_ancient(¤t_ancient.append_vec().accounts)); assert_ne!(current_ancient.append_vec_id(), id); @@ -17059,9 +17122,9 @@ pub mod tests { assert_eq!(db.get_sorted_potential_ancient_slots(), vec![root1]); } - impl CurrentAncientAppendVec { + impl<'a> CurrentAncientAppendVec<'a> { fn is_none(&self) -> bool { - self.slot_and_append_vec.is_none() + matches!(self, CurrentAncientAppendVec::Uninitialized) } } @@ -17377,7 +17440,7 @@ pub mod tests { ); // now, shrink the second ancient append vec into the first one - let mut current_ancient = CurrentAncientAppendVec::new( + let current_ancient = CurrentAncientAppendVec::new_slot_append_vec( ancient_slot, Arc::clone( db.get_storages_for_slot(ancient_slot) @@ -17390,7 +17453,7 @@ pub mod tests { db.combine_one_store_into_ancient( next_slot, &db.get_storages_for_slot(next_slot).unwrap(), - &mut current_ancient, + current_ancient, &mut AncientSlotPubkeys::default(), &mut dropped_roots, ); @@ -17702,7 +17765,8 @@ pub mod tests { assert!(should_move); // try 2 storages in 1 slot, should not be able to move - current_ancient = CurrentAncientAppendVec::new(slot5, Arc::clone(&storages[0])); // just 'some', contents don't matter + current_ancient = + CurrentAncientAppendVec::new_slot_append_vec(slot5, Arc::clone(&storages[0])); // just 'some', contents don't matter let two_storages = vec![storages[0].clone(), storages[0].clone()]; let should_move = db.should_move_to_ancient_append_vec( &two_storages, @@ -17713,7 +17777,8 @@ pub mod tests { assert!(current_ancient.is_none()); assert!(!should_move); - current_ancient = CurrentAncientAppendVec::new(slot5, Arc::clone(&storages[0])); // just 'some', contents don't matter + current_ancient = + CurrentAncientAppendVec::new_slot_append_vec(slot5, Arc::clone(&storages[0])); // just 'some', contents don't matter let should_move = db.should_move_to_ancient_append_vec( &storages, &mut current_ancient, @@ -17731,40 +17796,52 @@ pub mod tests { // now, create an ancient slot and make sure that it does NOT think it needs to be moved and that it becomes the ancient append vec to use let mut current_ancient = CurrentAncientAppendVec::default(); let slot1_ancient = 1; + // there has to be an existing append vec at this slot for a new current ancient at the slot to make sense + let _existing_append_vec = db.create_and_insert_store(slot1_ancient, 1000, "test"); let ancient1 = db.create_ancient_append_vec(slot1_ancient); let should_move = db.should_move_to_ancient_append_vec( - &vec![ancient1.clone()], + &vec![ancient1.new_storage().clone()], &mut current_ancient, slot1_ancient, CAN_RANDOMLY_SHRINK_FALSE, ); assert!(!should_move); - assert_eq!(current_ancient.append_vec_id(), ancient1.append_vec_id()); + assert_eq!( + current_ancient.append_vec_id(), + ancient1.new_storage().append_vec_id() + ); assert_eq!(current_ancient.slot(), slot1_ancient); // current is ancient1 // try to move ancient2 // current should become ancient2 let slot2_ancient = 2; - let mut current_ancient = CurrentAncientAppendVec::new(slot1_ancient, ancient1.clone()); + let mut current_ancient = CurrentAncientAppendVec::new(ancient1); + // there has to be an existing append vec at this slot for a new current ancient at the slot to make sense + let _existing_append_vec = db.create_and_insert_store(slot2_ancient, 1000, "test"); let ancient2 = db.create_ancient_append_vec(slot2_ancient); let should_move = db.should_move_to_ancient_append_vec( - &vec![ancient2.clone()], + &vec![ancient2.new_storage().clone()], &mut current_ancient, slot2_ancient, CAN_RANDOMLY_SHRINK_FALSE, ); assert!(!should_move); - assert_eq!(current_ancient.append_vec_id(), ancient2.append_vec_id()); + assert_eq!( + current_ancient.append_vec_id(), + ancient2.new_storage().append_vec_id() + ); assert_eq!(current_ancient.slot(), slot2_ancient); // now try a full ancient append vec // current is None let slot3_full_ancient = 3; let mut current_ancient = CurrentAncientAppendVec::default(); + // there has to be an existing append vec at this slot for a new current ancient at the slot to make sense + let _existing_append_vec = db.create_and_insert_store(slot3_full_ancient, 1000, "test"); let full_ancient_3 = make_full_ancient_append_vec(&db, slot3_full_ancient); let should_move = db.should_move_to_ancient_append_vec( - &vec![full_ancient_3.clone()], + &vec![full_ancient_3.new_storage().clone()], &mut current_ancient, slot3_full_ancient, CAN_RANDOMLY_SHRINK_FALSE, @@ -17772,14 +17849,15 @@ pub mod tests { assert!(!should_move); assert_eq!( current_ancient.append_vec_id(), - full_ancient_3.append_vec_id() + full_ancient_3.new_storage().append_vec_id() ); assert_eq!(current_ancient.slot(), slot3_full_ancient); // now set current_ancient to something - let mut current_ancient = CurrentAncientAppendVec::new(slot1_ancient, ancient1.clone()); + let ancient1 = db.create_ancient_append_vec(slot1_ancient); + let mut current_ancient = CurrentAncientAppendVec::new(ancient1); let should_move = db.should_move_to_ancient_append_vec( - &vec![full_ancient_3.clone()], + &vec![full_ancient_3.new_storage().clone()], &mut current_ancient, slot3_full_ancient, CAN_RANDOMLY_SHRINK_FALSE, @@ -17787,17 +17865,17 @@ pub mod tests { assert!(!should_move); assert_eq!( current_ancient.append_vec_id(), - full_ancient_3.append_vec_id() + full_ancient_3.new_storage().append_vec_id() ); assert_eq!(current_ancient.slot(), slot3_full_ancient); // now mark the full ancient as candidate for shrink - adjust_alive_bytes(&full_ancient_3, 0); + adjust_alive_bytes(full_ancient_3.new_storage(), 0); // should shrink here, returning none for current let mut current_ancient = CurrentAncientAppendVec::default(); let should_move = db.should_move_to_ancient_append_vec( - &vec![full_ancient_3.clone()], + &vec![full_ancient_3.new_storage().clone()], &mut current_ancient, slot3_full_ancient, CAN_RANDOMLY_SHRINK_FALSE, @@ -17807,15 +17885,19 @@ pub mod tests { // should return true here, returning current from prior // now set current_ancient to something and see if it still goes to None - let mut current_ancient = CurrentAncientAppendVec::new(slot1_ancient, ancient1.clone()); + let ancient1 = db.create_ancient_append_vec(slot1_ancient); + let mut current_ancient = CurrentAncientAppendVec::new(ancient1); let should_move = db.should_move_to_ancient_append_vec( - &vec![full_ancient_3], + &vec![Arc::clone(full_ancient_3.new_storage())], &mut current_ancient, slot3_full_ancient, CAN_RANDOMLY_SHRINK_FALSE, ); assert!(should_move); - assert_eq!(current_ancient.append_vec_id(), ancient1.append_vec_id()); + assert_eq!( + current_ancient.append_vec_id(), + current_ancient.append_vec_id() + ); assert_eq!(current_ancient.slot(), slot1_ancient); } @@ -17831,9 +17913,9 @@ pub mod tests { adjust_alive_bytes(ancient, ancient.total_bytes() as usize); } - fn make_full_ancient_append_vec(db: &AccountsDb, slot: Slot) -> Arc { + fn make_full_ancient_append_vec(db: &AccountsDb, slot: Slot) -> ShrinkInProgress<'_> { let full = db.create_ancient_append_vec(slot); - make_ancient_append_vec_full(&full); + make_ancient_append_vec_full(full.new_storage()); full } } diff --git a/runtime/src/snapshot_minimizer.rs b/runtime/src/snapshot_minimizer.rs index 2e1591bfe0e301..ca47336cb6bf18 100644 --- a/runtime/src/snapshot_minimizer.rs +++ b/runtime/src/snapshot_minimizer.rs @@ -351,6 +351,7 @@ impl<'a> SnapshotMinimizer<'a> { let _ = self.accounts_db().purge_keys_exact(purge_pubkeys.iter()); let aligned_total: u64 = AccountsDb::page_align(total_bytes as u64); + let mut shrink_in_progress = None; if aligned_total > 0 { let mut accounts = Vec::with_capacity(keep_accounts.len()); let mut hashes = Vec::with_capacity(keep_accounts.len()); @@ -362,7 +363,8 @@ impl<'a> SnapshotMinimizer<'a> { write_versions.push(alive_account.account.meta.write_version_obsolete); } - let new_storage = self.accounts_db().get_store_for_shrink(slot, aligned_total); + shrink_in_progress = Some(self.accounts_db().get_store_for_shrink(slot, aligned_total)); + let new_storage = shrink_in_progress.as_ref().unwrap().new_storage(); self.accounts_db().store_accounts_frozen( ( slot, @@ -370,7 +372,7 @@ impl<'a> SnapshotMinimizer<'a> { crate::accounts_db::INCLUDE_SLOT_IN_HASH_IRRELEVANT_APPEND_VEC_OPERATION, ), Some(hashes), - Some(&new_storage), + Some(new_storage), Some(Box::new(write_versions.into_iter())), StoreReclaims::Default, ); @@ -386,6 +388,7 @@ impl<'a> SnapshotMinimizer<'a> { slot, |store| !append_vec_set.contains(&store.append_vec_id()), true, // add_dirty_stores + shrink_in_progress, ); dead_storages .lock()