use std::cmp::Ordering;
use std::sync::Arc;
use tessarikv_sync::{Cursor, CursorPosition};
use tessarikv_types::{
InternalKeyRef, SequenceNumber, ValueKind, compare_internal, encode_internal, seek_trailer,
};
use super::{InternalKeyComparator, Memtable};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) struct MemtableEntry<'a> {
pub(crate) user_key: &'a [u8],
pub(crate) sequence: SequenceNumber,
pub(crate) kind: ValueKind,
pub(crate) value: &'a [u8],
}
pub(crate) struct MemtableIter<'a> {
cursor: Cursor<'a, InternalKeyComparator>,
seek_key: Vec<u8>,
}
impl<'a> MemtableIter<'a> {
pub(super) fn new(cursor: Cursor<'a, InternalKeyComparator>) -> Self {
Self {
cursor,
seek_key: Vec::new(),
}
}
pub(crate) fn seek_to_first(&mut self) {
self.cursor.seek_to_first();
}
pub(crate) fn seek(&mut self, key: &[u8], snapshot: SequenceNumber) {
self.seek_key.clear();
encode_internal(key, seek_trailer(snapshot), &mut self.seek_key);
self.cursor.seek(&self.seek_key);
}
pub(crate) fn next(&mut self) {
self.cursor.next();
}
pub(crate) fn seek_to_last(&mut self) {
self.cursor.seek_to_last();
}
pub(crate) fn seek_for_prev(&mut self, target: &[u8]) {
self.cursor.seek(target);
if !self.cursor.valid() {
self.cursor.seek_to_last();
} else if compare_internal(self.cursor.key(), target) == Ordering::Greater {
self.cursor.prev();
}
}
pub(crate) fn prev(&mut self) {
self.cursor.prev();
}
pub(crate) fn entry(&self) -> Option<MemtableEntry<'a>> {
if !self.cursor.valid() {
return None;
}
let internal = InternalKeyRef::parse(self.cursor.key()).ok()?;
Some(MemtableEntry {
user_key: internal.user_key(),
sequence: internal.trailer().sequence(),
kind: internal.trailer().kind().ok()?,
value: self.cursor.value(),
})
}
}
pub(crate) struct MemtableCursor {
table: Arc<Memtable>,
position: CursorPosition,
seek_key: Vec<u8>,
}
impl MemtableCursor {
pub(crate) fn new(table: Arc<Memtable>) -> Self {
let position = table.entries.cursor().position();
Self {
table,
position,
seek_key: Vec::new(),
}
}
pub(crate) fn seek(&mut self, key: &[u8], snapshot: SequenceNumber) {
self.step(|versions| versions.seek(key, snapshot));
}
pub(crate) fn next(&mut self) {
self.step(|versions| versions.next());
}
pub(crate) fn seek_to_last(&mut self) {
self.step(|versions| versions.seek_to_last());
}
pub(crate) fn seek_for_prev(&mut self, target: &[u8]) {
self.step(|versions| versions.seek_for_prev(target));
}
pub(crate) fn prev(&mut self) {
self.step(|versions| versions.prev());
}
pub(crate) fn entry(&self) -> Option<MemtableEntry<'_>> {
MemtableIter::new(self.table.entries.cursor_at(self.position)).entry()
}
fn step(&mut self, move_to: impl FnOnce(&mut MemtableIter<'_>)) {
let mut versions = MemtableIter {
cursor: self.table.entries.cursor_at(self.position),
seek_key: std::mem::take(&mut self.seek_key),
};
move_to(&mut versions);
self.position = versions.cursor.position();
self.seek_key = versions.seek_key;
}
}