Initial column family (broken) stubs.

master
Tyler Neely 10 years ago
parent 6ca40b78d4
commit 520d9cef43
  1. 21
      src/ffi.rs
  2. 2
      src/lib.rs
  3. 66
      src/rocksdb.rs
  4. 1
      test/test.rs
  5. 57
      test/test_column_family.rs
  6. 63
      test/test_multithreaded.rs

@ -353,9 +353,28 @@ extern {
name_fn: extern fn(*mut c_void) -> *const c_char name_fn: extern fn(*mut c_void) -> *const c_char
) -> RocksDBComparator; ) -> RocksDBComparator;
pub fn rocksdb_comparator_destroy(cmp: RocksDBComparator); pub fn rocksdb_comparator_destroy(cmp: RocksDBComparator);
// Column Family
pub fn rocksdb_open_column_families(options: RocksDBOptions,
path: *const i8,
num_column_families: c_int,
column_family_names: *const *const i8,
column_family_options: *const [RocksDBOptions],
column_family_handles: *mut *const RocksDBCFHandle,
err: *mut *const i8
) -> RocksDBInstance;
pub fn rocksdb_create_column_family(db: RocksDBInstance,
column_family_options: RocksDBOptions,
column_family_name: *const i8,
err: *mut *const i8
) -> RocksDBCFHandle;
pub fn rocksdb_drop_column_family(db: RocksDBInstance,
column_family_handle: *const RocksDBCFHandle,
err: *mut *const i8);
pub fn rocksdb_column_family_handle_destroy(column_family_handle: *mut *const RocksDBCFHandle);
} }
#[allow(dead_code)]
#[test] #[test]
fn internal() { fn internal() {
unsafe { unsafe {

@ -18,7 +18,9 @@
#![feature(libc)] #![feature(libc)]
#![feature(unique)] #![feature(unique)]
#![feature(path_ext)] #![feature(path_ext)]
#![feature(convert)]
#![feature(raw)] #![feature(raw)]
#![allow(dead_code)]
pub use ffi as rocksdb_ffi; pub use ffi as rocksdb_ffi;
pub use ffi::{new_bloom_filter, RocksDBCompactionStyle, RocksDBComparator}; pub use ffi::{new_bloom_filter, RocksDBCompactionStyle, RocksDBComparator};

@ -23,13 +23,13 @@ use std::path::Path;
use std::ptr::Unique; use std::ptr::Unique;
use std::slice; use std::slice;
use std::str::from_utf8; use std::str::from_utf8;
use std::marker::PhantomData;
use rocksdb_ffi; use rocksdb_ffi;
use rocksdb_options::Options; use rocksdb_options::Options;
pub struct RocksDB { pub struct RocksDB {
inner: rocksdb_ffi::RocksDBInstance, inner: rocksdb_ffi::RocksDBInstance,
cfs: Vec<rocksdb_ffi::RocksDBCFHandle>,
} }
unsafe impl Send for RocksDB {} unsafe impl Send for RocksDB {}
@ -184,6 +184,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![])
}
pub fn open_cf(opts: &Options, path: &str, mut cfs: Vec<&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(_) =>
@ -203,18 +207,49 @@ impl RocksDB {
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;
unsafe { if cfs.len() == 0 {
db = rocksdb_ffi::rocksdb_open(opts.inner, cpath_ptr, err_ptr); unsafe {
db = rocksdb_ffi::rocksdb_open(opts.inner, cpath_ptr, err_ptr);
}
} else {
let nfam = cfs.len();
let mut cfnames: Vec<*const i8> = vec![];
let mut cfhandles: Vec<rocksdb_ffi::RocksDBCFHandle> = vec![];
let mut cfopts: Vec<rocksdb_ffi::RocksDBOptions> = vec![];
cfs.push("default");
for name in cfs {
match CString::new(name.as_bytes()) {
Ok(c) => {
cfnames.push(c.as_ptr());
cfhandles.push(rocksdb_ffi::RocksDBCFHandle(0 as *mut c_void));
cfopts.push(Options::new().inner);
},
Err(_) =>
return Err("Failed to convert path to CString when opening rocksdb".to_string()),
}
};
unsafe {
println!("1!");
println!("nfam: {}", nfam);
db = rocksdb_ffi::rocksdb_open_column_families(opts.inner, cpath_ptr,
nfam as libc::c_int,
cfnames.as_slice().as_ptr(),
cfopts.as_slice(),
cfhandles.as_ptr() as *mut *const rocksdb_ffi::RocksDBCFHandle,
err_ptr);
println!("2!");
}
} }
if !err.is_null() { if !err.is_null() {
return Err(error_message(err)); return Err(error_message(err));
} }
let rocksdb_ffi::RocksDBInstance(db_ptr) = db; if db.0.is_null() {
if db_ptr.is_null() {
return Err("Could not initialize database.".to_string()); return Err("Could not initialize database.".to_string());
} }
Ok(RocksDB { inner: db })
Ok(RocksDB { inner: db, cfs: vec![] })
} }
pub fn destroy(opts: &Options, path: &str) -> Result<(), String> { pub fn destroy(opts: &Options, path: &str) -> Result<(), String> {
@ -300,6 +335,24 @@ impl RocksDB {
} }
} }
pub fn create_cf(&mut self, name: &str, opts: &Options) -> Result<(), String> {
let cname = match CString::new(name.as_bytes()) {
Ok(c) => c,
Err(_) =>
return Err("Failed to convert path to CString when opening rocksdb".to_string()),
};
let cname_ptr = cname.as_ptr();
let mut err: *const i8 = 0 as *const i8;
let err_ptr: *mut *const i8 = &mut err;
unsafe {
rocksdb_ffi::rocksdb_create_column_family(self.inner, opts.inner, cname_ptr, err_ptr);
}
if !err.is_null() {
return Err(error_message(err));
}
Ok(())
}
pub fn iterator(&self) -> DBIterator { pub fn iterator(&self) -> DBIterator {
let opts = ReadOptions::new(); let opts = ReadOptions::new();
DBIterator::new(&self, &opts) DBIterator::new(&self, &opts)
@ -546,7 +599,6 @@ impl <T, E> RocksDBResult<T, E> {
} }
} }
#[allow(dead_code)]
#[test] #[test]
fn external() { fn external() {
let path = "_rust_rocksdb_externaltest"; let path = "_rust_rocksdb_externaltest";

@ -2,3 +2,4 @@ extern crate rocksdb;
mod test_iterator; mod test_iterator;
mod test_multithreaded; mod test_multithreaded;
mod test_column_family;

@ -0,0 +1,57 @@
/*
Copyright 2014 Tyler Neely
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
use rocksdb::{Options, RocksDB, Writable, Direction};
#[test]
pub fn test_column_family() {
let path = "_rust_rocksdb_cftest";
// should be able to create column families
{
let mut db = RocksDB::open_default(path).unwrap();
let opts = Options::new();
match db.create_cf("cf1", &opts) {
Ok(_) => println!("cf1 created successfully"),
Err(e) => {
panic!("could not create column family: {}", e);
},
}
}
// should fail to open db without specifying same column families
{
match RocksDB::open_default(path) {
Ok(_) => panic!("should not have opened DB successfully without specifying column
families"),
Err(e) => assert!(e.starts_with("Invalid argument: You have to open all column families.")),
}
}
// should properly open db when specyfing all column families
{
match RocksDB::open_cf(&Options::new(), path, vec!["cf1"]) {
Ok(_) => println!("successfully opened db with column family"),
Err(e) => panic!("failed to open db with column family"),
}
}
// should be able to write, read, merge, batch, and iterate over a cf
{
}
assert!(RocksDB::destroy(&Options::new(), path).is_ok());
}

@ -2,47 +2,50 @@ use rocksdb::{Options, RocksDB, Writable, Direction, RocksDBResult};
use std::thread::{self, Builder}; use std::thread::{self, Builder};
use std::sync::Arc; use std::sync::Arc;
const N: usize = 1000_000; const N: usize = 100_000;
#[test] #[test]
pub fn test_multithreaded() { pub fn test_multithreaded() {
let path = "_rust_rocksdb_multithreadtest"; let path = "_rust_rocksdb_multithreadtest";
let db = RocksDB::open_default(path).unwrap(); {
let db = Arc::new(db); let db = RocksDB::open_default(path).unwrap();
let db = Arc::new(db);
db.put(b"key", b"value1"); db.put(b"key", b"value1");
let db1 = db.clone(); let db1 = db.clone();
let j1 = thread::spawn(move|| { let j1 = thread::spawn(move|| {
for i in 1..N { for i in 1..N {
db1.put(b"key", b"value1"); db1.put(b"key", b"value1");
} }
}); });
let db2 = db.clone(); let db2 = db.clone();
let j2 = thread::spawn(move|| { let j2 = thread::spawn(move|| {
for i in 1..N { for i in 1..N {
db2.put(b"key", b"value2"); db2.put(b"key", b"value2");
} }
}); });
let db3 = db.clone(); let db3 = db.clone();
let j3 = thread::spawn(move|| { let j3 = thread::spawn(move|| {
for i in 1..N { for i in 1..N {
match db3.get(b"key") { match db3.get(b"key") {
RocksDBResult::Some(v) => { RocksDBResult::Some(v) => {
if &v[..] != b"value1" && &v[..] != b"value2" { if &v[..] != b"value1" && &v[..] != b"value2" {
assert!(false);
}
}
_ => {
assert!(false); assert!(false);
} }
} }
_ => {
assert!(false);
}
} }
} });
});
j1.join(); j1.join();
j2.join(); j2.join();
j3.join(); j3.join();
}
assert!(RocksDB::destroy(&Options::new(), path).is_ok());
} }

Loading…
Cancel
Save