diff --git a/bucket_map/src/bucket.rs b/bucket_map/src/bucket.rs index b1c1eabd1c..1761adcefb 100644 --- a/bucket_map/src/bucket.rs +++ b/bucket_map/src/bucket.rs @@ -78,10 +78,10 @@ impl Reallocated { } // >= 2 instances of BucketStorage per 'bucket' in the bucket map. 1 for index, >= 1 for data -pub struct Bucket { +pub struct Bucket { drives: Arc>, //index - pub index: BucketStorage, + pub index: BucketStorage>, //random offset for the index random: u64, //storage buckets to store SlotSlice up to a power of 2 in len @@ -89,7 +89,7 @@ pub struct Bucket { _phantom: PhantomData, stats: Arc, - pub reallocated: Reallocated, + pub reallocated: Reallocated, DataBucket>, } impl<'b, T: Clone + Copy + 'static> Bucket { @@ -156,7 +156,7 @@ impl<'b, T: Clone + Copy + 'static> Bucket { result } - pub fn find_index_entry(&self, key: &Pubkey) -> Option<(IndexEntryPlaceInBucket, u64)> { + pub fn find_index_entry(&self, key: &Pubkey) -> Option<(IndexEntryPlaceInBucket, u64)> { Self::bucket_find_index_entry(&self.index, key, self.random) } @@ -165,10 +165,10 @@ impl<'b, T: Clone + Copy + 'static> Bucket { /// if entry does not exist, return just the index of an empty entry appropriate for this key /// returns (existing entry, index of the found or empty entry) fn find_index_entry_mut( - index: &mut BucketStorage, + index: &mut BucketStorage>, key: &Pubkey, random: u64, - ) -> Result<(Option, u64), BucketMapError> { + ) -> Result<(Option>, u64), BucketMapError> { let ix = Self::bucket_index_ix(index, key, random); let mut first_free = None; let mut m = Measure::start("bucket_find_index_entry_mut"); @@ -204,10 +204,10 @@ impl<'b, T: Clone + Copy + 'static> Bucket { } fn bucket_find_index_entry( - index: &BucketStorage, + index: &BucketStorage>, key: &Pubkey, random: u64, - ) -> Option<(IndexEntryPlaceInBucket, u64)> { + ) -> Option<(IndexEntryPlaceInBucket, u64)> { let ix = Self::bucket_index_ix(index, key, random); for i in ix..ix + index.max_search() { let ii = i % index.capacity(); @@ -223,7 +223,7 @@ impl<'b, T: Clone + Copy + 'static> Bucket { } fn bucket_create_key( - index: &mut BucketStorage, + index: &mut BucketStorage>, key: &Pubkey, random: u64, is_resizing: bool, @@ -421,7 +421,7 @@ impl<'b, T: Clone + Copy + 'static> Bucket { } } - pub fn apply_grow_index(&mut self, random: u64, index: BucketStorage) { + pub fn apply_grow_index(&mut self, random: u64, index: BucketStorage>) { self.stats .index .resize_grow(self.index.capacity_bytes(), index.capacity_bytes()); @@ -480,7 +480,7 @@ impl<'b, T: Clone + Copy + 'static> Bucket { items.data = Some((data_index, new_bucket)); } - fn bucket_index_ix(index: &BucketStorage, key: &Pubkey, random: u64) -> u64 { + fn bucket_index_ix(index: &BucketStorage>, key: &Pubkey, random: u64) -> u64 { let mut s = DefaultHasher::new(); key.hash(&mut s); //the locally generated random will make it hard for an attacker diff --git a/bucket_map/src/bucket_storage.rs b/bucket_map/src/bucket_storage.rs index b03990f3c9..1fd63a5199 100644 --- a/bucket_map/src/bucket_storage.rs +++ b/bucket_map/src/bucket_storage.rs @@ -370,7 +370,7 @@ mod test { let paths: Vec = vec![tmpdir.path().to_path_buf()]; assert!(!paths.is_empty()); - let mut storage = BucketStorage::::new( + let mut storage = BucketStorage::>::new( Arc::new(paths), 1, 1, diff --git a/bucket_map/src/index_entry.rs b/bucket_map/src/index_entry.rs index 8a5f360ef2..8507de8b68 100644 --- a/bucket_map/src/index_entry.rs +++ b/bucket_map/src/index_entry.rs @@ -8,7 +8,7 @@ use { bv::BitVec, modular_bitfield::prelude::*, solana_sdk::{clock::Slot, pubkey::Pubkey}, - std::fmt::Debug, + std::{fmt::Debug, marker::PhantomData}, }; /// in use/occupied @@ -25,11 +25,12 @@ struct OccupiedHeader { } /// allocated in `contents` in a BucketStorage -pub struct BucketWithBitVec { +pub struct BucketWithBitVec { pub occupied: BitVec, + _phantom: PhantomData<&'static T>, } -impl BucketOccupied for BucketWithBitVec { +impl BucketOccupied for BucketWithBitVec { fn occupy(&mut self, element: &mut [u8], ix: usize) { assert!(self.is_free(element, ix)); self.occupied.set(ix as u64, true); @@ -48,17 +49,19 @@ impl BucketOccupied for BucketWithBitVec { fn new(num_elements: usize) -> Self { Self { occupied: BitVec::new_fill(false, num_elements as u64), + _phantom: PhantomData, } } } -pub type DataBucket = BucketWithBitVec; -pub type IndexBucket = BucketWithBitVec; +pub type DataBucket = BucketWithBitVec<()>; +pub type IndexBucket = BucketWithBitVec; /// contains the index of an entry in the index bucket. /// This type allows us to call methods to interact with the index entry on this type. -pub struct IndexEntryPlaceInBucket { +pub struct IndexEntryPlaceInBucket { pub ix: u64, + _phantom: PhantomData<&'static T>, } #[repr(C)] @@ -98,8 +101,8 @@ impl IndexEntry { } } -impl IndexEntryPlaceInBucket { - pub fn init(&self, index_bucket: &mut BucketStorage, pubkey: &Pubkey) { +impl IndexEntryPlaceInBucket { + pub fn init(&self, index_bucket: &mut BucketStorage>, pubkey: &Pubkey) { let index_entry = index_bucket.get_mut::(self.ix); index_entry.key = *pubkey; index_entry.ref_count = 0; @@ -109,7 +112,7 @@ impl IndexEntryPlaceInBucket { pub fn set_storage_capacity_when_created_pow2( &self, - index_bucket: &mut BucketStorage, + index_bucket: &mut BucketStorage>, storage_capacity_when_created_pow2: u8, ) { index_bucket @@ -120,7 +123,7 @@ impl IndexEntryPlaceInBucket { pub fn set_storage_offset( &self, - index_bucket: &mut BucketStorage, + index_bucket: &mut BucketStorage>, storage_offset: u64, ) { index_bucket @@ -130,23 +133,26 @@ impl IndexEntryPlaceInBucket { .expect("New storage offset must fit into 7 bytes!"); } - pub fn data_bucket_ix(&self, index_bucket: &BucketStorage) -> u64 { + pub fn data_bucket_ix(&self, index_bucket: &BucketStorage>) -> u64 { IndexEntry::data_bucket_from_num_slots(self.num_slots(index_bucket)) } - pub fn ref_count(&self, index_bucket: &BucketStorage) -> RefCount { + pub fn ref_count(&self, index_bucket: &BucketStorage>) -> RefCount { let index_entry = index_bucket.get::(self.ix); index_entry.ref_count } - fn storage_capacity_when_created_pow2(&self, index_bucket: &BucketStorage) -> u8 { + fn storage_capacity_when_created_pow2( + &self, + index_bucket: &BucketStorage>, + ) -> u8 { let index_entry = index_bucket.get::(self.ix); index_entry .storage_cap_and_offset .capacity_when_created_pow2() } - pub fn storage_offset(&self, index_bucket: &BucketStorage) -> u64 { + pub fn storage_offset(&self, index_bucket: &BucketStorage>) -> u64 { index_bucket .get::(self.ix) .storage_cap_and_offset @@ -157,7 +163,7 @@ impl IndexEntryPlaceInBucket { /// This is coupled with how we resize bucket storages. pub fn data_loc( &self, - index_bucket: &BucketStorage, + index_bucket: &BucketStorage>, storage: &BucketStorage, ) -> u64 { let index_entry = index_bucket.get::(self.ix); @@ -168,9 +174,9 @@ impl IndexEntryPlaceInBucket { .capacity_when_created_pow2()) } - pub fn read_value<'a, T>( + pub fn read_value<'a>( &self, - index_bucket: &BucketStorage, + index_bucket: &BucketStorage>, data_buckets: &'a [BucketStorage], ) -> Option<(&'a [T], RefCount)> { let num_slots = self.num_slots(index_bucket); @@ -188,28 +194,31 @@ impl IndexEntryPlaceInBucket { } pub fn new(ix: u64) -> Self { - Self { ix } + Self { + ix, + _phantom: PhantomData, + } } - pub fn key<'a>(&self, index_bucket: &'a BucketStorage) -> &'a Pubkey { + pub fn key<'a>(&self, index_bucket: &'a BucketStorage>) -> &'a Pubkey { let entry: &IndexEntry = index_bucket.get(self.ix); &entry.key } pub fn set_ref_count( &self, - index_bucket: &mut BucketStorage, + index_bucket: &mut BucketStorage>, ref_count: RefCount, ) { let index_entry = index_bucket.get_mut::(self.ix); index_entry.ref_count = ref_count; } - pub fn num_slots(&self, index_bucket: &BucketStorage) -> Slot { + pub fn num_slots(&self, index_bucket: &BucketStorage>) -> Slot { index_bucket.get::(self.ix).num_slots } - pub fn set_num_slots(&self, index_bucket: &mut BucketStorage, num_slots: Slot) { + pub fn set_num_slots(&self, index_bucket: &mut BucketStorage>, num_slots: Slot) { index_bucket.get_mut::(self.ix).num_slots = num_slots; } } @@ -261,13 +270,13 @@ mod tests { assert_eq!(std::mem::size_of::(), 32 + 8 + 8 + 8); } - fn index_bucket_for_testing() -> BucketStorage { + fn index_bucket_for_testing() -> BucketStorage> { let tmpdir = tempdir().unwrap(); let paths: Vec = vec![tmpdir.path().to_path_buf()]; assert!(!paths.is_empty()); // `new` here creates a file in `tmpdir`. Once the file is created, `tmpdir` can be dropped without issue. - BucketStorage::::new( + BucketStorage::>::new( Arc::new(paths), 1, std::mem::size_of::() as u64, @@ -277,7 +286,10 @@ mod tests { ) } - fn index_entry_for_testing() -> (BucketStorage, IndexEntryPlaceInBucket) { + fn index_entry_for_testing() -> ( + BucketStorage>, + IndexEntryPlaceInBucket, + ) { (index_bucket_for_testing(), IndexEntryPlaceInBucket::new(0)) }