use mkit::{
self,
db::{self, Bloom},
};
use std::{cmp, convert::TryFrom, hash, marker, time};
use crate::{Error, Result};
pub struct BuildScan<K, V, D, I> {
iter: I,
entry: Option<db::Entry<K, V, D>>,
start: time::SystemTime,
seqno: u64,
n_count: u64,
n_deleted: u64,
_key: marker::PhantomData<K>,
_val: marker::PhantomData<V>,
}
impl<K, V, D, I> BuildScan<K, V, D, I> {
pub fn new(iter: I, seqno: u64) -> BuildScan<K, V, D, I> {
BuildScan {
iter,
entry: None,
start: time::SystemTime::now(),
seqno,
n_count: u64::default(),
n_deleted: u64::default(),
_key: marker::PhantomData,
_val: marker::PhantomData,
}
}
pub fn push(&mut self, entry: db::Entry<K, V, D>) {
self.entry = match &self.entry {
None => Some(entry),
Some(_) => unreachable!(),
}
}
pub fn unwrap(self) -> Result<(u64, u64, u64, u64, u64, I)> {
let build_time = {
let elapsed = err_at!(Fatal, self.start.elapsed())?;
err_at!(FailConvert, u64::try_from(elapsed.as_nanos()))?
};
let epoch = {
let elapsed = err_at!(Fatal, time::UNIX_EPOCH.elapsed())?;
err_at!(FailConvert, u64::try_from(elapsed.as_nanos()))?
};
Ok((
build_time,
self.seqno,
self.n_count,
self.n_deleted,
epoch,
self.iter,
))
}
}
impl<K, V, D, I> Iterator for BuildScan<K, V, D, I>
where
I: Iterator<Item = db::Entry<K, V, D>>,
{
type Item = db::Entry<K, V, D>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match self.entry.take() {
Some(entry) => Some(entry),
None => {
let entry = self.iter.next()?;
self.seqno = cmp::max(self.seqno, entry.to_seqno());
self.n_count += 1;
if entry.is_deleted() {
self.n_deleted += 1;
}
Some(entry)
}
}
}
}
pub struct BitmappedScan<K, V, D, B, I> {
iter: I,
bitmap: B,
_key: marker::PhantomData<K>,
_val: marker::PhantomData<V>,
_dff: marker::PhantomData<D>,
}
impl<K, V, D, B, I> BitmappedScan<K, V, D, B, I>
where
B: Bloom,
{
pub fn new(iter: I, bitmap: B) -> BitmappedScan<K, V, D, B, I> {
BitmappedScan {
iter,
bitmap,
_key: marker::PhantomData,
_val: marker::PhantomData,
_dff: marker::PhantomData,
}
}
pub fn unwrap(self) -> Result<(B, I)> {
Ok((self.bitmap, self.iter))
}
}
impl<K, V, D, B, I> Iterator for BitmappedScan<K, V, D, B, I>
where
K: hash::Hash,
B: Bloom,
I: Iterator<Item = db::Entry<K, V, D>>,
{
type Item = db::Entry<K, V, D>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let entry = self.iter.next()?;
self.bitmap.add_key(&entry.key);
Some(entry)
}
}
pub struct CompactScan<K, V, D, I> {
iter: I,
cutoff: db::Cutoff,
_key: marker::PhantomData<K>,
_val: marker::PhantomData<V>,
_dff: marker::PhantomData<D>,
}
impl<K, V, D, I> CompactScan<K, V, D, I> {
pub fn new(iter: I, cutoff: db::Cutoff) -> Self {
CompactScan {
iter,
cutoff,
_key: marker::PhantomData,
_val: marker::PhantomData,
_dff: marker::PhantomData,
}
}
}
impl<K, V, D, I> Iterator for CompactScan<K, V, D, I>
where
I: Iterator<Item = db::Entry<K, V, D>>,
{
type Item = db::Entry<K, V, D>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some(entry) = self.iter.next()?.purge(self.cutoff) {
break Some(entry);
}
}
}
}
#[cfg(test)]
#[path = "scans_test.rs"]
mod scans_test;