Add initial support for request ID in scheduler #31

Merged
muellerr merged 7 commits from request_id_support_sched into main 2023-02-13 09:30:53 +01:00
Showing only changes of commit 08de5cb41c - Show all commits

View File

@ -11,7 +11,7 @@ use spacepackets::ecss::scheduling::TimeWindowType;
use spacepackets::ecss::{PusError, PusPacket}; use spacepackets::ecss::{PusError, PusPacket};
use spacepackets::tc::{GenericPusTcSecondaryHeader, PusTc}; use spacepackets::tc::{GenericPusTcSecondaryHeader, PusTc};
use spacepackets::time::cds::DaysLen24Bits; use spacepackets::time::cds::DaysLen24Bits;
use spacepackets::time::{CcsdsTimeProvider, TimeReader, TimestampError, UnixTimestamp}; use spacepackets::time::{CcsdsTimeProvider, cds, TimeReader, TimestampError, UnixTimestamp};
use spacepackets::CcsdsPacket; use spacepackets::CcsdsPacket;
use std::collections::BTreeMap; use std::collections::BTreeMap;
#[cfg(feature = "std")] #[cfg(feature = "std")]
@ -425,7 +425,9 @@ impl PusScheduler {
} }
/// This function uses [Self::retrieve_by_time_filter] to extract all scheduled commands inside /// This function uses [Self::retrieve_by_time_filter] to extract all scheduled commands inside
/// the time range and then deletes them from the provided store. /// the time range and then deletes them from the provided store. Like specified in the
/// documentation of [Self::retrieve_by_time_filter], the range extraction for deletion is
/// always inclusive.
pub fn delete_by_time_filter<TimeProvider: CcsdsTimeProvider + Clone>( pub fn delete_by_time_filter<TimeProvider: CcsdsTimeProvider + Clone>(
&mut self, &mut self,
time_window: TimeWindow<TimeProvider>, time_window: TimeWindow<TimeProvider>,
@ -434,6 +436,7 @@ impl PusScheduler {
let range = self.retrieve_by_time_filter(time_window); let range = self.retrieve_by_time_filter(time_window);
let mut del_packets = 0; let mut del_packets = 0;
let mut res_if_fails = None; let mut res_if_fails = None;
let mut keys_to_delete = Vec::new();
for time_bucket in range { for time_bucket in range {
for tc in time_bucket.1 { for tc in time_bucket.1 {
match pool.delete(tc.addr) { match pool.delete(tc.addr) {
@ -441,6 +444,10 @@ impl PusScheduler {
Err(e) => res_if_fails = Some(e), Err(e) => res_if_fails = Some(e),
} }
} }
keys_to_delete.push(*time_bucket.0);
}
for key in keys_to_delete {
self.tc_map.remove(&key);
} }
if let Some(err) = res_if_fails { if let Some(err) = res_if_fails {
return Err((del_packets, err)); return Err((del_packets, err));
@ -448,11 +455,19 @@ impl PusScheduler {
Ok(del_packets) Ok(del_packets)
} }
/// Deletes all the scheduled commands. This also deletes the packets from the passed TC pool.
pub fn delete_all(&mut self, pool: &mut (impl PoolProvider + ?Sized)) -> Result<u64, (u64, StoreError)> {
self.delete_by_time_filter(TimeWindow::<cds::TimeProvider>::new_select_all(), pool)
}
/// Retrieve a range over all scheduled commands.
pub fn retrieve_all(&mut self) -> Range<'_, UnixTimestamp, Vec<TcInfo>> { pub fn retrieve_all(&mut self) -> Range<'_, UnixTimestamp, Vec<TcInfo>> {
self.tc_map.range(..) self.tc_map.range(..)
} }
/// This retrieves scheduled telecommands which are inside the provided time window. /// This retrieves scheduled telecommands which are inside the provided time window.
/// It should be noted that the ranged extraction is always inclusive. For example, a range
/// from 50 to 100 unix seconds would also include command scheduled at 100 unix seconds.
pub fn retrieve_by_time_filter<TimeProvider: CcsdsTimeProvider>( pub fn retrieve_by_time_filter<TimeProvider: CcsdsTimeProvider>(
&mut self, &mut self,
time_window: TimeWindow<TimeProvider>, time_window: TimeWindow<TimeProvider>,
@ -1466,7 +1481,7 @@ mod tests {
} }
#[test] #[test]
fn test_time_window_retrieval_select_to_stamp() { fn test_time_window_retrieval_select_to_time() {
let mut pool = LocalPool::new(PoolCfg::new(vec![(10, 32), (5, 64)])); let mut pool = LocalPool::new(PoolCfg::new(vec![(10, 32), (5, 64)]));
let mut scheduler = let mut scheduler =
PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5));
@ -1497,7 +1512,7 @@ mod tests {
} }
#[test] #[test]
fn test_time_window_retrieval_select_from_to_stamp() { fn test_time_window_retrieval_select_from_time_to_time() {
let mut pool = LocalPool::new(PoolCfg::new(vec![(10, 32), (5, 64)])); let mut pool = LocalPool::new(PoolCfg::new(vec![(10, 32), (5, 64)]));
let mut scheduler = let mut scheduler =
PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5));
@ -1530,4 +1545,73 @@ mod tests {
} }
assert_eq!(tcs_in_range, 2); assert_eq!(tcs_in_range, 2);
} }
#[test]
fn test_deletion_all() {
let mut pool = LocalPool::new(PoolCfg::new(vec![(10, 32), (5, 64)]));
let mut scheduler =
PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5));
insert_command_with_release_time(&mut pool, &mut scheduler, 0, 50);
insert_command_with_release_time(&mut pool, &mut scheduler, 0, 100);
assert_eq!(scheduler.num_scheduled_telecommands(), 2);
let del_res = scheduler.delete_all(&mut pool);
assert!(del_res.is_ok());
assert_eq!(del_res.unwrap(), 2);
assert_eq!(scheduler.num_scheduled_telecommands(), 0);
// Contrary to reset, this does not disable the scheduler.
assert!(scheduler.is_enabled());
insert_command_with_release_time(&mut pool, &mut scheduler, 0, 50);
insert_command_with_release_time(&mut pool, &mut scheduler, 0, 100);
assert_eq!(scheduler.num_scheduled_telecommands(), 2);
let del_res = scheduler.delete_by_time_filter(TimeWindow::<cds::TimeProvider>::new_select_all(), &mut pool);
assert!(del_res.is_ok());
assert_eq!(del_res.unwrap(), 2);
assert_eq!(scheduler.num_scheduled_telecommands(), 0);
// Contrary to reset, this does not disable the scheduler.
assert!(scheduler.is_enabled());
}
#[test]
fn test_deletion_from_start_time() {
let mut pool = LocalPool::new(PoolCfg::new(vec![(10, 32), (5, 64)]));
let mut scheduler =
PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5));
insert_command_with_release_time(&mut pool, &mut scheduler, 0, 50);
let cmd_0_to_delete = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 100);
let cmd_1_to_delete = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 150);
assert_eq!(scheduler.num_scheduled_telecommands(), 3);
let start_stamp =
cds::TimeProvider::from_unix_secs_with_u16_days(&UnixTimestamp::new_only_seconds(100))
.expect("creating start stamp failed");
let time_window = TimeWindow::new_from_time(&start_stamp);
let del_res = scheduler.delete_by_time_filter(time_window, &mut pool);
assert!(del_res.is_ok());
assert_eq!(del_res.unwrap(), 2);
assert_eq!(scheduler.num_scheduled_telecommands(), 1);
assert!(!pool.has_element_at(&cmd_0_to_delete.addr()).unwrap());
assert!(!pool.has_element_at(&cmd_1_to_delete.addr()).unwrap());
}
#[test]
fn test_deletion_to_end_time() {
let mut pool = LocalPool::new(PoolCfg::new(vec![(10, 32), (5, 64)]));
let mut scheduler =
PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5));
let cmd_0_to_delete = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 50);
let cmd_1_to_delete = insert_command_with_release_time(&mut pool, &mut scheduler, 0, 100);
insert_command_with_release_time(&mut pool, &mut scheduler, 0, 150);
assert_eq!(scheduler.num_scheduled_telecommands(), 3);
let end_stamp =
cds::TimeProvider::from_unix_secs_with_u16_days(&UnixTimestamp::new_only_seconds(100))
.expect("creating start stamp failed");
let time_window = TimeWindow::new_from_time(&end_stamp);
let del_res = scheduler.delete_by_time_filter(time_window, &mut pool);
assert!(del_res.is_ok());
assert_eq!(del_res.unwrap(), 2);
assert_eq!(scheduler.num_scheduled_telecommands(), 1);
assert!(!pool.has_element_at(&cmd_0_to_delete.addr()).unwrap());
assert!(!pool.has_element_at(&cmd_1_to_delete.addr()).unwrap());
}
} }