From ece485fdb5da5b57a09a6b042458b56f80649972 Mon Sep 17 00:00:00 2001 From: al8n Date: Mon, 30 Sep 2024 16:29:48 +0800 Subject: [PATCH 1/3] Add `K: ?Sized` and `V: ?Sized` for generic wal --- src/entry.rs | 77 ++++++++---------- src/pointer.rs | 41 +++++++--- src/swmr/generic.rs | 129 +++++++++++++++++++++---------- src/swmr/generic/builder.rs | 28 ++++--- src/swmr/generic/iter.rs | 38 ++++++--- src/swmr/generic/reader.rs | 21 +++-- src/swmr/generic/tests/get.rs | 9 +-- src/swmr/generic/tests/insert.rs | 26 ++----- src/wal/type.rs | 29 ------- 9 files changed, 221 insertions(+), 177 deletions(-) diff --git a/src/entry.rs b/src/entry.rs index 55198a8..e5a6b86 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -1,12 +1,11 @@ use core::borrow::Borrow; -use among::Among; use crossbeam_skiplist::set::Entry as SetEntry; +use dbutils::traits::{Type, TypeRef}; use rarena_allocator::either::Either; use super::{ pointer::{GenericPointer, Pointer}, - wal::r#type::{Type, TypeRef}, KeyBuilder, ValueBuilder, }; @@ -263,26 +262,24 @@ impl EntryWithBuilders { /// A wrapper around a generic type that can be used to construct a [`GenericEntry`]. #[repr(transparent)] -pub struct Generic<'a, T> { - data: Among, +pub struct Generic<'a, T: ?Sized> { + data: Either<&'a T, &'a [u8]>, } -impl Generic<'_, T> { +impl Generic<'_, T> { #[inline] pub(crate) fn encoded_len(&self) -> usize { match &self.data { - Among::Left(val) => val.encoded_len(), - Among::Middle(val) => val.encoded_len(), - Among::Right(val) => val.len(), + Either::Left(val) => val.encoded_len(), + Either::Right(val) => val.len(), } } #[inline] pub(crate) fn encode(&self, buf: &mut [u8]) -> Result { match &self.data { - Among::Left(val) => val.encode(buf), - Among::Middle(val) => val.encode(buf), - Among::Right(val) => { + Either::Left(val) => val.encode(buf), + Either::Right(val) => { buf.copy_from_slice(val); Ok(buf.len()) } @@ -290,15 +287,11 @@ impl Generic<'_, T> { } } -impl<'a, T> Generic<'a, T> { +impl<'a, T: ?Sized> Generic<'a, T> { /// Returns the value contained in the generic. #[inline] pub const fn data(&self) -> Either<&T, &'a [u8]> { - match &self.data { - Among::Left(val) => Either::Left(val), - Among::Middle(val) => Either::Left(val), - Among::Right(val) => Either::Right(val), - } + self.data } /// Creates a new generic from bytes for querying or inserting into the [`GenericOrderWal`](crate::swmr::GenericOrderWal). @@ -308,43 +301,29 @@ impl<'a, T> Generic<'a, T> { #[inline] pub const unsafe fn from_slice(slice: &'a [u8]) -> Self { Self { - data: Among::Right(slice), + data: Either::Right(slice), } } - - #[inline] - pub(crate) fn into_among(self) -> Among { - self.data - } } -impl<'a, T> From<&'a T> for Generic<'a, T> { +impl<'a, T: ?Sized> From<&'a T> for Generic<'a, T> { #[inline] fn from(value: &'a T) -> Self { Self { - data: Among::Middle(value), - } - } -} - -impl From for Generic<'_, T> { - #[inline] - fn from(value: T) -> Self { - Self { - data: Among::Left(value), + data: Either::Left(value), } } } /// An entry in the [`GenericOrderWal`](crate::swmr::GenericOrderWal). -pub struct GenericEntry<'a, K, V> { +pub struct GenericEntry<'a, K: ?Sized, V: ?Sized> { pub(crate) key: Generic<'a, K>, pub(crate) value: Generic<'a, V>, pub(crate) pointer: Option>, pub(crate) meta: BatchEncodedEntryMeta, } -impl<'a, K, V> GenericEntry<'a, K, V> { +impl<'a, K: ?Sized, V: ?Sized> GenericEntry<'a, K, V> { /// Creates a new entry. #[inline] pub fn new(key: impl Into>, value: impl Into>) -> Self { @@ -377,15 +356,19 @@ impl<'a, K, V> GenericEntry<'a, K, V> { /// The reference to an entry in the [`GenericOrderWal`](crate::swmr::GenericOrderWal). #[repr(transparent)] -pub struct GenericEntryRef<'a, K, V> { +pub struct GenericEntryRef<'a, K, V> +where + K: ?Sized, + V: ?Sized, +{ ent: SetEntry<'a, GenericPointer>, } impl<'a, K, V> core::fmt::Debug for GenericEntryRef<'a, K, V> where - K: Type, + K: Type + ?Sized, K::Ref<'a>: core::fmt::Debug, - V: Type, + V: Type + ?Sized, V::Ref<'a>: core::fmt::Debug, { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { @@ -396,7 +379,11 @@ where } } -impl Clone for GenericEntryRef<'_, K, V> { +impl Clone for GenericEntryRef<'_, K, V> +where + K: ?Sized, + V: ?Sized, +{ #[inline] fn clone(&self) -> Self { Self { @@ -405,7 +392,11 @@ impl Clone for GenericEntryRef<'_, K, V> { } } -impl<'a, K, V> GenericEntryRef<'a, K, V> { +impl<'a, K, V> GenericEntryRef<'a, K, V> +where + K: ?Sized, + V: ?Sized, +{ #[inline] pub(super) fn new(ent: SetEntry<'a, GenericPointer>) -> Self { Self { ent } @@ -414,8 +405,8 @@ impl<'a, K, V> GenericEntryRef<'a, K, V> { impl<'a, K, V> GenericEntryRef<'a, K, V> where - K: Type, - V: Type, + K: Type + ?Sized, + V: Type + ?Sized, { /// Returns the key of the entry. #[inline] diff --git a/src/pointer.rs b/src/pointer.rs index c114be0..1b1ae9a 100644 --- a/src/pointer.rs +++ b/src/pointer.rs @@ -1,8 +1,9 @@ use core::{borrow::Borrow, cmp, marker::PhantomData, slice}; -use dbutils::Comparator; - -use super::wal::r#type::{KeyRef, Type}; +use dbutils::{ + traits::{KeyRef, Type}, + Comparator, +}; #[doc(hidden)] pub struct Pointer { @@ -94,7 +95,7 @@ impl super::wal::sealed::Pointer for Pointer { #[doc(hidden)] #[derive(Debug)] -pub struct GenericPointer { +pub struct GenericPointer { /// The pointer to the start of the entry. ptr: *const u8, /// The length of the key. @@ -104,7 +105,7 @@ pub struct GenericPointer { _m: PhantomData<(fn() -> K, fn() -> V)>, } -impl crate::wal::sealed::Pointer for GenericPointer { +impl crate::wal::sealed::Pointer for GenericPointer { type Comparator = (); #[inline] @@ -113,18 +114,19 @@ impl crate::wal::sealed::Pointer for GenericPointer { } } -impl PartialEq for GenericPointer { +impl PartialEq for GenericPointer { fn eq(&self, other: &Self) -> bool { self.as_key_slice() == other.as_key_slice() } } -impl Eq for GenericPointer {} +impl Eq for GenericPointer {} impl PartialOrd for GenericPointer where - K: Type + Ord, + K: Type + Ord + ?Sized, for<'a> K::Ref<'a>: KeyRef<'a, K>, + V: ?Sized, { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) @@ -133,8 +135,9 @@ where impl Ord for GenericPointer where - K: Type + Ord, + K: Type + Ord + ?Sized, for<'a> K::Ref<'a>: KeyRef<'a, K>, + V: ?Sized, { fn cmp(&self, other: &Self) -> cmp::Ordering { // SAFETY: WALs guarantee that the self and other must be the same as the result returned by `::encode`. @@ -142,10 +145,24 @@ where } } -unsafe impl Send for GenericPointer {} -unsafe impl Sync for GenericPointer {} +unsafe impl Send for GenericPointer +where + K: ?Sized, + V: ?Sized, +{ +} +unsafe impl Sync for GenericPointer +where + K: ?Sized, + V: ?Sized, +{ +} -impl GenericPointer { +impl GenericPointer +where + K: ?Sized, + V: ?Sized, +{ #[inline] pub(crate) const fn new(key_len: usize, value_len: usize, ptr: *const u8) -> Self { Self { diff --git a/src/swmr/generic.rs b/src/swmr/generic.rs index c9db0ed..ac29404 100644 --- a/src/swmr/generic.rs +++ b/src/swmr/generic.rs @@ -29,10 +29,13 @@ use crate::{ pub use crate::{ entry::{Generic, GenericEntry, GenericEntryRef}, - wal::{r#type::*, GenericBatch}, + wal::GenericBatch, }; -pub use dbutils::equivalent::{Comparable, Equivalent}; +pub use dbutils::{ + equivalent::{Comparable, Equivalent}, + traits::{KeyRef, Type, TypeRef}, +}; mod reader; pub use reader::*; @@ -55,23 +58,23 @@ pub use builder::*; ))] mod tests; -struct PartialPointer { +struct PartialPointer { key_len: usize, ptr: *const u8, _k: PhantomData, } -impl PartialEq for PartialPointer { +impl PartialEq for PartialPointer { fn eq(&self, other: &Self) -> bool { self.as_key_slice() == other.as_key_slice() } } -impl Eq for PartialPointer {} +impl Eq for PartialPointer {} impl PartialOrd for PartialPointer where - K: Type + Ord, + K: Type + Ord + ?Sized, for<'a> K::Ref<'a>: KeyRef<'a, K>, { fn partial_cmp(&self, other: &Self) -> Option { @@ -81,7 +84,7 @@ where impl Ord for PartialPointer where - K: Type + Ord, + K: Type + Ord + ?Sized, for<'a> K::Ref<'a>: KeyRef<'a, K>, { fn cmp(&self, other: &Self) -> cmp::Ordering { @@ -89,7 +92,10 @@ where } } -impl PartialPointer { +impl PartialPointer +where + K: ?Sized, +{ #[inline] const fn new(key_len: usize, ptr: *const u8) -> Self { Self { @@ -112,8 +118,9 @@ impl PartialPointer { impl<'a, K, V> Equivalent> for PartialPointer where - K: Type + Ord, + K: Type + Ord + ?Sized, K::Ref<'a>: KeyRef<'a, K>, + V: ?Sized, { fn equivalent(&self, key: &GenericPointer) -> bool { self.compare(key).is_eq() @@ -122,8 +129,9 @@ where impl<'a, K, V> Comparable> for PartialPointer where - K: Type + Ord, + K: Type + Ord + ?Sized, K::Ref<'a>: KeyRef<'a, K>, + V: ?Sized, { fn compare(&self, p: &GenericPointer) -> cmp::Ordering { unsafe { @@ -135,12 +143,20 @@ where } #[derive(PartialEq, Eq, PartialOrd, Ord)] -struct Ref<'a, K, Q: ?Sized> { +struct Ref<'a, K, Q> +where + K: ?Sized, + Q: ?Sized, +{ key: &'a Q, _k: PhantomData, } -impl<'a, K, Q: ?Sized> Ref<'a, K, Q> { +impl<'a, K, Q> Ref<'a, K, Q> +where + K: ?Sized, + Q: ?Sized, +{ #[inline] const fn new(key: &'a Q) -> Self { Self { @@ -152,8 +168,9 @@ impl<'a, K, Q: ?Sized> Ref<'a, K, Q> { impl<'a, K, Q, V> Equivalent> for Ref<'a, K, Q> where - K: Type + Ord, + K: Type + Ord + ?Sized, K::Ref<'a>: KeyRef<'a, K>, + V: ?Sized, Q: ?Sized + Ord + Comparable>, { fn equivalent(&self, key: &GenericPointer) -> bool { @@ -163,8 +180,9 @@ where impl<'a, K, Q, V> Comparable> for Ref<'a, K, Q> where - K: Type + Ord, + K: Type + Ord + ?Sized, K::Ref<'a>: KeyRef<'a, K>, + V: ?Sized, Q: ?Sized + Ord + Comparable>, { fn compare(&self, p: &GenericPointer) -> cmp::Ordering { @@ -174,12 +192,20 @@ where } #[derive(PartialEq, Eq, PartialOrd, Ord)] -struct Owned<'a, K, Q: ?Sized> { +struct Owned<'a, K, Q> +where + K: ?Sized, + Q: ?Sized, +{ key: &'a Q, _k: PhantomData, } -impl<'a, K, Q: ?Sized> Owned<'a, K, Q> { +impl<'a, K, Q> Owned<'a, K, Q> +where + K: ?Sized, + Q: ?Sized, +{ #[inline] const fn new(key: &'a Q) -> Self { Self { @@ -191,8 +217,9 @@ impl<'a, K, Q: ?Sized> Owned<'a, K, Q> { impl<'a, K, Q, V> Equivalent> for Owned<'a, K, Q> where - K: Type + Ord, + K: Type + Ord + ?Sized, K::Ref<'a>: KeyRef<'a, K>, + V: ?Sized, Q: ?Sized + Ord + Comparable + Comparable>, { fn equivalent(&self, key: &GenericPointer) -> bool { @@ -202,8 +229,9 @@ where impl<'a, K, Q, V> Comparable> for Owned<'a, K, Q> where - K: Type + Ord, + K: Type + Ord + ?Sized, K::Ref<'a>: KeyRef<'a, K>, + V: ?Sized, Q: ?Sized + Ord + Comparable + Comparable>, { fn compare(&self, p: &GenericPointer) -> cmp::Ordering { @@ -213,14 +241,18 @@ where } #[doc(hidden)] -pub struct GenericOrderWalCore { +pub struct GenericOrderWalCore { arena: Arena, map: SkipSet>, opts: Options, cks: S, } -impl crate::wal::sealed::WalCore<(), S> for GenericOrderWalCore { +impl crate::wal::sealed::WalCore<(), S> for GenericOrderWalCore +where + K: ?Sized, + V: ?Sized, +{ type Allocator = Arena; type Base = SkipSet>; @@ -238,7 +270,11 @@ impl crate::wal::sealed::WalCore<(), S> for GenericOrderWalCore GenericOrderWalCore { +impl GenericOrderWalCore +where + K: ?Sized, + V: ?Sized, +{ #[inline] fn len(&self) -> usize { self.map.len() @@ -313,7 +349,11 @@ impl GenericOrderWalCore { } } -impl Constructor<(), S> for GenericOrderWal { +impl Constructor<(), S> for GenericOrderWal +where + K: ?Sized, + V: ?Sized, +{ type Allocator = Arena; type Core = GenericOrderWalCore; @@ -334,9 +374,9 @@ impl Constructor<(), S> for GenericOrderWal { impl GenericOrderWalCore where - K: Type + Ord, + K: Type + Ord + ?Sized, for<'a> ::Ref<'a>: KeyRef<'a, K>, - V: Type, + V: Type + ?Sized, { #[inline] fn contains_key<'a, Q>(&'a self, key: &'a Q) -> bool @@ -397,15 +437,16 @@ where /// Both read and write operations of this WAL are zero-cost (no allocation will happen for both read and write). /// /// Users can create multiple readers from the WAL by [`GenericOrderWal::reader`], but only one writer is allowed. -pub struct GenericOrderWal { +pub struct GenericOrderWal { core: Arc>, ro: bool, } impl GenericOrderWal where - K: Type + Ord + 'static, + K: Type + Ord + ?Sized + 'static, for<'a> ::Ref<'a>: KeyRef<'a, K>, + V: ?Sized, { /// Returns the first key-value pair in the map. The key in this pair is the minimum key in the wal. #[inline] @@ -454,8 +495,8 @@ where impl GenericOrderWal where - K: 'static, - V: 'static, + K: ?Sized + 'static, + V: ?Sized + 'static, { /// Returns a read-only WAL instance. #[inline] @@ -512,9 +553,9 @@ where impl GenericOrderWal where - K: Type + Ord, + K: Type + Ord + ?Sized, for<'a> K::Ref<'a>: KeyRef<'a, K>, - V: Type, + V: Type + ?Sized, { /// Returns `true` if the key exists in the WAL. #[inline] @@ -573,9 +614,9 @@ where impl GenericOrderWal where - K: Type + Ord + for<'a> Comparable> + 'static, + K: Type + Ord + for<'a> Comparable> + ?Sized + 'static, for<'a> K::Ref<'a>: KeyRef<'a, K>, - V: Type + 'static, + V: Type + ?Sized + 'static, S: BuildChecksumer, { /// Gets or insert the key value pair. @@ -594,7 +635,7 @@ where match ent.map(|e| Either::Left(GenericEntryRef::new(e))) { Some(e) => e, - None => Either::Right(self.insert_in(key.into_among(), value.into().into_among())), + None => Either::Right(self.insert_in(key, value.into())), } } @@ -603,8 +644,11 @@ where pub fn get_or_insert_with<'a>( &mut self, key: impl Into>, - value: impl FnOnce() -> Generic<'a, V>, - ) -> Either, Result<(), Among>> { + value: impl FnOnce() -> V, + ) -> Either, Result<(), Among>> + where + V: Sized, + { let key: Generic<'a, K> = key.into(); let map = &self.core.map; let ent = match key.data() { @@ -614,16 +658,19 @@ where match ent.map(|e| Either::Left(GenericEntryRef::new(e))) { Some(e) => e, - None => Either::Right(self.insert_in(key.into_among(), value().into_among())), + None => { + let v = value(); + Either::Right(self.insert_in(key, (&v).into())) + } } } } impl GenericOrderWal where - K: Type + Ord + 'static, + K: Type + Ord + ?Sized + 'static, for<'a> K::Ref<'a>: KeyRef<'a, K>, - V: Type + 'static, + V: Type + ?Sized + 'static, S: BuildChecksumer, { /// Inserts a key-value pair into the write-ahead log. @@ -689,7 +736,7 @@ where key: impl Into>, val: impl Into>, ) -> Result<(), Among> { - self.insert_in(key.into().into_among(), val.into().into_among()) + self.insert_in(key.into(), val.into()) } /// Inserts a batch of entries into the write-ahead log. @@ -808,8 +855,8 @@ where fn insert_in( &self, - key: Among, - val: Among, + key: Generic<'_, K>, + val: Generic<'_, V>, ) -> Result<(), Among> { let klen = key.encoded_len(); let vlen = val.encoded_len(); diff --git a/src/swmr/generic/builder.rs b/src/swmr/generic/builder.rs index f5d6029..157d303 100644 --- a/src/swmr/generic/builder.rs +++ b/src/swmr/generic/builder.rs @@ -652,7 +652,11 @@ impl GenericBuilder { /// let wal = GenericBuilder::new().with_capacity(1024).alloc::().unwrap(); /// ``` #[inline] - pub fn alloc(self) -> Result, Error> { + pub fn alloc(self) -> Result, Error> + where + K: ?Sized, + V: ?Sized, + { let Self { opts, cks } = self; arena_options(opts.reserved()) @@ -674,7 +678,11 @@ impl GenericBuilder { /// let wal = GenericBuilder::new().with_capacity(1024).map_anon::().unwrap(); /// ``` #[inline] - pub fn map_anon(self) -> Result, Error> { + pub fn map_anon(self) -> Result, Error> + where + K: ?Sized, + V: ?Sized, + { let Self { opts, cks } = self; arena_options(opts.reserved()) @@ -723,9 +731,9 @@ impl GenericBuilder { #[inline] pub unsafe fn map>(self, path: P) -> Result, Error> where - K: Type + Ord + 'static, + K: Type + Ord + ?Sized + 'static, for<'a> K::Ref<'a>: KeyRef<'a, K>, - V: 'static, + V: ?Sized + 'static, { self .map_with_path_builder::(|| dummy_path_builder(path)) @@ -771,9 +779,9 @@ impl GenericBuilder { path_builder: PB, ) -> Result, Either> where - K: Type + Ord + 'static, + K: Type + Ord + ?Sized + 'static, for<'a> K::Ref<'a>: KeyRef<'a, K>, - V: 'static, + V: ?Sized + 'static, PB: FnOnce() -> Result, { let Self { cks, opts } = self; @@ -826,9 +834,9 @@ impl GenericBuilder { path: P, ) -> Result, Error> where - K: Type + Ord + 'static, + K: Type + Ord + ?Sized + 'static, for<'a> K::Ref<'a>: KeyRef<'a, K>, - V: 'static, + V: ?Sized + 'static, { self .map_mut_with_path_builder::(|| dummy_path_builder(path)) @@ -871,9 +879,9 @@ impl GenericBuilder { path_builder: PB, ) -> Result, Either> where - K: Type + Ord + 'static, + K: Type + Ord + ?Sized + 'static, for<'a> K::Ref<'a>: KeyRef<'a, K>, - V: 'static, + V: ?Sized + 'static, PB: FnOnce() -> Result, { let Self { opts, cks } = self; diff --git a/src/swmr/generic/iter.rs b/src/swmr/generic/iter.rs index 477ba6b..a11b91f 100644 --- a/src/swmr/generic/iter.rs +++ b/src/swmr/generic/iter.rs @@ -18,11 +18,15 @@ type SetRange<'a, Q, K, V> = crossbeam_skiplist::set::Range< >; /// An iterator over the entries in the WAL. -pub struct Iter<'a, K, V> { +pub struct Iter<'a, K: ?Sized, V: ?Sized> { iter: crossbeam_skiplist::set::Iter<'a, Pointer>, } -impl<'a, K, V> Iter<'a, K, V> { +impl<'a, K, V> Iter<'a, K, V> +where + K: ?Sized, + V: ?Sized, +{ #[inline] pub(super) fn new(iter: crossbeam_skiplist::set::Iter<'a, Pointer>) -> Self { Self { iter } @@ -31,8 +35,9 @@ impl<'a, K, V> Iter<'a, K, V> { impl<'a, K, V> Iterator for Iter<'a, K, V> where - K: Type + Ord, + K: Type + Ord + ?Sized, for<'b> K::Ref<'b>: KeyRef<'b, K>, + V: ?Sized, { type Item = GenericEntryRef<'a, K, V>; @@ -49,8 +54,9 @@ where impl DoubleEndedIterator for Iter<'_, K, V> where - K: Type + Ord, + K: Type + Ord + ?Sized, for<'b> K::Ref<'b>: KeyRef<'b, K>, + V: ?Sized, { #[inline] fn next_back(&mut self) -> Option { @@ -61,8 +67,9 @@ where /// An iterator over a subset of the entries in the WAL. pub struct RefRange<'a, Q, K, V> where - K: Type + Ord, + K: Type + Ord + ?Sized, for<'b> K::Ref<'b>: KeyRef<'b, K>, + V: ?Sized, Q: Ord + ?Sized + Comparable>, { iter: SetRefRange<'a, Q, K, V>, @@ -70,8 +77,9 @@ where impl<'a, Q, K, V> RefRange<'a, Q, K, V> where - K: Type + Ord, + K: Type + Ord + ?Sized, for<'b> K::Ref<'b>: KeyRef<'b, K>, + V: ?Sized, Q: Ord + ?Sized + Comparable>, { #[inline] @@ -82,9 +90,10 @@ where impl<'a, Q, K, V> Iterator for RefRange<'a, Q, K, V> where - K: Type + Ord, + K: Type + Ord + ?Sized, for<'b> K::Ref<'b>: KeyRef<'b, K>, Q: Ord + ?Sized + Comparable>, + V: ?Sized, { type Item = GenericEntryRef<'a, K, V>; @@ -96,8 +105,9 @@ where impl<'a, Q, K, V> DoubleEndedIterator for RefRange<'a, Q, K, V> where - K: Type + Ord, + K: Type + Ord + ?Sized, for<'b> K::Ref<'b>: KeyRef<'b, K>, + V: ?Sized, Q: Ord + ?Sized + Comparable>, { #[inline] @@ -109,8 +119,9 @@ where /// An iterator over a subset of the entries in the WAL. pub struct Range<'a, Q, K, V> where - K: Type + Ord, + K: Type + Ord + ?Sized, for<'b> K::Ref<'b>: KeyRef<'b, K>, + V: ?Sized, Q: Ord + ?Sized + Comparable> + Comparable, { iter: SetRange<'a, Q, K, V>, @@ -118,8 +129,9 @@ where impl<'a, Q, K, V> Range<'a, Q, K, V> where - K: Type + Ord, + K: Type + Ord + ?Sized, for<'b> K::Ref<'b>: KeyRef<'b, K>, + V: ?Sized, Q: Ord + ?Sized + Comparable> + Comparable, { #[inline] @@ -130,8 +142,9 @@ where impl<'a, Q, K, V> Iterator for Range<'a, Q, K, V> where - K: Type + Ord, + K: Type + Ord + ?Sized, for<'b> K::Ref<'b>: KeyRef<'b, K>, + V: ?Sized, Q: Ord + ?Sized + Comparable> + Comparable, { type Item = GenericEntryRef<'a, K, V>; @@ -144,8 +157,9 @@ where impl<'a, Q, K, V> DoubleEndedIterator for Range<'a, Q, K, V> where - K: Type + Ord, + K: Type + Ord + ?Sized, for<'b> K::Ref<'b>: KeyRef<'b, K>, + V: ?Sized, Q: Ord + ?Sized + Comparable> + Comparable, { #[inline] diff --git a/src/swmr/generic/reader.rs b/src/swmr/generic/reader.rs index 8e385bb..7ef7d23 100644 --- a/src/swmr/generic/reader.rs +++ b/src/swmr/generic/reader.rs @@ -9,15 +9,23 @@ use super::{ }; /// A read-only view of a generic single-writer, multi-reader WAL. -pub struct GenericWalReader(Arc>); +pub struct GenericWalReader(Arc>); -impl Clone for GenericWalReader { +impl Clone for GenericWalReader +where + K: ?Sized, + V: ?Sized, +{ fn clone(&self) -> Self { Self(self.0.clone()) } } -impl GenericWalReader { +impl GenericWalReader +where + K: ?Sized, + V: ?Sized, +{ pub(super) fn new(wal: Arc>) -> Self { Self(wal) } @@ -57,8 +65,9 @@ impl GenericWalReader { impl GenericWalReader where - K: Type + Ord, + K: Type + Ord + ?Sized, for<'a> K::Ref<'a>: KeyRef<'a, K>, + V: ?Sized, { /// Returns the first key-value pair in the map. The key in this pair is the minimum key in the wal. #[inline] @@ -107,9 +116,9 @@ where impl GenericWalReader where - K: Type + Ord, + K: Type + Ord + ?Sized, for<'a> K::Ref<'a>: KeyRef<'a, K>, - V: Type, + V: Type + ?Sized, { /// Returns `true` if the key exists in the WAL. #[inline] diff --git a/src/swmr/generic/tests/get.rs b/src/swmr/generic/tests/get.rs index b005a59..4a0db16 100644 --- a/src/swmr/generic/tests/get.rs +++ b/src/swmr/generic/tests/get.rs @@ -194,7 +194,7 @@ fn get_or_insert_with(wal: &mut GenericOrderWal) { let p = Person::random(); let v = format!("My name is {}", p.name); wal - .get_or_insert_with(&p, || v.clone().into()) + .get_or_insert_with(&p, || (&v).into()) .unwrap_right() .unwrap(); (p, v) @@ -208,7 +208,7 @@ fn get_or_insert_with(wal: &mut GenericOrderWal) { assert!(wal.contains_key_by_ref(&p.as_ref())); assert_eq!( wal - .get_or_insert_with(p, || format!("Hello! {}!", p.name).into()) + .get_or_insert_with(p, || (&format!("Hello! {}!", p.name)).into()) .unwrap_left() .value(), pv @@ -419,7 +419,7 @@ fn get_by_bytes_or_insert_with(wal: &mut GenericOrderWal) { let v = format!("My name is {}", p.name); unsafe { wal - .get_or_insert_with(Generic::from_slice(pvec.as_ref()), || v.clone().into()) + .get_or_insert_with(Generic::from_slice(pvec.as_ref()), || v.clone()) .unwrap_right() .unwrap(); } @@ -435,8 +435,7 @@ fn get_by_bytes_or_insert_with(wal: &mut GenericOrderWal) { unsafe { assert_eq!( wal - .get_or_insert_with(Generic::from_slice(pvec), || format!("Hello! {}!", p.name) - .into()) + .get_or_insert_with(Generic::from_slice(pvec), || format!("Hello! {}!", p.name)) .unwrap_left() .value(), pv diff --git a/src/swmr/generic/tests/insert.rs b/src/swmr/generic/tests/insert.rs index e7c611a..0f9b21a 100644 --- a/src/swmr/generic/tests/insert.rs +++ b/src/swmr/generic/tests/insert.rs @@ -476,7 +476,7 @@ fn concurrent_one_key(mut w: GenericOrderWal) { }) }); - w.insert(1, 1u32.to_le_bytes()).unwrap(); + w.insert(&1, &1u32.to_le_bytes()).unwrap(); for handle in handles { handle.join().unwrap(); @@ -539,9 +539,7 @@ fn insert_batch( .collect::>(); for (person, val) in output.iter() { - if person.id % 3 == 0 { - batch.push(GenericEntry::new(person.clone(), val.clone())); - } else if person.id % 3 == 1 { + if person.id % 2 == 0 { batch.push(GenericEntry::new(person, val)); } else { unsafe { @@ -554,10 +552,10 @@ fn insert_batch( } let rp1 = Person::random(); - wal.insert(&rp1, "rp1".to_string()).unwrap(); + wal.insert(&rp1, &"rp1".to_string()).unwrap(); wal.insert_batch(&mut batch).unwrap(); let rp2 = Person::random(); - wal.insert(&rp2, "rp2".to_string()).unwrap(); + wal.insert(&rp2, &"rp2".to_string()).unwrap(); for (p, val) in output.iter() { assert_eq!(wal.get(p).unwrap().value(), val); @@ -579,22 +577,12 @@ fn insert_batch( #[test] fn test_insert_batch_inmemory() { - insert_batch( - &mut GenericBuilder::new() - .with_capacity(MB) - .alloc::() - .unwrap(), - ); + insert_batch(&mut GenericBuilder::new().with_capacity(MB).alloc().unwrap()); } #[test] fn test_insert_batch_map_anon() { - insert_batch( - &mut GenericBuilder::new() - .with_capacity(MB) - .map_anon::() - .unwrap(), - ); + insert_batch(&mut GenericBuilder::new().with_capacity(MB).map_anon().unwrap()); } #[test] @@ -612,7 +600,7 @@ fn test_insert_batch_map_file() { .with_create_new(true) .with_read(true) .with_write(true) - .map_mut::(&path) + .map_mut(&path) .unwrap() }; diff --git a/src/wal/type.rs b/src/wal/type.rs index 7c2b0b6..8b13789 100644 --- a/src/wal/type.rs +++ b/src/wal/type.rs @@ -1,30 +1 @@ -use among::Among; -pub use dbutils::traits::{KeyRef, Type, TypeRef}; -pub(crate) trait InsertAmongExt { - fn encoded_len(&self) -> usize; - fn encode(&self, buf: &mut [u8]) -> Result; -} - -impl InsertAmongExt for Among { - #[inline] - fn encoded_len(&self) -> usize { - match self { - Among::Left(t) => t.encoded_len(), - Among::Middle(t) => t.encoded_len(), - Among::Right(t) => t.len(), - } - } - - #[inline] - fn encode(&self, buf: &mut [u8]) -> Result { - match self { - Among::Left(t) => t.encode(buf), - Among::Middle(t) => t.encode(buf), - Among::Right(t) => { - buf.copy_from_slice(t); - Ok(buf.len()) - } - } - } -} From 34f8235aeb9388380393ceec1d45135de33f47bd Mon Sep 17 00:00:00 2001 From: al8n Date: Mon, 30 Sep 2024 16:32:33 +0800 Subject: [PATCH 2/3] Use `flush_header_and_range` instead of `flush_range` --- src/builder.rs | 14 +++++++------- src/options.rs | 18 +++++++++--------- src/swmr/generic.rs | 8 ++++---- src/swmr/generic/builder.rs | 14 +++++++------- src/wal/sealed.rs | 4 ++-- 5 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 38206f4..5bd32db 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -248,11 +248,11 @@ impl Builder { /// use orderwal::Builder; /// /// let options = Builder::new(); - /// assert_eq!(options.sync_on_write(), true); + /// assert_eq!(options.sync(), true); /// ``` #[inline] - pub const fn sync_on_write(&self) -> bool { - self.opts.sync_on_write() + pub const fn sync(&self) -> bool { + self.opts.sync() } /// Sets the capacity of the WAL. @@ -316,12 +316,12 @@ impl Builder { /// ```rust /// use orderwal::Builder; /// - /// let options = Builder::new().with_sync_on_write(false); - /// assert_eq!(options.sync_on_write(), false); + /// let options = Builder::new().with_sync(false); + /// assert_eq!(options.sync(), false); /// ``` #[inline] - pub const fn with_sync_on_write(mut self, sync: bool) -> Self { - self.opts = self.opts.with_sync_on_write(sync); + pub const fn with_sync(mut self, sync: bool) -> Self { + self.opts = self.opts.with_sync(sync); self } diff --git a/src/options.rs b/src/options.rs index 97ee7c6..6ec2146 100644 --- a/src/options.rs +++ b/src/options.rs @@ -3,7 +3,7 @@ pub struct Options { maximum_key_size: u32, maximum_value_size: u32, - sync_on_write: bool, + sync: bool, magic_version: u16, cap: Option, reserved: u32, @@ -46,7 +46,7 @@ impl Options { Self { maximum_key_size: u16::MAX as u32, maximum_value_size: u32::MAX, - sync_on_write: true, + sync: true, magic_version: 0, huge: None, cap: None, @@ -229,11 +229,11 @@ impl Options { /// use orderwal::Options; /// /// let options = Options::new(); - /// assert_eq!(options.sync_on_write(), true); + /// assert_eq!(options.sync(), true); /// ``` #[inline] - pub const fn sync_on_write(&self) -> bool { - self.sync_on_write + pub const fn sync(&self) -> bool { + self.sync } /// Sets the capacity of the WAL. @@ -297,12 +297,12 @@ impl Options { /// ```rust /// use orderwal::Options; /// - /// let options = Options::new().with_sync_on_write(false); - /// assert_eq!(options.sync_on_write(), false); + /// let options = Options::new().with_sync(false); + /// assert_eq!(options.sync(), false); /// ``` #[inline] - pub const fn with_sync_on_write(mut self, sync: bool) -> Self { - self.sync_on_write = sync; + pub const fn with_sync(mut self, sync: bool) -> Self { + self.sync = sync; self } diff --git a/src/swmr/generic.rs b/src/swmr/generic.rs index ac29404..0bdf641 100644 --- a/src/swmr/generic.rs +++ b/src/swmr/generic.rs @@ -835,9 +835,9 @@ where buf[0] = committed_flag.bits; let buf_cap = buf.capacity(); - if self.core.opts.sync_on_write() && allocator.is_ondisk() { + if self.core.opts.sync() && allocator.is_ondisk() { allocator - .flush_range(buf.offset(), buf_cap) + .flush_header_and_range(buf.offset(), buf_cap) .map_err(|e| Among::Right(e.into()))?; } buf.detach(); @@ -903,11 +903,11 @@ where // commit the entry buf[0] |= Flags::COMMITTED.bits(); - if self.core.opts.sync_on_write() && self.core.arena.is_ondisk() { + if self.core.opts.sync() && self.core.arena.is_ondisk() { self .core .arena - .flush_range(buf.offset(), elen as usize) + .flush_header_and_range(buf.offset(), elen as usize) .map_err(|e| Among::Right(e.into()))?; } buf.detach(); diff --git a/src/swmr/generic/builder.rs b/src/swmr/generic/builder.rs index 157d303..269b5c5 100644 --- a/src/swmr/generic/builder.rs +++ b/src/swmr/generic/builder.rs @@ -182,11 +182,11 @@ impl GenericBuilder { /// use orderwal::swmr::GenericBuilder; /// /// let options = GenericBuilder::new(); - /// assert_eq!(options.sync_on_write(), true); + /// assert_eq!(options.sync(), true); /// ``` #[inline] - pub const fn sync_on_write(&self) -> bool { - self.opts.sync_on_write() + pub const fn sync(&self) -> bool { + self.opts.sync() } /// Sets the capacity of the WAL. @@ -250,12 +250,12 @@ impl GenericBuilder { /// ```rust /// use orderwal::swmr::GenericBuilder; /// - /// let options = GenericBuilder::new().with_sync_on_write(false); - /// assert_eq!(options.sync_on_write(), false); + /// let options = GenericBuilder::new().with_sync(false); + /// assert_eq!(options.sync(), false); /// ``` #[inline] - pub const fn with_sync_on_write(mut self, sync: bool) -> Self { - self.opts = self.opts.with_sync_on_write(sync); + pub const fn with_sync(mut self, sync: bool) -> Self { + self.opts = self.opts.with_sync(sync); self } diff --git a/src/wal/sealed.rs b/src/wal/sealed.rs index c67b330..9d605f2 100644 --- a/src/wal/sealed.rs +++ b/src/wal/sealed.rs @@ -350,7 +350,7 @@ pub trait Sealed: Constructor { // commit the entry buf[0] |= Flags::COMMITTED.bits(); - if self.options().sync_on_write() && is_ondisk { + if self.options().sync() && is_ondisk { allocator .flush_header_and_range(buf.offset(), elen as usize) .map_err(|e| Among::Right(e.into()))?; @@ -395,7 +395,7 @@ trait SealedExt: Sealed { buf[0] = committed_flag.bits; let buf_cap = buf.capacity(); - if self.options().sync_on_write() && allocator.is_ondisk() { + if self.options().sync() && allocator.is_ondisk() { allocator.flush_header_and_range(buf.offset(), buf_cap)?; } buf.detach(); From 8f4ff1de28b49b1cad535b642228aadec9777098 Mon Sep 17 00:00:00 2001 From: al8n Date: Mon, 30 Sep 2024 16:47:36 +0800 Subject: [PATCH 3/3] Update `CHANGELOG.md` --- CHANGELOG.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 798dae4..4290633 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ -# 0.1.0 (Sep 14th, 2024) +# Rleases -- Publish version `0.1.0` +## 0.4.0 (Sep 30th, 2024) FEATURES + +- Support `K: ?Sized` and `V: ?Sized` for `GenericOrderWal`. +- Use `flush_header_and_range` instead of `flush_range` when insertion. + +## 0.1.0 (Sep 14th, 2024) + +- Publish version `0.1.0`