mod backward;
use std::sync::Arc;
use tessarikv_types::{KeyspaceId, SequenceNumber, ValueKind};
use super::Db;
use super::merge::{MergedVersions, Source};
use super::snapshot::Snapshot;
use super::table_versions::TableVersions;
use super::view::View;
use crate::memtable::MemtableCursor;
use crate::tombstones::Fragments;
use crate::{ReadOptions, Result};
pub struct DbIterator<'a> {
versions: MergedVersions<'static>,
snapshot: SequenceNumber,
fragments: Fragments,
lower: Option<Vec<u8>>,
upper: Option<Vec<u8>>,
key: Vec<u8>,
valid: bool,
backward: bool,
saved: Vec<u8>,
_snapshot: Option<Snapshot<'a>>,
}
impl Db {
pub fn iter(&self, keyspace: KeyspaceId, options: &ReadOptions) -> Result<DbIterator<'_>> {
self.check_keyspace(keyspace)?;
let snapshot = self.snapshot()?;
let sequence = snapshot.sequence();
DbIterator::new(
&self.view.load_full(),
keyspace,
sequence,
options,
Some(snapshot),
)
}
}
impl<'a> DbIterator<'a> {
pub(super) fn new(
view: &View,
keyspace: KeyspaceId,
snapshot: SequenceNumber,
options: &ReadOptions,
registration: Option<Snapshot<'a>>,
) -> Result<Self> {
let fragments = Fragments::new(&view.tombstones(keyspace.get())?, snapshot);
let sources = view
.shared_memtables(keyspace.get())
.map(|table| Source::Shared(MemtableCursor::new(Arc::clone(table))))
.chain(view.files(keyspace.get()).map(|file| {
let versions = TableVersions::new(file, options.fill_cache);
Source::Table(Box::new(versions))
}))
.collect();
Ok(Self {
versions: MergedVersions::new(sources),
snapshot,
fragments,
lower: options.lower_bound.clone(),
upper: options.upper_bound.clone(),
key: Vec::new(),
valid: false,
backward: false,
saved: Vec::new(),
_snapshot: registration,
})
}
pub fn valid(&self) -> bool {
self.valid
}
pub fn key(&self) -> &[u8] {
if self.valid { &self.key } else { &[] }
}
pub fn value(&self) -> &[u8] {
if !self.valid {
return &[];
}
if self.backward {
return &self.saved;
}
self.versions.entry().map_or(&[], |version| version.value)
}
pub async fn seek_to_first(&mut self) -> Result<()> {
let lower = self.lower.take();
let moved = self.position_at(lower.as_deref().unwrap_or_default()).await;
self.lower = lower;
moved
}
pub async fn seek(&mut self, key: &[u8]) -> Result<()> {
let lower = self.lower.take();
let start = match lower.as_deref() {
Some(lower) if lower > key => lower,
_ => key,
};
let moved = self.position_at(start).await;
self.lower = lower;
moved
}
pub async fn next(&mut self) -> Result<()> {
if !self.valid {
return Ok(());
}
if self.backward {
let key = std::mem::take(&mut self.key);
self.position_at(&key).await?;
if !self.valid {
return Ok(());
}
}
self.valid = false;
self.versions.next().await;
self.settle(true).await
}
async fn position_at(&mut self, start: &[u8]) -> Result<()> {
self.valid = false;
self.backward = false;
self.versions.seek(start, self.snapshot).await;
self.key.clear();
self.settle(false).await
}
async fn settle(&mut self, mut skipping: bool) -> Result<()> {
self.valid = false;
while let Some(version) = self.versions.entry() {
if self
.upper
.as_deref()
.is_some_and(|upper| version.user_key >= upper)
{
break;
}
let passed = version.sequence > self.snapshot
|| (skipping && version.user_key == self.key.as_slice());
if !passed {
self.key.clear();
self.key.extend_from_slice(version.user_key);
if version.kind == ValueKind::Value
&& !self.fragments.deletes(version.user_key, version.sequence)
{
self.valid = true;
break;
}
skipping = true;
}
self.versions.next().await;
}
if !self.valid {
self.key.clear();
}
self.finish_move()
}
fn finish_move(&mut self) -> Result<()> {
match self.versions.take_error() {
Some(error) => {
self.valid = false;
self.key.clear();
Err(error)
}
None => Ok(()),
}
}
}