Fix pointer use for opening column families.

master
Tyler Neely 9 years ago
parent 520d9cef43
commit 4db1723001
  1. 4
      src/ffi.rs
  2. 78
      src/rocksdb.rs
  3. 4
      test/test_column_family.rs

@ -359,8 +359,8 @@ extern {
path: *const i8, path: *const i8,
num_column_families: c_int, num_column_families: c_int,
column_family_names: *const *const i8, column_family_names: *const *const i8,
column_family_options: *const [RocksDBOptions], column_family_options: *const RocksDBOptions,
column_family_handles: *mut *const RocksDBCFHandle, column_family_handles: *const RocksDBCFHandle,
err: *mut *const i8 err: *mut *const i8
) -> RocksDBInstance; ) -> RocksDBInstance;
pub fn rocksdb_create_column_family(db: RocksDBInstance, pub fn rocksdb_create_column_family(db: RocksDBInstance,

@ -16,6 +16,7 @@
extern crate libc; extern crate libc;
use self::libc::{c_void, size_t}; use self::libc::{c_void, size_t};
use std::collections::BTreeMap;
use std::ffi::{CString, CStr}; use std::ffi::{CString, CStr};
use std::fs::{self, PathExt}; use std::fs::{self, PathExt};
use std::ops::Deref; use std::ops::Deref;
@ -29,7 +30,7 @@ use rocksdb_options::Options;
pub struct RocksDB { pub struct RocksDB {
inner: rocksdb_ffi::RocksDBInstance, inner: rocksdb_ffi::RocksDBInstance,
cfs: Vec<rocksdb_ffi::RocksDBCFHandle>, cfs: BTreeMap<String, rocksdb_ffi::RocksDBCFHandle>,
} }
unsafe impl Send for RocksDB {} unsafe impl Send for RocksDB {}
@ -184,10 +185,10 @@ impl RocksDB {
} }
pub fn open(opts: &Options, path: &str) -> Result<RocksDB, String> { pub fn open(opts: &Options, path: &str) -> Result<RocksDB, String> {
RocksDB::open_cf(opts, path, vec![]) RocksDB::open_cf(opts, path, &[])
} }
pub fn open_cf(opts: &Options, path: &str, mut cfs: Vec<&str>) -> Result<RocksDB, String> { pub fn open_cf(opts: &Options, path: &str, cfs: &[&str]) -> Result<RocksDB, String> {
let cpath = match CString::new(path.as_bytes()) { let cpath = match CString::new(path.as_bytes()) {
Ok(c) => c, Ok(c) => c,
Err(_) => Err(_) =>
@ -206,39 +207,62 @@ impl RocksDB {
let mut err: *const i8 = 0 as *const i8; let mut err: *const i8 = 0 as *const i8;
let err_ptr: *mut *const i8 = &mut err; let err_ptr: *mut *const i8 = &mut err;
let db: rocksdb_ffi::RocksDBInstance; let db: rocksdb_ffi::RocksDBInstance;
let mut cfMap = BTreeMap::new();
if cfs.len() == 0 { if cfs.len() == 0 {
unsafe { unsafe {
db = rocksdb_ffi::rocksdb_open(opts.inner, cpath_ptr, err_ptr); db = rocksdb_ffi::rocksdb_open(opts.inner, cpath_ptr, err_ptr);
} }
} else { } else {
let nfam = cfs.len(); let mut cfs_v = cfs.to_vec();
let mut cfnames: Vec<*const i8> = vec![]; // Always open the default column family
let mut cfhandles: Vec<rocksdb_ffi::RocksDBCFHandle> = vec![]; if !cfs_v.contains(&"default") {
let mut cfopts: Vec<rocksdb_ffi::RocksDBOptions> = vec![]; cfs_v.push("default");
}
cfs.push("default");
for name in cfs { // We need to store our CStrings in an intermediate vector
match CString::new(name.as_bytes()) { // so that their pointers remain valid.
Ok(c) => { let c_cfs: Vec<CString> = cfs_v.iter().map( |cf| {
cfnames.push(c.as_ptr()); CString::new(cf.as_bytes()).unwrap()
cfhandles.push(rocksdb_ffi::RocksDBCFHandle(0 as *mut c_void)); }).collect();
cfopts.push(Options::new().inner);
}, let cfnames: Vec<*const i8> = c_cfs.iter().map( |cf| {
Err(_) => cf.as_ptr()
return Err("Failed to convert path to CString when opening rocksdb".to_string()), }).collect();
}
}; // These handles will be populated by RocksDB.
let mut cfhandles: Vec<rocksdb_ffi::RocksDBCFHandle> =
cfs_v.iter().map( |_| {
rocksdb_ffi::RocksDBCFHandle(0 as *mut c_void)
}).collect();
// TODO(tyler) allow options to be passed in.
let cfopts: Vec<rocksdb_ffi::RocksDBOptions> = cfs_v.iter().map( |_| {
unsafe { rocksdb_ffi::rocksdb_options_create() }
}).collect();
// Prepare to ship to C.
let names = cfnames.as_slice();
let copts: *const rocksdb_ffi::RocksDBOptions = cfopts.as_ptr();
let handles: *const rocksdb_ffi::RocksDBCFHandle = cfhandles.as_ptr();
let nfam = cfs_v.len();
unsafe { unsafe {
println!("1!");
println!("nfam: {}", nfam);
db = rocksdb_ffi::rocksdb_open_column_families(opts.inner, cpath_ptr, db = rocksdb_ffi::rocksdb_open_column_families(opts.inner, cpath_ptr,
nfam as libc::c_int, nfam as libc::c_int,
cfnames.as_slice().as_ptr(), names.as_ptr(),
cfopts.as_slice(), copts,
cfhandles.as_ptr() as *mut *const rocksdb_ffi::RocksDBCFHandle, handles,
err_ptr); err_ptr);
println!("2!"); }
for handle in cfhandles.iter() {
if handle.0.is_null() {
return Err("Received null column family handle from RocksDB.".to_string());
}
}
for (n, h) in cfs_v.iter().zip(cfhandles) {
cfMap.insert(n.to_string(), h);
} }
} }
@ -249,7 +273,7 @@ impl RocksDB {
return Err("Could not initialize database.".to_string()); return Err("Could not initialize database.".to_string());
} }
Ok(RocksDB { inner: db, cfs: vec![] }) Ok(RocksDB { inner: db, cfs: cfMap })
} }
pub fn destroy(opts: &Options, path: &str) -> Result<(), String> { pub fn destroy(opts: &Options, path: &str) -> Result<(), String> {

@ -42,9 +42,9 @@ pub fn test_column_family() {
// should properly open db when specyfing all column families // should properly open db when specyfing all column families
{ {
match RocksDB::open_cf(&Options::new(), path, vec!["cf1"]) { match RocksDB::open_cf(&Options::new(), path, &["cf1"]) {
Ok(_) => println!("successfully opened db with column family"), Ok(_) => println!("successfully opened db with column family"),
Err(e) => panic!("failed to open db with column family"), Err(e) => panic!("failed to open db with column family: {}", e),
} }
} }

Loading…
Cancel
Save