2018-08-09 12:03:34 -07:00
|
|
|
//! The `retransmit_stage` retransmits blobs between validators
|
2018-06-13 21:52:23 -07:00
|
|
|
|
2018-08-09 13:41:21 -07:00
|
|
|
use counter::Counter;
|
2018-06-13 21:52:23 -07:00
|
|
|
use crdt::Crdt;
|
2018-08-09 13:41:21 -07:00
|
|
|
use log::Level;
|
2018-06-27 11:33:56 -07:00
|
|
|
use packet::BlobRecycler;
|
2018-08-09 13:41:21 -07:00
|
|
|
use result::{Error, Result};
|
2018-07-03 21:14:08 -07:00
|
|
|
use service::Service;
|
2018-06-13 21:52:23 -07:00
|
|
|
use std::net::UdpSocket;
|
2018-08-09 13:41:21 -07:00
|
|
|
use std::sync::atomic::AtomicUsize;
|
2018-06-13 21:52:23 -07:00
|
|
|
use std::sync::mpsc::channel;
|
2018-08-09 13:41:21 -07:00
|
|
|
use std::sync::mpsc::RecvTimeoutError;
|
2018-06-13 21:52:23 -07:00
|
|
|
use std::sync::{Arc, RwLock};
|
2018-08-09 14:17:50 -07:00
|
|
|
use std::thread::{self, Builder, JoinHandle};
|
2018-08-09 13:41:21 -07:00
|
|
|
use std::time::Duration;
|
2018-08-09 12:31:34 -07:00
|
|
|
use streamer::BlobReceiver;
|
|
|
|
use window::{self, SharedWindow};
|
2018-06-13 21:52:23 -07:00
|
|
|
|
2018-08-09 13:41:21 -07:00
|
|
|
fn retransmit(
|
|
|
|
crdt: &Arc<RwLock<Crdt>>,
|
|
|
|
recycler: &BlobRecycler,
|
|
|
|
r: &BlobReceiver,
|
|
|
|
sock: &UdpSocket,
|
|
|
|
) -> Result<()> {
|
|
|
|
let timer = Duration::new(1, 0);
|
|
|
|
let mut dq = r.recv_timeout(timer)?;
|
|
|
|
while let Ok(mut nq) = r.try_recv() {
|
|
|
|
dq.append(&mut nq);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
for b in &dq {
|
|
|
|
Crdt::retransmit(&crdt, b, sock)?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while let Some(b) = dq.pop_front() {
|
|
|
|
recycler.recycle(b);
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Service to retransmit messages from the leader to layer 1 nodes.
|
|
|
|
/// See `crdt` for network layer definitions.
|
|
|
|
/// # Arguments
|
|
|
|
/// * `sock` - Socket to read from. Read timeout is set to 1.
|
|
|
|
/// * `exit` - Boolean to signal system exit.
|
|
|
|
/// * `crdt` - This structure needs to be updated and populated by the bank and via gossip.
|
|
|
|
/// * `recycler` - Blob recycler.
|
|
|
|
/// * `r` - Receive channel for blobs to be retransmitted to all the layer 1 nodes.
|
2018-08-09 14:17:50 -07:00
|
|
|
fn retransmitter(
|
2018-08-28 16:32:40 -07:00
|
|
|
sock: Arc<UdpSocket>,
|
2018-08-09 13:41:21 -07:00
|
|
|
crdt: Arc<RwLock<Crdt>>,
|
|
|
|
recycler: BlobRecycler,
|
|
|
|
r: BlobReceiver,
|
|
|
|
) -> JoinHandle<()> {
|
|
|
|
Builder::new()
|
|
|
|
.name("solana-retransmitter".to_string())
|
|
|
|
.spawn(move || {
|
|
|
|
trace!("retransmitter started");
|
|
|
|
loop {
|
|
|
|
if let Err(e) = retransmit(&crdt, &recycler, &r, &sock) {
|
|
|
|
match e {
|
|
|
|
Error::RecvTimeoutError(RecvTimeoutError::Disconnected) => break,
|
|
|
|
Error::RecvTimeoutError(RecvTimeoutError::Timeout) => (),
|
|
|
|
_ => {
|
|
|
|
inc_new_counter_info!("streamer-retransmit-error", 1, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
trace!("exiting retransmitter");
|
|
|
|
})
|
|
|
|
.unwrap()
|
|
|
|
}
|
|
|
|
|
2018-08-09 12:03:34 -07:00
|
|
|
pub struct RetransmitStage {
|
2018-07-03 21:14:08 -07:00
|
|
|
thread_hdls: Vec<JoinHandle<()>>,
|
2018-06-13 21:52:23 -07:00
|
|
|
}
|
|
|
|
|
2018-08-09 12:03:34 -07:00
|
|
|
impl RetransmitStage {
|
2018-06-13 21:52:23 -07:00
|
|
|
pub fn new(
|
2018-07-11 13:40:46 -07:00
|
|
|
crdt: &Arc<RwLock<Crdt>>,
|
2018-07-30 16:56:01 -07:00
|
|
|
window: SharedWindow,
|
2018-06-27 12:35:58 -07:00
|
|
|
entry_height: u64,
|
2018-08-28 16:32:40 -07:00
|
|
|
retransmit_socket: Arc<UdpSocket>,
|
2018-07-11 13:40:46 -07:00
|
|
|
blob_recycler: &BlobRecycler,
|
2018-06-27 11:33:56 -07:00
|
|
|
fetch_stage_receiver: BlobReceiver,
|
2018-07-02 14:45:16 -07:00
|
|
|
) -> (Self, BlobReceiver) {
|
2018-06-13 21:52:23 -07:00
|
|
|
let (retransmit_sender, retransmit_receiver) = channel();
|
|
|
|
|
2018-08-09 13:41:21 -07:00
|
|
|
let t_retransmit = retransmitter(
|
2018-06-13 21:52:23 -07:00
|
|
|
retransmit_socket,
|
|
|
|
crdt.clone(),
|
|
|
|
blob_recycler.clone(),
|
|
|
|
retransmit_receiver,
|
|
|
|
);
|
|
|
|
let (blob_sender, blob_receiver) = channel();
|
2018-08-09 12:31:34 -07:00
|
|
|
let t_window = window::window(
|
2018-06-13 21:52:23 -07:00
|
|
|
crdt.clone(),
|
|
|
|
window,
|
2018-06-27 12:35:58 -07:00
|
|
|
entry_height,
|
2018-06-13 21:52:23 -07:00
|
|
|
blob_recycler.clone(),
|
|
|
|
fetch_stage_receiver,
|
|
|
|
blob_sender,
|
|
|
|
retransmit_sender,
|
|
|
|
);
|
|
|
|
let thread_hdls = vec![t_retransmit, t_window];
|
|
|
|
|
2018-08-09 12:03:34 -07:00
|
|
|
(RetransmitStage { thread_hdls }, blob_receiver)
|
2018-06-13 21:52:23 -07:00
|
|
|
}
|
|
|
|
}
|
2018-07-03 21:14:08 -07:00
|
|
|
|
2018-08-09 12:03:34 -07:00
|
|
|
impl Service for RetransmitStage {
|
2018-07-03 21:14:08 -07:00
|
|
|
fn thread_hdls(self) -> Vec<JoinHandle<()>> {
|
|
|
|
self.thread_hdls
|
|
|
|
}
|
|
|
|
|
|
|
|
fn join(self) -> thread::Result<()> {
|
|
|
|
for thread_hdl in self.thread_hdls() {
|
|
|
|
thread_hdl.join()?;
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|