#![allow(unused_variables)] // TODO(you): remove this lint after implementing this mod #![allow(dead_code)] // TODO(you): remove this lint after implementing this mod mod builder; mod iterator; use std::path::Path; use std::sync::Arc; use anyhow::Result; pub use builder::SsTableBuilder; use bytes::{Buf, Bytes}; pub use iterator::SsTableIterator; use crate::block::Block; use crate::lsm_storage::BlockCache; #[derive(Clone, Debug, PartialEq, Eq)] pub struct BlockMeta { /// Offset of this data block. pub offset: usize, /// The first key of the data block, mainly used for index purpose. pub first_key: Bytes, } impl BlockMeta { /// Encode block meta to a buffer. /// You may add extra fields to the buffer, /// in order to help keep track of `first_key` when decoding from the same buffer in the future. pub fn encode_block_meta( block_meta: &[BlockMeta], #[allow(clippy::ptr_arg)] // remove this allow after you finish buf: &mut Vec, ) { unimplemented!() } /// Decode block meta from a buffer. pub fn decode_block_meta(buf: impl Buf) -> Vec { unimplemented!() } } /// A file object. pub struct FileObject(Bytes); impl FileObject { pub fn read(&self, offset: u64, len: u64) -> Result> { Ok(self.0[offset as usize..(offset + len) as usize].to_vec()) } pub fn size(&self) -> u64 { self.0.len() as u64 } /// Create a new file object (day 2) and write the file to the disk (day 4). pub fn create(path: &Path, data: Vec) -> Result { unimplemented!() } pub fn open(path: &Path) -> Result { unimplemented!() } } /// ------------------------------------------------------------------------------------------------------- /// | Data Block | Meta Block | Extra | /// ------------------------------------------------------------------------------------------------------- /// | Data Block #1 | ... | Data Block #N | Meta Block #1 | ... | Meta Block #N | Meta Block Offset (u32) | /// ------------------------------------------------------------------------------------------------------- pub struct SsTable { /// The actual storage unit of SsTable, the format is as above. file: FileObject, /// The meta blocks that hold info for data blocks. block_metas: Vec, /// The offset that indicates the start point of meta blocks in `file`. block_meta_offset: usize, } impl SsTable { #[cfg(test)] pub(crate) fn open_for_test(file: FileObject) -> Result { Self::open(0, None, file) } /// Open SSTable from a file. pub fn open(id: usize, block_cache: Option>, file: FileObject) -> Result { unimplemented!() } /// Read a block from the disk. pub fn read_block(&self, block_idx: usize) -> Result> { unimplemented!() } /// Read a block from disk, with block cache. (Day 4) pub fn read_block_cached(&self, block_idx: usize) -> Result> { unimplemented!() } /// Find the block that may contain `key`. /// Note: You may want to make use of the `first_key` stored in `BlockMeta`. /// You may also assume the key-value pairs stored in each consecutive block are sorted. pub fn find_block_idx(&self, key: &[u8]) -> usize { unimplemented!() } /// Get number of data blocks. pub fn num_of_blocks(&self) -> usize { unimplemented!() } } #[cfg(test)] mod tests;