1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
//! Runtime monitoring interface to query current system state from eCAL.
//!
//! This module wraps the C API `eCAL_Monitoring_GetMonitoring` and provides
//! a safe Rust API to access a snapshot of the middleware's state.
use crate::core_types::monitoring::{
ClientInfo, MonitoringSnapshot, ProcessInfo, ServerInfo, TopicInfo,
};
use crate::error::RustecalError;
use std::{ptr, slice};
/// Provides access to eCAL runtime monitoring data.
pub struct Monitoring;
impl Monitoring {
/// Retrieves a snapshot of the current system state from the eCAL runtime.
///
/// If no eCAL instances are running (nothing to monitor), returns an
/// empty `MonitoringSnapshot`. The C API signals “nothing to monitor”
/// by returning a non‑zero status.
///
/// # Errors
///
/// - `RustecalError::NullPointer` if the C API returns a null pointer
/// when a snapshot *should* have been provided.
pub fn get_snapshot() -> Result<MonitoringSnapshot, RustecalError> {
// 1) Prepare a null pointer for the C function to fill in
let mut raw: *mut rustecal_sys::eCAL_Monitoring_SMonitoring = ptr::null_mut();
// 2) Call the FFI: non‑zero means “no snapshot available”
let ret = unsafe { rustecal_sys::eCAL_Monitoring_GetMonitoring(&mut raw, ptr::null()) };
// 3) If nothing to monitor, return an empty snapshot
if ret != 0 {
return Ok(MonitoringSnapshot {
processes: Vec::new(),
publishers: Vec::new(),
subscribers: Vec::new(),
servers: Vec::new(),
clients: Vec::new(),
});
}
// 4) On success (ret == 0), ensure we got a valid pointer
if raw.is_null() {
return Err(RustecalError::NullPointer);
}
// 5) Build the snapshot and free the C‑allocated memory
let snapshot = unsafe {
let processes = {
let cnt = (*raw).processes_length;
let ptr = (*raw).processes;
slice::from_raw_parts(ptr, cnt)
.iter()
.map(|r| ProcessInfo::from(*r))
.collect()
};
let publishers = {
let cnt = (*raw).publishers_length;
let ptr = (*raw).publishers;
slice::from_raw_parts(ptr, cnt)
.iter()
.map(|r| TopicInfo::from(*r))
.collect()
};
let subscribers = {
let cnt = (*raw).subscribers_length;
let ptr = (*raw).subscribers;
slice::from_raw_parts(ptr, cnt)
.iter()
.map(|r| TopicInfo::from(*r))
.collect()
};
let servers = {
let cnt = (*raw).servers_length;
let ptr = (*raw).servers;
slice::from_raw_parts(ptr, cnt)
.iter()
.map(|r| ServerInfo::from(*r))
.collect()
};
let clients = {
let cnt = (*raw).clients_length;
let ptr = (*raw).clients;
slice::from_raw_parts(ptr, cnt)
.iter()
.map(|r| ClientInfo::from(*r))
.collect()
};
// free the C‑allocated snapshot
rustecal_sys::eCAL_Free(raw as *mut _);
MonitoringSnapshot {
processes,
publishers,
subscribers,
servers,
clients,
}
};
Ok(snapshot)
}
}