use std::num::ParseIntError;
use std::path::{Path, PathBuf};
use std::{fmt, io};
use perf_event_open_sys::bindings;
use crate::events::Event;
#[derive(Clone, Copy, Debug)]
pub struct Tracepoint {
id: u64,
}
impl Tracepoint {
pub fn with_id(id: u64) -> Self {
Self { id }
}
pub fn with_name(name: impl AsRef<Path>) -> io::Result<Self> {
let mut path = PathBuf::from("/sys/kernel/debug/tracing/events");
path.push(name.as_ref());
path.push("id");
let id = std::fs::read_to_string(&path)?
.trim_end()
.parse()
.map_err(move |e| {
io::Error::new(io::ErrorKind::Other, UnparseableIdFile::new(path, e))
})?;
Ok(Self::with_id(id))
}
pub fn id(&self) -> u64 {
self.id
}
}
impl Event for Tracepoint {
fn update_attrs(self, attr: &mut bindings::perf_event_attr) {
attr.type_ = bindings::PERF_TYPE_TRACEPOINT;
attr.config = self.id;
}
}
#[derive(Debug)]
struct UnparseableIdFile {
path: PathBuf,
source: ParseIntError,
}
impl UnparseableIdFile {
fn new(path: PathBuf, source: ParseIntError) -> Self {
Self { path, source }
}
}
impl fmt::Display for UnparseableIdFile {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_fmt(format_args!(
"unparseable tracepoint id file `{}`",
self.path.display()
))
}
}
impl std::error::Error for UnparseableIdFile {
fn cause(&self) -> Option<&dyn std::error::Error> {
Some(&self.source)
}
}