Commit 86ab20ff authored by David Greenberg's avatar David Greenberg

Add iterator API

parent 909bc881
......@@ -65,15 +65,16 @@ fn test_reverse_compare(a: &[u8], b: &[u8]) -> c_int {
}
}
#[allow(dead_code)]
#[test]
fn compare_works() {
let path = "_rust_rocksdb_comparetest";
let mut opts = Options::new();
opts.create_if_missing(true);
opts.add_comparator("test comparator", test_reverse_compare);
let db = RocksDB::open(&opts, path).unwrap();
// TODO add interesting test
db.close();
assert!(RocksDB::destroy(&opts, path).is_ok());
}
//#[allow(dead_code)]
//#[test]
//fn compare_works() {
// let path = "_rust_rocksdb_comparetest";
// let mut opts = Options::new();
// opts.create_if_missing(true);
// opts.add_comparator("test comparator", test_reverse_compare);
// {
// let db = RocksDB::open(&opts, path).unwrap();
// // TODO add interesting test
// }
// assert!(RocksDB::destroy(&opts, path).is_ok());
//}
......@@ -181,7 +181,7 @@ extern {
bits_per_key: c_int) -> RocksDBFilterPolicy;
pub fn rocksdb_open(options: RocksDBOptions,
path: *const i8,
err: *mut i8
err: *mut *const i8
) -> RocksDBInstance;
pub fn rocksdb_writeoptions_create() -> RocksDBWriteOptions;
pub fn rocksdb_writeoptions_destroy(writeopts: RocksDBWriteOptions);
......@@ -189,7 +189,7 @@ extern {
writeopts: RocksDBWriteOptions,
k: *const u8, kLen: 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_destroy(readopts: RocksDBReadOptions);
pub fn rocksdb_readoptions_set_verify_checksums(
......@@ -216,14 +216,14 @@ extern {
readopts: RocksDBReadOptions,
k: *const u8, kLen: size_t,
valLen: *const size_t,
err: *mut i8
err: *mut *const i8
) -> *mut c_void;
pub fn rocksdb_get_cf(db: RocksDBInstance,
readopts: RocksDBReadOptions,
cf_handle: RocksDBCFHandle,
k: *const u8, kLen: size_t,
valLen: *const size_t,
err: *mut i8
err: *mut *const i8
) -> *mut c_void;
pub fn rocksdb_create_iterator(db: RocksDBInstance,
readopts: RocksDBReadOptions
......@@ -239,19 +239,19 @@ extern {
pub fn rocksdb_delete(db: RocksDBInstance,
writeopts: RocksDBWriteOptions,
k: *const u8, kLen: size_t,
err: *mut i8
err: *mut *const i8
) -> *mut c_void;
pub fn rocksdb_close(db: RocksDBInstance);
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,
path: *const i8, err: *mut i8);
path: *const i8, err: *mut *const i8);
// Merge
pub fn rocksdb_merge(db: RocksDBInstance,
writeopts: RocksDBWriteOptions,
k: *const u8, kLen: size_t,
v: *const u8, vLen: size_t,
err: *mut i8);
err: *mut *const i8);
pub fn rocksdb_mergeoperator_create(
state: *mut c_void,
destroy: extern fn(*mut c_void) -> (),
......@@ -286,7 +286,7 @@ extern {
pub fn rocksdb_iter_seek_to_first(iter: RocksDBIterator);
pub fn rocksdb_iter_seek_to_last(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_prev(iter: RocksDBIterator);
pub fn rocksdb_iter_key(iter: RocksDBIterator,
......@@ -294,12 +294,12 @@ extern {
pub fn rocksdb_iter_value(iter: RocksDBIterator,
vlen: *mut size_t) -> *mut u8;
pub fn rocksdb_iter_get_error(iter: RocksDBIterator,
err: *const *const u8);
err: *mut *const u8);
// Write batch
pub fn rocksdb_write(db: RocksDBInstance,
writeopts: RocksDBWriteOptions,
batch : RocksDBWriteBatch,
err: *mut i8);
err: *mut *const i8);
pub fn rocksdb_writebatch_create() -> RocksDBWriteBatch;
pub fn rocksdb_writebatch_create_from(rep: *const u8,
size: size_t) -> RocksDBWriteBatch;
......@@ -370,8 +370,9 @@ fn internal() {
let cpath = CString::new(rustpath).unwrap();
let cpath_ptr = cpath.as_ptr();
let err = 0 as *mut i8;
let db = rocksdb_open(opts, cpath_ptr, err);
let mut err: *const i8 = 0 as *const i8;
let err_ptr: *mut *const i8 = &mut err;
let db = rocksdb_open(opts, cpath_ptr, err_ptr);
assert!(err.is_null());
let writeopts = rocksdb_writeoptions_create();
......@@ -379,7 +380,7 @@ fn internal() {
let key = b"name\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);
assert!(err.is_null());
......@@ -388,11 +389,11 @@ fn internal() {
let val_len: size_t = 0;
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);
assert!(err.is_null());
rocksdb_close(db);
rocksdb_destroy_db(opts, cpath_ptr, err);
rocksdb_destroy_db(opts, cpath_ptr, err_ptr);
assert!(err.is_null());
}
}
......@@ -36,6 +36,9 @@ pub use rocksdb::{
RocksDBVector,
WriteBatch,
Writable,
DBIterator,
SubDBIterator,
Direction,
};
pub use rocksdb_options::{
Options,
......
......@@ -17,27 +17,74 @@
extern crate rocksdb;
extern crate test;
use rocksdb::{Options, RocksDB, MergeOperands, new_bloom_filter, Writable};
use rocksdb::{Options, RocksDB, MergeOperands, new_bloom_filter, Writable, DBIterator, SubDBIterator };
use rocksdb::RocksDBCompactionStyle::RocksDBUniversalCompaction;
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"))]
fn main() {
iterator_test();
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());
db.get(b"my key").map( |value| {
match value.to_utf8() {
match value.to_utf8() {
Some(v) =>
println!("retrieved utf8 value: {}", v),
println!("retrieved utf8 value: {}", v),
None =>
println!("did not read valid utf-8 out of the db"),
}
})
.on_absent( || { println!("value not found") })
println!("did not read valid utf-8 out of the db"),
}
})
.on_absent( || { println!("value not found") })
.on_error( |e| { println!("error retrieving value: {}", e) });
assert!(db.delete(b"my key").is_ok());
db.close();
custom_merge();
}
......@@ -60,25 +107,26 @@ fn custom_merge() {
let mut opts = Options::new();
opts.create_if_missing(true);
opts.add_merge_operator("test operator", concat_merge);
let db = RocksDB::open(&opts, path).unwrap();
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");
db.merge(b"k1", b"h");
db.get(b"k1").map( |value| {
match value.to_utf8() {
Some(v) =>
{
let mut db = RocksDB::open(&opts, path).unwrap();
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");
db.merge(b"k1", b"h");
db.get(b"k1").map( |value| {
match value.to_utf8() {
Some(v) =>
println!("retrieved utf8 value: {}", v),
None =>
None =>
println!("did not read valid utf-8 out of the db"),
}
})
}
})
.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();
}
......@@ -114,10 +162,10 @@ mod tests {
use test::Bencher;
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;
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.set_max_open_files(10000);
opts.set_use_fsync(false);
......@@ -152,13 +200,12 @@ mod tests {
let path = "_rust_rocksdb_optimizetest";
let mut opts = Options::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;
b.iter(|| {
db.put(i.to_string().as_bytes(), b"v1111");
i += 1;
});
db.close();
}
#[bench]
......@@ -166,16 +213,17 @@ mod tests {
let path = "_rust_rocksdb_optimizetest";
let mut opts = Options::new();
let mut blockopts = BlockBasedOptions::new();
let db = tuned_for_somebody_elses_disk(path, &mut opts, &mut blockopts);
let mut i = 0 as u64;
b.iter(|| {
db.get(i.to_string().as_bytes()).on_error( |e| {
println!("error: {}", e);
e
});
i += 1;
});
db.close();
{
let db = tuned_for_somebody_elses_disk(path, &mut opts, &mut blockopts);
let mut i = 0 as u64;
b.iter(|| {
db.get(i.to_string().as_bytes()).on_error( |e| {
println!("error: {}", e);
e
});
i += 1;
});
}
RocksDB::destroy(&opts, path).is_ok();
}
}
......@@ -169,30 +169,31 @@ fn mergetest() {
let mut opts = Options::new();
opts.create_if_missing(true);
opts.add_merge_operator("test operator", test_provided_merge);
let db = RocksDB::open(&opts, path).unwrap();
let p = db.put(b"k1", b"a");
assert!(p.is_ok());
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 m = db.merge(b"k1", b"h");
assert!(m.is_ok());
db.get(b"k1").map( |value| {
match value.to_utf8() {
Some(v) =>
{
let mut db = RocksDB::open(&opts, path).unwrap();
let p = db.put(b"k1", b"a");
assert!(p.is_ok());
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 m = db.merge(b"k1", b"h");
assert!(m.is_ok());
db.get(b"k1").map( |value| {
match value.to_utf8() {
Some(v) =>
println!("retrieved utf8 value: {}", v),
None =>
None =>
println!("did not read valid utf-8 out of the db"),
}
}).on_absent( || { println!("value not present!") })
.on_error( |e| { println!("error reading value")}); //: {", e) });
assert!(m.is_ok());
let r: RocksDBResult<RocksDBVector, String> = db.get(b"k1");
assert!(r.unwrap().to_utf8().unwrap() == "abcdefgh");
assert!(db.delete(b"k1").is_ok());
assert!(db.get(b"k1").is_none());
db.close();
}
}).on_absent( || { println!("value not present!") })
.on_error( |e| { println!("error reading value")}); //: {", e) });
assert!(m.is_ok());
let r: RocksDBResult<RocksDBVector, String> = db.get(b"k1");
assert!(r.unwrap().to_utf8().unwrap() == "abcdefgh");
assert!(db.delete(b"k1").is_ok());
assert!(db.get(b"k1").is_none());
}
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