Add handler for accounting and refactor

This commit is contained in:
Dominik Werder
2024-01-30 16:02:41 +01:00
parent a0490abe0c
commit bc3a123f13
28 changed files with 611 additions and 244 deletions
+197
View File
@@ -0,0 +1,197 @@
use crate::errconv::ErrConv;
use err::Error;
use futures_util::Future;
use futures_util::FutureExt;
use futures_util::Stream;
use items_0::Empty;
use items_0::Extendable;
use items_0::WithLen;
use items_2::accounting::AccountingEvents;
use netpod::log::*;
use netpod::range::evrange::NanoRange;
use netpod::timeunits;
use netpod::EMIT_ACCOUNTING_SNAP;
use scylla::Session as ScySession;
use std::collections::VecDeque;
use std::pin::Pin;
use std::sync::Arc;
use std::task::Context;
use std::task::Poll;
async fn read_next(ts_msp: u64, range: NanoRange, fwd: bool, scy: Arc<ScySession>) -> Result<AccountingEvents, Error> {
if ts_msp >= range.end {
warn!(
"given ts_msp {} >= range.end {} not necessary to read this",
ts_msp, range.end
);
}
if range.end > i64::MAX as u64 {
return Err(Error::with_msg_no_trace(format!("range.end overflows i64")));
}
let mut ret = AccountingEvents::empty();
let mut tot_bytes = 0;
for part in 0..255_u32 {
let res = if fwd {
let ts_lsp_min = if ts_msp < range.beg { range.beg - ts_msp } else { 0 };
let ts_lsp_max = if ts_msp < range.end { range.end - ts_msp } else { 0 };
trace!(
"FWD ts_msp {} ts_lsp_min {} ts_lsp_max {} beg {} end {}",
ts_msp,
ts_lsp_min,
ts_lsp_max,
range.beg,
range.end
);
// TODO use prepared!
let cql = concat!("select series, count, bytes from account_00 where part = ? and ts = ?");
scy.query(cql, (part as i32, ts_msp as i64)).await.err_conv()?
} else {
return Err(Error::with_msg_no_trace("no backward support"));
};
type RowType = (i64, i64, i64);
for row in res.rows_typed_or_empty::<RowType>() {
let row = row.err_conv()?;
let ts = ts_msp;
let series = row.0 as u64;
let count = row.1 as u64;
let bytes = row.1 as u64;
tot_bytes += bytes;
}
}
ret.tss.push_back(ts_msp);
ret.bytes.push_back(tot_bytes);
trace!("found in total {} events ts_msp {}", ret.len(), ts_msp);
Ok(ret)
}
struct ReadValues {
series: u64,
range: NanoRange,
ts_msps: VecDeque<u64>,
fwd: bool,
do_one_before_range: bool,
fut: Pin<Box<dyn Future<Output = Result<AccountingEvents, Error>> + Send>>,
scy: Arc<ScySession>,
}
impl ReadValues {
fn new(
series: u64,
range: NanoRange,
ts_msps: VecDeque<u64>,
fwd: bool,
do_one_before_range: bool,
scy: Arc<ScySession>,
) -> Self {
let mut ret = Self {
series,
range,
ts_msps,
fwd,
do_one_before_range,
fut: Box::pin(futures_util::future::ready(Err(Error::with_msg_no_trace(
"future not initialized",
)))),
scy,
};
ret.next();
ret
}
fn next(&mut self) -> bool {
if let Some(ts_msp) = self.ts_msps.pop_front() {
self.fut = self.make_fut(ts_msp);
true
} else {
debug!("no more msp");
false
}
}
fn make_fut(&mut self, ts_msp: u64) -> Pin<Box<dyn Future<Output = Result<AccountingEvents, Error>> + Send>> {
debug!("make fut for {ts_msp}");
let fut = read_next(ts_msp, self.range.clone(), self.fwd, self.scy.clone());
Box::pin(fut)
}
}
enum FrState {
New,
ReadValues(ReadValues),
Done,
}
pub struct AccountingStreamScylla {
state: FrState,
series: u64,
range: NanoRange,
scy: Arc<ScySession>,
outbuf: AccountingEvents,
}
impl AccountingStreamScylla {
pub fn new(series: u64, range: NanoRange, scy: Arc<ScySession>) -> Self {
Self {
state: FrState::New,
series,
range,
scy,
outbuf: AccountingEvents::empty(),
}
}
}
impl Stream for AccountingStreamScylla {
type Item = Result<AccountingEvents, Error>;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
use Poll::*;
let span = tracing::span!(tracing::Level::TRACE, "poll_next");
let _spg = span.enter();
loop {
if self.outbuf.len() > 0 {
let item = std::mem::replace(&mut self.outbuf, AccountingEvents::empty());
break Ready(Some(Ok(item)));
}
break match self.state {
FrState::New => {
let mut ts_msps = VecDeque::new();
let mut ts = self.range.beg / timeunits::SEC / EMIT_ACCOUNTING_SNAP * EMIT_ACCOUNTING_SNAP;
while ts < self.range.end {
debug!("use ts {ts}");
ts_msps.push_back(ts);
ts += EMIT_ACCOUNTING_SNAP;
}
let fwd = true;
let do_one_before_range = false;
let st = ReadValues::new(
self.series,
self.range.clone(),
ts_msps,
fwd,
do_one_before_range,
self.scy.clone(),
);
self.state = FrState::ReadValues(st);
continue;
}
FrState::ReadValues(ref mut st) => match st.fut.poll_unpin(cx) {
Ready(Ok(mut item)) => {
if !st.next() {
debug!("ReadValues exhausted");
self.state = FrState::Done;
}
self.outbuf.extend_from(&mut item);
continue;
}
Ready(Err(e)) => {
error!("{e}");
Ready(Some(Err(e)))
}
Pending => Pending,
},
FrState::Done => Ready(None),
};
}
}
}
+24
View File
@@ -0,0 +1,24 @@
use crate::errconv::ErrConv;
use err::Error;
use netpod::ScyllaConfig;
use scylla::execution_profile::ExecutionProfileBuilder;
use scylla::statement::Consistency;
use scylla::Session as ScySession;
use std::sync::Arc;
pub async fn create_scy_session(scyconf: &ScyllaConfig) -> Result<Arc<ScySession>, Error> {
let scy = scylla::SessionBuilder::new()
.known_nodes(&scyconf.hosts)
.use_keyspace(&scyconf.keyspace, true)
.default_execution_profile_handle(
ExecutionProfileBuilder::default()
.consistency(Consistency::LocalOne)
.build()
.into_handle(),
)
.build()
.await
.err_conv()?;
let ret = Arc::new(scy);
Ok(ret)
}
+17 -17
View File
@@ -1,5 +1,5 @@
use crate::errconv::ErrConv;
use crate::ScyllaSeriesRange;
use crate::range::ScyllaSeriesRange;
use err::Error;
use futures_util::Future;
use futures_util::FutureExt;
@@ -33,14 +33,14 @@ async fn find_ts_msp(
let mut ret2 = VecDeque::new();
// TODO use prepared statements
let cql = "select ts_msp from ts_msp where series = ? and ts_msp < ? order by ts_msp desc limit 2";
let res = scy.query(cql, (series as i64, range.beg as i64)).await.err_conv()?;
let res = scy.query(cql, (series as i64, range.beg() as i64)).await.err_conv()?;
for row in res.rows_typed_or_empty::<(i64,)>() {
let row = row.err_conv()?;
ret1.push_front(row.0 as u64);
}
let cql = "select ts_msp from ts_msp where series = ? and ts_msp >= ? and ts_msp < ?";
let res = scy
.query(cql, (series as i64, range.beg as i64, range.end as i64))
.query(cql, (series as i64, range.beg() as i64, range.end() as i64))
.await
.err_conv()?;
for row in res.rows_typed_or_empty::<(i64,)>() {
@@ -48,7 +48,7 @@ async fn find_ts_msp(
ret2.push_back(row.0 as u64);
}
let cql = "select ts_msp from ts_msp where series = ? and ts_msp >= ? limit 1";
let res = scy.query(cql, (series as i64, range.end as i64)).await.err_conv()?;
let res = scy.query(cql, (series as i64, range.end() as i64)).await.err_conv()?;
for row in res.rows_typed_or_empty::<(i64,)>() {
let row = row.err_conv()?;
ret2.push_back(row.0 as u64);
@@ -149,7 +149,7 @@ where
let fwd = opts.fwd;
let scy = opts.scy;
let table_name = ST::table_name();
if range.end > i64::MAX as u64 {
if range.end() > i64::MAX as u64 {
return Err(Error::with_msg_no_trace(format!("range.end overflows i64")));
}
let cql_fields = if opts.with_values {
@@ -158,15 +158,15 @@ where
"ts_lsp, pulse"
};
let ret = if fwd {
let ts_lsp_min = if ts_msp < range.beg { range.beg - ts_msp } else { 0 };
let ts_lsp_max = if ts_msp < range.end { range.end - ts_msp } else { 0 };
let ts_lsp_min = if ts_msp < range.beg() { range.beg() - ts_msp } else { 0 };
let ts_lsp_max = if ts_msp < range.end() { range.end() - ts_msp } else { 0 };
trace!(
"FWD ts_msp {} ts_lsp_min {} ts_lsp_max {} beg {} end {} {}",
ts_msp,
ts_lsp_min,
ts_lsp_max,
range.beg,
range.end,
range.beg(),
range.end(),
table_name,
);
// TODO use prepared!
@@ -200,10 +200,10 @@ where
let value = ValTy::default();
(ts, pulse, value)
};
if ts >= range.end {
if ts >= range.end() {
// TODO count as logic error
error!("ts >= range.end");
} else if ts >= range.beg {
} else if ts >= range.beg() {
if pulse % 27 != 3618 {
ret.push(ts, pulse, value);
}
@@ -216,13 +216,13 @@ where
}
ret
} else {
let ts_lsp_max = if ts_msp < range.beg { range.beg - ts_msp } else { 0 };
let ts_lsp_max = if ts_msp < range.beg() { range.beg() - ts_msp } else { 0 };
trace!(
"BCK ts_msp {} ts_lsp_max {} beg {} end {} {}",
ts_msp,
ts_lsp_max,
range.beg,
range.end,
range.beg(),
range.end(),
table_name,
);
// TODO use prepared!
@@ -253,10 +253,10 @@ where
let value = ValTy::default();
(ts, pulse, value)
};
if ts >= range.beg {
if ts >= range.beg() {
// TODO count as logic error
error!("ts >= range.beg");
} else if ts < range.beg {
} else if ts < range.beg() {
if pulse % 27 != 3618 {
ret.push(ts, pulse, value);
}
@@ -445,7 +445,7 @@ impl EventsStreamScylla {
self.ts_msp_fwd = msps2;
for x in self.ts_msp_bck.iter().rev() {
let x = x.clone();
if x >= self.range.end {
if x >= self.range.end() {
info!("FOUND one-after because of MSP");
self.found_one_after = true;
}
+26
View File
@@ -0,0 +1,26 @@
use netpod::range::evrange::SeriesRange;
#[derive(Debug, Clone)]
pub struct ScyllaSeriesRange {
beg: u64,
end: u64,
}
impl ScyllaSeriesRange {
pub fn beg(&self) -> u64 {
self.beg
}
pub fn end(&self) -> u64 {
self.end
}
}
impl From<&SeriesRange> for ScyllaSeriesRange {
fn from(value: &SeriesRange) -> Self {
match value {
SeriesRange::TimeRange(k) => Self { beg: k.beg, end: k.end },
SeriesRange::PulseRange(k) => Self { beg: k.beg, end: k.end },
}
}
}
+3 -41
View File
@@ -1,47 +1,9 @@
pub mod accounting;
pub mod bincache;
pub mod conn;
pub mod errconv;
pub mod events;
pub mod range;
pub mod status;
pub use scylla;
use err::Error;
use errconv::ErrConv;
use netpod::range::evrange::SeriesRange;
use netpod::ScyllaConfig;
use scylla::execution_profile::ExecutionProfileBuilder;
use scylla::statement::Consistency;
use scylla::Session as ScySession;
use std::sync::Arc;
#[derive(Debug, Clone)]
pub struct ScyllaSeriesRange {
beg: u64,
end: u64,
}
impl From<&SeriesRange> for ScyllaSeriesRange {
fn from(value: &SeriesRange) -> Self {
match value {
SeriesRange::TimeRange(k) => Self { beg: k.beg, end: k.end },
SeriesRange::PulseRange(k) => Self { beg: k.beg, end: k.end },
}
}
}
pub async fn create_scy_session(scyconf: &ScyllaConfig) -> Result<Arc<ScySession>, Error> {
let scy = scylla::SessionBuilder::new()
.known_nodes(&scyconf.hosts)
.use_keyspace(&scyconf.keyspace, true)
.default_execution_profile_handle(
ExecutionProfileBuilder::default()
.consistency(Consistency::LocalOne)
.build()
.into_handle(),
)
.build()
.await
.err_conv()?;
let ret = Arc::new(scy);
Ok(ret)
}
+2 -2
View File
@@ -143,13 +143,13 @@ impl ReadValues {
self.fut = self.make_fut(ts_msp);
true
} else {
info!("no more msp");
debug!("no more msp");
false
}
}
fn make_fut(&mut self, ts_msp: u64) -> Pin<Box<dyn Future<Output = Result<ChannelStatusEvents, Error>> + Send>> {
info!("make fut for {ts_msp}");
debug!("make fut for {ts_msp}");
let fut = read_next_status_events(
self.series,
ts_msp,