[pbs-devel] [proxmox-backup] CalendarEvent: add calendar_event_match and fix compute_next_event
Dietmar Maurer
dietmar at proxmox.com
Fri Nov 5 10:58:34 CET 2021
Signed-off-by: Dietmar Maurer <dietmar at proxmox.com>
---
proxmox-systemd/src/parse_time.rs | 4 +-
proxmox-systemd/src/time.rs | 129 +++++++++++++++++++++++++++++-
2 files changed, 130 insertions(+), 3 deletions(-)
diff --git a/proxmox-systemd/src/parse_time.rs b/proxmox-systemd/src/parse_time.rs
index ba9449b1..9a2ecd77 100644
--- a/proxmox-systemd/src/parse_time.rs
+++ b/proxmox-systemd/src/parse_time.rs
@@ -211,7 +211,7 @@ fn parse_date_time_comp_list(start: u32, max: usize) -> impl Fn(&str) -> IResult
return Ok((n, vec![DateTimeValue::Repeated(start, repeat)]));
}
}
- return Ok((rest, Vec::new()));
+ return Ok((rest, vec![DateTimeValue::Range(start, max as u32)]));
}
separated_nonempty_list(tag(","), parse_date_time_comp(max))(i)
@@ -229,7 +229,7 @@ fn parse_time_spec(i: &str) -> IResult<&str, TimeSpec> {
if let Some(second) = opt_second {
Ok((i, TimeSpec { hour, minute, second }))
} else {
- Ok((i, TimeSpec { hour, minute, second: vec![DateTimeValue::Single(0)] }))
+ Ok((i, TimeSpec { hour, minute, second: Vec::new() }))
}
}
diff --git a/proxmox-systemd/src/time.rs b/proxmox-systemd/src/time.rs
index b81e970e..acba4763 100644
--- a/proxmox-systemd/src/time.rs
+++ b/proxmox-systemd/src/time.rs
@@ -234,6 +234,69 @@ pub fn verify_calendar_event(i: &str) -> Result<(), Error> {
Ok(())
}
+pub fn calendar_event_match(
+ event: &CalendarEvent,
+ epoch: i64,
+ utc: bool,
+) -> Result<bool, Error> {
+
+ let t = TmEditor::with_epoch(epoch, utc)?;
+
+ if !event.year.is_empty() {
+ let year: u32 = t.year().try_into()?;
+ if !DateTimeValue::list_contains(&event.year, year) {
+ return Ok(false);
+ }
+ }
+
+ if !event.month.is_empty() {
+ let month: u32 = t.month().try_into()?;
+ if !DateTimeValue::list_contains(&event.month, month) {
+ return Ok(false);
+ }
+ }
+
+ if !event.day.is_empty() {
+ let day: u32 = t.day().try_into()?;
+ if !DateTimeValue::list_contains(&event.day, day) {
+ return Ok(false);
+ }
+ }
+
+ let all_days = event.days.is_empty() || event.days.is_all();
+
+ if !all_days {
+ let day_num: u32 = t.day_num().try_into()?;
+ let day = WeekDays::from_bits(1<<day_num).unwrap();
+ if !event.days.contains(day) {
+ return Ok(false);
+ }
+ }
+
+ if !event.hour.is_empty() {
+ let hour = t.hour().try_into()?;
+ if !DateTimeValue::list_contains(&event.hour, hour) {
+ return Ok(false);
+ }
+ }
+
+ if !event.minute.is_empty() {
+ let minute = t.min().try_into()?;
+ if !DateTimeValue::list_contains(&event.minute, minute) {
+ return Ok(false);
+ }
+ }
+
+ if !event.second.is_empty() {
+ let second = t.sec().try_into()?;
+ if !DateTimeValue::list_contains(&event.second, second) {
+ return Ok(false);
+ }
+ }
+
+ Ok(true)
+}
+
pub fn compute_next_event(
event: &CalendarEvent,
last: i64,
@@ -339,6 +402,29 @@ pub fn compute_next_event(
t.set_time(t.hour() + 1, 0, 0)?;
}
continue;
+ } else {
+ // Match, but
+ if event.second.is_empty() && t.sec() != 0 {
+ if let Some(n) = DateTimeValue::find_next(&event.minute, minute) {
+ // test next minute
+ t.set_min_sec(n.try_into()?, 0)?;
+ } else {
+ // test next hour
+ if !event.hour.is_empty() {
+ let hour = t.hour().try_into()?;
+ if let Some(n) = DateTimeValue::find_next(&event.hour, hour) {
+ // test next hour
+ t.set_time(n.try_into()?, 0, 0)?;
+ } else {
+ // test next day
+ t.add_days(1)?;
+ }
+ } else {
+ t.set_time(t.hour() + 1, 0, 0)?;
+ }
+ }
+ continue;
+ }
}
}
@@ -383,6 +469,47 @@ mod test {
(mday*3600*24 + hour*3600 + min*60) as i64
}
+ #[test]
+ fn test_date_time_value_contains() -> Result<(), Error> {
+
+ let dtv = DateTimeValue::Repeated(5, 2);
+
+ assert!(!dtv.contains(0));
+ assert!(!dtv.contains(1));
+ assert!(!dtv.contains(2));
+ assert!(!dtv.contains(3));
+ assert!(!dtv.contains(4));
+ assert!(dtv.contains(5));
+ assert!(!dtv.contains(6));
+ assert!(dtv.contains(7));
+ assert!(!dtv.contains(8));
+
+ Ok(())
+ }
+
+ #[test]
+ fn test_event_match() -> Result<(), Error> {
+
+ const THURSDAY_00_00: i64 = make_test_time(0, 0, 0);
+ const SATURDAY_09_00: i64 = make_test_time(2, 9, 0);
+ const SUNDAY_09_00: i64 = make_test_time(3, 9, 0);
+
+ let event = parse_calendar_event("mon..fri 8..16:*")?;
+
+ const HOUR: i64 = 3600;
+
+ assert!(!calendar_event_match(&event, THURSDAY_00_00, true)?);
+ assert!(!calendar_event_match(&event, THURSDAY_00_00 + 7*HOUR, true)?);
+ assert!(calendar_event_match(&event, THURSDAY_00_00 + 8*HOUR, true)?);
+ assert!(calendar_event_match(&event, THURSDAY_00_00 + 15*HOUR, true)?);
+ assert!(calendar_event_match(&event, THURSDAY_00_00 + 16*HOUR, true)?);
+ assert!(!calendar_event_match(&event, THURSDAY_00_00 + 17*HOUR, true)?);
+ assert!(!calendar_event_match(&event, SATURDAY_09_00, true)?);
+ assert!(!calendar_event_match(&event, SUNDAY_09_00, true)?);
+
+ Ok(())
+ }
+
#[test]
fn test_compute_next_event() -> Result<(), Error> {
@@ -405,7 +532,7 @@ mod test {
);
}
}
- Ok(None) => bail!("next {:?} failed to find a timestamp", event),
+ Ok(None) => bail!("next {} {:?} failed to find a timestamp", v, event),
Err(err) => bail!("compute next for '{}' failed - {}", v, err),
}
--
2.30.2
More information about the pbs-devel
mailing list