-
Notifications
You must be signed in to change notification settings - Fork 245
[kvdb-rocksdb] switch to upstream #257
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
Changes from 21 commits
215a28d
2c0468f
d445cde
2d42479
47a6e22
81bce7c
71b2af0
e5cd5cb
c7640d1
fb208ad
8a2442a
fa16fb5
3b31e4f
f595233
df8d614
a479485
1e1a865
3153cca
ed372f4
28de430
d978759
9adccb8
13b029c
c88186f
03a2ba0
407c604
1739d8a
8c658ba
87d0aec
3a071af
cd343cc
7eeaf7b
bd5abf1
f23574f
8986947
6a64e36
15af306
0217438
e0d59e5
c4b5413
adde7df
b40b416
38876cf
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 |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| // Copyright 2019 Parity Technologies (UK) Ltd. | ||
| // This file is part of Parity. | ||
|
|
||
| // Parity is free software: you can redistribute it and/or modify | ||
| // it under the terms of the GNU General Public License as published by | ||
| // the Free Software Foundation, either version 3 of the License, or | ||
| // (at your option) any later version. | ||
|
|
||
| // Parity is distributed in the hope that it will be useful, | ||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| // GNU General Public License for more details. | ||
|
|
||
| // You should have received a copy of the GNU General Public License | ||
| // along with Parity. If not, see <http://www.gnu.org/licenses/>. | ||
|
|
||
| //! This module contains an implementation of a RocksDB iterator | ||
| //! wrapped inside a `RwLock`. Since `RwLock` "owns" the inner data, | ||
| //! we're using `owning_ref` to work around the borrowing rules of Rust. | ||
|
|
||
| use crate::DBAndColumns; | ||
| use owning_ref::{OwningHandle, StableAddress}; | ||
| use parking_lot::RwLockReadGuard; | ||
| use rocksdb::{DBIterator, Direction, IteratorMode}; | ||
| use std::ops::{Deref, DerefMut}; | ||
|
|
||
| pub type KeyValuePair = (Box<[u8]>, Box<[u8]>); | ||
|
|
||
| pub struct ReadGuardedIterator<'a, I, T> { | ||
| inner: OwningHandle<UnsafeStableAddress<'a, Option<T>>, DerefWrapper<Option<I>>>, | ||
| } | ||
|
|
||
| // We can't implement `StableAddress` for a `RwLockReadGuard` | ||
| // directly due to orphan rules. | ||
| #[repr(transparent)] | ||
| struct UnsafeStableAddress<'a, T>(RwLockReadGuard<'a, T>); | ||
|
|
||
| impl<'a, T> Deref for UnsafeStableAddress<'a, T> { | ||
| type Target = T; | ||
| fn deref(&self) -> &Self::Target { | ||
| self.0.deref() | ||
| } | ||
| } | ||
|
|
||
| // RwLockReadGuard dereferences to a stable address; qed | ||
| unsafe impl<'a, T> StableAddress for UnsafeStableAddress<'a, T> {} | ||
|
|
||
| struct DerefWrapper<T>(T); | ||
|
|
||
| impl<T> Deref for DerefWrapper<T> { | ||
| type Target = T; | ||
| fn deref(&self) -> &Self::Target { | ||
| &self.0 | ||
| } | ||
| } | ||
|
|
||
| impl<T> DerefMut for DerefWrapper<T> { | ||
| fn deref_mut(&mut self) -> &mut Self::Target { | ||
| &mut self.0 | ||
| } | ||
| } | ||
|
|
||
| impl<'a, I: Iterator, T> Iterator for ReadGuardedIterator<'a, I, T> { | ||
| type Item = I::Item; | ||
|
|
||
| fn next(&mut self) -> Option<Self::Item> { | ||
| self.inner.deref_mut().as_mut().and_then(|iter| iter.next()) | ||
| } | ||
| } | ||
|
|
||
| pub trait IterationHandler { | ||
|
Member
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 documentation would be nice :)
Contributor
Author
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 trait was originally added in #120, we can remove it and all generics here, but it's good to have if we will consider merging something similar to #120. Another idea I had is replace |
||
| type Iterator: Iterator<Item = KeyValuePair>; | ||
|
|
||
| fn iter(&self, col: Option<u32>) -> Self::Iterator; | ||
| fn iter_from_prefix(&self, col: Option<u32>, prefix: &[u8]) -> Self::Iterator; | ||
| } | ||
|
|
||
| impl<'a, T> ReadGuardedIterator<'a, <&'a T as IterationHandler>::Iterator, T> | ||
| where | ||
| &'a T: IterationHandler, | ||
| { | ||
| pub fn new(read_lock: RwLockReadGuard<'a, Option<T>>, col: Option<u32>) -> Self { | ||
| Self { | ||
| inner: OwningHandle::new_with_fn(UnsafeStableAddress(read_lock), move |rlock| { | ||
| let rlock = unsafe { rlock.as_ref().expect("initialized as non-null; qed") }; | ||
| DerefWrapper(rlock.as_ref().map(|db| db.iter(col))) | ||
| }), | ||
| } | ||
| } | ||
|
|
||
| pub fn new_from_prefix(read_lock: RwLockReadGuard<'a, Option<T>>, col: Option<u32>, prefix: &[u8]) -> Self { | ||
| Self { | ||
| inner: OwningHandle::new_with_fn(UnsafeStableAddress(read_lock), move |rlock| { | ||
|
ordian marked this conversation as resolved.
Outdated
|
||
| let rlock = unsafe { rlock.as_ref().expect("initialized as non-null; qed") }; | ||
|
ordian marked this conversation as resolved.
Outdated
|
||
| DerefWrapper(rlock.as_ref().map(|db| db.iter_from_prefix(col, prefix))) | ||
| }), | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl<'a> IterationHandler for &'a DBAndColumns { | ||
| type Iterator = DBIterator<'a>; | ||
|
|
||
| fn iter(&self, col: Option<u32>) -> Self::Iterator { | ||
| col.map_or_else( | ||
| || self.db.iterator(IteratorMode::Start), | ||
| |c| { | ||
| self.db | ||
| .iterator_cf(self.get_cf(c as usize), IteratorMode::Start) | ||
| .expect("iterator params are valid; qed") | ||
| }, | ||
| ) | ||
| } | ||
|
|
||
| fn iter_from_prefix(&self, col: Option<u32>, prefix: &[u8]) -> Self::Iterator { | ||
| col.map_or_else( | ||
| || self.db.iterator(IteratorMode::From(prefix, Direction::Forward)), | ||
| |c| { | ||
| self.db | ||
| .iterator_cf(self.get_cf(c as usize), IteratorMode::From(prefix, Direction::Forward)) | ||
| .expect("iterator params are valid; qed") | ||
| }, | ||
| ) | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.