2020-03-22 13:47:21 +00:00
|
|
|
use crate::{
|
|
|
|
api::Stream,
|
2020-05-04 13:27:58 +00:00
|
|
|
channel::Channel,
|
Fixing the DEADLOCK in handshake -> channel creation
- this bug was initially called imbris bug, as it happened on his runners and i couldn't reproduce it locally at fist :)
- When in a Handshake a seperate mpsc::Channel was created for (Cid, Frame) transport
however the protocol could already catch non handshake data any more and push in into this
mpsc::Channel.
Then this channel got dropped and a fresh one was created for the network::Channel.
These droped Frames are ofc a BUG!
I tried multiple things to solve this:
- dont create a new mpsc::Channel, but instead bind it to the Protocol itself and always use 1.
This would work theoretically, but in bParticipant side we are using 1 mpsc::Channel<(Cid, Frame)>
to handle ALL the network::channel.
If now ever Protocol would have it's own, and with that every network::Channel had it's own it would no longer work out
Bad Idea...
- using the first method but creating the mpsc::Channel inside the scheduler instead protocol neither works, as the
scheduler doesnt know the remote_pid yet
- i dont want a hack to say the protocol only listen to 2 messages and then stop no matter what
So i switched over to the simply method now:
- Do everything like before with 2 mpsc::Channels
- after the handshake. close the receiver and listen for all remaining (cid, frame) combinations
- when starting the channel, reapply them to the new sender/listener combination
- added tracing
- switched Protocol RwLock to Mutex, as it's only ever 1
- Additionally changed the layout and introduces the c2w_frame_s and w2s_cid_frame_s name schema
- Fixed a bug in scheduler which WOULD cause a DEADLOCK if handshake would fail
- fixd a but in api_send_send_main, i need to store the stream_p otherwise it's immeadiatly closed and a stream_a.send() isn't guaranteed
- add extra test to verify that a send message is received even if the Stream is already closed
- changed OutGoing to Outgoing
- fixed a bug that `metrics.tick()` was never called
- removed 2 unused nightly features and added `deny_code`
2020-06-03 07:13:00 +00:00
|
|
|
message::{IncomingMessage, MessageBuffer, OutgoingMessage},
|
2020-05-24 23:17:03 +00:00
|
|
|
metrics::{NetworkMetrics, PidCidFrameCache},
|
2020-05-22 14:00:08 +00:00
|
|
|
prios::PrioManager,
|
2020-05-04 13:27:58 +00:00
|
|
|
protocols::Protocols,
|
2020-04-08 14:26:42 +00:00
|
|
|
types::{Cid, Frame, Pid, Prio, Promises, Sid},
|
2020-03-22 13:47:21 +00:00
|
|
|
};
|
|
|
|
use async_std::sync::RwLock;
|
|
|
|
use futures::{
|
|
|
|
channel::{mpsc, oneshot},
|
2020-04-08 14:26:42 +00:00
|
|
|
future::FutureExt,
|
|
|
|
select,
|
2020-03-22 13:47:21 +00:00
|
|
|
sink::SinkExt,
|
|
|
|
stream::StreamExt,
|
|
|
|
};
|
|
|
|
use std::{
|
2020-05-22 14:00:08 +00:00
|
|
|
collections::{HashMap, VecDeque},
|
2020-04-08 14:26:42 +00:00
|
|
|
sync::{
|
2020-05-22 14:00:08 +00:00
|
|
|
atomic::{AtomicBool, AtomicUsize, Ordering},
|
|
|
|
Arc,
|
2020-04-08 14:26:42 +00:00
|
|
|
},
|
2020-05-27 15:58:57 +00:00
|
|
|
time::{Duration, Instant},
|
2020-03-22 13:47:21 +00:00
|
|
|
};
|
|
|
|
use tracing::*;
|
|
|
|
|
2020-05-15 12:29:17 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
struct ChannelInfo {
|
|
|
|
cid: Cid,
|
2020-05-27 15:58:57 +00:00
|
|
|
cid_string: String, //optimisationmetrics
|
2020-05-15 12:29:17 +00:00
|
|
|
b2w_frame_s: mpsc::UnboundedSender<Frame>,
|
|
|
|
b2r_read_shutdown: oneshot::Sender<()>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
struct StreamInfo {
|
|
|
|
prio: Prio,
|
|
|
|
promises: Promises,
|
Fixing the DEADLOCK in handshake -> channel creation
- this bug was initially called imbris bug, as it happened on his runners and i couldn't reproduce it locally at fist :)
- When in a Handshake a seperate mpsc::Channel was created for (Cid, Frame) transport
however the protocol could already catch non handshake data any more and push in into this
mpsc::Channel.
Then this channel got dropped and a fresh one was created for the network::Channel.
These droped Frames are ofc a BUG!
I tried multiple things to solve this:
- dont create a new mpsc::Channel, but instead bind it to the Protocol itself and always use 1.
This would work theoretically, but in bParticipant side we are using 1 mpsc::Channel<(Cid, Frame)>
to handle ALL the network::channel.
If now ever Protocol would have it's own, and with that every network::Channel had it's own it would no longer work out
Bad Idea...
- using the first method but creating the mpsc::Channel inside the scheduler instead protocol neither works, as the
scheduler doesnt know the remote_pid yet
- i dont want a hack to say the protocol only listen to 2 messages and then stop no matter what
So i switched over to the simply method now:
- Do everything like before with 2 mpsc::Channels
- after the handshake. close the receiver and listen for all remaining (cid, frame) combinations
- when starting the channel, reapply them to the new sender/listener combination
- added tracing
- switched Protocol RwLock to Mutex, as it's only ever 1
- Additionally changed the layout and introduces the c2w_frame_s and w2s_cid_frame_s name schema
- Fixed a bug in scheduler which WOULD cause a DEADLOCK if handshake would fail
- fixd a but in api_send_send_main, i need to store the stream_p otherwise it's immeadiatly closed and a stream_a.send() isn't guaranteed
- add extra test to verify that a send message is received even if the Stream is already closed
- changed OutGoing to Outgoing
- fixed a bug that `metrics.tick()` was never called
- removed 2 unused nightly features and added `deny_code`
2020-06-03 07:13:00 +00:00
|
|
|
b2a_msg_recv_s: mpsc::UnboundedSender<IncomingMessage>,
|
2020-05-15 12:29:17 +00:00
|
|
|
closed: Arc<AtomicBool>,
|
|
|
|
}
|
|
|
|
|
2020-03-22 13:47:21 +00:00
|
|
|
#[derive(Debug)]
|
2020-06-08 09:47:39 +00:00
|
|
|
#[allow(clippy::type_complexity)]
|
2020-03-22 13:47:21 +00:00
|
|
|
struct ControlChannels {
|
2020-05-15 12:29:17 +00:00
|
|
|
a2b_steam_open_r: mpsc::UnboundedReceiver<(Prio, Promises, oneshot::Sender<Stream>)>,
|
|
|
|
b2a_stream_opened_s: mpsc::UnboundedSender<Stream>,
|
Fixing the DEADLOCK in handshake -> channel creation
- this bug was initially called imbris bug, as it happened on his runners and i couldn't reproduce it locally at fist :)
- When in a Handshake a seperate mpsc::Channel was created for (Cid, Frame) transport
however the protocol could already catch non handshake data any more and push in into this
mpsc::Channel.
Then this channel got dropped and a fresh one was created for the network::Channel.
These droped Frames are ofc a BUG!
I tried multiple things to solve this:
- dont create a new mpsc::Channel, but instead bind it to the Protocol itself and always use 1.
This would work theoretically, but in bParticipant side we are using 1 mpsc::Channel<(Cid, Frame)>
to handle ALL the network::channel.
If now ever Protocol would have it's own, and with that every network::Channel had it's own it would no longer work out
Bad Idea...
- using the first method but creating the mpsc::Channel inside the scheduler instead protocol neither works, as the
scheduler doesnt know the remote_pid yet
- i dont want a hack to say the protocol only listen to 2 messages and then stop no matter what
So i switched over to the simply method now:
- Do everything like before with 2 mpsc::Channels
- after the handshake. close the receiver and listen for all remaining (cid, frame) combinations
- when starting the channel, reapply them to the new sender/listener combination
- added tracing
- switched Protocol RwLock to Mutex, as it's only ever 1
- Additionally changed the layout and introduces the c2w_frame_s and w2s_cid_frame_s name schema
- Fixed a bug in scheduler which WOULD cause a DEADLOCK if handshake would fail
- fixd a but in api_send_send_main, i need to store the stream_p otherwise it's immeadiatly closed and a stream_a.send() isn't guaranteed
- add extra test to verify that a send message is received even if the Stream is already closed
- changed OutGoing to Outgoing
- fixed a bug that `metrics.tick()` was never called
- removed 2 unused nightly features and added `deny_code`
2020-06-03 07:13:00 +00:00
|
|
|
s2b_create_channel_r:
|
|
|
|
mpsc::UnboundedReceiver<(Cid, Sid, Protocols, Vec<(Cid, Frame)>, oneshot::Sender<()>)>,
|
2020-05-15 12:29:17 +00:00
|
|
|
a2b_close_stream_r: mpsc::UnboundedReceiver<Sid>,
|
|
|
|
a2b_close_stream_s: mpsc::UnboundedSender<Sid>,
|
|
|
|
s2b_shutdown_bparticipant_r: oneshot::Receiver<oneshot::Sender<async_std::io::Result<()>>>, /* own */
|
2020-03-22 13:47:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct BParticipant {
|
|
|
|
remote_pid: Pid,
|
2020-05-24 23:17:03 +00:00
|
|
|
remote_pid_string: String, //optimisation
|
2020-03-22 13:47:21 +00:00
|
|
|
offset_sid: Sid,
|
2020-05-15 12:29:17 +00:00
|
|
|
channels: Arc<RwLock<Vec<ChannelInfo>>>,
|
|
|
|
streams: RwLock<HashMap<Sid, StreamInfo>>,
|
|
|
|
running_mgr: AtomicUsize,
|
2020-03-22 13:47:21 +00:00
|
|
|
run_channels: Option<ControlChannels>,
|
2020-04-24 10:56:04 +00:00
|
|
|
metrics: Arc<NetworkMetrics>,
|
2020-03-22 13:47:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl BParticipant {
|
2020-06-08 09:47:39 +00:00
|
|
|
#[allow(clippy::type_complexity)]
|
2020-03-22 13:47:21 +00:00
|
|
|
pub(crate) fn new(
|
|
|
|
remote_pid: Pid,
|
|
|
|
offset_sid: Sid,
|
2020-04-24 10:56:04 +00:00
|
|
|
metrics: Arc<NetworkMetrics>,
|
2020-03-22 13:47:21 +00:00
|
|
|
) -> (
|
|
|
|
Self,
|
|
|
|
mpsc::UnboundedSender<(Prio, Promises, oneshot::Sender<Stream>)>,
|
|
|
|
mpsc::UnboundedReceiver<Stream>,
|
Fixing the DEADLOCK in handshake -> channel creation
- this bug was initially called imbris bug, as it happened on his runners and i couldn't reproduce it locally at fist :)
- When in a Handshake a seperate mpsc::Channel was created for (Cid, Frame) transport
however the protocol could already catch non handshake data any more and push in into this
mpsc::Channel.
Then this channel got dropped and a fresh one was created for the network::Channel.
These droped Frames are ofc a BUG!
I tried multiple things to solve this:
- dont create a new mpsc::Channel, but instead bind it to the Protocol itself and always use 1.
This would work theoretically, but in bParticipant side we are using 1 mpsc::Channel<(Cid, Frame)>
to handle ALL the network::channel.
If now ever Protocol would have it's own, and with that every network::Channel had it's own it would no longer work out
Bad Idea...
- using the first method but creating the mpsc::Channel inside the scheduler instead protocol neither works, as the
scheduler doesnt know the remote_pid yet
- i dont want a hack to say the protocol only listen to 2 messages and then stop no matter what
So i switched over to the simply method now:
- Do everything like before with 2 mpsc::Channels
- after the handshake. close the receiver and listen for all remaining (cid, frame) combinations
- when starting the channel, reapply them to the new sender/listener combination
- added tracing
- switched Protocol RwLock to Mutex, as it's only ever 1
- Additionally changed the layout and introduces the c2w_frame_s and w2s_cid_frame_s name schema
- Fixed a bug in scheduler which WOULD cause a DEADLOCK if handshake would fail
- fixd a but in api_send_send_main, i need to store the stream_p otherwise it's immeadiatly closed and a stream_a.send() isn't guaranteed
- add extra test to verify that a send message is received even if the Stream is already closed
- changed OutGoing to Outgoing
- fixed a bug that `metrics.tick()` was never called
- removed 2 unused nightly features and added `deny_code`
2020-06-03 07:13:00 +00:00
|
|
|
mpsc::UnboundedSender<(Cid, Sid, Protocols, Vec<(Cid, Frame)>, oneshot::Sender<()>)>,
|
2020-05-15 12:29:17 +00:00
|
|
|
oneshot::Sender<oneshot::Sender<async_std::io::Result<()>>>,
|
2020-03-22 13:47:21 +00:00
|
|
|
) {
|
2020-05-15 12:29:17 +00:00
|
|
|
let (a2b_steam_open_s, a2b_steam_open_r) =
|
2020-03-22 13:47:21 +00:00
|
|
|
mpsc::unbounded::<(Prio, Promises, oneshot::Sender<Stream>)>();
|
2020-05-15 12:29:17 +00:00
|
|
|
let (b2a_stream_opened_s, b2a_stream_opened_r) = mpsc::unbounded::<Stream>();
|
|
|
|
let (a2b_close_stream_s, a2b_close_stream_r) = mpsc::unbounded();
|
|
|
|
let (s2b_shutdown_bparticipant_s, s2b_shutdown_bparticipant_r) = oneshot::channel();
|
Fixing the DEADLOCK in handshake -> channel creation
- this bug was initially called imbris bug, as it happened on his runners and i couldn't reproduce it locally at fist :)
- When in a Handshake a seperate mpsc::Channel was created for (Cid, Frame) transport
however the protocol could already catch non handshake data any more and push in into this
mpsc::Channel.
Then this channel got dropped and a fresh one was created for the network::Channel.
These droped Frames are ofc a BUG!
I tried multiple things to solve this:
- dont create a new mpsc::Channel, but instead bind it to the Protocol itself and always use 1.
This would work theoretically, but in bParticipant side we are using 1 mpsc::Channel<(Cid, Frame)>
to handle ALL the network::channel.
If now ever Protocol would have it's own, and with that every network::Channel had it's own it would no longer work out
Bad Idea...
- using the first method but creating the mpsc::Channel inside the scheduler instead protocol neither works, as the
scheduler doesnt know the remote_pid yet
- i dont want a hack to say the protocol only listen to 2 messages and then stop no matter what
So i switched over to the simply method now:
- Do everything like before with 2 mpsc::Channels
- after the handshake. close the receiver and listen for all remaining (cid, frame) combinations
- when starting the channel, reapply them to the new sender/listener combination
- added tracing
- switched Protocol RwLock to Mutex, as it's only ever 1
- Additionally changed the layout and introduces the c2w_frame_s and w2s_cid_frame_s name schema
- Fixed a bug in scheduler which WOULD cause a DEADLOCK if handshake would fail
- fixd a but in api_send_send_main, i need to store the stream_p otherwise it's immeadiatly closed and a stream_a.send() isn't guaranteed
- add extra test to verify that a send message is received even if the Stream is already closed
- changed OutGoing to Outgoing
- fixed a bug that `metrics.tick()` was never called
- removed 2 unused nightly features and added `deny_code`
2020-06-03 07:13:00 +00:00
|
|
|
let (s2b_create_channel_s, s2b_create_channel_r) = mpsc::unbounded();
|
2020-03-22 13:47:21 +00:00
|
|
|
|
|
|
|
let run_channels = Some(ControlChannels {
|
2020-05-15 12:29:17 +00:00
|
|
|
a2b_steam_open_r,
|
|
|
|
b2a_stream_opened_s,
|
|
|
|
s2b_create_channel_r,
|
|
|
|
a2b_close_stream_r,
|
|
|
|
a2b_close_stream_s,
|
|
|
|
s2b_shutdown_bparticipant_r,
|
2020-03-22 13:47:21 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
(
|
|
|
|
Self {
|
|
|
|
remote_pid,
|
2020-05-24 23:17:03 +00:00
|
|
|
remote_pid_string: remote_pid.to_string(),
|
2020-03-22 13:47:21 +00:00
|
|
|
offset_sid,
|
2020-05-04 13:27:58 +00:00
|
|
|
channels: Arc::new(RwLock::new(vec![])),
|
2020-03-22 13:47:21 +00:00
|
|
|
streams: RwLock::new(HashMap::new()),
|
2020-05-15 12:29:17 +00:00
|
|
|
running_mgr: AtomicUsize::new(0),
|
2020-03-22 13:47:21 +00:00
|
|
|
run_channels,
|
2020-04-24 10:56:04 +00:00
|
|
|
metrics,
|
2020-03-22 13:47:21 +00:00
|
|
|
},
|
2020-05-15 12:29:17 +00:00
|
|
|
a2b_steam_open_s,
|
|
|
|
b2a_stream_opened_r,
|
|
|
|
s2b_create_channel_s,
|
|
|
|
s2b_shutdown_bparticipant_s,
|
2020-03-22 13:47:21 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2020-05-27 15:58:57 +00:00
|
|
|
pub async fn run(mut self, b2s_prio_statistic_s: mpsc::UnboundedSender<(Pid, u64, u64)>) {
|
2020-04-08 14:26:42 +00:00
|
|
|
//those managers that listen on api::Participant need an additional oneshot for
|
|
|
|
// shutdown scenario, those handled by scheduler will be closed by it.
|
2020-05-22 14:00:08 +00:00
|
|
|
let (shutdown_send_mgr_sender, shutdown_send_mgr_receiver) = oneshot::channel();
|
2020-05-15 12:29:17 +00:00
|
|
|
let (shutdown_stream_close_mgr_sender, shutdown_stream_close_mgr_receiver) =
|
2020-04-08 14:26:42 +00:00
|
|
|
oneshot::channel();
|
2020-05-22 14:00:08 +00:00
|
|
|
let (shutdown_open_mgr_sender, shutdown_open_mgr_receiver) = oneshot::channel();
|
|
|
|
let (b2b_prios_flushed_s, b2b_prios_flushed_r) = oneshot::channel();
|
2020-05-15 12:29:17 +00:00
|
|
|
let (w2b_frames_s, w2b_frames_r) = mpsc::unbounded::<(Cid, Frame)>();
|
2020-05-27 15:58:57 +00:00
|
|
|
let (prios, a2p_msg_s, b2p_notify_empty_stream_s) =
|
|
|
|
PrioManager::new(self.metrics.clone(), self.remote_pid_string.clone());
|
2020-04-08 14:26:42 +00:00
|
|
|
|
2020-03-22 13:47:21 +00:00
|
|
|
let run_channels = self.run_channels.take().unwrap();
|
|
|
|
futures::join!(
|
2020-05-15 12:29:17 +00:00
|
|
|
self.open_mgr(
|
|
|
|
run_channels.a2b_steam_open_r,
|
|
|
|
run_channels.a2b_close_stream_s.clone(),
|
2020-05-22 14:00:08 +00:00
|
|
|
a2p_msg_s.clone(),
|
2020-05-15 12:29:17 +00:00
|
|
|
shutdown_open_mgr_receiver,
|
2020-03-22 13:47:21 +00:00
|
|
|
),
|
2020-05-15 12:29:17 +00:00
|
|
|
self.handle_frames_mgr(
|
|
|
|
w2b_frames_r,
|
|
|
|
run_channels.b2a_stream_opened_s,
|
|
|
|
run_channels.a2b_close_stream_s,
|
2020-05-22 14:00:08 +00:00
|
|
|
a2p_msg_s.clone(),
|
2020-05-04 13:27:58 +00:00
|
|
|
),
|
Fixing the DEADLOCK in handshake -> channel creation
- this bug was initially called imbris bug, as it happened on his runners and i couldn't reproduce it locally at fist :)
- When in a Handshake a seperate mpsc::Channel was created for (Cid, Frame) transport
however the protocol could already catch non handshake data any more and push in into this
mpsc::Channel.
Then this channel got dropped and a fresh one was created for the network::Channel.
These droped Frames are ofc a BUG!
I tried multiple things to solve this:
- dont create a new mpsc::Channel, but instead bind it to the Protocol itself and always use 1.
This would work theoretically, but in bParticipant side we are using 1 mpsc::Channel<(Cid, Frame)>
to handle ALL the network::channel.
If now ever Protocol would have it's own, and with that every network::Channel had it's own it would no longer work out
Bad Idea...
- using the first method but creating the mpsc::Channel inside the scheduler instead protocol neither works, as the
scheduler doesnt know the remote_pid yet
- i dont want a hack to say the protocol only listen to 2 messages and then stop no matter what
So i switched over to the simply method now:
- Do everything like before with 2 mpsc::Channels
- after the handshake. close the receiver and listen for all remaining (cid, frame) combinations
- when starting the channel, reapply them to the new sender/listener combination
- added tracing
- switched Protocol RwLock to Mutex, as it's only ever 1
- Additionally changed the layout and introduces the c2w_frame_s and w2s_cid_frame_s name schema
- Fixed a bug in scheduler which WOULD cause a DEADLOCK if handshake would fail
- fixd a but in api_send_send_main, i need to store the stream_p otherwise it's immeadiatly closed and a stream_a.send() isn't guaranteed
- add extra test to verify that a send message is received even if the Stream is already closed
- changed OutGoing to Outgoing
- fixed a bug that `metrics.tick()` was never called
- removed 2 unused nightly features and added `deny_code`
2020-06-03 07:13:00 +00:00
|
|
|
self.create_channel_mgr(run_channels.s2b_create_channel_r, w2b_frames_s),
|
2020-05-27 15:58:57 +00:00
|
|
|
self.send_mgr(
|
|
|
|
prios,
|
|
|
|
shutdown_send_mgr_receiver,
|
|
|
|
b2b_prios_flushed_s,
|
|
|
|
b2s_prio_statistic_s
|
|
|
|
),
|
2020-05-15 12:29:17 +00:00
|
|
|
self.stream_close_mgr(
|
|
|
|
run_channels.a2b_close_stream_r,
|
|
|
|
shutdown_stream_close_mgr_receiver,
|
2020-05-26 13:06:03 +00:00
|
|
|
b2p_notify_empty_stream_s,
|
2020-04-08 14:26:42 +00:00
|
|
|
),
|
2020-05-15 12:29:17 +00:00
|
|
|
self.participant_shutdown_mgr(
|
|
|
|
run_channels.s2b_shutdown_bparticipant_r,
|
2020-05-22 14:00:08 +00:00
|
|
|
b2b_prios_flushed_r,
|
|
|
|
vec!(
|
|
|
|
shutdown_send_mgr_sender,
|
|
|
|
shutdown_open_mgr_sender,
|
|
|
|
shutdown_stream_close_mgr_sender
|
|
|
|
)
|
2020-04-08 14:26:42 +00:00
|
|
|
),
|
2020-03-22 13:47:21 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-05-22 14:00:08 +00:00
|
|
|
async fn send_mgr(
|
|
|
|
&self,
|
|
|
|
mut prios: PrioManager,
|
|
|
|
mut shutdown_send_mgr_receiver: oneshot::Receiver<()>,
|
|
|
|
b2b_prios_flushed_s: oneshot::Sender<()>,
|
2020-05-27 15:58:57 +00:00
|
|
|
mut b2s_prio_statistic_s: mpsc::UnboundedSender<(Pid, u64, u64)>,
|
2020-05-22 14:00:08 +00:00
|
|
|
) {
|
|
|
|
//This time equals the MINIMUM Latency in average, so keep it down and //Todo:
|
|
|
|
// make it configureable or switch to await E.g. Prio 0 = await, prio 50
|
|
|
|
// wait for more messages
|
2020-05-27 15:58:57 +00:00
|
|
|
const TICK_TIME: Duration = Duration::from_millis(10);
|
2020-05-22 14:00:08 +00:00
|
|
|
const FRAMES_PER_TICK: usize = 10005;
|
|
|
|
self.running_mgr.fetch_add(1, Ordering::Relaxed);
|
|
|
|
let mut closing_up = false;
|
|
|
|
trace!("start send_mgr");
|
2020-05-24 23:17:03 +00:00
|
|
|
let mut send_cache =
|
|
|
|
PidCidFrameCache::new(self.metrics.frames_out_total.clone(), self.remote_pid);
|
2020-05-22 14:00:08 +00:00
|
|
|
//while !self.closed.load(Ordering::Relaxed) {
|
|
|
|
loop {
|
|
|
|
let mut frames = VecDeque::new();
|
|
|
|
prios.fill_frames(FRAMES_PER_TICK, &mut frames).await;
|
|
|
|
let len = frames.len();
|
|
|
|
if len > 0 {
|
|
|
|
trace!("tick {}", len);
|
|
|
|
}
|
|
|
|
for (_, frame) in frames {
|
2020-05-24 23:17:03 +00:00
|
|
|
self.send_frame(frame, &mut send_cache).await;
|
2020-05-22 14:00:08 +00:00
|
|
|
}
|
2020-05-27 15:58:57 +00:00
|
|
|
b2s_prio_statistic_s
|
|
|
|
.send((self.remote_pid, len as u64, /* */ 0))
|
|
|
|
.await
|
|
|
|
.unwrap();
|
2020-05-22 14:00:08 +00:00
|
|
|
async_std::task::sleep(TICK_TIME).await;
|
|
|
|
//shutdown after all msg are send!
|
|
|
|
if closing_up && (len == 0) {
|
|
|
|
break;
|
|
|
|
}
|
2020-05-26 13:06:03 +00:00
|
|
|
//this IF below the break IF to give it another chance to close all streams
|
|
|
|
// closed
|
|
|
|
if !closing_up && shutdown_send_mgr_receiver.try_recv().unwrap().is_some() {
|
|
|
|
closing_up = true;
|
|
|
|
}
|
2020-05-22 14:00:08 +00:00
|
|
|
}
|
|
|
|
trace!("stop send_mgr");
|
|
|
|
b2b_prios_flushed_s.send(()).unwrap();
|
|
|
|
self.running_mgr.fetch_sub(1, Ordering::Relaxed);
|
|
|
|
}
|
|
|
|
|
2020-06-08 09:47:39 +00:00
|
|
|
//retruns false if sending isn't possible. In that case we have to render the
|
|
|
|
// Participant `closed`
|
|
|
|
#[must_use = "You need to check if the send was successful and report to client!"]
|
|
|
|
async fn send_frame(
|
|
|
|
&self,
|
|
|
|
frame: Frame,
|
|
|
|
frames_out_total_cache: &mut PidCidFrameCache,
|
|
|
|
) -> bool {
|
2020-04-08 14:26:42 +00:00
|
|
|
// find out ideal channel here
|
2020-03-22 13:47:21 +00:00
|
|
|
//TODO: just take first
|
2020-05-27 15:58:57 +00:00
|
|
|
let mut lock = self.channels.write().await;
|
|
|
|
if let Some(ci) = lock.get_mut(0) {
|
|
|
|
//note: this is technically wrong we should only increase when it suceeded, but
|
|
|
|
// this requiered me to clone `frame` which is a to big performance impact for
|
|
|
|
// error handling
|
2020-05-24 23:17:03 +00:00
|
|
|
frames_out_total_cache
|
|
|
|
.with_label_values(ci.cid, &frame)
|
2020-05-04 13:27:58 +00:00
|
|
|
.inc();
|
2020-05-27 15:58:57 +00:00
|
|
|
if let Err(e) = ci.b2w_frame_s.send(frame).await {
|
|
|
|
warn!(
|
|
|
|
?e,
|
|
|
|
"the channel got closed unexpectedly, cleaning it up now."
|
|
|
|
);
|
|
|
|
let ci = lock.remove(0);
|
|
|
|
if let Err(e) = ci.b2r_read_shutdown.send(()) {
|
|
|
|
debug!(
|
|
|
|
?e,
|
|
|
|
"error shutdowning channel, which is prob fine as we detected it to no \
|
|
|
|
longer work in the first place"
|
|
|
|
);
|
|
|
|
};
|
2020-06-08 09:47:39 +00:00
|
|
|
//TODO
|
|
|
|
warn!(
|
|
|
|
"FIXME: the frame is actually drop. which is fine for now as the participant \
|
|
|
|
will be closed, but not if we do channel-takeover"
|
|
|
|
);
|
|
|
|
false
|
|
|
|
} else {
|
|
|
|
true
|
2020-05-27 15:58:57 +00:00
|
|
|
}
|
2020-03-22 13:47:21 +00:00
|
|
|
} else {
|
|
|
|
error!("participant has no channel to communicate on");
|
2020-06-08 09:47:39 +00:00
|
|
|
false
|
2020-03-22 13:47:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-15 12:29:17 +00:00
|
|
|
async fn handle_frames_mgr(
|
2020-03-22 13:47:21 +00:00
|
|
|
&self,
|
2020-05-15 12:29:17 +00:00
|
|
|
mut w2b_frames_r: mpsc::UnboundedReceiver<(Cid, Frame)>,
|
|
|
|
mut b2a_stream_opened_s: mpsc::UnboundedSender<Stream>,
|
|
|
|
a2b_close_stream_s: mpsc::UnboundedSender<Sid>,
|
Fixing the DEADLOCK in handshake -> channel creation
- this bug was initially called imbris bug, as it happened on his runners and i couldn't reproduce it locally at fist :)
- When in a Handshake a seperate mpsc::Channel was created for (Cid, Frame) transport
however the protocol could already catch non handshake data any more and push in into this
mpsc::Channel.
Then this channel got dropped and a fresh one was created for the network::Channel.
These droped Frames are ofc a BUG!
I tried multiple things to solve this:
- dont create a new mpsc::Channel, but instead bind it to the Protocol itself and always use 1.
This would work theoretically, but in bParticipant side we are using 1 mpsc::Channel<(Cid, Frame)>
to handle ALL the network::channel.
If now ever Protocol would have it's own, and with that every network::Channel had it's own it would no longer work out
Bad Idea...
- using the first method but creating the mpsc::Channel inside the scheduler instead protocol neither works, as the
scheduler doesnt know the remote_pid yet
- i dont want a hack to say the protocol only listen to 2 messages and then stop no matter what
So i switched over to the simply method now:
- Do everything like before with 2 mpsc::Channels
- after the handshake. close the receiver and listen for all remaining (cid, frame) combinations
- when starting the channel, reapply them to the new sender/listener combination
- added tracing
- switched Protocol RwLock to Mutex, as it's only ever 1
- Additionally changed the layout and introduces the c2w_frame_s and w2s_cid_frame_s name schema
- Fixed a bug in scheduler which WOULD cause a DEADLOCK if handshake would fail
- fixd a but in api_send_send_main, i need to store the stream_p otherwise it's immeadiatly closed and a stream_a.send() isn't guaranteed
- add extra test to verify that a send message is received even if the Stream is already closed
- changed OutGoing to Outgoing
- fixed a bug that `metrics.tick()` was never called
- removed 2 unused nightly features and added `deny_code`
2020-06-03 07:13:00 +00:00
|
|
|
a2p_msg_s: std::sync::mpsc::Sender<(Prio, Sid, OutgoingMessage)>,
|
2020-03-22 13:47:21 +00:00
|
|
|
) {
|
2020-05-15 12:29:17 +00:00
|
|
|
self.running_mgr.fetch_add(1, Ordering::Relaxed);
|
2020-05-22 14:00:08 +00:00
|
|
|
trace!("start handle_frames_mgr");
|
2020-03-22 13:47:21 +00:00
|
|
|
let mut messages = HashMap::new();
|
2020-05-27 15:58:57 +00:00
|
|
|
let mut dropped_instant = Instant::now();
|
|
|
|
let mut dropped_cnt = 0u64;
|
|
|
|
let mut dropped_sid = Sid::new(0);
|
|
|
|
|
2020-05-15 12:29:17 +00:00
|
|
|
while let Some((cid, frame)) = w2b_frames_r.next().await {
|
2020-05-04 13:27:58 +00:00
|
|
|
let cid_string = cid.to_string();
|
2020-05-15 12:29:17 +00:00
|
|
|
//trace!("handling frame");
|
2020-05-04 13:27:58 +00:00
|
|
|
self.metrics
|
|
|
|
.frames_in_total
|
2020-05-24 23:17:03 +00:00
|
|
|
.with_label_values(&[&self.remote_pid_string, &cid_string, frame.get_string()])
|
2020-05-04 13:27:58 +00:00
|
|
|
.inc();
|
2020-03-22 13:47:21 +00:00
|
|
|
match frame {
|
|
|
|
Frame::OpenStream {
|
|
|
|
sid,
|
|
|
|
prio,
|
|
|
|
promises,
|
|
|
|
} => {
|
2020-05-15 12:29:17 +00:00
|
|
|
let a2p_msg_s = a2p_msg_s.clone();
|
2020-03-22 13:47:21 +00:00
|
|
|
let stream = self
|
2020-05-15 12:29:17 +00:00
|
|
|
.create_stream(sid, prio, promises, a2p_msg_s, &a2b_close_stream_s)
|
2020-03-22 13:47:21 +00:00
|
|
|
.await;
|
2020-05-15 12:29:17 +00:00
|
|
|
b2a_stream_opened_s.send(stream).await.unwrap();
|
2020-03-22 13:47:21 +00:00
|
|
|
trace!("opened frame from remote");
|
|
|
|
},
|
|
|
|
Frame::CloseStream { sid } => {
|
2020-04-08 14:26:42 +00:00
|
|
|
// Closing is realised by setting a AtomicBool to true, however we also have a
|
|
|
|
// guarantee that send or recv fails if the other one is destroyed
|
|
|
|
// However Stream.send() is not async and their receiver isn't dropped if Steam
|
|
|
|
// is dropped, so i need a way to notify the Stream that it's send messages will
|
|
|
|
// be dropped... from remote, notify local
|
2020-05-27 15:58:57 +00:00
|
|
|
trace!(
|
|
|
|
?sid,
|
|
|
|
"got remote request to close a stream, without flushing it, local \
|
|
|
|
messages are dropped"
|
|
|
|
);
|
|
|
|
// no wait for flush here, as the remote wouldn't care anyway.
|
2020-05-15 12:29:17 +00:00
|
|
|
if let Some(si) = self.streams.write().await.remove(&sid) {
|
2020-04-24 10:56:04 +00:00
|
|
|
self.metrics
|
|
|
|
.streams_closed_total
|
2020-05-24 23:17:03 +00:00
|
|
|
.with_label_values(&[&self.remote_pid_string])
|
2020-04-24 10:56:04 +00:00
|
|
|
.inc();
|
2020-05-15 12:29:17 +00:00
|
|
|
si.closed.store(true, Ordering::Relaxed);
|
2020-05-27 15:58:57 +00:00
|
|
|
trace!(?sid, "closed stream from remote");
|
2020-03-22 13:47:21 +00:00
|
|
|
} else {
|
2020-05-27 15:58:57 +00:00
|
|
|
warn!(
|
|
|
|
?sid,
|
2020-04-08 14:26:42 +00:00
|
|
|
"couldn't find stream to close, either this is a duplicate message, \
|
|
|
|
or the local copy of the Stream got closed simultaniously"
|
|
|
|
);
|
2020-03-22 13:47:21 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
Frame::DataHeader { mid, sid, length } => {
|
Fixing the DEADLOCK in handshake -> channel creation
- this bug was initially called imbris bug, as it happened on his runners and i couldn't reproduce it locally at fist :)
- When in a Handshake a seperate mpsc::Channel was created for (Cid, Frame) transport
however the protocol could already catch non handshake data any more and push in into this
mpsc::Channel.
Then this channel got dropped and a fresh one was created for the network::Channel.
These droped Frames are ofc a BUG!
I tried multiple things to solve this:
- dont create a new mpsc::Channel, but instead bind it to the Protocol itself and always use 1.
This would work theoretically, but in bParticipant side we are using 1 mpsc::Channel<(Cid, Frame)>
to handle ALL the network::channel.
If now ever Protocol would have it's own, and with that every network::Channel had it's own it would no longer work out
Bad Idea...
- using the first method but creating the mpsc::Channel inside the scheduler instead protocol neither works, as the
scheduler doesnt know the remote_pid yet
- i dont want a hack to say the protocol only listen to 2 messages and then stop no matter what
So i switched over to the simply method now:
- Do everything like before with 2 mpsc::Channels
- after the handshake. close the receiver and listen for all remaining (cid, frame) combinations
- when starting the channel, reapply them to the new sender/listener combination
- added tracing
- switched Protocol RwLock to Mutex, as it's only ever 1
- Additionally changed the layout and introduces the c2w_frame_s and w2s_cid_frame_s name schema
- Fixed a bug in scheduler which WOULD cause a DEADLOCK if handshake would fail
- fixd a but in api_send_send_main, i need to store the stream_p otherwise it's immeadiatly closed and a stream_a.send() isn't guaranteed
- add extra test to verify that a send message is received even if the Stream is already closed
- changed OutGoing to Outgoing
- fixed a bug that `metrics.tick()` was never called
- removed 2 unused nightly features and added `deny_code`
2020-06-03 07:13:00 +00:00
|
|
|
let imsg = IncomingMessage {
|
2020-03-22 13:47:21 +00:00
|
|
|
buffer: MessageBuffer { data: Vec::new() },
|
|
|
|
length,
|
|
|
|
mid,
|
|
|
|
sid,
|
|
|
|
};
|
|
|
|
messages.insert(mid, imsg);
|
|
|
|
},
|
|
|
|
Frame::Data {
|
2020-04-24 10:56:04 +00:00
|
|
|
mid,
|
2020-03-22 13:47:21 +00:00
|
|
|
start: _,
|
|
|
|
mut data,
|
|
|
|
} => {
|
2020-04-24 10:56:04 +00:00
|
|
|
let finished = if let Some(imsg) = messages.get_mut(&mid) {
|
2020-03-22 13:47:21 +00:00
|
|
|
imsg.buffer.data.append(&mut data);
|
|
|
|
imsg.buffer.data.len() as u64 == imsg.length
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
};
|
|
|
|
if finished {
|
2020-05-15 12:29:17 +00:00
|
|
|
//debug!(?mid, "finished receiving message");
|
2020-04-24 10:56:04 +00:00
|
|
|
let imsg = messages.remove(&mid).unwrap();
|
2020-05-15 12:29:17 +00:00
|
|
|
if let Some(si) = self.streams.write().await.get_mut(&imsg.sid) {
|
2020-05-27 15:58:57 +00:00
|
|
|
if let Err(e) = si.b2a_msg_recv_s.send(imsg).await {
|
|
|
|
warn!(
|
|
|
|
?e,
|
|
|
|
?mid,
|
|
|
|
"dropping message, as streams seem to be in act of beeing \
|
|
|
|
dropped right now"
|
|
|
|
);
|
|
|
|
}
|
2020-04-08 14:26:42 +00:00
|
|
|
} else {
|
2020-05-27 15:58:57 +00:00
|
|
|
//aggregate errors
|
|
|
|
let n = Instant::now();
|
|
|
|
if dropped_sid != imsg.sid
|
|
|
|
|| n.duration_since(dropped_instant) > Duration::from_secs(1)
|
|
|
|
{
|
|
|
|
warn!(
|
|
|
|
?dropped_cnt,
|
|
|
|
"dropping multiple messages as stream no longer seems to \
|
|
|
|
exist because it was dropped probably."
|
|
|
|
);
|
|
|
|
dropped_cnt = 0;
|
|
|
|
dropped_instant = n;
|
|
|
|
dropped_sid = imsg.sid;
|
|
|
|
} else {
|
|
|
|
dropped_cnt += 1;
|
|
|
|
}
|
2020-03-22 13:47:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
_ => unreachable!("never reaches frame!"),
|
|
|
|
}
|
|
|
|
}
|
2020-05-27 15:58:57 +00:00
|
|
|
if dropped_cnt > 0 {
|
|
|
|
warn!(
|
|
|
|
?dropped_cnt,
|
|
|
|
"dropping multiple messages as stream no longer seems to exist because it was \
|
|
|
|
dropped probably."
|
|
|
|
);
|
|
|
|
}
|
2020-05-22 14:00:08 +00:00
|
|
|
trace!("stop handle_frames_mgr");
|
2020-05-15 12:29:17 +00:00
|
|
|
self.running_mgr.fetch_sub(1, Ordering::Relaxed);
|
2020-03-22 13:47:21 +00:00
|
|
|
}
|
|
|
|
|
2020-06-08 09:47:39 +00:00
|
|
|
#[allow(clippy::type_complexity)]
|
2020-05-15 12:29:17 +00:00
|
|
|
async fn create_channel_mgr(
|
2020-05-04 13:27:58 +00:00
|
|
|
&self,
|
Fixing the DEADLOCK in handshake -> channel creation
- this bug was initially called imbris bug, as it happened on his runners and i couldn't reproduce it locally at fist :)
- When in a Handshake a seperate mpsc::Channel was created for (Cid, Frame) transport
however the protocol could already catch non handshake data any more and push in into this
mpsc::Channel.
Then this channel got dropped and a fresh one was created for the network::Channel.
These droped Frames are ofc a BUG!
I tried multiple things to solve this:
- dont create a new mpsc::Channel, but instead bind it to the Protocol itself and always use 1.
This would work theoretically, but in bParticipant side we are using 1 mpsc::Channel<(Cid, Frame)>
to handle ALL the network::channel.
If now ever Protocol would have it's own, and with that every network::Channel had it's own it would no longer work out
Bad Idea...
- using the first method but creating the mpsc::Channel inside the scheduler instead protocol neither works, as the
scheduler doesnt know the remote_pid yet
- i dont want a hack to say the protocol only listen to 2 messages and then stop no matter what
So i switched over to the simply method now:
- Do everything like before with 2 mpsc::Channels
- after the handshake. close the receiver and listen for all remaining (cid, frame) combinations
- when starting the channel, reapply them to the new sender/listener combination
- added tracing
- switched Protocol RwLock to Mutex, as it's only ever 1
- Additionally changed the layout and introduces the c2w_frame_s and w2s_cid_frame_s name schema
- Fixed a bug in scheduler which WOULD cause a DEADLOCK if handshake would fail
- fixd a but in api_send_send_main, i need to store the stream_p otherwise it's immeadiatly closed and a stream_a.send() isn't guaranteed
- add extra test to verify that a send message is received even if the Stream is already closed
- changed OutGoing to Outgoing
- fixed a bug that `metrics.tick()` was never called
- removed 2 unused nightly features and added `deny_code`
2020-06-03 07:13:00 +00:00
|
|
|
s2b_create_channel_r: mpsc::UnboundedReceiver<(
|
|
|
|
Cid,
|
|
|
|
Sid,
|
|
|
|
Protocols,
|
|
|
|
Vec<(Cid, Frame)>,
|
|
|
|
oneshot::Sender<()>,
|
|
|
|
)>,
|
2020-05-15 12:29:17 +00:00
|
|
|
w2b_frames_s: mpsc::UnboundedSender<(Cid, Frame)>,
|
2020-05-04 13:27:58 +00:00
|
|
|
) {
|
2020-05-15 12:29:17 +00:00
|
|
|
self.running_mgr.fetch_add(1, Ordering::Relaxed);
|
|
|
|
trace!("start create_channel_mgr");
|
|
|
|
s2b_create_channel_r
|
Fixing the DEADLOCK in handshake -> channel creation
- this bug was initially called imbris bug, as it happened on his runners and i couldn't reproduce it locally at fist :)
- When in a Handshake a seperate mpsc::Channel was created for (Cid, Frame) transport
however the protocol could already catch non handshake data any more and push in into this
mpsc::Channel.
Then this channel got dropped and a fresh one was created for the network::Channel.
These droped Frames are ofc a BUG!
I tried multiple things to solve this:
- dont create a new mpsc::Channel, but instead bind it to the Protocol itself and always use 1.
This would work theoretically, but in bParticipant side we are using 1 mpsc::Channel<(Cid, Frame)>
to handle ALL the network::channel.
If now ever Protocol would have it's own, and with that every network::Channel had it's own it would no longer work out
Bad Idea...
- using the first method but creating the mpsc::Channel inside the scheduler instead protocol neither works, as the
scheduler doesnt know the remote_pid yet
- i dont want a hack to say the protocol only listen to 2 messages and then stop no matter what
So i switched over to the simply method now:
- Do everything like before with 2 mpsc::Channels
- after the handshake. close the receiver and listen for all remaining (cid, frame) combinations
- when starting the channel, reapply them to the new sender/listener combination
- added tracing
- switched Protocol RwLock to Mutex, as it's only ever 1
- Additionally changed the layout and introduces the c2w_frame_s and w2s_cid_frame_s name schema
- Fixed a bug in scheduler which WOULD cause a DEADLOCK if handshake would fail
- fixd a but in api_send_send_main, i need to store the stream_p otherwise it's immeadiatly closed and a stream_a.send() isn't guaranteed
- add extra test to verify that a send message is received even if the Stream is already closed
- changed OutGoing to Outgoing
- fixed a bug that `metrics.tick()` was never called
- removed 2 unused nightly features and added `deny_code`
2020-06-03 07:13:00 +00:00
|
|
|
.for_each_concurrent(
|
|
|
|
None,
|
|
|
|
|(cid, _, protocol, leftover_cid_frame, b2s_create_channel_done_s)| {
|
|
|
|
// This channel is now configured, and we are running it in scope of the
|
|
|
|
// participant.
|
|
|
|
let w2b_frames_s = w2b_frames_s.clone();
|
|
|
|
let channels = self.channels.clone();
|
|
|
|
async move {
|
|
|
|
let (channel, b2w_frame_s, b2r_read_shutdown) = Channel::new(cid);
|
|
|
|
channels.write().await.push(ChannelInfo {
|
|
|
|
cid,
|
|
|
|
cid_string: cid.to_string(),
|
|
|
|
b2w_frame_s,
|
|
|
|
b2r_read_shutdown,
|
|
|
|
});
|
|
|
|
b2s_create_channel_done_s.send(()).unwrap();
|
|
|
|
self.metrics
|
|
|
|
.channels_connected_total
|
|
|
|
.with_label_values(&[&self.remote_pid_string])
|
|
|
|
.inc();
|
|
|
|
trace!(?cid, "running channel in participant");
|
|
|
|
channel
|
|
|
|
.run(protocol, w2b_frames_s, leftover_cid_frame)
|
|
|
|
.await;
|
|
|
|
self.metrics
|
|
|
|
.channels_disconnected_total
|
|
|
|
.with_label_values(&[&self.remote_pid_string])
|
|
|
|
.inc();
|
|
|
|
trace!(?cid, "channel got closed");
|
|
|
|
}
|
|
|
|
},
|
|
|
|
)
|
2020-05-04 13:27:58 +00:00
|
|
|
.await;
|
2020-05-15 12:29:17 +00:00
|
|
|
trace!("stop create_channel_mgr");
|
|
|
|
self.running_mgr.fetch_sub(1, Ordering::Relaxed);
|
2020-05-04 13:27:58 +00:00
|
|
|
}
|
|
|
|
|
2020-05-15 12:29:17 +00:00
|
|
|
async fn open_mgr(
|
2020-03-22 13:47:21 +00:00
|
|
|
&self,
|
2020-05-15 12:29:17 +00:00
|
|
|
mut a2b_steam_open_r: mpsc::UnboundedReceiver<(Prio, Promises, oneshot::Sender<Stream>)>,
|
|
|
|
a2b_close_stream_s: mpsc::UnboundedSender<Sid>,
|
Fixing the DEADLOCK in handshake -> channel creation
- this bug was initially called imbris bug, as it happened on his runners and i couldn't reproduce it locally at fist :)
- When in a Handshake a seperate mpsc::Channel was created for (Cid, Frame) transport
however the protocol could already catch non handshake data any more and push in into this
mpsc::Channel.
Then this channel got dropped and a fresh one was created for the network::Channel.
These droped Frames are ofc a BUG!
I tried multiple things to solve this:
- dont create a new mpsc::Channel, but instead bind it to the Protocol itself and always use 1.
This would work theoretically, but in bParticipant side we are using 1 mpsc::Channel<(Cid, Frame)>
to handle ALL the network::channel.
If now ever Protocol would have it's own, and with that every network::Channel had it's own it would no longer work out
Bad Idea...
- using the first method but creating the mpsc::Channel inside the scheduler instead protocol neither works, as the
scheduler doesnt know the remote_pid yet
- i dont want a hack to say the protocol only listen to 2 messages and then stop no matter what
So i switched over to the simply method now:
- Do everything like before with 2 mpsc::Channels
- after the handshake. close the receiver and listen for all remaining (cid, frame) combinations
- when starting the channel, reapply them to the new sender/listener combination
- added tracing
- switched Protocol RwLock to Mutex, as it's only ever 1
- Additionally changed the layout and introduces the c2w_frame_s and w2s_cid_frame_s name schema
- Fixed a bug in scheduler which WOULD cause a DEADLOCK if handshake would fail
- fixd a but in api_send_send_main, i need to store the stream_p otherwise it's immeadiatly closed and a stream_a.send() isn't guaranteed
- add extra test to verify that a send message is received even if the Stream is already closed
- changed OutGoing to Outgoing
- fixed a bug that `metrics.tick()` was never called
- removed 2 unused nightly features and added `deny_code`
2020-06-03 07:13:00 +00:00
|
|
|
a2p_msg_s: std::sync::mpsc::Sender<(Prio, Sid, OutgoingMessage)>,
|
2020-05-15 12:29:17 +00:00
|
|
|
shutdown_open_mgr_receiver: oneshot::Receiver<()>,
|
2020-03-22 13:47:21 +00:00
|
|
|
) {
|
2020-05-15 12:29:17 +00:00
|
|
|
self.running_mgr.fetch_add(1, Ordering::Relaxed);
|
|
|
|
trace!("start open_mgr");
|
2020-03-22 13:47:21 +00:00
|
|
|
let mut stream_ids = self.offset_sid;
|
2020-05-24 23:17:03 +00:00
|
|
|
let mut send_cache =
|
|
|
|
PidCidFrameCache::new(self.metrics.frames_out_total.clone(), self.remote_pid);
|
2020-05-15 12:29:17 +00:00
|
|
|
let mut shutdown_open_mgr_receiver = shutdown_open_mgr_receiver.fuse();
|
2020-04-08 14:26:42 +00:00
|
|
|
//from api or shutdown signal
|
2020-05-15 12:29:17 +00:00
|
|
|
while let Some((prio, promises, p2a_return_stream)) = select! {
|
|
|
|
next = a2b_steam_open_r.next().fuse() => next,
|
|
|
|
_ = shutdown_open_mgr_receiver => None,
|
2020-04-08 14:26:42 +00:00
|
|
|
} {
|
2020-03-22 13:47:21 +00:00
|
|
|
debug!(?prio, ?promises, "got request to open a new steam");
|
2020-05-22 14:00:08 +00:00
|
|
|
let a2p_msg_s = a2p_msg_s.clone();
|
2020-03-22 13:47:21 +00:00
|
|
|
let sid = stream_ids;
|
|
|
|
let stream = self
|
2020-05-22 14:00:08 +00:00
|
|
|
.create_stream(sid, prio, promises, a2p_msg_s, &a2b_close_stream_s)
|
2020-03-22 13:47:21 +00:00
|
|
|
.await;
|
2020-06-08 09:47:39 +00:00
|
|
|
if self
|
|
|
|
.send_frame(
|
|
|
|
Frame::OpenStream {
|
|
|
|
sid,
|
|
|
|
prio,
|
|
|
|
promises,
|
|
|
|
},
|
|
|
|
&mut send_cache,
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
{
|
|
|
|
//On error, we drop this, so it gets closed and client will handle this as an
|
|
|
|
// Err any way (:
|
|
|
|
p2a_return_stream.send(stream).unwrap();
|
|
|
|
stream_ids += Sid::from(1);
|
|
|
|
}
|
2020-03-22 13:47:21 +00:00
|
|
|
}
|
2020-05-15 12:29:17 +00:00
|
|
|
trace!("stop open_mgr");
|
|
|
|
self.running_mgr.fetch_sub(1, Ordering::Relaxed);
|
2020-03-22 13:47:21 +00:00
|
|
|
}
|
|
|
|
|
2020-05-15 12:29:17 +00:00
|
|
|
/// when activated this function will drop the participant completly and
|
|
|
|
/// wait for everything to go right! Then return 1. Shutting down
|
|
|
|
/// Streams for API and End user! 2. Wait for all "prio queued" Messages
|
|
|
|
/// to be send. 3. Send Stream
|
|
|
|
async fn participant_shutdown_mgr(
|
2020-04-08 14:26:42 +00:00
|
|
|
&self,
|
2020-05-15 12:29:17 +00:00
|
|
|
s2b_shutdown_bparticipant_r: oneshot::Receiver<oneshot::Sender<async_std::io::Result<()>>>,
|
2020-05-22 14:00:08 +00:00
|
|
|
b2b_prios_flushed_r: oneshot::Receiver<()>,
|
2020-04-08 14:26:42 +00:00
|
|
|
mut to_shutdown: Vec<oneshot::Sender<()>>,
|
|
|
|
) {
|
2020-05-15 12:29:17 +00:00
|
|
|
self.running_mgr.fetch_add(1, Ordering::Relaxed);
|
|
|
|
trace!("start participant_shutdown_mgr");
|
|
|
|
let sender = s2b_shutdown_bparticipant_r.await.unwrap();
|
2020-04-08 14:26:42 +00:00
|
|
|
debug!("closing all managers");
|
|
|
|
for sender in to_shutdown.drain(..) {
|
2020-05-27 15:58:57 +00:00
|
|
|
if let Err(e) = sender.send(()) {
|
|
|
|
warn!(?e, "manager seems to be closed already, weird, maybe a bug");
|
2020-04-08 14:26:42 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
debug!("closing all streams");
|
2020-05-22 14:00:08 +00:00
|
|
|
for (sid, si) in self.streams.write().await.drain() {
|
2020-04-08 14:26:42 +00:00
|
|
|
trace!(?sid, "shutting down Stream");
|
2020-05-15 12:29:17 +00:00
|
|
|
si.closed.store(true, Ordering::Relaxed);
|
|
|
|
}
|
2020-05-22 14:00:08 +00:00
|
|
|
debug!("waiting for prios to be flushed");
|
|
|
|
b2b_prios_flushed_r.await.unwrap();
|
2020-05-15 12:29:17 +00:00
|
|
|
debug!("closing all channels");
|
|
|
|
for ci in self.channels.write().await.drain(..) {
|
2020-05-26 13:06:03 +00:00
|
|
|
if let Err(e) = ci.b2r_read_shutdown.send(()) {
|
|
|
|
debug!(?e, ?ci.cid, "seems like this read protocol got already dropped by closing the Stream itself, just ignoring the fact");
|
|
|
|
};
|
2020-04-08 14:26:42 +00:00
|
|
|
}
|
2020-05-15 12:29:17 +00:00
|
|
|
//Wait for other bparticipants mgr to close via AtomicUsize
|
2020-05-27 15:58:57 +00:00
|
|
|
const SLEEP_TIME: Duration = Duration::from_millis(5);
|
2020-05-15 12:29:17 +00:00
|
|
|
async_std::task::sleep(SLEEP_TIME).await;
|
|
|
|
let mut i: u32 = 1;
|
|
|
|
while self.running_mgr.load(Ordering::Relaxed) > 1 {
|
|
|
|
i += 1;
|
|
|
|
if i.rem_euclid(10) == 1 {
|
|
|
|
trace!(
|
|
|
|
"waiting for bparticipant mgr to shut down, remaining {}",
|
|
|
|
self.running_mgr.load(Ordering::Relaxed) - 1
|
|
|
|
);
|
|
|
|
}
|
|
|
|
async_std::task::sleep(SLEEP_TIME * i).await;
|
|
|
|
}
|
|
|
|
trace!("all bparticipant mgr (except me) are shut down now");
|
2020-04-24 10:56:04 +00:00
|
|
|
self.metrics.participants_disconnected_total.inc();
|
2020-05-15 12:29:17 +00:00
|
|
|
sender.send(Ok(())).unwrap();
|
|
|
|
trace!("stop participant_shutdown_mgr");
|
|
|
|
self.running_mgr.fetch_sub(1, Ordering::Relaxed);
|
2020-04-08 14:26:42 +00:00
|
|
|
}
|
|
|
|
|
2020-05-15 12:29:17 +00:00
|
|
|
async fn stream_close_mgr(
|
2020-04-08 14:26:42 +00:00
|
|
|
&self,
|
2020-05-15 12:29:17 +00:00
|
|
|
mut a2b_close_stream_r: mpsc::UnboundedReceiver<Sid>,
|
|
|
|
shutdown_stream_close_mgr_receiver: oneshot::Receiver<()>,
|
2020-05-26 13:06:03 +00:00
|
|
|
b2p_notify_empty_stream_s: std::sync::mpsc::Sender<(Sid, oneshot::Sender<()>)>,
|
2020-04-08 14:26:42 +00:00
|
|
|
) {
|
2020-05-15 12:29:17 +00:00
|
|
|
self.running_mgr.fetch_add(1, Ordering::Relaxed);
|
|
|
|
trace!("start stream_close_mgr");
|
2020-05-24 23:17:03 +00:00
|
|
|
let mut send_cache =
|
|
|
|
PidCidFrameCache::new(self.metrics.frames_out_total.clone(), self.remote_pid);
|
2020-05-15 12:29:17 +00:00
|
|
|
let mut shutdown_stream_close_mgr_receiver = shutdown_stream_close_mgr_receiver.fuse();
|
|
|
|
|
2020-04-08 14:26:42 +00:00
|
|
|
//from api or shutdown signal
|
|
|
|
while let Some(sid) = select! {
|
2020-05-15 12:29:17 +00:00
|
|
|
next = a2b_close_stream_r.next().fuse() => next,
|
|
|
|
_ = shutdown_stream_close_mgr_receiver => None,
|
2020-04-08 14:26:42 +00:00
|
|
|
} {
|
2020-05-15 12:29:17 +00:00
|
|
|
//TODO: make this concurrent!
|
|
|
|
//TODO: Performance, closing is slow!
|
2020-04-08 14:26:42 +00:00
|
|
|
trace!(?sid, "got request from api to close steam");
|
2020-05-15 12:29:17 +00:00
|
|
|
//This needs to first stop clients from sending any more.
|
|
|
|
//Then it will wait for all pending messages (in prio) to be send to the
|
|
|
|
// protocol After this happened the stream is closed
|
|
|
|
//Only after all messages are send to the prococol, we can send the CloseStream
|
|
|
|
// frame! If we would send it before, all followup messages couldn't
|
|
|
|
// be handled at the remote side.
|
2020-04-08 14:26:42 +00:00
|
|
|
|
2020-05-15 12:29:17 +00:00
|
|
|
trace!(?sid, "stopping api to use this stream");
|
2020-05-27 15:58:57 +00:00
|
|
|
match self.streams.read().await.get(&sid) {
|
|
|
|
Some(si) => {
|
|
|
|
si.closed.store(true, Ordering::Relaxed);
|
|
|
|
},
|
|
|
|
None => warn!("couldn't find the stream, might be simulanious close from remote"),
|
|
|
|
}
|
2020-05-15 12:29:17 +00:00
|
|
|
|
2020-05-27 15:58:57 +00:00
|
|
|
//TODO: what happens if RIGHT NOW the remote sends a StreamClose and this
|
|
|
|
// streams get closed and removed? RACE CONDITION
|
2020-05-15 12:29:17 +00:00
|
|
|
trace!(?sid, "wait for stream to be flushed");
|
|
|
|
let (s2b_stream_finished_closed_s, s2b_stream_finished_closed_r) = oneshot::channel();
|
2020-05-26 13:06:03 +00:00
|
|
|
b2p_notify_empty_stream_s
|
2020-05-22 14:00:08 +00:00
|
|
|
.send((sid, s2b_stream_finished_closed_s))
|
2020-04-08 14:26:42 +00:00
|
|
|
.unwrap();
|
2020-05-15 12:29:17 +00:00
|
|
|
s2b_stream_finished_closed_r.await.unwrap();
|
|
|
|
|
2020-04-08 14:26:42 +00:00
|
|
|
trace!(?sid, "stream was successfully flushed");
|
2020-04-24 10:56:04 +00:00
|
|
|
self.metrics
|
|
|
|
.streams_closed_total
|
2020-05-24 23:17:03 +00:00
|
|
|
.with_label_values(&[&self.remote_pid_string])
|
2020-04-24 10:56:04 +00:00
|
|
|
.inc();
|
2020-05-15 12:29:17 +00:00
|
|
|
//only now remove the Stream, that means we can still recv on it.
|
2020-03-22 13:47:21 +00:00
|
|
|
self.streams.write().await.remove(&sid);
|
2020-05-24 23:17:03 +00:00
|
|
|
self.send_frame(Frame::CloseStream { sid }, &mut send_cache)
|
|
|
|
.await;
|
2020-03-22 13:47:21 +00:00
|
|
|
}
|
2020-05-15 12:29:17 +00:00
|
|
|
trace!("stop stream_close_mgr");
|
|
|
|
self.running_mgr.fetch_sub(1, Ordering::Relaxed);
|
2020-03-22 13:47:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
async fn create_stream(
|
|
|
|
&self,
|
|
|
|
sid: Sid,
|
|
|
|
prio: Prio,
|
|
|
|
promises: Promises,
|
Fixing the DEADLOCK in handshake -> channel creation
- this bug was initially called imbris bug, as it happened on his runners and i couldn't reproduce it locally at fist :)
- When in a Handshake a seperate mpsc::Channel was created for (Cid, Frame) transport
however the protocol could already catch non handshake data any more and push in into this
mpsc::Channel.
Then this channel got dropped and a fresh one was created for the network::Channel.
These droped Frames are ofc a BUG!
I tried multiple things to solve this:
- dont create a new mpsc::Channel, but instead bind it to the Protocol itself and always use 1.
This would work theoretically, but in bParticipant side we are using 1 mpsc::Channel<(Cid, Frame)>
to handle ALL the network::channel.
If now ever Protocol would have it's own, and with that every network::Channel had it's own it would no longer work out
Bad Idea...
- using the first method but creating the mpsc::Channel inside the scheduler instead protocol neither works, as the
scheduler doesnt know the remote_pid yet
- i dont want a hack to say the protocol only listen to 2 messages and then stop no matter what
So i switched over to the simply method now:
- Do everything like before with 2 mpsc::Channels
- after the handshake. close the receiver and listen for all remaining (cid, frame) combinations
- when starting the channel, reapply them to the new sender/listener combination
- added tracing
- switched Protocol RwLock to Mutex, as it's only ever 1
- Additionally changed the layout and introduces the c2w_frame_s and w2s_cid_frame_s name schema
- Fixed a bug in scheduler which WOULD cause a DEADLOCK if handshake would fail
- fixd a but in api_send_send_main, i need to store the stream_p otherwise it's immeadiatly closed and a stream_a.send() isn't guaranteed
- add extra test to verify that a send message is received even if the Stream is already closed
- changed OutGoing to Outgoing
- fixed a bug that `metrics.tick()` was never called
- removed 2 unused nightly features and added `deny_code`
2020-06-03 07:13:00 +00:00
|
|
|
a2p_msg_s: std::sync::mpsc::Sender<(Prio, Sid, OutgoingMessage)>,
|
2020-05-15 12:29:17 +00:00
|
|
|
a2b_close_stream_s: &mpsc::UnboundedSender<Sid>,
|
2020-03-22 13:47:21 +00:00
|
|
|
) -> Stream {
|
Fixing the DEADLOCK in handshake -> channel creation
- this bug was initially called imbris bug, as it happened on his runners and i couldn't reproduce it locally at fist :)
- When in a Handshake a seperate mpsc::Channel was created for (Cid, Frame) transport
however the protocol could already catch non handshake data any more and push in into this
mpsc::Channel.
Then this channel got dropped and a fresh one was created for the network::Channel.
These droped Frames are ofc a BUG!
I tried multiple things to solve this:
- dont create a new mpsc::Channel, but instead bind it to the Protocol itself and always use 1.
This would work theoretically, but in bParticipant side we are using 1 mpsc::Channel<(Cid, Frame)>
to handle ALL the network::channel.
If now ever Protocol would have it's own, and with that every network::Channel had it's own it would no longer work out
Bad Idea...
- using the first method but creating the mpsc::Channel inside the scheduler instead protocol neither works, as the
scheduler doesnt know the remote_pid yet
- i dont want a hack to say the protocol only listen to 2 messages and then stop no matter what
So i switched over to the simply method now:
- Do everything like before with 2 mpsc::Channels
- after the handshake. close the receiver and listen for all remaining (cid, frame) combinations
- when starting the channel, reapply them to the new sender/listener combination
- added tracing
- switched Protocol RwLock to Mutex, as it's only ever 1
- Additionally changed the layout and introduces the c2w_frame_s and w2s_cid_frame_s name schema
- Fixed a bug in scheduler which WOULD cause a DEADLOCK if handshake would fail
- fixd a but in api_send_send_main, i need to store the stream_p otherwise it's immeadiatly closed and a stream_a.send() isn't guaranteed
- add extra test to verify that a send message is received even if the Stream is already closed
- changed OutGoing to Outgoing
- fixed a bug that `metrics.tick()` was never called
- removed 2 unused nightly features and added `deny_code`
2020-06-03 07:13:00 +00:00
|
|
|
let (b2a_msg_recv_s, b2a_msg_recv_r) = mpsc::unbounded::<IncomingMessage>();
|
2020-04-08 14:26:42 +00:00
|
|
|
let closed = Arc::new(AtomicBool::new(false));
|
2020-05-15 12:29:17 +00:00
|
|
|
self.streams.write().await.insert(sid, StreamInfo {
|
|
|
|
prio,
|
|
|
|
promises,
|
|
|
|
b2a_msg_recv_s,
|
|
|
|
closed: closed.clone(),
|
|
|
|
});
|
2020-04-24 10:56:04 +00:00
|
|
|
self.metrics
|
|
|
|
.streams_opened_total
|
2020-05-24 23:17:03 +00:00
|
|
|
.with_label_values(&[&self.remote_pid_string])
|
2020-04-24 10:56:04 +00:00
|
|
|
.inc();
|
2020-03-22 13:47:21 +00:00
|
|
|
Stream::new(
|
|
|
|
self.remote_pid,
|
|
|
|
sid,
|
|
|
|
prio,
|
|
|
|
promises,
|
2020-05-15 12:29:17 +00:00
|
|
|
a2p_msg_s,
|
|
|
|
b2a_msg_recv_r,
|
2020-04-08 14:26:42 +00:00
|
|
|
closed.clone(),
|
2020-05-15 12:29:17 +00:00
|
|
|
a2b_close_stream_s.clone(),
|
2020-03-22 13:47:21 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|