use bytes::Bytes;
use crate::Result;
use crate::vfs::Vfs;
use super::core::{BTree, SeenPageIds};
fn scan_guard() -> SeenPageIds {
SeenPageIds::new("btree_scan")
}
impl<V: Vfs> BTree<V> {
pub async fn collect_range(&self, start: &[u8], end: &[u8]) -> Result<Vec<(Bytes, Bytes)>> {
if self.root_page_id == 0 {
return Ok(Vec::new());
}
let mut path = self.path_to_leaf_for_key(start).await?;
let mut seen_leaves = scan_guard();
let mut out: Vec<(Bytes, Bytes)> = Vec::new();
loop {
let leaf_id = *path.last().expect("non-empty path");
seen_leaves.insert(leaf_id)?;
let leaf = self.read_leaf(leaf_id).await?;
for (k, v) in &leaf.records {
if k.as_slice() >= end {
return Ok(out);
}
if k.as_slice() >= start {
let val = self.resolve_leaf_value(v).await?;
out.push((Bytes::copy_from_slice(k), val));
}
}
match self.next_leaf_after(&path).await? {
Some(next_path) => path = next_path,
None => return Ok(out),
}
}
}
pub async fn collect_all(&self) -> Result<Vec<(Bytes, Bytes)>> {
if self.root_page_id == 0 {
return Ok(Vec::new());
}
let mut path = self.path_to_leaf_for_key(&[]).await?;
let mut seen_leaves = scan_guard();
let mut out: Vec<(Bytes, Bytes)> = Vec::new();
loop {
let leaf_id = *path.last().expect("non-empty path");
seen_leaves.insert(leaf_id)?;
let leaf = self.read_leaf(leaf_id).await?;
for (k, v) in &leaf.records {
let val = self.resolve_leaf_value(v).await?;
out.push((Bytes::copy_from_slice(k), val));
}
match self.next_leaf_after(&path).await? {
Some(next_path) => path = next_path,
None => return Ok(out),
}
}
}
pub async fn collect_batch_from(
&self,
start: &[u8],
limit: usize,
) -> Result<Vec<(Bytes, Bytes)>> {
if self.root_page_id == 0 || limit == 0 {
return Ok(Vec::new());
}
let mut path = self.path_to_leaf_for_key(start).await?;
let mut seen_leaves = scan_guard();
let mut out: Vec<(Bytes, Bytes)> = Vec::with_capacity(limit);
loop {
let leaf_id = *path.last().expect("non-empty path");
seen_leaves.insert(leaf_id)?;
let leaf = self.read_leaf(leaf_id).await?;
for (k, v) in &leaf.records {
if k.as_slice() < start {
continue;
}
if out.len() == limit {
return Ok(out);
}
let val = self.resolve_leaf_value(v).await?;
out.push((Bytes::copy_from_slice(k), val));
}
if out.len() == limit {
return Ok(out);
}
match self.next_leaf_after(&path).await? {
Some(next_path) => path = next_path,
None => return Ok(out),
}
}
}
pub async fn collect_prefix_batch_from(
&self,
prefix: &[u8],
start: &[u8],
limit: usize,
) -> Result<Vec<(Bytes, Bytes)>> {
let mut batch = self.collect_batch_from(start, limit).await?;
if let Some(end) = batch.iter().position(|(key, _)| !key.starts_with(prefix)) {
batch.truncate(end);
}
Ok(batch)
}
pub async fn first_key(&self) -> Result<Option<Vec<u8>>> {
if self.root_page_id == 0 {
return Ok(None);
}
let path = self.path_to_leaf_for_key(&[]).await?;
let leaf_id = *path.last().expect("non-empty path");
let leaf = self.read_leaf(leaf_id).await?;
Ok(leaf.records.first().map(|(k, _)| k.clone()))
}
pub async fn scan_rev(&self, start: &[u8], end: &[u8]) -> Result<Vec<(Bytes, Bytes)>> {
let mut forward = self.collect_range(start, end).await?;
forward.reverse();
Ok(forward)
}
pub async fn scan_prefix(&self, prefix: &[u8]) -> Result<Vec<(Bytes, Bytes)>> {
if self.root_page_id == 0 {
return Ok(Vec::new());
}
let mut path = self.path_to_leaf_for_key(prefix).await?;
let mut seen_leaves = scan_guard();
let mut out: Vec<(Bytes, Bytes)> = Vec::new();
loop {
let leaf_id = *path.last().expect("non-empty path");
seen_leaves.insert(leaf_id)?;
let leaf = self.read_leaf(leaf_id).await?;
let mut past_prefix = false;
for (k, v) in &leaf.records {
if k.as_slice() < prefix {
continue;
}
if !k.starts_with(prefix) {
past_prefix = true;
break;
}
let val = self.resolve_leaf_value(v).await?;
out.push((Bytes::copy_from_slice(k), val));
}
if past_prefix {
return Ok(out);
}
match self.next_leaf_after(&path).await? {
Some(next_path) => path = next_path,
None => return Ok(out),
}
}
}
}