use std::collections::BTreeMap;
use std::fmt::{self, Debug};
use std::sync::Arc;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::SeqCst;
use bincode::{Infinite, deserialize, serialize};
use serde::de::DeserializeOwned;
use serde::Serialize;
use coco::epoch::Ptr;
use super::*;
mod page_cache;
pub use self::page_cache::PageCache;
pub trait Materializer {
type PageFrag;
type Recovery;
fn merge(&self, &[&Self::PageFrag]) -> Self::PageFrag;
fn recover(&self, &Self::PageFrag) -> Option<Self::Recovery>;
}
#[derive(Debug, Clone, PartialEq)]
pub enum CacheEntry<M: Send + Sync> {
MergedResident(M, LogID),
Resident(M, LogID),
PartialFlush(LogID),
Flush(LogID),
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct CasKey<P>
where P: 'static + Send + Sync
{
ptr: *const ds::stack::Node<CacheEntry<P>>,
tag: usize,
}
impl<'s, P> From<Ptr<'s, ds::stack::Node<CacheEntry<P>>>> for CasKey<P>
where P: 'static + Send + Sync
{
fn from(ptr: Ptr<'s, ds::stack::Node<CacheEntry<P>>>) -> CasKey<P> {
CasKey {
ptr: ptr.as_raw(),
tag: ptr.tag(),
}
}
}
impl<'s, P> Into<Ptr<'s, ds::stack::Node<CacheEntry<P>>>> for CasKey<P>
where P: 'static + Send + Sync
{
fn into(self) -> Ptr<'s, ds::stack::Node<CacheEntry<P>>> {
unsafe { Ptr::from_raw(self.ptr).with_tag(self.tag) }
}
}
#[serde(bound(deserialize = ""))]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub(super) struct LoggedUpdate<PageFrag>
where PageFrag: Serialize + DeserializeOwned
{
pid: PageID,
update: Update<PageFrag>,
}
#[serde(bound(deserialize = ""))]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
enum Update<PageFrag>
where PageFrag: DeserializeOwned + Serialize
{
Append(PageFrag),
Compact(PageFrag),
Del,
Alloc,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
struct Snapshot<R> {
pub max_lid: LogID,
pub max_pid: PageID,
pub pt: BTreeMap<PageID, Vec<LogID>>,
pub free: Vec<PageID>,
pub recovery: Option<R>,
}
impl<R> Default for Snapshot<R> {
fn default() -> Snapshot<R> {
Snapshot {
max_lid: 0,
max_pid: 0,
pt: BTreeMap::new(),
free: vec![],
recovery: None,
}
}
}
struct PidDropper(PageID, Arc<Stack<PageID>>);
impl Drop for PidDropper {
fn drop(&mut self) {
self.1.push(self.0);
}
}
struct LidDropper(Vec<LogID>, Config);
impl Drop for LidDropper {
fn drop(&mut self) {
let cached_f = self.1.cached_file();
let mut f = cached_f.borrow_mut();
for lid in &self.0 {
if let Err(_e) = log::punch_hole(&mut f, *lid) {
#[cfg(feature = "log")]
error!("failed to punch hole in log: {}", _e);
}
}
}
}