prep for 0.5 release

master
Tyler Neely 8 years ago
parent 121ed9a993
commit ad2c15ac7c
  1. 8
      .gitmodules
  2. 6
      Cargo.toml
  3. 167
      README.md
  4. 0
      rocksdb_sys/.gitignore
  5. 4
      rocksdb_sys/Cargo.toml
  6. 0
      rocksdb_sys/Makefile
  7. 0
      rocksdb_sys/README.md
  8. 0
      rocksdb_sys/build.rs
  9. 0
      rocksdb_sys/build_version.cc
  10. 0
      rocksdb_sys/build_version.h
  11. 0
      rocksdb_sys/rocksdb
  12. 0
      rocksdb_sys/rocksdb_lib_sources.txt
  13. 0
      rocksdb_sys/snappy
  14. 0
      rocksdb_sys/snappy-stubs-public.h
  15. 0
      rocksdb_sys/src/lib.rs
  16. 0
      rocksdb_sys/src/test.rs
  17. 0
      rocksdb_sys/tests/ffi.rs
  18. 80
      src/lib.rs
  19. 42
      src/merge_operator.rs
  20. 233
      src/rocksdb.rs
  21. 5
      test/test_column_family.rs
  22. 43
      test/test_iterator.rs
  23. 2
      test/test_multithreaded.rs

8
.gitmodules vendored

@ -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

@ -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 <t@jujit.su>", "David Greenberg <dsg123456789@gmail.com>"]
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" }

@ -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<u8> {
let mut result: Vec<u8> = 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"
```

@ -1,11 +1,11 @@
[package]
name = "rocksdb-sys"
name = "rocksdb_sys"
version = "0.4.0"
authors = ["Karl Hobley <karlhobley10@gmail.com>", "Arkadiy Paronyan <arkadiy@ethcore.io>"]
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"

@ -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,
}

@ -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<u8> {
//!
//! let mut result: Vec<u8> = 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();

@ -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<String, *mut ffi::rocksdb_column_family_handle_t>,
@ -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<P: AsRef<Path>>(path: P) -> Result<DB, Error> {
@ -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());

@ -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();

@ -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::<Vec<_>>().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::<Vec<_>>(), expected);
@ -114,48 +112,35 @@ pub fn test_iterator() {
assert_eq!(iterator1.collect::<Vec<_>>(), 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::<Vec<_>>(), 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::<Vec<_>>(), 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();

@ -13,7 +13,7 @@
// limitations under the License.
//
use rocksdb::{DB, Options, Writable};
use rocksdb::{DB, Options};
use std::thread;
use std::sync::Arc;

Loading…
Cancel
Save