Fix a few memory leaks. Add valgrind feature for conditionally building a testable binary. Get rid of unstable vector usage.

master
Tyler Neely 10 years ago
parent 14dc3d00dd
commit 8d5b1e4c6c
  1. 4
      Cargo.toml
  2. 4
      README.md
  3. 14
      src/ffi.rs
  4. 1
      src/lib.rs
  5. 32
      src/main.rs
  6. 4
      src/merge_operator.rs
  7. 15
      src/rocksdb.rs

@ -5,3 +5,7 @@ description = "A Rust wrapper for Facebook's RocksDB embeddable database."
version = "0.0.5" version = "0.0.5"
authors = ["Tyler Neely <t@jujit.su>"] authors = ["Tyler Neely <t@jujit.su>"]
license = "Apache-2.0" license = "Apache-2.0"
[features]
default=[]
valgrind=[]

@ -45,9 +45,9 @@ use rocksdb::{RocksDBOptions, RocksDB, MergeOperands};
fn concat_merge(new_key: &[u8], existing_val: Option<&[u8]>, fn concat_merge(new_key: &[u8], existing_val: Option<&[u8]>,
operands: &mut MergeOperands) -> Vec<u8> { operands: &mut MergeOperands) -> Vec<u8> {
let mut result: Vec<u8> = Vec::with_capacity(operands.size_hint().0); let mut result: Vec<u8> = Vec::with_capacity(operands.size_hint().0);
existing_val.map(|v| { result.push_all(v) }); existing_val.map(|v| { result.extend(v) });
for op in operands { for op in operands {
result.push_all(op); result.extend(op);
} }
result result
} }

