-
Notifications
You must be signed in to change notification settings - Fork 42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
STORAGE: KVRead::iterate #919
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,20 +2,23 @@ | |
// SPDX-License-Identifier: Apache-2.0, MIT | ||
use std::{ | ||
hash::Hash, | ||
marker::PhantomData, | ||
mem, | ||
sync::{Arc, Mutex, MutexGuard}, | ||
thread, | ||
}; | ||
|
||
use crate::{ | ||
Decode, Encode, KVRead, KVReadable, KVResult, KVStore, KVTransaction, KVWritable, KVWrite, | ||
Decode, Encode, KVError, KVRead, KVReadable, KVResult, KVStore, KVTransaction, KVWritable, | ||
KVWrite, | ||
}; | ||
|
||
/// Read-only mode. | ||
pub struct Read; | ||
/// Read-write mode. | ||
pub struct Write; | ||
|
||
/// Immutable data multimap. | ||
type IDataMap<S> = im::HashMap< | ||
<S as KVStore>::Namespace, | ||
im::HashMap<<S as KVStore>::Repr, Arc<<S as KVStore>::Repr>>, | ||
|
@@ -152,6 +155,23 @@ where | |
} | ||
Ok(None) | ||
} | ||
|
||
fn iterate<K, V>(&self, ns: &S::Namespace) -> impl Iterator<Item = KVResult<(K, V)>> | ||
where | ||
S: Decode<K> + Decode<V>, | ||
<S as KVStore>::Repr: Ord + 'static, | ||
K: 'static, | ||
V: 'static, | ||
{ | ||
if let Some(m) = self.data.get(ns) { | ||
let mut items = m.iter().map(|(k, v)| (k, v.as_ref())).collect::<Vec<_>>(); | ||
items.sort_by(|a, b| a.0.cmp(b.0)); | ||
|
||
KVIter::<S, K, V>::new(items) | ||
} else { | ||
KVIter::empty() | ||
} | ||
} | ||
} | ||
|
||
impl<'a, S: KVStore> KVWrite<S> for Transaction<'a, S, Write> | ||
|
@@ -183,6 +203,48 @@ where | |
} | ||
} | ||
|
||
struct KVIter<'a, S: KVStore, K, V> { | ||
items: Vec<(&'a S::Repr, &'a S::Repr)>, | ||
next: usize, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What I wanted to express here is the next index that will be returned from the |
||
phantom_v: PhantomData<V>, | ||
phantom_k: PhantomData<K>, | ||
} | ||
|
||
impl<'a, S, K, V> KVIter<'a, S, K, V> | ||
where | ||
S: KVStore, | ||
{ | ||
pub fn new(items: Vec<(&'a S::Repr, &'a S::Repr)>) -> Self { | ||
KVIter { | ||
items, | ||
next: 0, | ||
phantom_v: PhantomData, | ||
phantom_k: PhantomData, | ||
} | ||
} | ||
|
||
pub fn empty() -> Self { | ||
Self::new(vec![]) | ||
} | ||
} | ||
|
||
impl<'a, S, K, V> Iterator for KVIter<'a, S, K, V> | ||
where | ||
S: KVStore + Decode<K> + Decode<V>, | ||
{ | ||
type Item = Result<(K, V), KVError>; | ||
|
||
fn next(&mut self) -> Option<Self::Item> { | ||
if let Some((k, v)) = self.items.get(self.next) { | ||
self.next += 1; | ||
let kv = S::from_repr(k).and_then(|k| S::from_repr(v).map(|v| (k, v))); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
Some(kv) | ||
} else { | ||
None | ||
} | ||
} | ||
} | ||
|
||
#[cfg(all(feature = "inmem", test))] | ||
mod tests { | ||
use std::borrow::Cow; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -66,6 +66,16 @@ pub trait KVRead<S: KVStore> { | |
fn get<K, V>(&self, ns: &S::Namespace, k: &K) -> KVResult<Option<V>> | ||
where | ||
S: Encode<K> + Decode<V>; | ||
|
||
/// Iterate items in the namespace ordered by their representation. | ||
/// | ||
/// TODO: Add parameters for iteration direction and bounds. | ||
fn iterate<K, V>(&self, ns: &S::Namespace) -> impl Iterator<Item = KVResult<(K, V)>> | ||
where | ||
K: 'static, | ||
V: 'static, | ||
S: Decode<K> + Decode<V>, | ||
<S as KVStore>::Repr: Ord + 'static; | ||
} | ||
|
||
/// Operations available on a write transaction. | ||
|
@@ -156,4 +166,18 @@ where | |
pub fn delete(&self, kv: &mut impl KVWrite<S>, k: &K) -> KVResult<()> { | ||
kv.delete(&self.ns, k) | ||
} | ||
|
||
pub fn iterate<'a, 'b>( | ||
&'a self, | ||
kv: &'b impl KVRead<S>, | ||
) -> impl Iterator<Item = KVResult<(K, V)>> + 'b | ||
where | ||
S::Repr: Ord + 'static, | ||
S: Decode<K>, | ||
K: 'static, | ||
V: 'static, | ||
'a: 'b, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I recall seeing this before, but its one of these lifetimes I never remember how is written There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is also from the compiler. I didn't think adding this method on |
||
{ | ||
kv.iterate::<K, V>(&self.ns) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to be static so K/V is guaranteed to outlive the iterator?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I can explain, but the compiler insisted that the iterator can outlive these types 🤷