Merge pull request #32 from spacejam/tyler_nuke_DBResult

nuke db result
master
Tyler Neely 9 years ago
commit ad201263f8
  1. 1
      .gitignore
  2. 2
      Cargo.toml
  3. 18
      README.md
  4. 2
      src/lib.rs
  5. 40
      src/main.rs
  6. 25
      src/merge_operator.rs
  7. 106
      src/rocksdb.rs
  8. 21
      test/test_column_family.rs
  9. 4
      test/test_multithreaded.rs

1
.gitignore vendored

@ -2,3 +2,4 @@
*.swp
target
Cargo.lock
*.orig

@ -2,7 +2,7 @@
name = "rocksdb"
description = "A Rust wrapper for Facebook's RocksDB embeddable database."
version = "0.1.1"
version = "0.2.0"
authors = ["Tyler Neely <t@jujit.su>", "David Greenberg <dsg123456789@gmail.com>"]
license = "Apache-2.0"
keywords = ["database", "embedded", "LSM-tree", "persistence"]

@ -3,7 +3,7 @@ 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 OSX. The 0.1.1 crate should work with the Rust 1.2 stable and nightly releases as of 9/7/15.
This library has been tested against RocksDB 3.13.1 on linux and OSX. The 0.2.0 crate should work with the Rust 1.4 stable and nightly releases as of 11/7/15.
### status
- [x] basic open/put/get/delete/close
@ -16,6 +16,7 @@ This library has been tested against RocksDB 3.13.1 on linux and OSX. The 0.1.1
- [x] comparator
- [x] snapshot
- [x] column family operations
- [ ] prefix seek
- [ ] slicetransform
- [ ] windows support
@ -35,7 +36,7 @@ sudo make install
###### Cargo.toml
```rust
[dependencies]
rocksdb = "~0.1.1"
rocksdb = "~0.2.0"
```
###### Code
```rust
@ -45,12 +46,11 @@ 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");
db.get(b"my key")
.map( |value| {
println!("retrieved value {}", value.to_utf8().unwrap())
})
.on_absent( || { println!("value not found") })
.on_error( |e| { println!("operational problem encountered: {}", e) });
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");
}
@ -141,7 +141,7 @@ fn main() {
db.merge(b"k1", b"d");
db.merge(b"k1", b"efg");
let r = db.get(b"k1");
assert!(r.unwrap().to_utf8().unwrap() == "abcdefg");
assert!(r.unwrap().unwrap().to_utf8().unwrap() == "abcdefg");
}
```

@ -15,7 +15,7 @@
*/
pub use ffi as rocksdb_ffi;
pub use ffi::{new_bloom_filter, DBCompactionStyle, DBComparator};
pub use rocksdb::{DB, DBResult, DBVector, WriteBatch, Writable, Direction};
pub use rocksdb::{DB, DBVector, WriteBatch, Writable, Direction};
pub use rocksdb_options::{Options, BlockBasedOptions};
pub use merge_operator::MergeOperands;
pub mod rocksdb;

@ -48,16 +48,18 @@ fn main() {
let path = "/tmp/rust-rocksdb";
let db = DB::open_default(path).unwrap();
assert!(db.put(b"my key", b"my value").is_ok());
db.get(b"my key").map( |value| {
match db.get(b"my key") {
Ok(Some(value)) => {
match value.to_utf8() {
Some(v) =>
println!("retrieved utf8 value: {}", v),
None =>
println!("did not read valid utf-8 out of the db"),
Some(v) =>
println!("retrieved utf8 value: {}", v),
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) });
},
Err(e) => println!("error retrieving value: {}", e),
_ => panic!("value not present!"),
}
assert!(db.delete(b"my key").is_ok());
@ -94,17 +96,18 @@ fn custom_merge() {
db.merge(b"k1", b"d").unwrap();
db.merge(b"k1", b"efg").unwrap();
db.merge(b"k1", b"h").unwrap();
db.get(b"k1").map( |value| {
match db.get(b"k1") {
Ok(Some(value)) => {
match value.to_utf8() {
Some(v) =>
println!("retrieved utf8 value: {}", v),
None =>
println!("did not read valid utf-8 out of the db"),
Some(v) =>
println!("retrieved utf8 value: {}", v),
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) });
}
Err(e) => println!("error retrieving value: {}", e),
_ => panic!("value not present!"),
}
}
DB::destroy(&opts, path).is_ok();
}
@ -129,8 +132,7 @@ fn main() {
None => panic!("value corrupted"),
}
})
.on_absent( || { panic!("value not found") })
.on_error( |e| { panic!("error retrieving value: {}", e) });
.or_else( |e| { panic!("error retrieving value: {}", e) });
db.delete(b"k1");
}
}