@ -180,12 +180,14 @@ extern {
err: *mut i8 err: *mut 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_put(db: RocksDBInstance, pub fn rocksdb_put(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 i8);
pub fn rocksdb_readoptions_create() -> RocksDBReadOptions; pub fn rocksdb_readoptions_create() -> RocksDBReadOptions;
pub fn rocksdb_readoptions_destroy(readopts: RocksDBReadOptions);
pub fn rocksdb_readoptions_set_snapshot(read_opts: RocksDBReadOptions, pub fn rocksdb_readoptions_set_snapshot(read_opts: RocksDBReadOptions,
snapshot: RocksDBSnapshot); snapshot: RocksDBSnapshot);
pub fn rocksdb_get(db: RocksDBInstance, pub fn rocksdb_get(db: RocksDBInstance,
@ -338,22 +340,22 @@ fn internal() {
assert!(err.is_null()); assert!(err.is_null());
let writeopts = rocksdb_writeoptions_create(); let writeopts = rocksdb_writeoptions_create();
let RocksDBWriteOptions(write_opt_ptr) = writeopts; assert!(!writeopts.0.is_null());
assert!(!write_opt_ptr.is_null());
let key = b"name\x00"; let key = b"name\x00";
let val = b"spacejam\x00"; let val = b"spacejam\x00";
rocksdb_put(db, writeopts, key.as_ptr(), 4, val.as_ptr(), 8, err); rocksdb_put(db, writeopts.clone(), key.as_ptr(), 4, val.as_ptr(), 8, err);
rocksdb_writeoptions_destroy(writeopts);
assert!(err.is_null()); assert!(err.is_null());
let readopts = rocksdb_readoptions_create(); let readopts = rocksdb_readoptions_create();
let RocksDBReadOptions(read_opts_ptr) = readopts; assert!(!readopts.0.is_null());
assert!(!read_opts_ptr.is_null());
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, key.as_ptr(), 4, val_len_ptr, err); rocksdb_get(db, readopts.clone(), key.as_ptr(), 4, val_len_ptr, err);
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);

@ -19,7 +19,6 @@
#![feature(unique)] #![feature(unique)]
#![feature(path_ext)] #![feature(path_ext)]
#![feature(raw)] #![feature(raw)]
#![feature(vec_push_all)]
pub use ffi as rocksdb_ffi; pub use ffi as rocksdb_ffi;
pub use ffi::{ pub use ffi::{

@ -14,13 +14,13 @@
limitations under the License. limitations under the License.
*/ */
#![feature(test)] #![feature(test)]
#![feature(vec_push_all)]
extern crate rocksdb; extern crate rocksdb;
extern crate test; extern crate test;
use rocksdb::{RocksDBOptions, RocksDB, MergeOperands, new_bloom_filter, Writable}; use rocksdb::{RocksDBOptions, RocksDB, MergeOperands, new_bloom_filter, Writable};
use rocksdb::RocksDBCompactionStyle::RocksDBUniversalCompaction; use rocksdb::RocksDBCompactionStyle::RocksDBUniversalCompaction;
#[cfg(not(feature = "valgrind"))]
fn main() { fn main() {
let path = "/tmp/rust-rocksdb"; let path = "/tmp/rust-rocksdb";
let db = RocksDB::open_default(path).unwrap(); let db = RocksDB::open_default(path).unwrap();
@ -46,11 +46,11 @@ fn concat_merge(new_key: &[u8], existing_val: Option<&[u8]>,
mut operands: &mut MergeOperands) -> Vec<u8> { mut operands: &mut MergeOperands) -> Vec<u8> {
let mut result: Vec<u8> = Vec::with_capacity(operands.size_hint().0); let mut result: Vec<u8> = Vec::with_capacity(operands.size_hint().0);
match existing_val { match existing_val {
Some(v) => result.push_all(v), Some(v) => result.extend(v),
None => (), None => (),
} }
for op in operands { for op in operands {
result.push_all(op); result.extend(op);
} }
result result
} }
@ -82,6 +82,32 @@ fn custom_merge() {
RocksDB::destroy(opts, path).is_ok(); RocksDB::destroy(opts, path).is_ok();
} }
#[cfg(feature = "valgrind")]
fn main() {
let path = "_rust_rocksdb_valgrind";
let opts = RocksDBOptions::new();
opts.create_if_missing(true);
opts.add_merge_operator("test operator", concat_merge);
let db = RocksDB::open(opts, path).unwrap();
loop {
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) => (),
None => panic!("value corrupted"),
}
})
.on_absent( || { panic!("value not found") })
.on_error( |e| { panic!("error retrieving value: {}", e) });
db.delete(b"k1");
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

@ -153,11 +153,11 @@ fn test_provided_merge(new_key: &[u8], existing_val: Option<&[u8]>,
let nops = operands.size_hint().0; let nops = operands.size_hint().0;
let mut result: Vec<u8> = Vec::with_capacity(nops); let mut result: Vec<u8> = Vec::with_capacity(nops);
match existing_val { match existing_val {
Some(v) => result.push_all(v), Some(v) => result.extend(v),
None => (), None => (),
} }
for op in operands { for op in operands {
result.push_all(op); result.extend(op);
} }
result result
} }

@ -132,7 +132,8 @@ impl RocksDB {
unsafe { unsafe {
let writeopts = rocksdb_ffi::rocksdb_writeoptions_create(); let writeopts = rocksdb_ffi::rocksdb_writeoptions_create();
let err = 0 as *mut i8; let err = 0 as *mut i8;
rocksdb_ffi::rocksdb_write(self.inner, writeopts, batch.inner, err); rocksdb_ffi::rocksdb_write(self.inner, writeopts.clone(), batch.inner, err);
rocksdb_ffi::rocksdb_writeoptions_destroy(writeopts);
if !err.is_null() { if !err.is_null() {
return Err(error_message(err)); return Err(error_message(err));
} }
@ -153,8 +154,9 @@ impl RocksDB {
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;
let err = 0 as *mut i8; let err = 0 as *mut i8;
let val = rocksdb_ffi::rocksdb_get(self.inner, readopts, let val = rocksdb_ffi::rocksdb_get(self.inner, readopts.clone(),
key.as_ptr(), key.len() as size_t, val_len_ptr, err) as *mut u8; key.as_ptr(), key.len() as size_t, val_len_ptr, err) as *mut u8;
rocksdb_ffi::rocksdb_readoptions_destroy(readopts);
if !err.is_null() { if !err.is_null() {
return RocksDBResult::Error(error_message(err)); return RocksDBResult::Error(error_message(err));
} }
@ -177,9 +179,10 @@ impl Writable for RocksDB {
unsafe { unsafe {
let writeopts = rocksdb_ffi::rocksdb_writeoptions_create(); let writeopts = rocksdb_ffi::rocksdb_writeoptions_create();
let err = 0 as *mut i8; let err = 0 as *mut i8;
rocksdb_ffi::rocksdb_put(self.inner, writeopts, key.as_ptr(), rocksdb_ffi::rocksdb_put(self.inner, writeopts.clone(), key.as_ptr(),
key.len() as size_t, value.as_ptr(), key.len() as size_t, value.as_ptr(),
value.len() as size_t, err); value.len() as size_t, err);
rocksdb_ffi::rocksdb_writeoptions_destroy(writeopts);
if !err.is_null() { if !err.is_null() {
return Err(error_message(err)); return Err(error_message(err));
} }
@ -191,9 +194,10 @@ impl Writable for RocksDB {
unsafe { unsafe {
let writeopts = rocksdb_ffi::rocksdb_writeoptions_create(); let writeopts = rocksdb_ffi::rocksdb_writeoptions_create();
let err = 0 as *mut i8; let err = 0 as *mut i8;
rocksdb_ffi::rocksdb_merge(self.inner, writeopts, key.as_ptr(), rocksdb_ffi::rocksdb_merge(self.inner, writeopts.clone(), key.as_ptr(),
key.len() as size_t, value.as_ptr(), key.len() as size_t, value.as_ptr(),
value.len() as size_t, err); value.len() as size_t, err);
rocksdb_ffi::rocksdb_writeoptions_destroy(writeopts);
if !err.is_null() { if !err.is_null() {
return Err(error_message(err)); return Err(error_message(err));
} }
@ -205,8 +209,9 @@ impl Writable for RocksDB {
unsafe { unsafe {
let writeopts = rocksdb_ffi::rocksdb_writeoptions_create(); let writeopts = rocksdb_ffi::rocksdb_writeoptions_create();
let err = 0 as *mut i8; let err = 0 as *mut i8;
rocksdb_ffi::rocksdb_delete(self.inner, writeopts, key.as_ptr(), rocksdb_ffi::rocksdb_delete(self.inner, writeopts.clone(), key.as_ptr(),
key.len() as size_t, err); key.len() as size_t, err);
rocksdb_ffi::rocksdb_writeoptions_destroy(writeopts);
if !err.is_null() { if !err.is_null() {
return Err(error_message(err)); return Err(error_message(err));
} }

Loading…
Cancel
Save