#[derive(Default, Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
#[derive(Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct MemoryOrInputOutputTimeStalled
{
pub some: TimeStalled,
pub full: TimeStalled,
}
impl MemoryOrInputOutputTimeStalled
{
pub fn monitor_some(file_path: &Path, maximum_total_stall_time_in_window: U64Microseconds, window: U64Microseconds) -> io::Result<File>
{
Self::monitor(file_path, "some", maximum_total_stall_time_in_window, window)
}
pub fn monitor_all(file_path: &Path, maximum_total_stall_time_in_window: U64Microseconds, window: U64Microseconds) -> io::Result<File>
{
Self::monitor(file_path, "all", maximum_total_stall_time_in_window, window)
}
fn monitor(file_path: &Path, name: &str, maximum_total_stall_time_in_window: U64Microseconds, window: U64Microseconds) -> io::Result<File>
{
assert!(maximum_total_stall_time_in_window <= window);
let mut file = OpenOptions::new().read(true).write(true).open(file_path)?;
file.write_all(format!("{} {} {}\n", name, maximum_total_stall_time_in_window.0, window.0).as_ref())?;
Ok(file)
}
#[inline(always)]
pub fn memory_for_self(proc_path: &ProcPath) -> io::Result<Self>
{
Self::memory_for_process(proc_path, ProcessIdentifierChoice::Current)
}
#[inline(always)]
pub fn memory_for_process(proc_path: &ProcPath, process_identifier: ProcessIdentifierChoice) -> io::Result<Self>
{
Self::for_process(proc_path, process_identifier, "memory")
}
#[inline(always)]
pub fn input_output_for_self(proc_path: &ProcPath) -> io::Result<Self>
{
Self::input_output_for_process(proc_path, ProcessIdentifierChoice::Current)
}
#[inline(always)]
pub fn input_output_for_process(proc_path: &ProcPath, process_identifier: ProcessIdentifierChoice) -> io::Result<Self>
{
Self::for_process(proc_path, process_identifier, "io")
}
#[inline(always)]
fn for_process(proc_path: &ProcPath, process_identifier: ProcessIdentifierChoice, file_name: &str) -> io::Result<Self>
{
let file_path = proc_path.process_pressure_stall_information_file_path(process_identifier, file_name);
Self::from_file(&file_path)
}
#[inline(always)]
pub(crate) fn from_file(file_path: &impl AsRef<Path>) -> io::Result<Self>
{
#[inline(always)]
fn store_field(time_stalled: TimeStalled, field: &mut Option<TimeStalled>) -> io::Result<()>
{
if field.is_some()
{
Err(io_error_invalid_data("duplicate field"))
}
else
{
*field = Some(time_stalled);
Ok(())
}
}
#[inline(always)]
fn unwrap_field<T: FromBytes>(field: Option<T>) -> io::Result<T>
{
field.ok_or(io_error_invalid_data("Missing field"))
}
let bytes = file_path.as_ref().read_raw()?;
let mut some = None;
let mut full = None;
for line in bytes.split_bytes(b'\n')
{
let (name, time_stalled) = TimeStalled::parse_line(line)?;
match name
{
b"some" => store_field(time_stalled, &mut some)?,
b"full" => store_field(time_stalled, &mut full)?,
_ => continue,
}
}
Ok
(
Self
{
some: unwrap_field(some)?,
full: unwrap_field(full)?,
}
)
}
}