diff --git a/src/db/file_meta_data.rs b/src/db/file_meta_data.rs index bc67682954616e298755d3232aff10decc9772d9..7c9e3b679ba01c0bd3faf4fd811e8fb67b051460 100644 --- a/src/db/file_meta_data.rs +++ b/src/db/file_meta_data.rs @@ -68,12 +68,23 @@ impl FileMetaData { } } + pub fn get_number(&self) -> u64 { + self.number + } + + /// File size in bytes + pub fn get_file_size(&self) -> u64 { + self.file_size + } + + /// Smallest internal key served by table pub fn get_smallest(&self) -> &InternalKey { &self.smallest } - pub fn get_number(&self) -> u64 { - self.number + /// Largest internal key served by table + pub fn get_largest(&self) -> &InternalKey { + &self.largest } pub fn get_refs(&self) -> i32 { diff --git a/src/db/version_edit.rs b/src/db/version_edit.rs index e820e778d9c66e6d1b9c3c9349b33411a9792c30..aa6bea4c4a5bacab024c83a8063b8976f74771fd 100644 --- a/src/db/version_edit.rs +++ b/src/db/version_edit.rs @@ -1,8 +1,13 @@ +use std::fs::read; use std::iter::Map; use crate::db::db_format::InternalKey; use crate::db::file_meta_data::FileMetaData; +use crate::db::version_edit; +use crate::traits::coding_trait::CodingTrait; +use crate::util::coding::Coding; use crate::util::slice::Slice; use crate::util::Result; +use crate::util::status::{LevelError, Status}; pub struct VersionEdit { comparator_: String, @@ -17,35 +22,99 @@ pub struct VersionEdit { has_last_sequence_: bool, compact_pointers_: Vec<(u32, InternalKey)>, + // left: level; right: file number deleted_files_: Vec<(u32, u64)>, + // left: level; right: FileMetaData new_files_: Vec<(u32, FileMetaData)>, } -enum Tag { - // kComparator = 1, - // kLogNumber = 2, - // kNextFileNumber = 3, - // kLastSequence = 4, - // kCompactPointer = 5, - // kDeletedFile = 6, - // kNewFile = 7, - // // 8 was used for large value refs - // kPrevLogNumber = 9 - - kComparator, - kLogNumber, - kNextFileNumber, - kLastSequence, - kCompactPointer, - kDeletedFile, - kNewFile, +pub enum Tag { + k_comparator = 1, + kLogNumber = 2, + kNextFileNumber = 3, + kLastSequence = 4, + kCompactPointer = 5, + kDeletedFile = 6, + kNewFile = 7, // 8 was used for large value refs - kPrevLogNumber + kPrevLogNumber = 9 +} + +impl Tag { + /// 得到枚举 Tag 的固定值 + /// Tag numbers for serialized VersionEdit. These numbers are written to disk and should not be changed. + pub fn get_value(&self) -> i32 { + let val = match self { + Tag::k_comparator => 1, + Tag::kLogNumber => 2, + Tag::kNextFileNumber => 3, + Tag::kLastSequence => 4, + Tag::kCompactPointer => 5, + Tag::kDeletedFile => 6, + Tag::kNewFile => 7, + Tag::kPrevLogNumber => 9, + _ => 0 + }; + + val + } + + /// 根据值计算枚举 Tag + pub fn from_value(val: u32) -> Option { + let val = match val { + 1 => Some(Tag::k_comparator), + 2 => Some(Tag::kLogNumber), + 3 => Some(Tag::kNextFileNumber), + 4 => Some(Tag::kLastSequence), + 5 => Some(Tag::kCompactPointer), + 6 => Some(Tag::kDeletedFile), + 7 => Some(Tag::kNewFile), + 9 => Some(Tag::kPrevLogNumber), + _ => None + }; + + val + } } impl VersionEdit { + #[inline] + pub fn new() -> Self { + Self { + comparator_ : String::new(), + log_number_: 0, + prev_log_number_: 0, + next_file_number_: 0, + last_sequence_: 0, + has_comparator_: false, + has_log_number_: false, + has_prev_log_number_: false, + has_next_file_number_: false, + has_last_sequence_: false, + compact_pointers_: vec![], + deleted_files_: vec![], + new_files_: vec![] + } + } + + #[inline] + pub fn new_with_log_number(log_number: u64) -> Self { + let mut version_edit = VersionEdit::new(); + version_edit.set_log_number(log_number); + + version_edit + } + + #[inline] + pub fn new_with_prev_log_number(prev_log_number: u64) -> Self { + let mut version_edit = VersionEdit::new(); + version_edit.set_prev_log_number(prev_log_number); + + version_edit + } + /// 清空 - fn clear(&mut self) { + pub fn clear(&mut self) { self.comparator_.clear(); self.log_number_ = 0; self.prev_log_number_ = 0; @@ -62,27 +131,32 @@ impl VersionEdit { // compact_pointers_ don't clear } - fn set_comparator_name(&mut self, name: Slice){ + pub fn set_comparator_name(&mut self, name: Slice){ self.has_comparator_ = true; self.comparator_ = name.into(); } - fn set_prev_log_number(&mut self, num: u64){ + pub fn set_log_number(&mut self, num: u64){ + self.has_log_number_ = true; + self.log_number_ = num; + } + + pub fn set_prev_log_number(&mut self, num: u64){ self.has_prev_log_number_ = true; self.prev_log_number_ = num; } - fn set_next_file(&mut self, num: u64){ + pub fn set_next_file(&mut self, num: u64){ self.has_next_file_number_ = true; self.next_file_number_ = num; } - fn set_last_sequence(&mut self, seq: u64){ + pub fn set_last_sequence(&mut self, seq: u64){ self.has_last_sequence_ = true; self.last_sequence_ = seq; } - fn set_compact_pointer(&mut self, level: u32, key: InternalKey) { + pub fn set_compact_pointer(&mut self, level: u32, key: InternalKey) { self.compact_pointers_.push((level, key)) } @@ -105,13 +179,13 @@ impl VersionEdit { /// ``` /// /// ``` - fn add_file(&mut self, level: u32, file: u64, file_size: u64, smallest: InternalKey, largest: InternalKey) { + pub fn add_file(&mut self, level: u32, file: u64, file_size: u64, smallest: InternalKey, largest: InternalKey) { let file_meta_data = FileMetaData::new_with_number_file_size_internal_key(file, file_size, smallest, largest); self.new_files_.push((level, file_meta_data)); } - fn delete_file(&mut self, level: u32, file: u64) { + pub fn delete_file(&mut self, level: u32, file: u64) { self.deleted_files_.push((level, file)); } @@ -128,8 +202,59 @@ impl VersionEdit { /// ``` /// /// ``` - fn encode_to(&self, target: Vec) { - todo!() + pub fn encode_to(&self, target: &mut Vec) { + let mut position: usize = 0; + if self.has_comparator_ { + position += Coding::put_varint32(target, position, Tag::k_comparator.get_value() as u32); + position += Coding::put_length_prefixed_slice(target, position, self.comparator_.len()); + } + + if self.has_log_number_ { + let mut offset = Coding::put_varint32(target, position, Tag::kLogNumber.get_value() as u32); + position = position + offset; + + offset = Coding::put_varint64(target, position, self.log_number_); + position = position + offset; + } + + if self.has_prev_log_number_ { + position += Coding::put_varint32(target, position, Tag::kPrevLogNumber.get_value() as u32); + position += Coding::put_varint64(target, position, self.prev_log_number_); + } + + if self.has_next_file_number_ { + position += Coding::put_varint32(target, position, Tag::kNextFileNumber.get_value() as u32); + position += Coding::put_varint64(target, position, self.next_file_number_); + } + + if self.has_last_sequence_ { + position += Coding::put_varint32(target, position, Tag::kLastSequence.get_value() as u32); + position += Coding::put_varint64(target, position, self.last_sequence_); + } + + for i in 0..self.compact_pointers_.len() { + position += Coding::put_varint32(target, position, Tag::kCompactPointer.get_value() as u32); + position += Coding::put_varint32(target, position, self.compact_pointers_[i].0); + position += Coding::put_length_prefixed_slice(target, position, + self.compact_pointers_[i].1.encode_len()); + } + + for i in 0..self.deleted_files_.len() { + position += Coding::put_varint32(target, position, Tag::kDeletedFile.get_value() as u32); + position += Coding::put_varint32(target, position, self.deleted_files_[i].0); + position += Coding::put_varint64(target, position, self.deleted_files_[i].1); + } + + for i in 0..self.new_files_.len() { + let f: &FileMetaData = &self.new_files_[i].1; + position += Coding::put_varint32(target, position, Tag::kNewFile.get_value() as u32); + // level + position += Coding::put_varint32(target, position, self.new_files_[i].0); + position += Coding::put_varint64(target, position, f.get_number()); + position += Coding::put_varint64(target, position, f.get_file_size()); + position += Coding::put_length_prefixed_slice(target, position, f.get_smallest().encode_len()); + position += Coding::put_length_prefixed_slice(target, position, f.get_largest().encode_len()); + } } /// 将 source 中的数据解码至 self VersionEdit 中 @@ -145,18 +270,40 @@ impl VersionEdit { /// ``` /// /// ``` - fn decode_from(&mut self, source: Slice) { + pub fn decode_from(&mut self, source: &mut Slice) -> Status { self.clear(); + let msg : Option = Option::None; + // while msg == None && Coding::get_varint32(source) != 0_u32 { + // let tag_value = Coding::get_varint32(source); + // let tag = Tag::from_value(tag_value); + // + // if tag.is_none() { + // return LevelError::corruption_string("VersionEdit", "unknown tag"); + // } + // + // // match tag { + // // Tag::k_comparator => 1, + // // Tag::kLogNumber => 2, + // // Tag::kNextFileNumber => 3, + // // Tag::kLastSequence => 4, + // // Tag::kCompactPointer => 5, + // // Tag::kDeletedFile => 6, + // // Tag::kNewFile => 7, + // // Tag::kPrevLogNumber => 9, + // // _ => 0 + // // }; + // } todo!() } /// VersionEdit 输出调试信息 - fn debug_string(&self) -> Slice { + pub fn debug_string(&self) -> Slice { todo!() } } +/// 静态方法 impl<'a> VersionEdit { pub fn get_internal_key(inout: Slice) -> Result { todo!() diff --git a/src/db/version_edit_test.rs b/src/db/version_edit_test.rs index 3024e557cdf3bbb6f694195504a00074f8eaa364..ffec818b1f719f325c4e90ab786022f6493cc610 100644 --- a/src/db/version_edit_test.rs +++ b/src/db/version_edit_test.rs @@ -1,10 +1,27 @@ mod test { + use crate::db::version_edit; + use crate::db::version_edit::{Tag, VersionEdit}; + #[test] - fn test_() { + fn test_Tag() { + let tag = Tag::kCompactPointer; + assert_eq!(tag.get_value(), 5); + + let tag1 = Tag::k_comparator; + let v = tag1.get_value(); + assert_eq!(v, 1); - println!("get_name: {}", "a"); + } + + #[test] + fn test_Version_edit() { + let mut target: Vec = vec![]; + let version_edit = VersionEdit::new_with_log_number(6); + version_edit.encode_to(&mut target); + println!("target: {}.", &target.len()); + assert_eq!(target.len(), 2); } } \ No newline at end of file diff --git a/src/traits/coding_trait.rs b/src/traits/coding_trait.rs index 3a0a49e42ebb574d2c92272b3e57f0ff406bf999..84981798ae3475080bbfcbd88cd50efcd2400a6d 100644 --- a/src/traits/coding_trait.rs +++ b/src/traits/coding_trait.rs @@ -70,7 +70,7 @@ pub trait CodingTrait { /// # Arguments /// /// * `dst`: 目标字符串 - /// * `value`: Slice类型的编码值 + /// * `value_len`: Slice类型的编码值长度 /// /// returns: () /// @@ -79,7 +79,8 @@ pub trait CodingTrait { /// ``` /// /// ``` - fn put_length_prefixed_slice(dst: &mut [u8], offset: usize, value: Slice) -> usize; + // fn put_length_prefixed_slice(dst: &mut [u8], offset: usize, value: &Slice) -> usize; + fn put_length_prefixed_slice(dst: &mut [u8], offset: usize, value_len: usize) -> usize; /// 从slice的开头解码一个32位的变长整数, 并将slice的索引置于解码后的位置 /// /// # Arguments diff --git a/src/util/coding.rs b/src/util/coding.rs index 3a13b7dd95b7ac2a1c47de34c178dfbb328487bb..a2a0f85ca0f9daf7384bc486609a88fff27729dd 100644 --- a/src/util/coding.rs +++ b/src/util/coding.rs @@ -83,8 +83,9 @@ impl CodingTrait for Coding { offset } - fn put_length_prefixed_slice(dst: &mut [u8], offset: usize, value: Slice) -> usize { - Self::put_varint64(dst, offset, value.size() as u64); + // fn put_length_prefixed_slice(dst: &mut [u8], offset: usize, value: &Slice) -> usize { + fn put_length_prefixed_slice(dst: &mut [u8], offset: usize, value_len: usize) -> usize { + Self::put_varint64(dst, offset, value_len as u64); offset } diff --git a/src/util/status.rs b/src/util/status.rs index 20493355fe69b7d68d1283013845b385c613d43f..42663cd0878c27400be7a3ddcde8b48cd767a1db 100644 --- a/src/util/status.rs +++ b/src/util/status.rs @@ -270,6 +270,10 @@ impl LevelError { } } + pub fn corruption_string(msg: &str, msg2: &str) -> Status { + LevelError::corruption(Slice::from(msg), Slice::from(msg2)) + } + pub fn not_supported(mut msg: Slice, msg2: Slice) -> Status { let _ = &msg.merge(msg2, Some(String::from(COLON_WHITE_SPACE))); diff --git a/src/util/status_test.rs b/src/util/status_test.rs index baad8329e2ec23eb0947c41ace8fff6759b67772..a7dce285ea754dff0fae290c40055bb90acb86f2 100644 --- a/src/util/status_test.rs +++ b/src/util/status_test.rs @@ -37,6 +37,9 @@ mod test { String::from(msg2).into()); assert!(&err.is_corruption()); + let err1: Status = LevelError::corruption_string("AAaaa", "bbhugy"); + assert!(&err1.is_corruption()); + let err: Status = LevelError::not_found(String::from(msg1).into(), String::from(msg2).into()); assert!(&err.is_not_found());