Skip to content
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

kvdb-rocksdb: update rocksdb to 0.14 #379

Merged
merged 12 commits into from
Apr 29, 2020
1 change: 1 addition & 0 deletions kvdb-rocksdb/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ The format is based on [Keep a Changelog].
[Keep a Changelog]: http://keepachangelog.com/en/1.0.0/

## [Unreleased]
- Updated RocksDB to 6.7.3. [#379](https://github.com/paritytech/parity-common/pull/379)
### Breaking
- Updated to the new `kvdb` interface. [#313](https://github.com/paritytech/parity-common/pull/313)
- Rename and optimize prefix iteration. [#365](https://github.com/paritytech/parity-common/pull/365)
Expand Down
2 changes: 1 addition & 1 deletion kvdb-rocksdb/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ log = "0.4.8"
num_cpus = "1.10.1"
parking_lot = "0.10.0"
regex = "1.3.1"
rocksdb = { version = "0.13", features = ["snappy"], default-features = false }
rocksdb = { version = "0.14", features = ["snappy"], default-features = false }
owning_ref = "0.4.0"
parity-util-mem = { path = "../parity-util-mem", version = "0.6", default-features = false, features = ["std", "smallvec"] }

Expand Down
43 changes: 14 additions & 29 deletions kvdb-rocksdb/src/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,6 @@ pub type KeyValuePair = (Box<[u8]>, Box<[u8]>);
/// Iterator with built-in synchronization.
pub struct ReadGuardedIterator<'a, I, T> {
inner: OwningHandle<UnsafeStableAddress<'a, Option<T>>, DerefWrapper<Option<I>>>,
// We store the upper bound here
// to make sure it lives at least as long as the iterator.
// See https://github.com/rust-rocksdb/rust-rocksdb/pull/309.
// TODO: remove this once https://github.com/rust-rocksdb/rust-rocksdb/pull/377
// is merged and released.
#[allow(dead_code)]
upper_bound_prefix: Option<Box<[u8]>>,
}

// We can't implement `StableAddress` for a `RwLockReadGuard`
Expand Down Expand Up @@ -80,15 +73,15 @@ impl<'a, I: Iterator, T> Iterator for ReadGuardedIterator<'a, I, T> {
pub trait IterationHandler {
type Iterator: Iterator<Item = KeyValuePair>;

/// Create an `Iterator` over a `ColumnFamily` corresponding to the passed index. Takes a
/// reference to a `ReadOptions` to allow configuration of the new iterator (see
/// Create an `Iterator` over a `ColumnFamily` corresponding to the passed index. Takes
/// `ReadOptions` to allow configuration of the new iterator (see
/// https://github.com/facebook/rocksdb/blob/master/include/rocksdb/options.h#L1169).
fn iter(&self, col: u32, read_opts: &ReadOptions) -> Self::Iterator;
/// Create an `Iterator` over a `ColumnFamily` corresponding to the passed index. Takes a
/// reference to a `ReadOptions` to allow configuration of the new iterator (see
fn iter(&self, col: u32, read_opts: ReadOptions) -> Self::Iterator;
/// Create an `Iterator` over a `ColumnFamily` corresponding to the passed index. Takes
/// `ReadOptions` to allow configuration of the new iterator (see
/// https://github.com/facebook/rocksdb/blob/master/include/rocksdb/options.h#L1169).
/// The `Iterator` iterates over keys which start with the provided `prefix`.
fn iter_with_prefix(&self, col: u32, prefix: &[u8], read_opts: &ReadOptions) -> Self::Iterator;
fn iter_with_prefix(&self, col: u32, prefix: &[u8], read_opts: ReadOptions) -> Self::Iterator;
}

impl<'a, T> ReadGuardedIterator<'a, <&'a T as IterationHandler>::Iterator, T>
Expand All @@ -97,8 +90,8 @@ where
{
/// Creates a new `ReadGuardedIterator` that maps `RwLock<RocksDB>` to `RwLock<DBIterator>`,
/// where `DBIterator` iterates over all keys.
pub fn new(read_lock: RwLockReadGuard<'a, Option<T>>, col: u32, read_opts: &ReadOptions) -> Self {
Self { inner: Self::new_inner(read_lock, |db| db.iter(col, read_opts)), upper_bound_prefix: None }
pub fn new(read_lock: RwLockReadGuard<'a, Option<T>>, col: u32, read_opts: ReadOptions) -> Self {
Self { inner: Self::new_inner(read_lock, |db| db.iter(col, read_opts)) }
}

/// Creates a new `ReadGuardedIterator` that maps `RwLock<RocksDB>` to `RwLock<DBIterator>`,
Expand All @@ -107,13 +100,9 @@ where
read_lock: RwLockReadGuard<'a, Option<T>>,
col: u32,
prefix: &[u8],
upper_bound: Option<Box<[u8]>>,
read_opts: &ReadOptions,
read_opts: ReadOptions,
) -> Self {
Self {
inner: Self::new_inner(read_lock, |db| db.iter_with_prefix(col, prefix, read_opts)),
upper_bound_prefix: upper_bound,
}
Self { inner: Self::new_inner(read_lock, |db| db.iter_with_prefix(col, prefix, read_opts)) }
}

fn new_inner(
Expand All @@ -130,15 +119,11 @@ where
impl<'a> IterationHandler for &'a DBAndColumns {
type Iterator = DBIterator<'a>;

fn iter(&self, col: u32, read_opts: &ReadOptions) -> Self::Iterator {
self.db
.iterator_cf_opt(self.cf(col as usize), read_opts, IteratorMode::Start)
.expect("iterator params are valid; qed")
fn iter(&self, col: u32, read_opts: ReadOptions) -> Self::Iterator {
self.db.iterator_cf_opt(self.cf(col as usize), read_opts, IteratorMode::Start)
}

fn iter_with_prefix(&self, col: u32, prefix: &[u8], read_opts: &ReadOptions) -> Self::Iterator {
self.db
.iterator_cf_opt(self.cf(col as usize), read_opts, IteratorMode::From(prefix, Direction::Forward))
.expect("iterator params are valid; qed")
fn iter_with_prefix(&self, col: u32, prefix: &[u8], read_opts: ReadOptions) -> Self::Iterator {
self.db.iterator_cf_opt(self.cf(col as usize), read_opts, IteratorMode::From(prefix, Direction::Forward))
}
}
37 changes: 18 additions & 19 deletions kvdb-rocksdb/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,12 @@ fn generate_options(config: &DatabaseConfig) -> Options {
opts
}

fn generate_read_options() -> ReadOptions {
let mut read_opts = ReadOptions::default();
read_opts.set_verify_checksums(false);
read_opts
}

/// Generate the block based options for RocksDB, based on the given `DatabaseConfig`.
fn generate_block_based_options(config: &DatabaseConfig) -> BlockBasedOptions {
let mut block_opts = BlockBasedOptions::default();
Expand Down Expand Up @@ -360,8 +366,7 @@ impl Database {
let column_names: Vec<_> = (0..config.columns).map(|c| format!("col{}", c)).collect();

let write_opts = WriteOptions::default();
let mut read_opts = ReadOptions::default();
read_opts.set_verify_checksums(false);
let read_opts = generate_read_options();

let cf_descriptors: Vec<_> = (0..config.columns)
.map(|i| ColumnFamilyDescriptor::new(&column_names[i as usize], config.column_config(&block_opts, i)))
Expand Down Expand Up @@ -436,22 +441,22 @@ impl Database {
match op {
DBOp::Insert { col: _, key, value } => {
stats_total_bytes += key.len() + value.len();
batch.put_cf(cf, &key, &value).map_err(other_io_err)?
batch.put_cf(cf, &key, &value);
}
DBOp::Delete { col: _, key } => {
// We count deletes as writes.
stats_total_bytes += key.len();
batch.delete_cf(cf, &key).map_err(other_io_err)?
batch.delete_cf(cf, &key);
}
DBOp::DeletePrefix { col, prefix } => {
let end_prefix = kvdb::end_prefix(&prefix[..]);
let no_end = end_prefix.is_none();
let end_range = end_prefix.unwrap_or_else(|| vec![u8::max_value(); 16]);
batch.delete_range_cf(cf, &prefix[..], &end_range[..]).map_err(other_io_err)?;
batch.delete_range_cf(cf, &prefix[..], &end_range[..]);
if no_end {
let prefix = if prefix.len() > end_range.len() { &prefix[..] } else { &end_range[..] };
for (key, _) in self.iter_with_prefix(col, prefix) {
batch.delete_cf(cf, &key[..]).map_err(other_io_err)?;
batch.delete_cf(cf, &key[..]);
}
}
}
Expand Down Expand Up @@ -502,7 +507,8 @@ impl Database {
pub fn iter<'a>(&'a self, col: u32) -> impl Iterator<Item = KeyValuePair> + 'a {
let read_lock = self.db.read();
let optional = if read_lock.is_some() {
let guarded = iter::ReadGuardedIterator::new(read_lock, col, &self.read_opts);
let read_opts = generate_read_options();
let guarded = iter::ReadGuardedIterator::new(read_lock, col, read_opts);
Some(guarded)
} else {
None
Expand All @@ -516,19 +522,12 @@ impl Database {
fn iter_with_prefix<'a>(&'a self, col: u32, prefix: &'a [u8]) -> impl Iterator<Item = iter::KeyValuePair> + 'a {
let read_lock = self.db.read();
let optional = if read_lock.is_some() {
let mut read_opts = ReadOptions::default();
read_opts.set_verify_checksums(false);
let mut read_opts = generate_read_options();
// rocksdb doesn't work with an empty upper bound
let end_prefix = kvdb::end_prefix(prefix).map(|end_prefix| {
let end_prefix = end_prefix.into_boxed_slice();
// SAFETY: the end_prefix lives as long as the iterator
// See `ReadGuardedIterator` definition for more details.
unsafe {
read_opts.set_iterate_upper_bound(&end_prefix);
}
end_prefix
});
let guarded = iter::ReadGuardedIterator::new_with_prefix(read_lock, col, prefix, end_prefix, &read_opts);
if let Some(end_prefix) = kvdb::end_prefix(prefix) {
read_opts.set_iterate_upper_bound(end_prefix);
}
let guarded = iter::ReadGuardedIterator::new_with_prefix(read_lock, col, prefix, read_opts);
Some(guarded)
} else {
None
Expand Down