add second type to accounts index for disk (#30446)
This commit is contained in:
parent
6df160bedd
commit
e39626ab14
|
@ -24,7 +24,7 @@ fn bench_accounts_index(bencher: &mut Bencher) {
|
||||||
const NUM_FORKS: u64 = 16;
|
const NUM_FORKS: u64 = 16;
|
||||||
|
|
||||||
let mut reclaims = vec![];
|
let mut reclaims = vec![];
|
||||||
let index = AccountsIndex::<AccountInfo>::new(
|
let index = AccountsIndex::<AccountInfo, AccountInfo>::new(
|
||||||
Some(ACCOUNTS_INDEX_CONFIG_FOR_BENCHMARKS),
|
Some(ACCOUNTS_INDEX_CONFIG_FOR_BENCHMARKS),
|
||||||
&Arc::default(),
|
&Arc::default(),
|
||||||
);
|
);
|
||||||
|
|
|
@ -1344,7 +1344,7 @@ struct RemoveUnrootedSlotsSynchronization {
|
||||||
signal: Condvar,
|
signal: Condvar,
|
||||||
}
|
}
|
||||||
|
|
||||||
type AccountInfoAccountsIndex = AccountsIndex<AccountInfo>;
|
type AccountInfoAccountsIndex = AccountsIndex<AccountInfo, AccountInfo>;
|
||||||
|
|
||||||
// This structure handles the load/store of the accounts
|
// This structure handles the load/store of the accounts
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -13593,7 +13593,7 @@ pub mod tests {
|
||||||
|
|
||||||
// returns the rooted entries and the storage ref count
|
// returns the rooted entries and the storage ref count
|
||||||
fn roots_and_ref_count<T: IndexValue>(
|
fn roots_and_ref_count<T: IndexValue>(
|
||||||
index: &AccountsIndex<T>,
|
index: &AccountsIndex<T, T>,
|
||||||
locked_account_entry: &ReadAccountMapEntry<T>,
|
locked_account_entry: &ReadAccountMapEntry<T>,
|
||||||
max_inclusive: Option<Slot>,
|
max_inclusive: Option<Slot>,
|
||||||
) -> (SlotList<T>, RefCount) {
|
) -> (SlotList<T>, RefCount) {
|
||||||
|
|
|
@ -70,7 +70,7 @@ pub type ScanResult<T> = Result<T, ScanError>;
|
||||||
pub type SlotList<T> = Vec<(Slot, T)>;
|
pub type SlotList<T> = Vec<(Slot, T)>;
|
||||||
pub type SlotSlice<'s, T> = &'s [(Slot, T)];
|
pub type SlotSlice<'s, T> = &'s [(Slot, T)];
|
||||||
pub type RefCount = u64;
|
pub type RefCount = u64;
|
||||||
pub type AccountMap<V> = Arc<InMemAccountsIndex<V>>;
|
pub type AccountMap<T, U> = Arc<InMemAccountsIndex<T, U>>;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
/// how accounts index 'upsert' should handle reclaims
|
/// how accounts index 'upsert' should handle reclaims
|
||||||
|
@ -232,13 +232,18 @@ pub struct AccountMapEntryMeta {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AccountMapEntryMeta {
|
impl AccountMapEntryMeta {
|
||||||
pub fn new_dirty<T: IndexValue>(storage: &Arc<BucketMapHolder<T>>, is_cached: bool) -> Self {
|
pub fn new_dirty<T: IndexValue, U: IndexValue + From<T> + Into<T>>(
|
||||||
|
storage: &Arc<BucketMapHolder<T, U>>,
|
||||||
|
is_cached: bool,
|
||||||
|
) -> Self {
|
||||||
AccountMapEntryMeta {
|
AccountMapEntryMeta {
|
||||||
dirty: AtomicBool::new(true),
|
dirty: AtomicBool::new(true),
|
||||||
age: AtomicU8::new(storage.future_age_to_flush(is_cached)),
|
age: AtomicU8::new(storage.future_age_to_flush(is_cached)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn new_clean<T: IndexValue>(storage: &Arc<BucketMapHolder<T>>) -> Self {
|
pub fn new_clean<T: IndexValue, U: IndexValue + From<T> + Into<T>>(
|
||||||
|
storage: &Arc<BucketMapHolder<T, U>>,
|
||||||
|
) -> Self {
|
||||||
AccountMapEntryMeta {
|
AccountMapEntryMeta {
|
||||||
dirty: AtomicBool::new(false),
|
dirty: AtomicBool::new(false),
|
||||||
age: AtomicU8::new(storage.future_age_to_flush(false)),
|
age: AtomicU8::new(storage.future_age_to_flush(false)),
|
||||||
|
@ -397,10 +402,10 @@ impl<T: IndexValue> PreAllocatedAccountMapEntry<T> {
|
||||||
/// 1. new empty (refcount=0, slot_list={})
|
/// 1. new empty (refcount=0, slot_list={})
|
||||||
/// 2. update(slot, account_info)
|
/// 2. update(slot, account_info)
|
||||||
/// This code is called when the first entry [ie. (slot,account_info)] for a pubkey is inserted into the index.
|
/// This code is called when the first entry [ie. (slot,account_info)] for a pubkey is inserted into the index.
|
||||||
pub fn new(
|
pub fn new<U: IndexValue + From<T> + Into<T>>(
|
||||||
slot: Slot,
|
slot: Slot,
|
||||||
account_info: T,
|
account_info: T,
|
||||||
storage: &Arc<BucketMapHolder<T>>,
|
storage: &Arc<BucketMapHolder<T, U>>,
|
||||||
store_raw: bool,
|
store_raw: bool,
|
||||||
) -> PreAllocatedAccountMapEntry<T> {
|
) -> PreAllocatedAccountMapEntry<T> {
|
||||||
if store_raw {
|
if store_raw {
|
||||||
|
@ -410,10 +415,10 @@ impl<T: IndexValue> PreAllocatedAccountMapEntry<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn allocate(
|
fn allocate<U: IndexValue + From<T> + Into<T>>(
|
||||||
slot: Slot,
|
slot: Slot,
|
||||||
account_info: T,
|
account_info: T,
|
||||||
storage: &Arc<BucketMapHolder<T>>,
|
storage: &Arc<BucketMapHolder<T, U>>,
|
||||||
) -> AccountMapEntry<T> {
|
) -> AccountMapEntry<T> {
|
||||||
let is_cached = account_info.is_cached();
|
let is_cached = account_info.is_cached();
|
||||||
let ref_count = u64::from(!is_cached);
|
let ref_count = u64::from(!is_cached);
|
||||||
|
@ -425,7 +430,10 @@ impl<T: IndexValue> PreAllocatedAccountMapEntry<T> {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_account_map_entry(self, storage: &Arc<BucketMapHolder<T>>) -> AccountMapEntry<T> {
|
pub fn into_account_map_entry<U: IndexValue + From<T> + Into<T>>(
|
||||||
|
self,
|
||||||
|
storage: &Arc<BucketMapHolder<T, U>>,
|
||||||
|
) -> AccountMapEntry<T> {
|
||||||
match self {
|
match self {
|
||||||
Self::Entry(entry) => entry,
|
Self::Entry(entry) => entry,
|
||||||
Self::Raw((slot, account_info)) => Self::allocate(slot, account_info, storage),
|
Self::Raw((slot, account_info)) => Self::allocate(slot, account_info, storage),
|
||||||
|
@ -487,8 +495,8 @@ pub struct AccountsIndexRootsStats {
|
||||||
pub clean_dead_slot_us: u64,
|
pub clean_dead_slot_us: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AccountsIndexIterator<'a, T: IndexValue> {
|
pub struct AccountsIndexIterator<'a, T: IndexValue, U: IndexValue + From<T> + Into<T>> {
|
||||||
account_maps: &'a LockMapTypeSlice<T>,
|
account_maps: &'a LockMapTypeSlice<T, U>,
|
||||||
bin_calculator: &'a PubkeyBinCalculator24,
|
bin_calculator: &'a PubkeyBinCalculator24,
|
||||||
start_bound: Bound<Pubkey>,
|
start_bound: Bound<Pubkey>,
|
||||||
end_bound: Bound<Pubkey>,
|
end_bound: Bound<Pubkey>,
|
||||||
|
@ -496,9 +504,9 @@ pub struct AccountsIndexIterator<'a, T: IndexValue> {
|
||||||
collect_all_unsorted: bool,
|
collect_all_unsorted: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: IndexValue> AccountsIndexIterator<'a, T> {
|
impl<'a, T: IndexValue, U: IndexValue + From<T> + Into<T>> AccountsIndexIterator<'a, T, U> {
|
||||||
fn range<R>(
|
fn range<R>(
|
||||||
map: &AccountMaps<T>,
|
map: &AccountMaps<T, U>,
|
||||||
range: R,
|
range: R,
|
||||||
collect_all_unsorted: bool,
|
collect_all_unsorted: bool,
|
||||||
) -> Vec<(Pubkey, AccountMapEntry<T>)>
|
) -> Vec<(Pubkey, AccountMapEntry<T>)>
|
||||||
|
@ -556,7 +564,7 @@ impl<'a, T: IndexValue> AccountsIndexIterator<'a, T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new<R>(
|
pub fn new<R>(
|
||||||
index: &'a AccountsIndex<T>,
|
index: &'a AccountsIndex<T, U>,
|
||||||
range: Option<&R>,
|
range: Option<&R>,
|
||||||
collect_all_unsorted: bool,
|
collect_all_unsorted: bool,
|
||||||
) -> Self
|
) -> Self
|
||||||
|
@ -596,7 +604,9 @@ impl<'a, T: IndexValue> AccountsIndexIterator<'a, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: IndexValue> Iterator for AccountsIndexIterator<'a, T> {
|
impl<'a, T: IndexValue, U: IndexValue + From<T> + Into<T>> Iterator
|
||||||
|
for AccountsIndexIterator<'a, T, U>
|
||||||
|
{
|
||||||
type Item = Vec<(Pubkey, AccountMapEntry<T>)>;
|
type Item = Vec<(Pubkey, AccountMapEntry<T>)>;
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
if self.is_finished {
|
if self.is_finished {
|
||||||
|
@ -634,10 +644,10 @@ pub trait ZeroLamport {
|
||||||
fn is_zero_lamport(&self) -> bool;
|
fn is_zero_lamport(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
type MapType<T> = AccountMap<T>;
|
type MapType<T, U> = AccountMap<T, U>;
|
||||||
type LockMapType<T> = Vec<MapType<T>>;
|
type LockMapType<T, U> = Vec<MapType<T, U>>;
|
||||||
type LockMapTypeSlice<T> = [MapType<T>];
|
type LockMapTypeSlice<T, U> = [MapType<T, U>];
|
||||||
type AccountMaps<'a, T> = &'a MapType<T>;
|
type AccountMaps<'a, T, U> = &'a MapType<T, U>;
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct ScanSlotTracker {
|
pub struct ScanSlotTracker {
|
||||||
|
@ -665,8 +675,10 @@ pub enum AccountsIndexScanResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct AccountsIndex<T: IndexValue> {
|
/// T: account info type to interact in in-memory items
|
||||||
pub account_maps: LockMapType<T>,
|
/// U: account info type to be persisted to disk
|
||||||
|
pub struct AccountsIndex<T: IndexValue, U: IndexValue + From<T> + Into<T>> {
|
||||||
|
pub account_maps: LockMapType<T, U>,
|
||||||
pub bin_calculator: PubkeyBinCalculator24,
|
pub bin_calculator: PubkeyBinCalculator24,
|
||||||
program_id_index: SecondaryIndex<DashMapSecondaryIndexEntry>,
|
program_id_index: SecondaryIndex<DashMapSecondaryIndexEntry>,
|
||||||
spl_token_mint_index: SecondaryIndex<DashMapSecondaryIndexEntry>,
|
spl_token_mint_index: SecondaryIndex<DashMapSecondaryIndexEntry>,
|
||||||
|
@ -685,7 +697,7 @@ pub struct AccountsIndex<T: IndexValue> {
|
||||||
// scanning the fork with that Bank at the tip is no longer possible.
|
// scanning the fork with that Bank at the tip is no longer possible.
|
||||||
pub removed_bank_ids: Mutex<HashSet<BankId>>,
|
pub removed_bank_ids: Mutex<HashSet<BankId>>,
|
||||||
|
|
||||||
storage: AccountsIndexStorage<T>,
|
storage: AccountsIndexStorage<T, U>,
|
||||||
|
|
||||||
/// when a scan's accumulated data exceeds this limit, abort the scan
|
/// when a scan's accumulated data exceeds this limit, abort the scan
|
||||||
pub scan_results_limit_bytes: Option<usize>,
|
pub scan_results_limit_bytes: Option<usize>,
|
||||||
|
@ -703,7 +715,7 @@ pub struct AccountsIndex<T: IndexValue> {
|
||||||
pub rent_paying_accounts_by_partition: OnceCell<RentPayingAccountsByPartition>,
|
pub rent_paying_accounts_by_partition: OnceCell<RentPayingAccountsByPartition>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: IndexValue> AccountsIndex<T> {
|
impl<T: IndexValue, U: IndexValue + From<T> + Into<T>> AccountsIndex<T, U> {
|
||||||
pub fn default_for_tests() -> Self {
|
pub fn default_for_tests() -> Self {
|
||||||
Self::new(Some(ACCOUNTS_INDEX_CONFIG_FOR_TESTING), &Arc::default())
|
Self::new(Some(ACCOUNTS_INDEX_CONFIG_FOR_TESTING), &Arc::default())
|
||||||
}
|
}
|
||||||
|
@ -742,9 +754,9 @@ impl<T: IndexValue> AccountsIndex<T> {
|
||||||
config: Option<AccountsIndexConfig>,
|
config: Option<AccountsIndexConfig>,
|
||||||
exit: &Arc<AtomicBool>,
|
exit: &Arc<AtomicBool>,
|
||||||
) -> (
|
) -> (
|
||||||
LockMapType<T>,
|
LockMapType<T, U>,
|
||||||
PubkeyBinCalculator24,
|
PubkeyBinCalculator24,
|
||||||
AccountsIndexStorage<T>,
|
AccountsIndexStorage<T, U>,
|
||||||
) {
|
) {
|
||||||
let bins = config
|
let bins = config
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -759,7 +771,7 @@ impl<T: IndexValue> AccountsIndex<T> {
|
||||||
(account_maps, bin_calculator, storage)
|
(account_maps, bin_calculator, storage)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iter<R>(&self, range: Option<&R>, collect_all_unsorted: bool) -> AccountsIndexIterator<T>
|
fn iter<R>(&self, range: Option<&R>, collect_all_unsorted: bool) -> AccountsIndexIterator<T, U>
|
||||||
where
|
where
|
||||||
R: RangeBounds<Pubkey>,
|
R: RangeBounds<Pubkey>,
|
||||||
{
|
{
|
||||||
|
@ -1121,7 +1133,7 @@ impl<T: IndexValue> AccountsIndex<T> {
|
||||||
pub fn get_account_read_entry_with_lock(
|
pub fn get_account_read_entry_with_lock(
|
||||||
&self,
|
&self,
|
||||||
pubkey: &Pubkey,
|
pubkey: &Pubkey,
|
||||||
lock: &AccountMaps<'_, T>,
|
lock: &AccountMaps<'_, T, U>,
|
||||||
) -> Option<ReadAccountMapEntry<T>> {
|
) -> Option<ReadAccountMapEntry<T>> {
|
||||||
lock.get(pubkey)
|
lock.get(pubkey)
|
||||||
.map(ReadAccountMapEntry::from_account_map_entry)
|
.map(ReadAccountMapEntry::from_account_map_entry)
|
||||||
|
@ -1572,7 +1584,7 @@ impl<T: IndexValue> AccountsIndex<T> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_bin(&self, pubkey: &Pubkey) -> AccountMaps<T> {
|
pub(crate) fn get_bin(&self, pubkey: &Pubkey) -> AccountMaps<T, U> {
|
||||||
&self.account_maps[self.bin_calculator.bin_from_pubkey(pubkey)]
|
&self.account_maps[self.bin_calculator.bin_from_pubkey(pubkey)]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2090,7 +2102,7 @@ pub mod tests {
|
||||||
fn create_dashmap_secondary_index_state() -> (usize, usize, AccountSecondaryIndexes) {
|
fn create_dashmap_secondary_index_state() -> (usize, usize, AccountSecondaryIndexes) {
|
||||||
{
|
{
|
||||||
// Check that we're actually testing the correct variant
|
// Check that we're actually testing the correct variant
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
let _type_check = SecondaryIndexTypes::DashMap(&index.spl_token_mint_index);
|
let _type_check = SecondaryIndexTypes::DashMap(&index.spl_token_mint_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2100,7 +2112,7 @@ pub mod tests {
|
||||||
fn create_rwlock_secondary_index_state() -> (usize, usize, AccountSecondaryIndexes) {
|
fn create_rwlock_secondary_index_state() -> (usize, usize, AccountSecondaryIndexes) {
|
||||||
{
|
{
|
||||||
// Check that we're actually testing the correct variant
|
// Check that we're actually testing the correct variant
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
let _type_check = SecondaryIndexTypes::RwLock(&index.spl_token_owner_index);
|
let _type_check = SecondaryIndexTypes::RwLock(&index.spl_token_owner_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2132,7 +2144,7 @@ pub mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: IndexValue> AccountsIndex<T> {
|
impl<T: IndexValue> AccountsIndex<T, T> {
|
||||||
/// provides the ability to refactor this function on the api without bloody changes
|
/// provides the ability to refactor this function on the api without bloody changes
|
||||||
pub fn get_for_tests(
|
pub fn get_for_tests(
|
||||||
&self,
|
&self,
|
||||||
|
@ -2147,7 +2159,7 @@ pub mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_next_original_root() {
|
fn test_get_next_original_root() {
|
||||||
let ancestors = None;
|
let ancestors = None;
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
for slot in 0..2 {
|
for slot in 0..2 {
|
||||||
assert_eq!(index.get_next_original_root(slot, ancestors), None);
|
assert_eq!(index.get_next_original_root(slot, ancestors), None);
|
||||||
}
|
}
|
||||||
|
@ -2173,7 +2185,7 @@ pub mod tests {
|
||||||
fn test_get_next_original_root_ancestors() {
|
fn test_get_next_original_root_ancestors() {
|
||||||
let orig_ancestors = Ancestors::default();
|
let orig_ancestors = Ancestors::default();
|
||||||
let ancestors = Some(&orig_ancestors);
|
let ancestors = Some(&orig_ancestors);
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
for slot in 0..2 {
|
for slot in 0..2 {
|
||||||
assert_eq!(index.get_next_original_root(slot, ancestors), None);
|
assert_eq!(index.get_next_original_root(slot, ancestors), None);
|
||||||
}
|
}
|
||||||
|
@ -2201,7 +2213,7 @@ pub mod tests {
|
||||||
fn test_get_next_original_root_roots_and_ancestors() {
|
fn test_get_next_original_root_roots_and_ancestors() {
|
||||||
let orig_ancestors = Ancestors::default();
|
let orig_ancestors = Ancestors::default();
|
||||||
let ancestors = Some(&orig_ancestors);
|
let ancestors = Some(&orig_ancestors);
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
for slot in 0..2 {
|
for slot in 0..2 {
|
||||||
assert_eq!(index.get_next_original_root(slot, ancestors), None);
|
assert_eq!(index.get_next_original_root(slot, ancestors), None);
|
||||||
}
|
}
|
||||||
|
@ -2226,7 +2238,7 @@ pub mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_remove_old_historical_roots() {
|
fn test_remove_old_historical_roots() {
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
index.add_root(1);
|
index.add_root(1);
|
||||||
index.add_root(2);
|
index.add_root(2);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -2267,7 +2279,7 @@ pub mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
// now use 'keep'
|
// now use 'keep'
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
index.add_root(1);
|
index.add_root(1);
|
||||||
index.add_root(2);
|
index.add_root(2);
|
||||||
let hash_set_1 = vec![1].into_iter().collect();
|
let hash_set_1 = vec![1].into_iter().collect();
|
||||||
|
@ -2307,7 +2319,7 @@ pub mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_empty() {
|
fn test_get_empty() {
|
||||||
let key = solana_sdk::pubkey::new_rand();
|
let key = solana_sdk::pubkey::new_rand();
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
let ancestors = Ancestors::default();
|
let ancestors = Ancestors::default();
|
||||||
let key = &key;
|
let key = &key;
|
||||||
assert!(index.get_for_tests(key, Some(&ancestors), None).is_none());
|
assert!(index.get_for_tests(key, Some(&ancestors), None).is_none());
|
||||||
|
@ -2373,7 +2385,7 @@ pub mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_insert_no_ancestors() {
|
fn test_insert_no_ancestors() {
|
||||||
let key = solana_sdk::pubkey::new_rand();
|
let key = solana_sdk::pubkey::new_rand();
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
let mut gc = Vec::new();
|
let mut gc = Vec::new();
|
||||||
index.upsert(
|
index.upsert(
|
||||||
0,
|
0,
|
||||||
|
@ -2421,7 +2433,7 @@ pub mod tests {
|
||||||
let pubkey = &key;
|
let pubkey = &key;
|
||||||
let slot = 0;
|
let slot = 0;
|
||||||
|
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
let account_info = true;
|
let account_info = true;
|
||||||
let items = vec![(*pubkey, account_info)];
|
let items = vec![(*pubkey, account_info)];
|
||||||
index.set_startup(Startup::Startup);
|
index.set_startup(Startup::Startup);
|
||||||
|
@ -2456,7 +2468,7 @@ pub mod tests {
|
||||||
assert_eq!(num, 1);
|
assert_eq!(num, 1);
|
||||||
|
|
||||||
// not zero lamports
|
// not zero lamports
|
||||||
let index = AccountsIndex::<AccountInfoTest>::default_for_tests();
|
let index = AccountsIndex::<AccountInfoTest, AccountInfoTest>::default_for_tests();
|
||||||
let account_info: AccountInfoTest = 0 as AccountInfoTest;
|
let account_info: AccountInfoTest = 0 as AccountInfoTest;
|
||||||
let items = vec![(*pubkey, account_info)];
|
let items = vec![(*pubkey, account_info)];
|
||||||
index.set_startup(Startup::Startup);
|
index.set_startup(Startup::Startup);
|
||||||
|
@ -2494,7 +2506,7 @@ pub mod tests {
|
||||||
fn get_pre_allocated<T: IndexValue>(
|
fn get_pre_allocated<T: IndexValue>(
|
||||||
slot: Slot,
|
slot: Slot,
|
||||||
account_info: T,
|
account_info: T,
|
||||||
storage: &Arc<BucketMapHolder<T>>,
|
storage: &Arc<BucketMapHolder<T, T>>,
|
||||||
store_raw: bool,
|
store_raw: bool,
|
||||||
to_raw_first: bool,
|
to_raw_first: bool,
|
||||||
) -> PreAllocatedAccountMapEntry<T> {
|
) -> PreAllocatedAccountMapEntry<T> {
|
||||||
|
@ -2562,7 +2574,7 @@ pub mod tests {
|
||||||
let key0 = solana_sdk::pubkey::new_rand();
|
let key0 = solana_sdk::pubkey::new_rand();
|
||||||
let key1 = solana_sdk::pubkey::new_rand();
|
let key1 = solana_sdk::pubkey::new_rand();
|
||||||
|
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
let account_infos = [true, false];
|
let account_infos = [true, false];
|
||||||
|
|
||||||
index.set_startup(Startup::Startup);
|
index.set_startup(Startup::Startup);
|
||||||
|
@ -2600,7 +2612,7 @@ pub mod tests {
|
||||||
} else {
|
} else {
|
||||||
IndexLimitMb::InMemOnly // in-mem only
|
IndexLimitMb::InMemOnly // in-mem only
|
||||||
};
|
};
|
||||||
let index = AccountsIndex::<T>::new(Some(config), &Arc::default());
|
let index = AccountsIndex::<T, T>::new(Some(config), &Arc::default());
|
||||||
let mut gc = Vec::new();
|
let mut gc = Vec::new();
|
||||||
|
|
||||||
if upsert {
|
if upsert {
|
||||||
|
@ -2715,7 +2727,7 @@ pub mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_insert_with_lock_no_ancestors() {
|
fn test_insert_with_lock_no_ancestors() {
|
||||||
let key = solana_sdk::pubkey::new_rand();
|
let key = solana_sdk::pubkey::new_rand();
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
let slot = 0;
|
let slot = 0;
|
||||||
let account_info = true;
|
let account_info = true;
|
||||||
|
|
||||||
|
@ -2761,7 +2773,7 @@ pub mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_insert_wrong_ancestors() {
|
fn test_insert_wrong_ancestors() {
|
||||||
let key = solana_sdk::pubkey::new_rand();
|
let key = solana_sdk::pubkey::new_rand();
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
let mut gc = Vec::new();
|
let mut gc = Vec::new();
|
||||||
index.upsert(
|
index.upsert(
|
||||||
0,
|
0,
|
||||||
|
@ -2792,7 +2804,7 @@ pub mod tests {
|
||||||
{
|
{
|
||||||
// non-cached
|
// non-cached
|
||||||
let key = solana_sdk::pubkey::new_rand();
|
let key = solana_sdk::pubkey::new_rand();
|
||||||
let index = AccountsIndex::<u64>::default_for_tests();
|
let index = AccountsIndex::<u64, u64>::default_for_tests();
|
||||||
let mut reclaims = Vec::new();
|
let mut reclaims = Vec::new();
|
||||||
let slot = 0;
|
let slot = 0;
|
||||||
let value = 1;
|
let value = 1;
|
||||||
|
@ -2838,7 +2850,7 @@ pub mod tests {
|
||||||
{
|
{
|
||||||
// cached
|
// cached
|
||||||
let key = solana_sdk::pubkey::new_rand();
|
let key = solana_sdk::pubkey::new_rand();
|
||||||
let index = AccountsIndex::<AccountInfoTest>::default_for_tests();
|
let index = AccountsIndex::<AccountInfoTest, AccountInfoTest>::default_for_tests();
|
||||||
let mut reclaims = Vec::new();
|
let mut reclaims = Vec::new();
|
||||||
let slot = 0;
|
let slot = 0;
|
||||||
let value = 1.0;
|
let value = 1.0;
|
||||||
|
@ -2886,7 +2898,7 @@ pub mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_insert_with_ancestors() {
|
fn test_insert_with_ancestors() {
|
||||||
let key = solana_sdk::pubkey::new_rand();
|
let key = solana_sdk::pubkey::new_rand();
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
let mut gc = Vec::new();
|
let mut gc = Vec::new();
|
||||||
index.upsert(
|
index.upsert(
|
||||||
0,
|
0,
|
||||||
|
@ -2921,8 +2933,8 @@ pub mod tests {
|
||||||
assert!(found_key);
|
assert!(found_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_accounts_index_keys(num_pubkeys: usize) -> (AccountsIndex<bool>, Vec<Pubkey>) {
|
fn setup_accounts_index_keys(num_pubkeys: usize) -> (AccountsIndex<bool, bool>, Vec<Pubkey>) {
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
let root_slot = 0;
|
let root_slot = 0;
|
||||||
|
|
||||||
let mut pubkeys: Vec<Pubkey> = std::iter::repeat_with(|| {
|
let mut pubkeys: Vec<Pubkey> = std::iter::repeat_with(|| {
|
||||||
|
@ -2962,7 +2974,7 @@ pub mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_test_range(
|
fn run_test_range(
|
||||||
index: &AccountsIndex<bool>,
|
index: &AccountsIndex<bool, bool>,
|
||||||
pubkeys: &[Pubkey],
|
pubkeys: &[Pubkey],
|
||||||
start_bound: Bound<usize>,
|
start_bound: Bound<usize>,
|
||||||
end_bound: Bound<usize>,
|
end_bound: Bound<usize>,
|
||||||
|
@ -3004,7 +3016,7 @@ pub mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_test_range_indexes(
|
fn run_test_range_indexes(
|
||||||
index: &AccountsIndex<bool>,
|
index: &AccountsIndex<bool, bool>,
|
||||||
pubkeys: &[Pubkey],
|
pubkeys: &[Pubkey],
|
||||||
start: Option<usize>,
|
start: Option<usize>,
|
||||||
end: Option<usize>,
|
end: Option<usize>,
|
||||||
|
@ -3102,7 +3114,7 @@ pub mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_is_alive_root() {
|
fn test_is_alive_root() {
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
assert!(!index.is_alive_root(0));
|
assert!(!index.is_alive_root(0));
|
||||||
index.add_root(0);
|
index.add_root(0);
|
||||||
assert!(index.is_alive_root(0));
|
assert!(index.is_alive_root(0));
|
||||||
|
@ -3111,7 +3123,7 @@ pub mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_insert_with_root() {
|
fn test_insert_with_root() {
|
||||||
let key = solana_sdk::pubkey::new_rand();
|
let key = solana_sdk::pubkey::new_rand();
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
let mut gc = Vec::new();
|
let mut gc = Vec::new();
|
||||||
index.upsert(
|
index.upsert(
|
||||||
0,
|
0,
|
||||||
|
@ -3132,7 +3144,7 @@ pub mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_clean_first() {
|
fn test_clean_first() {
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
index.add_root(0);
|
index.add_root(0);
|
||||||
index.add_root(1);
|
index.add_root(1);
|
||||||
index.clean_dead_slot(0, &mut AccountsIndexRootsStats::default());
|
index.clean_dead_slot(0, &mut AccountsIndexRootsStats::default());
|
||||||
|
@ -3143,7 +3155,7 @@ pub mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_clean_last() {
|
fn test_clean_last() {
|
||||||
//this behavior might be undefined, clean up should only occur on older slots
|
//this behavior might be undefined, clean up should only occur on older slots
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
index.add_root(0);
|
index.add_root(0);
|
||||||
index.add_root(1);
|
index.add_root(1);
|
||||||
index.clean_dead_slot(1, &mut AccountsIndexRootsStats::default());
|
index.clean_dead_slot(1, &mut AccountsIndexRootsStats::default());
|
||||||
|
@ -3153,7 +3165,7 @@ pub mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_clean_and_unclean_slot() {
|
fn test_clean_and_unclean_slot() {
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
assert_eq!(0, index.roots_tracker.read().unwrap().uncleaned_roots.len());
|
assert_eq!(0, index.roots_tracker.read().unwrap().uncleaned_roots.len());
|
||||||
index.add_root(0);
|
index.add_root(0);
|
||||||
index.add_root(1);
|
index.add_root(1);
|
||||||
|
@ -3227,7 +3239,7 @@ pub mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_update_last_wins() {
|
fn test_update_last_wins() {
|
||||||
let key = solana_sdk::pubkey::new_rand();
|
let key = solana_sdk::pubkey::new_rand();
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
let ancestors = vec![(0, 0)].into_iter().collect();
|
let ancestors = vec![(0, 0)].into_iter().collect();
|
||||||
let mut gc = Vec::new();
|
let mut gc = Vec::new();
|
||||||
index.upsert(
|
index.upsert(
|
||||||
|
@ -3265,7 +3277,7 @@ pub mod tests {
|
||||||
fn test_update_new_slot() {
|
fn test_update_new_slot() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let key = solana_sdk::pubkey::new_rand();
|
let key = solana_sdk::pubkey::new_rand();
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
let ancestors = vec![(0, 0)].into_iter().collect();
|
let ancestors = vec![(0, 0)].into_iter().collect();
|
||||||
let mut gc = Vec::new();
|
let mut gc = Vec::new();
|
||||||
index.upsert(
|
index.upsert(
|
||||||
|
@ -3300,7 +3312,7 @@ pub mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_update_gc_purged_slot() {
|
fn test_update_gc_purged_slot() {
|
||||||
let key = solana_sdk::pubkey::new_rand();
|
let key = solana_sdk::pubkey::new_rand();
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
let mut gc = Vec::new();
|
let mut gc = Vec::new();
|
||||||
index.upsert(
|
index.upsert(
|
||||||
0,
|
0,
|
||||||
|
@ -3381,14 +3393,14 @@ pub mod tests {
|
||||||
assert!(found_key);
|
assert!(found_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn account_maps_stats_len<T: IndexValue>(index: &AccountsIndex<T>) -> usize {
|
fn account_maps_stats_len<T: IndexValue>(index: &AccountsIndex<T, T>) -> usize {
|
||||||
index.storage.storage.stats.total_count()
|
index.storage.storage.stats.total_count()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_purge() {
|
fn test_purge() {
|
||||||
let key = solana_sdk::pubkey::new_rand();
|
let key = solana_sdk::pubkey::new_rand();
|
||||||
let index = AccountsIndex::<u64>::default_for_tests();
|
let index = AccountsIndex::<u64, u64>::default_for_tests();
|
||||||
let mut gc = Vec::new();
|
let mut gc = Vec::new();
|
||||||
assert_eq!(0, account_maps_stats_len(&index));
|
assert_eq!(0, account_maps_stats_len(&index));
|
||||||
index.upsert(
|
index.upsert(
|
||||||
|
@ -3439,7 +3451,7 @@ pub mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_latest_slot() {
|
fn test_latest_slot() {
|
||||||
let slot_slice = vec![(0, true), (5, true), (3, true), (7, true)];
|
let slot_slice = vec![(0, true), (5, true), (3, true), (7, true)];
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
|
|
||||||
// No ancestors, no root, should return None
|
// No ancestors, no root, should return None
|
||||||
assert!(index.latest_slot(None, &slot_slice, None).is_none());
|
assert!(index.latest_slot(None, &slot_slice, None).is_none());
|
||||||
|
@ -3482,7 +3494,7 @@ pub mod tests {
|
||||||
fn run_test_purge_exact_secondary_index<
|
fn run_test_purge_exact_secondary_index<
|
||||||
SecondaryIndexEntryType: SecondaryIndexEntry + Default + Sync + Send,
|
SecondaryIndexEntryType: SecondaryIndexEntry + Default + Sync + Send,
|
||||||
>(
|
>(
|
||||||
index: &AccountsIndex<bool>,
|
index: &AccountsIndex<bool, bool>,
|
||||||
secondary_index: &SecondaryIndex<SecondaryIndexEntryType>,
|
secondary_index: &SecondaryIndex<SecondaryIndexEntryType>,
|
||||||
key_start: usize,
|
key_start: usize,
|
||||||
key_end: usize,
|
key_end: usize,
|
||||||
|
@ -3548,7 +3560,7 @@ pub mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_purge_exact_dashmap_secondary_index() {
|
fn test_purge_exact_dashmap_secondary_index() {
|
||||||
let (key_start, key_end, secondary_indexes) = create_dashmap_secondary_index_state();
|
let (key_start, key_end, secondary_indexes) = create_dashmap_secondary_index_state();
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
run_test_purge_exact_secondary_index(
|
run_test_purge_exact_secondary_index(
|
||||||
&index,
|
&index,
|
||||||
&index.spl_token_mint_index,
|
&index.spl_token_mint_index,
|
||||||
|
@ -3561,7 +3573,7 @@ pub mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_purge_exact_rwlock_secondary_index() {
|
fn test_purge_exact_rwlock_secondary_index() {
|
||||||
let (key_start, key_end, secondary_indexes) = create_rwlock_secondary_index_state();
|
let (key_start, key_end, secondary_indexes) = create_rwlock_secondary_index_state();
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
run_test_purge_exact_secondary_index(
|
run_test_purge_exact_secondary_index(
|
||||||
&index,
|
&index,
|
||||||
&index.spl_token_owner_index,
|
&index.spl_token_owner_index,
|
||||||
|
@ -3574,7 +3586,7 @@ pub mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_purge_older_root_entries() {
|
fn test_purge_older_root_entries() {
|
||||||
// No roots, should be no reclaims
|
// No roots, should be no reclaims
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
let mut slot_list = vec![(1, true), (2, true), (5, true), (9, true)];
|
let mut slot_list = vec![(1, true), (2, true), (5, true), (9, true)];
|
||||||
let mut reclaims = vec![];
|
let mut reclaims = vec![];
|
||||||
index.purge_older_root_entries(&mut slot_list, &mut reclaims, None);
|
index.purge_older_root_entries(&mut slot_list, &mut reclaims, None);
|
||||||
|
@ -3666,7 +3678,7 @@ pub mod tests {
|
||||||
SecondaryIndexEntryType: SecondaryIndexEntry + Default + Sync + Send,
|
SecondaryIndexEntryType: SecondaryIndexEntry + Default + Sync + Send,
|
||||||
>(
|
>(
|
||||||
token_id: &Pubkey,
|
token_id: &Pubkey,
|
||||||
index: &AccountsIndex<bool>,
|
index: &AccountsIndex<bool, bool>,
|
||||||
secondary_index: &SecondaryIndex<SecondaryIndexEntryType>,
|
secondary_index: &SecondaryIndex<SecondaryIndexEntryType>,
|
||||||
key_start: usize,
|
key_start: usize,
|
||||||
key_end: usize,
|
key_end: usize,
|
||||||
|
@ -3766,7 +3778,7 @@ pub mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_dashmap_secondary_index() {
|
fn test_dashmap_secondary_index() {
|
||||||
let (key_start, key_end, secondary_indexes) = create_dashmap_secondary_index_state();
|
let (key_start, key_end, secondary_indexes) = create_dashmap_secondary_index_state();
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
for token_id in [inline_spl_token::id(), inline_spl_token_2022::id()] {
|
for token_id in [inline_spl_token::id(), inline_spl_token_2022::id()] {
|
||||||
run_test_spl_token_secondary_indexes(
|
run_test_spl_token_secondary_indexes(
|
||||||
&token_id,
|
&token_id,
|
||||||
|
@ -3782,7 +3794,7 @@ pub mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rwlock_secondary_index() {
|
fn test_rwlock_secondary_index() {
|
||||||
let (key_start, key_end, secondary_indexes) = create_rwlock_secondary_index_state();
|
let (key_start, key_end, secondary_indexes) = create_rwlock_secondary_index_state();
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
for token_id in [inline_spl_token::id(), inline_spl_token_2022::id()] {
|
for token_id in [inline_spl_token::id(), inline_spl_token_2022::id()] {
|
||||||
run_test_spl_token_secondary_indexes(
|
run_test_spl_token_secondary_indexes(
|
||||||
&token_id,
|
&token_id,
|
||||||
|
@ -3799,7 +3811,7 @@ pub mod tests {
|
||||||
SecondaryIndexEntryType: SecondaryIndexEntry + Default + Sync + Send,
|
SecondaryIndexEntryType: SecondaryIndexEntry + Default + Sync + Send,
|
||||||
>(
|
>(
|
||||||
token_id: &Pubkey,
|
token_id: &Pubkey,
|
||||||
index: &AccountsIndex<bool>,
|
index: &AccountsIndex<bool, bool>,
|
||||||
secondary_index: &SecondaryIndex<SecondaryIndexEntryType>,
|
secondary_index: &SecondaryIndex<SecondaryIndexEntryType>,
|
||||||
index_key_start: usize,
|
index_key_start: usize,
|
||||||
index_key_end: usize,
|
index_key_end: usize,
|
||||||
|
@ -3887,7 +3899,7 @@ pub mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_dashmap_secondary_index_same_slot_and_forks() {
|
fn test_dashmap_secondary_index_same_slot_and_forks() {
|
||||||
let (key_start, key_end, account_index) = create_dashmap_secondary_index_state();
|
let (key_start, key_end, account_index) = create_dashmap_secondary_index_state();
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
for token_id in [inline_spl_token::id(), inline_spl_token_2022::id()] {
|
for token_id in [inline_spl_token::id(), inline_spl_token_2022::id()] {
|
||||||
run_test_secondary_indexes_same_slot_and_forks(
|
run_test_secondary_indexes_same_slot_and_forks(
|
||||||
&token_id,
|
&token_id,
|
||||||
|
@ -3903,7 +3915,7 @@ pub mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rwlock_secondary_index_same_slot_and_forks() {
|
fn test_rwlock_secondary_index_same_slot_and_forks() {
|
||||||
let (key_start, key_end, account_index) = create_rwlock_secondary_index_state();
|
let (key_start, key_end, account_index) = create_rwlock_secondary_index_state();
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
for token_id in [inline_spl_token::id(), inline_spl_token_2022::id()] {
|
for token_id in [inline_spl_token::id(), inline_spl_token_2022::id()] {
|
||||||
run_test_secondary_indexes_same_slot_and_forks(
|
run_test_secondary_indexes_same_slot_and_forks(
|
||||||
&token_id,
|
&token_id,
|
||||||
|
@ -3942,7 +3954,7 @@ pub mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_bin_start_and_range() {
|
fn test_bin_start_and_range() {
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
let iter = AccountsIndexIterator::new(
|
let iter = AccountsIndexIterator::new(
|
||||||
&index,
|
&index,
|
||||||
None::<&RangeInclusive<Pubkey>>,
|
None::<&RangeInclusive<Pubkey>>,
|
||||||
|
@ -3984,7 +3996,7 @@ pub mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_newest_root_in_slot_list() {
|
fn test_get_newest_root_in_slot_list() {
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
let return_0 = 0;
|
let return_0 = 0;
|
||||||
let slot1 = 1;
|
let slot1 = 1;
|
||||||
let slot2 = 2;
|
let slot2 = 2;
|
||||||
|
@ -3996,7 +4008,7 @@ pub mod tests {
|
||||||
let slot_list = Vec::<(Slot, bool)>::default();
|
let slot_list = Vec::<(Slot, bool)>::default();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
return_0,
|
return_0,
|
||||||
AccountsIndex::get_newest_root_in_slot_list(
|
AccountsIndex::<bool, bool>::get_newest_root_in_slot_list(
|
||||||
&roots_tracker.alive_roots,
|
&roots_tracker.alive_roots,
|
||||||
&slot_list,
|
&slot_list,
|
||||||
Some(slot1),
|
Some(slot1),
|
||||||
|
@ -4004,7 +4016,7 @@ pub mod tests {
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
return_0,
|
return_0,
|
||||||
AccountsIndex::get_newest_root_in_slot_list(
|
AccountsIndex::<bool, bool>::get_newest_root_in_slot_list(
|
||||||
&roots_tracker.alive_roots,
|
&roots_tracker.alive_roots,
|
||||||
&slot_list,
|
&slot_list,
|
||||||
Some(slot2),
|
Some(slot2),
|
||||||
|
@ -4012,7 +4024,7 @@ pub mod tests {
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
return_0,
|
return_0,
|
||||||
AccountsIndex::get_newest_root_in_slot_list(
|
AccountsIndex::<bool, bool>::get_newest_root_in_slot_list(
|
||||||
&roots_tracker.alive_roots,
|
&roots_tracker.alive_roots,
|
||||||
&slot_list,
|
&slot_list,
|
||||||
Some(slot99),
|
Some(slot99),
|
||||||
|
@ -4027,7 +4039,7 @@ pub mod tests {
|
||||||
let slot_list = vec![(slot2, true)];
|
let slot_list = vec![(slot2, true)];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
slot2,
|
slot2,
|
||||||
AccountsIndex::get_newest_root_in_slot_list(
|
AccountsIndex::<bool, bool>::get_newest_root_in_slot_list(
|
||||||
&roots_tracker.alive_roots,
|
&roots_tracker.alive_roots,
|
||||||
&slot_list,
|
&slot_list,
|
||||||
Some(slot2),
|
Some(slot2),
|
||||||
|
@ -4036,7 +4048,7 @@ pub mod tests {
|
||||||
// no newest root
|
// no newest root
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
return_0,
|
return_0,
|
||||||
AccountsIndex::get_newest_root_in_slot_list(
|
AccountsIndex::<bool, bool>::get_newest_root_in_slot_list(
|
||||||
&roots_tracker.alive_roots,
|
&roots_tracker.alive_roots,
|
||||||
&slot_list,
|
&slot_list,
|
||||||
Some(slot1),
|
Some(slot1),
|
||||||
|
@ -4044,7 +4056,7 @@ pub mod tests {
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
slot2,
|
slot2,
|
||||||
AccountsIndex::get_newest_root_in_slot_list(
|
AccountsIndex::<bool, bool>::get_newest_root_in_slot_list(
|
||||||
&roots_tracker.alive_roots,
|
&roots_tracker.alive_roots,
|
||||||
&slot_list,
|
&slot_list,
|
||||||
Some(slot99),
|
Some(slot99),
|
||||||
|
@ -4053,7 +4065,7 @@ pub mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: IndexValue> AccountsIndex<T> {
|
impl<T: IndexValue> AccountsIndex<T, T> {
|
||||||
fn upsert_simple_test(&self, key: &Pubkey, slot: Slot, value: T) {
|
fn upsert_simple_test(&self, key: &Pubkey, slot: Slot, value: T) {
|
||||||
let mut gc = Vec::new();
|
let mut gc = Vec::new();
|
||||||
self.upsert(
|
self.upsert(
|
||||||
|
@ -4074,7 +4086,7 @@ pub mod tests {
|
||||||
fn test_unref() {
|
fn test_unref() {
|
||||||
let value = true;
|
let value = true;
|
||||||
let key = solana_sdk::pubkey::new_rand();
|
let key = solana_sdk::pubkey::new_rand();
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
let slot1 = 1;
|
let slot1 = 1;
|
||||||
|
|
||||||
index.upsert_simple_test(&key, slot1, value);
|
index.upsert_simple_test(&key, slot1, value);
|
||||||
|
@ -4107,7 +4119,7 @@ pub mod tests {
|
||||||
let value = true;
|
let value = true;
|
||||||
let key = solana_sdk::pubkey::new_rand();
|
let key = solana_sdk::pubkey::new_rand();
|
||||||
let key_unknown = solana_sdk::pubkey::new_rand();
|
let key_unknown = solana_sdk::pubkey::new_rand();
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
let slot1 = 1;
|
let slot1 = 1;
|
||||||
|
|
||||||
let mut gc = Vec::new();
|
let mut gc = Vec::new();
|
||||||
|
@ -4165,7 +4177,7 @@ pub mod tests {
|
||||||
let slot_list = vec![(slot2, value)];
|
let slot_list = vec![(slot2, value)];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
0,
|
0,
|
||||||
AccountsIndex::get_newest_root_in_slot_list(
|
AccountsIndex::<bool, bool>::get_newest_root_in_slot_list(
|
||||||
&roots_tracker.alive_roots,
|
&roots_tracker.alive_roots,
|
||||||
&slot_list,
|
&slot_list,
|
||||||
None,
|
None,
|
||||||
|
@ -4178,7 +4190,7 @@ pub mod tests {
|
||||||
let slot_list = vec![(slot2, value)];
|
let slot_list = vec![(slot2, value)];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
slot2,
|
slot2,
|
||||||
AccountsIndex::get_newest_root_in_slot_list(
|
AccountsIndex::<bool, bool>::get_newest_root_in_slot_list(
|
||||||
&roots_tracker.alive_roots,
|
&roots_tracker.alive_roots,
|
||||||
&slot_list,
|
&slot_list,
|
||||||
None,
|
None,
|
||||||
|
@ -4186,7 +4198,7 @@ pub mod tests {
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
0,
|
0,
|
||||||
AccountsIndex::get_newest_root_in_slot_list(
|
AccountsIndex::<bool, bool>::get_newest_root_in_slot_list(
|
||||||
&roots_tracker.alive_roots,
|
&roots_tracker.alive_roots,
|
||||||
&slot_list,
|
&slot_list,
|
||||||
Some(0),
|
Some(0),
|
||||||
|
@ -4208,7 +4220,7 @@ pub mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_handle_dead_keys_return() {
|
fn test_handle_dead_keys_return() {
|
||||||
let key = solana_sdk::pubkey::new_rand();
|
let key = solana_sdk::pubkey::new_rand();
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
index.handle_dead_keys(&[&key], &AccountSecondaryIndexes::default()),
|
index.handle_dead_keys(&[&key], &AccountSecondaryIndexes::default()),
|
||||||
|
@ -4218,7 +4230,7 @@ pub mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_start_end_bin() {
|
fn test_start_end_bin() {
|
||||||
let index = AccountsIndex::<bool>::default_for_tests();
|
let index = AccountsIndex::<bool, bool>::default_for_tests();
|
||||||
assert_eq!(index.bins(), BINS_FOR_TESTING);
|
assert_eq!(index.bins(), BINS_FOR_TESTING);
|
||||||
let iter = AccountsIndexIterator::new(
|
let iter = AccountsIndexIterator::new(
|
||||||
&index,
|
&index,
|
||||||
|
@ -4282,7 +4294,7 @@ pub mod tests {
|
||||||
fn test_illegal_bins() {
|
fn test_illegal_bins() {
|
||||||
let mut config = AccountsIndexConfig::default();
|
let mut config = AccountsIndexConfig::default();
|
||||||
config.bins = Some(3);
|
config.bins = Some(3);
|
||||||
AccountsIndex::<bool>::new(Some(config), &Arc::default());
|
AccountsIndex::<bool, bool>::new(Some(config), &Arc::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -16,18 +16,18 @@ use {
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Manages the lifetime of the background processing threads.
|
/// Manages the lifetime of the background processing threads.
|
||||||
pub struct AccountsIndexStorage<T: IndexValue> {
|
pub struct AccountsIndexStorage<T: IndexValue, U: IndexValue + From<T> + Into<T>> {
|
||||||
_bg_threads: BgThreads,
|
_bg_threads: BgThreads,
|
||||||
|
|
||||||
pub storage: Arc<BucketMapHolder<T>>,
|
pub storage: Arc<BucketMapHolder<T, U>>,
|
||||||
pub in_mem: Vec<Arc<InMemAccountsIndex<T>>>,
|
pub in_mem: Vec<Arc<InMemAccountsIndex<T, U>>>,
|
||||||
exit: Arc<AtomicBool>,
|
exit: Arc<AtomicBool>,
|
||||||
|
|
||||||
/// set_startup(true) creates bg threads which are kept alive until set_startup(false)
|
/// set_startup(true) creates bg threads which are kept alive until set_startup(false)
|
||||||
startup_worker_threads: Mutex<Option<BgThreads>>,
|
startup_worker_threads: Mutex<Option<BgThreads>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: IndexValue> Debug for AccountsIndexStorage<T> {
|
impl<T: IndexValue, U: IndexValue + From<T> + Into<T>> Debug for AccountsIndexStorage<T, U> {
|
||||||
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -53,9 +53,9 @@ impl Drop for BgThreads {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BgThreads {
|
impl BgThreads {
|
||||||
fn new<T: IndexValue>(
|
fn new<T: IndexValue, U: IndexValue + From<T> + Into<T>>(
|
||||||
storage: &Arc<BucketMapHolder<T>>,
|
storage: &Arc<BucketMapHolder<T, U>>,
|
||||||
in_mem: &[Arc<InMemAccountsIndex<T>>],
|
in_mem: &[Arc<InMemAccountsIndex<T, U>>],
|
||||||
threads: usize,
|
threads: usize,
|
||||||
can_advance_age: bool,
|
can_advance_age: bool,
|
||||||
exit: &Arc<AtomicBool>,
|
exit: &Arc<AtomicBool>,
|
||||||
|
@ -109,7 +109,7 @@ pub enum Startup {
|
||||||
StartupWithExtraThreads,
|
StartupWithExtraThreads,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: IndexValue> AccountsIndexStorage<T> {
|
impl<T: IndexValue, U: IndexValue + From<T> + Into<T>> AccountsIndexStorage<T, U> {
|
||||||
/// startup=true causes:
|
/// startup=true causes:
|
||||||
/// in mem to act in a way that flushes to disk asap
|
/// in mem to act in a way that flushes to disk asap
|
||||||
/// also creates some additional bg threads to facilitate flushing to disk asap
|
/// also creates some additional bg threads to facilitate flushing to disk asap
|
||||||
|
|
|
@ -13,6 +13,7 @@ use {
|
||||||
},
|
},
|
||||||
std::{
|
std::{
|
||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
|
marker::PhantomData,
|
||||||
sync::{
|
sync::{
|
||||||
atomic::{AtomicBool, AtomicU8, AtomicUsize, Ordering},
|
atomic::{AtomicBool, AtomicU8, AtomicUsize, Ordering},
|
||||||
Arc,
|
Arc,
|
||||||
|
@ -27,8 +28,8 @@ const AGE_MS: u64 = DEFAULT_MS_PER_SLOT; // match one age per slot time
|
||||||
// 10 GB limit for in-mem idx. In practice, we don't get this high. This tunes how aggressively to save items we expect to use soon.
|
// 10 GB limit for in-mem idx. In practice, we don't get this high. This tunes how aggressively to save items we expect to use soon.
|
||||||
pub const DEFAULT_DISK_INDEX: Option<usize> = Some(10_000);
|
pub const DEFAULT_DISK_INDEX: Option<usize> = Some(10_000);
|
||||||
|
|
||||||
pub struct BucketMapHolder<T: IndexValue> {
|
pub struct BucketMapHolder<T: IndexValue, U: IndexValue + From<T> + Into<T>> {
|
||||||
pub disk: Option<BucketMap<(Slot, T)>>,
|
pub disk: Option<BucketMap<(Slot, U)>>,
|
||||||
|
|
||||||
pub count_buckets_flushed: AtomicUsize,
|
pub count_buckets_flushed: AtomicUsize,
|
||||||
|
|
||||||
|
@ -66,16 +67,17 @@ pub struct BucketMapHolder<T: IndexValue> {
|
||||||
/// and writing to disk in parallel are.
|
/// and writing to disk in parallel are.
|
||||||
/// Note startup is an optimization and is not required for correctness.
|
/// Note startup is an optimization and is not required for correctness.
|
||||||
startup: AtomicBool,
|
startup: AtomicBool,
|
||||||
|
_phantom: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: IndexValue> Debug for BucketMapHolder<T> {
|
impl<T: IndexValue, U: IndexValue + From<T> + Into<T>> Debug for BucketMapHolder<T, U> {
|
||||||
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::mutex_atomic)]
|
#[allow(clippy::mutex_atomic)]
|
||||||
impl<T: IndexValue> BucketMapHolder<T> {
|
impl<T: IndexValue, U: IndexValue + From<T> + Into<T>> BucketMapHolder<T, U> {
|
||||||
/// is the accounts index using disk as a backing store
|
/// is the accounts index using disk as a backing store
|
||||||
pub fn is_disk_index_enabled(&self) -> bool {
|
pub fn is_disk_index_enabled(&self) -> bool {
|
||||||
self.disk.is_some()
|
self.disk.is_some()
|
||||||
|
@ -256,6 +258,7 @@ impl<T: IndexValue> BucketMapHolder<T> {
|
||||||
startup: AtomicBool::default(),
|
startup: AtomicBool::default(),
|
||||||
mem_budget_mb,
|
mem_budget_mb,
|
||||||
threads,
|
threads,
|
||||||
|
_phantom: PhantomData::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,7 +331,7 @@ impl<T: IndexValue> BucketMapHolder<T> {
|
||||||
pub fn background(
|
pub fn background(
|
||||||
&self,
|
&self,
|
||||||
exit: Vec<Arc<AtomicBool>>,
|
exit: Vec<Arc<AtomicBool>>,
|
||||||
in_mem: Vec<Arc<InMemAccountsIndex<T>>>,
|
in_mem: Vec<Arc<InMemAccountsIndex<T, U>>>,
|
||||||
can_advance_age: bool,
|
can_advance_age: bool,
|
||||||
) {
|
) {
|
||||||
let bins = in_mem.len();
|
let bins = in_mem.len();
|
||||||
|
@ -402,7 +405,7 @@ pub mod tests {
|
||||||
fn test_next_bucket_to_flush() {
|
fn test_next_bucket_to_flush() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let bins = 4;
|
let bins = 4;
|
||||||
let test = BucketMapHolder::<u64>::new(bins, &Some(AccountsIndexConfig::default()), 1);
|
let test = BucketMapHolder::<u64, u64>::new(bins, &Some(AccountsIndexConfig::default()), 1);
|
||||||
let visited = (0..bins)
|
let visited = (0..bins)
|
||||||
.map(|_| AtomicUsize::default())
|
.map(|_| AtomicUsize::default())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
@ -425,7 +428,7 @@ pub mod tests {
|
||||||
fn test_ages() {
|
fn test_ages() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let bins = 4;
|
let bins = 4;
|
||||||
let test = BucketMapHolder::<u64>::new(bins, &Some(AccountsIndexConfig::default()), 1);
|
let test = BucketMapHolder::<u64, u64>::new(bins, &Some(AccountsIndexConfig::default()), 1);
|
||||||
assert_eq!(0, test.current_age());
|
assert_eq!(0, test.current_age());
|
||||||
assert_eq!(test.ages_to_stay_in_cache, test.future_age_to_flush(false));
|
assert_eq!(test.ages_to_stay_in_cache, test.future_age_to_flush(false));
|
||||||
assert_eq!(u8::MAX, test.future_age_to_flush(true));
|
assert_eq!(u8::MAX, test.future_age_to_flush(true));
|
||||||
|
@ -445,7 +448,7 @@ pub mod tests {
|
||||||
fn test_age_increment() {
|
fn test_age_increment() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let bins = 4;
|
let bins = 4;
|
||||||
let test = BucketMapHolder::<u64>::new(bins, &Some(AccountsIndexConfig::default()), 1);
|
let test = BucketMapHolder::<u64, u64>::new(bins, &Some(AccountsIndexConfig::default()), 1);
|
||||||
for age in 0..513 {
|
for age in 0..513 {
|
||||||
assert_eq!(test.current_age(), (age % 256) as Age);
|
assert_eq!(test.current_age(), (age % 256) as Age);
|
||||||
|
|
||||||
|
@ -466,7 +469,7 @@ pub mod tests {
|
||||||
fn test_throttle() {
|
fn test_throttle() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let bins = 128;
|
let bins = 128;
|
||||||
let test = BucketMapHolder::<u64>::new(bins, &Some(AccountsIndexConfig::default()), 1);
|
let test = BucketMapHolder::<u64, u64>::new(bins, &Some(AccountsIndexConfig::default()), 1);
|
||||||
let bins = test.bins as u64;
|
let bins = test.bins as u64;
|
||||||
let interval_ms = test.age_interval_ms();
|
let interval_ms = test.age_interval_ms();
|
||||||
// 90% of time elapsed, all but 1 bins flushed, should not wait since we'll end up right on time
|
// 90% of time elapsed, all but 1 bins flushed, should not wait since we'll end up right on time
|
||||||
|
@ -498,7 +501,7 @@ pub mod tests {
|
||||||
index_limit_mb: IndexLimitMb::Limit(0),
|
index_limit_mb: IndexLimitMb::Limit(0),
|
||||||
..AccountsIndexConfig::default()
|
..AccountsIndexConfig::default()
|
||||||
};
|
};
|
||||||
let test = BucketMapHolder::<u64>::new(bins, &Some(config), 1);
|
let test = BucketMapHolder::<u64, u64>::new(bins, &Some(config), 1);
|
||||||
assert!(test.is_disk_index_enabled());
|
assert!(test.is_disk_index_enabled());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -506,7 +509,7 @@ pub mod tests {
|
||||||
fn test_age_time() {
|
fn test_age_time() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let bins = 1;
|
let bins = 1;
|
||||||
let test = BucketMapHolder::<u64>::new(bins, &Some(AccountsIndexConfig::default()), 1);
|
let test = BucketMapHolder::<u64, u64>::new(bins, &Some(AccountsIndexConfig::default()), 1);
|
||||||
let threads = 2;
|
let threads = 2;
|
||||||
let time = AGE_MS * 8 / 3;
|
let time = AGE_MS * 8 / 3;
|
||||||
let expected = (time / AGE_MS) as Age;
|
let expected = (time / AGE_MS) as Age;
|
||||||
|
@ -538,7 +541,7 @@ pub mod tests {
|
||||||
fn test_age_broad() {
|
fn test_age_broad() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let bins = 4;
|
let bins = 4;
|
||||||
let test = BucketMapHolder::<u64>::new(bins, &Some(AccountsIndexConfig::default()), 1);
|
let test = BucketMapHolder::<u64, u64>::new(bins, &Some(AccountsIndexConfig::default()), 1);
|
||||||
assert_eq!(test.current_age(), 0);
|
assert_eq!(test.current_age(), 0);
|
||||||
for _ in 0..bins {
|
for _ in 0..bins {
|
||||||
assert!(!test.all_buckets_flushed_at_current_age());
|
assert!(!test.all_buckets_flushed_at_current_age());
|
||||||
|
|
|
@ -99,7 +99,11 @@ impl BucketMapHolderStats {
|
||||||
per_bucket.map(|stat| stat.fetch_sub(count, Ordering::Relaxed));
|
per_bucket.map(|stat| stat.fetch_sub(count, Ordering::Relaxed));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ms_per_age<T: IndexValue>(&self, storage: &BucketMapHolder<T>, elapsed_ms: u64) -> u64 {
|
fn ms_per_age<T: IndexValue, U: IndexValue + From<T> + Into<T>>(
|
||||||
|
&self,
|
||||||
|
storage: &BucketMapHolder<T, U>,
|
||||||
|
elapsed_ms: u64,
|
||||||
|
) -> u64 {
|
||||||
let age_now = storage.current_age();
|
let age_now = storage.current_age();
|
||||||
let ages_flushed = storage.count_buckets_flushed() as u64;
|
let ages_flushed = storage.count_buckets_flushed() as u64;
|
||||||
let last_age = self.last_age.swap(age_now, Ordering::Relaxed) as u64;
|
let last_age = self.last_age.swap(age_now, Ordering::Relaxed) as u64;
|
||||||
|
@ -172,7 +176,10 @@ impl BucketMapHolderStats {
|
||||||
in_mem.saturating_sub(held_in_mem) as usize
|
in_mem.saturating_sub(held_in_mem) as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn report_stats<T: IndexValue>(&self, storage: &BucketMapHolder<T>) {
|
pub fn report_stats<T: IndexValue, U: IndexValue + From<T> + Into<T>>(
|
||||||
|
&self,
|
||||||
|
storage: &BucketMapHolder<T, U>,
|
||||||
|
) {
|
||||||
let elapsed_ms = self.last_time.elapsed_ms();
|
let elapsed_ms = self.last_time.elapsed_ms();
|
||||||
if elapsed_ms < STATS_INTERVAL_MS {
|
if elapsed_ms < STATS_INTERVAL_MS {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -83,15 +83,15 @@ impl<T: IndexValue> PossibleEvictions<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// one instance of this represents one bin of the accounts index.
|
// one instance of this represents one bin of the accounts index.
|
||||||
pub struct InMemAccountsIndex<T: IndexValue> {
|
pub struct InMemAccountsIndex<T: IndexValue, U: IndexValue + From<T> + Into<T>> {
|
||||||
last_age_flushed: AtomicU8,
|
last_age_flushed: AtomicU8,
|
||||||
|
|
||||||
// backing store
|
// backing store
|
||||||
map_internal: RwLock<InMemMap<T>>,
|
map_internal: RwLock<InMemMap<T>>,
|
||||||
storage: Arc<BucketMapHolder<T>>,
|
storage: Arc<BucketMapHolder<T, U>>,
|
||||||
bin: usize,
|
bin: usize,
|
||||||
|
|
||||||
bucket: Option<Arc<BucketApi<(Slot, T)>>>,
|
bucket: Option<Arc<BucketApi<(Slot, U)>>>,
|
||||||
|
|
||||||
// pubkey ranges that this bin must hold in the cache while the range is present in this vec
|
// pubkey ranges that this bin must hold in the cache while the range is present in this vec
|
||||||
pub(crate) cache_ranges_held: CacheRangesHeld,
|
pub(crate) cache_ranges_held: CacheRangesHeld,
|
||||||
|
@ -112,7 +112,7 @@ pub struct InMemAccountsIndex<T: IndexValue> {
|
||||||
age_to_flush_bin_mod: Age,
|
age_to_flush_bin_mod: Age,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: IndexValue> Debug for InMemAccountsIndex<T> {
|
impl<T: IndexValue, U: IndexValue + From<T> + Into<T>> Debug for InMemAccountsIndex<T, U> {
|
||||||
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -141,8 +141,8 @@ struct FlushScanResult<T> {
|
||||||
evictions_random: Vec<(Pubkey, AccountMapEntry<T>)>,
|
evictions_random: Vec<(Pubkey, AccountMapEntry<T>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: IndexValue> InMemAccountsIndex<T> {
|
impl<T: IndexValue, U: IndexValue + From<T> + Into<T>> InMemAccountsIndex<T, U> {
|
||||||
pub fn new(storage: &Arc<BucketMapHolder<T>>, bin: usize) -> Self {
|
pub fn new(storage: &Arc<BucketMapHolder<T, U>>, bin: usize) -> Self {
|
||||||
let ages_to_stay_in_cache = storage.ages_to_stay_in_cache;
|
let ages_to_stay_in_cache = storage.ages_to_stay_in_cache;
|
||||||
Self {
|
Self {
|
||||||
map_internal: RwLock::default(),
|
map_internal: RwLock::default(),
|
||||||
|
@ -237,7 +237,7 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
|
||||||
keys
|
keys
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_from_disk(&self, pubkey: &Pubkey) -> Option<(SlotList<T>, RefCount)> {
|
fn load_from_disk(&self, pubkey: &Pubkey) -> Option<(SlotList<U>, RefCount)> {
|
||||||
self.bucket.as_ref().and_then(|disk| {
|
self.bucket.as_ref().and_then(|disk| {
|
||||||
let m = Measure::start("load_disk_found_count");
|
let m = Measure::start("load_disk_found_count");
|
||||||
let entry_disk = disk.read_value(pubkey);
|
let entry_disk = disk.read_value(pubkey);
|
||||||
|
@ -641,11 +641,14 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
|
||||||
// convert from raw data on disk to AccountMapEntry, set to age in future
|
// convert from raw data on disk to AccountMapEntry, set to age in future
|
||||||
fn disk_to_cache_entry(
|
fn disk_to_cache_entry(
|
||||||
&self,
|
&self,
|
||||||
slot_list: SlotList<T>,
|
slot_list: SlotList<U>,
|
||||||
ref_count: RefCount,
|
ref_count: RefCount,
|
||||||
) -> AccountMapEntry<T> {
|
) -> AccountMapEntry<T> {
|
||||||
Arc::new(AccountMapEntryInner::new(
|
Arc::new(AccountMapEntryInner::new(
|
||||||
slot_list,
|
slot_list
|
||||||
|
.into_iter()
|
||||||
|
.map(|(slot, info)| (slot, info.into()))
|
||||||
|
.collect(),
|
||||||
ref_count,
|
ref_count,
|
||||||
AccountMapEntryMeta::new_clean(&self.storage),
|
AccountMapEntryMeta::new_clean(&self.storage),
|
||||||
))
|
))
|
||||||
|
@ -681,7 +684,7 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
|
||||||
Entry::Occupied(occupied) => {
|
Entry::Occupied(occupied) => {
|
||||||
// in cache, so merge into cache
|
// in cache, so merge into cache
|
||||||
let (slot, account_info) = new_entry.into();
|
let (slot, account_info) = new_entry.into();
|
||||||
InMemAccountsIndex::lock_and_update_slot_list(
|
InMemAccountsIndex::<T, U>::lock_and_update_slot_list(
|
||||||
occupied.get(),
|
occupied.get(),
|
||||||
(slot, account_info),
|
(slot, account_info),
|
||||||
None, // should be None because we don't expect a different slot # during index generation
|
None, // should be None because we don't expect a different slot # during index generation
|
||||||
|
@ -699,7 +702,7 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
|
||||||
self.stats().inc_mem_count(self.bin);
|
self.stats().inc_mem_count(self.bin);
|
||||||
if let Some(disk_entry) = disk_entry {
|
if let Some(disk_entry) = disk_entry {
|
||||||
let (slot, account_info) = new_entry.into();
|
let (slot, account_info) = new_entry.into();
|
||||||
InMemAccountsIndex::lock_and_update_slot_list(
|
InMemAccountsIndex::<T, U>::lock_and_update_slot_list(
|
||||||
&disk_entry,
|
&disk_entry,
|
||||||
(slot, account_info),
|
(slot, account_info),
|
||||||
// None because we are inserting the first element in the slot list for this pubkey.
|
// None because we are inserting the first element in the slot list for this pubkey.
|
||||||
|
@ -1051,7 +1054,7 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
|
||||||
// merge this in, mark as conflict
|
// merge this in, mark as conflict
|
||||||
let mut slot_list = Vec::with_capacity(current_slot_list.len() + 1);
|
let mut slot_list = Vec::with_capacity(current_slot_list.len() + 1);
|
||||||
slot_list.extend_from_slice(current_slot_list);
|
slot_list.extend_from_slice(current_slot_list);
|
||||||
slot_list.push(entry); // will never be from the same slot that already exists in the list
|
slot_list.push((entry.0, entry.1.into())); // will never be from the same slot that already exists in the list
|
||||||
ref_count += new_ref_count;
|
ref_count += new_ref_count;
|
||||||
duplicates.push((slot, k));
|
duplicates.push((slot, k));
|
||||||
Some((slot_list, ref_count))
|
Some((slot_list, ref_count))
|
||||||
|
@ -1059,7 +1062,7 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
|
||||||
None => {
|
None => {
|
||||||
count += 1;
|
count += 1;
|
||||||
// not on disk, insert it
|
// not on disk, insert it
|
||||||
Some((vec![entry], new_ref_count))
|
Some((vec![(entry.0, entry.1.into())], new_ref_count))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1159,7 +1162,16 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
|
||||||
let slot_list = slot_list
|
let slot_list = slot_list
|
||||||
.take()
|
.take()
|
||||||
.unwrap_or_else(|| v.slot_list.read().unwrap());
|
.unwrap_or_else(|| v.slot_list.read().unwrap());
|
||||||
disk.try_write(&k, (&slot_list, v.ref_count()))
|
disk.try_write(
|
||||||
|
&k,
|
||||||
|
(
|
||||||
|
&slot_list
|
||||||
|
.iter()
|
||||||
|
.map(|(slot, info)| (*slot, (*info).into()))
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
v.ref_count(),
|
||||||
|
),
|
||||||
|
)
|
||||||
};
|
};
|
||||||
match disk_resize {
|
match disk_resize {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
|
@ -1385,7 +1397,9 @@ struct EvictionsGuard<'a> {
|
||||||
|
|
||||||
impl<'a> EvictionsGuard<'a> {
|
impl<'a> EvictionsGuard<'a> {
|
||||||
#[must_use = "if unused, this evictions lock will be immediately unlocked"]
|
#[must_use = "if unused, this evictions lock will be immediately unlocked"]
|
||||||
fn lock<T: IndexValue>(in_mem_accounts_index: &'a InMemAccountsIndex<T>) -> Self {
|
fn lock<T: IndexValue, U: IndexValue + From<T> + Into<T>>(
|
||||||
|
in_mem_accounts_index: &'a InMemAccountsIndex<T, U>,
|
||||||
|
) -> Self {
|
||||||
Self::lock_with(
|
Self::lock_with(
|
||||||
&in_mem_accounts_index.stop_evictions,
|
&in_mem_accounts_index.stop_evictions,
|
||||||
&in_mem_accounts_index.stop_evictions_changes,
|
&in_mem_accounts_index.stop_evictions_changes,
|
||||||
|
@ -1433,7 +1447,7 @@ mod tests {
|
||||||
itertools::Itertools,
|
itertools::Itertools,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn new_for_test<T: IndexValue>() -> InMemAccountsIndex<T> {
|
fn new_for_test<T: IndexValue>() -> InMemAccountsIndex<T, T> {
|
||||||
let holder = Arc::new(BucketMapHolder::new(
|
let holder = Arc::new(BucketMapHolder::new(
|
||||||
BINS_FOR_TESTING,
|
BINS_FOR_TESTING,
|
||||||
&Some(AccountsIndexConfig::default()),
|
&Some(AccountsIndexConfig::default()),
|
||||||
|
@ -1443,7 +1457,7 @@ mod tests {
|
||||||
InMemAccountsIndex::new(&holder, bin)
|
InMemAccountsIndex::new(&holder, bin)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_disk_buckets_for_test<T: IndexValue>() -> InMemAccountsIndex<T> {
|
fn new_disk_buckets_for_test<T: IndexValue>() -> InMemAccountsIndex<T, T> {
|
||||||
let holder = Arc::new(BucketMapHolder::new(
|
let holder = Arc::new(BucketMapHolder::new(
|
||||||
BINS_FOR_TESTING,
|
BINS_FOR_TESTING,
|
||||||
&Some(AccountsIndexConfig {
|
&Some(AccountsIndexConfig {
|
||||||
|
@ -1723,7 +1737,7 @@ mod tests {
|
||||||
let mut slot_list = Vec::default();
|
let mut slot_list = Vec::default();
|
||||||
// upserting into empty slot_list, so always addref
|
// upserting into empty slot_list, so always addref
|
||||||
assert!(
|
assert!(
|
||||||
InMemAccountsIndex::update_slot_list(
|
InMemAccountsIndex::<u64, u64>::update_slot_list(
|
||||||
&mut slot_list,
|
&mut slot_list,
|
||||||
new_slot,
|
new_slot,
|
||||||
info,
|
info,
|
||||||
|
@ -1746,7 +1760,7 @@ mod tests {
|
||||||
// upserting into slot_list that does NOT contain an entry at 'new_slot'
|
// upserting into slot_list that does NOT contain an entry at 'new_slot'
|
||||||
// but, it DOES contain an entry at other_slot, so we do NOT add-ref. The assumption is that 'other_slot' is going away
|
// but, it DOES contain an entry at other_slot, so we do NOT add-ref. The assumption is that 'other_slot' is going away
|
||||||
// and that the previously held add-ref is now used by 'new_slot'
|
// and that the previously held add-ref is now used by 'new_slot'
|
||||||
!InMemAccountsIndex::update_slot_list(
|
!InMemAccountsIndex::<u64, u64>::update_slot_list(
|
||||||
&mut slot_list,
|
&mut slot_list,
|
||||||
new_slot,
|
new_slot,
|
||||||
info,
|
info,
|
||||||
|
@ -1766,7 +1780,7 @@ mod tests {
|
||||||
// upserting into slot_list that already contain an entry at 'new-slot', so do NOT addref
|
// upserting into slot_list that already contain an entry at 'new-slot', so do NOT addref
|
||||||
let mut reclaims = Vec::default();
|
let mut reclaims = Vec::default();
|
||||||
assert!(
|
assert!(
|
||||||
!InMemAccountsIndex::update_slot_list(
|
!InMemAccountsIndex::<u64, u64>::update_slot_list(
|
||||||
&mut slot_list,
|
&mut slot_list,
|
||||||
new_slot,
|
new_slot,
|
||||||
info,
|
info,
|
||||||
|
@ -1837,7 +1851,7 @@ mod tests {
|
||||||
let original = slot_list.clone();
|
let original = slot_list.clone();
|
||||||
let mut reclaims = Vec::default();
|
let mut reclaims = Vec::default();
|
||||||
|
|
||||||
let result = InMemAccountsIndex::update_slot_list(
|
let result = InMemAccountsIndex::<u64, u64>::update_slot_list(
|
||||||
&mut slot_list,
|
&mut slot_list,
|
||||||
new_slot,
|
new_slot,
|
||||||
info,
|
info,
|
||||||
|
@ -1965,7 +1979,7 @@ mod tests {
|
||||||
let info = 65;
|
let info = 65;
|
||||||
let mut reclaims = Vec::default();
|
let mut reclaims = Vec::default();
|
||||||
// first upsert, should increase
|
// first upsert, should increase
|
||||||
let len = InMemAccountsIndex::lock_and_update_slot_list(
|
let len = InMemAccountsIndex::<u64, u64>::lock_and_update_slot_list(
|
||||||
&test,
|
&test,
|
||||||
(1, info),
|
(1, info),
|
||||||
None,
|
None,
|
||||||
|
@ -1975,7 +1989,7 @@ mod tests {
|
||||||
assert_eq!(test.slot_list.read().unwrap().len(), len);
|
assert_eq!(test.slot_list.read().unwrap().len(), len);
|
||||||
assert_eq!(len, 1);
|
assert_eq!(len, 1);
|
||||||
// update to different slot, should increase
|
// update to different slot, should increase
|
||||||
let len = InMemAccountsIndex::lock_and_update_slot_list(
|
let len = InMemAccountsIndex::<u64, u64>::lock_and_update_slot_list(
|
||||||
&test,
|
&test,
|
||||||
(2, info),
|
(2, info),
|
||||||
None,
|
None,
|
||||||
|
@ -1985,7 +1999,7 @@ mod tests {
|
||||||
assert_eq!(test.slot_list.read().unwrap().len(), len);
|
assert_eq!(test.slot_list.read().unwrap().len(), len);
|
||||||
assert_eq!(len, 2);
|
assert_eq!(len, 2);
|
||||||
// update to same slot, should not increase
|
// update to same slot, should not increase
|
||||||
let len = InMemAccountsIndex::lock_and_update_slot_list(
|
let len = InMemAccountsIndex::<u64, u64>::lock_and_update_slot_list(
|
||||||
&test,
|
&test,
|
||||||
(2, info),
|
(2, info),
|
||||||
None,
|
None,
|
||||||
|
|
Loading…
Reference in New Issue