summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTyler Neely <t@jujit.su>2016-11-20 11:43:06 +0100
committerGitHub <noreply@github.com>2016-11-20 11:43:06 +0100
commita84012c3c8b7db9cd09f620a1a31b31c73d72cf1 (patch)
treeda6693659b4ff299dfff8cee280996ff8041ea8f
parenta2e916869450c854906c8d8200829b4e3a505147 (diff)
parent60049edad0f9e2e569426ea87ca83e54fa32128a (diff)
Merge pull request #93 from spacejam/0.5.0v0.5.0
0.5.0
-rw-r--r--.gitignore1
-rw-r--r--.gitmodules8
-rw-r--r--.travis.yml2
-rw-r--r--CHANGELOG.txt17
-rw-r--r--Cargo.toml6
-rw-r--r--README.md167
-rw-r--r--librocksdb-sys/.gitignore (renamed from rocksdb-sys/.gitignore)0
-rw-r--r--librocksdb-sys/Cargo.toml (renamed from rocksdb-sys/Cargo.toml)6
-rw-r--r--librocksdb-sys/Makefile (renamed from rocksdb-sys/Makefile)0
-rw-r--r--librocksdb-sys/README.md (renamed from rocksdb-sys/README.md)0
-rw-r--r--librocksdb-sys/build.rs (renamed from rocksdb-sys/build.rs)0
-rw-r--r--librocksdb-sys/build_version.cc (renamed from rocksdb-sys/build_version.cc)0
-rw-r--r--librocksdb-sys/build_version.h (renamed from rocksdb-sys/build_version.h)0
m---------librocksdb-sys/rocksdb (renamed from rocksdb-sys/rocksdb)0
-rw-r--r--librocksdb-sys/rocksdb_lib_sources.txt (renamed from rocksdb-sys/rocksdb_lib_sources.txt)0
m---------librocksdb-sys/snappy (renamed from rocksdb-sys/snappy)0
-rw-r--r--librocksdb-sys/snappy-stubs-public.h (renamed from rocksdb-sys/snappy-stubs-public.h)0
-rw-r--r--librocksdb-sys/src/lib.rs (renamed from rocksdb-sys/src/lib.rs)0
-rw-r--r--librocksdb-sys/src/test.rs (renamed from rocksdb-sys/src/test.rs)0
-rw-r--r--librocksdb-sys/tests/ffi.rs (renamed from rocksdb-sys/tests/ffi.rs)301
-rw-r--r--src/lib.rs82
-rw-r--r--src/merge_operator.rs42
-rw-r--r--src/rocksdb.rs233
-rw-r--r--test/test_column_family.rs5
-rw-r--r--test/test_iterator.rs43
-rw-r--r--test/test_multithreaded.rs2
26 files changed, 394 insertions, 521 deletions
diff --git a/.gitignore b/.gitignore
index aabca7b..1fc9772 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,4 @@ Cargo.lock
_rust_rocksdb*
*rlib
tags
+path
diff --git a/.gitmodules b/.gitmodules
index 10d03de..2c818bd 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,6 +1,6 @@
-[submodule "rocksdb-sys/snappy"]
- path = rocksdb-sys/snappy
+[submodule "rocksdb_sys/snappy"]
+ path = librocksdb-sys/snappy
url = https://github.com/google/snappy.git
-[submodule "rocksdb-sys/rocksdb"]
- path = rocksdb-sys/rocksdb
+[submodule "rocksdb_sys/rocksdb"]
+ path = librocksdb-sys/rocksdb
url = https://github.com/facebook/rocksdb.git
diff --git a/.travis.yml b/.travis.yml
index bb3e1de..e6d8d5f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,7 +14,7 @@ addons:
- g++-5
script:
- - cargo test --manifest-path=rocksdb-sys/Cargo.toml
+ - cargo test --manifest-path=librocksdb-sys/Cargo.toml
- cargo test
cache:
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index b571e42..0359f34 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -4,6 +4,23 @@ Changelog
0.5 (in development)
~~~~~~~~~~~~~~~~~~~~
+**Breaking changes**
+
+ * No more Writable trait, as WriteBatch is not thread-safe as a DB (spacejam)
* All imports of `rocksdb::rocksdb::*` should now be simply `rocksdb::*` (alexreg)
+ * All errors changed to use a new `rocksdb::Error` type (kaedroho, alexreg)
+ * Removed `Options.set_filter_deletes` as it was removed in RocksDB (kaedroho)
+ * Renamed `add_merge_operator` to `set_merge_operator` and `add_comparator` to `set_comparator` (kaedroho)
+
+ **New features**
+
+ * Windows support (development by jsgf and arkpar. ported by kaedroho)
+ * The RocksDB library is now built at crate compile-time and statically linked with the resulting binary (development by jsgf and arkpar. ported by kaedroho)
+ * Cleaned up and improved coverage and tests of the ffi module (alexreg)
+ * Added many new methods to the `Options` type (development by ngaut, BusyJay, zhangjinpeng1987, siddontang and hhkbp2. ported by kaedroho)
+ * Added `len` and `is_empty` methods to `WriteBatch` (development by siddontang. ported by kaedroho)
+ * Added `path` mathod to `DB` (development by siddontang. ported by kaedroho)
+ * `DB::open` now accepts any type that implements `Into<Path>` as the path argument (kaedroho)
+ * `DB` now implements the `Debug` trait (kaedroho)
* Add iterator_cf to snapshot (jezell)
* Changelog started
diff --git a/Cargo.toml b/Cargo.toml
index 74958f5..9dfc6d5 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-rc.1"
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"
+librocksdb-sys = { path = "librocksdb-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<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"
```
diff --git a/rocksdb-sys/.gitignore b/librocksdb-sys/.gitignore
index a9d37c5..a9d37c5 100644
--- a/rocksdb-sys/.gitignore
+++ b/librocksdb-sys/.gitignore
diff --git a/rocksdb-sys/Cargo.toml b/librocksdb-sys/Cargo.toml
index dcceeec..58f3223 100644
--- a/rocksdb-sys/Cargo.toml
+++ b/librocksdb-sys/Cargo.toml
@@ -1,11 +1,11 @@
[package]
-name = "rocksdb-sys"
+name = "librocksdb-sys"
version = "0.4.0"
authors = ["Karl Hobley <karlhobley10@gmail.com>", "Arkadiy Paronyan <arkadiy@ethcore.io>"]
-license = "MIT/Apache-2.0/BSD"
+license = "MIT/Apache-2.0/BSD-3-Clause"
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/librocksdb-sys/Makefile
index 8e5405a..8e5405a 100644
--- a/rocksdb-sys/Makefile
+++ b/librocksdb-sys/Makefile
diff --git a/rocksdb-sys/README.md b/librocksdb-sys/README.md
index 495ac54..495ac54 100644
--- a/rocksdb-sys/README.md
+++ b/librocksdb-sys/README.md
diff --git a/rocksdb-sys/build.rs b/librocksdb-sys/build.rs
index dd75c77..dd75c77 100644
--- a/rocksdb-sys/build.rs
+++ b/librocksdb-sys/build.rs
diff --git a/rocksdb-sys/build_version.cc b/librocksdb-sys/build_version.cc
index 7f600db..7f600db 100644
--- a/rocksdb-sys/build_version.cc
+++ b/librocksdb-sys/build_version.cc
diff --git a/rocksdb-sys/build_version.h b/librocksdb-sys/build_version.h
index ca1dbf5..ca1dbf5 100644
--- a/rocksdb-sys/build_version.h
+++ b/librocksdb-sys/build_version.h
diff --git a/rocksdb-sys/rocksdb b/librocksdb-sys/rocksdb
-Subproject f201a44b4102308b840b15d9b89122af787476f
+Subproject f201a44b4102308b840b15d9b89122af787476f
diff --git a/rocksdb-sys/rocksdb_lib_sources.txt b/librocksdb-sys/rocksdb_lib_sources.txt
index 209deb5..209deb5 100644
--- a/rocksdb-sys/rocksdb_lib_sources.txt
+++ b/librocksdb-sys/rocksdb_lib_sources.txt
diff --git a/rocksdb-sys/snappy b/librocksdb-sys/snappy
-Subproject efb39e81b8b66b757ec900db33657c47b475074
+Subproject efb39e81b8b66b757ec900db33657c47b475074
diff --git a/rocksdb-sys/snappy-stubs-public.h b/librocksdb-sys/snappy-stubs-public.h
index 14592e0..14592e0 100644
--- a/rocksdb-sys/snappy-stubs-public.h
+++ b/librocksdb-sys/snappy-stubs-public.h
diff --git a/rocksdb-sys/src/lib.rs b/librocksdb-sys/src/lib.rs
index c5d7e77..c5d7e77 100644
--- a/rocksdb-sys/src/lib.rs
+++ b/librocksdb-sys/src/lib.rs
diff --git a/rocksdb-sys/src/test.rs b/librocksdb-sys/src/test.rs
index 6d3aa79..6d3aa79 100644
--- a/rocksdb-sys/src/test.rs
+++ b/librocksdb-sys/src/test.rs
diff --git a/rocksdb-sys/tests/ffi.rs b/librocksdb-sys/tests/ffi.rs
index 157e5cc..15e8d9b 100644
--- a/rocksdb-sys/tests/ffi.rs
+++ b/librocksdb-sys/tests/ffi.rs
@@ -20,7 +20,7 @@
#[macro_use]
extern crate const_cstr;
extern crate libc;
-extern crate rocksdb_sys as ffi;
+extern crate librocksdb_sys as ffi;
use ::ffi::*;
use ::libc::*;
@@ -113,8 +113,7 @@ unsafe fn CheckGet(mut db: *mut rocksdb_t,
expected: *const c_char) {
let mut err: *mut c_char = ptr::null_mut();
let mut val_len: size_t = 0;
- let mut val: *mut c_char =
- rocksdb_get(db, options, key, strlen(key), &mut val_len, &mut err);
+ let mut val: *mut c_char = rocksdb_get(db, options, key, strlen(key), &mut val_len, &mut err);
CheckNoError!(err);
CheckEqual(expected, val, val_len);
Free(&mut val);
@@ -139,9 +138,7 @@ unsafe fn CheckGetCF(db: *mut rocksdb_t,
Free(&mut val);
}
-unsafe fn CheckIter(iter: *mut rocksdb_iterator_t,
- key: *const c_char,
- val: *const c_char) {
+unsafe fn CheckIter(iter: *mut rocksdb_iterator_t, key: *const c_char, val: *const c_char) {
let mut len: size_t = 0;
let mut str: *const c_char;
str = rocksdb_iter_key(iter, &mut len);
@@ -173,9 +170,7 @@ unsafe extern "C" fn CheckPut(ptr: *mut c_void,
}
// Callback from rocksdb_writebatch_iterate()
-unsafe extern "C" fn CheckDel(ptr: *mut c_void,
- k: *const c_char,
- klen: size_t) {
+unsafe extern "C" fn CheckDel(ptr: *mut c_void, k: *const c_char, klen: size_t) {
let mut state: *mut c_int = ptr as *mut c_int;
CheckCondition!(*state == 2);
CheckEqual(cstrp!("bar"), k, klen);
@@ -286,7 +281,9 @@ unsafe extern "C" fn CFilterFactoryName(arg: *mut c_void) -> *const c_char {
cstrp!("foo")
}
-unsafe extern "C" fn CFilterCreate(arg: *mut c_void, context: *mut rocksdb_compactionfiltercontext_t) -> *mut rocksdb_compactionfilter_t {
+unsafe extern "C" fn CFilterCreate(arg: *mut c_void,
+ context: *mut rocksdb_compactionfiltercontext_t)
+ -> *mut rocksdb_compactionfilter_t {
rocksdb_compactionfilter_create(ptr::null_mut(),
Some(CFilterDestroy),
Some(CFilterFilter),
@@ -365,7 +362,15 @@ unsafe extern "C" fn MergeOperatorFullMerge(arg: *mut c_void,
result
}
-unsafe extern "C" fn MergeOperatorPartialMerge(arg: *mut c_void, key: *const c_char, key_length: size_t, operands_list: *const *const c_char, operands_list_length: *const size_t, num_operands: c_int, success: *mut u8, new_value_length: *mut size_t) -> *mut c_char {
+unsafe extern "C" fn MergeOperatorPartialMerge(arg: *mut c_void,
+ key: *const c_char,
+ key_length: size_t,
+ operands_list: *const *const c_char,
+ operands_list_length: *const size_t,
+ num_operands: c_int,
+ success: *mut u8,
+ new_value_length: *mut size_t)
+ -> *mut c_char {
*new_value_length = 4;
*success = 1;
let result: *mut c_char = malloc(4) as *mut _;
@@ -433,8 +438,8 @@ fn ffi() {
no_compression,
];
rocksdb_options_set_compression_per_level(options,
- mem::transmute(compression_levels.as_ptr()),
- compression_levels.len() as size_t);
+ mem::transmute(compression_levels.as_ptr()),
+ compression_levels.len() as size_t);
roptions = rocksdb_readoptions_create();
rocksdb_readoptions_set_verify_checksums(roptions, 1);
@@ -459,13 +464,7 @@ fn ffi() {
CheckGet(db, roptions, cstrp!("foo") as *const _, ptr::null());
StartPhase("put");
- rocksdb_put(db,
- woptions,
- cstrp!("foo"),
- 3,
- cstrp!("hello"),
- 5,
- &mut err);
+ rocksdb_put(db, woptions, cstrp!("foo"), 3, cstrp!("hello"), 5, &mut err);
CheckNoError!(err);
CheckGet(db, roptions, cstrp!("foo"), cstrp!("hello"));
@@ -474,19 +473,14 @@ fn ffi() {
rocksdb_destroy_db(options, dbbackupname, &mut err);
CheckNoError!(err);
- let be =
- rocksdb_backup_engine_open(options, dbbackupname, &mut err);
+ let be = rocksdb_backup_engine_open(options, dbbackupname, &mut err);
CheckNoError!(err);
rocksdb_backup_engine_create_new_backup(be, db, &mut err);
CheckNoError!(err);
// need a change to trigger a new backup
- rocksdb_delete(db,
- woptions,
- cstrp!("does-not-exist"),
- 14,
- &mut err);
+ rocksdb_delete(db, woptions, cstrp!("does-not-exist"), 14, &mut err);
CheckNoError!(err);
rocksdb_backup_engine_create_new_backup(be, db, &mut err);
@@ -515,7 +509,11 @@ fn ffi() {
let restore_options = rocksdb_restore_options_create();
rocksdb_restore_options_set_keep_log_files(restore_options, 0);
- rocksdb_backup_engine_restore_db_from_latest_backup(be, dbname, dbname, restore_options, &mut err);
+ rocksdb_backup_engine_restore_db_from_latest_backup(be,
+ dbname,
+ dbname,
+ restore_options,
+ &mut err);
CheckNoError!(err);
rocksdb_restore_options_destroy(restore_options);
@@ -564,8 +562,7 @@ fn ffi() {
let wb = rocksdb_writebatch_create();
let k_list: [*const c_char; 2] = [cstrp!("z"), cstrp!("ap")];
let k_sizes: [size_t; 2] = [1, 2];
- let v_list: [*const c_char; 3] =
- [cstrp!("x"), cstrp!("y"), cstrp!("z")];
+ let v_list: [*const c_char; 3] = [cstrp!("x"), cstrp!("y"), cstrp!("z")];
let v_sizes: [size_t; 3] = [1, 1, 1];
rocksdb_writebatch_putv(wb,
k_list.len() as c_int,
@@ -591,14 +588,14 @@ fn ffi() {
rocksdb_writebatch_put(wb1, cstrp!("quux"), 4, cstrp!("e"), 1);
rocksdb_writebatch_delete(wb1, cstrp!("quux"), 4);
let mut repsize1: size_t = 0;
- let mut rep =
- rocksdb_writebatch_data(wb1, &mut repsize1) as *const c_void;
- let mut wb2 = rocksdb_writebatch_create_from(rep as *const c_char,
- repsize1);
- CheckCondition!(rocksdb_writebatch_count(wb1) ==
- rocksdb_writebatch_count(wb2));
+ let mut rep = rocksdb_writebatch_data(wb1, &mut repsize1) as *const c_void;
+ let mut wb2 = rocksdb_writebatch_create_from(rep as *const c_char, repsize1);
+ CheckCondition!(rocksdb_writebatch_count(wb1) == rocksdb_writebatch_count(wb2));
let mut repsize2: size_t = 0;
- CheckCondition!(memcmp(rep, rocksdb_writebatch_data(wb2, &mut repsize2) as *const c_void, repsize1) == 0);
+ CheckCondition!(memcmp(rep,
+ rocksdb_writebatch_data(wb2, &mut repsize2) as *const c_void,
+ repsize1) ==
+ 0);
rocksdb_writebatch_destroy(wb1);
rocksdb_writebatch_destroy(wb2);
}
@@ -627,14 +624,11 @@ fn ffi() {
StartPhase("multiget");
{
- let keys: [*const c_char; 3] =
- [cstrp!("box"), cstrp!("foo"), cstrp!("notfound")];
+ let keys: [*const c_char; 3] = [cstrp!("box"), cstrp!("foo"), cstrp!("notfound")];
let keys_sizes: [size_t; 3] = [3, 3, 8];
- let mut vals: [*mut c_char; 3] =
- [ptr::null_mut(), ptr::null_mut(), ptr::null_mut()];
+ let mut vals: [*mut c_char; 3] = [ptr::null_mut(), ptr::null_mut(), ptr::null_mut()];
let mut vals_sizes: [size_t; 3] = [0, 0, 0];
- let mut errs: [*mut c_char; 3] =
- [ptr::null_mut(), ptr::null_mut(), ptr::null_mut()];
+ let mut errs: [*mut c_char; 3] = [ptr::null_mut(), ptr::null_mut(), ptr::null_mut()];
rocksdb_multi_get(db,
roptions,
3,
@@ -659,11 +653,9 @@ fn ffi() {
StartPhase("approximate_sizes");
{
let mut sizes: [uint64_t; 2] = [0, 0];
- let start: [*const c_char; 2] = [cstrp!("a"),
- cstrp!("k00000000000000010000")];
+ let start: [*const c_char; 2] = [cstrp!("a"), cstrp!("k00000000000000010000")];
let start_len: [size_t; 2] = [1, 21];
- let limit: [*const c_char; 2] = [cstrp!("k00000000000000010000"),
- cstrp!("z")];
+ let limit: [*const c_char; 2] = [cstrp!("k00000000000000010000"), cstrp!("z")];
let limit_len: [size_t; 2] = [21, 1];
rocksdb_writeoptions_set_sync(woptions, 0);
for i in 0..20000 {
@@ -747,14 +739,12 @@ fn ffi() {
rocksdb_filterpolicy_create_bloom(10)
};
- rocksdb_block_based_options_set_filter_policy(table_options,
- policy);
+ rocksdb_block_based_options_set_filter_policy(table_options, policy);
// Create new database
rocksdb_close(db);
rocksdb_destroy_db(options, dbname, &mut err);
- rocksdb_options_set_block_based_table_factory(options,
- table_options);
+ rocksdb_options_set_block_based_table_factory(options, table_options);
db = rocksdb_open(options, dbname, &mut err);
CheckNoError!(err);
rocksdb_put(db,
@@ -789,10 +779,8 @@ fn ffi() {
CheckGet(db, roptions, cstrp!("bar"), cstrp!("barvalue"));
}
// Reset the policy
- rocksdb_block_based_options_set_filter_policy(table_options,
- ptr::null_mut());
- rocksdb_options_set_block_based_table_factory(options,
- table_options);
+ rocksdb_block_based_options_set_filter_policy(table_options, ptr::null_mut());
+ rocksdb_options_set_block_based_table_factory(options, table_options);
}
StartPhase("compaction_filter");
@@ -807,14 +795,9 @@ fn ffi() {
rocksdb_close(db);
rocksdb_destroy_db(options_with_filter, dbname, &mut err);
rocksdb_options_set_compaction_filter(options_with_filter, cfilter);
- db = CheckCompaction(dbname,
- db,
- options_with_filter,
- roptions,
- woptions);
+ db = CheckCompaction(dbname, db, options_with_filter, roptions, woptions);
- rocksdb_options_set_compaction_filter(options_with_filter,
- ptr::null_mut());
+ rocksdb_options_set_compaction_filter(options_with_filter, ptr::null_mut());
rocksdb_compactionfilter_destroy(cfilter);
rocksdb_options_destroy(options_with_filter);
}
@@ -822,32 +805,30 @@ fn ffi() {
StartPhase("compaction_filter_factory");
{
let mut options_with_filter_factory = rocksdb_options_create();
- rocksdb_options_set_create_if_missing(options_with_filter_factory,
- 1);
- let mut factory = rocksdb_compactionfilterfactory_create(ptr::null_mut(), Some(CFilterFactoryDestroy), Some(CFilterCreate), Some(CFilterFactoryName));
+ rocksdb_options_set_create_if_missing(options_with_filter_factory, 1);
+ let mut factory = rocksdb_compactionfilterfactory_create(ptr::null_mut(),
+ Some(CFilterFactoryDestroy),
+ Some(CFilterCreate),
+ Some(CFilterFactoryName));
// Create new database
rocksdb_close(db);
rocksdb_destroy_db(options_with_filter_factory, dbname, &mut err);
rocksdb_options_set_compaction_filter_factory(options_with_filter_factory, factory);
- db = CheckCompaction(dbname,
- db,
- options_with_filter_factory,
- roptions,
- woptions);
+ db = CheckCompaction(dbname, db, options_with_filter_factory, roptions, woptions);
- rocksdb_options_set_compaction_filter_factory(options_with_filter_factory, ptr::null_mut());
+ rocksdb_options_set_compaction_filter_factory(options_with_filter_factory,
+ ptr::null_mut());
rocksdb_options_destroy(options_with_filter_factory);
}
StartPhase("merge_operator");
{
- let mut merge_operator =
- rocksdb_mergeoperator_create(ptr::null_mut(),
- Some(MergeOperatorDestroy),
- Some(MergeOperatorFullMerge),
- Some(MergeOperatorPartialMerge),
- None,
- Some(MergeOperatorName));
+ let mut merge_operator = rocksdb_mergeoperator_create(ptr::null_mut(),
+ Some(MergeOperatorDestroy),
+ Some(MergeOperatorFullMerge),
+ Some(MergeOperatorPartialMerge),
+ None,
+ Some(MergeOperatorName));
// Create new database
rocksdb_close(db);
rocksdb_destroy_db(options, dbname, &mut err);
@@ -895,21 +876,15 @@ fn ffi() {
rocksdb_options_set_create_if_missing(db_options, 1);
db = rocksdb_open(db_options, dbname, &mut err);
CheckNoError!(err);
- let mut cfh = rocksdb_create_column_family(db,
- db_options,
- cstrp!("cf1"),
- &mut err);
+ let mut cfh = rocksdb_create_column_family(db, db_options, cstrp!("cf1"), &mut err);
rocksdb_column_family_handle_destroy(cfh);
CheckNoError!(err);
rocksdb_close(db);
let mut cflen: size_t = 0;
- let column_fams_raw = rocksdb_list_column_families(db_options,
- dbname,
- &mut cflen,
- &mut err);
- let column_fams = slice::from_raw_parts(column_fams_raw,
- cflen as usize);
+ let column_fams_raw =
+ rocksdb_list_column_families(db_options, dbname, &mut cflen, &mut err);
+ let column_fams = slice::from_raw_parts(column_fams_raw, cflen as usize);
CheckEqual(cstrp!("default"), column_fams[0], 7);
CheckEqual(cstrp!("cf1"), column_fams[1], 3);
CheckCondition!(cflen == 2);
@@ -917,12 +892,10 @@ fn ffi() {
let mut cf_options = rocksdb_options_create();
- let cf_names: [*const c_char; 2] = [cstrp!("default"),
- cstrp!("cf1")];
- let cf_opts: [*const rocksdb_options_t; 2] = [cf_options,
- cf_options];
- let mut handles: [*mut rocksdb_column_family_handle_t; 2] =
- [ptr::null_mut(), ptr::null_mut()];
+ let cf_names: [*const c_char; 2] = [cstrp!("default"), cstrp!("cf1")];
+ let cf_opts: [*const rocksdb_options_t; 2] = [cf_options, cf_options];
+ let mut handles: [*mut rocksdb_column_family_handle_t; 2] = [ptr::null_mut(),
+ ptr::null_mut()];
db = rocksdb_open_column_families(db_options,
dbname,
2,
@@ -942,42 +915,18 @@ fn ffi() {
&mut err);
CheckNoError!(err);
- CheckGetCF(db,
- roptions,
- handles[1],
- cstrp!("foo"),
- cstrp!("hello"));
+ CheckGetCF(db, roptions, handles[1], cstrp!("foo"), cstrp!("hello"));
- rocksdb_delete_cf(db,
- woptions,
- handles[1],
- cstrp!("foo"),
- 3,
- &mut err);
+ rocksdb_delete_cf(db, woptions, handles[1], cstrp!("foo"), 3, &mut err);
CheckNoError!(err);
CheckGetCF(db, roptions, handles[1], cstrp!("foo"), ptr::null());
let mut wb = rocksdb_writebatch_create();
- rocksdb_writebatch_put_cf(wb,
- handles[1],
- cstrp!("baz"),
- 3,
- cstrp!("a"),
- 1);
+ rocksdb_writebatch_put_cf(wb, handles[1], cstrp!("baz"), 3, cstrp!("a"), 1);
rocksdb_writebatch_clear(wb);
- rocksdb_writebatch_put_cf(wb,
- handles[1],
- cstrp!("bar"),
- 3,
- cstrp!("b"),
- 1);
- rocksdb_writebatch_put_cf(wb,
- handles[1],
- cstrp!("box"),
- 3,
- cstrp!("c"),
- 1);
+ rocksdb_writebatch_put_cf(wb, handles[1], cstrp!("bar"), 3, cstrp!("b"), 1);
+ rocksdb_writebatch_put_cf(wb, handles[1], cstrp!("box"), 3, cstrp!("c"), 1);
rocksdb_writebatch_delete_cf(wb, handles[1], cstrp!("bar"), 3);
rocksdb_write(db, woptions, wb, &mut err);
CheckNoError!(err);
@@ -986,16 +935,13 @@ fn ffi() {
CheckGetCF(db, roptions, handles[1], cstrp!("box"), cstrp!("c"));
rocksdb_writebatch_destroy(wb);
- let keys: [*const c_char; 3] =
- [cstrp!("box"), cstrp!("box"), cstrp!("barfooxx")];
- let get_handles: [*const rocksdb_column_family_handle_t; 3] =
- [handles[0], handles[1], handles[1]];
+ let keys: [*const c_char; 3] = [cstrp!("box"), cstrp!("box"), cstrp!("barfooxx")];
+ let get_handles: [*const rocksdb_column_family_handle_t; 3] = [handles[0], handles[1],
+ handles[1]];
let keys_sizes: [size_t; 3] = [3, 3, 8];
- let mut vals: [*mut c_char; 3] =
- [ptr::null_mut(), ptr::null_mut(), ptr::null_mut()];
+ let mut vals: [*mut c_char; 3] = [ptr::null_mut(), ptr::null_mut(), ptr::null_mut()];
let mut vals_sizes: [size_t; 3] = [0, 0, 0];
- let mut errs: [*mut c_char; 3] =
- [ptr::null_mut(), ptr::null_mut(), ptr::null_mut()];
+ let mut errs: [*mut c_char; 3] = [ptr::null_mut(), ptr::null_mut(), ptr::null_mut()];
rocksdb_multi_get_cf(db,
roptions,
get_handles.as_ptr(),
@@ -1032,9 +978,10 @@ fn ffi() {
CheckNoError!(err);
rocksdb_iter_destroy(iter);
- let mut iters_cf_handles: [*mut rocksdb_column_family_handle_t; 2] = [handles[0], handles[1]];
- let mut iters_handles: [*mut rocksdb_iterator_t; 2] =
- [ptr::null_mut(), ptr::null_mut()];
+ let mut iters_cf_handles: [*mut rocksdb_column_family_handle_t; 2] = [handles[0],
+ handles[1]];
+ let mut iters_handles: [*mut rocksdb_iterator_t; 2] = [ptr::null_mut(),
+ ptr::null_mut()];
rocksdb_create_iterators(db,
roptions,
iters_cf_handles.as_mut_ptr(),
@@ -1079,60 +1026,25 @@ fn ffi() {
{
// Create new database
rocksdb_options_set_allow_mmap_reads(options, 1);
- rocksdb_options_set_prefix_extractor(options, rocksdb_slicetransform_create_fixed_prefix(3));
+ rocksdb_options_set_prefix_extractor(options,
+ rocksdb_slicetransform_create_fixed_prefix(3));
rocksdb_options_set_hash_skip_list_rep(options, 5000, 4, 4);
rocksdb_options_set_plain_table_factory(options, 4, 10, 0.75, 16);
db = rocksdb_open(options, dbname, &mut err);
CheckNoError!(err);
- rocksdb_put(db,
- woptions,
- cstrp!("foo1"),
- 4,
- cstrp!("foo"),
- 3,
- &mut err);
+ rocksdb_put(db, woptions, cstrp!("foo1"), 4, cstrp!("foo"), 3, &mut err);
CheckNoError!(err);
- rocksdb_put(db,
- woptions,
- cstrp!("foo2"),
- 4,
- cstrp!("foo"),
- 3,
- &mut err);
+ rocksdb_put(db, woptions, cstrp!("foo2"), 4, cstrp!("foo"), 3, &mut err);
CheckNoError!(err);
- rocksdb_put(db,
- woptions,
- cstrp!("foo3"),
- 4,
- cstrp!("foo"),
- 3,
- &mut err);
+ rocksdb_put(db, woptions, cstrp!("foo3"), 4, cstrp!("foo"), 3, &mut err);
CheckNoError!(err);
- rocksdb_put(db,
- woptions,
- cstrp!("bar1"),
- 4,
- cstrp!("bar"),
- 3,
- &mut err);
+ rocksdb_put(db, woptions, cstrp!("bar1"), 4, cstrp!("bar"), 3, &mut err);
CheckNoError!(err);
- rocksdb_put(db,
- woptions,
- cstrp!("bar2"),
- 4,
- cstrp!("bar"),
- 3,
- &mut err);
+ rocksdb_put(db, woptions, cstrp!("bar2"), 4, cstrp!("bar"), 3, &mut err);
CheckNoError!(err);
- rocksdb_put(db,
- woptions,
- cstrp!("bar3"),
- 4,
- cstrp!("bar"),
- 3,
- &mut err);
+ rocksdb_put(db, woptions, cstrp!("bar3"), 4, cstrp!("bar"), 3, &mut err);
CheckNoError!(err);
let mut iter = rocksdb_create_iterator(db, roptions);
@@ -1162,8 +1074,7 @@ fn ffi() {
rocksdb_cuckoo_options_set_hash_ratio(cuckoo_options, 0.5);
rocksdb_cuckoo_options_set_max_search_depth(cuckoo_options, 200);
rocksdb_cuckoo_options_set_cuckoo_block_size(cuckoo_options, 10);
- rocksdb_cuckoo_options_set_identity_as_first_hash(cuckoo_options,
- 1);
+ rocksdb_cuckoo_options_set_identity_as_first_hash(cuckoo_options, 1);
rocksdb_cuckoo_options_set_use_module_hash(cuckoo_options, 0);
rocksdb_options_set_cuckoo_table_factory(options, cuckoo_options);
@@ -1186,36 +1097,16 @@ fn ffi() {
rocksdb_put(db, woptions, cstrp!("a"), 1, cstrp!("0"), 1, &mut err);
CheckNoError!(err);
- rocksdb_put(db,
- woptions,
- cstrp!("foo"),
- 3,
- cstrp!("bar"),
- 3,
- &mut err);
+ rocksdb_put(db, woptions, cstrp!("foo"), 3, cstrp!("bar"), 3, &mut err);
CheckNoError!(err);
- rocksdb_put(db,
- woptions,
- cstrp!("foo1"),
- 4,
- cstrp!("bar1"),
- 4,
- &mut err);
+ rocksdb_put(db, woptions, cstrp!("foo1"), 4, cstrp!("bar1"), 4, &mut err);
CheckNoError!(err);
- rocksdb_put(db,
- woptions,
- cstrp!("g1"),
- 2,
- cstrp!("0"),
- 1,
- &mut err);
+ rocksdb_put(db, woptions, cstrp!("g1"), 2, cstrp!("0"), 1, &mut err);
CheckNoError!(err);
// testing basic case with no iterate_upper_bound and no prefix_extractor
{
- rocksdb_readoptions_set_iterate_upper_bound(roptions,
- ptr::null(),
- 0);
+ rocksdb_readoptions_set_iterate_upper_bound(roptions, ptr::null(), 0);
let mut iter = rocksdb_create_iterator(db, roptions);
rocksdb_iter_seek(iter, cstrp!("foo"), 3);
@@ -1237,9 +1128,7 @@ fn ffi() {
// to make sure it stops at bound
{
// iterate_upper_bound points beyond the last expected entry
- rocksdb_readoptions_set_iterate_upper_bound(roptions,
- cstrp!("foo2"),
- 4);
+ rocksdb_readoptions_set_iterate_upper_bound(roptions, cstrp!("foo2"), 4);
let mut iter = rocksdb_create_iterator(db, roptions);
diff --git a/src/lib.rs b/src/lib.rs
index db3fdc9..0854799 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;
+extern crate librocksdb_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..8980ee0 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<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();
diff --git a/src/rocksdb.rs b/src/rocksdb.rs
index 4e5443f..b1eef6c 100644
--- a/src/rocksdb.rs
+++ b/src/rocksdb.rs
@@ -37,6 +37,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>,
@@ -71,6 +72,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,
}
@@ -79,11 +96,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,
@@ -284,27 +338,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> {
@@ -611,12 +644,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,
@@ -629,7 +662,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,
@@ -639,11 +672,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,
@@ -653,41 +686,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())
}
}
@@ -700,40 +731,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,
@@ -744,11 +744,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,
@@ -760,7 +760,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,
@@ -771,11 +771,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,
@@ -790,7 +790,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,
@@ -799,10 +799,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,
@@ -813,6 +813,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) }
@@ -926,7 +955,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());
@@ -941,7 +970,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::<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();
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;