handling frames no longer is channel -> scheduler -> participant, but it's directly channel -> participant, removing a lock and a single bottleneck in the scheduler

This commit is contained in:
Marcel Märtens 2020-05-04 11:44:09 +02:00
parent 661060808d
commit 9074de533a
3 changed files with 51 additions and 83 deletions

View File

@ -1,6 +1,7 @@
use crate::{
metrics::NetworkMetrics,
protocols::Protocols,
scheduler::ConfigureInfo,
types::{
Cid, Frame, Pid, Sid, STREAM_ID_OFFSET1, STREAM_ID_OFFSET2, VELOREN_MAGIC_NUMBER,
VELOREN_NETWORK_VERSION,
@ -66,18 +67,13 @@ impl Channel {
self,
protocol: Protocols,
part_in_receiver: mpsc::UnboundedReceiver<Frame>,
part_out_sender: mpsc::UnboundedSender<(Cid, Frame)>,
configured_sender: mpsc::UnboundedSender<(Cid, Pid, Sid, oneshot::Sender<()>)>,
configured_sender: mpsc::UnboundedSender<ConfigureInfo>,
) {
let (prot_in_sender, prot_in_receiver) = mpsc::unbounded::<Frame>();
let (prot_out_sender, prot_out_receiver) = mpsc::unbounded::<Frame>();
let handler_future = self.frame_handler(
prot_in_receiver,
prot_out_sender,
part_out_sender,
configured_sender,
);
let handler_future =
self.frame_handler(prot_in_receiver, prot_out_sender, configured_sender);
match protocol {
Protocols::Tcp(tcp) => {
futures::join!(
@ -102,13 +98,18 @@ impl Channel {
&self,
mut frames: mpsc::UnboundedReceiver<Frame>,
mut frame_sender: mpsc::UnboundedSender<Frame>,
mut external_frame_sender: mpsc::UnboundedSender<(Cid, Frame)>,
mut configured_sender: mpsc::UnboundedSender<(Cid, Pid, Sid, oneshot::Sender<()>)>,
mut configured_sender: mpsc::UnboundedSender<(
Cid,
Pid,
Sid,
oneshot::Sender<mpsc::UnboundedSender<(Cid, Frame)>>,
)>,
) {
const ERR_S: &str = "Got A Raw Message, these are usually Debug Messages indicating that \
something went wrong on network layer and connection will be closed";
let mut pid_string = "".to_string();
let cid_string = self.cid.to_string();
let mut external_frame_sender: Option<mpsc::UnboundedSender<(Cid, Frame)>> = None;
while let Some(frame) = frames.next().await {
match frame {
Frame::Handshake {
@ -165,7 +166,7 @@ impl Channel {
.send((self.cid, pid, stream_id_offset, sender))
.await
.unwrap();
receiver.await.unwrap();
external_frame_sender = Some(receiver.await.unwrap());
//TODO: this is sync anyway, because we need to wait. so find a better way than
// there channels like direct method call... otherwise a
// frame might jump in before its officially configured yet
@ -200,7 +201,14 @@ impl Channel {
},
_ => {
trace!("forward frame");
external_frame_sender.send((self.cid, frame)).await.unwrap();
let pid = &pid_string;
match &mut external_frame_sender {
None => error!(
?pid,
"cannot forward frame, as channel isn't configured correctly!"
),
Some(sender) => sender.send((self.cid, frame)).await.unwrap(),
};
},
}
}

View File

@ -26,7 +26,7 @@ struct ControlChannels {
stream_open_receiver: mpsc::UnboundedReceiver<(Prio, Promises, oneshot::Sender<Stream>)>,
stream_opened_sender: mpsc::UnboundedSender<Stream>,
transfer_channel_receiver: mpsc::UnboundedReceiver<(Cid, mpsc::UnboundedSender<Frame>)>,
frame_recv_receiver: mpsc::UnboundedReceiver<Frame>,
frame_recv_receiver: mpsc::UnboundedReceiver<(Cid, Frame)>,
shutdown_api_receiver: mpsc::UnboundedReceiver<Sid>,
shutdown_api_sender: mpsc::UnboundedSender<Sid>,
send_outgoing: Arc<Mutex<std::sync::mpsc::Sender<(Prio, Pid, Sid, OutGoingMessage)>>>, //api
@ -67,7 +67,7 @@ impl BParticipant {
mpsc::UnboundedSender<(Prio, Promises, oneshot::Sender<Stream>)>,
mpsc::UnboundedReceiver<Stream>,
mpsc::UnboundedSender<(Cid, mpsc::UnboundedSender<Frame>)>,
mpsc::UnboundedSender<Frame>,
mpsc::UnboundedSender<(Cid, Frame)>,
mpsc::UnboundedSender<(Pid, Sid, Frame)>,
oneshot::Sender<()>,
) {
@ -76,7 +76,7 @@ impl BParticipant {
let (stream_opened_sender, stream_opened_receiver) = mpsc::unbounded::<Stream>();
let (transfer_channel_sender, transfer_channel_receiver) =
mpsc::unbounded::<(Cid, mpsc::UnboundedSender<Frame>)>();
let (frame_recv_sender, frame_recv_receiver) = mpsc::unbounded::<Frame>();
let (frame_recv_sender, frame_recv_receiver) = mpsc::unbounded::<(Cid, Frame)>();
let (shutdown_api_sender, shutdown_api_receiver) = mpsc::unbounded();
let (frame_send_sender, frame_send_receiver) = mpsc::unbounded::<(Pid, Sid, Frame)>();
let (shutdown_sender, shutdown_receiver) = oneshot::channel();
@ -162,7 +162,7 @@ impl BParticipant {
async fn handle_frames(
&self,
mut frame_recv_receiver: mpsc::UnboundedReceiver<Frame>,
mut frame_recv_receiver: mpsc::UnboundedReceiver<(Cid, Frame)>,
mut stream_opened_sender: mpsc::UnboundedSender<Stream>,
shutdown_api_sender: mpsc::UnboundedSender<Sid>,
send_outgoing: Arc<Mutex<std::sync::mpsc::Sender<(Prio, Pid, Sid, OutGoingMessage)>>>,
@ -172,7 +172,7 @@ impl BParticipant {
let mut messages = HashMap::new();
let pid_u128: u128 = self.remote_pid.into();
let pid_string = pid_u128.to_string();
while let Some(frame) = frame_recv_receiver.next().await {
while let Some((cid, frame)) = frame_recv_receiver.next().await {
debug!("handling frame");
match frame {
Frame::OpenStream {

View File

@ -34,7 +34,6 @@ use tracing_futures::Instrument;
type ParticipantInfo = (
mpsc::UnboundedSender<(Cid, mpsc::UnboundedSender<Frame>)>,
mpsc::UnboundedSender<Frame>,
mpsc::UnboundedSender<(Pid, Sid, Frame)>,
oneshot::Sender<()>,
);
@ -42,6 +41,12 @@ type UnknownChannelInfo = (
mpsc::UnboundedSender<Frame>,
Option<oneshot::Sender<io::Result<Participant>>>,
);
pub(crate) type ConfigureInfo = (
Cid,
Pid,
Sid,
oneshot::Sender<mpsc::UnboundedSender<(Cid, Frame)>>,
);
#[derive(Debug)]
struct ControlChannels {
@ -121,29 +126,18 @@ impl Scheduler {
}
pub async fn run(mut self) {
let (part_out_sender, part_out_receiver) = mpsc::unbounded::<(Cid, Frame)>();
let (configured_sender, configured_receiver) =
mpsc::unbounded::<(Cid, Pid, Sid, oneshot::Sender<()>)>();
let (configured_sender, configured_receiver) = mpsc::unbounded::<ConfigureInfo>();
let (disconnect_sender, disconnect_receiver) = mpsc::unbounded::<Pid>();
let (stream_finished_request_sender, stream_finished_request_receiver) = mpsc::unbounded();
let run_channels = self.run_channels.take().unwrap();
futures::join!(
self.listen_manager(
run_channels.listen_receiver,
part_out_sender.clone(),
configured_sender.clone(),
),
self.connect_manager(
run_channels.connect_receiver,
part_out_sender,
configured_sender,
),
self.listen_manager(run_channels.listen_receiver, configured_sender.clone(),),
self.connect_manager(run_channels.connect_receiver, configured_sender,),
self.disconnect_manager(disconnect_receiver,),
self.send_outgoing(),
self.stream_finished_manager(stream_finished_request_receiver),
self.shutdown_manager(run_channels.shutdown_receiver),
self.handle_frames(part_out_receiver),
self.channel_configurer(
run_channels.connected_sender,
configured_receiver,
@ -157,14 +151,12 @@ impl Scheduler {
async fn listen_manager(
&self,
listen_receiver: mpsc::UnboundedReceiver<(Address, oneshot::Sender<io::Result<()>>)>,
part_out_sender: mpsc::UnboundedSender<(Cid, Frame)>,
configured_sender: mpsc::UnboundedSender<(Cid, Pid, Sid, oneshot::Sender<()>)>,
configured_sender: mpsc::UnboundedSender<ConfigureInfo>,
) {
trace!("start listen_manager");
listen_receiver
.for_each_concurrent(None, |(address, result_sender)| {
let address = address.clone();
let part_out_sender = part_out_sender.clone();
let configured_sender = configured_sender.clone();
async move {
@ -185,7 +177,6 @@ impl Scheduler {
self.channel_creator(
address,
end_receiver,
part_out_sender.clone(),
configured_sender.clone(),
result_sender,
)
@ -202,8 +193,7 @@ impl Scheduler {
Address,
oneshot::Sender<io::Result<Participant>>,
)>,
part_out_sender: mpsc::UnboundedSender<(Cid, Frame)>,
configured_sender: mpsc::UnboundedSender<(Cid, Pid, Sid, oneshot::Sender<()>)>,
configured_sender: mpsc::UnboundedSender<ConfigureInfo>,
) {
trace!("start connect_manager");
while let Some((addr, pid_sender)) = connect_receiver.next().await {
@ -258,7 +248,6 @@ impl Scheduler {
};
self.init_protocol(
addr,
&part_out_sender,
&configured_sender,
protocol,
Some(pid_sender),
@ -277,7 +266,7 @@ impl Scheduler {
// 2. we need to close BParticipant, this will drop its senderns and receivers
// 3. Participant will try to access the BParticipant senders and receivers with
// their next api action, it will fail and be closed then.
if let Some((_, _, _, sender)) = self.participants.write().await.remove(&pid) {
if let Some((_, _, sender)) = self.participants.write().await.remove(&pid) {
sender.send(()).unwrap();
}
}
@ -298,7 +287,7 @@ impl Scheduler {
.await
.fill_frames(FRAMES_PER_TICK, &mut frames);
for (pid, sid, frame) in frames {
if let Some((_, _, sender, _)) = self.participants.write().await.get_mut(&pid) {
if let Some((_, sender, _)) = self.participants.write().await.get_mut(&pid) {
sender.send((pid, sid, frame)).await.unwrap();
}
}
@ -307,30 +296,13 @@ impl Scheduler {
trace!("stop send_outgoing");
}
//TODO Why is this done in scheduler when it just redirecty everything to
// participant?
async fn handle_frames(&self, mut part_out_receiver: mpsc::UnboundedReceiver<(Cid, Frame)>) {
trace!("start handle_frames");
while let Some((cid, frame)) = part_out_receiver.next().await {
trace!("handling frame");
if let Some(pid) = self.participant_from_channel.read().await.get(&cid) {
if let Some((_, sender, _, _)) = self.participants.write().await.get_mut(&pid) {
sender.send(frame).await.unwrap();
}
} else {
error!("dropping frame, unreachable, got a frame from a non existing channel");
}
}
trace!("stop handle_frames");
}
//TODO: //ERROR CHECK IF THIS SHOULD BE PUT IN A ASYNC FUNC WHICH IS SEND OVER
// TO CHANNEL OR NOT FOR RETURN VALUE!
async fn channel_configurer(
&self,
mut connected_sender: mpsc::UnboundedSender<Participant>,
mut receiver: mpsc::UnboundedReceiver<(Cid, Pid, Sid, oneshot::Sender<()>)>,
mut receiver: mpsc::UnboundedReceiver<ConfigureInfo>,
disconnect_sender: mpsc::UnboundedSender<Pid>,
prios_sender: std::sync::mpsc::Sender<(Prio, Pid, Sid, OutGoingMessage)>,
stream_finished_request_sender: mpsc::UnboundedSender<(Pid, Sid, oneshot::Sender<()>)>,
@ -387,7 +359,6 @@ impl Scheduler {
pid,
(
transfer_channel_receiver,
frame_recv_sender,
frame_send_sender,
shutdown_sender,
),
@ -398,13 +369,17 @@ impl Scheduler {
.run()
.instrument(tracing::info_span!("participant", ?pid)),
);
sender.send(frame_recv_sender).unwrap();
} else {
error!(
"2ND channel of participants opens, but we cannot verify that this is not \
a attack to "
)
);
//ERROR DEADLOCK AS NO SENDER HERE!
//sender.send(frame_recv_sender).unwrap();
}
sender.send(()).unwrap();
//From now on this CHANNEL can receiver other frames! move
// directly to participant!
}
}
trace!("stop channel_activator");
@ -461,7 +436,7 @@ impl Scheduler {
self.closed.store(true, Ordering::Relaxed);
debug!("shutting down all BParticipants gracefully");
let mut participants = self.participants.write().await;
for (pid, (_, _, _, sender)) in participants.drain() {
for (pid, (_, _, sender)) in participants.drain() {
trace!(?pid, "shutting down BParticipants");
sender.send(()).unwrap();
}
@ -472,8 +447,7 @@ impl Scheduler {
&self,
addr: Address,
end_receiver: oneshot::Receiver<()>,
part_out_sender: mpsc::UnboundedSender<(Cid, Frame)>,
configured_sender: mpsc::UnboundedSender<(Cid, Pid, Sid, oneshot::Sender<()>)>,
configured_sender: mpsc::UnboundedSender<ConfigureInfo>,
result_sender: oneshot::Sender<io::Result<()>>,
) {
info!(?addr, "start up channel creator");
@ -505,7 +479,6 @@ impl Scheduler {
info!("Accepting Tcp from: {}", stream.peer_addr().unwrap());
self.init_protocol(
addr,
&part_out_sender,
&configured_sender,
Protocols::Tcp(TcpProtocol::new(stream, self.metrics.clone())),
None,
@ -552,15 +525,8 @@ impl Scheduler {
self.metrics.clone(),
udp_data_receiver,
));
self.init_protocol(
addr,
&part_out_sender,
&configured_sender,
protocol,
None,
true,
)
.await;
self.init_protocol(addr, &configured_sender, protocol, None, true)
.await;
}
let udp_data_sender = listeners.get_mut(&remote_addr).unwrap();
udp_data_sender.send(datavec).await.unwrap();
@ -598,8 +564,7 @@ impl Scheduler {
async fn init_protocol(
&self,
addr: std::net::SocketAddr,
part_out_sender: &mpsc::UnboundedSender<(Cid, Frame)>,
configured_sender: &mpsc::UnboundedSender<(Cid, Pid, Sid, oneshot::Sender<()>)>,
configured_sender: &mpsc::UnboundedSender<ConfigureInfo>,
protocol: Protocols,
pid_sender: Option<oneshot::Sender<io::Result<Participant>>>,
send_handshake: bool,
@ -618,12 +583,7 @@ impl Scheduler {
}
self.pool.spawn_ok(
channel
.run(
protocol,
part_in_receiver,
part_out_sender.clone(),
configured_sender.clone(),
)
.run(protocol, part_in_receiver, configured_sender.clone())
.instrument(tracing::info_span!("channel", ?addr)),
);
self.unknown_channels