Disk buckets: abstract UID_UNLOCKED (#22051)
This commit is contained in:
parent
711856cad3
commit
b36f7151fc
|
@ -3,7 +3,7 @@ use {
|
|||
bucket_item::BucketItem,
|
||||
bucket_map::BucketMapError,
|
||||
bucket_stats::BucketMapStats,
|
||||
bucket_storage::{BucketStorage, Uid, DEFAULT_CAPACITY_POW2, UID_UNLOCKED},
|
||||
bucket_storage::{BucketStorage, Uid, DEFAULT_CAPACITY_POW2},
|
||||
index_entry::IndexEntry,
|
||||
MaxSearch, RefCount,
|
||||
},
|
||||
|
@ -105,7 +105,7 @@ impl<T: Clone + Copy> Bucket<T> {
|
|||
pub fn keys(&self) -> Vec<Pubkey> {
|
||||
let mut rv = vec![];
|
||||
for i in 0..self.index.capacity() {
|
||||
if self.index.uid(i) == UID_UNLOCKED {
|
||||
if self.index.uid(i).is_none() {
|
||||
continue;
|
||||
}
|
||||
let ix: &IndexEntry = self.index.get(i);
|
||||
|
@ -121,7 +121,7 @@ impl<T: Clone + Copy> Bucket<T> {
|
|||
let mut result = Vec::with_capacity(self.index.count.load(Ordering::Relaxed) as usize);
|
||||
for i in 0..self.index.capacity() {
|
||||
let ii = i % self.index.capacity();
|
||||
if self.index.uid(ii) == UID_UNLOCKED {
|
||||
if self.index.uid(ii).is_none() {
|
||||
continue;
|
||||
}
|
||||
let ix: &IndexEntry = self.index.get(ii);
|
||||
|
@ -154,7 +154,7 @@ impl<T: Clone + Copy> Bucket<T> {
|
|||
let ix = Self::bucket_index_ix(index, key, random);
|
||||
for i in ix..ix + index.max_search() {
|
||||
let ii = i % index.capacity();
|
||||
if index.uid(ii) == UID_UNLOCKED {
|
||||
if index.uid(ii).is_none() {
|
||||
continue;
|
||||
}
|
||||
let elem: &mut IndexEntry = index.get_mut(ii);
|
||||
|
@ -173,7 +173,7 @@ impl<T: Clone + Copy> Bucket<T> {
|
|||
let ix = Self::bucket_index_ix(index, key, random);
|
||||
for i in ix..ix + index.max_search() {
|
||||
let ii = i % index.capacity();
|
||||
if index.uid(ii) == UID_UNLOCKED {
|
||||
if index.uid(ii).is_none() {
|
||||
continue;
|
||||
}
|
||||
let elem: &IndexEntry = index.get(ii);
|
||||
|
@ -194,7 +194,7 @@ impl<T: Clone + Copy> Bucket<T> {
|
|||
let ix = Self::bucket_index_ix(index, key, random);
|
||||
for i in ix..ix + index.max_search() {
|
||||
let ii = i as u64 % index.capacity();
|
||||
if index.uid(ii) != UID_UNLOCKED {
|
||||
if index.uid(ii).is_some() {
|
||||
continue;
|
||||
}
|
||||
index.allocate(ii, elem_uid, is_resizing).unwrap();
|
||||
|
@ -257,14 +257,14 @@ impl<T: Clone + Copy> Bucket<T> {
|
|||
Some(res) => res,
|
||||
};
|
||||
elem.ref_count = ref_count;
|
||||
let elem_uid = self.index.uid(elem_ix);
|
||||
let elem_uid = self.index.uid_unchecked(elem_ix);
|
||||
let bucket_ix = elem.data_bucket_ix();
|
||||
let current_bucket = &self.data[bucket_ix as usize];
|
||||
if best_fit_bucket == bucket_ix && elem.num_slots > 0 {
|
||||
// in place update
|
||||
let elem_loc = elem.data_loc(current_bucket);
|
||||
let slice: &mut [T] = current_bucket.get_mut_cell_slice(elem_loc, data.len() as u64);
|
||||
assert!(current_bucket.uid(elem_loc) == elem_uid);
|
||||
assert!(current_bucket.uid(elem_loc) == Some(elem_uid));
|
||||
elem.num_slots = data.len() as u64;
|
||||
slice.copy_from_slice(data);
|
||||
Ok(())
|
||||
|
@ -276,7 +276,7 @@ impl<T: Clone + Copy> Bucket<T> {
|
|||
let pos = thread_rng().gen_range(0, cap);
|
||||
for i in pos..pos + self.index.max_search() {
|
||||
let ix = i % cap;
|
||||
if best_bucket.uid(ix) == UID_UNLOCKED {
|
||||
if best_bucket.uid(ix).is_none() {
|
||||
let elem_loc = elem.data_loc(current_bucket);
|
||||
if elem.num_slots > 0 {
|
||||
current_bucket.free(elem_loc, elem_uid);
|
||||
|
@ -299,7 +299,7 @@ impl<T: Clone + Copy> Bucket<T> {
|
|||
|
||||
pub fn delete_key(&mut self, key: &Pubkey) {
|
||||
if let Some((elem, elem_ix)) = self.find_entry(key) {
|
||||
let elem_uid = self.index.uid(elem_ix);
|
||||
let elem_uid = self.index.uid_unchecked(elem_ix);
|
||||
if elem.num_slots > 0 {
|
||||
let data_bucket = &self.data[elem.data_bucket_ix() as usize];
|
||||
let loc = elem.data_loc(data_bucket);
|
||||
|
@ -334,7 +334,7 @@ impl<T: Clone + Copy> Bucket<T> {
|
|||
let mut valid = true;
|
||||
for ix in 0..self.index.capacity() {
|
||||
let uid = self.index.uid(ix);
|
||||
if UID_UNLOCKED != uid {
|
||||
if let Some(uid) = uid {
|
||||
let elem: &IndexEntry = self.index.get(ix);
|
||||
let new_ix = Self::bucket_create_key(&index, &elem.key, uid, random, true);
|
||||
if new_ix.is_err() {
|
||||
|
|
|
@ -35,7 +35,7 @@ use {
|
|||
pub const DEFAULT_CAPACITY_POW2: u8 = 5;
|
||||
|
||||
/// A Header UID of 0 indicates that the header is unlocked
|
||||
pub(crate) const UID_UNLOCKED: Uid = 0;
|
||||
const UID_UNLOCKED: Uid = 0;
|
||||
|
||||
pub(crate) type Uid = u64;
|
||||
|
||||
|
@ -54,8 +54,13 @@ impl Header {
|
|||
fn unlock(&self) -> Uid {
|
||||
self.lock.swap(UID_UNLOCKED, Ordering::Release)
|
||||
}
|
||||
fn uid(&self) -> Uid {
|
||||
self.lock.load(Ordering::Acquire)
|
||||
fn uid(&self) -> Option<Uid> {
|
||||
let result = self.lock.load(Ordering::Acquire);
|
||||
if result == UID_UNLOCKED {
|
||||
None
|
||||
} else {
|
||||
Some(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,11 +141,16 @@ impl BucketStorage {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn uid(&self, ix: u64) -> Uid {
|
||||
pub fn uid(&self, ix: u64) -> Option<Uid> {
|
||||
assert!(ix < self.capacity(), "bad index size");
|
||||
self.header_ptr(ix).uid()
|
||||
}
|
||||
|
||||
/// caller knows id is not empty
|
||||
pub fn uid_unchecked(&self, ix: u64) -> Uid {
|
||||
self.uid(ix).unwrap()
|
||||
}
|
||||
|
||||
/// 'is_resizing' true if caller is resizing the index (so don't increment count)
|
||||
/// 'is_resizing' false if caller is adding an item to the index (so increment count)
|
||||
pub fn allocate(&self, ix: u64, uid: Uid, is_resizing: bool) -> Result<(), BucketStorageError> {
|
||||
|
|
|
@ -69,7 +69,7 @@ impl IndexEntry {
|
|||
let slice = if self.num_slots > 0 {
|
||||
let loc = self.data_loc(data_bucket);
|
||||
let uid = Self::key_uid(&self.key);
|
||||
assert_eq!(uid, bucket.data[data_bucket_ix as usize].uid(loc));
|
||||
assert_eq!(Some(uid), bucket.data[data_bucket_ix as usize].uid(loc));
|
||||
bucket.data[data_bucket_ix as usize].get_cell_slice(loc, self.num_slots)
|
||||
} else {
|
||||
// num_slots is 0. This means we don't have an actual allocation.
|
||||
|
|
Loading…
Reference in New Issue