WIP split channel

This commit is contained in:
Dominik Werder
2023-09-11 17:25:44 +02:00
parent 9d329c26ad
commit 6407af9574
10 changed files with 439 additions and 236 deletions

View File

@@ -1,5 +1,6 @@
pub mod conn;
pub mod connset;
pub mod connset_input_merge;
pub mod finder;
pub mod findioc;
pub mod proto;

View File

@@ -1,11 +1,5 @@
use super::proto;
use super::proto::CaItem;
use super::proto::CaMsg;
use super::proto::CaMsgTy;
use super::proto::CaProto;
use super::ExtraInsertsConf;
use crate::ca::proto::CreateChan;
use crate::ca::proto::EventAdd;
use crate::senderpolling::SenderPolling;
use crate::timebin::ConnTimeBin;
use async_channel::Sender;
@@ -23,6 +17,12 @@ use netpod::ScalarType;
use netpod::Shape;
use netpod::TS_MSP_GRID_SPACING;
use netpod::TS_MSP_GRID_UNIT;
use proto::CaItem;
use proto::CaMsg;
use proto::CaMsgTy;
use proto::CaProto;
use proto::CreateChan;
use proto::EventAdd;
use scywr::iteminsertqueue as scywriiq;
use scywriiq::ChannelInfoItem;
use scywriiq::ChannelStatus;
@@ -46,9 +46,7 @@ use std::ops::ControlFlow;
use std::pin::Pin;
use std::sync::atomic;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;
use std::sync::Arc;
use std::sync::Mutex as StdMutex;
use std::task::Context;
use std::task::Poll;
use std::time::Duration;
@@ -57,10 +55,19 @@ use std::time::SystemTime;
use taskrun::tokio;
use tokio::net::TcpStream;
#[allow(unused)]
macro_rules! trace2 {
($($arg:tt)*) => {
if false {
trace!($($arg)*);
}
};
}
#[allow(unused)]
macro_rules! trace3 {
($($arg:tt)*) => {
if true {
if false {
trace!($($arg)*);
}
};
@@ -69,7 +76,7 @@ macro_rules! trace3 {
#[allow(unused)]
macro_rules! trace4 {
($($arg:tt)*) => {
if true {
if false {
trace!($($arg)*);
}
};
@@ -394,12 +401,6 @@ pub struct CaConnEvent {
pub value: CaConnEventValue,
}
#[derive(Debug)]
enum ChannelSetOp {
Add(ChannelStatusSeriesId),
Remove,
}
struct SendSeriesLookup {
tx: Sender<ConnCommand>,
}
@@ -626,6 +627,7 @@ impl CaConn {
&mut self,
res: Result<ChannelInfoResult, dbpg::seriesbychannel::Error>,
) -> Result<(), Error> {
trace2!("handle_series_lookup_result {res:?}");
match res {
Ok(res) => {
let series = res.series.into_inner();
@@ -643,7 +645,7 @@ impl CaConn {
let data_type = st2.data_type;
let data_count = st2.data_count;
match self.channel_to_evented(cid, sid, data_type, data_count, series) {
Ok(_) => {}
Ok(()) => {}
Err(e) => {
error!("handle_series_lookup_result {e}");
}
@@ -668,38 +670,40 @@ impl CaConn {
fn handle_conn_command(&mut self, cx: &mut Context) -> Poll<Option<Result<(), Error>>> {
// TODO if this loops for too long time, yield and make sure we get wake up again.
use Poll::*;
self.stats.caconn_loop3_count.inc();
match self.conn_command_rx.poll_next_unpin(cx) {
Ready(Some(a)) => {
trace!("handle_conn_command received a command {}", self.remote_addr_dbg);
match a.kind {
ConnCommandKind::ChannelAdd(name, cssid) => {
self.cmd_channel_add(name, cssid);
Ready(Some(Ok(())))
loop {
self.stats.caconn_loop3_count.inc();
break match self.conn_command_rx.poll_next_unpin(cx) {
Ready(Some(a)) => {
trace3!("handle_conn_command received a command {}", self.remote_addr_dbg);
match a.kind {
ConnCommandKind::ChannelAdd(name, cssid) => {
self.cmd_channel_add(name, cssid);
Ready(Some(Ok(())))
}
ConnCommandKind::ChannelRemove(name) => {
self.cmd_channel_remove(name);
Ready(Some(Ok(())))
}
ConnCommandKind::CheckHealth => {
self.cmd_check_health();
Ready(Some(Ok(())))
}
ConnCommandKind::Shutdown => {
self.cmd_shutdown();
Ready(Some(Ok(())))
}
ConnCommandKind::SeriesLookupResult(x) => match self.handle_series_lookup_result(x) {
Ok(()) => Ready(Some(Ok(()))),
Err(e) => Ready(Some(Err(e))),
},
}
ConnCommandKind::ChannelRemove(name) => {
self.cmd_channel_remove(name);
Ready(Some(Ok(())))
}
ConnCommandKind::CheckHealth => {
self.cmd_check_health();
Ready(Some(Ok(())))
}
ConnCommandKind::Shutdown => {
self.cmd_shutdown();
Ready(Some(Ok(())))
}
ConnCommandKind::SeriesLookupResult(x) => match self.handle_series_lookup_result(x) {
Ok(()) => Ready(Some(Ok(()))),
Err(e) => Ready(Some(Err(e))),
},
}
}
Ready(None) => {
error!("Command queue closed");
Ready(None)
}
Pending => Pending,
Ready(None) => {
error!("Command queue closed");
Ready(None)
}
Pending => Pending,
};
}
}
@@ -937,22 +941,23 @@ impl CaConn {
series: SeriesId,
) -> Result<(), Error> {
let tsnow = Instant::now();
let name = self.name_by_cid(cid).unwrap().to_string();
// TODO handle error better! Transition channel to Error state?
let scalar_type = ScalarType::from_ca_id(data_type)?;
let shape = Shape::from_ca_count(data_count)?;
trace2!("channel_to_evented {name:?} {scalar_type:?} {shape:?}");
self.stats.get_series_id_ok.inc();
if series.id() == 0 {
warn!("Weird series id: {series:?}");
warn!("unexpected {series:?}");
}
if data_type > 6 {
error!("data type of series unexpected: {}", data_type);
}
// TODO handle error better! Transition channel to Error state?
let scalar_type = ScalarType::from_ca_id(data_type)?;
let shape = Shape::from_ca_count(data_count)?;
let mut tb = ConnTimeBin::empty();
tb.setup_for(series.clone(), &scalar_type, &shape)?;
self.time_binners.insert(cid, tb);
let subid = self.subid_store.next();
self.cid_by_subid.insert(subid, cid);
let name = self.name_by_cid(cid).unwrap().to_string();
// TODO convert first to CaDbrType, set to `Time`, then convert to ix:
let data_type_asked = data_type + 14;
let msg = CaMsg {
@@ -1170,10 +1175,12 @@ impl CaConn {
let item_queue = &mut self.insert_item_queue;
let inserts_counter = &mut self.inserts_counter;
let extra_inserts_conf = &self.extra_inserts_conf;
if let Some(tb) = self.time_binners.get_mut(&cid) {
tb.push(ts, &ev.value)?;
} else {
// TODO count or report error
if false {
if let Some(tb) = self.time_binners.get_mut(&cid) {
tb.push(ts, &ev.value)?;
} else {
// TODO count or report error
}
}
#[cfg(DISABLED)]
match &ev.value.data {
@@ -1383,10 +1390,7 @@ impl CaConn {
let sid = k.sid;
// TODO handle error:
let name = self.name_by_cid(cid).unwrap().to_string();
debug!("CreateChanRes {name:?}");
if false && name.contains(".STAT") {
info!("Channel created for {}", name);
}
trace3!("CreateChanRes {name:?}");
if k.data_type > 6 {
error!("CreateChanRes with unexpected data_type {}", k.data_type);
}
@@ -1438,7 +1442,7 @@ impl CaConn {
do_wake_again = true;
}
CaMsgTy::EventAddRes(k) => {
trace!("got EventAddRes: {k:?}");
trace4!("got EventAddRes: {k:?}");
self.stats.caconn_recv_data.inc();
let res = Self::handle_event_add_res(self, k, tsnow);
let ts2 = Instant::now();
@@ -1509,17 +1513,19 @@ impl CaConn {
Break(Pending)
}
fn handle_conn_state(&mut self, cx: &mut Context) -> Result<Option<Poll<()>>, Error> {
fn handle_conn_state(&mut self, cx: &mut Context) -> Result<Poll<Option<()>>, Error> {
use Poll::*;
match &mut self.state {
CaConnState::Unconnected => {
trace4!("Unconnected");
let addr = self.remote_addr_dbg.clone();
trace!("create tcp connection to {:?}", (addr.ip(), addr.port()));
let fut = tokio::time::timeout(Duration::from_millis(1000), TcpStream::connect(addr));
self.state = CaConnState::Connecting(addr, Box::pin(fut));
Ok(None)
Ok(Ready(Some(())))
}
CaConnState::Connecting(ref addr, ref mut fut) => {
trace4!("Connecting");
match fut.poll_unpin(cx) {
Ready(connect_result) => {
match connect_result {
@@ -1535,7 +1541,7 @@ impl CaConn {
let proto = CaProto::new(tcp, self.remote_addr_dbg.clone(), self.opts.array_truncate);
self.state = CaConnState::Init;
self.proto = Some(proto);
Ok(None)
Ok(Ready(Some(())))
}
Ok(Err(_e)) => {
// TODO log with exponential backoff
@@ -1549,7 +1555,7 @@ impl CaConn {
let dt = self.backoff_next();
self.state = CaConnState::Wait(wait_fut(dt));
self.proto = None;
Ok(None)
Ok(Ready(Some(())))
}
Err(e) => {
// TODO log with exponential backoff
@@ -1564,14 +1570,15 @@ impl CaConn {
let dt = self.backoff_next();
self.state = CaConnState::Wait(wait_fut(dt));
self.proto = None;
Ok(None)
Ok(Ready(Some(())))
}
}
}
Pending => Ok(Some(Pending)),
Pending => Ok(Pending),
}
}
CaConnState::Init => {
trace4!("Init");
let hostname = self.local_epics_hostname.clone();
let proto = self.proto.as_mut().unwrap();
let msg = CaMsg { ty: CaMsgTy::Version };
@@ -1585,54 +1592,74 @@ impl CaConn {
};
proto.push_out(msg);
self.state = CaConnState::Listen;
Ok(None)
Ok(Ready(Some(())))
}
CaConnState::Listen => {
trace4!("Listen");
match {
let res = self.handle_conn_listen(cx);
res
} {
Ready(Some(Ok(()))) => Ok(Ready(Some(()))),
Ready(Some(Err(e))) => Err(e),
Ready(None) => Ok(Ready(Some(()))),
Pending => Ok(Pending),
}
}
CaConnState::Listen => match {
let res = self.handle_conn_listen(cx);
res
} {
Ready(Some(Ok(()))) => Ok(Some(Ready(()))),
Ready(Some(Err(e))) => Err(e),
Ready(None) => Ok(None),
Pending => Ok(Some(Pending)),
},
CaConnState::PeerReady => {
trace4!("PeerReady");
let res = self.handle_peer_ready(cx);
match res {
Ready(Some(Ok(()))) => Ok(None),
Ready(Some(Ok(()))) => Ok(Ready(Some(()))),
Ready(Some(Err(e))) => Err(e),
Ready(None) => Ok(None),
Pending => Ok(Some(Pending)),
Ready(None) => Ok(Ready(Some(()))),
Pending => Ok(Pending),
}
}
CaConnState::Wait(inst) => match inst.poll_unpin(cx) {
Ready(_) => {
self.state = CaConnState::Unconnected;
self.proto = None;
Ok(None)
CaConnState::Wait(inst) => {
trace4!("Wait");
match inst.poll_unpin(cx) {
Ready(_) => {
self.state = CaConnState::Unconnected;
self.proto = None;
Ok(Ready(Some(())))
}
Pending => Ok(Pending),
}
Pending => Ok(Some(Pending)),
},
CaConnState::Shutdown => Ok(None),
CaConnState::EndOfStream => Ok(None),
}
CaConnState::Shutdown => {
trace4!("Shutdown");
Ok(Ready(None))
}
CaConnState::EndOfStream => {
trace4!("EndOfStream");
Ok(Ready(None))
}
}
}
fn loop_inner(&mut self, cx: &mut Context) -> Result<Option<Poll<()>>, Error> {
fn loop_inner(&mut self, cx: &mut Context) -> Result<Poll<Option<()>>, Error> {
use Poll::*;
loop {
self.stats.caconn_loop2_count.inc();
if self.is_shutdown() {
break Ok(None);
}
if self.insert_item_queue.len() >= self.opts.insert_queue_max {
break Ok(None);
}
match self.handle_conn_state(cx)? {
Some(Ready(_)) => continue,
Some(Pending) => break Ok(Some(Pending)),
None => break Ok(None),
}
break if self.is_shutdown() {
Ok(Ready(None))
} else if self.insert_item_queue.len() >= self.opts.insert_queue_max {
warn!("======================================================= queue stall");
Ok(Ready(None))
} else {
match self.handle_conn_state(cx) {
Ok(x) => match x {
Ready(Some(())) => continue,
Ready(None) => {
error!("handle_conn_state yields {x:?}");
Err(Error::with_msg_no_trace("logic error"))
}
Pending => Ok(Pending),
},
Err(e) => Err(e),
}
};
}
}
@@ -1662,9 +1689,11 @@ impl CaConn {
fn handle_own_ticker_tick(self: Pin<&mut Self>, _cx: &mut Context) -> Result<(), Error> {
let this = self.get_mut();
for (_, tb) in this.time_binners.iter_mut() {
let iiq = &mut this.insert_item_queue;
tb.tick(iiq)?;
if false {
for (_, tb) in this.time_binners.iter_mut() {
let iiq = &mut this.insert_item_queue;
tb.tick(iiq)?;
}
}
Ok(())
}
@@ -1680,10 +1709,11 @@ impl CaConn {
break if sd.is_sending() {
match sd.poll_unpin(cx) {
Ready(Ok(())) => continue,
Ready(Err(e)) => Err(Error::with_msg_no_trace("can not send into channel")),
Ready(Err(_)) => Err(Error::with_msg_no_trace("can not send into channel")),
Pending => Ok(()),
}
} else if let Some(item) = self.channel_info_query_queue.pop_front() {
trace3!("send series query {item:?}");
let sd = &mut self.channel_info_query_sending;
sd.send(item);
continue;
@@ -1700,8 +1730,8 @@ impl Stream for CaConn {
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
use Poll::*;
self.stats.caconn_poll_count.inc();
loop {
let mut have_pending = false;
let poll_ts1 = Instant::now();
let ret = loop {
break if let CaConnState::EndOfStream = self.state {
Ready(None)
} else if let Err(e) = self.as_mut().handle_own_ticker(cx) {
@@ -1724,64 +1754,42 @@ impl Stream for CaConn {
Ready(Some(Err(e)))
} else if let Ready(Some(Err(e))) = self.as_mut().handle_conn_command(cx) {
Ready(Some(Err(e)))
} else if let Some(item) = {
match self.loop_inner(cx) {
// TODO what does this mean: should we re-loop or yield something?
Ok(Some(Ready(()))) => None,
// This is the last step, so we yield Pending.
// But in general, this does not compose well when we would add another step.
Ok(Some(Pending)) => {
have_pending = true;
None
}
Ok(None) => None,
Err(e) => Some(Err(e)),
}
} {
Ready(Some(item))
} else {
// Ready(_) => self.stats.conn_stream_ready.inc(),
// Pending => self.stats.conn_stream_pending.inc(),
let _item = CaConnEvent {
ts: Instant::now(),
value: CaConnEventValue::None,
};
if self.is_shutdown() && self.queues_async_out_flushed() {
self.state = CaConnState::EndOfStream;
Ready(None)
} else if have_pending {
Pending
} else {
continue;
match self.loop_inner(cx) {
Ok(Ready(Some(()))) => continue,
Ok(Ready(None)) => {
// Ready(_) => self.stats.conn_stream_ready.inc(),
// Pending => self.stats.conn_stream_pending.inc(),
let _item = CaConnEvent {
ts: Instant::now(),
value: CaConnEventValue::None,
};
if self.is_shutdown() && self.queues_async_out_flushed() {
debug!("end of stream {}", self.remote_addr_dbg);
self.state = CaConnState::EndOfStream;
Ready(None)
} else {
continue;
}
}
Ok(Pending) => Pending,
Err(e) => {
error!("{e}");
self.state = CaConnState::EndOfStream;
Ready(Some(Err(e)))
}
}
};
}
}
}
pub struct PollTimer<INP> {
inp: INP,
}
impl<INP> PollTimer<INP> {
pub fn new(inp: INP) -> Self {
Self { inp }
}
}
impl<INP> Stream for PollTimer<INP>
where
INP: Stream + Unpin,
{
type Item = <INP as Stream>::Item;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
let poll_ts1 = Instant::now();
let inp = &mut self.inp;
let ret = inp.poll_next_unpin(cx);
};
let poll_ts2 = Instant::now();
let dt = poll_ts2.saturating_duration_since(poll_ts1);
if dt > Duration::from_millis(40) {}
if dt > Duration::from_millis(80) {
warn!("long poll duration {:.0} ms", dt.as_secs_f32() * 1e3)
} else if dt > Duration::from_millis(40) {
info!("long poll duration {:.0} ms", dt.as_secs_f32() * 1e3)
} else if dt > Duration::from_millis(5) {
debug!("long poll duration {:.0} ms", dt.as_secs_f32() * 1e3)
}
ret
}
}

View File

@@ -1,3 +1,4 @@
use super::connset_input_merge::InputMerge;
use super::findioc::FindIocRes;
use super::statemap;
use super::statemap::ChannelState;
@@ -68,6 +69,33 @@ static SEARCH_REQ_RECV_COUNT: AtomicUsize = AtomicUsize::new(0);
static SEARCH_REQ_BATCH_SEND_COUNT: AtomicUsize = AtomicUsize::new(0);
static SEARCH_ANS_COUNT: AtomicUsize = AtomicUsize::new(0);
#[allow(unused)]
macro_rules! trace2 {
($($arg:tt)*) => {
if false {
trace!($($arg)*);
}
};
}
#[allow(unused)]
macro_rules! trace3 {
($($arg:tt)*) => {
if false {
trace!($($arg)*);
}
};
}
#[allow(unused)]
macro_rules! trace4 {
($($arg:tt)*) => {
if false {
trace!($($arg)*);
}
};
}
#[derive(Debug, PartialEq, Eq)]
pub struct CmdId(SocketAddrV4, usize);
@@ -122,7 +150,7 @@ pub enum ConnSetCmd {
ChannelAddWithAddr(ChannelAddWithAddr),
ChannelRemove(ChannelRemove),
IocAddrQueryResult(VecDeque<FindIocRes>),
CheckHealth,
CheckHealth(Instant),
Shutdown,
}
@@ -134,7 +162,7 @@ pub enum CaConnSetEvent {
#[derive(Debug, Clone)]
pub enum CaConnSetItem {
Healthy,
Healthy(Instant, Instant),
}
pub struct CaConnSetCtrl {
@@ -173,7 +201,7 @@ impl CaConnSetCtrl {
}
pub async fn check_health(&self) -> Result<(), Error> {
let cmd = ConnSetCmd::CheckHealth;
let cmd = ConnSetCmd::CheckHealth(Instant::now());
self.tx.send(CaConnSetEvent::ConnSetCmd(cmd)).await?;
Ok(())
}
@@ -212,7 +240,8 @@ pub struct CaConnSet {
ca_conn_ress: BTreeMap<SocketAddr, CaConnRes>,
channel_states: ChannelStateMap,
connset_tx: Sender<CaConnSetEvent>,
connset_rx: Receiver<CaConnSetEvent>,
// connset_rx: Receiver<CaConnSetEvent>,
connset_rx: crate::ca::connset_input_merge::InputMerge,
channel_info_query_tx: Sender<ChannelInfoQuery>,
storage_insert_tx: Sender<QueryItem>,
shutdown_stopping: bool,
@@ -231,17 +260,20 @@ impl CaConnSet {
channel_info_query_tx: Sender<ChannelInfoQuery>,
pgconf: Database,
) -> CaConnSetCtrl {
let (connset_inp_tx, connset_inp_rx) = async_channel::bounded(256);
let (connset_out_tx, connset_out_rx) = async_channel::bounded(256);
let (connset_tx, connset_rx) = async_channel::bounded(10000);
let (search_tx, ioc_finder_jh) = super::finder::start_finder(connset_tx.clone(), backend.clone(), pgconf);
let (find_ioc_res_tx, find_ioc_res_rx) = async_channel::bounded(10000);
let (search_tx, ioc_finder_jh) = super::finder::start_finder(find_ioc_res_tx.clone(), backend.clone(), pgconf);
let input_merge = InputMerge::new(todo!(), find_ioc_res_rx);
let connset = Self {
backend,
local_epics_hostname,
search_tx,
ca_conn_ress: BTreeMap::new(),
channel_states: ChannelStateMap::new(),
connset_tx: connset_tx.clone(),
connset_rx,
connset_tx: connset_inp_tx,
// connset_rx: find_ioc_res_rx,
connset_rx: todo!(),
channel_info_query_tx,
storage_insert_tx,
shutdown_stopping: false,
@@ -254,7 +286,7 @@ impl CaConnSet {
// TODO await on jh
let jh = tokio::spawn(CaConnSet::run(connset));
CaConnSetCtrl {
tx: connset_tx,
tx: connset_inp_tx,
rx: connset_out_rx,
jh,
}
@@ -262,10 +294,10 @@ impl CaConnSet {
async fn run(mut this: CaConnSet) -> Result<(), Error> {
loop {
let x = this.connset_rx.recv().await;
let x = this.connset_rx.next().await;
match x {
Ok(ev) => this.handle_event(ev).await?,
Err(_) => {
Some(ev) => this.handle_event(ev).await?,
None => {
if this.shutdown_stopping {
// all fine
break;
@@ -302,7 +334,7 @@ impl CaConnSet {
ConnSetCmd::ChannelRemove(x) => self.handle_remove_channel(x).await,
ConnSetCmd::IocAddrQueryResult(x) => self.handle_ioc_query_result(x).await,
ConnSetCmd::SeriesLookupResult(x) => self.handle_series_lookup_result(x).await,
ConnSetCmd::CheckHealth => self.handle_check_health().await,
ConnSetCmd::CheckHealth(ts1) => self.handle_check_health(ts1).await,
ConnSetCmd::Shutdown => self.handle_shutdown().await,
},
CaConnSetEvent::CaConnEvent((addr, ev)) => match ev.value {
@@ -322,7 +354,7 @@ impl CaConnSet {
&mut self,
res: Result<ChannelInfoResult, dbpg::seriesbychannel::Error>,
) -> Result<(), Error> {
debug!("handle_series_lookup_result {res:?}");
trace3!("handle_series_lookup_result {res:?}");
match res {
Ok(res) => {
let add = ChannelAddWithStatusId {
@@ -372,7 +404,7 @@ impl CaConnSet {
debug!("handle_add_channel but shutdown_stopping");
return Ok(());
}
debug!("handle_add_channel_with_status_id {add:?}");
trace3!("handle_add_channel_with_status_id {add:?}");
let ch = Channel::new(add.name.clone());
if let Some(chst) = self.channel_states.inner().get_mut(&ch) {
if let ChannelStateValue::Active(chst2) = &mut chst.value {
@@ -462,7 +494,7 @@ impl CaConnSet {
} = ast
{
if let Some(addr) = e.addr {
debug!("ioc found {e:?}");
trace3!("ioc found {e:?}");
let add = ChannelAddWithAddr {
backend: self.backend.clone(),
name: e.channel,
@@ -496,9 +528,10 @@ impl CaConnSet {
Ok(())
}
async fn handle_check_health(&mut self) -> Result<(), Error> {
async fn handle_check_health(&mut self, ts1: Instant) -> Result<(), Error> {
debug!("TODO handle_check_health");
let item = CaConnSetItem::Healthy;
let ts2 = Instant::now();
let item = CaConnSetItem::Healthy(ts1, ts2);
self.connset_out_tx.send(item).await?;
Ok(())
}
@@ -907,7 +940,6 @@ impl CaConnSet {
}
}
}
use atomic::Ordering::Release;
self.stats.channel_unknown_address.__set(unknown_address);
self.stats.channel_search_pending.__set(search_pending);
self.stats.channel_no_address.__set(no_address);

View File

@@ -0,0 +1,66 @@
use super::connset::CaConnSetEvent;
use super::findioc::FindIocRes;
use crate::ca::connset::ConnSetCmd;
use async_channel::Receiver;
use futures_util::StreamExt;
use std::collections::VecDeque;
use std::pin::Pin;
use std::task::Context;
use std::task::Poll;
pub struct InputMerge {
inp1: Option<Receiver<CaConnSetEvent>>,
inp2: Option<Receiver<VecDeque<FindIocRes>>>,
}
impl InputMerge {
pub fn new(inp1: Receiver<CaConnSetEvent>, inp2: Receiver<VecDeque<FindIocRes>>) -> Self {
Self {
inp1: Some(inp1),
inp2: Some(inp2),
}
}
pub fn close(&mut self) {
if let Some(x) = self.inp1.as_ref() {
x.close();
}
}
}
impl futures_util::Stream for InputMerge {
type Item = CaConnSetEvent;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
use Poll::*;
let mut poll_next = false;
let ret = if let Some(inp) = &mut self.inp2 {
match inp.poll_next_unpin(cx) {
Ready(Some(x)) => Some(CaConnSetEvent::ConnSetCmd(ConnSetCmd::IocAddrQueryResult(x))),
Ready(None) => {
self.inp2 = None;
None
}
Pending => None,
}
} else {
None
};
if let Some(x) = ret {
Ready(Some(x))
} else {
if let Some(inp) = &mut self.inp1 {
match inp.poll_next_unpin(cx) {
Ready(Some(x)) => Ready(Some(x)),
Ready(None) => {
self.inp1 = None;
Ready(None)
}
Pending => Pending,
}
} else {
Ready(None)
}
}
}
}

View File

@@ -85,7 +85,7 @@ fn transform_pgres(rows: Vec<PgRow>) -> VecDeque<FindIocRes> {
async fn finder_worker_single(
inp: Receiver<Vec<IocAddrQuery>>,
tx: Sender<CaConnSetEvent>,
tx: Sender<VecDeque<FindIocRes>>,
backend: String,
db: Database,
) -> Result<(), Error> {
@@ -164,11 +164,7 @@ async fn finder_worker_single(
error!("STILL NOT MATCHING LEN");
}
SEARCH_RES_3_COUNT.fetch_add(items.len(), atomic::Ordering::AcqRel);
let x = tx
.send(CaConnSetEvent::ConnSetCmd(
crate::ca::connset::ConnSetCmd::IocAddrQueryResult(items),
))
.await;
let x = tx.send(items).await;
match x {
Ok(_) => {}
Err(e) => {
@@ -191,7 +187,7 @@ async fn finder_worker_single(
async fn finder_worker(
qrx: Receiver<IocAddrQuery>,
tx: Sender<CaConnSetEvent>,
tx: Sender<VecDeque<FindIocRes>>,
backend: String,
db: Database,
) -> Result<(), Error> {
@@ -215,7 +211,7 @@ async fn finder_worker(
}
pub fn start_finder(
tx: Sender<CaConnSetEvent>,
tx: Sender<VecDeque<FindIocRes>>,
backend: String,
db: Database,
) -> (Sender<IocAddrQuery>, JoinHandle<Result<(), Error>>) {

View File

@@ -7,6 +7,7 @@ pub mod linuxhelper;
pub mod metrics;
pub mod netbuf;
pub mod patchcollect;
pub mod polltimer;
pub mod rt;
pub mod senderpolling;
#[cfg(test)]

38
netfetch/src/polltimer.rs Normal file
View File

@@ -0,0 +1,38 @@
use futures_util::Stream;
use futures_util::StreamExt;
use log::*;
use std::pin::Pin;
use std::task::Context;
use std::task::Poll;
use std::time::Duration;
use std::time::Instant;
pub struct PollTimer<INP> {
inp: INP,
timeout_warn: Duration,
}
impl<INP> PollTimer<INP> {
pub fn new(inp: INP, timeout_warn: Duration) -> Self {
Self { inp, timeout_warn }
}
}
impl<INP> Stream for PollTimer<INP>
where
INP: Stream + Unpin,
{
type Item = <INP as Stream>::Item;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
let poll_ts1 = Instant::now();
let inp = &mut self.inp;
let ret = inp.poll_next_unpin(cx);
let poll_ts2 = Instant::now();
let dt = poll_ts2.saturating_duration_since(poll_ts1);
if dt > self.timeout_warn {
warn!("long poll duration {:.0} ms", dt.as_secs_f32() * 1e3)
}
ret
}
}

View File

@@ -26,6 +26,15 @@ use std::any::Any;
use std::collections::VecDeque;
use std::time::SystemTime;
#[allow(unused)]
macro_rules! trace2 {
($($arg:tt)*) => {
if false {
trace!($($arg)*);
}
};
}
struct TickParams<'a> {
series: SeriesId,
acc: &'a mut Box<dyn Any + Send>,
@@ -77,7 +86,7 @@ impl ConnTimeBin {
match scalar_type {
I8 => {
type ST = i8;
info!("SCALAR {}", any::type_name::<ST>());
trace2!("SCALAR {}", any::type_name::<ST>());
let cont = Cont::<ST>::empty();
self.events_binner =
Some(cont.as_time_binnable_ref().time_binner_new(binrange, do_time_weight));
@@ -88,7 +97,7 @@ impl ConnTimeBin {
}
I16 => {
type ST = i16;
info!("SCALAR {}", std::any::type_name::<ST>());
trace2!("SCALAR {}", std::any::type_name::<ST>());
let cont = Cont::<ST>::empty();
self.events_binner =
Some(cont.as_time_binnable_ref().time_binner_new(binrange, do_time_weight));
@@ -99,7 +108,7 @@ impl ConnTimeBin {
}
I32 => {
type ST = i32;
info!("SCALAR {}", std::any::type_name::<ST>());
trace2!("SCALAR {}", std::any::type_name::<ST>());
let cont = Cont::<ST>::empty();
self.events_binner =
Some(cont.as_time_binnable_ref().time_binner_new(binrange, do_time_weight));
@@ -110,7 +119,7 @@ impl ConnTimeBin {
}
F32 => {
type ST = f32;
info!("SCALAR {}", std::any::type_name::<ST>());
trace2!("SCALAR {}", std::any::type_name::<ST>());
let cont = Cont::<ST>::empty();
self.events_binner =
Some(cont.as_time_binnable_ref().time_binner_new(binrange, do_time_weight));
@@ -121,7 +130,7 @@ impl ConnTimeBin {
}
F64 => {
type ST = f64;
info!("SCALAR {}", std::any::type_name::<ST>());
trace2!("SCALAR {}", std::any::type_name::<ST>());
let cont = Cont::<ST>::empty();
self.events_binner =
Some(cont.as_time_binnable_ref().time_binner_new(binrange, do_time_weight));