1use crate::{
2 accounts_index_storage::AccountsIndexStorage,
3 ancestors::Ancestors,
4 bucket_map_holder::{Age, BucketMapHolder},
5 contains::Contains,
6 in_mem_accounts_index::InMemAccountsIndex,
7 inline_spl_token_v2_0::{self, SPL_TOKEN_ACCOUNT_MINT_OFFSET, SPL_TOKEN_ACCOUNT_OWNER_OFFSET},
8 pubkey_bins::PubkeyBinCalculator16,
9 secondary_index::*,
10};
11use bv::BitVec;
12use log::*;
13use ouroboros::self_referencing;
14use rand::thread_rng;
15use rand::Rng;
16use gemachain_measure::measure::Measure;
17use gemachain_sdk::{
18 clock::{BankId, Slot},
19 pubkey::{Pubkey, PUBKEY_BYTES},
20};
21use std::{
22 collections::{btree_map::BTreeMap, HashSet},
23 fmt::Debug,
24 ops::{
25 Bound,
26 Bound::{Excluded, Included, Unbounded},
27 Range, RangeBounds,
28 },
29 path::PathBuf,
30 sync::{
31 atomic::{AtomicBool, AtomicU64, AtomicU8, Ordering},
32 Arc, Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard,
33 },
34};
35use thiserror::Error;
36
37pub const ITER_BATCH_SIZE: usize = 1000;
38pub const BINS_DEFAULT: usize = 8192;
39pub const BINS_FOR_TESTING: usize = 2; pub const BINS_FOR_BENCHMARKS: usize = 2;
41pub const FLUSH_THREADS_TESTING: usize = 1;
42pub const ACCOUNTS_INDEX_CONFIG_FOR_TESTING: AccountsIndexConfig = AccountsIndexConfig {
43 bins: Some(BINS_FOR_TESTING),
44 flush_threads: Some(FLUSH_THREADS_TESTING),
45 drives: None,
46 index_limit_mb: Some(1),
47 ages_to_stay_in_cache: None,
48};
49pub const ACCOUNTS_INDEX_CONFIG_FOR_BENCHMARKS: AccountsIndexConfig = AccountsIndexConfig {
50 bins: Some(BINS_FOR_BENCHMARKS),
51 flush_threads: Some(FLUSH_THREADS_TESTING),
52 drives: None,
53 index_limit_mb: None,
54 ages_to_stay_in_cache: None,
55};
56pub type ScanResult<T> = Result<T, ScanError>;
57pub type SlotList<T> = Vec<(Slot, T)>;
58pub type SlotSlice<'s, T> = &'s [(Slot, T)];
59pub type RefCount = u64;
60pub type AccountMap<V> = Arc<InMemAccountsIndex<V>>;
61
62pub(crate) type AccountMapEntry<T> = Arc<AccountMapEntryInner<T>>;
63
64pub trait IsCached:
65 'static + Clone + Debug + PartialEq + ZeroCarat + Copy + Default + Sync + Send
66{
67 fn is_cached(&self) -> bool;
68}
69
70pub trait IndexValue:
71 'static + IsCached + Clone + Debug + PartialEq + ZeroCarat + Copy + Default + Sync + Send
72{
73}
74
75#[derive(Error, Debug, PartialEq)]
76pub enum ScanError {
77 #[error("Node detected it replayed bad version of slot {slot:?} with id {bank_id:?}, thus the scan on said slot was aborted")]
78 SlotRemoved { slot: Slot, bank_id: BankId },
79}
80
81enum ScanTypes<R: RangeBounds<Pubkey>> {
82 Unindexed(Option<R>),
83 Indexed(IndexKey),
84}
85
86#[derive(Debug, Clone, Copy)]
87pub enum IndexKey {
88 ProgramId(Pubkey),
89 SplTokenMint(Pubkey),
90 SplTokenOwner(Pubkey),
91}
92
93#[derive(Debug, Clone, PartialEq, Eq, Hash)]
94pub enum AccountIndex {
95 ProgramId,
96 SplTokenMint,
97 SplTokenOwner,
98}
99
100#[derive(Debug, PartialEq, Eq, Clone)]
101pub struct AccountSecondaryIndexesIncludeExclude {
102 pub exclude: bool,
103 pub keys: HashSet<Pubkey>,
104}
105
106#[derive(Debug, Default, Clone)]
107pub struct AccountsIndexConfig {
108 pub bins: Option<usize>,
109 pub flush_threads: Option<usize>,
110 pub drives: Option<Vec<PathBuf>>,
111 pub index_limit_mb: Option<usize>,
112 pub ages_to_stay_in_cache: Option<Age>,
113}
114
115#[derive(Debug, Default, Clone)]
116pub struct AccountSecondaryIndexes {
117 pub keys: Option<AccountSecondaryIndexesIncludeExclude>,
118 pub indexes: HashSet<AccountIndex>,
119}
120
121impl AccountSecondaryIndexes {
122 pub fn is_empty(&self) -> bool {
123 self.indexes.is_empty()
124 }
125 pub fn contains(&self, index: &AccountIndex) -> bool {
126 self.indexes.contains(index)
127 }
128 pub fn include_key(&self, key: &Pubkey) -> bool {
129 match &self.keys {
130 Some(options) => options.exclude ^ options.keys.contains(key),
131 None => true, }
133 }
134}
135
136#[derive(Debug, Default)]
137pub struct AccountMapEntryMeta {
138 pub dirty: AtomicBool,
139 pub age: AtomicU8,
140}
141
142impl AccountMapEntryMeta {
143 pub fn new_dirty<T: IndexValue>(storage: &Arc<BucketMapHolder<T>>) -> Self {
144 AccountMapEntryMeta {
145 dirty: AtomicBool::new(true),
146 age: AtomicU8::new(storage.future_age_to_flush()),
147 }
148 }
149}
150
151#[derive(Debug, Default)]
152pub struct AccountMapEntryInner<T> {
153 ref_count: AtomicU64,
154 pub slot_list: RwLock<SlotList<T>>,
155 pub meta: AccountMapEntryMeta,
156}
157
158impl<T: IndexValue> AccountMapEntryInner<T> {
159 pub fn new(slot_list: SlotList<T>, ref_count: RefCount, meta: AccountMapEntryMeta) -> Self {
160 Self {
161 slot_list: RwLock::new(slot_list),
162 ref_count: AtomicU64::new(ref_count),
163 meta,
164 }
165 }
166 pub fn ref_count(&self) -> RefCount {
167 self.ref_count.load(Ordering::Relaxed)
168 }
169
170 pub fn add_un_ref(&self, add: bool) {
171 if add {
172 self.ref_count.fetch_add(1, Ordering::Relaxed);
173 } else {
174 self.ref_count.fetch_sub(1, Ordering::Relaxed);
175 }
176 self.set_dirty(true);
177 }
178
179 pub fn dirty(&self) -> bool {
180 self.meta.dirty.load(Ordering::Acquire)
181 }
182
183 pub fn set_dirty(&self, value: bool) {
184 self.meta.dirty.store(value, Ordering::Release)
185 }
186
187 pub fn age(&self) -> Age {
188 self.meta.age.load(Ordering::Relaxed)
189 }
190
191 pub fn set_age(&self, value: Age) {
192 self.meta.age.store(value, Ordering::Relaxed)
193 }
194}
195
196pub enum AccountIndexGetResult<'a, T: IndexValue> {
197 Found(ReadAccountMapEntry<T>, usize),
198 NotFoundOnFork,
199 Missing(AccountMapsReadLock<'a, T>),
200}
201
202#[self_referencing]
203pub struct ReadAccountMapEntry<T: IndexValue> {
204 owned_entry: AccountMapEntry<T>,
205 #[borrows(owned_entry)]
206 #[covariant]
207 slot_list_guard: RwLockReadGuard<'this, SlotList<T>>,
208}
209
210impl<T: IndexValue> Debug for ReadAccountMapEntry<T> {
211 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
212 write!(f, "{:?}", self.borrow_owned_entry())
213 }
214}
215
216impl<T: IndexValue> ReadAccountMapEntry<T> {
217 pub fn from_account_map_entry(account_map_entry: AccountMapEntry<T>) -> Self {
218 ReadAccountMapEntryBuilder {
219 owned_entry: account_map_entry,
220 slot_list_guard_builder: |lock| lock.slot_list.read().unwrap(),
221 }
222 .build()
223 }
224
225 pub fn slot_list(&self) -> &SlotList<T> {
226 &*self.borrow_slot_list_guard()
227 }
228
229 pub fn ref_count(&self) -> RefCount {
230 self.borrow_owned_entry().ref_count()
231 }
232
233 pub fn unref(&self) {
234 self.borrow_owned_entry().add_un_ref(false);
235 }
236
237 pub fn addref(&self) {
238 self.borrow_owned_entry().add_un_ref(true);
239 }
240}
241
242pub struct PreAllocatedAccountMapEntry<T: IndexValue> {
243 entry: AccountMapEntry<T>,
244}
245
246impl<T: IndexValue> From<PreAllocatedAccountMapEntry<T>> for AccountMapEntry<T> {
247 fn from(source: PreAllocatedAccountMapEntry<T>) -> AccountMapEntry<T> {
248 source.entry
249 }
250}
251
252impl<T: IndexValue> From<PreAllocatedAccountMapEntry<T>> for (Slot, T) {
253 fn from(source: PreAllocatedAccountMapEntry<T>) -> (Slot, T) {
254 source.entry.slot_list.write().unwrap().remove(0)
255 }
256}
257
258impl<T: IndexValue> PreAllocatedAccountMapEntry<T> {
259 pub fn new(
264 slot: Slot,
265 account_info: T,
266 storage: &Arc<BucketMapHolder<T>>,
267 ) -> PreAllocatedAccountMapEntry<T> {
268 Self::new_internal(slot, account_info, AccountMapEntryMeta::new_dirty(storage))
269 }
270
271 fn new_internal(
272 slot: Slot,
273 account_info: T,
274 meta: AccountMapEntryMeta,
275 ) -> PreAllocatedAccountMapEntry<T> {
276 let ref_count = if account_info.is_cached() { 0 } else { 1 };
277 PreAllocatedAccountMapEntry {
278 entry: Arc::new(AccountMapEntryInner::new(
279 vec![(slot, account_info)],
280 ref_count,
281 meta,
282 )),
283 }
284 }
285}
286
287#[self_referencing]
288pub struct WriteAccountMapEntry<T: IndexValue> {
289 owned_entry: AccountMapEntry<T>,
290 #[borrows(owned_entry)]
291 #[covariant]
292 slot_list_guard: RwLockWriteGuard<'this, SlotList<T>>,
293}
294
295impl<T: IndexValue> WriteAccountMapEntry<T> {
296 pub fn from_account_map_entry(account_map_entry: AccountMapEntry<T>) -> Self {
297 WriteAccountMapEntryBuilder {
298 owned_entry: account_map_entry,
299 slot_list_guard_builder: |lock| lock.slot_list.write().unwrap(),
300 }
301 .build()
302 }
303
304 pub fn slot_list(&self) -> &SlotList<T> {
305 &*self.borrow_slot_list_guard()
306 }
307
308 pub fn slot_list_mut<RT>(
309 &mut self,
310 user: impl for<'this> FnOnce(&mut RwLockWriteGuard<'this, SlotList<T>>) -> RT,
311 ) -> RT {
312 let result = self.with_slot_list_guard_mut(user);
313 self.borrow_owned_entry().set_dirty(true);
314 result
315 }
316}
317
318#[derive(Debug, Default, AbiExample, Clone)]
319pub struct RollingBitField {
320 max_width: u64,
321 min: u64,
322 max: u64, bits: BitVec,
324 count: usize,
325 excess: HashSet<u64>,
330}
331
332impl PartialEq<RollingBitField> for RollingBitField {
333 fn eq(&self, other: &Self) -> bool {
334 self.len() == other.len() && {
337 for item in self.get_all() {
338 if !other.contains(&item) {
339 return false;
340 }
341 }
342 true
343 }
344 }
345}
346
347impl RollingBitField {
351 pub fn new(max_width: u64) -> Self {
352 assert!(max_width > 0);
353 assert!(max_width.is_power_of_two()); let bits = BitVec::new_fill(false, max_width);
355 Self {
356 max_width,
357 bits,
358 count: 0,
359 min: 0,
360 max: 0,
361 excess: HashSet::new(),
362 }
363 }
364
365 fn get_address(&self, key: &u64) -> u64 {
367 key % self.max_width
368 }
369
370 pub fn range_width(&self) -> u64 {
371 self.max - self.min
373 }
374
375 pub fn min(&self) -> Option<u64> {
376 if self.is_empty() {
377 None
378 } else if self.excess.is_empty() {
379 Some(self.min)
380 } else {
381 let mut min = if self.all_items_in_excess() {
382 u64::MAX
383 } else {
384 self.min
385 };
386 for item in &self.excess {
387 min = std::cmp::min(min, *item);
388 }
389 Some(min)
390 }
391 }
392
393 pub fn insert(&mut self, key: u64) {
394 let mut bits_empty = self.count == 0 || self.all_items_in_excess();
395 let update_bits = if bits_empty {
396 true } else if key < self.min {
398 if self.excess.insert(key) {
400 self.count += 1;
401 }
402 false
403 } else if key < self.max {
404 true } else {
406 let new_max = key + 1;
408 loop {
409 let new_width = new_max.saturating_sub(self.min);
410 if new_width <= self.max_width {
411 break;
413 }
414
415 let inserted = self.excess.insert(self.min);
417 assert!(inserted);
418
419 let key = self.min;
420 let address = self.get_address(&key);
421 self.bits.set(address, false);
422 self.purge(&key);
423
424 if self.all_items_in_excess() {
425 bits_empty = true;
427 break;
428 }
429 }
430
431 true };
433
434 if update_bits {
435 let address = self.get_address(&key);
436 let value = self.bits.get(address);
437 if !value {
438 self.bits.set(address, true);
439 if bits_empty {
440 self.min = key;
441 self.max = key + 1;
442 } else {
443 self.min = std::cmp::min(self.min, key);
444 self.max = std::cmp::max(self.max, key + 1);
445 assert!(
446 self.min + self.max_width >= self.max,
447 "min: {}, max: {}, max_width: {}",
448 self.min,
449 self.max,
450 self.max_width
451 );
452 }
453 self.count += 1;
454 }
455 }
456 }
457
458 pub fn remove(&mut self, key: &u64) -> bool {
459 if key >= &self.min {
460 if key < &self.max {
462 let address = self.get_address(key);
463 let get = self.bits.get(address);
464 if get {
465 self.count -= 1;
466 self.bits.set(address, false);
467 self.purge(key);
468 }
469 get
470 } else {
471 false
472 }
473 } else {
474 let remove = self.excess.remove(key);
476 if remove {
477 self.count -= 1;
478 }
479 remove
480 }
481 }
482
483 fn all_items_in_excess(&self) -> bool {
484 self.excess.len() == self.count
485 }
486
487 fn purge(&mut self, key: &u64) {
489 if self.count > 0 && !self.all_items_in_excess() {
490 if key == &self.min {
491 let start = self.min + 1; for key in start..self.max {
493 if self.contains_assume_in_range(&key) {
494 self.min = key;
495 break;
496 }
497 }
498 }
499 } else {
500 self.min = self.max;
512 }
513 }
514
515 fn contains_assume_in_range(&self, key: &u64) -> bool {
516 let address = self.get_address(key);
518 self.bits.get(address)
519 }
520
521 pub fn contains(&self, key: &u64) -> bool {
524 if key < &self.max {
525 if key >= &self.min {
526 self.contains_assume_in_range(key)
528 } else {
529 self.excess.contains(key)
530 }
531 } else {
532 false
533 }
534 }
535
536 pub fn len(&self) -> usize {
537 self.count
538 }
539
540 pub fn is_empty(&self) -> bool {
541 self.len() == 0
542 }
543
544 pub fn clear(&mut self) {
545 let mut n = Self::new(self.max_width);
546 std::mem::swap(&mut n, self);
547 }
548
549 pub fn max(&self) -> u64 {
550 self.max
551 }
552
553 pub fn get_all(&self) -> Vec<u64> {
554 let mut all = Vec::with_capacity(self.count);
555 self.excess.iter().for_each(|slot| all.push(*slot));
556 for key in self.min..self.max {
557 if self.contains_assume_in_range(&key) {
558 all.push(key);
559 }
560 }
561 all
562 }
563}
564
565#[derive(Debug)]
566pub struct RootsTracker {
567 roots: RollingBitField,
568 max_root: Slot,
569 uncleaned_roots: HashSet<Slot>,
570 previous_uncleaned_roots: HashSet<Slot>,
571}
572
573impl Default for RootsTracker {
574 fn default() -> Self {
575 RootsTracker::new(4194304)
579 }
580}
581
582impl RootsTracker {
583 pub fn new(max_width: u64) -> Self {
584 Self {
585 roots: RollingBitField::new(max_width),
586 max_root: 0,
587 uncleaned_roots: HashSet::new(),
588 previous_uncleaned_roots: HashSet::new(),
589 }
590 }
591
592 pub fn min_root(&self) -> Option<Slot> {
593 self.roots.min()
594 }
595}
596
597#[derive(Debug, Default)]
598pub struct AccountsIndexRootsStats {
599 pub roots_len: usize,
600 pub uncleaned_roots_len: usize,
601 pub previous_uncleaned_roots_len: usize,
602 pub roots_range: u64,
603 pub rooted_cleaned_count: usize,
604 pub unrooted_cleaned_count: usize,
605}
606
607pub struct AccountsIndexIterator<'a, T: IndexValue> {
608 account_maps: &'a LockMapTypeSlice<T>,
609 bin_calculator: &'a PubkeyBinCalculator16,
610 start_bound: Bound<Pubkey>,
611 end_bound: Bound<Pubkey>,
612 is_finished: bool,
613 collect_all_unsorted: bool,
614}
615
616impl<'a, T: IndexValue> AccountsIndexIterator<'a, T> {
617 fn range<R>(
618 map: &AccountMapsReadLock<T>,
619 range: R,
620 collect_all_unsorted: bool,
621 ) -> Vec<(Pubkey, AccountMapEntry<T>)>
622 where
623 R: RangeBounds<Pubkey> + std::fmt::Debug,
624 {
625 let mut result = map.items(&Some(&range));
626 if !collect_all_unsorted {
627 result.sort_unstable_by(|a, b| a.0.cmp(&b.0));
628 }
629 result
630 }
631
632 fn clone_bound(bound: Bound<&Pubkey>) -> Bound<Pubkey> {
633 match bound {
634 Unbounded => Unbounded,
635 Included(k) => Included(*k),
636 Excluded(k) => Excluded(*k),
637 }
638 }
639
640 fn bin_from_bound(&self, bound: &Bound<Pubkey>, unbounded_bin: usize) -> usize {
641 match bound {
642 Bound::Included(bound) | Bound::Excluded(bound) => {
643 self.bin_calculator.bin_from_pubkey(bound)
644 }
645 Bound::Unbounded => unbounded_bin,
646 }
647 }
648
649 fn start_bin(&self) -> usize {
650 self.bin_from_bound(&self.start_bound, 0)
652 }
653
654 fn end_bin_inclusive(&self) -> usize {
655 self.bin_from_bound(&self.end_bound, usize::MAX)
657 }
658
659 fn bin_start_and_range(&self) -> (usize, usize) {
660 let start_bin = self.start_bin();
661 let end_bin_inclusive = self.end_bin_inclusive();
663 let bin_range = if start_bin > end_bin_inclusive {
664 0 } else if end_bin_inclusive == usize::MAX {
666 usize::MAX
667 } else {
668 end_bin_inclusive.saturating_add(1) - start_bin
671 };
672 (start_bin, bin_range)
673 }
674
675 pub fn new<R>(
676 index: &'a AccountsIndex<T>,
677 range: Option<&R>,
678 collect_all_unsorted: bool,
679 ) -> Self
680 where
681 R: RangeBounds<Pubkey>,
682 {
683 Self {
684 start_bound: range
685 .as_ref()
686 .map(|r| Self::clone_bound(r.start_bound()))
687 .unwrap_or(Unbounded),
688 end_bound: range
689 .as_ref()
690 .map(|r| Self::clone_bound(r.end_bound()))
691 .unwrap_or(Unbounded),
692 account_maps: &index.account_maps,
693 is_finished: false,
694 bin_calculator: &index.bin_calculator,
695 collect_all_unsorted,
696 }
697 }
698
699 pub fn hold_range_in_memory<R>(&self, range: &R, start_holding: bool)
700 where
701 R: RangeBounds<Pubkey> + Debug,
702 {
703 let (start_bin, bin_range) = self.bin_start_and_range();
705 self.account_maps
706 .iter()
707 .skip(start_bin)
708 .take(bin_range)
709 .for_each(|map| {
710 map.read()
711 .unwrap()
712 .hold_range_in_memory(range, start_holding);
713 });
714 }
715}
716
717impl<'a, T: IndexValue> Iterator for AccountsIndexIterator<'a, T> {
718 type Item = Vec<(Pubkey, AccountMapEntry<T>)>;
719 fn next(&mut self) -> Option<Self::Item> {
720 if self.is_finished {
721 return None;
722 }
723 let (start_bin, bin_range) = self.bin_start_and_range();
724 let mut chunk = Vec::with_capacity(ITER_BATCH_SIZE);
725 'outer: for i in self.account_maps.iter().skip(start_bin).take(bin_range) {
726 for (pubkey, account_map_entry) in Self::range(
727 &i.read().unwrap(),
728 (self.start_bound, self.end_bound),
729 self.collect_all_unsorted,
730 ) {
731 if chunk.len() >= ITER_BATCH_SIZE && !self.collect_all_unsorted {
732 break 'outer;
733 }
734 let item = (pubkey, account_map_entry);
735 chunk.push(item);
736 }
737 }
738
739 if chunk.is_empty() {
740 self.is_finished = true;
741 return None;
742 } else if self.collect_all_unsorted {
743 self.is_finished = true;
744 }
745
746 self.start_bound = Excluded(chunk.last().unwrap().0);
747 Some(chunk)
748 }
749}
750
751pub trait ZeroCarat {
752 fn is_zero_carat(&self) -> bool;
753}
754
755type MapType<T> = AccountMap<T>;
756type LockMapType<T> = Vec<RwLock<MapType<T>>>;
757type LockMapTypeSlice<T> = [RwLock<MapType<T>>];
758type AccountMapsWriteLock<'a, T> = RwLockWriteGuard<'a, MapType<T>>;
759type AccountMapsReadLock<'a, T> = RwLockReadGuard<'a, MapType<T>>;
760
761#[derive(Debug, Default)]
762pub struct ScanSlotTracker {
763 is_removed: bool,
764 ref_count: u64,
765}
766
767impl ScanSlotTracker {
768 pub fn is_removed(&self) -> bool {
769 self.is_removed
770 }
771
772 pub fn mark_removed(&mut self) {
773 self.is_removed = true;
774 }
775}
776
777#[derive(Debug)]
778pub struct AccountsIndex<T: IndexValue> {
779 pub account_maps: LockMapType<T>,
780 pub bin_calculator: PubkeyBinCalculator16,
781 program_id_index: SecondaryIndex<DashMapSecondaryIndexEntry>,
782 spl_token_mint_index: SecondaryIndex<DashMapSecondaryIndexEntry>,
783 spl_token_owner_index: SecondaryIndex<RwLockSecondaryIndexEntry>,
784 roots_tracker: RwLock<RootsTracker>,
785 ongoing_scan_roots: RwLock<BTreeMap<Slot, u64>>,
786 pub removed_bank_ids: Mutex<HashSet<BankId>>,
797
798 storage: AccountsIndexStorage<T>,
799}
800
801impl<T: IndexValue> AccountsIndex<T> {
802 pub fn default_for_tests() -> Self {
803 Self::new(Some(ACCOUNTS_INDEX_CONFIG_FOR_TESTING))
804 }
805
806 pub fn new(config: Option<AccountsIndexConfig>) -> Self {
807 let (account_maps, bin_calculator, storage) = Self::allocate_accounts_index(config);
808 Self {
809 account_maps,
810 bin_calculator,
811 program_id_index: SecondaryIndex::<DashMapSecondaryIndexEntry>::new(
812 "program_id_index_stats",
813 ),
814 spl_token_mint_index: SecondaryIndex::<DashMapSecondaryIndexEntry>::new(
815 "spl_token_mint_index_stats",
816 ),
817 spl_token_owner_index: SecondaryIndex::<RwLockSecondaryIndexEntry>::new(
818 "spl_token_owner_index_stats",
819 ),
820 roots_tracker: RwLock::<RootsTracker>::default(),
821 ongoing_scan_roots: RwLock::<BTreeMap<Slot, u64>>::default(),
822 removed_bank_ids: Mutex::<HashSet<BankId>>::default(),
823 storage,
824 }
825 }
826
827 fn allocate_accounts_index(
828 config: Option<AccountsIndexConfig>,
829 ) -> (
830 LockMapType<T>,
831 PubkeyBinCalculator16,
832 AccountsIndexStorage<T>,
833 ) {
834 let bins = config
835 .as_ref()
836 .and_then(|config| config.bins)
837 .unwrap_or(BINS_DEFAULT);
838 let bin_calculator = PubkeyBinCalculator16::new(bins);
840 let storage = AccountsIndexStorage::new(bins, &config);
841 let account_maps = (0..bins)
842 .into_iter()
843 .map(|bin| RwLock::new(Arc::clone(&storage.in_mem[bin])))
844 .collect::<Vec<_>>();
845 (account_maps, bin_calculator, storage)
846 }
847
848 fn iter<R>(&self, range: Option<&R>, collect_all_unsorted: bool) -> AccountsIndexIterator<T>
849 where
850 R: RangeBounds<Pubkey>,
851 {
852 AccountsIndexIterator::new(self, range, collect_all_unsorted)
853 }
854
855 fn do_checked_scan_accounts<F, R>(
856 &self,
857 metric_name: &'static str,
858 ancestors: &Ancestors,
859 scan_bank_id: BankId,
860 func: F,
861 scan_type: ScanTypes<R>,
862 collect_all_unsorted: bool,
863 ) -> Result<(), ScanError>
864 where
865 F: FnMut(&Pubkey, (&T, Slot)),
866 R: RangeBounds<Pubkey> + std::fmt::Debug,
867 {
868 {
869 let locked_removed_bank_ids = self.removed_bank_ids.lock().unwrap();
870 if locked_removed_bank_ids.contains(&scan_bank_id) {
871 return Err(ScanError::SlotRemoved {
872 slot: ancestors.max_slot(),
873 bank_id: scan_bank_id,
874 });
875 }
876 }
877
878 let max_root = {
879 let mut w_ongoing_scan_roots = self
880 .ongoing_scan_roots
885 .write()
886 .unwrap();
887 let max_root = self.max_root();
892 *w_ongoing_scan_roots.entry(max_root).or_default() += 1;
893
894 max_root
895 };
896
897 let empty = Ancestors::default();
948 let ancestors = if ancestors.contains_key(&max_root) {
949 ancestors
950 } else {
951 &empty
972 };
973
974 match scan_type {
1013 ScanTypes::Unindexed(range) => {
1014 self.do_scan_accounts(
1016 metric_name,
1017 ancestors,
1018 func,
1019 range,
1020 Some(max_root),
1021 collect_all_unsorted,
1022 );
1023 }
1024 ScanTypes::Indexed(IndexKey::ProgramId(program_id)) => {
1025 self.do_scan_secondary_index(
1026 ancestors,
1027 func,
1028 &self.program_id_index,
1029 &program_id,
1030 Some(max_root),
1031 );
1032 }
1033 ScanTypes::Indexed(IndexKey::SplTokenMint(mint_key)) => {
1034 self.do_scan_secondary_index(
1035 ancestors,
1036 func,
1037 &self.spl_token_mint_index,
1038 &mint_key,
1039 Some(max_root),
1040 );
1041 }
1042 ScanTypes::Indexed(IndexKey::SplTokenOwner(owner_key)) => {
1043 self.do_scan_secondary_index(
1044 ancestors,
1045 func,
1046 &self.spl_token_owner_index,
1047 &owner_key,
1048 Some(max_root),
1049 );
1050 }
1051 }
1052
1053 {
1054 let mut ongoing_scan_roots = self.ongoing_scan_roots.write().unwrap();
1055 let count = ongoing_scan_roots.get_mut(&max_root).unwrap();
1056 *count -= 1;
1057 if *count == 0 {
1058 ongoing_scan_roots.remove(&max_root);
1059 }
1060 }
1061
1062 let was_scan_corrupted = self
1065 .removed_bank_ids
1066 .lock()
1067 .unwrap()
1068 .contains(&scan_bank_id);
1069
1070 if was_scan_corrupted {
1071 Err(ScanError::SlotRemoved {
1072 slot: ancestors.max_slot(),
1073 bank_id: scan_bank_id,
1074 })
1075 } else {
1076 Ok(())
1077 }
1078 }
1079
1080 fn do_unchecked_scan_accounts<F, R>(
1081 &self,
1082 metric_name: &'static str,
1083 ancestors: &Ancestors,
1084 func: F,
1085 range: Option<R>,
1086 collect_all_unsorted: bool,
1087 ) where
1088 F: FnMut(&Pubkey, (&T, Slot)),
1089 R: RangeBounds<Pubkey> + std::fmt::Debug,
1090 {
1091 self.do_scan_accounts(
1092 metric_name,
1093 ancestors,
1094 func,
1095 range,
1096 None,
1097 collect_all_unsorted,
1098 );
1099 }
1100
1101 fn do_scan_accounts<F, R>(
1105 &self,
1106 metric_name: &'static str,
1107 ancestors: &Ancestors,
1108 mut func: F,
1109 range: Option<R>,
1110 max_root: Option<Slot>,
1111 collect_all_unsorted: bool,
1112 ) where
1113 F: FnMut(&Pubkey, (&T, Slot)),
1114 R: RangeBounds<Pubkey> + std::fmt::Debug,
1115 {
1116 let mut total_elapsed_timer = Measure::start("total");
1119 let mut num_keys_iterated = 0;
1120 let mut latest_slot_elapsed = 0;
1121 let mut load_account_elapsed = 0;
1122 let mut read_lock_elapsed = 0;
1123 let mut iterator_elapsed = 0;
1124 let mut iterator_timer = Measure::start("iterator_elapsed");
1125 for pubkey_list in self.iter(range.as_ref(), collect_all_unsorted) {
1126 iterator_timer.stop();
1127 iterator_elapsed += iterator_timer.as_us();
1128 for (pubkey, list) in pubkey_list {
1129 num_keys_iterated += 1;
1130 let mut read_lock_timer = Measure::start("read_lock");
1131 let list_r = &list.slot_list.read().unwrap();
1132 read_lock_timer.stop();
1133 read_lock_elapsed += read_lock_timer.as_us();
1134 let mut latest_slot_timer = Measure::start("latest_slot");
1135 if let Some(index) = self.latest_slot(Some(ancestors), list_r, max_root) {
1136 latest_slot_timer.stop();
1137 latest_slot_elapsed += latest_slot_timer.as_us();
1138 let mut load_account_timer = Measure::start("load_account");
1139 func(&pubkey, (&list_r[index].1, list_r[index].0));
1140 load_account_timer.stop();
1141 load_account_elapsed += load_account_timer.as_us();
1142 }
1143 }
1144 iterator_timer = Measure::start("iterator_elapsed");
1145 }
1146
1147 total_elapsed_timer.stop();
1148 if !metric_name.is_empty() {
1149 datapoint_info!(
1150 metric_name,
1151 ("total_elapsed", total_elapsed_timer.as_us(), i64),
1152 ("latest_slot_elapsed", latest_slot_elapsed, i64),
1153 ("read_lock_elapsed", read_lock_elapsed, i64),
1154 ("load_account_elapsed", load_account_elapsed, i64),
1155 ("iterator_elapsed", iterator_elapsed, i64),
1156 ("num_keys_iterated", num_keys_iterated, i64),
1157 )
1158 }
1159 }
1160
1161 fn do_scan_secondary_index<
1162 F,
1163 SecondaryIndexEntryType: SecondaryIndexEntry + Default + Sync + Send,
1164 >(
1165 &self,
1166 ancestors: &Ancestors,
1167 mut func: F,
1168 index: &SecondaryIndex<SecondaryIndexEntryType>,
1169 index_key: &Pubkey,
1170 max_root: Option<Slot>,
1171 ) where
1172 F: FnMut(&Pubkey, (&T, Slot)),
1173 {
1174 for pubkey in index.get(index_key) {
1175 if let AccountIndexGetResult::Found(list_r, index) =
1178 self.get(&pubkey, Some(ancestors), max_root)
1179 {
1180 func(
1181 &pubkey,
1182 (&list_r.slot_list()[index].1, list_r.slot_list()[index].0),
1183 );
1184 }
1185 }
1186 }
1187
1188 pub fn get_account_read_entry(&self, pubkey: &Pubkey) -> Option<ReadAccountMapEntry<T>> {
1189 let lock = self.get_account_maps_read_lock(pubkey);
1190 self.get_account_read_entry_with_lock(pubkey, &lock)
1191 }
1192
1193 pub fn get_account_read_entry_with_lock(
1194 &self,
1195 pubkey: &Pubkey,
1196 lock: &AccountMapsReadLock<'_, T>,
1197 ) -> Option<ReadAccountMapEntry<T>> {
1198 lock.get(pubkey)
1199 .map(ReadAccountMapEntry::from_account_map_entry)
1200 }
1201
1202 fn get_account_write_entry(&self, pubkey: &Pubkey) -> Option<WriteAccountMapEntry<T>> {
1203 self.account_maps[self.bin_calculator.bin_from_pubkey(pubkey)]
1204 .read()
1205 .unwrap()
1206 .get(pubkey)
1207 .map(WriteAccountMapEntry::from_account_map_entry)
1208 }
1209
1210 pub fn handle_dead_keys(
1211 &self,
1212 dead_keys: &[&Pubkey],
1213 account_indexes: &AccountSecondaryIndexes,
1214 ) {
1215 if !dead_keys.is_empty() {
1216 for key in dead_keys.iter() {
1217 let w_index = self.get_account_maps_write_lock(key);
1218 if w_index.remove_if_slot_list_empty(**key) {
1219 self.purge_secondary_indexes_by_inner_key(key, account_indexes);
1223 }
1224 }
1225 }
1226 }
1227
1228 pub(crate) fn scan_accounts<F>(
1230 &self,
1231 ancestors: &Ancestors,
1232 scan_bank_id: BankId,
1233 func: F,
1234 ) -> Result<(), ScanError>
1235 where
1236 F: FnMut(&Pubkey, (&T, Slot)),
1237 {
1238 let collect_all_unsorted = false;
1239 self.do_checked_scan_accounts(
1241 "",
1242 ancestors,
1243 scan_bank_id,
1244 func,
1245 ScanTypes::Unindexed(None::<Range<Pubkey>>),
1246 collect_all_unsorted,
1247 )
1248 }
1249
1250 pub(crate) fn unchecked_scan_accounts<F>(
1251 &self,
1252 metric_name: &'static str,
1253 ancestors: &Ancestors,
1254 func: F,
1255 collect_all_unsorted: bool,
1256 ) where
1257 F: FnMut(&Pubkey, (&T, Slot)),
1258 {
1259 self.do_unchecked_scan_accounts(
1260 metric_name,
1261 ancestors,
1262 func,
1263 None::<Range<Pubkey>>,
1264 collect_all_unsorted,
1265 );
1266 }
1267
1268 pub(crate) fn range_scan_accounts<F, R>(
1270 &self,
1271 metric_name: &'static str,
1272 ancestors: &Ancestors,
1273 range: R,
1274 collect_all_unsorted: bool,
1275 func: F,
1276 ) where
1277 F: FnMut(&Pubkey, (&T, Slot)),
1278 R: RangeBounds<Pubkey> + std::fmt::Debug,
1279 {
1280 self.do_unchecked_scan_accounts(
1282 metric_name,
1283 ancestors,
1284 func,
1285 Some(range),
1286 collect_all_unsorted,
1287 );
1288 }
1289
1290 pub(crate) fn index_scan_accounts<F>(
1292 &self,
1293 ancestors: &Ancestors,
1294 scan_bank_id: BankId,
1295 index_key: IndexKey,
1296 func: F,
1297 ) -> Result<(), ScanError>
1298 where
1299 F: FnMut(&Pubkey, (&T, Slot)),
1300 {
1301 let collect_all_unsorted = false;
1302
1303 self.do_checked_scan_accounts(
1305 "",
1306 ancestors,
1307 scan_bank_id,
1308 func,
1309 ScanTypes::<Range<Pubkey>>::Indexed(index_key),
1310 collect_all_unsorted,
1311 )
1312 }
1313
1314 pub fn get_rooted_entries(&self, slice: SlotSlice<T>, max: Option<Slot>) -> SlotList<T> {
1315 let max = max.unwrap_or(Slot::MAX);
1316 let lock = &self.roots_tracker.read().unwrap().roots;
1317 slice
1318 .iter()
1319 .filter(|(slot, _)| *slot <= max && lock.contains(slot))
1320 .cloned()
1321 .collect()
1322 }
1323
1324 pub fn roots_and_ref_count(
1326 &self,
1327 locked_account_entry: &ReadAccountMapEntry<T>,
1328 max: Option<Slot>,
1329 ) -> (SlotList<T>, RefCount) {
1330 (
1331 self.get_rooted_entries(locked_account_entry.slot_list(), max),
1332 locked_account_entry.ref_count(),
1333 )
1334 }
1335
1336 pub fn purge_exact<'a, C>(
1337 &'a self,
1338 pubkey: &Pubkey,
1339 slots_to_purge: &'a C,
1340 reclaims: &mut SlotList<T>,
1341 ) -> bool
1342 where
1343 C: Contains<'a, Slot>,
1344 {
1345 if let Some(mut write_account_map_entry) = self.get_account_write_entry(pubkey) {
1346 write_account_map_entry.slot_list_mut(|slot_list| {
1347 slot_list.retain(|(slot, item)| {
1348 let should_purge = slots_to_purge.contains(slot);
1349 if should_purge {
1350 reclaims.push((*slot, *item));
1351 false
1352 } else {
1353 true
1354 }
1355 });
1356 slot_list.is_empty()
1357 })
1358 } else {
1359 true
1360 }
1361 }
1362
1363 pub fn min_ongoing_scan_root(&self) -> Option<Slot> {
1364 self.ongoing_scan_roots
1365 .read()
1366 .unwrap()
1367 .keys()
1368 .next()
1369 .cloned()
1370 }
1371
1372 fn latest_slot(
1375 &self,
1376 ancestors: Option<&Ancestors>,
1377 slice: SlotSlice<T>,
1378 max_root: Option<Slot>,
1379 ) -> Option<usize> {
1380 let mut current_max = 0;
1381 let mut rv = None;
1382 if let Some(ancestors) = ancestors {
1383 if !ancestors.is_empty() {
1384 for (i, (slot, _t)) in slice.iter().rev().enumerate() {
1385 if (rv.is_none() || *slot > current_max) && ancestors.contains_key(slot) {
1386 rv = Some(i);
1387 current_max = *slot;
1388 }
1389 }
1390 }
1391 }
1392
1393 let max_root = max_root.unwrap_or(Slot::MAX);
1394 let mut tracker = None;
1395
1396 for (i, (slot, _t)) in slice.iter().rev().enumerate() {
1397 if (rv.is_none() || *slot > current_max) && *slot <= max_root {
1398 let lock = match tracker {
1399 Some(inner) => inner,
1400 None => self.roots_tracker.read().unwrap(),
1401 };
1402 if lock.roots.contains(slot) {
1403 rv = Some(i);
1404 current_max = *slot;
1405 }
1406 tracker = Some(lock);
1407 }
1408 }
1409
1410 rv.map(|index| slice.len() - 1 - index)
1411 }
1412
1413 pub fn hold_range_in_memory<R>(&self, range: &R, start_holding: bool)
1414 where
1415 R: RangeBounds<Pubkey> + Debug,
1416 {
1417 let iter = self.iter(Some(range), true);
1418 iter.hold_range_in_memory(range, start_holding);
1419 }
1420
1421 pub fn set_startup(&self, value: bool) {
1422 self.storage.storage.set_startup(value);
1423 }
1424
1425 pub(crate) fn get(
1428 &self,
1429 pubkey: &Pubkey,
1430 ancestors: Option<&Ancestors>,
1431 max_root: Option<Slot>,
1432 ) -> AccountIndexGetResult<'_, T> {
1433 let read_lock = self.account_maps[self.bin_calculator.bin_from_pubkey(pubkey)]
1434 .read()
1435 .unwrap();
1436 let account = read_lock
1437 .get(pubkey)
1438 .map(ReadAccountMapEntry::from_account_map_entry);
1439
1440 match account {
1441 Some(locked_entry) => {
1442 drop(read_lock);
1443 let slot_list = locked_entry.slot_list();
1444 let found_index = self.latest_slot(ancestors, slot_list, max_root);
1445 match found_index {
1446 Some(found_index) => AccountIndexGetResult::Found(locked_entry, found_index),
1447 None => AccountIndexGetResult::NotFoundOnFork,
1448 }
1449 }
1450 None => AccountIndexGetResult::Missing(read_lock),
1451 }
1452 }
1453
1454 fn get_newest_root_in_slot_list(
1456 roots: &RollingBitField,
1457 slice: SlotSlice<T>,
1458 max_allowed_root: Option<Slot>,
1459 ) -> Slot {
1460 let mut max_root = 0;
1461 for (f, _) in slice.iter() {
1462 if let Some(max_allowed_root) = max_allowed_root {
1463 if *f > max_allowed_root {
1464 continue;
1465 }
1466 }
1467 if *f > max_root && roots.contains(f) {
1468 max_root = *f;
1469 }
1470 }
1471 max_root
1472 }
1473
1474 pub(crate) fn update_secondary_indexes(
1475 &self,
1476 pubkey: &Pubkey,
1477 account_owner: &Pubkey,
1478 account_data: &[u8],
1479 account_indexes: &AccountSecondaryIndexes,
1480 ) {
1481 if account_indexes.is_empty() {
1482 return;
1483 }
1484
1485 if account_indexes.contains(&AccountIndex::ProgramId)
1486 && account_indexes.include_key(account_owner)
1487 {
1488 self.program_id_index.insert(account_owner, pubkey);
1489 }
1490 if *account_owner == inline_spl_token_v2_0::id()
1504 && account_data.len() == inline_spl_token_v2_0::state::Account::get_packed_len()
1505 {
1506 if account_indexes.contains(&AccountIndex::SplTokenOwner) {
1507 let owner_key = Pubkey::new(
1508 &account_data[SPL_TOKEN_ACCOUNT_OWNER_OFFSET
1509 ..SPL_TOKEN_ACCOUNT_OWNER_OFFSET + PUBKEY_BYTES],
1510 );
1511 if account_indexes.include_key(&owner_key) {
1512 self.spl_token_owner_index.insert(&owner_key, pubkey);
1513 }
1514 }
1515
1516 if account_indexes.contains(&AccountIndex::SplTokenMint) {
1517 let mint_key = Pubkey::new(
1518 &account_data[SPL_TOKEN_ACCOUNT_MINT_OFFSET
1519 ..SPL_TOKEN_ACCOUNT_MINT_OFFSET + PUBKEY_BYTES],
1520 );
1521 if account_indexes.include_key(&mint_key) {
1522 self.spl_token_mint_index.insert(&mint_key, pubkey);
1523 }
1524 }
1525 }
1526 }
1527
1528 fn get_account_maps_write_lock(&self, pubkey: &Pubkey) -> AccountMapsWriteLock<T> {
1529 self.account_maps[self.bin_calculator.bin_from_pubkey(pubkey)]
1530 .write()
1531 .unwrap()
1532 }
1533
1534 pub(crate) fn get_account_maps_read_lock(&self, pubkey: &Pubkey) -> AccountMapsReadLock<T> {
1535 self.account_maps[self.bin_calculator.bin_from_pubkey(pubkey)]
1536 .read()
1537 .unwrap()
1538 }
1539
1540 pub fn bins(&self) -> usize {
1541 self.account_maps.len()
1542 }
1543
1544 #[allow(clippy::needless_collect)]
1551 pub(crate) fn insert_new_if_missing_into_primary_index(
1552 &self,
1553 slot: Slot,
1554 item_len: usize,
1555 items: impl Iterator<Item = (Pubkey, T)>,
1556 ) -> (Vec<Pubkey>, u64) {
1557 let bins = self.bins();
1560 let expected_items_per_bin = item_len * 2 / bins;
1561 let random_offset = thread_rng().gen_range(0, bins);
1564 let mut binned = (0..bins)
1565 .into_iter()
1566 .map(|mut pubkey_bin| {
1567 pubkey_bin = if pubkey_bin < random_offset {
1569 pubkey_bin + bins - random_offset
1570 } else {
1571 pubkey_bin - random_offset
1572 };
1573 (pubkey_bin, Vec::with_capacity(expected_items_per_bin))
1574 })
1575 .collect::<Vec<_>>();
1576 let mut dirty_pubkeys = items
1577 .filter_map(|(pubkey, account_info)| {
1578 let pubkey_bin = self.bin_calculator.bin_from_pubkey(&pubkey);
1579 let binned_index = (pubkey_bin + random_offset) % bins;
1580 let is_zero_carat = account_info.is_zero_carat();
1582 let result = if is_zero_carat { Some(pubkey) } else { None };
1583
1584 let info =
1585 PreAllocatedAccountMapEntry::new(slot, account_info, &self.storage.storage);
1586 binned[binned_index].1.push((pubkey, info));
1587 result
1588 })
1589 .collect::<Vec<_>>();
1590 binned.retain(|x| !x.1.is_empty());
1591
1592 let insertion_time = AtomicU64::new(0);
1593
1594 binned.into_iter().for_each(|(pubkey_bin, items)| {
1595 let mut _reclaims = SlotList::new();
1596
1597 let w_account_maps = self.account_maps[pubkey_bin].write().unwrap();
1600 let mut insert_time = Measure::start("insert_into_primary_index");
1601 items.into_iter().for_each(|(pubkey, new_item)| {
1602 let already_exists =
1603 w_account_maps.insert_new_entry_if_missing_with_lock(pubkey, new_item);
1604 if let Some((account_entry, account_info, pubkey)) = already_exists {
1605 let is_zero_carat = account_info.is_zero_carat();
1606 InMemAccountsIndex::lock_and_update_slot_list(
1607 &account_entry,
1608 (slot, account_info),
1609 &mut _reclaims,
1610 false,
1611 );
1612
1613 if !is_zero_carat {
1614 dirty_pubkeys.push(pubkey);
1616 }
1617 }
1618 });
1619 insert_time.stop();
1620 insertion_time.fetch_add(insert_time.as_us(), Ordering::Relaxed);
1621 });
1622
1623 (dirty_pubkeys, insertion_time.load(Ordering::Relaxed))
1624 }
1625
1626 pub fn upsert(
1630 &self,
1631 slot: Slot,
1632 pubkey: &Pubkey,
1633 account_owner: &Pubkey,
1634 account_data: &[u8],
1635 account_indexes: &AccountSecondaryIndexes,
1636 account_info: T,
1637 reclaims: &mut SlotList<T>,
1638 previous_slot_entry_was_cached: bool,
1639 ) {
1640 let new_item = PreAllocatedAccountMapEntry::new(slot, account_info, &self.storage.storage);
1652 let map = &self.account_maps[self.bin_calculator.bin_from_pubkey(pubkey)];
1653
1654 {
1655 let r_account_maps = map.read().unwrap();
1656 r_account_maps.upsert(pubkey, new_item, reclaims, previous_slot_entry_was_cached);
1657 }
1658 self.update_secondary_indexes(pubkey, account_owner, account_data, account_indexes);
1659 }
1660
1661 pub fn unref_from_storage(&self, pubkey: &Pubkey) {
1662 if let Some(locked_entry) = self.get_account_read_entry(pubkey) {
1663 locked_entry.unref();
1664 }
1665 }
1666
1667 pub fn ref_count_from_storage(&self, pubkey: &Pubkey) -> RefCount {
1668 if let Some(locked_entry) = self.get_account_read_entry(pubkey) {
1669 locked_entry.ref_count()
1670 } else {
1671 0
1672 }
1673 }
1674
1675 fn purge_secondary_indexes_by_inner_key<'a>(
1676 &'a self,
1677 inner_key: &Pubkey,
1678 account_indexes: &AccountSecondaryIndexes,
1679 ) {
1680 if account_indexes.contains(&AccountIndex::ProgramId) {
1681 self.program_id_index.remove_by_inner_key(inner_key);
1682 }
1683
1684 if account_indexes.contains(&AccountIndex::SplTokenOwner) {
1685 self.spl_token_owner_index.remove_by_inner_key(inner_key);
1686 }
1687
1688 if account_indexes.contains(&AccountIndex::SplTokenMint) {
1689 self.spl_token_mint_index.remove_by_inner_key(inner_key);
1690 }
1691 }
1692
1693 fn purge_older_root_entries(
1694 &self,
1695 slot_list: &mut SlotList<T>,
1696 reclaims: &mut SlotList<T>,
1697 max_clean_root: Option<Slot>,
1698 ) {
1699 let roots_tracker = &self.roots_tracker.read().unwrap();
1700 let newest_root_in_slot_list =
1701 Self::get_newest_root_in_slot_list(&roots_tracker.roots, slot_list, max_clean_root);
1702 let max_clean_root = max_clean_root.unwrap_or(roots_tracker.max_root);
1703
1704 slot_list.retain(|(slot, value)| {
1705 let should_purge =
1706 Self::can_purge_older_entries(max_clean_root, newest_root_in_slot_list, *slot)
1707 && !value.is_cached();
1708 if should_purge {
1709 reclaims.push((*slot, *value));
1710 }
1711 !should_purge
1712 });
1713 }
1714
1715 pub fn clean_rooted_entries(
1716 &self,
1717 pubkey: &Pubkey,
1718 reclaims: &mut SlotList<T>,
1719 max_clean_root: Option<Slot>,
1720 ) {
1721 let mut is_slot_list_empty = false;
1722 if let Some(mut locked_entry) = self.get_account_write_entry(pubkey) {
1723 locked_entry.slot_list_mut(|slot_list| {
1724 self.purge_older_root_entries(slot_list, reclaims, max_clean_root);
1725 is_slot_list_empty = slot_list.is_empty();
1726 });
1727 }
1728
1729 if is_slot_list_empty {
1734 let w_maps = self.get_account_maps_write_lock(pubkey);
1735 w_maps.remove_if_slot_list_empty(*pubkey);
1736 }
1737 }
1738
1739 fn can_purge_older_entries(
1752 max_clean_root: Slot,
1753 newest_root_in_slot_list: Slot,
1754 slot: Slot,
1755 ) -> bool {
1756 slot < max_clean_root && slot != newest_root_in_slot_list
1757 }
1758
1759 pub fn get_rooted_from_list<'a>(&self, slots: impl Iterator<Item = &'a Slot>) -> Vec<Slot> {
1761 let roots_tracker = self.roots_tracker.read().unwrap();
1762 slots
1763 .filter_map(|s| {
1764 if roots_tracker.roots.contains(s) {
1765 Some(*s)
1766 } else {
1767 None
1768 }
1769 })
1770 .collect()
1771 }
1772
1773 pub fn is_root(&self, slot: Slot) -> bool {
1774 self.roots_tracker.read().unwrap().roots.contains(&slot)
1775 }
1776
1777 pub fn add_root(&self, slot: Slot, caching_enabled: bool) {
1778 let mut w_roots_tracker = self.roots_tracker.write().unwrap();
1779 w_roots_tracker.roots.insert(slot);
1780 if !caching_enabled {
1782 w_roots_tracker.uncleaned_roots.insert(slot);
1783 }
1784 assert!(slot >= w_roots_tracker.max_root);
1786 w_roots_tracker.max_root = slot;
1787 }
1788
1789 pub fn add_uncleaned_roots<I>(&self, roots: I)
1790 where
1791 I: IntoIterator<Item = Slot>,
1792 {
1793 let mut w_roots_tracker = self.roots_tracker.write().unwrap();
1794 w_roots_tracker.uncleaned_roots.extend(roots);
1795 }
1796
1797 pub fn max_root(&self) -> Slot {
1798 self.roots_tracker.read().unwrap().max_root
1799 }
1800
1801 pub fn clean_dead_slot(&self, slot: Slot) -> Option<AccountsIndexRootsStats> {
1804 let (roots_len, uncleaned_roots_len, previous_uncleaned_roots_len, roots_range) = {
1805 let mut w_roots_tracker = self.roots_tracker.write().unwrap();
1806 let removed_from_unclean_roots = w_roots_tracker.uncleaned_roots.remove(&slot);
1807 let removed_from_previous_uncleaned_roots =
1808 w_roots_tracker.previous_uncleaned_roots.remove(&slot);
1809 if !w_roots_tracker.roots.remove(&slot) {
1810 if removed_from_unclean_roots {
1811 error!("clean_dead_slot-removed_from_unclean_roots: {}", slot);
1812 inc_new_counter_error!("clean_dead_slot-removed_from_unclean_roots", 1, 1);
1813 }
1814 if removed_from_previous_uncleaned_roots {
1815 error!(
1816 "clean_dead_slot-removed_from_previous_uncleaned_roots: {}",
1817 slot
1818 );
1819 inc_new_counter_error!(
1820 "clean_dead_slot-removed_from_previous_uncleaned_roots",
1821 1,
1822 1
1823 );
1824 }
1825 return None;
1826 }
1827 (
1828 w_roots_tracker.roots.len(),
1829 w_roots_tracker.uncleaned_roots.len(),
1830 w_roots_tracker.previous_uncleaned_roots.len(),
1831 w_roots_tracker.roots.range_width(),
1832 )
1833 };
1834 Some(AccountsIndexRootsStats {
1835 roots_len,
1836 uncleaned_roots_len,
1837 previous_uncleaned_roots_len,
1838 roots_range,
1839 rooted_cleaned_count: 0,
1840 unrooted_cleaned_count: 0,
1841 })
1842 }
1843
1844 pub fn min_root(&self) -> Option<Slot> {
1845 self.roots_tracker.read().unwrap().min_root()
1846 }
1847
1848 pub fn reset_uncleaned_roots(&self, max_clean_root: Option<Slot>) -> HashSet<Slot> {
1849 let mut cleaned_roots = HashSet::new();
1850 let mut w_roots_tracker = self.roots_tracker.write().unwrap();
1851 w_roots_tracker.uncleaned_roots.retain(|root| {
1852 let is_cleaned = max_clean_root
1853 .map(|max_clean_root| *root <= max_clean_root)
1854 .unwrap_or(true);
1855 if is_cleaned {
1856 cleaned_roots.insert(*root);
1857 }
1858 !is_cleaned
1860 });
1861 std::mem::replace(&mut w_roots_tracker.previous_uncleaned_roots, cleaned_roots)
1862 }
1863
1864 #[cfg(test)]
1865 pub fn clear_uncleaned_roots(&self, max_clean_root: Option<Slot>) -> HashSet<Slot> {
1866 let mut cleaned_roots = HashSet::new();
1867 let mut w_roots_tracker = self.roots_tracker.write().unwrap();
1868 w_roots_tracker.uncleaned_roots.retain(|root| {
1869 let is_cleaned = max_clean_root
1870 .map(|max_clean_root| *root <= max_clean_root)
1871 .unwrap_or(true);
1872 if is_cleaned {
1873 cleaned_roots.insert(*root);
1874 }
1875 !is_cleaned
1877 });
1878 cleaned_roots
1879 }
1880
1881 pub fn is_uncleaned_root(&self, slot: Slot) -> bool {
1882 self.roots_tracker
1883 .read()
1884 .unwrap()
1885 .uncleaned_roots
1886 .contains(&slot)
1887 }
1888
1889 pub fn num_roots(&self) -> usize {
1890 self.roots_tracker.read().unwrap().roots.len()
1891 }
1892
1893 pub fn all_roots(&self) -> Vec<Slot> {
1894 let tracker = self.roots_tracker.read().unwrap();
1895 tracker.roots.get_all()
1896 }
1897
1898 #[cfg(test)]
1899 pub fn clear_roots(&self) {
1900 self.roots_tracker.write().unwrap().roots.clear()
1901 }
1902
1903 #[cfg(test)]
1904 pub fn uncleaned_roots_len(&self) -> usize {
1905 self.roots_tracker.read().unwrap().uncleaned_roots.len()
1906 }
1907
1908 #[cfg(test)]
1909 pub fn purge_roots(&self, pubkey: &Pubkey) -> (SlotList<T>, bool) {
1913 let mut write_account_map_entry = self.get_account_write_entry(pubkey).unwrap();
1914 write_account_map_entry.slot_list_mut(|slot_list| {
1915 let reclaims = self.get_rooted_entries(slot_list, None);
1916 slot_list.retain(|(slot, _)| !self.is_root(*slot));
1917 (reclaims, slot_list.is_empty())
1918 })
1919 }
1920}
1921
1922#[cfg(test)]
1923pub mod tests {
1924 use super::*;
1925 use gemachain_sdk::signature::{Keypair, Signer};
1926 use std::ops::RangeInclusive;
1927
1928 pub enum SecondaryIndexTypes<'a> {
1929 RwLock(&'a SecondaryIndex<RwLockSecondaryIndexEntry>),
1930 DashMap(&'a SecondaryIndex<DashMapSecondaryIndexEntry>),
1931 }
1932
1933 pub fn spl_token_mint_index_enabled() -> AccountSecondaryIndexes {
1934 let mut account_indexes = HashSet::new();
1935 account_indexes.insert(AccountIndex::SplTokenMint);
1936 AccountSecondaryIndexes {
1937 indexes: account_indexes,
1938 keys: None,
1939 }
1940 }
1941
1942 pub fn spl_token_owner_index_enabled() -> AccountSecondaryIndexes {
1943 let mut account_indexes = HashSet::new();
1944 account_indexes.insert(AccountIndex::SplTokenOwner);
1945 AccountSecondaryIndexes {
1946 indexes: account_indexes,
1947 keys: None,
1948 }
1949 }
1950
1951 impl<'a, T: IndexValue> AccountIndexGetResult<'a, T> {
1952 pub fn unwrap(self) -> (ReadAccountMapEntry<T>, usize) {
1953 match self {
1954 AccountIndexGetResult::Found(lock, size) => (lock, size),
1955 _ => {
1956 panic!("trying to unwrap AccountIndexGetResult with non-Success result");
1957 }
1958 }
1959 }
1960
1961 pub fn is_none(&self) -> bool {
1962 !self.is_some()
1963 }
1964
1965 pub fn is_some(&self) -> bool {
1966 matches!(self, AccountIndexGetResult::Found(_lock, _size))
1967 }
1968
1969 pub fn map<V, F: FnOnce((ReadAccountMapEntry<T>, usize)) -> V>(self, f: F) -> Option<V> {
1970 match self {
1971 AccountIndexGetResult::Found(lock, size) => Some(f((lock, size))),
1972 _ => None,
1973 }
1974 }
1975 }
1976
1977 fn create_dashmap_secondary_index_state() -> (usize, usize, AccountSecondaryIndexes) {
1978 {
1979 let index = AccountsIndex::<bool>::default_for_tests();
1981 let _type_check = SecondaryIndexTypes::DashMap(&index.spl_token_mint_index);
1982 }
1983
1984 (0, PUBKEY_BYTES, spl_token_mint_index_enabled())
1985 }
1986
1987 fn create_rwlock_secondary_index_state() -> (usize, usize, AccountSecondaryIndexes) {
1988 {
1989 let index = AccountsIndex::<bool>::default_for_tests();
1991 let _type_check = SecondaryIndexTypes::RwLock(&index.spl_token_owner_index);
1992 }
1993
1994 (
1995 SPL_TOKEN_ACCOUNT_OWNER_OFFSET,
1996 SPL_TOKEN_ACCOUNT_OWNER_OFFSET + PUBKEY_BYTES,
1997 spl_token_owner_index_enabled(),
1998 )
1999 }
2000
2001 impl<T: IndexValue> Clone for PreAllocatedAccountMapEntry<T> {
2002 fn clone(&self) -> Self {
2003 let (slot, info) = self.entry.slot_list.read().unwrap()[0];
2005 let meta = AccountMapEntryMeta {
2006 dirty: AtomicBool::new(self.entry.dirty()),
2007 age: AtomicU8::new(self.entry.age()),
2008 };
2009 PreAllocatedAccountMapEntry::new_internal(slot, info, meta)
2010 }
2011 }
2012
2013 #[test]
2014 fn test_bitfield_delete_non_excess() {
2015 gemachain_logger::setup();
2016 let len = 16;
2017 let mut bitfield = RollingBitField::new(len);
2018 assert_eq!(bitfield.min(), None);
2019
2020 bitfield.insert(0);
2021 assert_eq!(bitfield.min(), Some(0));
2022 let too_big = len + 1;
2023 bitfield.insert(too_big);
2024 assert!(bitfield.contains(&0));
2025 assert!(bitfield.contains(&too_big));
2026 assert_eq!(bitfield.len(), 2);
2027 assert_eq!(bitfield.excess.len(), 1);
2028 assert_eq!(bitfield.min, too_big);
2029 assert_eq!(bitfield.min(), Some(0));
2030 assert_eq!(bitfield.max, too_big + 1);
2031
2032 bitfield.remove(&too_big);
2034 assert_eq!(bitfield.min, too_big + 1);
2035 assert_eq!(bitfield.max, too_big + 1);
2036 let too_big_times_2 = too_big * 2;
2037 bitfield.insert(too_big_times_2);
2038 assert!(bitfield.contains(&0));
2039 assert!(bitfield.contains(&too_big_times_2));
2040 assert_eq!(bitfield.len(), 2);
2041 assert_eq!(bitfield.excess.len(), 1);
2042 assert_eq!(bitfield.min(), bitfield.excess.iter().min().copied());
2043 assert_eq!(bitfield.min, too_big_times_2);
2044 assert_eq!(bitfield.max, too_big_times_2 + 1);
2045
2046 bitfield.remove(&0);
2047 bitfield.remove(&too_big_times_2);
2048 assert!(bitfield.is_empty());
2049 let other = 5;
2050 bitfield.insert(other);
2051 assert!(bitfield.contains(&other));
2052 assert!(bitfield.excess.is_empty());
2053 assert_eq!(bitfield.min, other);
2054 assert_eq!(bitfield.max, other + 1);
2055 }
2056
2057 #[test]
2058 fn test_bitfield_insert_excess() {
2059 gemachain_logger::setup();
2060 let len = 16;
2061 let mut bitfield = RollingBitField::new(len);
2062
2063 bitfield.insert(0);
2064 let too_big = len + 1;
2065 bitfield.insert(too_big);
2066 assert!(bitfield.contains(&0));
2067 assert!(bitfield.contains(&too_big));
2068 assert_eq!(bitfield.len(), 2);
2069 assert_eq!(bitfield.excess.len(), 1);
2070 assert!(bitfield.excess.contains(&0));
2071 assert_eq!(bitfield.min, too_big);
2072 assert_eq!(bitfield.max, too_big + 1);
2073
2074 bitfield.remove(&0);
2077 assert_eq!(bitfield.min, too_big);
2078 assert_eq!(bitfield.max, too_big + 1);
2079 bitfield.insert(0);
2081 assert!(bitfield.contains(&0));
2082 assert!(bitfield.contains(&too_big));
2083 assert_eq!(bitfield.len(), 2);
2084 assert_eq!(bitfield.excess.len(), 1);
2085 assert_eq!(bitfield.min, too_big);
2086 assert_eq!(bitfield.max, too_big + 1);
2087 }
2088
2089 #[test]
2090 fn test_bitfield_permutations() {
2091 gemachain_logger::setup();
2092 let mut bitfield = RollingBitField::new(2097152);
2093 let mut hash = HashSet::new();
2094
2095 let min = 101_000;
2096 let width = 400_000;
2097 let dead = 19;
2098
2099 let mut slot = min;
2100 while hash.len() < width {
2101 slot += 1;
2102 if slot % dead == 0 {
2103 continue;
2104 }
2105 hash.insert(slot);
2106 bitfield.insert(slot);
2107 }
2108 compare(&hash, &bitfield);
2109
2110 let max = slot + 1;
2111
2112 let mut time = Measure::start("");
2113 let mut count = 0;
2114 for slot in (min - 10)..max + 100 {
2115 if hash.contains(&slot) {
2116 count += 1;
2117 }
2118 }
2119 time.stop();
2120
2121 let mut time2 = Measure::start("");
2122 let mut count2 = 0;
2123 for slot in (min - 10)..max + 100 {
2124 if bitfield.contains(&slot) {
2125 count2 += 1;
2126 }
2127 }
2128 time2.stop();
2129 info!(
2130 "{}ms, {}ms, {} ratio",
2131 time.as_ms(),
2132 time2.as_ms(),
2133 time.as_ns() / time2.as_ns()
2134 );
2135 assert_eq!(count, count2);
2136 }
2137
2138 #[test]
2139 #[should_panic(expected = "assertion failed: max_width.is_power_of_two()")]
2140 fn test_bitfield_power_2() {
2141 let _ = RollingBitField::new(3);
2142 }
2143
2144 #[test]
2145 #[should_panic(expected = "assertion failed: max_width > 0")]
2146 fn test_bitfield_0() {
2147 let _ = RollingBitField::new(0);
2148 }
2149
2150 fn setup_empty(width: u64) -> RollingBitFieldTester {
2151 let bitfield = RollingBitField::new(width);
2152 let hash_set = HashSet::new();
2153 RollingBitFieldTester { bitfield, hash_set }
2154 }
2155
2156 struct RollingBitFieldTester {
2157 pub bitfield: RollingBitField,
2158 pub hash_set: HashSet<u64>,
2159 }
2160
2161 impl RollingBitFieldTester {
2162 fn insert(&mut self, slot: u64) {
2163 self.bitfield.insert(slot);
2164 self.hash_set.insert(slot);
2165 assert!(self.bitfield.contains(&slot));
2166 compare(&self.hash_set, &self.bitfield);
2167 }
2168 fn remove(&mut self, slot: &u64) -> bool {
2169 let result = self.bitfield.remove(slot);
2170 assert_eq!(result, self.hash_set.remove(slot));
2171 assert!(!self.bitfield.contains(slot));
2172 self.compare();
2173 result
2174 }
2175 fn compare(&self) {
2176 compare(&self.hash_set, &self.bitfield);
2177 }
2178 }
2179
2180 fn setup_wide(width: u64, start: u64) -> RollingBitFieldTester {
2181 let mut tester = setup_empty(width);
2182
2183 tester.compare();
2184 tester.insert(start);
2185 tester.insert(start + 1);
2186 tester
2187 }
2188
2189 #[test]
2190 fn test_bitfield_insert_wide() {
2191 gemachain_logger::setup();
2192 let width = 16;
2193 let start = 0;
2194 let mut tester = setup_wide(width, start);
2195
2196 let slot = start + width;
2197 let all = tester.bitfield.get_all();
2198 tester.insert(slot);
2200 let bitfield = tester.bitfield;
2201 for slot in all {
2202 assert!(bitfield.contains(&slot));
2203 }
2204 assert_eq!(bitfield.excess.len(), 1);
2205 assert_eq!(bitfield.count, 3);
2206 }
2207
2208 #[test]
2209 fn test_bitfield_insert_wide_before() {
2210 gemachain_logger::setup();
2211 let width = 16;
2212 let start = 100;
2213 let mut bitfield = setup_wide(width, start).bitfield;
2214
2215 let slot = start + 1 - width;
2216 bitfield.insert(slot);
2218 assert_eq!(1, bitfield.excess.len());
2219 assert_eq!(3, bitfield.count);
2220 assert!(bitfield.contains(&slot));
2221 }
2222
2223 #[test]
2224 fn test_bitfield_insert_wide_before_ok() {
2225 gemachain_logger::setup();
2226 let width = 16;
2227 let start = 100;
2228 let mut bitfield = setup_wide(width, start).bitfield;
2229
2230 let slot = start + 2 - width; bitfield.insert(slot);
2232 assert_eq!(1, bitfield.excess.len());
2233 assert!(bitfield.contains(&slot));
2234 assert_eq!(3, bitfield.count);
2235 }
2236
2237 #[test]
2238 fn test_bitfield_contains_wide_no_assert() {
2239 {
2240 let width = 16;
2241 let start = 0;
2242 let bitfield = setup_wide(width, start).bitfield;
2243
2244 let mut slot = width;
2245 assert!(!bitfield.contains(&slot));
2246 slot += 1;
2247 assert!(!bitfield.contains(&slot));
2248 }
2249 {
2250 let width = 16;
2251 let start = 100;
2252 let bitfield = setup_wide(width, start).bitfield;
2253
2254 let mut slot = width;
2256 assert!(!bitfield.contains(&slot));
2257 slot += 1;
2258 assert!(!bitfield.contains(&slot));
2259 slot = 0;
2261 assert!(!bitfield.contains(&slot));
2262 }
2263 }
2264
2265 #[test]
2266 fn test_bitfield_remove_wide() {
2267 let width = 16;
2268 let start = 0;
2269 let mut tester = setup_wide(width, start);
2270 let slot = width;
2271 assert!(!tester.remove(&slot));
2272 }
2273
2274 #[test]
2275 fn test_bitfield_excess2() {
2276 gemachain_logger::setup();
2277 let width = 16;
2278 let mut tester = setup_empty(width);
2279 let slot = 100;
2280 tester.insert(slot);
2282 assert!(tester.bitfield.excess.is_empty());
2283
2284 let slot2 = slot - 1;
2286 tester.insert(slot2);
2287 assert_eq!(tester.bitfield.excess.len(), 1);
2288
2289 tester.remove(&slot);
2291 assert!(tester.bitfield.contains(&slot2));
2292 assert_eq!(tester.bitfield.excess.len(), 1);
2293
2294 tester.insert(slot);
2296 assert_eq!(tester.bitfield.excess.len(), 1);
2297
2298 tester.remove(&slot2);
2300 assert!(tester.bitfield.contains(&slot));
2301 assert!(tester.bitfield.excess.is_empty());
2302
2303 tester.insert(slot2);
2305 assert_eq!(tester.bitfield.excess.len(), 1);
2306 }
2307
2308 #[test]
2309 fn test_bitfield_excess() {
2310 gemachain_logger::setup();
2311 for width in [16, 4194304].iter() {
2313 let width = *width;
2314 let mut tester = setup_empty(width);
2315 for start in [0, width * 5].iter().cloned() {
2316 for recreate in [false, true].iter().cloned() {
2318 let max = start + 3;
2319 for slot in start..max {
2321 for slot2 in (slot + 1)..max {
2323 for reverse_slots in [false, true].iter().cloned() {
2325 let maybe_reverse = |slot| {
2326 if reverse_slots {
2327 max - slot
2328 } else {
2329 slot
2330 }
2331 };
2332 if recreate {
2333 let recreated = setup_empty(width);
2334 tester = recreated;
2335 }
2336
2337 for slot in slot..=slot2 {
2339 let slot_use = maybe_reverse(slot);
2340 tester.insert(slot_use);
2341 debug!(
2342 "slot: {}, bitfield: {:?}, reverse: {}, len: {}, excess: {:?}",
2343 slot_use,
2344 tester.bitfield,
2345 reverse_slots,
2346 tester.bitfield.len(),
2347 tester.bitfield.excess
2348 );
2349 assert!(
2350 (reverse_slots && tester.bitfield.len() > 1)
2351 ^ tester.bitfield.excess.is_empty()
2352 );
2353 }
2354 if start > width * 2 {
2355 assert!(!tester.bitfield.contains(&(start - width * 2)));
2356 }
2357 assert!(!tester.bitfield.contains(&(start + width * 2)));
2358 let len = (slot2 - slot + 1) as usize;
2359 assert_eq!(tester.bitfield.len(), len);
2360 assert_eq!(tester.bitfield.count, len);
2361
2362 for slot in slot..=slot2 {
2364 let slot_use = maybe_reverse(slot);
2365 assert!(tester.remove(&slot_use));
2366 assert!(
2367 (reverse_slots && !tester.bitfield.is_empty())
2368 ^ tester.bitfield.excess.is_empty()
2369 );
2370 }
2371 assert!(tester.bitfield.is_empty());
2372 assert_eq!(tester.bitfield.count, 0);
2373 if start > width * 2 {
2374 assert!(!tester.bitfield.contains(&(start - width * 2)));
2375 }
2376 assert!(!tester.bitfield.contains(&(start + width * 2)));
2377 }
2378 }
2379 }
2380 }
2381 }
2382 }
2383 }
2384
2385 #[test]
2386 fn test_bitfield_remove_wide_before() {
2387 let width = 16;
2388 let start = 100;
2389 let mut tester = setup_wide(width, start);
2390 let slot = start + 1 - width;
2391 assert!(!tester.remove(&slot));
2392 }
2393
2394 fn compare_internal(hashset: &HashSet<u64>, bitfield: &RollingBitField) {
2395 assert_eq!(hashset.len(), bitfield.len());
2396 assert_eq!(hashset.is_empty(), bitfield.is_empty());
2397 if !bitfield.is_empty() {
2398 let mut min = Slot::MAX;
2399 let mut overall_min = Slot::MAX;
2400 let mut max = Slot::MIN;
2401 for item in bitfield.get_all() {
2402 assert!(hashset.contains(&item));
2403 if !bitfield.excess.contains(&item) {
2404 min = std::cmp::min(min, item);
2405 max = std::cmp::max(max, item);
2406 }
2407 overall_min = std::cmp::min(overall_min, item);
2408 }
2409 assert_eq!(bitfield.min(), Some(overall_min));
2410 assert_eq!(bitfield.get_all().len(), hashset.len());
2411 if bitfield.excess.len() != bitfield.len() {
2413 let width = if bitfield.is_empty() {
2414 0
2415 } else {
2416 max + 1 - min
2417 };
2418 assert!(
2419 bitfield.range_width() >= width,
2420 "hashset: {:?}, bitfield: {:?}, bitfield.range_width: {}, width: {}",
2421 hashset,
2422 bitfield.get_all(),
2423 bitfield.range_width(),
2424 width,
2425 );
2426 }
2427 } else {
2428 assert_eq!(bitfield.min(), None);
2429 }
2430 }
2431
2432 fn compare(hashset: &HashSet<u64>, bitfield: &RollingBitField) {
2433 compare_internal(hashset, bitfield);
2434 let clone = bitfield.clone();
2435 compare_internal(hashset, &clone);
2436 assert!(clone.eq(bitfield));
2437 assert_eq!(clone, *bitfield);
2438 }
2439
2440 #[test]
2441 fn test_bitfield_functionality() {
2442 gemachain_logger::setup();
2443
2444 for power in 0..10 {
2446 let max_bitfield_width = 2u64.pow(power) as u64;
2447 let width_iteration_max = if max_bitfield_width > 1 {
2448 3
2450 } else {
2451 2
2453 };
2454 for width in 0..width_iteration_max {
2455 let mut tester = setup_empty(max_bitfield_width);
2456
2457 let min = 101_000;
2458 let dead = 19;
2459
2460 let mut slot = min;
2461 while tester.hash_set.len() < width {
2462 slot += 1;
2463 if max_bitfield_width > 2 && slot % dead == 0 {
2464 continue;
2466 }
2467 tester.insert(slot);
2468 }
2469 let max = slot + 1;
2470
2471 for slot in (min - 10)..max + 100 {
2472 assert_eq!(
2473 tester.bitfield.contains(&slot),
2474 tester.hash_set.contains(&slot)
2475 );
2476 }
2477
2478 if width > 0 {
2479 assert!(tester.remove(&slot));
2480 assert!(!tester.remove(&slot));
2481 }
2482
2483 let all = tester.bitfield.get_all();
2484
2485 for item in all.iter() {
2487 assert!(tester.remove(item));
2488 assert!(!tester.remove(item));
2489 }
2490
2491 let min = max + ((width * 2) as u64) + 3;
2492 let slot = min; let max = slot + 1;
2494 tester.insert(slot);
2495
2496 for slot in (min - 10)..max + 100 {
2497 assert_eq!(
2498 tester.bitfield.contains(&slot),
2499 tester.hash_set.contains(&slot)
2500 );
2501 }
2502 }
2503 }
2504 }
2505
2506 fn bitfield_insert_and_test(bitfield: &mut RollingBitField, slot: Slot) {
2507 let len = bitfield.len();
2508 let old_all = bitfield.get_all();
2509 let (new_min, new_max) = if bitfield.is_empty() {
2510 (slot, slot + 1)
2511 } else {
2512 (
2513 std::cmp::min(bitfield.min, slot),
2514 std::cmp::max(bitfield.max, slot + 1),
2515 )
2516 };
2517 bitfield.insert(slot);
2518 assert_eq!(bitfield.min, new_min);
2519 assert_eq!(bitfield.max, new_max);
2520 assert_eq!(bitfield.len(), len + 1);
2521 assert!(!bitfield.is_empty());
2522 assert!(bitfield.contains(&slot));
2523 assert!(bitfield.contains_assume_in_range(&(slot + bitfield.max_width)));
2525 let get_all = bitfield.get_all();
2526 old_all
2527 .into_iter()
2528 .for_each(|slot| assert!(get_all.contains(&slot)));
2529 assert!(get_all.contains(&slot));
2530 assert!(get_all.len() == len + 1);
2531 }
2532
2533 #[test]
2534 fn test_bitfield_clear() {
2535 let mut bitfield = RollingBitField::new(4);
2536 assert_eq!(bitfield.len(), 0);
2537 assert!(bitfield.is_empty());
2538 bitfield_insert_and_test(&mut bitfield, 0);
2539 bitfield.clear();
2540 assert_eq!(bitfield.len(), 0);
2541 assert!(bitfield.is_empty());
2542 assert!(bitfield.get_all().is_empty());
2543 bitfield_insert_and_test(&mut bitfield, 1);
2544 bitfield.clear();
2545 assert_eq!(bitfield.len(), 0);
2546 assert!(bitfield.is_empty());
2547 assert!(bitfield.get_all().is_empty());
2548 bitfield_insert_and_test(&mut bitfield, 4);
2549 }
2550
2551 #[test]
2552 fn test_bitfield_wrapping() {
2553 let mut bitfield = RollingBitField::new(4);
2554 assert_eq!(bitfield.len(), 0);
2555 assert!(bitfield.is_empty());
2556 bitfield_insert_and_test(&mut bitfield, 0);
2557 assert_eq!(bitfield.get_all(), vec![0]);
2558 bitfield_insert_and_test(&mut bitfield, 2);
2559 assert_eq!(bitfield.get_all(), vec![0, 2]);
2560 bitfield_insert_and_test(&mut bitfield, 3);
2561 bitfield.insert(3); assert_eq!(bitfield.get_all(), vec![0, 2, 3]);
2563 assert!(bitfield.remove(&0));
2564 assert!(!bitfield.remove(&0));
2565 assert_eq!(bitfield.min, 2);
2566 assert_eq!(bitfield.max, 4);
2567 assert_eq!(bitfield.len(), 2);
2568 assert!(!bitfield.remove(&0)); assert_eq!(bitfield.len(), 2);
2570 assert_eq!(bitfield.get_all(), vec![2, 3]);
2571 bitfield.insert(4); assert_eq!(bitfield.min, 2);
2573 assert_eq!(bitfield.max, 5);
2574 assert_eq!(bitfield.len(), 3);
2575 assert_eq!(bitfield.get_all(), vec![2, 3, 4]);
2576 assert!(bitfield.remove(&2));
2577 assert_eq!(bitfield.min, 3);
2578 assert_eq!(bitfield.max, 5);
2579 assert_eq!(bitfield.len(), 2);
2580 assert_eq!(bitfield.get_all(), vec![3, 4]);
2581 assert!(bitfield.remove(&3));
2582 assert_eq!(bitfield.min, 4);
2583 assert_eq!(bitfield.max, 5);
2584 assert_eq!(bitfield.len(), 1);
2585 assert_eq!(bitfield.get_all(), vec![4]);
2586 assert!(bitfield.remove(&4));
2587 assert_eq!(bitfield.len(), 0);
2588 assert!(bitfield.is_empty());
2589 assert!(bitfield.get_all().is_empty());
2590 bitfield_insert_and_test(&mut bitfield, 8);
2591 assert!(bitfield.remove(&8));
2592 assert_eq!(bitfield.len(), 0);
2593 assert!(bitfield.is_empty());
2594 assert!(bitfield.get_all().is_empty());
2595 bitfield_insert_and_test(&mut bitfield, 9);
2596 assert!(bitfield.remove(&9));
2597 assert_eq!(bitfield.len(), 0);
2598 assert!(bitfield.is_empty());
2599 assert!(bitfield.get_all().is_empty());
2600 }
2601
2602 #[test]
2603 fn test_bitfield_smaller() {
2604 gemachain_logger::setup();
2606
2607 for width in 0..34 {
2608 let mut bitfield = RollingBitField::new(4096);
2609 let mut hash_set = HashSet::new();
2610
2611 let min = 1_010_000;
2612 let dead = 19;
2613
2614 let mut slot = min;
2615 while hash_set.len() < width {
2616 slot += 1;
2617 if slot % dead == 0 {
2618 continue;
2619 }
2620 hash_set.insert(slot);
2621 bitfield.insert(slot);
2622 }
2623
2624 let max = slot + 1;
2625
2626 let mut time = Measure::start("");
2627 let mut count = 0;
2628 for slot in (min - 10)..max + 100 {
2629 if hash_set.contains(&slot) {
2630 count += 1;
2631 }
2632 }
2633 time.stop();
2634
2635 let mut time2 = Measure::start("");
2636 let mut count2 = 0;
2637 for slot in (min - 10)..max + 100 {
2638 if bitfield.contains(&slot) {
2639 count2 += 1;
2640 }
2641 }
2642 time2.stop();
2643 info!(
2644 "{}, {}, {}",
2645 time.as_ms(),
2646 time2.as_ms(),
2647 time.as_ns() / time2.as_ns()
2648 );
2649 assert_eq!(count, count2);
2650 }
2651 }
2652
2653 const COLLECT_ALL_UNSORTED_FALSE: bool = false;
2654
2655 #[test]
2656 fn test_get_empty() {
2657 let key = Keypair::new();
2658 let index = AccountsIndex::<bool>::default_for_tests();
2659 let ancestors = Ancestors::default();
2660 assert!(index.get(&key.pubkey(), Some(&ancestors), None).is_none());
2661 assert!(index.get(&key.pubkey(), None, None).is_none());
2662
2663 let mut num = 0;
2664 index.unchecked_scan_accounts(
2665 "",
2666 &ancestors,
2667 |_pubkey, _index| num += 1,
2668 COLLECT_ALL_UNSORTED_FALSE,
2669 );
2670 assert_eq!(num, 0);
2671 }
2672
2673 #[test]
2674 fn test_secondary_index_include_exclude() {
2675 let pk1 = Pubkey::new_unique();
2676 let pk2 = Pubkey::new_unique();
2677 let mut index = AccountSecondaryIndexes::default();
2678
2679 assert!(!index.contains(&AccountIndex::ProgramId));
2680 index.indexes.insert(AccountIndex::ProgramId);
2681 assert!(index.contains(&AccountIndex::ProgramId));
2682 assert!(index.include_key(&pk1));
2683 assert!(index.include_key(&pk2));
2684
2685 let exclude = false;
2686 index.keys = Some(AccountSecondaryIndexesIncludeExclude {
2687 keys: [pk1].iter().cloned().collect::<HashSet<_>>(),
2688 exclude,
2689 });
2690 assert!(index.include_key(&pk1));
2691 assert!(!index.include_key(&pk2));
2692
2693 let exclude = true;
2694 index.keys = Some(AccountSecondaryIndexesIncludeExclude {
2695 keys: [pk1].iter().cloned().collect::<HashSet<_>>(),
2696 exclude,
2697 });
2698 assert!(!index.include_key(&pk1));
2699 assert!(index.include_key(&pk2));
2700
2701 let exclude = true;
2702 index.keys = Some(AccountSecondaryIndexesIncludeExclude {
2703 keys: [pk1, pk2].iter().cloned().collect::<HashSet<_>>(),
2704 exclude,
2705 });
2706 assert!(!index.include_key(&pk1));
2707 assert!(!index.include_key(&pk2));
2708
2709 let exclude = false;
2710 index.keys = Some(AccountSecondaryIndexesIncludeExclude {
2711 keys: [pk1, pk2].iter().cloned().collect::<HashSet<_>>(),
2712 exclude,
2713 });
2714 assert!(index.include_key(&pk1));
2715 assert!(index.include_key(&pk2));
2716 }
2717
2718 const UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE: bool = false;
2719
2720 #[test]
2721 fn test_insert_no_ancestors() {
2722 let key = Keypair::new();
2723 let index = AccountsIndex::<bool>::default_for_tests();
2724 let mut gc = Vec::new();
2725 index.upsert(
2726 0,
2727 &key.pubkey(),
2728 &Pubkey::default(),
2729 &[],
2730 &AccountSecondaryIndexes::default(),
2731 true,
2732 &mut gc,
2733 UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE,
2734 );
2735 assert!(gc.is_empty());
2736
2737 let ancestors = Ancestors::default();
2738 assert!(index.get(&key.pubkey(), Some(&ancestors), None).is_none());
2739 assert!(index.get(&key.pubkey(), None, None).is_none());
2740
2741 let mut num = 0;
2742 index.unchecked_scan_accounts(
2743 "",
2744 &ancestors,
2745 |_pubkey, _index| num += 1,
2746 COLLECT_ALL_UNSORTED_FALSE,
2747 );
2748 assert_eq!(num, 0);
2749 }
2750
2751 type AccountInfoTest = f64;
2752
2753 impl IndexValue for AccountInfoTest {}
2754 impl IsCached for AccountInfoTest {
2755 fn is_cached(&self) -> bool {
2756 true
2757 }
2758 }
2759
2760 impl ZeroCarat for AccountInfoTest {
2761 fn is_zero_carat(&self) -> bool {
2762 true
2763 }
2764 }
2765 #[test]
2766 fn test_insert_new_with_lock_no_ancestors() {
2767 let key = Keypair::new();
2768 let pubkey = &key.pubkey();
2769 let slot = 0;
2770
2771 let index = AccountsIndex::<bool>::default_for_tests();
2772 let account_info = true;
2773 let items = vec![(*pubkey, account_info)];
2774 index.insert_new_if_missing_into_primary_index(slot, items.len(), items.into_iter());
2775
2776 let mut ancestors = Ancestors::default();
2777 assert!(index.get(pubkey, Some(&ancestors), None).is_none());
2778 assert!(index.get(pubkey, None, None).is_none());
2779
2780 let mut num = 0;
2781 index.unchecked_scan_accounts(
2782 "",
2783 &ancestors,
2784 |_pubkey, _index| num += 1,
2785 COLLECT_ALL_UNSORTED_FALSE,
2786 );
2787 assert_eq!(num, 0);
2788 ancestors.insert(slot, 0);
2789 assert!(index.get(pubkey, Some(&ancestors), None).is_some());
2790 assert_eq!(index.ref_count_from_storage(pubkey), 1);
2791 index.unchecked_scan_accounts(
2792 "",
2793 &ancestors,
2794 |_pubkey, _index| num += 1,
2795 COLLECT_ALL_UNSORTED_FALSE,
2796 );
2797 assert_eq!(num, 1);
2798
2799 let index = AccountsIndex::<AccountInfoTest>::default_for_tests();
2801 let account_info: AccountInfoTest = 0 as AccountInfoTest;
2802 let items = vec![(*pubkey, account_info)];
2803 index.insert_new_if_missing_into_primary_index(slot, items.len(), items.into_iter());
2804
2805 let mut ancestors = Ancestors::default();
2806 assert!(index.get(pubkey, Some(&ancestors), None).is_none());
2807 assert!(index.get(pubkey, None, None).is_none());
2808
2809 let mut num = 0;
2810 index.unchecked_scan_accounts(
2811 "",
2812 &ancestors,
2813 |_pubkey, _index| num += 1,
2814 COLLECT_ALL_UNSORTED_FALSE,
2815 );
2816 assert_eq!(num, 0);
2817 ancestors.insert(slot, 0);
2818 assert!(index.get(pubkey, Some(&ancestors), None).is_some());
2819 assert_eq!(index.ref_count_from_storage(pubkey), 0); index.unchecked_scan_accounts(
2821 "",
2822 &ancestors,
2823 |_pubkey, _index| num += 1,
2824 COLLECT_ALL_UNSORTED_FALSE,
2825 );
2826 assert_eq!(num, 1);
2827 }
2828
2829 #[test]
2830 fn test_new_entry() {
2831 let slot = 0;
2832 let account_info = AccountInfoTest::default();
2834 let index = AccountsIndex::default_for_tests();
2835
2836 let new_entry: AccountMapEntry<_> =
2837 PreAllocatedAccountMapEntry::new(slot, account_info, &index.storage.storage).into();
2838 assert_eq!(new_entry.ref_count.load(Ordering::Relaxed), 0);
2839 assert_eq!(new_entry.slot_list.read().unwrap().capacity(), 1);
2840 assert_eq!(
2841 new_entry.slot_list.read().unwrap().to_vec(),
2842 vec![(slot, account_info)]
2843 );
2844
2845 let account_info = true;
2847 let index = AccountsIndex::default_for_tests();
2848
2849 let new_entry: AccountMapEntry<_> =
2850 PreAllocatedAccountMapEntry::new(slot, account_info, &index.storage.storage).into();
2851 assert_eq!(new_entry.ref_count.load(Ordering::Relaxed), 1);
2852 assert_eq!(new_entry.slot_list.read().unwrap().capacity(), 1);
2853 assert_eq!(
2854 new_entry.slot_list.read().unwrap().to_vec(),
2855 vec![(slot, account_info)]
2856 );
2857 }
2858
2859 #[test]
2860 fn test_batch_insert() {
2861 let slot0 = 0;
2862 let key0 = Keypair::new().pubkey();
2863 let key1 = Keypair::new().pubkey();
2864
2865 let index = AccountsIndex::<bool>::default_for_tests();
2866 let account_infos = [true, false];
2867
2868 let items = vec![(key0, account_infos[0]), (key1, account_infos[1])];
2869 index.insert_new_if_missing_into_primary_index(slot0, items.len(), items.into_iter());
2870
2871 for (i, key) in [key0, key1].iter().enumerate() {
2872 let entry = index.get_account_read_entry(key).unwrap();
2873 assert_eq!(entry.ref_count(), 1);
2874 assert_eq!(entry.slot_list().to_vec(), vec![(slot0, account_infos[i]),]);
2875 }
2876 }
2877
2878 fn test_new_entry_code_paths_helper<T: IndexValue>(
2879 account_infos: [T; 2],
2880 is_cached: bool,
2881 upsert: bool,
2882 ) {
2883 let slot0 = 0;
2884 let slot1 = 1;
2885 let key = Keypair::new().pubkey();
2886
2887 let index = AccountsIndex::<T>::default_for_tests();
2888 let mut gc = Vec::new();
2889
2890 if upsert {
2891 index.upsert(
2893 slot0,
2894 &key,
2895 &Pubkey::default(),
2896 &[],
2897 &AccountSecondaryIndexes::default(),
2898 account_infos[0],
2899 &mut gc,
2900 UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE,
2901 );
2902 } else {
2903 let items = vec![(key, account_infos[0])];
2904 index.insert_new_if_missing_into_primary_index(slot0, items.len(), items.into_iter());
2905 }
2906 assert!(gc.is_empty());
2907
2908 {
2910 let entry = index.get_account_read_entry(&key).unwrap();
2911 assert_eq!(entry.ref_count(), if is_cached { 0 } else { 1 });
2912 let expected = vec![(slot0, account_infos[0])];
2913 assert_eq!(entry.slot_list().to_vec(), expected);
2914 let new_entry: AccountMapEntry<_> =
2915 PreAllocatedAccountMapEntry::new(slot0, account_infos[0], &index.storage.storage)
2916 .into();
2917 assert_eq!(
2918 entry.slot_list().to_vec(),
2919 new_entry.slot_list.read().unwrap().to_vec(),
2920 );
2921 }
2922
2923 if upsert {
2925 index.upsert(
2926 slot1,
2927 &key,
2928 &Pubkey::default(),
2929 &[],
2930 &AccountSecondaryIndexes::default(),
2931 account_infos[1],
2932 &mut gc,
2933 UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE,
2934 );
2935 } else {
2936 let items = vec![(key, account_infos[1])];
2937 index.insert_new_if_missing_into_primary_index(slot1, items.len(), items.into_iter());
2938 }
2939 assert!(gc.is_empty());
2940
2941 for lock in &[false, true] {
2942 let read_lock = if *lock {
2943 Some(index.get_account_maps_read_lock(&key))
2944 } else {
2945 None
2946 };
2947
2948 let entry = if *lock {
2949 index
2950 .get_account_read_entry_with_lock(&key, read_lock.as_ref().unwrap())
2951 .unwrap()
2952 } else {
2953 index.get_account_read_entry(&key).unwrap()
2954 };
2955
2956 assert_eq!(entry.ref_count(), if is_cached { 0 } else { 2 });
2957 assert_eq!(
2958 entry.slot_list().to_vec(),
2959 vec![(slot0, account_infos[0]), (slot1, account_infos[1])]
2960 );
2961
2962 let new_entry =
2963 PreAllocatedAccountMapEntry::new(slot1, account_infos[1], &index.storage.storage);
2964 assert_eq!(entry.slot_list()[1], new_entry.into());
2965 }
2966 }
2967
2968 #[test]
2969 fn test_new_entry_and_update_code_paths() {
2970 for is_upsert in &[false, true] {
2971 test_new_entry_code_paths_helper([1.0, 2.0], true, *is_upsert);
2973
2974 test_new_entry_code_paths_helper([true, false], false, *is_upsert);
2976 }
2977 }
2978
2979 #[test]
2980 fn test_insert_with_lock_no_ancestors() {
2981 let key = Keypair::new();
2982 let index = AccountsIndex::<bool>::default_for_tests();
2983 let slot = 0;
2984 let account_info = true;
2985
2986 let new_entry =
2987 PreAllocatedAccountMapEntry::new(slot, account_info, &index.storage.storage);
2988 assert_eq!(0, account_maps_len_expensive(&index));
2989 assert_eq!((slot, account_info), new_entry.clone().into());
2990
2991 assert_eq!(0, account_maps_len_expensive(&index));
2992 let w_account_maps = index.get_account_maps_write_lock(&key.pubkey());
2993 w_account_maps.upsert(
2994 &key.pubkey(),
2995 new_entry,
2996 &mut SlotList::default(),
2997 UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE,
2998 );
2999 drop(w_account_maps);
3000 assert_eq!(1, account_maps_len_expensive(&index));
3001
3002 let mut ancestors = Ancestors::default();
3003 assert!(index.get(&key.pubkey(), Some(&ancestors), None).is_none());
3004 assert!(index.get(&key.pubkey(), None, None).is_none());
3005
3006 let mut num = 0;
3007 index.unchecked_scan_accounts(
3008 "",
3009 &ancestors,
3010 |_pubkey, _index| num += 1,
3011 COLLECT_ALL_UNSORTED_FALSE,
3012 );
3013 assert_eq!(num, 0);
3014 ancestors.insert(slot, 0);
3015 assert!(index.get(&key.pubkey(), Some(&ancestors), None).is_some());
3016 index.unchecked_scan_accounts(
3017 "",
3018 &ancestors,
3019 |_pubkey, _index| num += 1,
3020 COLLECT_ALL_UNSORTED_FALSE,
3021 );
3022 assert_eq!(num, 1);
3023 }
3024
3025 #[test]
3026 fn test_insert_wrong_ancestors() {
3027 let key = Keypair::new();
3028 let index = AccountsIndex::<bool>::default_for_tests();
3029 let mut gc = Vec::new();
3030 index.upsert(
3031 0,
3032 &key.pubkey(),
3033 &Pubkey::default(),
3034 &[],
3035 &AccountSecondaryIndexes::default(),
3036 true,
3037 &mut gc,
3038 UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE,
3039 );
3040 assert!(gc.is_empty());
3041
3042 let ancestors = vec![(1, 1)].into_iter().collect();
3043 assert!(index.get(&key.pubkey(), Some(&ancestors), None).is_none());
3044
3045 let mut num = 0;
3046 index.unchecked_scan_accounts(
3047 "",
3048 &ancestors,
3049 |_pubkey, _index| num += 1,
3050 COLLECT_ALL_UNSORTED_FALSE,
3051 );
3052 assert_eq!(num, 0);
3053 }
3054
3055 #[test]
3056 fn test_insert_with_ancestors() {
3057 let key = Keypair::new();
3058 let index = AccountsIndex::<bool>::default_for_tests();
3059 let mut gc = Vec::new();
3060 index.upsert(
3061 0,
3062 &key.pubkey(),
3063 &Pubkey::default(),
3064 &[],
3065 &AccountSecondaryIndexes::default(),
3066 true,
3067 &mut gc,
3068 UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE,
3069 );
3070 assert!(gc.is_empty());
3071
3072 let ancestors = vec![(0, 0)].into_iter().collect();
3073 let (list, idx) = index.get(&key.pubkey(), Some(&ancestors), None).unwrap();
3074 assert_eq!(list.slot_list()[idx], (0, true));
3075
3076 let mut num = 0;
3077 let mut found_key = false;
3078 index.unchecked_scan_accounts(
3079 "",
3080 &ancestors,
3081 |pubkey, _index| {
3082 if pubkey == &key.pubkey() {
3083 found_key = true
3084 };
3085 num += 1
3086 },
3087 COLLECT_ALL_UNSORTED_FALSE,
3088 );
3089 assert_eq!(num, 1);
3090 assert!(found_key);
3091 }
3092
3093 fn setup_accounts_index_keys(num_pubkeys: usize) -> (AccountsIndex<bool>, Vec<Pubkey>) {
3094 let index = AccountsIndex::<bool>::default_for_tests();
3095 let root_slot = 0;
3096
3097 let mut pubkeys: Vec<Pubkey> = std::iter::repeat_with(|| {
3098 let new_pubkey = gemachain_sdk::pubkey::new_rand();
3099 index.upsert(
3100 root_slot,
3101 &new_pubkey,
3102 &Pubkey::default(),
3103 &[],
3104 &AccountSecondaryIndexes::default(),
3105 true,
3106 &mut vec![],
3107 UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE,
3108 );
3109 new_pubkey
3110 })
3111 .take(num_pubkeys.saturating_sub(1))
3112 .collect();
3113
3114 if num_pubkeys != 0 {
3115 pubkeys.push(Pubkey::default());
3116 index.upsert(
3117 root_slot,
3118 &Pubkey::default(),
3119 &Pubkey::default(),
3120 &[],
3121 &AccountSecondaryIndexes::default(),
3122 true,
3123 &mut vec![],
3124 UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE,
3125 );
3126 }
3127
3128 index.add_root(root_slot, false);
3129
3130 (index, pubkeys)
3131 }
3132
3133 fn run_test_range(
3134 index: &AccountsIndex<bool>,
3135 pubkeys: &[Pubkey],
3136 start_bound: Bound<usize>,
3137 end_bound: Bound<usize>,
3138 ) {
3139 let (pubkey_start, index_start) = match start_bound {
3141 Unbounded => (Unbounded, 0),
3142 Included(i) => (Included(pubkeys[i]), i),
3143 Excluded(i) => (Excluded(pubkeys[i]), i + 1),
3144 };
3145
3146 let (pubkey_end, index_end) = match end_bound {
3148 Unbounded => (Unbounded, pubkeys.len()),
3149 Included(i) => (Included(pubkeys[i]), i + 1),
3150 Excluded(i) => (Excluded(pubkeys[i]), i),
3151 };
3152 let pubkey_range = (pubkey_start, pubkey_end);
3153
3154 let ancestors = Ancestors::default();
3155 let mut scanned_keys = HashSet::new();
3156 index.range_scan_accounts(
3157 "",
3158 &ancestors,
3159 pubkey_range,
3160 COLLECT_ALL_UNSORTED_FALSE,
3161 |pubkey, _index| {
3162 scanned_keys.insert(*pubkey);
3163 },
3164 );
3165
3166 let mut expected_len = 0;
3167 for key in &pubkeys[index_start..index_end] {
3168 expected_len += 1;
3169 assert!(scanned_keys.contains(key));
3170 }
3171
3172 assert_eq!(scanned_keys.len(), expected_len);
3173 }
3174
3175 fn run_test_range_indexes(
3176 index: &AccountsIndex<bool>,
3177 pubkeys: &[Pubkey],
3178 start: Option<usize>,
3179 end: Option<usize>,
3180 ) {
3181 let start_options = start
3182 .map(|i| vec![Included(i), Excluded(i)])
3183 .unwrap_or_else(|| vec![Unbounded]);
3184 let end_options = end
3185 .map(|i| vec![Included(i), Excluded(i)])
3186 .unwrap_or_else(|| vec![Unbounded]);
3187
3188 for start in &start_options {
3189 for end in &end_options {
3190 run_test_range(index, pubkeys, *start, *end);
3191 }
3192 }
3193 }
3194
3195 #[test]
3196 fn test_range_scan_accounts() {
3197 let (index, mut pubkeys) = setup_accounts_index_keys(3 * ITER_BATCH_SIZE);
3198 pubkeys.sort();
3199
3200 run_test_range_indexes(&index, &pubkeys, None, None);
3201
3202 run_test_range_indexes(&index, &pubkeys, Some(ITER_BATCH_SIZE), None);
3203
3204 run_test_range_indexes(&index, &pubkeys, None, Some(2 * ITER_BATCH_SIZE as usize));
3205
3206 run_test_range_indexes(
3207 &index,
3208 &pubkeys,
3209 Some(ITER_BATCH_SIZE as usize),
3210 Some(2 * ITER_BATCH_SIZE as usize),
3211 );
3212
3213 run_test_range_indexes(
3214 &index,
3215 &pubkeys,
3216 Some(ITER_BATCH_SIZE as usize),
3217 Some(2 * ITER_BATCH_SIZE as usize - 1),
3218 );
3219
3220 run_test_range_indexes(
3221 &index,
3222 &pubkeys,
3223 Some(ITER_BATCH_SIZE - 1_usize),
3224 Some(2 * ITER_BATCH_SIZE as usize + 1),
3225 );
3226 }
3227
3228 fn run_test_scan_accounts(num_pubkeys: usize) {
3229 let (index, _) = setup_accounts_index_keys(num_pubkeys);
3230 let ancestors = Ancestors::default();
3231
3232 let mut scanned_keys = HashSet::new();
3233 index.unchecked_scan_accounts(
3234 "",
3235 &ancestors,
3236 |pubkey, _index| {
3237 scanned_keys.insert(*pubkey);
3238 },
3239 COLLECT_ALL_UNSORTED_FALSE,
3240 );
3241 assert_eq!(scanned_keys.len(), num_pubkeys);
3242 }
3243
3244 #[test]
3245 fn test_scan_accounts() {
3246 run_test_scan_accounts(0);
3247 run_test_scan_accounts(1);
3248 run_test_scan_accounts(ITER_BATCH_SIZE * 10);
3249 run_test_scan_accounts(ITER_BATCH_SIZE * 10 - 1);
3250 run_test_scan_accounts(ITER_BATCH_SIZE * 10 + 1);
3251 }
3252
3253 #[test]
3254 fn test_accounts_iter_finished() {
3255 let (index, _) = setup_accounts_index_keys(0);
3256 let mut iter = index.iter(None::<&Range<Pubkey>>, COLLECT_ALL_UNSORTED_FALSE);
3257 assert!(iter.next().is_none());
3258 let mut gc = vec![];
3259 index.upsert(
3260 0,
3261 &gemachain_sdk::pubkey::new_rand(),
3262 &Pubkey::default(),
3263 &[],
3264 &AccountSecondaryIndexes::default(),
3265 true,
3266 &mut gc,
3267 UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE,
3268 );
3269 assert!(iter.next().is_none());
3270 }
3271
3272 #[test]
3273 fn test_is_root() {
3274 let index = AccountsIndex::<bool>::default_for_tests();
3275 assert!(!index.is_root(0));
3276 index.add_root(0, false);
3277 assert!(index.is_root(0));
3278 }
3279
3280 #[test]
3281 fn test_insert_with_root() {
3282 let key = Keypair::new();
3283 let index = AccountsIndex::<bool>::default_for_tests();
3284 let mut gc = Vec::new();
3285 index.upsert(
3286 0,
3287 &key.pubkey(),
3288 &Pubkey::default(),
3289 &[],
3290 &AccountSecondaryIndexes::default(),
3291 true,
3292 &mut gc,
3293 UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE,
3294 );
3295 assert!(gc.is_empty());
3296
3297 index.add_root(0, false);
3298 let (list, idx) = index.get(&key.pubkey(), None, None).unwrap();
3299 assert_eq!(list.slot_list()[idx], (0, true));
3300 }
3301
3302 #[test]
3303 fn test_clean_first() {
3304 let index = AccountsIndex::<bool>::default_for_tests();
3305 index.add_root(0, false);
3306 index.add_root(1, false);
3307 index.clean_dead_slot(0);
3308 assert!(index.is_root(1));
3309 assert!(!index.is_root(0));
3310 }
3311
3312 #[test]
3313 fn test_clean_last() {
3314 let index = AccountsIndex::<bool>::default_for_tests();
3316 index.add_root(0, false);
3317 index.add_root(1, false);
3318 index.clean_dead_slot(1);
3319 assert!(!index.is_root(1));
3320 assert!(index.is_root(0));
3321 }
3322
3323 #[test]
3324 fn test_clean_and_unclean_slot() {
3325 let index = AccountsIndex::<bool>::default_for_tests();
3326 assert_eq!(0, index.roots_tracker.read().unwrap().uncleaned_roots.len());
3327 index.add_root(0, false);
3328 index.add_root(1, false);
3329 assert_eq!(2, index.roots_tracker.read().unwrap().uncleaned_roots.len());
3330
3331 assert_eq!(
3332 0,
3333 index
3334 .roots_tracker
3335 .read()
3336 .unwrap()
3337 .previous_uncleaned_roots
3338 .len()
3339 );
3340 index.reset_uncleaned_roots(None);
3341 assert_eq!(2, index.roots_tracker.read().unwrap().roots.len());
3342 assert_eq!(0, index.roots_tracker.read().unwrap().uncleaned_roots.len());
3343 assert_eq!(
3344 2,
3345 index
3346 .roots_tracker
3347 .read()
3348 .unwrap()
3349 .previous_uncleaned_roots
3350 .len()
3351 );
3352
3353 index.add_root(2, false);
3354 index.add_root(3, false);
3355 assert_eq!(4, index.roots_tracker.read().unwrap().roots.len());
3356 assert_eq!(2, index.roots_tracker.read().unwrap().uncleaned_roots.len());
3357 assert_eq!(
3358 2,
3359 index
3360 .roots_tracker
3361 .read()
3362 .unwrap()
3363 .previous_uncleaned_roots
3364 .len()
3365 );
3366
3367 index.clean_dead_slot(1);
3368 assert_eq!(3, index.roots_tracker.read().unwrap().roots.len());
3369 assert_eq!(2, index.roots_tracker.read().unwrap().uncleaned_roots.len());
3370 assert_eq!(
3371 1,
3372 index
3373 .roots_tracker
3374 .read()
3375 .unwrap()
3376 .previous_uncleaned_roots
3377 .len()
3378 );
3379
3380 index.clean_dead_slot(2);
3381 assert_eq!(2, index.roots_tracker.read().unwrap().roots.len());
3382 assert_eq!(1, index.roots_tracker.read().unwrap().uncleaned_roots.len());
3383 assert_eq!(
3384 1,
3385 index
3386 .roots_tracker
3387 .read()
3388 .unwrap()
3389 .previous_uncleaned_roots
3390 .len()
3391 );
3392 }
3393
3394 #[test]
3395 fn test_update_last_wins() {
3396 let key = Keypair::new();
3397 let index = AccountsIndex::<bool>::default_for_tests();
3398 let ancestors = vec![(0, 0)].into_iter().collect();
3399 let mut gc = Vec::new();
3400 index.upsert(
3401 0,
3402 &key.pubkey(),
3403 &Pubkey::default(),
3404 &[],
3405 &AccountSecondaryIndexes::default(),
3406 true,
3407 &mut gc,
3408 UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE,
3409 );
3410 assert!(gc.is_empty());
3411 let (list, idx) = index.get(&key.pubkey(), Some(&ancestors), None).unwrap();
3412 assert_eq!(list.slot_list()[idx], (0, true));
3413 drop(list);
3414
3415 let mut gc = Vec::new();
3416 index.upsert(
3417 0,
3418 &key.pubkey(),
3419 &Pubkey::default(),
3420 &[],
3421 &AccountSecondaryIndexes::default(),
3422 false,
3423 &mut gc,
3424 UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE,
3425 );
3426 assert_eq!(gc, vec![(0, true)]);
3427 let (list, idx) = index.get(&key.pubkey(), Some(&ancestors), None).unwrap();
3428 assert_eq!(list.slot_list()[idx], (0, false));
3429 }
3430
3431 #[test]
3432 fn test_update_new_slot() {
3433 gemachain_logger::setup();
3434 let key = Keypair::new();
3435 let index = AccountsIndex::<bool>::default_for_tests();
3436 let ancestors = vec![(0, 0)].into_iter().collect();
3437 let mut gc = Vec::new();
3438 index.upsert(
3439 0,
3440 &key.pubkey(),
3441 &Pubkey::default(),
3442 &[],
3443 &AccountSecondaryIndexes::default(),
3444 true,
3445 &mut gc,
3446 UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE,
3447 );
3448 assert!(gc.is_empty());
3449 index.upsert(
3450 1,
3451 &key.pubkey(),
3452 &Pubkey::default(),
3453 &[],
3454 &AccountSecondaryIndexes::default(),
3455 false,
3456 &mut gc,
3457 UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE,
3458 );
3459 assert!(gc.is_empty());
3460 let (list, idx) = index.get(&key.pubkey(), Some(&ancestors), None).unwrap();
3461 assert_eq!(list.slot_list()[idx], (0, true));
3462 let ancestors = vec![(1, 0)].into_iter().collect();
3463 let (list, idx) = index.get(&key.pubkey(), Some(&ancestors), None).unwrap();
3464 assert_eq!(list.slot_list()[idx], (1, false));
3465 }
3466
3467 #[test]
3468 fn test_update_gc_purged_slot() {
3469 let key = Keypair::new();
3470 let index = AccountsIndex::<bool>::default_for_tests();
3471 let mut gc = Vec::new();
3472 index.upsert(
3473 0,
3474 &key.pubkey(),
3475 &Pubkey::default(),
3476 &[],
3477 &AccountSecondaryIndexes::default(),
3478 true,
3479 &mut gc,
3480 UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE,
3481 );
3482 assert!(gc.is_empty());
3483 index.upsert(
3484 1,
3485 &key.pubkey(),
3486 &Pubkey::default(),
3487 &[],
3488 &AccountSecondaryIndexes::default(),
3489 false,
3490 &mut gc,
3491 UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE,
3492 );
3493 index.upsert(
3494 2,
3495 &key.pubkey(),
3496 &Pubkey::default(),
3497 &[],
3498 &AccountSecondaryIndexes::default(),
3499 true,
3500 &mut gc,
3501 UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE,
3502 );
3503 index.upsert(
3504 3,
3505 &key.pubkey(),
3506 &Pubkey::default(),
3507 &[],
3508 &AccountSecondaryIndexes::default(),
3509 true,
3510 &mut gc,
3511 UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE,
3512 );
3513 index.add_root(0, false);
3514 index.add_root(1, false);
3515 index.add_root(3, false);
3516 index.upsert(
3517 4,
3518 &key.pubkey(),
3519 &Pubkey::default(),
3520 &[],
3521 &AccountSecondaryIndexes::default(),
3522 true,
3523 &mut gc,
3524 UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE,
3525 );
3526
3527 assert_eq!(gc, vec![]);
3530 let (list, idx) = index.get(&key.pubkey(), None, None).unwrap();
3531 assert_eq!(list.slot_list()[idx], (3, true));
3532
3533 let mut num = 0;
3534 let mut found_key = false;
3535 index.unchecked_scan_accounts(
3536 "",
3537 &Ancestors::default(),
3538 |pubkey, _index| {
3539 if pubkey == &key.pubkey() {
3540 found_key = true;
3541 assert_eq!(_index, (&true, 3));
3542 };
3543 num += 1
3544 },
3545 COLLECT_ALL_UNSORTED_FALSE,
3546 );
3547 assert_eq!(num, 1);
3548 assert!(found_key);
3549 }
3550
3551 fn account_maps_len_expensive<T: IndexValue>(index: &AccountsIndex<T>) -> usize {
3552 index
3553 .account_maps
3554 .iter()
3555 .map(|bin_map| bin_map.read().unwrap().len())
3556 .sum()
3557 }
3558
3559 #[test]
3560 fn test_purge() {
3561 let key = Keypair::new();
3562 let index = AccountsIndex::<u64>::default_for_tests();
3563 let mut gc = Vec::new();
3564 assert_eq!(0, account_maps_len_expensive(&index));
3565 index.upsert(
3566 1,
3567 &key.pubkey(),
3568 &Pubkey::default(),
3569 &[],
3570 &AccountSecondaryIndexes::default(),
3571 12,
3572 &mut gc,
3573 UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE,
3574 );
3575 assert_eq!(1, account_maps_len_expensive(&index));
3576
3577 index.upsert(
3578 1,
3579 &key.pubkey(),
3580 &Pubkey::default(),
3581 &[],
3582 &AccountSecondaryIndexes::default(),
3583 10,
3584 &mut gc,
3585 UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE,
3586 );
3587 assert_eq!(1, account_maps_len_expensive(&index));
3588
3589 let purges = index.purge_roots(&key.pubkey());
3590 assert_eq!(purges, (vec![], false));
3591 index.add_root(1, false);
3592
3593 let purges = index.purge_roots(&key.pubkey());
3594 assert_eq!(purges, (vec![(1, 10)], true));
3595
3596 assert_eq!(1, account_maps_len_expensive(&index));
3597 index.upsert(
3598 1,
3599 &key.pubkey(),
3600 &Pubkey::default(),
3601 &[],
3602 &AccountSecondaryIndexes::default(),
3603 9,
3604 &mut gc,
3605 UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE,
3606 );
3607 assert_eq!(1, account_maps_len_expensive(&index));
3608 }
3609
3610 #[test]
3611 fn test_latest_slot() {
3612 let slot_slice = vec![(0, true), (5, true), (3, true), (7, true)];
3613 let index = AccountsIndex::<bool>::default_for_tests();
3614
3615 assert!(index.latest_slot(None, &slot_slice, None).is_none());
3617
3618 index.add_root(5, false);
3620 assert_eq!(index.latest_slot(None, &slot_slice, None).unwrap(), 1);
3621
3622 assert_eq!(index.latest_slot(None, &slot_slice, Some(5)).unwrap(), 1);
3624
3625 assert!(index.latest_slot(None, &slot_slice, Some(4)).is_none());
3627
3628 let ancestors = vec![(3, 1), (7, 1)].into_iter().collect();
3631 assert_eq!(
3632 index
3633 .latest_slot(Some(&ancestors), &slot_slice, Some(4))
3634 .unwrap(),
3635 3
3636 );
3637 assert_eq!(
3638 index
3639 .latest_slot(Some(&ancestors), &slot_slice, Some(7))
3640 .unwrap(),
3641 3
3642 );
3643
3644 assert_eq!(
3646 index
3647 .latest_slot(Some(&ancestors), &slot_slice, None)
3648 .unwrap(),
3649 3
3650 );
3651 }
3652
3653 fn run_test_purge_exact_secondary_index<
3654 SecondaryIndexEntryType: SecondaryIndexEntry + Default + Sync + Send,
3655 >(
3656 index: &AccountsIndex<bool>,
3657 secondary_index: &SecondaryIndex<SecondaryIndexEntryType>,
3658 key_start: usize,
3659 key_end: usize,
3660 secondary_indexes: &AccountSecondaryIndexes,
3661 ) {
3662 let slots = vec![1, 2, 5, 9];
3664 let index_key = Pubkey::new_unique();
3665 let account_key = Pubkey::new_unique();
3666
3667 let mut account_data = vec![0; inline_spl_token_v2_0::state::Account::get_packed_len()];
3668 account_data[key_start..key_end].clone_from_slice(&(index_key.to_bytes()));
3669
3670 for slot in &slots {
3672 index.upsert(
3673 *slot,
3674 &account_key,
3675 &inline_spl_token_v2_0::id(),
3677 &account_data,
3678 secondary_indexes,
3679 true,
3680 &mut vec![],
3681 UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE,
3682 );
3683 }
3684
3685 assert_eq!(secondary_index.index.get(&index_key).unwrap().len(), 1);
3687
3688 assert_eq!(
3691 secondary_index
3692 .reverse_index
3693 .get(&account_key)
3694 .unwrap()
3695 .value()
3696 .read()
3697 .unwrap()
3698 .len(),
3699 1
3700 );
3701
3702 index.purge_exact(
3703 &account_key,
3704 &slots.into_iter().collect::<HashSet<Slot>>(),
3705 &mut vec![],
3706 );
3707
3708 index.handle_dead_keys(&[&account_key], secondary_indexes);
3709 assert!(secondary_index.index.is_empty());
3710 assert!(secondary_index.reverse_index.is_empty());
3711 }
3712
3713 #[test]
3714 fn test_purge_exact_dashmap_secondary_index() {
3715 let (key_start, key_end, secondary_indexes) = create_dashmap_secondary_index_state();
3716 let index = AccountsIndex::<bool>::default_for_tests();
3717 run_test_purge_exact_secondary_index(
3718 &index,
3719 &index.spl_token_mint_index,
3720 key_start,
3721 key_end,
3722 &secondary_indexes,
3723 );
3724 }
3725
3726 #[test]
3727 fn test_purge_exact_rwlock_secondary_index() {
3728 let (key_start, key_end, secondary_indexes) = create_rwlock_secondary_index_state();
3729 let index = AccountsIndex::<bool>::default_for_tests();
3730 run_test_purge_exact_secondary_index(
3731 &index,
3732 &index.spl_token_owner_index,
3733 key_start,
3734 key_end,
3735 &secondary_indexes,
3736 );
3737 }
3738
3739 #[test]
3740 fn test_purge_older_root_entries() {
3741 let index = AccountsIndex::<bool>::default_for_tests();
3743 let mut slot_list = vec![(1, true), (2, true), (5, true), (9, true)];
3744 let mut reclaims = vec![];
3745 index.purge_older_root_entries(&mut slot_list, &mut reclaims, None);
3746 assert!(reclaims.is_empty());
3747 assert_eq!(slot_list, vec![(1, true), (2, true), (5, true), (9, true)]);
3748
3749 slot_list = vec![(1, true), (2, true), (5, true), (9, true)];
3751 index.add_root(1, false);
3752 index.add_root(5, false);
3754 reclaims = vec![];
3755 index.purge_older_root_entries(&mut slot_list, &mut reclaims, None);
3756 assert_eq!(reclaims, vec![(1, true), (2, true)]);
3757 assert_eq!(slot_list, vec![(5, true), (9, true)]);
3758
3759 slot_list = vec![(1, true), (2, true), (5, true), (9, true)];
3761 index.add_root(6, false);
3762 reclaims = vec![];
3763 index.purge_older_root_entries(&mut slot_list, &mut reclaims, None);
3764 assert_eq!(reclaims, vec![(1, true), (2, true)]);
3765 assert_eq!(slot_list, vec![(5, true), (9, true)]);
3766
3767 slot_list = vec![(1, true), (2, true), (5, true), (9, true)];
3770 reclaims = vec![];
3771 index.purge_older_root_entries(&mut slot_list, &mut reclaims, Some(6));
3772 assert_eq!(reclaims, vec![(1, true), (2, true)]);
3773 assert_eq!(slot_list, vec![(5, true), (9, true)]);
3774
3775 slot_list = vec![(1, true), (2, true), (5, true), (9, true)];
3777 reclaims = vec![];
3778 index.purge_older_root_entries(&mut slot_list, &mut reclaims, Some(5));
3779 assert_eq!(reclaims, vec![(1, true), (2, true)]);
3780 assert_eq!(slot_list, vec![(5, true), (9, true)]);
3781
3782 slot_list = vec![(1, true), (2, true), (5, true), (9, true)];
3785 reclaims = vec![];
3786 index.purge_older_root_entries(&mut slot_list, &mut reclaims, Some(2));
3787 assert!(reclaims.is_empty());
3788 assert_eq!(slot_list, vec![(1, true), (2, true), (5, true), (9, true)]);
3789
3790 slot_list = vec![(1, true), (2, true), (5, true), (9, true)];
3793 reclaims = vec![];
3794 index.purge_older_root_entries(&mut slot_list, &mut reclaims, Some(1));
3795 assert!(reclaims.is_empty());
3796 assert_eq!(slot_list, vec![(1, true), (2, true), (5, true), (9, true)]);
3797
3798 slot_list = vec![(1, true), (2, true), (5, true), (9, true)];
3801 reclaims = vec![];
3802 index.purge_older_root_entries(&mut slot_list, &mut reclaims, Some(7));
3803 assert_eq!(reclaims, vec![(1, true), (2, true)]);
3804 assert_eq!(slot_list, vec![(5, true), (9, true)]);
3805 }
3806
3807 fn check_secondary_index_mapping_correct<SecondaryIndexEntryType>(
3808 secondary_index: &SecondaryIndex<SecondaryIndexEntryType>,
3809 secondary_index_keys: &[Pubkey],
3810 account_key: &Pubkey,
3811 ) where
3812 SecondaryIndexEntryType: SecondaryIndexEntry + Default + Sync + Send,
3813 {
3814 for secondary_index_key in secondary_index_keys {
3817 assert_eq!(secondary_index.index.len(), secondary_index_keys.len());
3818 let account_key_map = secondary_index.get(secondary_index_key);
3819 assert_eq!(account_key_map.len(), 1);
3820 assert_eq!(account_key_map, vec![*account_key]);
3821 }
3822 let secondary_index_key_map = secondary_index.reverse_index.get(account_key).unwrap();
3824 assert_eq!(
3825 &*secondary_index_key_map.value().read().unwrap(),
3826 secondary_index_keys
3827 );
3828 }
3829
3830 fn run_test_secondary_indexes<
3831 SecondaryIndexEntryType: SecondaryIndexEntry + Default + Sync + Send,
3832 >(
3833 index: &AccountsIndex<bool>,
3834 secondary_index: &SecondaryIndex<SecondaryIndexEntryType>,
3835 key_start: usize,
3836 key_end: usize,
3837 secondary_indexes: &AccountSecondaryIndexes,
3838 ) {
3839 let mut secondary_indexes = secondary_indexes.clone();
3840 let account_key = Pubkey::new_unique();
3841 let index_key = Pubkey::new_unique();
3842 let mut account_data = vec![0; inline_spl_token_v2_0::state::Account::get_packed_len()];
3843 account_data[key_start..key_end].clone_from_slice(&(index_key.to_bytes()));
3844
3845 index.upsert(
3847 0,
3848 &account_key,
3849 &Pubkey::default(),
3850 &account_data,
3851 &secondary_indexes,
3852 true,
3853 &mut vec![],
3854 UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE,
3855 );
3856 assert!(secondary_index.index.is_empty());
3857 assert!(secondary_index.reverse_index.is_empty());
3858
3859 index.upsert(
3861 0,
3862 &account_key,
3863 &inline_spl_token_v2_0::id(),
3864 &account_data[1..],
3865 &secondary_indexes,
3866 true,
3867 &mut vec![],
3868 UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE,
3869 );
3870 assert!(secondary_index.index.is_empty());
3871 assert!(secondary_index.reverse_index.is_empty());
3872
3873 secondary_indexes.keys = None;
3874
3875 for _ in 0..2 {
3877 index.update_secondary_indexes(
3878 &account_key,
3879 &inline_spl_token_v2_0::id(),
3880 &account_data,
3881 &secondary_indexes,
3882 );
3883 check_secondary_index_mapping_correct(secondary_index, &[index_key], &account_key);
3884 }
3885
3886 assert!(!secondary_index.index.is_empty());
3888 assert!(!secondary_index.reverse_index.is_empty());
3889
3890 secondary_indexes.keys = Some(AccountSecondaryIndexesIncludeExclude {
3891 keys: [index_key].iter().cloned().collect::<HashSet<_>>(),
3892 exclude: false,
3893 });
3894 secondary_index.index.clear();
3895 secondary_index.reverse_index.clear();
3896 index.update_secondary_indexes(
3897 &account_key,
3898 &inline_spl_token_v2_0::id(),
3899 &account_data,
3900 &secondary_indexes,
3901 );
3902 assert!(!secondary_index.index.is_empty());
3903 assert!(!secondary_index.reverse_index.is_empty());
3904 check_secondary_index_mapping_correct(secondary_index, &[index_key], &account_key);
3905
3906 secondary_indexes.keys = Some(AccountSecondaryIndexesIncludeExclude {
3908 keys: [].iter().cloned().collect::<HashSet<_>>(),
3909 exclude: true,
3910 });
3911 secondary_index.index.clear();
3912 secondary_index.reverse_index.clear();
3913 index.update_secondary_indexes(
3914 &account_key,
3915 &inline_spl_token_v2_0::id(),
3916 &account_data,
3917 &secondary_indexes,
3918 );
3919 assert!(!secondary_index.index.is_empty());
3920 assert!(!secondary_index.reverse_index.is_empty());
3921 check_secondary_index_mapping_correct(secondary_index, &[index_key], &account_key);
3922
3923 secondary_indexes.keys = None;
3924
3925 index
3926 .get_account_write_entry(&account_key)
3927 .unwrap()
3928 .slot_list_mut(|slot_list| slot_list.clear());
3929
3930 index.handle_dead_keys(&[&account_key], &secondary_indexes);
3932 assert!(secondary_index.index.is_empty());
3933 assert!(secondary_index.reverse_index.is_empty());
3934 }
3935
3936 #[test]
3937 fn test_dashmap_secondary_index() {
3938 let (key_start, key_end, secondary_indexes) = create_dashmap_secondary_index_state();
3939 let index = AccountsIndex::<bool>::default_for_tests();
3940 run_test_secondary_indexes(
3941 &index,
3942 &index.spl_token_mint_index,
3943 key_start,
3944 key_end,
3945 &secondary_indexes,
3946 );
3947 }
3948
3949 #[test]
3950 fn test_rwlock_secondary_index() {
3951 let (key_start, key_end, secondary_indexes) = create_rwlock_secondary_index_state();
3952 let index = AccountsIndex::<bool>::default_for_tests();
3953 run_test_secondary_indexes(
3954 &index,
3955 &index.spl_token_owner_index,
3956 key_start,
3957 key_end,
3958 &secondary_indexes,
3959 );
3960 }
3961
3962 fn run_test_secondary_indexes_same_slot_and_forks<
3963 SecondaryIndexEntryType: SecondaryIndexEntry + Default + Sync + Send,
3964 >(
3965 index: &AccountsIndex<bool>,
3966 secondary_index: &SecondaryIndex<SecondaryIndexEntryType>,
3967 index_key_start: usize,
3968 index_key_end: usize,
3969 secondary_indexes: &AccountSecondaryIndexes,
3970 ) {
3971 let account_key = Pubkey::new_unique();
3972 let secondary_key1 = Pubkey::new_unique();
3973 let secondary_key2 = Pubkey::new_unique();
3974 let slot = 1;
3975 let mut account_data1 = vec![0; inline_spl_token_v2_0::state::Account::get_packed_len()];
3976 account_data1[index_key_start..index_key_end]
3977 .clone_from_slice(&(secondary_key1.to_bytes()));
3978 let mut account_data2 = vec![0; inline_spl_token_v2_0::state::Account::get_packed_len()];
3979 account_data2[index_key_start..index_key_end]
3980 .clone_from_slice(&(secondary_key2.to_bytes()));
3981
3982 index.upsert(
3984 slot,
3985 &account_key,
3986 &inline_spl_token_v2_0::id(),
3987 &account_data1,
3988 secondary_indexes,
3989 true,
3990 &mut vec![],
3991 UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE,
3992 );
3993
3994 index.upsert(
3996 slot,
3997 &account_key,
3998 &inline_spl_token_v2_0::id(),
3999 &account_data2,
4000 secondary_indexes,
4001 true,
4002 &mut vec![],
4003 UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE,
4004 );
4005
4006 check_secondary_index_mapping_correct(
4008 secondary_index,
4009 &[secondary_key1, secondary_key2],
4010 &account_key,
4011 );
4012
4013 let later_slot = slot + 1;
4015 index.upsert(
4016 later_slot,
4017 &account_key,
4018 &inline_spl_token_v2_0::id(),
4019 &account_data1,
4020 secondary_indexes,
4021 true,
4022 &mut vec![],
4023 UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE,
4024 );
4025 assert_eq!(secondary_index.get(&secondary_key1), vec![account_key]);
4026
4027 index.add_root(later_slot, false);
4031 index
4032 .get_account_write_entry(&account_key)
4033 .unwrap()
4034 .slot_list_mut(|slot_list| {
4035 index.purge_older_root_entries(slot_list, &mut vec![], None)
4036 });
4037
4038 check_secondary_index_mapping_correct(
4039 secondary_index,
4040 &[secondary_key1, secondary_key2],
4041 &account_key,
4042 );
4043
4044 let mut reclaims = vec![];
4047 index.purge_exact(&account_key, &later_slot, &mut reclaims);
4048 index.handle_dead_keys(&[&account_key], secondary_indexes);
4049 assert!(secondary_index.index.is_empty());
4050 assert!(secondary_index.reverse_index.is_empty());
4051 }
4052
4053 #[test]
4054 fn test_dashmap_secondary_index_same_slot_and_forks() {
4055 let (key_start, key_end, account_index) = create_dashmap_secondary_index_state();
4056 let index = AccountsIndex::<bool>::default_for_tests();
4057 run_test_secondary_indexes_same_slot_and_forks(
4058 &index,
4059 &index.spl_token_mint_index,
4060 key_start,
4061 key_end,
4062 &account_index,
4063 );
4064 }
4065
4066 #[test]
4067 fn test_rwlock_secondary_index_same_slot_and_forks() {
4068 let (key_start, key_end, account_index) = create_rwlock_secondary_index_state();
4069 let index = AccountsIndex::<bool>::default_for_tests();
4070 run_test_secondary_indexes_same_slot_and_forks(
4071 &index,
4072 &index.spl_token_owner_index,
4073 key_start,
4074 key_end,
4075 &account_index,
4076 );
4077 }
4078
4079 impl IndexValue for bool {}
4080 impl IndexValue for u64 {}
4081 impl IsCached for bool {
4082 fn is_cached(&self) -> bool {
4083 false
4084 }
4085 }
4086 impl IsCached for u64 {
4087 fn is_cached(&self) -> bool {
4088 false
4089 }
4090 }
4091 impl ZeroCarat for bool {
4092 fn is_zero_carat(&self) -> bool {
4093 false
4094 }
4095 }
4096
4097 impl ZeroCarat for u64 {
4098 fn is_zero_carat(&self) -> bool {
4099 false
4100 }
4101 }
4102
4103 #[test]
4104 fn test_bin_start_and_range() {
4105 let index = AccountsIndex::<bool>::default_for_tests();
4106 let iter = AccountsIndexIterator::new(
4107 &index,
4108 None::<&RangeInclusive<Pubkey>>,
4109 COLLECT_ALL_UNSORTED_FALSE,
4110 );
4111 assert_eq!((0, usize::MAX), iter.bin_start_and_range());
4112
4113 let key_0 = Pubkey::new(&[0; 32]);
4114 let key_ff = Pubkey::new(&[0xff; 32]);
4115
4116 let iter = AccountsIndexIterator::new(
4117 &index,
4118 Some(&RangeInclusive::new(key_0, key_ff)),
4119 COLLECT_ALL_UNSORTED_FALSE,
4120 );
4121 let bins = index.bins();
4122 assert_eq!((0, bins), iter.bin_start_and_range());
4123 let iter = AccountsIndexIterator::new(
4124 &index,
4125 Some(&RangeInclusive::new(key_ff, key_0)),
4126 COLLECT_ALL_UNSORTED_FALSE,
4127 );
4128 assert_eq!((bins - 1, 0), iter.bin_start_and_range());
4129 let iter = AccountsIndexIterator::new(
4130 &index,
4131 Some(&(Included(key_0), Unbounded)),
4132 COLLECT_ALL_UNSORTED_FALSE,
4133 );
4134 assert_eq!((0, usize::MAX), iter.bin_start_and_range());
4135 let iter = AccountsIndexIterator::new(
4136 &index,
4137 Some(&(Included(key_ff), Unbounded)),
4138 COLLECT_ALL_UNSORTED_FALSE,
4139 );
4140 assert_eq!((bins - 1, usize::MAX), iter.bin_start_and_range());
4141
4142 assert_eq!(
4143 (0..2)
4144 .into_iter()
4145 .skip(1)
4146 .take(usize::MAX)
4147 .collect::<Vec<_>>(),
4148 vec![1]
4149 );
4150 }
4151
4152 #[test]
4153 fn test_start_end_bin() {
4154 let index = AccountsIndex::<bool>::default_for_tests();
4155 assert_eq!(index.bins(), BINS_FOR_TESTING);
4156 let iter = AccountsIndexIterator::new(
4157 &index,
4158 None::<&RangeInclusive<Pubkey>>,
4159 COLLECT_ALL_UNSORTED_FALSE,
4160 );
4161 assert_eq!(iter.start_bin(), 0); assert_eq!(iter.end_bin_inclusive(), usize::MAX); let key = Pubkey::new(&[0; 32]);
4165 let iter = AccountsIndexIterator::new(
4166 &index,
4167 Some(&RangeInclusive::new(key, key)),
4168 COLLECT_ALL_UNSORTED_FALSE,
4169 );
4170 assert_eq!(iter.start_bin(), 0); assert_eq!(iter.end_bin_inclusive(), 0); let iter = AccountsIndexIterator::new(
4173 &index,
4174 Some(&(Included(key), Excluded(key))),
4175 COLLECT_ALL_UNSORTED_FALSE,
4176 );
4177 assert_eq!(iter.start_bin(), 0); assert_eq!(iter.end_bin_inclusive(), 0); let iter = AccountsIndexIterator::new(
4180 &index,
4181 Some(&(Excluded(key), Excluded(key))),
4182 COLLECT_ALL_UNSORTED_FALSE,
4183 );
4184 assert_eq!(iter.start_bin(), 0); assert_eq!(iter.end_bin_inclusive(), 0); let key = Pubkey::new(&[0xff; 32]);
4188 let iter = AccountsIndexIterator::new(
4189 &index,
4190 Some(&RangeInclusive::new(key, key)),
4191 COLLECT_ALL_UNSORTED_FALSE,
4192 );
4193 let bins = index.bins();
4194 assert_eq!(iter.start_bin(), bins - 1); assert_eq!(iter.end_bin_inclusive(), bins - 1);
4196 let iter = AccountsIndexIterator::new(
4197 &index,
4198 Some(&(Included(key), Excluded(key))),
4199 COLLECT_ALL_UNSORTED_FALSE,
4200 );
4201 assert_eq!(iter.start_bin(), bins - 1); assert_eq!(iter.end_bin_inclusive(), bins - 1);
4203 let iter = AccountsIndexIterator::new(
4204 &index,
4205 Some(&(Excluded(key), Excluded(key))),
4206 COLLECT_ALL_UNSORTED_FALSE,
4207 );
4208 assert_eq!(iter.start_bin(), bins - 1); assert_eq!(iter.end_bin_inclusive(), bins - 1);
4210 }
4211
4212 #[test]
4213 #[should_panic(expected = "bins.is_power_of_two()")]
4214 #[allow(clippy::field_reassign_with_default)]
4215 fn test_illegal_bins() {
4216 let mut config = AccountsIndexConfig::default();
4217 config.bins = Some(3);
4218 AccountsIndex::<bool>::new(Some(config));
4219 }
4220}