use super::*;
pub struct Reservation<'a> {
pub iobufs: &'a IoBufs,
pub idx: usize,
pub data: Vec<u8>,
pub destination: &'a mut [u8],
pub flushed: bool,
pub base_disk_offset: LogID,
}
impl<'a> Drop for Reservation<'a> {
fn drop(&mut self) {
let should_flush = !self.data.is_empty() && !self.flushed;
if should_flush {
self.flush(false);
}
}
}
impl<'a> Reservation<'a> {
pub fn abort(mut self) {
self.flush(false);
}
pub fn complete(mut self) -> LogID {
self.flush(true)
}
pub fn log_id(&self) -> LogID {
self.base_disk_offset
}
fn flush(&mut self, valid: bool) -> LogID {
if self.flushed {
panic!("flushing already-flushed reservation!");
}
self.flushed = true;
if !valid {
zero_failed_buf(&mut self.data);
}
self.destination.copy_from_slice(&*self.data);
self.iobufs.exit_reservation(self.idx);
self.log_id()
}
}
#[inline(always)]
fn zero_failed_buf(buf: &mut [u8]) {
if buf.len() < HEADER_LEN {
panic!("somehow zeroing a buf shorter than HEADER_LEN");
}
buf[0] = 0;
for mut c in buf[5..].iter_mut() {
*c = 0;
}
}