From: Dietmar Maurer <dietmar@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] [PATCH proxmox-backup 4/9] New DailyDuration type with nom parser
Date: Tue, 9 Nov 2021 07:52:44 +0100 [thread overview]
Message-ID: <20211109065253.980304-8-dietmar@proxmox.com> (raw)
In-Reply-To: <20211109065253.980304-1-dietmar@proxmox.com>
We will use this to specify timesframes for network rate limits (only
apply limite when inside the time frame).
Note: This is not systemd related, but we can reuse some of the parser
method.
Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
---
proxmox-systemd/src/daily_duration.rs | 92 +++++++++++++++++++++++++++
proxmox-systemd/src/lib.rs | 1 +
proxmox-systemd/src/parse_time.rs | 56 ++++++++++++++++
proxmox-systemd/src/time.rs | 2 +-
4 files changed, 150 insertions(+), 1 deletion(-)
create mode 100644 proxmox-systemd/src/daily_duration.rs
diff --git a/proxmox-systemd/src/daily_duration.rs b/proxmox-systemd/src/daily_duration.rs
new file mode 100644
index 00000000..bed4eb47
--- /dev/null
+++ b/proxmox-systemd/src/daily_duration.rs
@@ -0,0 +1,92 @@
+use std::cmp::{Ordering, PartialOrd};
+
+use super::time::{WeekDays};
+
+pub use super::parse_time::parse_daily_duration;
+
+/// Time of Day (hour with minute)
+#[derive(Default, PartialEq, Clone, Debug)]
+pub struct HmTime {
+ pub hour: u32,
+ pub minute: u32,
+}
+
+impl PartialOrd for HmTime {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ let mut order = self.hour.cmp(&other.hour);
+ if order == Ordering::Equal {
+ order = self.minute.cmp(&other.minute);
+ }
+ Some(order)
+ }
+}
+
+#[derive(Default, Clone, Debug)]
+pub struct DailyDuration {
+ /// the days in a week this duration should trigger
+ pub days: WeekDays,
+ pub start: HmTime,
+ pub end: HmTime,
+}
+
+#[cfg(test)]
+mod test {
+
+ use anyhow::{bail, Error};
+
+ use super::*;
+
+ fn test_parse(
+ duration_str: &str,
+ start_h: u32, start_m: u32,
+ end_h: u32, end_m: u32,
+ days: &[usize],
+ ) -> Result<(), Error> {
+ let mut day_bits = 0;
+ for day in days { day_bits |= 1<<day; }
+ let expected_days = WeekDays::from_bits(day_bits).unwrap();
+
+ let duration = parse_daily_duration(duration_str)?;
+
+ if duration.start.hour != start_h {
+ bail!("start hour missmatch, extected {}, got {:?}", start_h, duration);
+ }
+ if duration.start.minute != start_m {
+ bail!("start minute missmatch, extected {}, got {:?}", start_m, duration);
+ }
+ if duration.end.hour != end_h {
+ bail!("end hour missmatch, extected {}, got {:?}", end_h, duration);
+ }
+ if duration.end.minute != end_m {
+ bail!("end minute missmatch, extected {}, got {:?}", end_m, duration);
+ }
+
+ if duration.days != expected_days {
+ bail!("weekday missmatch, extected {:?}, got {:?}", expected_days, duration);
+ }
+
+ Ok(())
+ }
+
+ #[test]
+ fn test_daily_duration_parser() -> Result<(), Error> {
+
+ assert!(parse_daily_duration("").is_err());
+ assert!(parse_daily_duration(" 8-12").is_err());
+ assert!(parse_daily_duration("8:60-12").is_err());
+ assert!(parse_daily_duration("8-25").is_err());
+ assert!(parse_daily_duration("12-8").is_err());
+
+ test_parse("8-12", 8, 0, 12, 0, &[])?;
+ test_parse("8:0-12:0", 8, 0, 12, 0, &[])?;
+ test_parse("8:00-12:00", 8, 0, 12, 0, &[])?;
+ test_parse("8:05-12:20", 8, 5, 12, 20, &[])?;
+ test_parse("8:05 - 12:20", 8, 5, 12, 20, &[])?;
+
+ test_parse("mon 8-12", 8, 0, 12, 0, &[0])?;
+ test_parse("tue..fri 8-12", 8, 0, 12, 0, &[1,2,3,4])?;
+ test_parse("sat,tue..thu,fri 8-12", 8, 0, 12, 0, &[1,2,3,4,5])?;
+
+ Ok(())
+ }
+}
diff --git a/proxmox-systemd/src/lib.rs b/proxmox-systemd/src/lib.rs
index b4ab4b72..7c2b1f90 100644
--- a/proxmox-systemd/src/lib.rs
+++ b/proxmox-systemd/src/lib.rs
@@ -1,4 +1,5 @@
pub mod time;
+pub mod daily_duration;
mod parse_time;
mod unit;
diff --git a/proxmox-systemd/src/parse_time.rs b/proxmox-systemd/src/parse_time.rs
index ba9449b1..d212e264 100644
--- a/proxmox-systemd/src/parse_time.rs
+++ b/proxmox-systemd/src/parse_time.rs
@@ -4,6 +4,7 @@ use anyhow::{bail, Error};
use lazy_static::lazy_static;
use super::time::*;
+use super::daily_duration::*;
use nom::{
error::{context, ParseError, VerboseError},
@@ -452,3 +453,58 @@ fn parse_time_span_incomplete(mut i: &str) -> IResult<&str, TimeSpan> {
Ok((i, ts))
}
+
+pub fn parse_daily_duration(i: &str) -> Result<DailyDuration, Error> {
+ parse_complete_line("daily duration", i, parse_daily_duration_incomplete)
+}
+
+fn parse_daily_duration_incomplete(mut i: &str) -> IResult<&str, DailyDuration> {
+
+ let mut duration = DailyDuration::default();
+
+ if i.starts_with(|c: char| char::is_ascii_alphabetic(&c)) {
+
+ let (n, range_list) = context(
+ "weekday range list",
+ separated_nonempty_list(tag(","), parse_weekdays_range)
+ )(i)?;
+
+ i = space0(n)?.0;
+
+ for range in range_list { duration.days.insert(range); }
+ }
+
+ let (i, start) = parse_hm_time(i)?;
+
+ let i = space0(i)?.0;
+
+ let (i, _) = tag("-")(i)?;
+
+ let i = space0(i)?.0;
+
+ let end_time_start = i;
+
+ let (i, end) = parse_hm_time(i)?;
+
+ if start > end {
+ return Err(parse_error(end_time_start, "end time before start time"));
+ }
+
+ duration.start = start;
+ duration.end = end;
+
+ Ok((i, duration))
+}
+
+fn parse_hm_time(i: &str) -> IResult<&str, HmTime> {
+
+ let (i, (hour, opt_minute)) = tuple((
+ parse_time_comp(24),
+ opt(preceded(tag(":"), parse_time_comp(60))),
+ ))(i)?;
+
+ match opt_minute {
+ Some(minute) => Ok((i, HmTime { hour, minute })),
+ None => Ok((i, HmTime { hour, minute: 0})),
+ }
+}
diff --git a/proxmox-systemd/src/time.rs b/proxmox-systemd/src/time.rs
index b81e970e..e5fe7965 100644
--- a/proxmox-systemd/src/time.rs
+++ b/proxmox-systemd/src/time.rs
@@ -5,7 +5,7 @@ use bitflags::bitflags;
use proxmox_time::TmEditor;
-pub use super::parse_time::*;
+pub use super::parse_time::{parse_calendar_event, parse_time_span};
bitflags!{
#[derive(Default)]
--
2.30.2
next prev parent reply other threads:[~2021-11-09 6:53 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-11-09 6:52 [pbs-devel] [PATCH proxmox/proxmox-backup] Rate Limiter Implementation Dietmar Maurer
2021-11-09 6:52 ` [pbs-devel] [PATCH proxmox 1/7] Implement a rate limiting stream (AsyncRead, AsyncWrite) Dietmar Maurer
2021-11-09 6:52 ` [pbs-devel] [PATCH proxmox-backup 1/9] pbs-client: add option to use the new RateLimiter Dietmar Maurer
2021-11-09 6:52 ` [pbs-devel] [PATCH proxmox 2/7] RateLimitedStream: implement poll_write_vectored Dietmar Maurer
2021-11-09 6:52 ` [pbs-devel] [PATCH proxmox-backup 2/9] proxmox-backup-client: add rate/burst parameter to backup CLI Dietmar Maurer
2021-11-09 6:52 ` [pbs-devel] [PATCH proxmox 3/7] HttpsConnector: use RateLimitedStream Dietmar Maurer
2021-11-09 6:52 ` [pbs-devel] [PATCH proxmox-backup 3/9] implement Servive for RateLimitedStream Dietmar Maurer
2021-11-09 6:52 ` Dietmar Maurer [this message]
2021-11-09 6:52 ` [pbs-devel] [PATCH proxmox 4/7] RateLimitedStream: allow periodic limiter updates Dietmar Maurer
2021-11-09 6:52 ` [pbs-devel] [PATCH proxmox-backup 5/9] DailyDuration: implement time_match() Dietmar Maurer
2021-11-09 6:52 ` [pbs-devel] [PATCH proxmox 5/7] RateLimiter: avoid panic in time computations Dietmar Maurer
2021-11-09 6:52 ` [pbs-devel] [PATCH proxmox-backup 6/9] Add traffic control configuration config with API Dietmar Maurer
2021-11-09 6:52 ` [pbs-devel] [PATCH proxmox 6/7] RateLimitedStream: implement peer_addr Dietmar Maurer
2021-11-09 6:52 ` [pbs-devel] [PATCH proxmox 7/7] RateLimiter: add update_rate method Dietmar Maurer
2021-11-09 6:52 ` [pbs-devel] [PATCH proxmox-backup 7/9] traffic_control: use Memcom to track. config versions Dietmar Maurer
2021-11-09 6:52 ` [pbs-devel] [PATCH proxmox-backup 8/9] implement a traffic control cache for fast rate control limiter lockups Dietmar Maurer
2021-11-09 6:52 ` [pbs-devel] [PATCH proxmox-backup 9/9] proxmox-backup-proxy: implement traffic control Dietmar Maurer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20211109065253.980304-8-dietmar@proxmox.com \
--to=dietmar@proxmox.com \
--cc=pbs-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox