2021-09-14 15:51:07 -07:00
|
|
|
use crate::accounts_index::IndexValue;
|
2021-09-12 15:14:59 -07:00
|
|
|
use crate::bucket_map_holder::BucketMapHolder;
|
2021-09-16 14:12:22 -07:00
|
|
|
use crate::in_mem_accounts_index::InMemAccountsIndex;
|
2021-09-12 15:14:59 -07:00
|
|
|
use crate::waitable_condvar::WaitableCondvar;
|
2021-09-15 07:54:16 -07:00
|
|
|
use std::fmt::Debug;
|
2021-09-16 15:52:06 -07:00
|
|
|
use std::time::Duration;
|
2021-09-12 15:14:59 -07:00
|
|
|
use std::{
|
|
|
|
sync::{
|
|
|
|
atomic::{AtomicBool, Ordering},
|
|
|
|
Arc,
|
|
|
|
},
|
|
|
|
thread::{Builder, JoinHandle},
|
|
|
|
};
|
|
|
|
|
|
|
|
// eventually hold the bucket map
|
|
|
|
// Also manages the lifetime of the background processing threads.
|
|
|
|
// When this instance is dropped, it will drop the bucket map and cleanup
|
|
|
|
// and it will stop all the background threads and join them.
|
2021-09-14 15:51:07 -07:00
|
|
|
pub struct AccountsIndexStorage<T: IndexValue> {
|
2021-09-12 15:14:59 -07:00
|
|
|
// for managing the bg threads
|
|
|
|
exit: Arc<AtomicBool>,
|
|
|
|
wait: Arc<WaitableCondvar>,
|
|
|
|
handle: Option<JoinHandle<()>>,
|
|
|
|
|
|
|
|
// eventually the backing storage
|
2021-09-13 20:59:03 -07:00
|
|
|
storage: Arc<BucketMapHolder<T>>,
|
2021-09-16 14:12:22 -07:00
|
|
|
pub in_mem: Vec<Arc<InMemAccountsIndex<T>>>,
|
2021-09-12 15:14:59 -07:00
|
|
|
}
|
|
|
|
|
2021-09-15 07:54:16 -07:00
|
|
|
impl<T: IndexValue> Debug for AccountsIndexStorage<T> {
|
|
|
|
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-14 15:51:07 -07:00
|
|
|
impl<T: IndexValue> Drop for AccountsIndexStorage<T> {
|
2021-09-12 15:14:59 -07:00
|
|
|
fn drop(&mut self) {
|
|
|
|
self.exit.store(true, Ordering::Relaxed);
|
|
|
|
self.wait.notify_all();
|
|
|
|
if let Some(x) = self.handle.take() {
|
|
|
|
x.join().unwrap()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-14 15:51:07 -07:00
|
|
|
impl<T: IndexValue> AccountsIndexStorage<T> {
|
2021-09-15 11:07:53 -07:00
|
|
|
pub fn new(bins: usize) -> AccountsIndexStorage<T> {
|
|
|
|
let storage = Arc::new(BucketMapHolder::new(bins));
|
2021-09-16 14:12:22 -07:00
|
|
|
|
|
|
|
let in_mem = (0..bins)
|
|
|
|
.into_iter()
|
|
|
|
.map(|bin| Arc::new(InMemAccountsIndex::new(&storage, bin)))
|
|
|
|
.collect();
|
|
|
|
|
2021-09-16 15:52:06 -07:00
|
|
|
let storage_ = Arc::clone(&storage);
|
2021-09-12 15:14:59 -07:00
|
|
|
let exit = Arc::new(AtomicBool::default());
|
2021-09-16 15:52:06 -07:00
|
|
|
let exit_ = Arc::clone(&exit);
|
2021-09-12 15:14:59 -07:00
|
|
|
let wait = Arc::new(WaitableCondvar::default());
|
2021-09-16 15:52:06 -07:00
|
|
|
let wait_ = Arc::clone(&wait);
|
2021-09-12 15:14:59 -07:00
|
|
|
let handle = Some(
|
|
|
|
Builder::new()
|
|
|
|
.name("solana-index-flusher".to_string())
|
|
|
|
.spawn(move || {
|
2021-09-16 15:52:06 -07:00
|
|
|
Self::background(storage_, exit_, wait_);
|
2021-09-12 15:14:59 -07:00
|
|
|
})
|
|
|
|
.unwrap(),
|
|
|
|
);
|
|
|
|
|
|
|
|
Self {
|
|
|
|
exit,
|
|
|
|
wait,
|
|
|
|
handle,
|
|
|
|
storage,
|
2021-09-16 14:12:22 -07:00
|
|
|
in_mem,
|
2021-09-12 15:14:59 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-13 20:59:03 -07:00
|
|
|
pub fn storage(&self) -> &Arc<BucketMapHolder<T>> {
|
2021-09-12 15:14:59 -07:00
|
|
|
&self.storage
|
|
|
|
}
|
2021-09-16 15:52:06 -07:00
|
|
|
|
|
|
|
// intended to execute in a bg thread
|
|
|
|
pub fn background(
|
|
|
|
storage: Arc<BucketMapHolder<T>>,
|
|
|
|
exit: Arc<AtomicBool>,
|
|
|
|
wait: Arc<WaitableCondvar>,
|
|
|
|
) {
|
|
|
|
loop {
|
|
|
|
wait.wait_timeout(Duration::from_millis(10000)); // account index stats every 10 s
|
|
|
|
if exit.load(Ordering::Relaxed) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
storage.stats.report_stats();
|
|
|
|
}
|
|
|
|
}
|
2021-09-12 15:14:59 -07:00
|
|
|
}
|