From ad2c15ac7c963bfab84c8cdb1070a3040d855481 Mon Sep 17 00:00:00 2001 From: Tyler Neely Date: Sun, 13 Nov 2016 19:33:57 +0100 Subject: [PATCH] prep for 0.5 release --- .gitmodules | 8 +- Cargo.toml | 6 +- README.md | 167 +------------ {rocksdb-sys => rocksdb_sys}/.gitignore | 0 {rocksdb-sys => rocksdb_sys}/Cargo.toml | 4 +- {rocksdb-sys => rocksdb_sys}/Makefile | 0 {rocksdb-sys => rocksdb_sys}/README.md | 0 {rocksdb-sys => rocksdb_sys}/build.rs | 0 {rocksdb-sys => rocksdb_sys}/build_version.cc | 0 {rocksdb-sys => rocksdb_sys}/build_version.h | 0 {rocksdb-sys => rocksdb_sys}/rocksdb | 0 .../rocksdb_lib_sources.txt | 0 {rocksdb-sys => rocksdb_sys}/snappy | 0 .../snappy-stubs-public.h | 0 {rocksdb-sys => rocksdb_sys}/src/lib.rs | 0 {rocksdb-sys => rocksdb_sys}/src/test.rs | 0 {rocksdb-sys => rocksdb_sys}/tests/ffi.rs | 0 src/lib.rs | 80 +++++- src/merge_operator.rs | 42 +++- src/rocksdb.rs | 233 ++++++++++-------- test/test_column_family.rs | 5 +- test/test_iterator.rs | 43 ++-- test/test_multithreaded.rs | 2 +- 23 files changed, 278 insertions(+), 312 deletions(-) rename {rocksdb-sys => rocksdb_sys}/.gitignore (100%) rename {rocksdb-sys => rocksdb_sys}/Cargo.toml (85%) rename {rocksdb-sys => rocksdb_sys}/Makefile (100%) rename {rocksdb-sys => rocksdb_sys}/README.md (100%) rename {rocksdb-sys => rocksdb_sys}/build.rs (100%) rename {rocksdb-sys => rocksdb_sys}/build_version.cc (100%) rename {rocksdb-sys => rocksdb_sys}/build_version.h (100%) rename {rocksdb-sys => rocksdb_sys}/rocksdb (100%) rename {rocksdb-sys => rocksdb_sys}/rocksdb_lib_sources.txt (100%) rename {rocksdb-sys => rocksdb_sys}/snappy (100%) rename {rocksdb-sys => rocksdb_sys}/snappy-stubs-public.h (100%) rename {rocksdb-sys => rocksdb_sys}/src/lib.rs (100%) rename {rocksdb-sys => rocksdb_sys}/src/test.rs (100%) rename {rocksdb-sys => rocksdb_sys}/tests/ffi.rs (100%) diff --git a/.gitmodules b/.gitmodules index 10d03de..37f2c45 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ -[submodule "rocksdb-sys/snappy"] - path = rocksdb-sys/snappy +[submodule "rocksdb_sys/snappy"] + path = rocksdb_sys/snappy url = https://github.com/google/snappy.git -[submodule "rocksdb-sys/rocksdb"] - path = rocksdb-sys/rocksdb +[submodule "rocksdb_sys/rocksdb"] + path = rocksdb_sys/rocksdb url = https://github.com/facebook/rocksdb.git diff --git a/Cargo.toml b/Cargo.toml index 74958f5..f905f36 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rocksdb" description = "Rust wrapper for Facebook's RocksDB embeddable database" -version = "0.4.1" +version = "0.5.0" authors = ["Tyler Neely ", "David Greenberg "] license = "Apache-2.0" keywords = ["database", "embedded", "LSM-tree", "persistence"] @@ -22,5 +22,5 @@ name = "test" path = "test/test.rs" [dependencies] -libc = "0.2.13" -rocksdb-sys = { path = "rocksdb-sys", version = "0.4.0" } +libc = "0.2" +rocksdb_sys = { path = "rocksdb-sys", version = "0.4.0" } diff --git a/README.md b/README.md index 7f013c2..6e7fdbf 100644 --- a/README.md +++ b/README.md @@ -3,174 +3,11 @@ rust-rocksdb [![Build Status](https://travis-ci.org/spacejam/rust-rocksdb.svg?branch=master)](https://travis-ci.org/spacejam/rust-rocksdb) [![crates.io](http://meritbadge.herokuapp.com/rocksdb)](https://crates.io/crates/rocksdb) -This library has been tested against RocksDB 3.13.1 on Linux and OS X. The 0.4.1 crate should work with the Rust 1.9 stable and nightly releases as of 7/1/16. - -### Status - - [x] basic open/put/get/delete/close - - [x] rustic merge operator - - [x] write batch (thanks @dgrnbrg!) - - [x] compaction filter, style - - [x] LRU cache - - [x] destroy/repair - - [x] iterator - - [x] comparator - - [x] snapshot - - [x] column family operations - - [ ] prefix seek - - [ ] slicetransform - - [x] windows support +[documentation](http://spacejam.github.io/docs/rocksdb/rocksdb/) Feedback and pull requests welcome! If a particular feature of RocksDB is important to you, please let me know by opening an issue, and I'll prioritize it. -### Running -###### Cargo.toml ```rust [dependencies] -rocksdb = "0.4.1" -``` -###### Code -```rust -extern crate rocksdb; -use rocksdb::{DB, Writable}; - -fn main() { - let mut db = DB::open_default("/path/for/rocksdb/storage").unwrap(); - db.put(b"my key", b"my value"); - match db.get(b"my key") { - Ok(Some(value)) => println!("retrieved value {}", value.to_utf8().unwrap()), - Ok(None) => println!("value not found"), - Err(e) => println!("operational problem encountered: {}", e), - } - - db.delete(b"my key"); -} -``` - -###### Making an atomic commit of several writes -```rust -extern crate rocksdb; -use rocksdb::{DB, WriteBatch, Writable}; - -fn main() { - // NB: db is automatically freed at end of lifetime - let mut db = DB::open_default("/path/for/rocksdb/storage").unwrap(); - { - let mut batch = WriteBatch::default(); // WriteBatch and db both have trait Writable - batch.put(b"my key", b"my value"); - batch.put(b"key2", b"value2"); - batch.put(b"key3", b"value3"); - db.write(batch); // Atomically commits the batch - } -} -``` - -###### Getting an `Iterator` -```rust -extern crate rocksdb; -use rocksdb::{DB, Direction, IteratorMode}; - -fn main() { - // NB: db is automatically freed at end of lifetime - let mut db = DB::open_default("/path/for/rocksdb/storage").unwrap(); - let mut iter = db.iterator(IteratorMode::Start); // Always iterates forward - for (key, value) in iter { - println!("Saw {} {}", key, value); //actually, need to convert [u8] keys into Strings - } - iter = db.iterator(IteratorMode::End); // Always iterates backward - for (key, value) in iter { - println!("Saw {} {}", key, value); - } - iter = db.iterator(IteratorMode::From(b"my key", Direction::forward)); // From a key in Direction::{forward,reverse} - for (key, value) in iter { - println!("Saw {} {}", key, value); - } - - // You can seek with an existing Iterator instance, too - iter.set_mode(IteratorMode::From(b"another key", Direction::reverse)); - for (key, value) in iter { - println!("Saw {} {}", key, value); - } -} -``` - -###### Getting an `Iterator` from a `Snapshot` -```rust -extern crate rocksdb; -use rocksdb::{DB, Direction}; - -fn main() { - // NB: db is automatically freed at end of lifetime - let mut db = DB::open_default("/path/for/rocksdb/storage").unwrap(); - let snapshot = db.snapshot(); // Creates a longer-term snapshot of the DB, but freed when goes out of scope - let mut iter = snapshot.iterator(IteratorMode::Start); // Make as many iterators as you'd like from one snapshot -} -``` - -###### Rustic Merge Operator -```rust -extern crate rocksdb; -use rocksdb::{Options, DB, MergeOperands, Writable}; - -fn concat_merge(new_key: &[u8], existing_val: Option<&[u8]>, - operands: &mut MergeOperands) -> Vec { - let mut result: Vec = Vec::with_capacity(operands.size_hint().0); - existing_val.map(|v| { - for e in v { - result.push(*e) - } - }); - for op in operands { - for e in op { - result.push(*e) - } - } - result -} - -fn main() { - let path = "/path/to/rocksdb"; - let mut opts = Options::default(); - opts.create_if_missing(true); - opts.add_merge_operator("test operator", concat_merge); - let mut db = DB::open(&opts, path).unwrap(); - let p = db.put(b"k1", b"a"); - db.merge(b"k1", b"b"); - db.merge(b"k1", b"c"); - db.merge(b"k1", b"d"); - db.merge(b"k1", b"efg"); - let r = db.get(b"k1"); - assert!(r.unwrap().unwrap().to_utf8().unwrap() == "abcdefg"); -} -``` - -###### Apply Some Tunings -Please read [the official tuning guide](https://github.com/facebook/rocksdb/wiki/RocksDB-Tuning-Guide), and most importantly, measure performance under realistic workloads with realistic hardware. -```rust -use rocksdb::{Options, DB}; -use rocksdb::DBCompactionStyle::DBUniversalCompaction; - -fn badly_tuned_for_somebody_elses_disk() -> DB { - let path = "_rust_rocksdb_optimizetest"; - let mut opts = Options::default(); - opts.create_if_missing(true); - opts.set_max_open_files(10000); - opts.set_use_fsync(false); - opts.set_bytes_per_sync(8388608); - opts.set_disable_data_sync(false); - opts.set_block_cache_size_mb(1024); - opts.set_table_cache_num_shard_bits(6); - opts.set_max_write_buffer_number(32); - opts.set_write_buffer_size(536870912); - opts.set_target_file_size_base(1073741824); - opts.set_min_write_buffer_number_to_merge(4); - opts.set_level_zero_stop_writes_trigger(2000); - opts.set_level_zero_slowdown_writes_trigger(0); - opts.set_compaction_style(DBUniversalCompaction); - opts.set_max_background_compactions(4); - opts.set_max_background_flushes(4); - opts.set_filter_deletes(false); - opts.set_disable_auto_compactions(true); - - DB::open(&opts, path).unwrap() -} +rocksdb = "0.5.0" ``` diff --git a/rocksdb-sys/.gitignore b/rocksdb_sys/.gitignore similarity index 100% rename from rocksdb-sys/.gitignore rename to rocksdb_sys/.gitignore diff --git a/rocksdb-sys/Cargo.toml b/rocksdb_sys/Cargo.toml similarity index 85% rename from rocksdb-sys/Cargo.toml rename to rocksdb_sys/Cargo.toml index dcceeec..194068a 100644 --- a/rocksdb-sys/Cargo.toml +++ b/rocksdb_sys/Cargo.toml @@ -1,11 +1,11 @@ [package] -name = "rocksdb-sys" +name = "rocksdb_sys" version = "0.4.0" authors = ["Karl Hobley ", "Arkadiy Paronyan "] license = "MIT/Apache-2.0/BSD" description = "Native bindings to librocksdb" readme = "README.md" -repository = "https://github.com/jsgf/rocksdb-sys.git" +repository = "https://github.com/spacejam/rust-rocksdb.git" keywords = [ "ffi", "rocksdb" ] build = "build.rs" diff --git a/rocksdb-sys/Makefile b/rocksdb_sys/Makefile similarity index 100% rename from rocksdb-sys/Makefile rename to rocksdb_sys/Makefile diff --git a/rocksdb-sys/README.md b/rocksdb_sys/README.md similarity index 100% rename from rocksdb-sys/README.md rename to rocksdb_sys/README.md diff --git a/rocksdb-sys/build.rs b/rocksdb_sys/build.rs similarity index 100% rename from rocksdb-sys/build.rs rename to rocksdb_sys/build.rs diff --git a/rocksdb-sys/build_version.cc b/rocksdb_sys/build_version.cc similarity index 100% rename from rocksdb-sys/build_version.cc rename to rocksdb_sys/build_version.cc diff --git a/rocksdb-sys/build_version.h b/rocksdb_sys/build_version.h similarity index 100% rename from rocksdb-sys/build_version.h rename to rocksdb_sys/build_version.h diff --git a/rocksdb-sys/rocksdb b/rocksdb_sys/rocksdb similarity index 100% rename from rocksdb-sys/rocksdb rename to rocksdb_sys/rocksdb diff --git a/rocksdb-sys/rocksdb_lib_sources.txt b/rocksdb_sys/rocksdb_lib_sources.txt similarity index 100% rename from rocksdb-sys/rocksdb_lib_sources.txt rename to rocksdb_sys/rocksdb_lib_sources.txt diff --git a/rocksdb-sys/snappy b/rocksdb_sys/snappy similarity index 100% rename from rocksdb-sys/snappy rename to rocksdb_sys/snappy diff --git a/rocksdb-sys/snappy-stubs-public.h b/rocksdb_sys/snappy-stubs-public.h similarity index 100% rename from rocksdb-sys/snappy-stubs-public.h rename to rocksdb_sys/snappy-stubs-public.h diff --git a/rocksdb-sys/src/lib.rs b/rocksdb_sys/src/lib.rs similarity index 100% rename from rocksdb-sys/src/lib.rs rename to rocksdb_sys/src/lib.rs diff --git a/rocksdb-sys/src/test.rs b/rocksdb_sys/src/test.rs similarity index 100% rename from rocksdb-sys/src/test.rs rename to rocksdb_sys/src/test.rs diff --git a/rocksdb-sys/tests/ffi.rs b/rocksdb_sys/tests/ffi.rs similarity index 100% rename from rocksdb-sys/tests/ffi.rs rename to rocksdb_sys/tests/ffi.rs diff --git a/src/lib.rs b/src/lib.rs index db3fdc9..9d80f43 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,29 +13,105 @@ // limitations under the License. // +//! Rust wrapper for RocksDB. +//! +//! # Examples +//! +//! ``` +//! use rocksdb::DB; +//! // NB: db is automatically closed at end of lifetime +//! let db = DB::open_default("/path/for/rocksdb/storage").unwrap(); +//! db.put(b"my key", b"my value"); +//! match db.get(b"my key") { +//! Ok(Some(value)) => println!("retrieved value {}", value.to_utf8().unwrap()), +//! Ok(None) => println!("value not found"), +//! Err(e) => println!("operational problem encountered: {}", e), +//! } +//! db.delete(b"my key").unwrap(); +//! ``` +//! + extern crate libc; extern crate rocksdb_sys as ffi; #[macro_use] mod ffi_util; -pub mod comparator; +mod comparator; pub mod merge_operator; mod rocksdb; mod rocksdb_options; pub use rocksdb::{DB, DBCompactionStyle, DBCompressionType, DBIterator, DBRecoveryMode, DBVector, - Direction, Error, IteratorMode, Snapshot, Writable, WriteBatch, new_bloom_filter}; + Direction, Error, IteratorMode, Snapshot, WriteBatch, new_bloom_filter}; + pub use merge_operator::MergeOperands; +/// For configuring block-based file storage. pub struct BlockBasedOptions { inner: *mut ffi::rocksdb_block_based_table_options_t, } +/// Database-wide options around performance and behavior. +/// +/// Please read [the official tuning guide](https://github.com/facebook/rocksdb/wiki/RocksDB-Tuning-Guide), and most importantly, measure performance under realistic workloads with realistic hardware. +/// +/// # Examples +/// +/// ``` +/// use rocksdb::{Options, DB}; +/// use rocksdb::DBCompactionStyle; +/// +/// fn badly_tuned_for_somebody_elses_disk() -> DB { +/// let path = "/path/for/rocksdb/storage5"; +/// let mut opts = Options::default(); +/// opts.create_if_missing(true); +/// opts.set_max_open_files(10000); +/// opts.set_use_fsync(false); +/// opts.set_bytes_per_sync(8388608); +/// opts.set_disable_data_sync(false); +/// opts.optimize_for_point_lookup(1024); +/// opts.set_table_cache_num_shard_bits(6); +/// opts.set_max_write_buffer_number(32); +/// opts.set_write_buffer_size(536870912); +/// opts.set_target_file_size_base(1073741824); +/// opts.set_min_write_buffer_number_to_merge(4); +/// opts.set_level_zero_stop_writes_trigger(2000); +/// opts.set_level_zero_slowdown_writes_trigger(0); +/// opts.set_compaction_style(DBCompactionStyle::Universal); +/// opts.set_max_background_compactions(4); +/// opts.set_max_background_flushes(4); +/// opts.set_disable_auto_compactions(true); +/// +/// DB::open(&opts, path).unwrap() +/// } +/// ``` pub struct Options { inner: *mut ffi::rocksdb_options_t, } +/// Optionally disable WAL or sync for this write. +/// +/// # Examples +/// +/// Making an unsafe write of a batch: +/// +/// ``` +/// use rocksdb::{DB, WriteBatch, WriteOptions}; +/// +/// let db = DB::open_default("/path/for/rocksdb/storage6").unwrap(); +/// +/// let mut batch = WriteBatch::default(); +/// batch.put(b"my key", b"my value"); +/// batch.put(b"key2", b"value2"); +/// batch.put(b"key3", b"value3"); +/// +/// let mut write_options = WriteOptions::default(); +/// write_options.set_sync(false); +/// write_options.disable_wal(true); +/// +/// db.write_opt(batch, &write_options); +/// ``` pub struct WriteOptions { inner: *mut ffi::rocksdb_writeoptions_t, } diff --git a/src/merge_operator.rs b/src/merge_operator.rs index e98f996..8d36f87 100644 --- a/src/merge_operator.rs +++ b/src/merge_operator.rs @@ -13,6 +13,46 @@ // limitations under the License. // +//! rustic merge operator +//! +//! ``` +//! use rocksdb::{Options, DB, MergeOperands}; +//! +//! fn concat_merge(new_key: &[u8], +//! existing_val: Option<&[u8]>, +//! operands: &mut MergeOperands) +//! -> Vec { +//! +//! let mut result: Vec = Vec::with_capacity(operands.size_hint().0); +//! existing_val.map(|v| { +//! for e in v { +//! result.push(*e) +//! } +//! }); +//! for op in operands { +//! for e in op { +//! result.push(*e) +//! } +//! } +//! result +//! } +//! +//! fn main() { +//! let path = "/path/to/rocksdb"; +//! let mut opts = Options::default(); +//! opts.create_if_missing(true); +//! opts.add_merge_operator("test operator", concat_merge); +//! let db = DB::open(&opts, path).unwrap(); +//! let p = db.put(b"k1", b"a"); +//! db.merge(b"k1", b"b"); +//! db.merge(b"k1", b"c"); +//! db.merge(b"k1", b"d"); +//! db.merge(b"k1", b"efg"); +//! let r = db.get(b"k1"); +//! assert!(r.unwrap().unwrap().to_utf8().unwrap() == "abcdefg"); +//! } +//! ``` + use std::ffi::CString; use std::mem; use std::ptr; @@ -160,7 +200,7 @@ fn test_provided_merge(new_key: &[u8], #[test] fn mergetest() { use Options; - use rocksdb::{DB, Writable}; + use rocksdb::DB; let path = "_rust_rocksdb_mergetest"; let mut opts = Options::default(); diff --git a/src/rocksdb.rs b/src/rocksdb.rs index cbb69a9..b4f735e 100644 --- a/src/rocksdb.rs +++ b/src/rocksdb.rs @@ -36,6 +36,7 @@ pub fn new_cache(capacity: size_t) -> *mut ffi::rocksdb_cache_t { unsafe { ffi::rocksdb_cache_create_lru(capacity) } } +/// RocksDB wrapper object. pub struct DB { inner: *mut ffi::rocksdb_t, cfs: BTreeMap, @@ -70,6 +71,22 @@ pub enum DBRecoveryMode { SkipAnyCorruptedRecords = 3, } +/// An atomic batch of mutations. +/// +/// Making an atomic commit of several writes: +/// +/// ``` +/// use rocksdb::{DB, WriteBatch}; +/// +/// let db = DB::open_default("/path/for/rocksdb/storage1").unwrap(); +/// { +/// let mut batch = WriteBatch::default(); +/// batch.put(b"my key", b"my value"); +/// batch.put(b"key2", b"value2"); +/// batch.put(b"key3", b"value3"); +/// db.write(batch); // Atomically commits the batch +/// } +/// ``` pub struct WriteBatch { inner: *mut ffi::rocksdb_writebatch_t, } @@ -78,11 +95,48 @@ pub struct ReadOptions { inner: *mut ffi::rocksdb_readoptions_t, } +/// A consistent view of the database at the point of creation. +/// +/// ``` +/// use rocksdb::{DB, IteratorMode}; +/// +/// let db = DB::open_default("/path/for/rocksdb/storage3").unwrap(); +/// let snapshot = db.snapshot(); // Creates a longer-term snapshot of the DB, but closed when goes out of scope +/// let mut iter = snapshot.iterator(IteratorMode::Start); // Make as many iterators as you'd like from one snapshot +/// ``` +/// pub struct Snapshot<'a> { db: &'a DB, inner: *const ffi::rocksdb_snapshot_t, } +/// An iterator over a database or column family, with specifiable +/// ranges and direction. +/// +/// ``` +/// use rocksdb::{DB, Direction, IteratorMode}; +/// +/// let mut db = DB::open_default("/path/for/rocksdb/storage2").unwrap(); +/// let mut iter = db.iterator(IteratorMode::Start); // Always iterates forward +/// for (key, value) in iter { +/// println!("Saw {:?} {:?}", key, value); +/// } +/// iter = db.iterator(IteratorMode::End); // Always iterates backward +/// for (key, value) in iter { +/// println!("Saw {:?} {:?}", key, value); +/// } +/// iter = db.iterator(IteratorMode::From(b"my key", Direction::Forward)); // From a key in Direction::{forward,reverse} +/// for (key, value) in iter { +/// println!("Saw {:?} {:?}", key, value); +/// } +/// +/// // You can seek with an existing Iterator instance, too +/// iter = db.iterator(IteratorMode::Start); +/// iter.set_mode(IteratorMode::From(b"another key", Direction::Reverse)); +/// for (key, value) in iter { +/// println!("Saw {:?} {:?}", key, value); +/// } +/// ``` pub struct DBIterator { inner: *mut ffi::rocksdb_iterator_t, direction: Direction, @@ -277,27 +331,6 @@ impl<'a> Drop for Snapshot<'a> { } } -// This is for the DB and write batches to share the same API. -pub trait Writable { - fn put(&self, key: &[u8], value: &[u8]) -> Result<(), Error>; - fn put_cf(&self, - cf: *mut ffi::rocksdb_column_family_handle_t, - key: &[u8], - value: &[u8]) - -> Result<(), Error>; - fn merge(&self, key: &[u8], value: &[u8]) -> Result<(), Error>; - fn merge_cf(&self, - cf: *mut ffi::rocksdb_column_family_handle_t, - key: &[u8], - value: &[u8]) - -> Result<(), Error>; - fn delete(&self, key: &[u8]) -> Result<(), Error>; - fn delete_cf(&self, - cf: *mut ffi::rocksdb_column_family_handle_t, - key: &[u8]) - -> Result<(), Error>; -} - impl DB { /// Open a database with default options. pub fn open_default>(path: P) -> Result { @@ -604,12 +637,12 @@ impl DB { } } - fn merge_cf_opt(&self, - cf: *mut ffi::rocksdb_column_family_handle_t, - key: &[u8], - value: &[u8], - writeopts: &WriteOptions) - -> Result<(), Error> { + pub fn merge_cf_opt(&self, + cf: *mut ffi::rocksdb_column_family_handle_t, + key: &[u8], + value: &[u8], + writeopts: &WriteOptions) + -> Result<(), Error> { unsafe { ffi_try!(ffi::rocksdb_merge_cf(self.inner, writeopts.inner, @@ -622,7 +655,7 @@ impl DB { } } - fn delete_opt(&self, key: &[u8], writeopts: &WriteOptions) -> Result<(), Error> { + pub fn delete_opt(&self, key: &[u8], writeopts: &WriteOptions) -> Result<(), Error> { unsafe { ffi_try!(ffi::rocksdb_delete(self.inner, writeopts.inner, @@ -632,11 +665,11 @@ impl DB { } } - fn delete_cf_opt(&self, - cf: *mut ffi::rocksdb_column_family_handle_t, - key: &[u8], - writeopts: &WriteOptions) - -> Result<(), Error> { + pub fn delete_cf_opt(&self, + cf: *mut ffi::rocksdb_column_family_handle_t, + key: &[u8], + writeopts: &WriteOptions) + -> Result<(), Error> { unsafe { ffi_try!(ffi::rocksdb_delete_cf(self.inner, writeopts.inner, @@ -646,41 +679,39 @@ impl DB { Ok(()) } } -} -impl Writable for DB { - fn put(&self, key: &[u8], value: &[u8]) -> Result<(), Error> { + pub fn put(&self, key: &[u8], value: &[u8]) -> Result<(), Error> { self.put_opt(key, value, &WriteOptions::default()) } - fn put_cf(&self, - cf: *mut ffi::rocksdb_column_family_handle_t, - key: &[u8], - value: &[u8]) - -> Result<(), Error> { + pub fn put_cf(&self, + cf: *mut ffi::rocksdb_column_family_handle_t, + key: &[u8], + value: &[u8]) + -> Result<(), Error> { self.put_cf_opt(cf, key, value, &WriteOptions::default()) } - fn merge(&self, key: &[u8], value: &[u8]) -> Result<(), Error> { + pub fn merge(&self, key: &[u8], value: &[u8]) -> Result<(), Error> { self.merge_opt(key, value, &WriteOptions::default()) } - fn merge_cf(&self, - cf: *mut ffi::rocksdb_column_family_handle_t, - key: &[u8], - value: &[u8]) - -> Result<(), Error> { + pub fn merge_cf(&self, + cf: *mut ffi::rocksdb_column_family_handle_t, + key: &[u8], + value: &[u8]) + -> Result<(), Error> { self.merge_cf_opt(cf, key, value, &WriteOptions::default()) } - fn delete(&self, key: &[u8]) -> Result<(), Error> { + pub fn delete(&self, key: &[u8]) -> Result<(), Error> { self.delete_opt(key, &WriteOptions::default()) } - fn delete_cf(&self, - cf: *mut ffi::rocksdb_column_family_handle_t, - key: &[u8]) - -> Result<(), Error> { + pub fn delete_cf(&self, + cf: *mut ffi::rocksdb_column_family_handle_t, + key: &[u8]) + -> Result<(), Error> { self.delete_cf_opt(cf, key, &WriteOptions::default()) } } @@ -693,40 +724,9 @@ impl WriteBatch { pub fn is_empty(&self) -> bool { self.len() == 0 } -} -impl Default for WriteBatch { - fn default() -> WriteBatch { - WriteBatch { inner: unsafe { ffi::rocksdb_writebatch_create() } } - } -} - -impl Drop for WriteBatch { - fn drop(&mut self) { - unsafe { ffi::rocksdb_writebatch_destroy(self.inner) } - } -} - -impl Drop for DB { - fn drop(&mut self) { - unsafe { - for cf in self.cfs.values() { - ffi::rocksdb_column_family_handle_destroy(*cf); - } - ffi::rocksdb_close(self.inner); - } - } -} - -impl fmt::Debug for DB { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "RocksDB {{ path: {:?} }}", self.path()) - } -} - -impl Writable for WriteBatch { /// Insert a value into the database under the given key. - fn put(&self, key: &[u8], value: &[u8]) -> Result<(), Error> { + pub fn put(&mut self, key: &[u8], value: &[u8]) -> Result<(), Error> { unsafe { ffi::rocksdb_writebatch_put(self.inner, key.as_ptr() as *const i8, @@ -737,11 +737,11 @@ impl Writable for WriteBatch { } } - fn put_cf(&self, - cf: *mut ffi::rocksdb_column_family_handle_t, - key: &[u8], - value: &[u8]) - -> Result<(), Error> { + pub fn put_cf(&mut self, + cf: *mut ffi::rocksdb_column_family_handle_t, + key: &[u8], + value: &[u8]) + -> Result<(), Error> { unsafe { ffi::rocksdb_writebatch_put_cf(self.inner, cf, @@ -753,7 +753,7 @@ impl Writable for WriteBatch { } } - fn merge(&self, key: &[u8], value: &[u8]) -> Result<(), Error> { + pub fn merge(&mut self, key: &[u8], value: &[u8]) -> Result<(), Error> { unsafe { ffi::rocksdb_writebatch_merge(self.inner, key.as_ptr() as *const i8, @@ -764,11 +764,11 @@ impl Writable for WriteBatch { } } - fn merge_cf(&self, - cf: *mut ffi::rocksdb_column_family_handle_t, - key: &[u8], - value: &[u8]) - -> Result<(), Error> { + pub fn merge_cf(&mut self, + cf: *mut ffi::rocksdb_column_family_handle_t, + key: &[u8], + value: &[u8]) + -> Result<(), Error> { unsafe { ffi::rocksdb_writebatch_merge_cf(self.inner, cf, @@ -783,7 +783,7 @@ impl Writable for WriteBatch { /// Remove the database entry for key. /// /// Returns Err if the key was not found - fn delete(&self, key: &[u8]) -> Result<(), Error> { + pub fn delete(&mut self, key: &[u8]) -> Result<(), Error> { unsafe { ffi::rocksdb_writebatch_delete(self.inner, key.as_ptr() as *const i8, @@ -792,10 +792,10 @@ impl Writable for WriteBatch { } } - fn delete_cf(&self, - cf: *mut ffi::rocksdb_column_family_handle_t, - key: &[u8]) - -> Result<(), Error> { + pub fn delete_cf(&mut self, + cf: *mut ffi::rocksdb_column_family_handle_t, + key: &[u8]) + -> Result<(), Error> { unsafe { ffi::rocksdb_writebatch_delete_cf(self.inner, cf, @@ -806,6 +806,35 @@ impl Writable for WriteBatch { } } +impl Default for WriteBatch { + fn default() -> WriteBatch { + WriteBatch { inner: unsafe { ffi::rocksdb_writebatch_create() } } + } +} + +impl Drop for WriteBatch { + fn drop(&mut self) { + unsafe { ffi::rocksdb_writebatch_destroy(self.inner) } + } +} + +impl Drop for DB { + fn drop(&mut self) { + unsafe { + for cf in self.cfs.values() { + ffi::rocksdb_column_family_handle_destroy(*cf); + } + ffi::rocksdb_close(self.inner); + } + } +} + +impl fmt::Debug for DB { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "RocksDB {{ path: {:?} }}", self.path()) + } +} + impl Drop for ReadOptions { fn drop(&mut self) { unsafe { ffi::rocksdb_readoptions_destroy(self.inner) } @@ -920,7 +949,7 @@ fn writebatch_works() { let db = DB::open_default(path).unwrap(); { // test put - let batch = WriteBatch::default(); + let mut batch = WriteBatch::default(); assert!(db.get(b"k1").unwrap().is_none()); assert_eq!(batch.len(), 0); assert!(batch.is_empty()); @@ -935,7 +964,7 @@ fn writebatch_works() { } { // test delete - let batch = WriteBatch::default(); + let mut batch = WriteBatch::default(); let _ = batch.delete(b"k1"); assert_eq!(batch.len(), 1); assert!(!batch.is_empty()); diff --git a/test/test_column_family.rs b/test/test_column_family.rs index 129070b..a85ea20 100644 --- a/test/test_column_family.rs +++ b/test/test_column_family.rs @@ -13,7 +13,7 @@ // limitations under the License. // -use rocksdb::{DB, MergeOperands, Options, Writable}; +use rocksdb::{DB, MergeOperands, Options}; #[test] pub fn test_column_family() { @@ -96,8 +96,7 @@ fn test_merge_operator() { }; let cf1 = *db.cf_handle("cf1").unwrap(); assert!(db.put_cf(cf1, b"k1", b"v1").is_ok()); - assert!(db.get_cf(cf1, b"k1").unwrap().unwrap().to_utf8().unwrap() == - "v1"); + assert!(db.get_cf(cf1, b"k1").unwrap().unwrap().to_utf8().unwrap() == "v1"); let p = db.put_cf(cf1, b"k1", b"a"); assert!(p.is_ok()); db.merge_cf(cf1, b"k1", b"b").unwrap(); diff --git a/test/test_iterator.rs b/test/test_iterator.rs index 14ab1c1..b3c1293 100644 --- a/test/test_iterator.rs +++ b/test/test_iterator.rs @@ -13,7 +13,7 @@ // limitations under the License. // -use rocksdb::{DB, Direction, IteratorMode, Options, Writable}; +use rocksdb::{DB, Direction, IteratorMode, Options}; fn cba(input: &Box<[u8]>) -> Box<[u8]> { input.iter().cloned().collect::>().into_boxed_slice() @@ -38,9 +38,7 @@ pub fn test_iterator() { assert!(p.is_ok()); let p = db.put(&*k3, &*v3); assert!(p.is_ok()); - let expected = vec![(cba(&k1), cba(&v1)), - (cba(&k2), cba(&v2)), - (cba(&k3), cba(&v3))]; + let expected = vec![(cba(&k1), cba(&v1)), (cba(&k2), cba(&v2)), (cba(&k3), cba(&v3))]; { let iterator1 = db.iterator(IteratorMode::Start); assert_eq!(iterator1.collect::>(), expected); @@ -114,48 +112,35 @@ pub fn test_iterator() { assert_eq!(iterator1.collect::>(), expected2); } { - let iterator1 = - db.iterator(IteratorMode::From(b"k2", Direction::Forward)); - let expected = vec![(cba(&k2), cba(&v2)), - (cba(&k3), cba(&v3)), - (cba(&k4), cba(&v4))]; + let iterator1 = db.iterator(IteratorMode::From(b"k2", Direction::Forward)); + let expected = vec![(cba(&k2), cba(&v2)), (cba(&k3), cba(&v3)), (cba(&k4), cba(&v4))]; assert_eq!(iterator1.collect::>(), expected); } { - let iterator1 = - db.iterator(IteratorMode::From(b"k2", Direction::Reverse)); + let iterator1 = db.iterator(IteratorMode::From(b"k2", Direction::Reverse)); let expected = vec![(cba(&k2), cba(&v2)), (cba(&k1), cba(&v1))]; assert_eq!(iterator1.collect::>(), expected); } { - let iterator1 = - db.iterator(IteratorMode::From(b"k0", Direction::Forward)); + let iterator1 = db.iterator(IteratorMode::From(b"k0", Direction::Forward)); assert!(iterator1.valid()); - let iterator2 = - db.iterator(IteratorMode::From(b"k1", Direction::Forward)); + let iterator2 = db.iterator(IteratorMode::From(b"k1", Direction::Forward)); assert!(iterator2.valid()); - let iterator3 = - db.iterator(IteratorMode::From(b"k11", Direction::Forward)); + let iterator3 = db.iterator(IteratorMode::From(b"k11", Direction::Forward)); assert!(iterator3.valid()); - let iterator4 = - db.iterator(IteratorMode::From(b"k5", Direction::Forward)); + let iterator4 = db.iterator(IteratorMode::From(b"k5", Direction::Forward)); assert!(!iterator4.valid()); - let iterator5 = - db.iterator(IteratorMode::From(b"k0", Direction::Reverse)); + let iterator5 = db.iterator(IteratorMode::From(b"k0", Direction::Reverse)); assert!(iterator5.valid()); - let iterator6 = - db.iterator(IteratorMode::From(b"k1", Direction::Reverse)); + let iterator6 = db.iterator(IteratorMode::From(b"k1", Direction::Reverse)); assert!(iterator6.valid()); - let iterator7 = - db.iterator(IteratorMode::From(b"k11", Direction::Reverse)); + let iterator7 = db.iterator(IteratorMode::From(b"k11", Direction::Reverse)); assert!(iterator7.valid()); - let iterator8 = - db.iterator(IteratorMode::From(b"k5", Direction::Reverse)); + let iterator8 = db.iterator(IteratorMode::From(b"k5", Direction::Reverse)); assert!(!iterator8.valid()); } { - let mut iterator1 = - db.iterator(IteratorMode::From(b"k4", Direction::Forward)); + let mut iterator1 = db.iterator(IteratorMode::From(b"k4", Direction::Forward)); iterator1.next(); assert!(iterator1.valid()); iterator1.next(); diff --git a/test/test_multithreaded.rs b/test/test_multithreaded.rs index 57dabce..83a1c49 100644 --- a/test/test_multithreaded.rs +++ b/test/test_multithreaded.rs @@ -13,7 +13,7 @@ // limitations under the License. // -use rocksdb::{DB, Options, Writable}; +use rocksdb::{DB, Options}; use std::thread; use std::sync::Arc;