@ -21,7 +21,7 @@ use std::ptr;
use std::slice;
use rocksdb_options::Options;
use rocksdb::{DB, DBResult, DBVector, Writable};
use rocksdb::{DB, DBVector, Writable};
pub struct MergeOperatorCallback {
pub name: CString,
@ -196,21 +196,24 @@ fn mergetest() {
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 db.get(b"k1") {
Ok(Some(value)) => {
match value.to_utf8() {
Some(v) =>
println!("retrieved utf8 value: {}", v),
None =>
println!("did not read valid utf-8 out of the db"),
Some(v) =>
println!("retrieved utf8 value: {}", v),
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) });
},
Err(e) => { println!("error reading value")},
_ => panic!("value not present"),
}
assert!(m.is_ok());
let r: DBResult<DBVector, String> = db.get(b"k1");
assert!(r.unwrap().to_utf8().unwrap() == "abcdefgh");
let r: Result<Option<DBVector>, String> = db.get(b"k1");
assert!(r.unwrap().unwrap().to_utf8().unwrap() == "abcdefgh");
assert!(db.delete(b"k1").is_ok());
assert!(db.get(b"k1").is_none());
assert!(db.get(b"k1").unwrap().is_none());
}
assert!(DB::destroy(&opts, path).is_ok());
}

