use std::fs::File;
use std::io::Result;
use std::slice;
use std::sync::atomic::AtomicU64;
use iter::{CowIter, Iter};
use rb::Rb;
use super::arena::Arena;
use crate::ffi::Metadata;
pub mod iter;
mod rb;
pub struct AuxTracer<'a> {
tail: &'a AtomicU64,
head: &'a AtomicU64,
arena: Arena,
perf: &'a File,
}
impl<'a> AuxTracer<'a> {
pub(crate) fn new(perf: &'a File, metadata: *mut Metadata, exp: u8) -> Result<Self> {
#[cfg(feature = "linux-4.1")]
return {
use std::io::Error;
use crate::ffi::PAGE_SIZE;
let Some(len) = 2_usize
.checked_pow(exp as u32)
.and_then(|n| n.checked_mul(*PAGE_SIZE))
else {
return Err(Error::other("allocation size overflow"));
};
let aux_offset = unsafe { (*metadata).data_offset + (*metadata).data_size };
unsafe { (*metadata).aux_size = len as _ };
unsafe { (*metadata).aux_offset = aux_offset };
let arena = Arena::new(perf, len, aux_offset as _)?;
let tail = unsafe { AtomicU64::from_ptr(&mut (*metadata).aux_tail) };
let head = unsafe { AtomicU64::from_ptr(&mut (*metadata).aux_head) };
Ok(Self {
tail,
head,
arena,
perf,
})
};
#[cfg(not(feature = "linux-4.1"))]
return {
let _ = perf;
let _ = metadata;
let _ = exp;
Err(std::io::ErrorKind::Unsupported.into())
};
}
pub fn iter(&self) -> Iter<'_> {
let rb_ptr = self.arena.as_ptr();
let rb_len = self.arena.len();
let rb_alloc = unsafe { slice::from_raw_parts(rb_ptr, rb_len) };
Iter(CowIter {
rb: Rb::new(rb_alloc, self.tail, self.head),
perf: self.perf,
})
}
}