From 2b610f5f7dd89a02dde4baa89afbb54795f971da Mon Sep 17 00:00:00 2001 From: wangboo <5417808+wangboa@user.noreply.gitee.com> Date: Tue, 17 Jan 2023 18:28:36 +0800 Subject: [PATCH 1/8] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=83=A8=E5=88=86?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.toml | 2 +- src/db/skip_list.rs | 78 ++++++++++++++++++++++++++++++++++++++++++--- src/lib.rs | 1 + 3 files changed, 75 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6f688ef..c05ad50 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ path = "src/lib.rs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] - +rand = "0.8.5" [profile.dev] diff --git a/src/db/skip_list.rs b/src/db/skip_list.rs index 144c0b6..ff6d102 100644 --- a/src/db/skip_list.rs +++ b/src/db/skip_list.rs @@ -1,3 +1,5 @@ +use std::cmp::Ordering; +use std::ptr::NonNull; use std::rc::Rc; use crate::traits::comparator_trait::ComparatorTrait; @@ -6,26 +8,71 @@ use crate::util::comparator::BytewiseComparatorImpl; use crate::util::Result; use crate::util::slice::Slice; +use rand::prelude::*; +use crate::util::status::{LevelError, Status}; + // todo struct Node { - value: T, + /// 存储的值 + key: T, + /// 最大深度 + max_level: u8, + /// 柔性数组, 该节点层下存储的指向后方的节点 + next: Vec>>, } pub struct SkipList { - node: Option>, + /// 最高层数 + level: u8, + /// 最高层数 + max_level: u8, + /// 存储数据数量 + num: usize, + /// 头部指针 + head: Option>, + /// 比较器 comp: Rc, + /// 内存分配器 + arena: Rc, } impl SkipList { - pub fn create(comparator: Rc, _arena: Rc) -> Self { + pub fn create(comparator: Rc, arena: Rc) -> Self { Self { - node: None, + level: 0, + max_level: 8, + num: 0, + head: None, comp: comparator, + arena, } } - pub fn insert(&mut self, _seq_no: usize, _key: &Slice) -> Result<()> { + pub fn insert(&mut self, key: &Slice) -> Result<()> { + if self.head.is_none() { + self.head = Some(Node::create(key)); + self.level = 1; + self.num = 1; + self.max_level = 1; + return Ok(()) + } + let pre = self.head.unwrap(); + let mut next = true; + while next { + match self.comp.compare(&pre.key, key) { + None => Err(Status::wrapper(LevelError::KInvalidArgument, "key not comparable".into())); + Some(Ordering::Equal) => { + + }, + Some(Ordering::Less) => { + + }, + Some(Ordering::Greater) => { + + } + } + } todo!() } @@ -36,4 +83,25 @@ impl SkipList { pub fn get_max_height(&self) -> usize { todo!() } + + fn rnd_level(&self) -> u8 { + let mut level = 1; + for _ in 1..self.max_level { + if random() { + level += 1; + } + } + level + } + +} + +impl Node { + fn create(key: T) -> Self { + Self { + key, + max_level: 1, + next: Vec::with_capacity(4), + } + } } \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 064907a..a915437 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ #![feature(box_syntax)] +#![feature(let_else)] mod db; mod table; -- Gitee From e63dc99a9210abd29371125746167bac079a275e Mon Sep 17 00:00:00 2001 From: wangboo <5417808+wangboa@user.noreply.gitee.com> Date: Thu, 16 Mar 2023 16:47:20 +0800 Subject: [PATCH 2/8] =?UTF-8?q?=E9=83=A8=E5=88=86skiplist=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/db/mod.rs | 5 +- src/db/skip_list.rs | 404 ++++++++++++++++++++++++++++++++++----- src/db/skip_list_test.rs | 65 +++++++ src/lib.rs | 3 + src/util/arena.rs | 30 ++- src/util/const.rs | 2 + src/util/debug.rs | 17 ++ src/util/mod.rs | 3 +- src/util/slice.rs | 25 +++ src/util/status.rs | 18 +- 10 files changed, 513 insertions(+), 59 deletions(-) create mode 100644 src/db/skip_list_test.rs create mode 100644 src/util/debug.rs diff --git a/src/db/mod.rs b/src/db/mod.rs index 5a34cf6..6ce1187 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -1,5 +1,5 @@ -use crate::db::skip_list::SkipList; use crate::db::mem_table::MemTable; +use crate::db::skip_list::SkipList; use crate::util::comparator::{BytewiseComparatorImpl, InternalKeyComparator}; use crate::util::slice::Slice; @@ -9,8 +9,9 @@ mod log_wr_test; pub mod skip_list; pub mod mem_table; pub mod db; +mod skip_list_test; /// 默认调表 -pub type DefaultSkipList = SkipList; +pub type DefaultSkipList = SkipList; /// 默认内存表 pub type DefaultMemTable = MemTable; \ No newline at end of file diff --git a/src/db/skip_list.rs b/src/db/skip_list.rs index ff6d102..628f87c 100644 --- a/src/db/skip_list.rs +++ b/src/db/skip_list.rs @@ -1,107 +1,405 @@ -use std::cmp::Ordering; -use std::ptr::NonNull; -use std::rc::Rc; +use std::cell::{Cell, RefCell}; +use std::cmp::{max, min, Ordering}; +use std::fmt::format; +use std::mem; +use std::mem::{ManuallyDrop, size_of}; +use std::ops::{Deref, DerefMut}; +use std::ptr::{NonNull, null_mut}; +use std::sync::Arc; + +use rand::prelude::*; +use crate::debug; use crate::traits::comparator_trait::ComparatorTrait; use crate::util::Arena; +use crate::util::arena::{ArenaAllocLike, ArenaRef}; use crate::util::comparator::BytewiseComparatorImpl; use crate::util::Result; use crate::util::slice::Slice; - -use rand::prelude::*; use crate::util::status::{LevelError, Status}; +type RawNode = *mut Node; + +const MAX_LEVEL: usize = 8; + // todo -struct Node { - /// 存储的值 - key: T, - /// 最大深度 - max_level: u8, - /// 柔性数组, 该节点层下存储的指向后方的节点 - next: Vec>>, +struct Node { + /// 存储的值, 如果为空,则是头指针或者尾指针 + key: Option, + /// 数组元素首地址,代表一个数组,指向每层的下一个节点。 + next_elems: *mut RawNode, + /// 当前节点高度 + level: usize, } -pub struct SkipList { - /// 最高层数 - level: u8, +pub struct SkipList { /// 最高层数 - max_level: u8, + level: usize, /// 存储数据数量 num: usize, /// 头部指针 - head: Option>, + head: RawNode, + /// 尾指针 + tail: RawNode, /// 比较器 - comp: Rc, + cmp: Arc, /// 内存分配器 - arena: Rc, + arena: ArenaRef, } -impl SkipList { +pub struct Iter<'a, Cmp: ComparatorTrait> { + list: &'a SkipList, + node: RawNode, +} - pub fn create(comparator: Rc, arena: Rc) -> Self { +impl SkipList { + pub fn create(comparator: Arc, arena: ArenaRef) -> Self { Self { level: 0, - max_level: 8, num: 0, - head: None, - comp: comparator, + head: Node::create_head(arena.clone()), + tail: Node::create_tail(), + cmp: comparator, arena, } } - pub fn insert(&mut self, key: &Slice) -> Result<()> { - if self.head.is_none() { - self.head = Some(Node::create(key)); - self.level = 1; - self.num = 1; - self.max_level = 1; - return Ok(()) + pub fn insert(&mut self, key: Slice) -> Result<()> { + if self.num == 0 { + self.insert_ele0(key) + } else { + self.insert_elen(key) } - let pre = self.head.unwrap(); - let mut next = true; - while next { - match self.comp.compare(&pre.key, key) { - None => Err(Status::wrapper(LevelError::KInvalidArgument, "key not comparable".into())); - Some(Ordering::Equal) => { + } - }, - Some(Ordering::Less) => { + #[inline] + fn insert_ele0(&mut self, key: Slice) -> Result<()> { + let level = rand_level(); + debug!("insert {}, level: {}", &key, level); + let node = unsafe { Node::create(key, level, self.arena.clone()) }; + // head bind node + // TODO, use macro to expand for-loop + unsafe { + (&mut *node).level = level; + (&mut *self.head).level = level; + for l in 0..level { + (&mut *self.head).set_node(l, node); + (&mut *node).set_node(l, self.tail); + } + } + self.level = level; + self.num = 1; + return Ok(()); + } - }, - Some(Ordering::Greater) => { + fn insert_elen(&mut self, key: Slice) -> Result<()> { + let mut current = self.head; + let level = rand_level(); + debug!("insert {}, level: {}", &key, level); + let node_ptr = unsafe { + Node::create(key, level, self.arena.clone()) + }; + let node = unsafe { &mut *node_ptr }; + // loop from highest level to 0 + for l in (0..self.level).rev() { + 'inner_loop: loop { + let ele_ptr = unsafe { (&*current).get_node(l) }; + let ele = unsafe { &mut *ele_ptr }; + if ele.is_tail() { + if l < level { + // ele is tail node, add node to last + unsafe { + (&mut *current).set_node(l, node_ptr); + node.set_node(l, self.tail); + debug!("bind: {} before: {}, after: , at level: {}", + node.key.as_ref().unwrap(), + (&*current).key.as_ref().unwrap(), + l); + }; + } + break 'inner_loop; + } else { + match self.cmp.compare(node.key.as_ref().unwrap(), ele.key.as_ref().unwrap()) { + Some(Ordering::Less) => { + // node higher than current level at ele + if level > l { + unsafe { + (&mut *current).set_node(l, node_ptr); + node.set_node(l, ele_ptr); + if (&*current).is_head() { + debug!("bind: {} before: , after: {}, at level: {}", + node.key.as_ref().unwrap(), + ele.key.as_ref().unwrap(), + l); + } else { + debug!("bind: {} before: {}, after: {}, at level: {}", + node.key.as_ref().unwrap(), + (&*current).key.as_ref().unwrap(), + ele.key.as_ref().unwrap(), + l); + } + }; + } + break 'inner_loop; + } + Some(Ordering::Greater) => { + current = ele; + } + Some(Ordering::Equal) => { + // ignore equals + return Ok(()); + } + None => { + return Err(Status::wrapper(LevelError::KInvalidArgument, "key not comparable".into())); + } + } + } + } + } + // if head level is less than new node, then fix head node height + if self.level < level { + for l in (self.level()..level).rev() { + unsafe { + (&mut *self.head).set_node(l, node_ptr); + node.set_node(l, self.tail); + }; + } + self.level = level; + } + self.num += 1; + Ok(()) + } + #[macro_use] + pub fn contains(&self, key: &Slice) -> bool { + debug!("================== begin contains, key: {} ==================", key); + if self.num == 0 { + return false; + } + unsafe { + let mut current = unsafe { &*self.head }; + for level in (0..self.level).rev() { + 'a_loop: loop { + let ele_ptr = current.get_node(level); + let ele = &*ele_ptr; + if ele.is_tail() { + // tail node + if level == 0 { + debug!("next is tail, return false"); + return false; + } else { + debug!("next is tail, continue"); + break 'a_loop; + } + } + { + debug!("node: {} at level: {}", ele.key.as_ref().unwrap(), level) + } + match self.cmp.compare(key, ele.key.as_ref().unwrap()) { + None => return false, + Some(Ordering::Equal) => return true, + Some(Ordering::Less) => { + // break loop, decrease the level + break; + } + Some(Ordering::Greater) => { + if current.level() == 0 { + return false; + } + current = ele; + } + }; } } } - todo!() + // can not found in all level + false + } + + #[inline] + pub fn max_height(&self) -> usize { + MAX_LEVEL } - pub fn contains(&self, _key: &Slice) -> bool { - todo!() + #[inline] + pub fn level(&self) -> usize { + self.level } - pub fn get_max_height(&self) -> usize { - todo!() + #[inline] + pub fn len(&self) -> usize { + self.num } - fn rnd_level(&self) -> u8 { + #[inline] + pub fn iter(&self) -> Iter { + Iter::create(&self) + } + + fn rnd_level(&self) -> usize { let mut level = 1; - for _ in 1..self.max_level { + for _ in 1..MAX_LEVEL { if random() { level += 1; } } level } +} + +impl ToString for SkipList { + fn to_string(&self) -> String { + let mut tree = String::with_capacity(1024); + // calculate each item width + let mut widths = Vec::with_capacity(tree.len()); + self.iter().for_each(|s| { + widths.push(s.size()); + }); + // print value list + if self.num > 0 { + unsafe { + let mut node = &*((&*self.head).get_node(0)); + tree.push_str("[head]"); + while !node.is_head_or_tail() { + tree.push_str(" -> "); + tree.push_str(node.key.as_ref().unwrap().as_str()); + let level_str = format!("({})", node.level); + tree.push_str(level_str.as_str()); + node = &*node.get_node(0); + } + } + } + tree.push_str("-> [tail]"); + format!("height: {}, num: {}\n {}", self.level, self.num, tree) + } +} + + +impl Node { + #[inline] + fn create(src: Slice, level: usize, mut arena: ArenaRef) -> RawNode { + let key = src.copy_with_arena(arena.clone()); + let node = box Self { + key: Some(key), + next_elems: allocate_next_elems(arena), + level, + }; + Box::into_raw(node) + } + #[inline] + fn create_head(mut arena: ArenaRef) -> RawNode { + let node = box Self { + key: None, + next_elems: allocate_next_elems(arena), + level: MAX_LEVEL, + }; + Box::into_raw(node) + } + + #[inline] + fn create_tail() -> RawNode { + let node = box Self { + key: None, + next_elems: null_mut(), + level: 0, + }; + Box::into_raw(node) + } + + #[inline] + #[must_use] + fn is_head_or_tail(&self) -> bool { + self.key.is_none() + } + + #[inline] + #[must_use] + fn is_tail(&self) -> bool { + self.key.is_none() && self.level == 0 + } + + #[inline] + #[must_use] + fn is_head(&self) -> bool { + self.key.is_none() && self.level > 0 + } + + + #[inline] + fn level(&self) -> usize { + self.level + } + + #[inline] + #[must_use] + unsafe fn get_node(&self, level: usize) -> RawNode { + assert!(level < MAX_LEVEL); + self.next_elems.offset(level as isize).read() + } + + #[inline] + unsafe fn set_node(&mut self, level: usize, node: RawNode) { + assert!(level < MAX_LEVEL); + self.next_elems.offset(level as isize).write(node); + } } -impl Node { - fn create(key: T) -> Self { +fn rand_level() -> usize { + let mut level = 1_usize; + while random::() { + level += 1; + if level >= MAX_LEVEL { + break; + } + } + level +} + +fn allocate_next_elems(mut arena: ArenaRef) -> *mut RawNode { + // RawNode is a raw ptr + assert_eq!(size_of::(), size_of::()); + // allocate next_elems to 8 capacity array + let elems_size = size_of::() * MAX_LEVEL; + let mut lock = arena.lock().expect("lock arena"); + let elems_ptr = lock.allocate(elems_size); + // transmute raw ptr to RawNode ptr + unsafe { + mem::transmute(elems_ptr.as_ptr()) + } +} + +#[inline] +fn min_max(a: usize, b: usize) -> (usize, usize) { + if a < b { + (a, b) + } else { + (b, a) + } +} + +// 'b lifetime is bigger than 'a +impl<'a, Cmp: ComparatorTrait> Iter<'a, Cmp> { + fn create(list: &'a SkipList) -> Self { Self { - key, - max_level: 1, - next: Vec::with_capacity(4), + list, + node: list.head, + } + } +} + +impl<'a, Cmp: ComparatorTrait> Iterator for Iter<'a, Cmp> { + type Item = &'a Slice; + + #[inline] + fn next(&mut self) -> Option { + unsafe { + if (&*self.node).is_tail() { + return None; + } else { + self.node = (&*self.node).get_node(0); + } + (&*self.node).key.as_ref() } } } \ No newline at end of file diff --git a/src/db/skip_list_test.rs b/src/db/skip_list_test.rs new file mode 100644 index 0000000..b697a44 --- /dev/null +++ b/src/db/skip_list_test.rs @@ -0,0 +1,65 @@ + +mod test { + use std::collections::HashSet; + use std::io::{stdout, Write}; + use std::panic; + use std::sync::{Arc, Mutex}; + use rand::Rng; + use crate::util::Result; + use crate::db::DefaultSkipList; + use crate::db::skip_list::SkipList; + use crate::debug; + use crate::util::Arena; + use crate::util::comparator::BytewiseComparatorImpl; + use crate::util::slice::Slice; + + #[test] + fn test_add() -> Result<()> { + let cmp = Arc::new(BytewiseComparatorImpl::default()); + let arena = Arc::new(Mutex::new(Arena::default())); + let mut list = DefaultSkipList::create(cmp, arena); + let len = 10; + for i in 0..len { + list.insert(format!("key_{}", i).into()).expect("insert ok"); + } + assert_eq!(10, list.len(), "expect 10, but actually is: {}", list.len()); + println!("{}", list.to_string()); + for i in 0..len { + let key: Slice = format!("key_{}", i).into(); + println!("contains key: {}", key); + assert!(list.contains(&key), "contains key: {}", key); + } + list.iter().for_each(|slice| { + println!("slice: {}", slice.as_str()) + }); + Ok(()) + } + + #[test] + fn test_rnd_add() -> Result<()> { + panic::set_hook(Box::new(|_panic_info| { + stdout().flush().unwrap(); + })); + let cmp = Arc::new(BytewiseComparatorImpl::default()); + let arena = Arc::new(Mutex::new(Arena::default())); + let mut list = DefaultSkipList::create(cmp, arena); + let len = 10; + let mut rnd = rand::thread_rng(); + let mut set = HashSet::new(); + for i in 0..10 { + let j = rnd.gen_range(0..len); + let key = format!("key_{}", j); + set.insert(key.clone()); + list.insert(key.into())?; + debug!("skiplist: {}", list.to_string()); + } + assert_eq!(set.len(), list.len(), "list length must eq: {}", list.len()); + set.iter().for_each(|key| { + let c = list.contains(&key.clone().into()); + assert!(c, "must contains key: {}", key) + }); + + Ok(()) + } + +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index a915437..b3fbd97 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,8 @@ #![feature(box_syntax)] #![feature(let_else)] +#![feature(generic_associated_types)] + +extern crate core; mod db; mod table; diff --git a/src/util/arena.rs b/src/util/arena.rs index 3f46dcb..2022a51 100644 --- a/src/util/arena.rs +++ b/src/util/arena.rs @@ -1,10 +1,25 @@ +use std::{ptr, slice}; use std::alloc::{alloc, dealloc, Layout}; +use std::cell::Cell; +use std::ops::Deref; use std::ptr::NonNull; -use std::slice; +use std::rc::Rc; +use std::sync::{Arc, Mutex}; +use crate::util::mutex_lock::MutexLock; + +use crate::util::slice::Slice; // Arena block size const ARENA_BLOCK_SIZE: usize = 4096; +pub type ArenaRef = Arc>; + + +/// +pub trait ArenaAllocLike { + fn copy_with_arena(&self, arena: ArenaRef) -> Self; +} + pub struct Arena { alloc_ptr: Option>, alloc_bytes_remaining: usize, @@ -24,7 +39,6 @@ impl Default for Arena { } impl Arena { - /// 申请一块内存 /// /// # Arguments @@ -102,4 +116,16 @@ impl Drop for Arena { } } } +} + +impl ArenaAllocLike for Slice { + fn copy_with_arena(&self, mut arena: ArenaRef) -> Self { + unsafe { + let mut lock_guard = arena.lock().unwrap(); + let dst = lock_guard.allocate(self.len()); + let src = &**self; + dst.copy_from_slice(src); + Slice::from_raw_parts(dst.as_mut_ptr(), self.len()) + } + } } \ No newline at end of file diff --git a/src/util/const.rs b/src/util/const.rs index a8ffcf8..4ae2368 100644 --- a/src/util/const.rs +++ b/src/util/const.rs @@ -5,3 +5,5 @@ pub const COLON_WHITE_SPACE: &'static str = ": "; /// hash 的默认seed: 0xbc9f1d34 pub const HASH_DEFAULT_SEED: u32 = 0xbc9f1d34; + +pub const DEBUG_ENABLE: bool = true; diff --git a/src/util/debug.rs b/src/util/debug.rs new file mode 100644 index 0000000..9645f5f --- /dev/null +++ b/src/util/debug.rs @@ -0,0 +1,17 @@ +use std::fmt::format; +use std::io::Write; +#[macro_export] +macro_rules! debug { + () => { + if (crate::util::r#const::DEBUG_ENABLE) { + std::io::stdout().write("\n".as_bytes()).unwrap(); + } + }; + ($($arg:tt)*) => {{ + use std::io::Write; + if(crate::util::r#const::DEBUG_ENABLE) { + std::io::stdout().write(format!($($arg)*).as_bytes()); + debug!(); + } + }}; +} diff --git a/src/util/mod.rs b/src/util/mod.rs index b3e53d7..8f7293c 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -34,6 +34,7 @@ mod hash_test; mod mutex_lock; mod mutex_lock_test; pub mod options; +pub mod debug; /// 定义别名 -pub type Result = result::Result; +pub type Result = result::Result; \ No newline at end of file diff --git a/src/util/slice.rs b/src/util/slice.rs index 26ea8b1..7a14a22 100644 --- a/src/util/slice.rs +++ b/src/util/slice.rs @@ -1,6 +1,8 @@ use std::mem; use std::borrow::Cow; use std::cmp::Ordering; +use std::fmt::{Display, Formatter}; +use std::mem::ManuallyDrop; use std::ops::Deref; #[derive(Debug)] @@ -40,6 +42,12 @@ impl Slice { } } + #[inline] + pub unsafe fn from_raw_parts(ptr: *mut u8, len: usize) -> Self { + let data = Vec::from_raw_parts(ptr, len, len); + Self { data } + } + /// 获取 slice 长度 #[inline] pub fn size(&self) -> usize { @@ -96,6 +104,10 @@ impl Slice { } } + pub fn as_str(&self) -> &str { + let s = self.as_ref(); + std::str::from_utf8(s).unwrap() + } } impl<'a> Slice { @@ -195,3 +207,16 @@ impl Deref for Slice { } } +impl Display for Slice { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + unsafe { + let string = ManuallyDrop::new( + String::from_raw_parts( + self.as_ptr() as *mut u8, + self.data.len(), + self.data.capacity()) + ); + f.write_str(string.as_str()) + } + } +} diff --git a/src/util/status.rs b/src/util/status.rs index 8f5365d..afd4040 100644 --- a/src/util/status.rs +++ b/src/util/status.rs @@ -2,7 +2,7 @@ use std::fmt::{Display, Formatter}; use std::io; use crate::util::r#const::COLON_WHITE_SPACE; use crate::util::slice::Slice; -use crate::util::status::LevelError::{KCorruption, KIOError, KInvalidArgument, KNotSupported, KNotFound, KOk, KBadRecord}; +use crate::util::status::LevelError::{KCorruption, KIOError, KInvalidArgument, KNotSupported, KNotFound, KOk, KBadRecord, KRepeatedRecord}; /// db 中的返回状态,将错误号和错误信息封装成Status类,统一进行处理。 /// 在 leveldb的实现里, 为了节省空间Status将返回码(code), 错误信息message及长度打包存储于一个字符串数组中, 来存储错误信息。 @@ -134,6 +134,7 @@ impl Status { KInvalidArgument => "Invalid argument: ", KIOError => "IO error: ", KBadRecord=> "wal bad record", + KRepeatedRecord => "repeated record" }; if self.err.is_ok() { @@ -180,6 +181,7 @@ pub enum LevelError { KInvalidArgument, KIOError, KBadRecord, + KRepeatedRecord, } impl LevelError { @@ -225,6 +227,10 @@ impl LevelError { } } + pub fn is_repeated_record(&self) -> bool { + matches!(self, KRepeatedRecord) + } + pub fn ok() -> Status { Status{ err: Default::default(), @@ -282,6 +288,14 @@ impl LevelError { } } + #[inline] + pub fn repeated_record(msg: Slice) -> Status { + Status { + err: KRepeatedRecord, + msg + } + } + /// 生成 LevelError.KIOError /// /// # Arguments @@ -339,6 +353,7 @@ impl TryFrom for LevelError { 4 => Ok(KInvalidArgument), 5 => Ok(KIOError), 6 => Ok(KBadRecord), + 7 => Ok(KRepeatedRecord), // all other numbers _ => Err(String::from(format!("Unknown code: {}", value))) } @@ -363,6 +378,7 @@ impl Display for LevelError { KInvalidArgument => "Invalid argument: ", KIOError => "IO error: ", KBadRecord => "wal bad record: ", + KRepeatedRecord => "repeated record: ", }; print.push_str(msg_type); -- Gitee From c20740cf95e4a8ee14846a971455a0e4fa50f6ff Mon Sep 17 00:00:00 2001 From: wangboo <5417808+wangboa@user.noreply.gitee.com> Date: Thu, 16 Mar 2023 18:27:57 +0800 Subject: [PATCH 3/8] =?UTF-8?q?=E4=BF=AE=E6=94=B9skiplist=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E6=A1=88=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/db/skip_list_test.rs | 9 +++------ src/util/comparator.rs | 1 - src/util/mod.rs | 2 +- 4 files changed, 5 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 07c70b6..806faa6 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ LSM tree 是许多 KV型或日志型数据库所依赖的核心实现,例如Bi | Slice | wangboo | 100% | 2. 1.1.0 版本, 完成基础零部件 - + | 功能模块 | 完成人 | 进度 | |------------------|---------|-----| | skiplist | 未认领 | | diff --git a/src/db/skip_list_test.rs b/src/db/skip_list_test.rs index b697a44..93633a6 100644 --- a/src/db/skip_list_test.rs +++ b/src/db/skip_list_test.rs @@ -23,23 +23,20 @@ mod test { list.insert(format!("key_{}", i).into()).expect("insert ok"); } assert_eq!(10, list.len(), "expect 10, but actually is: {}", list.len()); - println!("{}", list.to_string()); + debug!("{}", list.to_string()); for i in 0..len { let key: Slice = format!("key_{}", i).into(); - println!("contains key: {}", key); + debug!("contains key: {}", key); assert!(list.contains(&key), "contains key: {}", key); } list.iter().for_each(|slice| { - println!("slice: {}", slice.as_str()) + debug!("slice: {}", slice.as_str()) }); Ok(()) } #[test] fn test_rnd_add() -> Result<()> { - panic::set_hook(Box::new(|_panic_info| { - stdout().flush().unwrap(); - })); let cmp = Arc::new(BytewiseComparatorImpl::default()); let arena = Arc::new(Mutex::new(Arena::default())); let mut list = DefaultSkipList::create(cmp, arena); diff --git a/src/util/comparator.rs b/src/util/comparator.rs index 71560fe..0417c10 100644 --- a/src/util/comparator.rs +++ b/src/util/comparator.rs @@ -62,7 +62,6 @@ impl ComparatorTrait for BytewiseComparatorImpl { } let shortest_separator: &[u8] = &start_char_vec[0..diff_index+1]; - let shortest_separator_val: String= Slice::from_buf(shortest_separator).into(); shortest_separator_val } diff --git a/src/util/mod.rs b/src/util/mod.rs index 8f7293c..652da5d 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -37,4 +37,4 @@ pub mod options; pub mod debug; /// 定义别名 -pub type Result = result::Result; \ No newline at end of file +pub type Result = result::Result; -- Gitee From e0c0d16b6ad41c0b7e153675cbe8f4bf5d34bc43 Mon Sep 17 00:00:00 2001 From: wangboo <5417808+wangboa@user.noreply.gitee.com> Date: Thu, 16 Mar 2023 20:22:15 +0800 Subject: [PATCH 4/8] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=BC=96=E8=AF=91?= =?UTF-8?q?=E9=80=89=E9=A1=B9=EF=BC=8C=E8=A7=A3=E5=86=B3DEBUG=E5=AE=8F?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .cargo/config.toml | 5 +++++ src/util/debug.rs | 11 +++++++++++ 2 files changed, 16 insertions(+) create mode 100644 .cargo/config.toml diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..c32ea9f --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,5 @@ +[target.dev] +rustc-cfg=['DEBUG="true"'] + +[target.release] +rustc-cfg=['DEBUG="false"'] \ No newline at end of file diff --git a/src/util/debug.rs b/src/util/debug.rs index 9645f5f..dcd2777 100644 --- a/src/util/debug.rs +++ b/src/util/debug.rs @@ -1,5 +1,7 @@ use std::fmt::format; use std::io::Write; + +#[cfg(DEBUG = "true")] #[macro_export] macro_rules! debug { () => { @@ -15,3 +17,12 @@ macro_rules! debug { } }}; } + +#[cfg(not(DEBUG = "true"))] +#[macro_export] +macro_rules! debug { + () => { + }; + ($($arg:tt)*) => {{ + }}; +} \ No newline at end of file -- Gitee From 94473e076d1d7d8d709aaef584ff72f007dd96f9 Mon Sep 17 00:00:00 2001 From: wangboo <5417808+wangboa@user.noreply.gitee.com> Date: Thu, 16 Mar 2023 21:04:06 +0800 Subject: [PATCH 5/8] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=B0=83=E8=AF=95?= =?UTF-8?q?=E6=97=B6=E7=9A=84=E7=BC=96=E8=AF=91=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .cargo/config.toml | 7 ++----- Cargo.toml | 7 +++++++ README.md | 9 ++++++++- src/util/debug.rs | 16 +++++++--------- 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index c32ea9f..0d0b4da 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,5 +1,2 @@ -[target.dev] -rustc-cfg=['DEBUG="true"'] - -[target.release] -rustc-cfg=['DEBUG="false"'] \ No newline at end of file +[build] +rustflags='--cfg CORE_DEBUG="true"' \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index c05ad50..b2f54ec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,11 @@ edition = "2021" name = "level_db_rust" path = "src/lib.rs" +[features] +default = ["debug-macro"] +release=[] + +debug-macro=[] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] @@ -14,4 +19,6 @@ rand = "0.8.5" [profile.dev] + [profile.release] + diff --git a/README.md b/README.md index 806faa6..d296d60 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,14 @@ LSM tree 是许多 KV型或日志型数据库所依赖的核心实现,例如Bi #### 使用说明 -1. xxxx +1. 编译参数 + CORE_DEBUG 默认开启,打印调试信息 + +在构建正式版本时,用户可以用 RUSTFLAGS 环境变量覆盖以上编译参数。 +eg: +```bash +RUSTFLAGS='--cfg CORE_DEBUG="false"' cargo test db::skip_list_test::test::test_add +``` #### 参与贡献 diff --git a/src/util/debug.rs b/src/util/debug.rs index dcd2777..c32caf1 100644 --- a/src/util/debug.rs +++ b/src/util/debug.rs @@ -1,24 +1,22 @@ use std::fmt::format; use std::io::Write; -#[cfg(DEBUG = "true")] +// #[cfg(feature = "debug-macro")] +#[cfg(CORE_DEBUG = "true")] #[macro_export] macro_rules! debug { () => { - if (crate::util::r#const::DEBUG_ENABLE) { - std::io::stdout().write("\n".as_bytes()).unwrap(); - } + std::io::stdout().write("\n".as_bytes()).unwrap(); }; ($($arg:tt)*) => {{ use std::io::Write; - if(crate::util::r#const::DEBUG_ENABLE) { - std::io::stdout().write(format!($($arg)*).as_bytes()); - debug!(); - } + std::io::stdout().write(format!($($arg)*).as_bytes()); + debug!(); }}; } -#[cfg(not(DEBUG = "true"))] +// #[cfg(not(feature = "debug-macro"))] +#[cfg(not(CORE_DEBUG = "true"))] #[macro_export] macro_rules! debug { () => { -- Gitee From e25dfd56a23aa0774f938214570403e6ba3bec6d Mon Sep 17 00:00:00 2001 From: wangboo <5417808+wangboa@user.noreply.gitee.com> Date: Thu, 16 Mar 2023 21:04:58 +0800 Subject: [PATCH 6/8] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=B0=83=E8=AF=95?= =?UTF-8?q?=E6=97=B6=E7=9A=84=E7=BC=96=E8=AF=91=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d296d60..f3c18ee 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ LSM tree 是许多 KV型或日志型数据库所依赖的核心实现,例如Bi 在构建正式版本时,用户可以用 RUSTFLAGS 环境变量覆盖以上编译参数。 eg: ```bash -RUSTFLAGS='--cfg CORE_DEBUG="false"' cargo test db::skip_list_test::test::test_add +RUSTFLAGS='--cfg CORE_DEBUG="false"' cargo build --release ``` #### 参与贡献 -- Gitee From 80c4d8ee8f4d4246d7bf7d88ea256109c127af12 Mon Sep 17 00:00:00 2001 From: wangboo <5417808+wangboa@user.noreply.gitee.com> Date: Thu, 16 Mar 2023 21:53:47 +0800 Subject: [PATCH 7/8] =?UTF-8?q?=E5=AE=8C=E6=88=90skiplist?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/db/skip_list.rs | 84 +++++++++++++++++++--------------------- src/db/skip_list_test.rs | 9 ++--- src/util/arena.rs | 6 +-- src/util/mod.rs | 2 - 4 files changed, 44 insertions(+), 57 deletions(-) diff --git a/src/db/skip_list.rs b/src/db/skip_list.rs index 628f87c..40436a7 100644 --- a/src/db/skip_list.rs +++ b/src/db/skip_list.rs @@ -1,19 +1,14 @@ -use std::cell::{Cell, RefCell}; -use std::cmp::{max, min, Ordering}; -use std::fmt::format; +use std::cmp::Ordering; use std::mem; -use std::mem::{ManuallyDrop, size_of}; -use std::ops::{Deref, DerefMut}; -use std::ptr::{NonNull, null_mut}; +use std::mem::size_of; +use std::ptr::null_mut; use std::sync::Arc; use rand::prelude::*; use crate::debug; use crate::traits::comparator_trait::ComparatorTrait; -use crate::util::Arena; use crate::util::arena::{ArenaAllocLike, ArenaRef}; -use crate::util::comparator::BytewiseComparatorImpl; use crate::util::Result; use crate::util::slice::Slice; use crate::util::status::{LevelError, Status}; @@ -34,7 +29,7 @@ struct Node { pub struct SkipList { /// 最高层数 - level: usize, + height: usize, /// 存储数据数量 num: usize, /// 头部指针 @@ -55,7 +50,7 @@ pub struct Iter<'a, Cmp: ComparatorTrait> { impl SkipList { pub fn create(comparator: Arc, arena: ArenaRef) -> Self { Self { - level: 0, + height: 0, num: 0, head: Node::create_head(arena.clone()), tail: Node::create_tail(), @@ -65,10 +60,16 @@ impl SkipList { } pub fn insert(&mut self, key: Slice) -> Result<()> { + // TODO 这里是否可以优化 + if self.contains(&key) { + return Ok(()); + } if self.num == 0 { self.insert_ele0(key) } else { - self.insert_elen(key) + unsafe { + self.insert_elen(key) + } } } @@ -87,58 +88,55 @@ impl SkipList { (&mut *node).set_node(l, self.tail); } } - self.level = level; + self.height = level; self.num = 1; return Ok(()); } - fn insert_elen(&mut self, key: Slice) -> Result<()> { + unsafe fn insert_elen(&mut self, key: Slice) -> Result<()> { let mut current = self.head; - let level = rand_level(); - debug!("insert {}, level: {}", &key, level); + let node_height = rand_level(); + let node_top_level = node_height - 1; + debug!("insert {}, level: {}", &key, node_height); let node_ptr = unsafe { - Node::create(key, level, self.arena.clone()) + Node::create(key, node_height, self.arena.clone()) }; let node = unsafe { &mut *node_ptr }; // loop from highest level to 0 - for l in (0..self.level).rev() { + for l in (0..self.height).rev() { 'inner_loop: loop { let ele_ptr = unsafe { (&*current).get_node(l) }; let ele = unsafe { &mut *ele_ptr }; if ele.is_tail() { - if l < level { + if l <= node_top_level { // ele is tail node, add node to last - unsafe { - (&mut *current).set_node(l, node_ptr); - node.set_node(l, self.tail); - debug!("bind: {} before: {}, after: , at level: {}", + (&mut *current).set_node(l, node_ptr); + node.set_node(l, self.tail); + debug!("bind: {} before: {}, after: , at level: {}", node.key.as_ref().unwrap(), (&*current).key.as_ref().unwrap(), l); - }; } break 'inner_loop; } else { match self.cmp.compare(node.key.as_ref().unwrap(), ele.key.as_ref().unwrap()) { Some(Ordering::Less) => { // node higher than current level at ele - if level > l { - unsafe { - (&mut *current).set_node(l, node_ptr); - node.set_node(l, ele_ptr); - if (&*current).is_head() { - debug!("bind: {} before: , after: {}, at level: {}", + if node_top_level >= l { + (&mut *current).set_node(l, node_ptr); + node.set_node(l, ele_ptr); + if (&*current).is_head() { + debug!("bind: {} before: , after: {}, at level: {}", node.key.as_ref().unwrap(), ele.key.as_ref().unwrap(), l); - } else { - debug!("bind: {} before: {}, after: {}, at level: {}", + } else { + debug!("bind: {} before: {}, after: {}, at level: {}", node.key.as_ref().unwrap(), (&*current).key.as_ref().unwrap(), ele.key.as_ref().unwrap(), l); - } - }; + } } break 'inner_loop; } @@ -157,14 +155,12 @@ impl SkipList { } } // if head level is less than new node, then fix head node height - if self.level < level { - for l in (self.level()..level).rev() { - unsafe { - (&mut *self.head).set_node(l, node_ptr); - node.set_node(l, self.tail); - }; + if self.height < node_height { + for l in (self.height()..node_height).rev() { + (&mut *self.head).set_node(l, node_ptr); + node.set_node(l, self.tail); } - self.level = level; + self.height = node_height; } self.num += 1; Ok(()) @@ -178,7 +174,7 @@ impl SkipList { } unsafe { let mut current = unsafe { &*self.head }; - for level in (0..self.level).rev() { + for level in (0..self.height).rev() { 'a_loop: loop { let ele_ptr = current.get_node(level); let ele = &*ele_ptr; @@ -222,8 +218,8 @@ impl SkipList { } #[inline] - pub fn level(&self) -> usize { - self.level + pub fn height(&self) -> usize { + self.height } #[inline] @@ -270,7 +266,7 @@ impl ToString for SkipList { } } tree.push_str("-> [tail]"); - format!("height: {}, num: {}\n {}", self.level, self.num, tree) + format!("height: {}, num: {}\n {}", self.height, self.num, tree) } } diff --git a/src/db/skip_list_test.rs b/src/db/skip_list_test.rs index 93633a6..eb699e9 100644 --- a/src/db/skip_list_test.rs +++ b/src/db/skip_list_test.rs @@ -1,16 +1,14 @@ - mod test { use std::collections::HashSet; - use std::io::{stdout, Write}; - use std::panic; use std::sync::{Arc, Mutex}; + use rand::Rng; - use crate::util::Result; + use crate::db::DefaultSkipList; - use crate::db::skip_list::SkipList; use crate::debug; use crate::util::Arena; use crate::util::comparator::BytewiseComparatorImpl; + use crate::util::Result; use crate::util::slice::Slice; #[test] @@ -58,5 +56,4 @@ mod test { Ok(()) } - } \ No newline at end of file diff --git a/src/util/arena.rs b/src/util/arena.rs index 2022a51..f382625 100644 --- a/src/util/arena.rs +++ b/src/util/arena.rs @@ -1,11 +1,7 @@ -use std::{ptr, slice}; +use std::slice; use std::alloc::{alloc, dealloc, Layout}; -use std::cell::Cell; -use std::ops::Deref; use std::ptr::NonNull; -use std::rc::Rc; use std::sync::{Arc, Mutex}; -use crate::util::mutex_lock::MutexLock; use crate::util::slice::Slice; diff --git a/src/util/mod.rs b/src/util/mod.rs index 652da5d..19c3097 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,9 +1,7 @@ -use std::rc::Rc; use std::result; pub use arena::Arena; -use crate::util::comparator::{BytewiseComparatorImpl, InternalKeyComparator}; use crate::util::status::Status; /// 常量定义 -- Gitee From 7ab46579f8abd8c45c40227dfb601ec7468625eb Mon Sep 17 00:00:00 2001 From: wangboo <5417808+wangboa@user.noreply.gitee.com> Date: Thu, 16 Mar 2023 21:54:51 +0800 Subject: [PATCH 8/8] =?UTF-8?q?=E5=8E=BB=E9=99=A4=E4=B8=80=E4=BA=9B?= =?UTF-8?q?=E6=97=A0=E7=94=A8=E7=9A=84=20use?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/db/log_wr_test.rs | 16 ++++++++-------- src/db/mem_table.rs | 2 +- src/db/mod.rs | 2 +- src/db/skip_list.rs | 6 +++--- src/db/skip_list_test.rs | 20 ++++++++++---------- src/traits/mod.rs | 2 +- src/util/arena.rs | 2 +- src/util/arena_test.rs | 2 +- src/util/coding.rs | 16 ++++++++-------- src/util/coding_test.rs | 6 +++--- src/util/comparator_test.rs | 10 +++++----- src/util/crc_test.rs | 4 ++-- src/util/debug.rs | 4 ++-- src/util/filter_policy.rs | 6 +++--- src/util/filter_policy_test.rs | 10 +++++----- src/util/hash.rs | 4 ++-- src/util/hash_test.rs | 8 ++++---- src/util/histogram_test.rs | 2 +- src/util/mutex_lock.rs | 2 +- src/util/mutex_lock_test.rs | 4 ++-- src/util/slice_test.rs | 4 ++-- src/util/status_test.rs | 6 +++--- 22 files changed, 69 insertions(+), 69 deletions(-) diff --git a/src/db/log_wr_test.rs b/src/db/log_wr_test.rs index 98b1648..d333556 100644 --- a/src/db/log_wr_test.rs +++ b/src/db/log_wr_test.rs @@ -1,12 +1,12 @@ mod test { - use std::fs::File; - use crate::db::log_reader::LogReader; - use crate::db::log_writer::LogWriter; - use crate::traits::coding_trait::CodingTrait; - use crate::util::coding::Coding; - use crate::util::crc::{AsCrc, ToMask}; - use crate::util::Result; + + + + + + + use crate::util::slice::Slice; #[test] @@ -28,7 +28,7 @@ mod test { let sample: Vec = ('0'..='9').map(|a|a as u8).collect(); for i in 0..100 { let slice = reader.read_next().expect("not error").expect("must have record"); - let mut expect = generate_slice(i, &sample); + let expect = generate_slice(i, &sample); assert_eq!(expect.len(), slice.len()); assert_eq!(expect.as_ref(), slice.as_ref()) } diff --git a/src/db/mem_table.rs b/src/db/mem_table.rs index 9bc002c..a9dcf71 100644 --- a/src/db/mem_table.rs +++ b/src/db/mem_table.rs @@ -1,7 +1,7 @@ use std::rc::Rc; use crate::traits::comparator_trait::ComparatorTrait; use crate::traits::DataIterator; -use crate::util::comparator::InternalKeyComparator; + use crate::util::slice::Slice; use crate::util::Result; diff --git a/src/db/mod.rs b/src/db/mod.rs index 6ce1187..5b5ff72 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -1,7 +1,7 @@ use crate::db::mem_table::MemTable; use crate::db::skip_list::SkipList; use crate::util::comparator::{BytewiseComparatorImpl, InternalKeyComparator}; -use crate::util::slice::Slice; + pub mod log_writer; pub mod log_reader; diff --git a/src/db/skip_list.rs b/src/db/skip_list.rs index 40436a7..ddef242 100644 --- a/src/db/skip_list.rs +++ b/src/db/skip_list.rs @@ -273,7 +273,7 @@ impl ToString for SkipList { impl Node { #[inline] - fn create(src: Slice, level: usize, mut arena: ArenaRef) -> RawNode { + fn create(src: Slice, level: usize, arena: ArenaRef) -> RawNode { let key = src.copy_with_arena(arena.clone()); let node = box Self { key: Some(key), @@ -284,7 +284,7 @@ impl Node { } #[inline] - fn create_head(mut arena: ArenaRef) -> RawNode { + fn create_head(arena: ArenaRef) -> RawNode { let node = box Self { key: None, next_elems: allocate_next_elems(arena), @@ -352,7 +352,7 @@ fn rand_level() -> usize { level } -fn allocate_next_elems(mut arena: ArenaRef) -> *mut RawNode { +fn allocate_next_elems(arena: ArenaRef) -> *mut RawNode { // RawNode is a raw ptr assert_eq!(size_of::(), size_of::()); // allocate next_elems to 8 capacity array diff --git a/src/db/skip_list_test.rs b/src/db/skip_list_test.rs index eb699e9..287d18c 100644 --- a/src/db/skip_list_test.rs +++ b/src/db/skip_list_test.rs @@ -1,15 +1,15 @@ mod test { - use std::collections::HashSet; - use std::sync::{Arc, Mutex}; + + - use rand::Rng; + - use crate::db::DefaultSkipList; - use crate::debug; - use crate::util::Arena; - use crate::util::comparator::BytewiseComparatorImpl; - use crate::util::Result; - use crate::util::slice::Slice; + + + + + + #[test] fn test_add() -> Result<()> { @@ -41,7 +41,7 @@ mod test { let len = 10; let mut rnd = rand::thread_rng(); let mut set = HashSet::new(); - for i in 0..10 { + for _i in 0..10 { let j = rnd.gen_range(0..len); let key = format!("key_{}", j); set.insert(key.clone()); diff --git a/src/traits/mod.rs b/src/traits/mod.rs index 47c662e..a1332ef 100644 --- a/src/traits/mod.rs +++ b/src/traits/mod.rs @@ -4,5 +4,5 @@ pub mod comparator_trait; pub mod coding_trait; pub mod filter_policy_trait; -use std::rc::Rc; + pub use iterator::DataIterator; diff --git a/src/util/arena.rs b/src/util/arena.rs index f382625..d239b48 100644 --- a/src/util/arena.rs +++ b/src/util/arena.rs @@ -115,7 +115,7 @@ impl Drop for Arena { } impl ArenaAllocLike for Slice { - fn copy_with_arena(&self, mut arena: ArenaRef) -> Self { + fn copy_with_arena(&self, arena: ArenaRef) -> Self { unsafe { let mut lock_guard = arena.lock().unwrap(); let dst = lock_guard.allocate(self.len()); diff --git a/src/util/arena_test.rs b/src/util/arena_test.rs index dbc8cf1..fc800e1 100644 --- a/src/util/arena_test.rs +++ b/src/util/arena_test.rs @@ -1,4 +1,4 @@ -use crate::util::Arena; + #[test] fn test_memory_usage() { diff --git a/src/util/coding.rs b/src/util/coding.rs index 125c042..f27bc7e 100644 --- a/src/util/coding.rs +++ b/src/util/coding.rs @@ -28,7 +28,7 @@ macro_rules! varint { pub struct Coding {} impl CodingTrait for Coding { - fn put_fixed32(mut dst: &mut String, value: u32) { + fn put_fixed32(dst: &mut String, value: u32) { let mut buf: [u8; 4] = [0, 0, 0, 0]; Self::encode_fixed32(value, &mut buf, 0); for b in buf.iter() { @@ -36,7 +36,7 @@ impl CodingTrait for Coding { } } - fn put_fixed64(mut dst: &mut String, value: u64) { + fn put_fixed64(dst: &mut String, value: u64) { let mut buf: [u8; 8] = [0, 0, 0, 0, 0, 0, 0, 0]; Self::encode_fixed64(value, &mut buf, 0); for b in buf.iter() { @@ -48,7 +48,7 @@ impl CodingTrait for Coding { varint!(u64,encode_varint64); - fn put_varint32(mut dst: &mut String, value: u32) { + fn put_varint32(dst: &mut String, value: u32) { let mut buf: [u8; 4] = [0, 0, 0, 0]; Self::encode_fixed32(value, &mut buf, 0); for b in buf.iter() { @@ -56,7 +56,7 @@ impl CodingTrait for Coding { } } - fn put_varint64(mut dst: &mut String, value: u64) { + fn put_varint64(dst: &mut String, value: u64) { let mut buf: [u8; 8] = [0, 0, 0, 0, 0, 0, 0, 0]; Self::encode_fixed64(value, &mut buf, 0); for b in buf.iter() { @@ -125,7 +125,7 @@ impl CodingTrait for Coding { len } - fn encode_fixed32(mut value: u32, buf: &mut [u8], mut offset: usize) -> usize { + fn encode_fixed32(value: u32, buf: &mut [u8], mut offset: usize) -> usize { buf[offset] = value as u8; offset += 1; buf[offset] = (value >> 8) as u8; @@ -137,7 +137,7 @@ impl CodingTrait for Coding { offset } - fn encode_fixed64(mut value: u64, buf: &mut [u8], mut offset: usize) -> usize { + fn encode_fixed64(value: u64, buf: &mut [u8], mut offset: usize) -> usize { buf[offset] = value as u8; offset += 1; buf[offset] = (value >> 8) as u8; @@ -196,7 +196,7 @@ macro_rules! encoding_impl { /// let value: u32 = 65534; /// let offset = value.varint(&mut buf, 0); /// ``` - fn varint(self, buf: &mut [u8], mut offset: usize) -> usize { + fn varint(self, buf: &mut [u8], offset: usize) -> usize { Coding::$VAR_NAME (self, buf, offset) } /// 定长正整数编码 @@ -215,7 +215,7 @@ macro_rules! encoding_impl { /// let value: u32 = 65534; /// let offset = value.fixedint(&mut buf, 0); /// ``` - fn fixedint(self, buf: &mut [u8], mut offset: usize) -> usize { + fn fixedint(self, buf: &mut [u8], offset: usize) -> usize { Coding::$FIXED_NAME (self, buf, offset) } } diff --git a/src/util/coding_test.rs b/src/util/coding_test.rs index 69ed744..fd56327 100644 --- a/src/util/coding_test.rs +++ b/src/util/coding_test.rs @@ -1,7 +1,7 @@ mod test { - use crate::traits::coding_trait::{Coding32, Coding64, CodingTrait}; - use crate::util::slice::Slice; - use crate::util::coding::{Coding}; + + + #[test] fn test_put_fixed32() { diff --git a/src/util/comparator_test.rs b/src/util/comparator_test.rs index fcfb034..234ccb8 100644 --- a/src/util/comparator_test.rs +++ b/src/util/comparator_test.rs @@ -1,10 +1,10 @@ mod test { - use std::cmp::Ordering; - use std::io::Write; - use crate::traits::comparator_trait::ComparatorTrait; - use crate::util::comparator::{BytewiseComparatorImpl, InternalKeyComparator}; - use crate::util::slice::Slice; + + + + + #[test] fn test_bytewise_comparator_impl_get_name() { diff --git a/src/util/crc_test.rs b/src/util/crc_test.rs index c67c0db..e304450 100644 --- a/src/util/crc_test.rs +++ b/src/util/crc_test.rs @@ -1,5 +1,5 @@ -use crate::util::crc::{AsCrc, CRC, ToMask}; -use crate::util::slice::Slice; + + #[test] fn test_crc() { diff --git a/src/util/debug.rs b/src/util/debug.rs index c32caf1..464919b 100644 --- a/src/util/debug.rs +++ b/src/util/debug.rs @@ -1,5 +1,5 @@ -use std::fmt::format; -use std::io::Write; + + // #[cfg(feature = "debug-macro")] #[cfg(CORE_DEBUG = "true")] diff --git a/src/util/filter_policy.rs b/src/util/filter_policy.rs index 5a87f2e..8ddd651 100644 --- a/src/util/filter_policy.rs +++ b/src/util/filter_policy.rs @@ -1,6 +1,6 @@ use std::ops::Mul; use crate::traits::filter_policy_trait::{FilterPolicy}; -use crate::util::hash::{Hash, ToHash}; +use crate::util::hash::{ToHash}; use crate::util::slice::Slice; pub struct BloomFilterPolicy { @@ -43,7 +43,7 @@ impl FilterPolicy for BloomFilterPolicy { String::from("leveldb.BuiltinBloomFilter2") } - fn create_filter(&self, keys: Slice, n: u32, dst: String) -> String { + fn create_filter(&self, _keys: Slice, _n: u32, _dst: String) -> String { // 根据指定的参数创建过滤器,并返回结果, 结果为dst的原始内容 + append结果。 // 参数keys[0,n-1]包含依据用户提供的comparator排序的key列表--可重复, // 并把根据这些key创建的filter追加到 dst中。 @@ -51,7 +51,7 @@ impl FilterPolicy for BloomFilterPolicy { todo!() } - fn key_may_match(key: &Slice, filter: &Slice) -> bool { + fn key_may_match(_key: &Slice, _filter: &Slice) -> bool { todo!() } } \ No newline at end of file diff --git a/src/util/filter_policy_test.rs b/src/util/filter_policy_test.rs index b49448f..c5175de 100644 --- a/src/util/filter_policy_test.rs +++ b/src/util/filter_policy_test.rs @@ -1,14 +1,14 @@ -use std::ptr::null; -use crate::util::bloom_filter; -use crate::util::filter_policy::BloomFilterPolicy; + + + #[test] fn test_new() { - let bloom_filter = BloomFilterPolicy::new(8); + let _bloom_filter = BloomFilterPolicy::new(8); println!("hash:{}", "a"); // assert_eq!(bloom_filter, null()); - let bloom_filter = BloomFilterPolicy::new(800); + let _bloom_filter = BloomFilterPolicy::new(800); println!("hash:{}", "a"); } \ No newline at end of file diff --git a/src/util/hash.rs b/src/util/hash.rs index c9fce80..3d7f257 100644 --- a/src/util/hash.rs +++ b/src/util/hash.rs @@ -4,9 +4,9 @@ use std::slice as stds; use crate::traits::coding_trait::CodingTrait; use crate::util::coding::Coding; -use crate::util::crc::AsCrc; + use crate::util::r#const::HASH_DEFAULT_SEED; -use crate::util::slice; + use crate::util::slice::Slice; /// 一种可以计算 hash 的特质 diff --git a/src/util/hash_test.rs b/src/util/hash_test.rs index 81dce89..e0961d0 100644 --- a/src/util/hash_test.rs +++ b/src/util/hash_test.rs @@ -1,7 +1,7 @@ -use crate::util::hash::{Hash, ToHash}; -use crate::util::r#const::HASH_DEFAULT_SEED; -use crate::util::slice::Slice; -use std::slice; + + + + #[test] fn test_hash() { diff --git a/src/util/histogram_test.rs b/src/util/histogram_test.rs index a4f01e7..74e9033 100644 --- a/src/util/histogram_test.rs +++ b/src/util/histogram_test.rs @@ -1,6 +1,6 @@ mod test{ - use crate::util::histogram::Histogram; + #[test] fn test_add() { diff --git a/src/util/mutex_lock.rs b/src/util/mutex_lock.rs index 84e6d65..c6c4d77 100644 --- a/src/util/mutex_lock.rs +++ b/src/util/mutex_lock.rs @@ -1,4 +1,4 @@ -use std::ops::Deref; + use std::sync::{Arc, LockResult, Mutex, MutexGuard, TryLockResult}; pub struct Lock { diff --git a/src/util/mutex_lock_test.rs b/src/util/mutex_lock_test.rs index 7273a71..548871f 100644 --- a/src/util/mutex_lock_test.rs +++ b/src/util/mutex_lock_test.rs @@ -1,7 +1,7 @@ mod test { - use std::thread; + - use crate::util::mutex_lock::MutexLock; + #[test] fn test() { diff --git a/src/util/slice_test.rs b/src/util/slice_test.rs index a2e0ec5..75ae7a7 100644 --- a/src/util/slice_test.rs +++ b/src/util/slice_test.rs @@ -1,5 +1,5 @@ mod test { - use std::cmp::Ordering; + use crate::util::slice::Slice; #[test] @@ -88,7 +88,7 @@ mod test { #[test] fn test_merge2() { let mut a0 = Slice::from("123"); - let mut a2 = Slice::from("456"); + let a2 = Slice::from("456"); a0.merge(a2, None); assert_eq!(String::from("123456"), String::from(a0)); } diff --git a/src/util/status_test.rs b/src/util/status_test.rs index 2ac1030..90f66ec 100644 --- a/src/util/status_test.rs +++ b/src/util/status_test.rs @@ -1,8 +1,8 @@ mod test { - use crate::util::r#const::COLON_WHITE_SPACE; - use crate::util::slice::Slice; - use crate::util::status::{LevelError, Status}; + + + #[test] fn test_wraper() { -- Gitee