diff --git a/Cargo.toml b/Cargo.toml index 57d19db..6b59043 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "value-log" description = "Value log implementation for key-value separated LSM storage" license = "MIT OR Apache-2.0" -version = "1.1.1" +version = "1.2.0" edition = "2021" rust-version = "1.74.0" readme = "README.md" @@ -27,7 +27,7 @@ min-max-heap = "1.3.0" path-absolutize = "3.1.1" quick_cache = { version = "0.6.5", default-features = false } rustc-hash = "2.0.0" -serde = { version = "1.0.204", optional = true, features = ["derive"] } +serde = { version = "1.0.215", optional = true, features = ["derive"] } tempfile = "3.12.0" xxhash-rust = { version = "0.8.12", features = ["xxh3"] } diff --git a/src/key_range.rs b/src/key_range.rs index 88f3ce7..d478bd9 100644 --- a/src/key_range.rs +++ b/src/key_range.rs @@ -53,14 +53,10 @@ impl Encode for KeyRange { impl Decode for KeyRange { fn decode_from(reader: &mut R) -> Result { let key_min_len = reader.read_u16::()?; - let mut key_min = vec![0; key_min_len.into()]; - reader.read_exact(&mut key_min)?; - let key_min: UserKey = Slice::from(key_min); + let key_min: UserKey = Slice::from_reader(reader, key_min_len.into())?; let key_max_len = reader.read_u16::()?; - let mut key_max = vec![0; key_max_len.into()]; - reader.read_exact(&mut key_max)?; - let key_max: UserKey = Slice::from(key_max); + let key_max: UserKey = Slice::from_reader(reader, key_max_len.into())?; Ok(Self::new((key_min, key_max))) } diff --git a/src/slice.rs b/src/slice.rs index 0020988..60e1f2a 100644 --- a/src/slice.rs +++ b/src/slice.rs @@ -15,6 +15,22 @@ impl Slice { pub fn new(bytes: &[u8]) -> Self { Self::from(bytes) } + + #[must_use] + #[doc(hidden)] + pub fn with_size(len: usize) -> Self { + // TODO: optimize this with byteview to remove the reallocation + let v = vec![0; len]; + Self(v.into()) + } + + #[doc(hidden)] + pub fn from_reader(reader: &mut R, len: usize) -> std::io::Result { + let mut view = Self::with_size(len); + let builder = Arc::get_mut(&mut view.0).expect("we are the owner"); + reader.read_exact(builder)?; + Ok(view) + } } impl std::borrow::Borrow<[u8]> for Slice { diff --git a/tests/basic_kv.rs b/tests/basic_kv.rs index 4de8f43..5956ebb 100644 --- a/tests/basic_kv.rs +++ b/tests/basic_kv.rs @@ -23,30 +23,34 @@ fn basic_kv() -> value_log::Result<()> { let index = MockIndex::default(); - let value_log = ValueLog::open(vl_path, Config::::default())?; - let items = ["a", "b", "c", "d", "e"]; { - let mut index_writer = MockIndexWriter(index.clone()); - let mut writer = value_log.get_writer()?; + let value_log = ValueLog::open(vl_path, Config::::default())?; - for key in &items { - let value = key.repeat(10_000); - let value = value.as_bytes(); + { + let mut index_writer = MockIndexWriter(index.clone()); + let mut writer = value_log.get_writer()?; - let key = key.as_bytes(); + for key in &items { + let value = key.repeat(10_000); + let value = value.as_bytes(); - let vhandle = writer.get_next_value_handle(); - index_writer.insert_indirect(key, vhandle, value.len() as u32)?; + let key = key.as_bytes(); - writer.write(key, value)?; - } + let vhandle = writer.get_next_value_handle(); + index_writer.insert_indirect(key, vhandle, value.len() as u32)?; - value_log.register_writer(writer)?; + writer.write(key, value)?; + } + + value_log.register_writer(writer)?; + } } { + let value_log = ValueLog::open(vl_path, Config::::default())?; + assert_eq!(1, value_log.segment_count()); let segments = value_log.manifest.list_segments(); @@ -65,11 +69,11 @@ fn basic_kv() -> value_log::Result<()> { segment.len(), segment.scan().into_iter().flatten().count() as u64 ); - } - for (key, (vhandle, _)) in index.read().unwrap().iter() { - let item = value_log.get(vhandle)?.unwrap(); - assert_eq!(&*item, &*key.repeat(10_000)); + for (key, (vhandle, _)) in index.read().unwrap().iter() { + let item = value_log.get(vhandle)?.unwrap(); + assert_eq!(&*item, &*key.repeat(10_000)); + } } Ok(())