Commit b6cf467a authored by Tyler Neely's avatar Tyler Neely

Merge pull request #15 from dgrnbrg/iterator-dev

Add Iterators and Snapshots
parents 90b5421c 3c257391
...@@ -11,9 +11,9 @@ This library has been tested against RocksDB 3.8.1 on linux and OSX. The 0.0.6 ...@@ -11,9 +11,9 @@ This library has been tested against RocksDB 3.8.1 on linux and OSX. The 0.0.6
- [x] compaction filter, style - [x] compaction filter, style
- [x] LRU cache - [x] LRU cache
- [x] destroy/repair - [x] destroy/repair
- [ ] iterator - [x] iterator
- [ ] comparator - [ ] comparator
- [ ] snapshot - [x] snapshot
- [ ] column family operations - [ ] column family operations
- [ ] slicetransform - [ ] slicetransform
- [ ] windows support - [ ] windows support
...@@ -39,7 +39,7 @@ extern crate rocksdb; ...@@ -39,7 +39,7 @@ extern crate rocksdb;
use rocksdb::RocksDB; use rocksdb::RocksDB;
fn main() { fn main() {
let db = RocksDB::open_default("/path/for/rocksdb/storage").unwrap(); let mut db = RocksDB::open_default("/path/for/rocksdb/storage").unwrap();
db.put(b"my key", b"my value"); db.put(b"my key", b"my value");
db.get(b"my key") db.get(b"my key")
.map( |value| { .map( |value| {
...@@ -49,7 +49,58 @@ fn main() { ...@@ -49,7 +49,58 @@ fn main() {
.on_error( |e| { println!("operational problem encountered: {}", e) }); .on_error( |e| { println!("operational problem encountered: {}", e) });
db.delete(b"my key"); db.delete(b"my key");
db.close(); }
```
###### Doing an atomic commit of several writes
```rust
extern crate rocksdb;
use rocksdb::{RocksDB, WriteBatch, Writable};
fn main() {
// NB: db is automatically freed at end of lifetime
let mut db = RocksDB::open_default("/path/for/rocksdb/storage").unwrap();
{
let mut batch = WriteBatch::new(); // 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::{RocksDB, Direction};
fn main() {
// NB: db is automatically freed at end of lifetime
let mut db = RocksDB::open_default("/path/for/rocksdb/storage").unwrap();
let mut iter = db.iterator();
for (key, value) in iter.from_start() { // Always iterates forward
println!("Saw {} {}", key, value); //actually, need to convert [u8] keys into Strings
}
for (key, value) in iter.from_end() { //Always iterates backward
println!("Saw {} {}", key, value);
}
for (key, value) in iter.from(b"my key", Direction::forward) { // From a key in Direction::{forward,reverse}
println!("Saw {} {}", key, value);
}
}
```
###### Getting an Iterator
```rust
extern crate rocksdb;
use rocksdb::{RocksDB, Direction};
fn main() {
// NB: db is automatically freed at end of lifetime
let mut db = RocksDB::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(); // Make as many iterators as you'd like from one snapshot
} }
``` ```
...@@ -73,7 +124,7 @@ fn main() { ...@@ -73,7 +124,7 @@ fn main() {
let opts = RocksDBOptions::new(); let opts = RocksDBOptions::new();
opts.create_if_missing(true); opts.create_if_missing(true);
opts.add_merge_operator("test operator", concat_merge); opts.add_merge_operator("test operator", concat_merge);
let db = RocksDB::open(opts, path).unwrap(); let mut db = RocksDB::open(opts, path).unwrap();
let p = db.put(b"k1", b"a"); let p = db.put(b"k1", b"a");
db.merge(b"k1", b"b"); db.merge(b"k1", b"b");
db.merge(b"k1", b"c"); db.merge(b"k1", b"c");
...@@ -81,7 +132,6 @@ fn main() { ...@@ -81,7 +132,6 @@ fn main() {
db.merge(b"k1", b"efg"); db.merge(b"k1", b"efg");
let r = db.get(b"k1"); let r = db.get(b"k1");
assert!(r.unwrap().to_utf8().unwrap() == "abcdefg"); assert!(r.unwrap().to_utf8().unwrap() == "abcdefg");
db.close();
} }
``` ```
......
...@@ -65,15 +65,16 @@ fn test_reverse_compare(a: &[u8], b: &[u8]) -> c_int { ...@@ -65,15 +65,16 @@ fn test_reverse_compare(a: &[u8], b: &[u8]) -> c_int {
} }
} }
#[allow(dead_code)] //#[allow(dead_code)]
#[test] //#[test]
fn compare_works() { //fn compare_works() {
let path = "_rust_rocksdb_comparetest"; // let path = "_rust_rocksdb_comparetest";
let mut opts = Options::new(); // let mut opts = Options::new();
opts.create_if_missing(true); // opts.create_if_missing(true);
opts.add_comparator("test comparator", test_reverse_compare); // opts.add_comparator("test comparator", test_reverse_compare);
let db = RocksDB::open(&opts, path).unwrap(); // {
// TODO add interesting test // let db = RocksDB::open(&opts, path).unwrap();
db.close(); // // TODO add interesting test
assert!(RocksDB::destroy(&opts, path).is_ok()); // }
} // assert!(RocksDB::destroy(&opts, path).is_ok());
//}
...@@ -181,7 +181,7 @@ extern { ...@@ -181,7 +181,7 @@ extern {
bits_per_key: c_int) -> RocksDBFilterPolicy; bits_per_key: c_int) -> RocksDBFilterPolicy;
pub fn rocksdb_open(options: RocksDBOptions, pub fn rocksdb_open(options: RocksDBOptions,
path: *const i8, path: *const i8,
err: *mut i8 err: *mut *const i8
) -> RocksDBInstance; ) -> RocksDBInstance;
pub fn rocksdb_writeoptions_create() -> RocksDBWriteOptions; pub fn rocksdb_writeoptions_create() -> RocksDBWriteOptions;
pub fn rocksdb_writeoptions_destroy(writeopts: RocksDBWriteOptions); pub fn rocksdb_writeoptions_destroy(writeopts: RocksDBWriteOptions);
...@@ -189,7 +189,7 @@ extern { ...@@ -189,7 +189,7 @@ extern {
writeopts: RocksDBWriteOptions, writeopts: RocksDBWriteOptions,
k: *const u8, kLen: size_t, k: *const u8, kLen: size_t,
v: *const u8, vLen: size_t, v: *const u8, vLen: size_t,
err: *mut i8); err: *mut *const i8);
pub fn rocksdb_readoptions_create() -> RocksDBReadOptions; pub fn rocksdb_readoptions_create() -> RocksDBReadOptions;
pub fn rocksdb_readoptions_destroy(readopts: RocksDBReadOptions); pub fn rocksdb_readoptions_destroy(readopts: RocksDBReadOptions);
pub fn rocksdb_readoptions_set_verify_checksums( pub fn rocksdb_readoptions_set_verify_checksums(
...@@ -216,14 +216,14 @@ extern { ...@@ -216,14 +216,14 @@ extern {
readopts: RocksDBReadOptions, readopts: RocksDBReadOptions,
k: *const u8, kLen: size_t, k: *const u8, kLen: size_t,
valLen: *const size_t, valLen: *const size_t,
err: *mut i8 err: *mut *const i8
) -> *mut c_void; ) -> *mut c_void;
pub fn rocksdb_get_cf(db: RocksDBInstance, pub fn rocksdb_get_cf(db: RocksDBInstance,
readopts: RocksDBReadOptions, readopts: RocksDBReadOptions,
cf_handle: RocksDBCFHandle, cf_handle: RocksDBCFHandle,
k: *const u8, kLen: size_t, k: *const u8, kLen: size_t,
valLen: *const size_t, valLen: *const size_t,
err: *mut i8 err: *mut *const i8
) -> *mut c_void; ) -> *mut c_void;
pub fn rocksdb_create_iterator(db: RocksDBInstance, pub fn rocksdb_create_iterator(db: RocksDBInstance,
readopts: RocksDBReadOptions readopts: RocksDBReadOptions
...@@ -239,19 +239,19 @@ extern { ...@@ -239,19 +239,19 @@ extern {
pub fn rocksdb_delete(db: RocksDBInstance, pub fn rocksdb_delete(db: RocksDBInstance,
writeopts: RocksDBWriteOptions, writeopts: RocksDBWriteOptions,
k: *const u8, kLen: size_t, k: *const u8, kLen: size_t,
err: *mut i8 err: *mut *const i8
) -> *mut c_void; ) -> *mut c_void;
pub fn rocksdb_close(db: RocksDBInstance); pub fn rocksdb_close(db: RocksDBInstance);
pub fn rocksdb_destroy_db(options: RocksDBOptions, pub fn rocksdb_destroy_db(options: RocksDBOptions,
path: *const i8, err: *mut i8); path: *const i8, err: *mut *const i8);
pub fn rocksdb_repair_db(options: RocksDBOptions, pub fn rocksdb_repair_db(options: RocksDBOptions,
path: *const i8, err: *mut i8); path: *const i8, err: *mut *const i8);
// Merge // Merge
pub fn rocksdb_merge(db: RocksDBInstance, pub fn rocksdb_merge(db: RocksDBInstance,
writeopts: RocksDBWriteOptions, writeopts: RocksDBWriteOptions,
k: *const u8, kLen: size_t, k: *const u8, kLen: size_t,
v: *const u8, vLen: size_t, v: *const u8, vLen: size_t,
err: *mut i8); err: *mut *const i8);
pub fn rocksdb_mergeoperator_create( pub fn rocksdb_mergeoperator_create(
state: *mut c_void, state: *mut c_void,
destroy: extern fn(*mut c_void) -> (), destroy: extern fn(*mut c_void) -> (),
...@@ -286,7 +286,7 @@ extern { ...@@ -286,7 +286,7 @@ extern {
pub fn rocksdb_iter_seek_to_first(iter: RocksDBIterator); pub fn rocksdb_iter_seek_to_first(iter: RocksDBIterator);
pub fn rocksdb_iter_seek_to_last(iter: RocksDBIterator); pub fn rocksdb_iter_seek_to_last(iter: RocksDBIterator);
pub fn rocksdb_iter_seek(iter: RocksDBIterator, pub fn rocksdb_iter_seek(iter: RocksDBIterator,
key: *mut u8, klen: size_t); key: *const u8, klen: size_t);
pub fn rocksdb_iter_next(iter: RocksDBIterator); pub fn rocksdb_iter_next(iter: RocksDBIterator);
pub fn rocksdb_iter_prev(iter: RocksDBIterator); pub fn rocksdb_iter_prev(iter: RocksDBIterator);
pub fn rocksdb_iter_key(iter: RocksDBIterator, pub fn rocksdb_iter_key(iter: RocksDBIterator,
...@@ -294,12 +294,12 @@ extern { ...@@ -294,12 +294,12 @@ extern {
pub fn rocksdb_iter_value(iter: RocksDBIterator, pub fn rocksdb_iter_value(iter: RocksDBIterator,
vlen: *mut size_t) -> *mut u8; vlen: *mut size_t) -> *mut u8;
pub fn rocksdb_iter_get_error(iter: RocksDBIterator, pub fn rocksdb_iter_get_error(iter: RocksDBIterator,
err: *const *const u8); err: *mut *const u8);
// Write batch // Write batch
pub fn rocksdb_write(db: RocksDBInstance, pub fn rocksdb_write(db: RocksDBInstance,
writeopts: RocksDBWriteOptions, writeopts: RocksDBWriteOptions,
batch : RocksDBWriteBatch, batch : RocksDBWriteBatch,
err: *mut i8); err: *mut *const i8);
pub fn rocksdb_writebatch_create() -> RocksDBWriteBatch; pub fn rocksdb_writebatch_create() -> RocksDBWriteBatch;
pub fn rocksdb_writebatch_create_from(rep: *const u8, pub fn rocksdb_writebatch_create_from(rep: *const u8,
size: size_t) -> RocksDBWriteBatch; size: size_t) -> RocksDBWriteBatch;
...@@ -370,8 +370,9 @@ fn internal() { ...@@ -370,8 +370,9 @@ fn internal() {
let cpath = CString::new(rustpath).unwrap(); let cpath = CString::new(rustpath).unwrap();
let cpath_ptr = cpath.as_ptr(); let cpath_ptr = cpath.as_ptr();
let err = 0 as *mut i8; let mut err: *const i8 = 0 as *const i8;
let db = rocksdb_open(opts, cpath_ptr, err); let err_ptr: *mut *const i8 = &mut err;
let db = rocksdb_open(opts, cpath_ptr, err_ptr);
assert!(err.is_null()); assert!(err.is_null());
let writeopts = rocksdb_writeoptions_create(); let writeopts = rocksdb_writeoptions_create();
...@@ -379,7 +380,7 @@ fn internal() { ...@@ -379,7 +380,7 @@ fn internal() {
let key = b"name\x00"; let key = b"name\x00";
let val = b"spacejam\x00"; let val = b"spacejam\x00";
rocksdb_put(db, writeopts.clone(), key.as_ptr(), 4, val.as_ptr(), 8, err); rocksdb_put(db, writeopts.clone(), key.as_ptr(), 4, val.as_ptr(), 8, err_ptr);
rocksdb_writeoptions_destroy(writeopts); rocksdb_writeoptions_destroy(writeopts);
assert!(err.is_null()); assert!(err.is_null());
...@@ -388,11 +389,11 @@ fn internal() { ...@@ -388,11 +389,11 @@ fn internal() {
let val_len: size_t = 0; let val_len: size_t = 0;
let val_len_ptr = &val_len as *const size_t; let val_len_ptr = &val_len as *const size_t;
rocksdb_get(db, readopts.clone(), key.as_ptr(), 4, val_len_ptr, err); rocksdb_get(db, readopts.clone(), key.as_ptr(), 4, val_len_ptr, err_ptr);
rocksdb_readoptions_destroy(readopts); rocksdb_readoptions_destroy(readopts);
assert!(err.is_null()); assert!(err.is_null());
rocksdb_close(db); rocksdb_close(db);
rocksdb_destroy_db(opts, cpath_ptr, err); rocksdb_destroy_db(opts, cpath_ptr, err_ptr);
assert!(err.is_null()); assert!(err.is_null());
} }
} }
...@@ -23,11 +23,7 @@ ...@@ -23,11 +23,7 @@
pub use ffi as rocksdb_ffi; pub use ffi as rocksdb_ffi;
pub use ffi::{ pub use ffi::{
new_bloom_filter, new_bloom_filter,
new_cache,
RocksDBUniversalCompactionStyle,
RocksDBCompactionStyle, RocksDBCompactionStyle,
RocksDBCompressionType,
RocksDBSnapshot,
RocksDBComparator, RocksDBComparator,
}; };
pub use rocksdb::{ pub use rocksdb::{
...@@ -36,6 +32,7 @@ pub use rocksdb::{ ...@@ -36,6 +32,7 @@ pub use rocksdb::{
RocksDBVector, RocksDBVector,
WriteBatch, WriteBatch,
Writable, Writable,
Direction,
}; };
pub use rocksdb_options::{ pub use rocksdb_options::{
Options, Options,
......
...@@ -17,27 +17,103 @@ ...@@ -17,27 +17,103 @@
extern crate rocksdb; extern crate rocksdb;
extern crate test; extern crate test;
use rocksdb::{Options, RocksDB, MergeOperands, new_bloom_filter, Writable}; use rocksdb::{Options, RocksDB, MergeOperands, new_bloom_filter, Writable, };
use rocksdb::RocksDBCompactionStyle::RocksDBUniversalCompaction; use rocksdb::RocksDBCompactionStyle::RocksDBUniversalCompaction;
fn snapshot_test() {
let path = "_rust_rocksdb_iteratortest";
{
let mut db = RocksDB::open_default(path).unwrap();
let p = db.put(b"k1", b"v1111");
assert!(p.is_ok());
let p = db.put(b"k2", b"v2222");
assert!(p.is_ok());
let p = db.put(b"k3", b"v3333");
assert!(p.is_ok());
let mut snap = db.snapshot();
let mut view1 = snap.iterator();
println!("See the output of the first iter");
for (k,v) in view1.from_start() {
println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap());
};
for (k,v) in view1.from_start() {
println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap());
};
for (k,v) in view1.from_end() {
println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap());
};
}
let opts = Options::new();
assert!(RocksDB::destroy(&opts, path).is_ok());
}
fn iterator_test() {
let path = "_rust_rocksdb_iteratortest";
{
let mut db = RocksDB::open_default(path).unwrap();
let p = db.put(b"k1", b"v1111");
assert!(p.is_ok());
let p = db.put(b"k2", b"v2222");
assert!(p.is_ok());
let p = db.put(b"k3", b"v3333");
assert!(p.is_ok());
{
let mut view1 = db.iterator();
println!("See the output of the first iter");
for (k,v) in view1.from_start() {
println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap());
};
for (k,v) in view1.from_start() {
println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap());
};
for (k,v) in view1.from_end() {
println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap());
};
}
let mut view2 = db.iterator();
let p = db.put(b"k4", b"v4444");
assert!(p.is_ok());
let mut view3 = db.iterator();
println!("See the output of the second iter");
for (k,v) in view2.from_start() {
println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap());
}
println!("See the output of the third iter");
for (k,v) in view3.from_start() {
println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap());
}
println!("now the 3rd iter from k2 fwd");
for (k,v) in view3.from(b"k2", rocksdb::Direction::forward) {
println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap());
}
println!("now the 3rd iter from k2 and back");
for (k,v) in view3.from(b"k2", rocksdb::Direction::reverse) {
println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap());
}
}
let opts = Options::new();
assert!(RocksDB::destroy(&opts, path).is_ok());
}
#[cfg(not(feature = "valgrind"))] #[cfg(not(feature = "valgrind"))]
fn main() { fn main() {
snapshot_test();
iterator_test();
let path = "/tmp/rust-rocksdb"; let path = "/tmp/rust-rocksdb";
let db = RocksDB::open_default(path).unwrap(); let mut db = RocksDB::open_default(path).unwrap();
assert!(db.put(b"my key", b"my value").is_ok()); assert!(db.put(b"my key", b"my value").is_ok());
db.get(b"my key").map( |value| { db.get(b"my key").map( |value| {
match value.to_utf8() { match value.to_utf8() {
Some(v) => Some(v) =>
println!("retrieved utf8 value: {}", v), println!("retrieved utf8 value: {}", v),
None => None =>
println!("did not read valid utf-8 out of the db"), println!("did not read valid utf-8 out of the db"),
} }
}) })
.on_absent( || { println!("value not found") }) .on_absent( || { println!("value not found") })
.on_error( |e| { println!("error retrieving value: {}", e) }); .on_error( |e| { println!("error retrieving value: {}", e) });
assert!(db.delete(b"my key").is_ok()); assert!(db.delete(b"my key").is_ok());
db.close();
custom_merge(); custom_merge();
} }
...@@ -60,25 +136,26 @@ fn custom_merge() { ...@@ -60,25 +136,26 @@ fn custom_merge() {
let mut opts = Options::new(); let mut opts = Options::new();
opts.create_if_missing(true); opts.create_if_missing(true);
opts.add_merge_operator("test operator", concat_merge); opts.add_merge_operator("test operator", concat_merge);
let db = RocksDB::open(&opts, path).unwrap(); {
db.put(b"k1", b"a"); let mut db = RocksDB::open(&opts, path).unwrap();
db.merge(b"k1", b"b"); db.put(b"k1", b"a");
db.merge(b"k1", b"c"); db.merge(b"k1", b"b");
db.merge(b"k1", b"d"); db.merge(b"k1", b"c");
db.merge(b"k1", b"efg"); db.merge(b"k1", b"d");
db.merge(b"k1", b"h"); db.merge(b"k1", b"efg");
db.get(b"k1").map( |value| { db.merge(b"k1", b"h");
match value.to_utf8() { db.get(b"k1").map( |value| {
Some(v) => match value.to_utf8() {
Some(v) =>
println!("retrieved utf8 value: {}", v), println!("retrieved utf8 value: {}", v),
None => None =>
println!("did not read valid utf-8 out of the db"), println!("did not read valid utf-8 out of the db"),
} }
}) })
.on_absent( || { println!("value not found") }) .on_absent( || { println!("value not found") })
.on_error( |e| { println!("error retrieving value: {}", e) }); .on_error( |e| { println!("error retrieving value: {}", e) });
db.close(); }
RocksDB::destroy(&opts, path).is_ok(); RocksDB::destroy(&opts, path).is_ok();
} }
...@@ -114,10 +191,10 @@ mod tests { ...@@ -114,10 +191,10 @@ mod tests {
use test::Bencher; use test::Bencher;
use std::thread::sleep_ms; use std::thread::sleep_ms;
use rocksdb::{BlockBasedOptions, Options, RocksDB, MergeOperands, new_bloom_filter, Writable}; use rocksdb::{BlockBasedOptions, Options, RocksDB, MergeOperands, new_bloom_filter, Writable };
use rocksdb::RocksDBCompactionStyle::RocksDBUniversalCompaction; use rocksdb::RocksDBCompactionStyle::RocksDBUniversalCompaction;
fn tuned_for_somebody_elses_disk(path: &str, opts: &mut Options, blockopts: &mut BlockBasedOptions) -> RocksDB { fn tuned_for_somebody_elses_disk(path: &str, opts: & mut Options, blockopts: &mut BlockBasedOptions) -> RocksDB {
opts.create_if_missing(true); opts.create_if_missing(true);
opts.set_max_open_files(10000); opts.set_max_open_files(10000);
opts.set_use_fsync(false); opts.set_use_fsync(false);
...@@ -152,13 +229,12 @@ mod tests { ...@@ -152,13 +229,12 @@ mod tests {
let path = "_rust_rocksdb_optimizetest"; let path = "_rust_rocksdb_optimizetest";
let mut opts = Options::new(); let mut opts = Options::new();
let mut blockopts = BlockBasedOptions::new(); let mut blockopts = BlockBasedOptions::new();
let db = tuned_for_somebody_elses_disk(path, &mut opts, &mut blockopts); let mut db = tuned_for_somebody_elses_disk(path, &mut opts, &mut blockopts);
let mut i = 0 as u64; let mut i = 0 as u64;
b.iter(|| { b.iter(|| {
db.put(i.to_string().as_bytes(), b"v1111"); db.put(i.to_string().as_bytes(), b"v1111");
i += 1; i += 1;
}); });
db.close();
} }
#[bench] #[bench]
...@@ -166,16 +242,17 @@ mod tests { ...@@ -166,16 +242,17 @@ mod tests {
let path = "_rust_rocksdb_optimizetest"; let path = "_rust_rocksdb_optimizetest";
let mut opts = Options::new(); let mut opts = Options::new();
let mut blockopts = BlockBasedOptions::new(); let mut blockopts = BlockBasedOptions::new();
let db = tuned_for_somebody_elses_disk(path, &mut opts, &mut blockopts); {
let mut i = 0 as u64; let db = tuned_for_somebody_elses_disk(path, &mut opts, &mut blockopts);
b.iter(|| { let mut i = 0 as u64;
db.get(i.to_string().as_bytes()).on_error( |e| { b.iter(|| {
println!("error: {}", e); db.get(i.to_string().as_bytes()).on_error( |e| {
e println!("error: {}", e);
}); e
i += 1; });
}); i += 1;
db.close(); });
}
RocksDB::destroy(&opts, path).is_ok(); RocksDB::destroy(&opts, path).is_ok();
} }
} }
...@@ -169,30 +169,31 @@ fn mergetest() { ...@@ -169,30 +169,31 @@ fn mergetest() {
let mut opts = Options::new(); let mut opts = Options::new();
opts.create_if_missing(true); opts.create_if_missing(true);
opts.add_merge_operator("test operator", test_provided_merge); opts.add_merge_operator("test operator", test_provided_merge);
let db = RocksDB::open(&opts, path).unwrap(); {
let p = db.put(b"k1", b"a"); let mut db = RocksDB::open(&opts, path).unwrap();
assert!(p.is_ok()); let p = db.put(b"k1", b"a");
db.merge(b"k1", b"b"); assert!(p.is_ok());
db.merge(b"k1", b"c"); db.merge(b"k1", b"b");
db.merge(b"k1", b"d"); db.merge(b"k1", b"c");
db.merge(b"k1", b"efg"); db.merge(b"k1", b"d");
let m = db.merge(b"k1", b"h"); db.merge(b"k1", b"efg");
assert!(m.is_ok()); let m = db.merge(b"k1", b"h");
db.get(b"k1").map( |value| { assert!(m.is_ok());
match value.to_utf8() { db.get(b"k1").map( |value| {
Some(v) => match value.to_utf8() {
Some(v) =>
println!("retrieved utf8 value: {}", v), println!("retrieved utf8 value: {}", v),
None => None =>
println!("did not read valid utf-8 out of the db"), println!("did not read valid utf-8 out of the db"),
} }
}).on_absent( || { println!("value not present!") }) }).on_absent( || { println!("value not present!") })
.on_error( |e| { println!("error reading value")}); //: {", e) }); .on_error( |e| { println!("error reading value")}); //: {", e) });
assert!(m.is_ok()); assert!(m.is_ok());
let r: RocksDBResult<RocksDBVector, String> = db.get(b"k1"); let r: RocksDBResult<RocksDBVector, String> = db.get(b"k1");
assert!(r.unwrap().to_utf8().unwrap() == "abcdefgh"); assert!(r.unwrap().to_utf8().unwrap() == "abcdefgh");
assert!(db.delete(b"k1").is_ok()); assert!(db.delete(b"k1").is_ok());
assert!(db.get(b"k1").is_none()); assert!(db.get(b"k1").is_none());
db.close(); }
assert!(RocksDB::destroy(&opts, path).is_ok()); assert!(RocksDB::destroy(&opts, path).is_ok());
} }
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment