-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Adds get_with_and_then() to AccountsIndex #35307
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1141,6 +1141,26 @@ impl<T: IndexValue, U: DiskIndexValue + From<T> + Into<T>> AccountsIndex<T, U> { | |
self.get_bin(pubkey).get_internal(pubkey, callback) | ||
} | ||
|
||
/// Gets the index's entry for `pubkey`, with `ancestors` and `max_root`, | ||
/// and applies `callback` to it | ||
pub(crate) fn get_with_and_then<R>( | ||
&self, | ||
pubkey: &Pubkey, | ||
ancestors: Option<&Ancestors>, | ||
max_root: Option<Slot>, | ||
should_add_to_in_mem_cache: bool, | ||
mut callback: impl FnMut((Slot, T)) -> R, | ||
) -> Option<R> { | ||
self.get_and_then(pubkey, |entry| { | ||
let callback_result = entry.and_then(|entry| { | ||
let slot_list = entry.slot_list.read().unwrap(); | ||
self.latest_slot(ancestors, &slot_list, max_root) | ||
.map(|found_index| callback(slot_list[found_index])) | ||
}); | ||
(should_add_to_in_mem_cache, callback_result) | ||
}) | ||
} | ||
|
||
/// Gets the index's entry for `pubkey` and clones it | ||
/// | ||
/// Prefer `get_and_then()` whenever possible. | ||
|
@@ -1154,6 +1174,17 @@ impl<T: IndexValue, U: DiskIndexValue + From<T> + Into<T>> AccountsIndex<T, U> { | |
self.get_and_then(pubkey, |entry| (false, entry.is_some())) | ||
} | ||
|
||
/// Is `pubkey`, with `ancestors` and `max_root`, in the index? | ||
pub fn contains_with( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. pub(crate)? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I can do that. For the most part, all of AccountsIndex really should not be public to the world, only the accounts db crate, right? Another way to handle this is to remove the (Mostly trying to avoid (1) unnecessary CI runs and (2) creating inconsistency within the accounts index code.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done in 97c3313. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My thought process is that Simultaneously we do not want others to call into AccountsIndex. So only AccountsDb would have visibility to AccountsIndex, and all others would not. Thus only AccountsDb could call AccountsIndex functions. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah bummer... Because this PR doesn't use Do you have a preference for resolution? I could mark these functions are dead code in this PR, and remove the annotations in future PRs. Or I could change the vis to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'm ok with marked as dead code. Isn't there a cfg[test] or something? Not a huge deal. Just trying to get it right with each commit. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I could decorate the functions with
Yah, I prefer that way too. IMO I still think There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
yes, that's what I'd prefer. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'm inclined to say make as little There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Decorated with |
||
&self, | ||
pubkey: &Pubkey, | ||
ancestors: Option<&Ancestors>, | ||
max_root: Option<Slot>, | ||
) -> bool { | ||
self.get_with_and_then(pubkey, ancestors, max_root, false, |_| ()) | ||
.is_some() | ||
} | ||
|
||
fn slot_list_mut<RT>( | ||
&self, | ||
pubkey: &Pubkey, | ||
|
@@ -2158,8 +2189,8 @@ pub mod tests { | |
let index = AccountsIndex::<bool, bool>::default_for_tests(); | ||
let ancestors = Ancestors::default(); | ||
let key = &key; | ||
assert!(index.get_for_tests(key, Some(&ancestors), None).is_none()); | ||
assert!(index.get_for_tests(key, None, None).is_none()); | ||
assert!(!index.contains_with(key, Some(&ancestors), None)); | ||
assert!(!index.contains_with(key, None, None)); | ||
|
||
let mut num = 0; | ||
index.unchecked_scan_accounts( | ||
|
@@ -2287,8 +2318,8 @@ pub mod tests { | |
assert!(gc.is_empty()); | ||
|
||
let ancestors = Ancestors::default(); | ||
assert!(index.get_for_tests(&key, Some(&ancestors), None).is_none()); | ||
assert!(index.get_for_tests(&key, None, None).is_none()); | ||
assert!(!index.contains_with(&key, Some(&ancestors), None)); | ||
assert!(!index.contains_with(&key, None, None)); | ||
|
||
let mut num = 0; | ||
index.unchecked_scan_accounts( | ||
|
@@ -2370,10 +2401,8 @@ pub mod tests { | |
index.set_startup(Startup::Normal); | ||
|
||
let mut ancestors = Ancestors::default(); | ||
assert!(index | ||
.get_for_tests(pubkey, Some(&ancestors), None) | ||
.is_none()); | ||
assert!(index.get_for_tests(pubkey, None, None).is_none()); | ||
assert!(!index.contains_with(pubkey, Some(&ancestors), None)); | ||
assert!(!index.contains_with(pubkey, None, None)); | ||
|
||
let mut num = 0; | ||
index.unchecked_scan_accounts( | ||
|
@@ -2384,9 +2413,7 @@ pub mod tests { | |
); | ||
assert_eq!(num, 0); | ||
ancestors.insert(slot, 0); | ||
assert!(index | ||
.get_for_tests(pubkey, Some(&ancestors), None) | ||
.is_some()); | ||
assert!(index.contains_with(pubkey, Some(&ancestors), None)); | ||
assert_eq!(index.ref_count_from_storage(pubkey), 1); | ||
index.unchecked_scan_accounts( | ||
"", | ||
|
@@ -2408,10 +2435,8 @@ pub mod tests { | |
index.set_startup(Startup::Normal); | ||
|
||
let mut ancestors = Ancestors::default(); | ||
assert!(index | ||
.get_for_tests(pubkey, Some(&ancestors), None) | ||
.is_none()); | ||
assert!(index.get_for_tests(pubkey, None, None).is_none()); | ||
assert!(!index.contains_with(pubkey, Some(&ancestors), None)); | ||
assert!(!index.contains_with(pubkey, None, None)); | ||
|
||
let mut num = 0; | ||
index.unchecked_scan_accounts( | ||
|
@@ -2422,9 +2447,7 @@ pub mod tests { | |
); | ||
assert_eq!(num, 0); | ||
ancestors.insert(slot, 0); | ||
assert!(index | ||
.get_for_tests(pubkey, Some(&ancestors), None) | ||
.is_some()); | ||
assert!(index.contains_with(pubkey, Some(&ancestors), None)); | ||
assert_eq!(index.ref_count_from_storage(pubkey), 1); | ||
index.unchecked_scan_accounts( | ||
"", | ||
|
@@ -2686,8 +2709,8 @@ pub mod tests { | |
assert_eq!(1, account_maps_stats_len(&index)); | ||
|
||
let mut ancestors = Ancestors::default(); | ||
assert!(index.get_for_tests(&key, Some(&ancestors), None).is_none()); | ||
assert!(index.get_for_tests(&key, None, None).is_none()); | ||
assert!(!index.contains_with(&key, Some(&ancestors), None)); | ||
assert!(!index.contains_with(&key, None, None)); | ||
|
||
let mut num = 0; | ||
index.unchecked_scan_accounts( | ||
|
@@ -2698,7 +2721,7 @@ pub mod tests { | |
); | ||
assert_eq!(num, 0); | ||
ancestors.insert(slot, 0); | ||
assert!(index.get_for_tests(&key, Some(&ancestors), None).is_some()); | ||
assert!(index.contains_with(&key, Some(&ancestors), None)); | ||
index.unchecked_scan_accounts( | ||
"", | ||
&ancestors, | ||
|
@@ -2726,7 +2749,7 @@ pub mod tests { | |
assert!(gc.is_empty()); | ||
|
||
let ancestors = vec![(1, 1)].into_iter().collect(); | ||
assert!(index.get_for_tests(&key, Some(&ancestors), None).is_none()); | ||
assert!(!index.contains_with(&key, Some(&ancestors), None)); | ||
|
||
let mut num = 0; | ||
index.unchecked_scan_accounts( | ||
|
@@ -2851,8 +2874,18 @@ pub mod tests { | |
assert!(gc.is_empty()); | ||
|
||
let ancestors = vec![(0, 0)].into_iter().collect(); | ||
let (list, idx) = index.get_for_tests(&key, Some(&ancestors), None).unwrap(); | ||
assert_eq!(list.slot_list()[idx], (0, true)); | ||
index | ||
.get_with_and_then( | ||
&key, | ||
Some(&ancestors), | ||
None, | ||
false, | ||
|(slot, account_info)| { | ||
assert_eq!(slot, 0); | ||
assert!(account_info); | ||
}, | ||
) | ||
.unwrap(); | ||
|
||
let mut num = 0; | ||
let mut found_key = false; | ||
|
@@ -3076,8 +3109,12 @@ pub mod tests { | |
assert!(gc.is_empty()); | ||
|
||
index.add_root(0); | ||
let (list, idx) = index.get_for_tests(&key, None, None).unwrap(); | ||
assert_eq!(list.slot_list()[idx], (0, true)); | ||
index | ||
.get_with_and_then(&key, None, None, false, |(slot, account_info)| { | ||
assert_eq!(slot, 0); | ||
assert!(account_info); | ||
}) | ||
.unwrap(); | ||
} | ||
|
||
#[test] | ||
|
@@ -3146,9 +3183,18 @@ pub mod tests { | |
UPSERT_POPULATE_RECLAIMS, | ||
); | ||
assert!(gc.is_empty()); | ||
let (list, idx) = index.get_for_tests(&key, Some(&ancestors), None).unwrap(); | ||
assert_eq!(list.slot_list()[idx], (0, true)); | ||
drop(list); | ||
index | ||
.get_with_and_then( | ||
&key, | ||
Some(&ancestors), | ||
None, | ||
false, | ||
|(slot, account_info)| { | ||
assert_eq!(slot, 0); | ||
assert!(account_info); | ||
}, | ||
) | ||
.unwrap(); | ||
|
||
let mut gc = Vec::new(); | ||
index.upsert( | ||
|
@@ -3162,8 +3208,18 @@ pub mod tests { | |
UPSERT_POPULATE_RECLAIMS, | ||
); | ||
assert_eq!(gc, vec![(0, true)]); | ||
let (list, idx) = index.get_for_tests(&key, Some(&ancestors), None).unwrap(); | ||
assert_eq!(list.slot_list()[idx], (0, false)); | ||
index | ||
.get_with_and_then( | ||
&key, | ||
Some(&ancestors), | ||
None, | ||
false, | ||
|(slot, account_info)| { | ||
assert_eq!(slot, 0); | ||
assert!(!account_info); | ||
}, | ||
) | ||
.unwrap(); | ||
} | ||
|
||
#[test] | ||
|
@@ -3195,11 +3251,31 @@ pub mod tests { | |
UPSERT_POPULATE_RECLAIMS, | ||
); | ||
assert!(gc.is_empty()); | ||
let (list, idx) = index.get_for_tests(&key, Some(&ancestors), None).unwrap(); | ||
assert_eq!(list.slot_list()[idx], (0, true)); | ||
index | ||
.get_with_and_then( | ||
&key, | ||
Some(&ancestors), | ||
None, | ||
false, | ||
|(slot, account_info)| { | ||
assert_eq!(slot, 0); | ||
assert!(account_info); | ||
}, | ||
) | ||
.unwrap(); | ||
let ancestors = vec![(1, 0)].into_iter().collect(); | ||
let (list, idx) = index.get_for_tests(&key, Some(&ancestors), None).unwrap(); | ||
assert_eq!(list.slot_list()[idx], (1, false)); | ||
index | ||
.get_with_and_then( | ||
&key, | ||
Some(&ancestors), | ||
None, | ||
false, | ||
|(slot, account_info)| { | ||
assert_eq!(slot, 1); | ||
assert!(!account_info); | ||
}, | ||
) | ||
.unwrap(); | ||
} | ||
|
||
#[test] | ||
|
@@ -3265,8 +3341,12 @@ pub mod tests { | |
// Updating index should not purge older roots, only purges | ||
// previous updates within the same slot | ||
assert_eq!(gc, vec![]); | ||
let (list, idx) = index.get_for_tests(&key, None, None).unwrap(); | ||
assert_eq!(list.slot_list()[idx], (3, true)); | ||
index | ||
.get_with_and_then(&key, None, None, false, |(slot, account_info)| { | ||
assert_eq!(slot, 3); | ||
assert!(account_info); | ||
}) | ||
.unwrap(); | ||
|
||
let mut num = 0; | ||
let mut found_key = false; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's the main new function. In subsequent PRs more calls to
get()
will be replaced with calls toget_with_and_then()
.