solana/ledger/src/entry_notifier_service.rs

79 lines
2.2 KiB
Rust

use {
crate::entry_notifier_interface::EntryNotifierLock,
crossbeam_channel::{unbounded, Receiver, RecvTimeoutError, Sender},
solana_entry::entry::EntrySummary,
solana_sdk::clock::Slot,
std::{
sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
thread::{self, Builder, JoinHandle},
time::Duration,
},
};
pub struct EntryNotification {
pub slot: Slot,
pub index: usize,
pub entry: EntrySummary,
}
pub type EntryNotifierSender = Sender<EntryNotification>;
pub type EntryNotifierReceiver = Receiver<EntryNotification>;
pub struct EntryNotifierService {
sender: EntryNotifierSender,
thread_hdl: JoinHandle<()>,
}
impl EntryNotifierService {
pub fn new(entry_notifier: EntryNotifierLock, exit: &Arc<AtomicBool>) -> Self {
let exit = exit.clone();
let (entry_notification_sender, entry_notification_receiver) = unbounded();
let thread_hdl = Builder::new()
.name("solEntryNotif".to_string())
.spawn(move || loop {
if exit.load(Ordering::Relaxed) {
break;
}
if let Err(RecvTimeoutError::Disconnected) =
Self::notify_entry(&entry_notification_receiver, entry_notifier.clone())
{
break;
}
})
.unwrap();
Self {
sender: entry_notification_sender,
thread_hdl,
}
}
fn notify_entry(
entry_notification_receiver: &EntryNotifierReceiver,
entry_notifier: EntryNotifierLock,
) -> Result<(), RecvTimeoutError> {
let EntryNotification { slot, index, entry } =
entry_notification_receiver.recv_timeout(Duration::from_secs(1))?;
entry_notifier
.write()
.unwrap()
.notify_entry(slot, index, &entry);
Ok(())
}
pub fn sender(&self) -> &EntryNotifierSender {
&self.sender
}
pub fn sender_cloned(&self) -> EntryNotifierSender {
self.sender.clone()
}
pub fn join(self) -> thread::Result<()> {
self.thread_hdl.join()
}
}