Skip to content

Commit

Permalink
[Feat] Block index with unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Gifted-s committed Aug 4, 2024
1 parent f696277 commit 56d2008
Show file tree
Hide file tree
Showing 5 changed files with 412 additions and 1 deletion.
1 change: 1 addition & 0 deletions v2/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ byteorder = "1.5.0"
crc32fast = "1.4.2"
crossbeam-skiplist = "0.1.3"
guardian = "1.1.0"
log = "0.4.22"
lz4_flex = "0.11.3"
nanoid = "0.4.0"
path-absolutize = "3.1.1"
Expand Down
72 changes: 72 additions & 0 deletions v2/src/sst/block_index/block_handle.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
use crate::lsm_entry::UserKey;
use crate::serde::{Deserializable, Serializable};
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use std::io::{Read, Write};
use std::sync::Arc;

/// Points to a block on file
#[derive(Clone, Debug)]
#[allow(clippy::module_name_repetitions)]
pub struct KeyedBlockHandle {
/// Key of last item block
pub end_key: UserKey,

/// Position of block in file
pub offset: u64,
}

impl PartialEq for KeyedBlockHandle {
fn eq(&self, other: &Self) -> bool {
self.offset == other.offset
}
}

impl Eq for KeyedBlockHandle {}

impl std::hash::Hash for KeyedBlockHandle {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
state.write_u64(self.offset);
}
}
impl PartialOrd for KeyedBlockHandle {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}

impl Ord for KeyedBlockHandle {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
(&self.end_key, self.offset).cmp(&(&other.end_key, other.offset))
}
}

impl Serializable for KeyedBlockHandle {
fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), crate::SerializeError> {
writer.write_u64::<BigEndian>(self.offset)?;

// NOTE: Truncation is okay and actually needed
#[allow(clippy::cast_possible_truncation)]
writer.write_u16::<BigEndian>(self.end_key.len() as u16)?;

writer.write_all(&self.end_key)?;

Ok(())
}
}

impl Deserializable for KeyedBlockHandle {
fn deserialize<R: Read>(reader: &mut R) -> Result<Self, crate::DeserializeError> {
let offset = reader.read_u64::<BigEndian>()?;

let key_len = reader.read_u16::<BigEndian>()?;

let mut key = vec![0; key_len.into()];

reader.read_exact(&mut key)?;

Ok(Self {
offset,
end_key: Arc::from(key),
})
}
}
22 changes: 22 additions & 0 deletions v2/src/sst/block_index/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
pub mod block_handle;
mod top_level;

use self::block_handle::KeyedBlockHandle;
use super::block::Block;
pub type IndexBlock = Block<KeyedBlockHandle>;

impl IndexBlock {
// TODO: same as TLI::get_lowest_block_containing_key
#[must_use]
pub fn get_lowest_data_block_handle_containing_item(&self, key: &[u8]) -> Option<&KeyedBlockHandle> {
let idx = self.items.partition_point(|x| &*x.end_key < key);

let handle = self.items.get(idx)?;

if key > &*handle.end_key {
None
} else {
Some(handle)
}
}
}
Loading

0 comments on commit 56d2008

Please sign in to comment.