use std::cell::UnsafeCell;
use std::fmt::{self, Debug};
use std::io::{self, SeekFrom};
use std::sync::Mutex;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::SeqCst;
use super::*;
mod lss;
mod iobuf;
mod reservation;
mod periodic_flusher;
pub use self::lss::*;
pub use self::iobuf::*;
pub use self::reservation::*;
pub trait Log: Sized {
fn reserve(&self, Vec<u8>) -> Reservation;
fn write(&self, Vec<u8>) -> LogID;
fn read(&self, id: LogID) -> io::Result<LogRead>;
fn stable_offset(&self) -> LogID;
fn make_stable(&self, id: LogID);
fn punch_hole(&self, id: LogID);
fn config(&self) -> &Config;
fn iter_from(&self, id: LogID) -> LogIter<Self> {
LogIter {
next_offset: id,
log: self,
}
}
}
#[doc(hidden)]
pub enum LogRead {
Flush(Vec<u8>, usize),
Aborted(usize),
Corrupted(usize),
}
impl LogRead {
pub fn flush(&self) -> Option<Vec<u8>> {
match *self {
LogRead::Flush(ref bytes, _) => Some(bytes.clone()),
_ => None,
}
}
pub fn is_flush(&self) -> bool {
match *self {
LogRead::Flush(_, _) => true,
_ => false,
}
}
pub fn is_abort(&self) -> bool {
match *self {
LogRead::Aborted(_) => true,
_ => false,
}
}
pub fn is_corrupt(&self) -> bool {
match *self {
LogRead::Corrupted(_) => true,
_ => false,
}
}
pub fn unwrap(self) -> Vec<u8> {
match self {
LogRead::Flush(bytes, _) => bytes,
_ => panic!("called unwrap on a non-flush LogRead"),
}
}
}
pub struct LogIter<'a, L: 'a + Log> {
next_offset: LogID,
log: &'a L,
}
impl<'a, L> Iterator for LogIter<'a, L>
where L: 'a + Log
{
type Item = (LogID, Vec<u8>);
fn next(&mut self) -> Option<Self::Item> {
loop {
match self.log.read(self.next_offset) {
Ok(LogRead::Flush(buf, len)) => {
let offset = self.next_offset;
self.next_offset += len as LogID + HEADER_LEN as LogID;
return Some((offset, buf));
}
Ok(LogRead::Aborted(len)) => self.next_offset += len as LogID + HEADER_LEN as LogID,
_ => return None,
}
}
}
}