use std::cmp::Ordering;
use tessarikv_types::{SequenceNumber, ValueKind};
use super::table_versions::TableVersions;
use crate::memtable::{MemtableCursor, MemtableEntry, MemtableIter};
use crate::{Error, Result};
#[derive(Debug, Clone, Copy)]
pub(super) struct KeyVersion<'a> {
pub(super) user_key: &'a [u8],
pub(super) sequence: SequenceNumber,
pub(super) kind: ValueKind,
pub(super) value: &'a [u8],
}
impl<'a> From<MemtableEntry<'a>> for KeyVersion<'a> {
fn from(entry: MemtableEntry<'a>) -> Self {
Self {
user_key: entry.user_key,
sequence: entry.sequence,
kind: entry.kind,
value: entry.value,
}
}
}
pub(super) enum Source<'a> {
Memtable(MemtableIter<'a>),
Shared(MemtableCursor),
Table(Box<TableVersions>),
}
impl Source<'_> {
async fn seek(&mut self, key: &[u8], snapshot: SequenceNumber) {
match self {
Self::Memtable(versions) => versions.seek(key, snapshot),
Self::Shared(versions) => versions.seek(key, snapshot),
Self::Table(versions) => versions.seek(key, snapshot).await,
}
}
async fn next(&mut self) {
match self {
Self::Memtable(versions) => versions.next(),
Self::Shared(versions) => versions.next(),
Self::Table(versions) => versions.next().await,
}
}
async fn seek_to_last(&mut self) {
match self {
Self::Memtable(versions) => versions.seek_to_last(),
Self::Shared(versions) => versions.seek_to_last(),
Self::Table(versions) => versions.seek_to_last().await,
}
}
async fn seek_for_prev(&mut self, target: &[u8]) {
match self {
Self::Memtable(versions) => versions.seek_for_prev(target),
Self::Shared(versions) => versions.seek_for_prev(target),
Self::Table(versions) => versions.seek_for_prev(target).await,
}
}
async fn prev(&mut self) {
match self {
Self::Memtable(versions) => versions.prev(),
Self::Shared(versions) => versions.prev(),
Self::Table(versions) => versions.prev().await,
}
}
fn entry(&self) -> Option<KeyVersion<'_>> {
match self {
Self::Memtable(versions) => versions.entry().map(KeyVersion::from),
Self::Shared(versions) => versions.entry().map(KeyVersion::from),
Self::Table(versions) => versions.entry(),
}
}
}
pub(super) struct MergedVersions<'a> {
sources: Vec<Source<'a>>,
backward: bool,
}
impl<'a> MergedVersions<'a> {
pub(super) fn new(sources: Vec<Source<'a>>) -> Self {
Self {
sources,
backward: false,
}
}
pub(super) async fn seek(&mut self, key: &[u8], snapshot: SequenceNumber) {
self.backward = false;
for source in &mut self.sources {
source.seek(key, snapshot).await;
}
}
pub(super) async fn seek_to_last(&mut self) {
self.backward = true;
for source in &mut self.sources {
source.seek_to_last().await;
}
}
pub(super) async fn seek_for_prev(&mut self, target: &[u8]) {
self.backward = true;
for source in &mut self.sources {
source.seek_for_prev(target).await;
}
}
pub(super) fn entry(&self) -> Option<KeyVersion<'_>> {
self.current().map(|(_, entry)| entry)
}
pub(super) async fn next(&mut self) {
if let Some((index, _)) = self.current()
&& let Some(source) = self.sources.get_mut(index)
{
source.next().await;
}
}
pub(super) async fn prev(&mut self) {
if let Some((index, _)) = self.current()
&& let Some(source) = self.sources.get_mut(index)
{
source.prev().await;
}
}
pub(super) fn take_error(&mut self) -> Option<Error> {
self.sources.iter_mut().find_map(|source| match source {
Source::Table(versions) => versions.take_error(),
Source::Memtable(_) | Source::Shared(_) => None,
})
}
pub(super) fn finish(mut self) -> Result<()> {
match self.take_error() {
Some(error) => Err(error),
None => Ok(()),
}
}
fn current(&self) -> Option<(usize, KeyVersion<'_>)> {
let versions = self
.sources
.iter()
.enumerate()
.filter_map(|(index, source)| source.entry().map(|entry| (index, entry)));
if self.backward {
versions.max_by(|(_, left), (_, right)| version_order(left, right))
} else {
versions.min_by(|(_, left), (_, right)| version_order(left, right))
}
}
}
fn version_order(left: &KeyVersion<'_>, right: &KeyVersion<'_>) -> Ordering {
left.user_key
.cmp(right.user_key)
.then_with(|| right.sequence.cmp(&left.sequence))
}