use std::fs::File;
use std::io::Result;
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: &'a 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"));
};
metadata.aux_size = len as _;
metadata.aux_offset = metadata.data_offset + metadata.data_size;
let arena = Arena::new(perf, metadata.aux_size as _, metadata.aux_offset as _)?;
let tail = unsafe { AtomicU64::from_ptr(&mut metadata.aux_tail as _) };
let head = unsafe { AtomicU64::from_ptr(&mut metadata.aux_head as _) };
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<'_> {
Iter(CowIter {
rb: Rb::new(self.arena.as_slice(), self.tail, self.head),
perf: self.perf,
})
}
}