Skip to content

Commit

Permalink
Add feature for SSTable
Browse files Browse the repository at this point in the history
  • Loading branch information
summerxwu committed Aug 24, 2023
1 parent 8c6e7c6 commit c9c8e73
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 22 deletions.
1 change: 1 addition & 0 deletions src/blocks/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,5 @@ fn test_iterator_next() {
iter.next();
assert!(iter.is_valid());
assert_eq!("key_6".as_bytes(),iter.key());
println!("finish")
}
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![allow(unused_variables)]
#![allow(dead_code)]
mod blocks;
pub mod blocks;
mod sstable;
mod util;

Expand Down
4 changes: 2 additions & 2 deletions src/sstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ impl SSTable {
/// create a new SSTable object by a exists disk file identified by sequence number
fn open(seq: usize) -> Result<Self> {
let file_path = env::sstfile_path(seq);
let file_object = env::FileObject::open(file_path.as_str())?;
let mut file_object = env::FileObject::open(file_path.as_str())?;

// Initialize the `indexes` field
// init the footer
Expand All @@ -84,7 +84,7 @@ impl SSTable {
// read records of each index block pointed by footer
for index_block_pointer in &footer_obj.index_block_pointers {
//read the index block
let buf = file_object.read(index_block_pointer.0, index_block_pointer.1)?;
let buf = file_object.read(index_block_pointer.0 as u64, index_block_pointer.1)?;
let index_block_obj = Blocks::decode(buf.as_ref());
let mut record_iter = BlockRecordIterator::new(&index_block_obj);
while record_iter.is_valid() {
Expand Down
3 changes: 2 additions & 1 deletion src/sstable/sstable_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ impl SSTableBuilder {
}
}
pub fn approximate_size_after_add(&self, key: &[u8], value: &[u8]) -> usize {
todo!()
//todo
1
}
// TODO(summerxwu): Maybe need a return value to indicate the result
pub fn add(&mut self, key: &[u8], value: &[u8]) {
Expand Down
2 changes: 1 addition & 1 deletion src/sstable/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ impl TestSSTable {
TestSSTable {
sstable,
builder,
record_num,
record_num:number,
}
}
}
Expand Down
127 changes: 110 additions & 17 deletions src/util/env.rs
Original file line number Diff line number Diff line change
@@ -1,52 +1,145 @@
use anyhow::Result;
use bytes::Bytes;
use std::fs;
use bytes::{Bytes, BytesMut};
use std::fs::{File, OpenOptions};
use std::io::{Seek, SeekFrom, Write};
use std::os::unix::fs::FileExt;

pub struct FileObject {
file_handler: fs::File,
/// size of current file
size: u64,
file_handler: File,
}
impl FileObject {
/// Create a new FileObject by a given file name.
/// Failed if file exists.
pub fn create(path: &str) -> Result<Self> {
todo!()
let file = OpenOptions::new()
.read(true)
.write(true)
.create_new(true)
.open(path)?;
Ok(FileObject { file_handler: file })
}

/// Open a new FileObject by a given file name.
/// Failed if file not exists.
pub fn open(path: &str) -> Result<Self> {
todo!()
let file_handler = OpenOptions::new().read(true).write(true).open(path)?;
let size = file_handler.metadata()?.len();
Ok(FileObject { file_handler })
}

/// Read content from file from `offset` by `length` long
pub fn read(&self, offset: usize, length: usize) -> Result<Bytes> {
todo!()
pub fn read(&mut self, offset: u64, length: usize) -> Result<Bytes> {
let mut buf = BytesMut::zeroed(length);
self.file_handler.read_exact_at(buf.as_mut(), offset)?;
Ok(buf.freeze())
}

/// Read Last length bytes of file content
pub fn read_last_of(&self, length: usize) -> Result<Bytes> {
todo!()
pub fn read_last_of(&mut self, length: usize) -> Result<Bytes> {
let offset = self.file_handler.metadata()?.len() - length as u64;
self.read(offset, length)
}

/// Write Content to file
pub fn write(&mut self, buf: &[u8]) -> Result<()> {
todo!()
let ret = self.file_handler.seek(SeekFrom::End(0))?;
self.file_handler.write(buf)?;
Ok(())
}
// Do fsync(), flush data to disk
pub fn sync() -> Result<()> {
todo!()
pub fn sync(&self) -> Result<()> {
self.file_handler.sync_all()?;
Ok(())
}

// Return the approximate size of current file
pub fn size(&self) -> u64 {
self.size
self.file_handler.metadata().unwrap().len()
}
}
pub fn sstfile_path(seq: usize) -> String {
todo!()
format!("/tmp/summer_kv_test/{}.sst", seq)
}
pub fn get_global_sequence_number() -> usize {
todo!()
1
}

#[cfg(test)]
mod tests {
use crate::util::env::FileObject;
use std::fs;
use std::io::Write;

const TMP_FILE: &str = "/tmp/test.test";
/// create file with amount of content of size `size` M
fn create_tmp_file(size: usize) {
let mut f = FileObject::create(TMP_FILE).unwrap();
for l in 0..size {
let buf: [u8; 1024] = [(l + 1) as u8; 1024];
f.file_handler.write(&buf).unwrap();
}
f.file_handler.sync_all().unwrap();
}
fn remove_tmp_file() {
let _ = fs::remove_file(TMP_FILE);
}
struct RaiiFinalize {}
impl Drop for RaiiFinalize {
fn drop(&mut self) {
remove_tmp_file()
}
}
#[test]
fn test_create() {
let raii = RaiiFinalize{};
let ret = FileObject::create(TMP_FILE) ;
assert!(ret.is_ok());
let ret = FileObject::create(TMP_FILE);
assert!(ret.is_err());

}
#[test]
fn test_open() {
let raii = RaiiFinalize{};
create_tmp_file(4);
let ret = FileObject::open(TMP_FILE);
assert!(ret.is_ok());
}
#[test]
fn test_read() {
let raii = RaiiFinalize {};
create_tmp_file(4);
let ret = FileObject::open(TMP_FILE);
assert!(ret.is_ok());
let mut file_obj = ret.unwrap();
let ret = file_obj.read(1023, 4);
assert!(ret.is_ok());
let buf = ret.unwrap();
assert_eq!(buf.to_vec().len(), 4);
let result = format!("{:?}", buf.to_vec());
assert_eq!(result, "[1, 2, 2, 2]");
}
#[test]
fn test_write_and_read_last() {
let raii = RaiiFinalize{};
create_tmp_file(1);
let ret = FileObject::open(TMP_FILE);
assert!(ret.is_ok());
let mut file_obj = ret.unwrap();
file_obj.write("abcdefg".as_bytes()).expect("Testing expect");
let ret = file_obj.read_last_of(7).expect("Testing expect");
assert_eq!(ret.len(),7);
assert_eq!(ret.as_ref(),"abcdefg".as_bytes())
}

#[test]
fn test_size(){
let raii = RaiiFinalize{};
create_tmp_file(1);
let ret = FileObject::open(TMP_FILE);
assert!(ret.is_ok());
let mut file_obj = ret.unwrap();
file_obj.write("abcdefg".as_bytes()).expect("Testing expect");
assert_eq!(1031,file_obj.size())
}
}

0 comments on commit c9c8e73

Please sign in to comment.