@ -327,11 +327,11 @@ impl DB {
return Ok(())
}
pub fn get(&self, key: &[u8]) -> DBResult<DBVector, String> {
pub fn get(&self, key: &[u8]) -> Result<Option<DBVector>, String> {
unsafe {
let readopts = rocksdb_ffi::rocksdb_readoptions_create();
if readopts.0.is_null() {
return DBResult::Error("Unable to create rocksdb read \
return Err("Unable to create rocksdb read \
options. This is a fairly trivial call, and its failure \
may be indicative of a mis-compiled or mis-loaded rocksdb \
library.".to_string());
@ -345,22 +345,22 @@ impl DB {
key.as_ptr(), key.len() as size_t, val_len_ptr, err_ptr) as *mut u8;
rocksdb_ffi::rocksdb_readoptions_destroy(readopts);
if !err.is_null() {
return DBResult::Error(error_message(err));
return Err(error_message(err));
}
match val.is_null() {
true => DBResult::None,
true => Ok(None),
false => {
DBResult::Some(DBVector::from_c(val, val_len))
Ok(Some(DBVector::from_c(val, val_len)))
}
}
}
}
pub fn get_cf(&self, cf: DBCFHandle, key: &[u8]) -> DBResult<DBVector, String> {
pub fn get_cf(&self, cf: DBCFHandle, key: &[u8]) -> Result<Option<DBVector>, String> {
unsafe {
let readopts = rocksdb_ffi::rocksdb_readoptions_create();
if readopts.0.is_null() {
return DBResult::Error("Unable to create rocksdb read \
return Err("Unable to create rocksdb read \
options. This is a fairly trivial call, and its failure \
may be indicative of a mis-compiled or mis-loaded rocksdb \
library.".to_string());
@ -375,12 +375,12 @@ impl DB {
err_ptr) as *mut u8;
rocksdb_ffi::rocksdb_readoptions_destroy(readopts);
if !err.is_null() {
return DBResult::Error(error_message(err));
return Err(error_message(err));
}
match val.is_null() {
true => DBResult::None,
true => Ok(None),
false => {
DBResult::Some(DBVector::from_c(val, val_len))
Ok(Some(DBVector::from_c(val, val_len)))
}
}
}
@ -691,76 +691,6 @@ impl DBVector {
}
}
// DBResult exists because of the inherent difference between
// an operational failure and the absence of a possible result.
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
pub enum DBResult<T, E> {
Some(T),
None,
Error(E),
}
impl <T, E> DBResult<T, E> {
pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> DBResult<U, E> {
match self {
DBResult::Some(x) => DBResult::Some(f(x)),
DBResult::None => DBResult::None,
DBResult::Error(e) => DBResult::Error(e),
}
}
pub fn unwrap(self) -> T {
match self {
DBResult::Some(x) => x,
DBResult::None =>
panic!("Attempted unwrap on DBResult::None"),
DBResult::Error(_) =>
panic!("Attempted unwrap on DBResult::Error"),
}
}
pub fn on_error<U, F: FnOnce(E) -> U>(self, f: F) -> DBResult<T, U> {
match self {
DBResult::Some(x) => DBResult::Some(x),
DBResult::None => DBResult::None,
DBResult::Error(e) => DBResult::Error(f(e)),
}
}
pub fn on_absent<F: FnOnce() -> ()>(self, f: F) -> DBResult<T, E> {
match self {
DBResult::Some(x) => DBResult::Some(x),
DBResult::None => {
f();
DBResult::None
},
DBResult::Error(e) => DBResult::Error(e),
}
}
pub fn is_some(self) -> bool {
match self {
DBResult::Some(_) => true,
DBResult::None => false,
DBResult::Error(_) => false,
}
}
pub fn is_none(self) -> bool {
match self {
DBResult::Some(_) => false,
DBResult::None => true,
DBResult::Error(_) => false,
}
}
pub fn is_error(self) -> bool {
match self {
DBResult::Some(_) => false,
DBResult::None => false,
DBResult::Error(_) => true,
}
}
}
#[test]
fn external() {
let path = "_rust_rocksdb_externaltest";
@ -768,10 +698,10 @@ fn external() {
let mut db = DB::open_default(path).unwrap();
let p = db.put(b"k1", b"v1111");
assert!(p.is_ok());
let r: DBResult<DBVector, String> = db.get(b"k1");
assert!(r.unwrap().to_utf8().unwrap() == "v1111");
let r: Result<Option<DBVector>, String> = db.get(b"k1");
assert!(r.unwrap().unwrap().to_utf8().unwrap() == "v1111");
assert!(db.delete(b"k1").is_ok());
assert!(db.get(b"k1").is_none());
assert!(db.get(b"k1").unwrap().is_none());
}
let opts = Options::new();
let result = DB::destroy(&opts, path);
@ -797,20 +727,20 @@ fn writebatch_works() {
let mut db = DB::open_default(path).unwrap();
{ // test put
let mut batch = WriteBatch::new();
assert!(db.get(b"k1").is_none());
assert!(db.get(b"k1").unwrap().is_none());
batch.put(b"k1", b"v1111");
assert!(db.get(b"k1").is_none());
assert!(db.get(b"k1").unwrap().is_none());
let p = db.write(batch);
assert!(p.is_ok());
let r: DBResult<DBVector, String> = db.get(b"k1");
assert!(r.unwrap().to_utf8().unwrap() == "v1111");
let r: Result<Option<DBVector>, String> = db.get(b"k1");
assert!(r.unwrap().unwrap().to_utf8().unwrap() == "v1111");
}
{ // test delete
let mut batch = WriteBatch::new();
batch.delete(b"k1");
let p = db.write(batch);
assert!(p.is_ok());
assert!(db.get(b"k1").is_none());
assert!(db.get(b"k1").unwrap().is_none());
}
}
let opts = Options::new();

@ -67,7 +67,7 @@ pub fn test_column_family() {
};
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().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();
@ -77,20 +77,23 @@ pub fn test_column_family() {
let m = db.merge_cf(cf1, b"k1", b"h");
println!("m is {:?}", m);
// TODO assert!(m.is_ok());
db.get(b"k1").map( |value| {
match db.get(b"k1") {
Ok(Some(value)) => {
match value.to_utf8() {
Some(v) =>
println!("retrieved utf8 value: {}", v),
None =>
println!("did not read valid utf-8 out of the db"),
Some(v) =>
println!("retrieved utf8 value: {}", v),
None =>
println!("did not read valid utf-8 out of the db"),
}
}).on_absent( || { println!("value not present!") })
.on_error( |_| { println!("error reading value")}); //: {", e) });
},
Err(e) => println!("error reading value"),
_ => panic!("value not present!"),
}
let _ = db.get_cf(cf1, b"k1");
// TODO assert!(r.unwrap().to_utf8().unwrap() == "abcdefgh");
assert!(db.delete(b"k1").is_ok());
assert!(db.get(b"k1").is_none());
assert!(db.get(b"k1").unwrap().is_none());
}
// TODO should be able to use writebatch ops with a cf
{

@ -1,4 +1,4 @@
use rocksdb::{Options, DB, Writable, DBResult};
use rocksdb::{Options, DB, Writable};
use std::thread;
use std::sync::Arc;
@ -31,7 +31,7 @@ pub fn test_multithreaded() {
let j3 = thread::spawn(move|| {
for _ in 1..N {
match db3.get(b"key") {
DBResult::Some(v) => {
Ok(Some(v)) => {
if &v[..] != b"value1" && &v[..] != b"value2" {
assert!(false);
}

Loading…
Cancel
Save