Add some documentation and wrap column_family_t

master
Richard Dodd 8 years ago
parent 2a29b0ae5f
commit 63a77d22c9
  1. 99
      src/db.rs
  2. 13
      src/lib.rs
  3. 2
      test/test_column_family.rs

@ -14,7 +14,7 @@
//
use {DB, Error, Options, WriteOptions};
use {DB, Error, Options, WriteOptions, ColumnFamily};
use ffi;
use ffi_util::opt_bytes_to_ptr;
@ -220,12 +220,12 @@ impl DBIterator {
}
fn new_cf(db: &DB,
cf_handle: *mut ffi::rocksdb_column_family_handle_t,
cf_handle: ColumnFamily,
readopts: &ReadOptions,
mode: IteratorMode)
-> Result<DBIterator, Error> {
unsafe {
let iterator = ffi::rocksdb_create_iterator_cf(db.inner, readopts.inner, cf_handle);
let iterator = ffi::rocksdb_create_iterator_cf(db.inner, readopts.inner, cf_handle.inner);
let mut rv = DBIterator {
inner: iterator,
@ -262,7 +262,7 @@ impl<'a> Snapshot<'a> {
}
pub fn iterator_cf(&self,
cf_handle: *mut ffi::rocksdb_column_family_handle_t,
cf_handle: ColumnFamily,
mode: IteratorMode)
-> Result<DBIterator, Error> {
let mut readopts = ReadOptions::default();
@ -277,7 +277,7 @@ impl<'a> Snapshot<'a> {
}
pub fn get_cf(&self,
cf: *mut ffi::rocksdb_column_family_handle_t,
cf: ColumnFamily,
key: &[u8])
-> Result<Option<DBVector>, Error> {
let mut readopts = ReadOptions::default();
@ -379,7 +379,7 @@ impl DB {
}
for (n, h) in cfs_v.iter().zip(cfhandles) {
cf_map.insert(n.to_string(), h);
cf_map.insert(n.to_string(), ColumnFamily { inner: h });
}
}
@ -462,7 +462,7 @@ impl DB {
}
pub fn get_cf_opt(&self,
cf: *mut ffi::rocksdb_column_family_handle_t,
cf: ColumnFamily,
key: &[u8],
readopts: &ReadOptions)
-> Result<Option<DBVector>, Error> {
@ -479,7 +479,7 @@ impl DB {
let mut val_len: size_t = 0;
let val = ffi_try!(ffi::rocksdb_get_cf(self.inner,
readopts.inner,
cf,
cf.inner,
key.as_ptr() as *const c_char,
key.len() as size_t,
&mut val_len)) as *mut u8;
@ -492,7 +492,7 @@ impl DB {
}
pub fn get_cf(&self,
cf: *mut ffi::rocksdb_column_family_handle_t,
cf: ColumnFamily,
key: &[u8])
-> Result<Option<DBVector>, Error> {
self.get_cf_opt(cf, key, &ReadOptions::default())
@ -501,7 +501,7 @@ impl DB {
pub fn create_cf(&mut self,
name: &str,
opts: &Options)
-> Result<*mut ffi::rocksdb_column_family_handle_t, Error> {
-> Result<ColumnFamily, Error> {
let cname = match CString::new(name.as_bytes()) {
Ok(c) => c,
Err(_) => {
@ -513,6 +513,7 @@ impl DB {
let cf_handler = unsafe {
let cf_handler =
ffi_try!(ffi::rocksdb_create_column_family(self.inner, opts.inner, cname.as_ptr()));
let cf_handler = ColumnFamily { inner: cf_handler };
self.cfs.insert(name.to_string(), cf_handler);
cf_handler
};
@ -525,14 +526,14 @@ impl DB {
return Err(Error::new(format!("Invalid column family: {}", name).to_owned()));
}
unsafe {
ffi_try!(ffi::rocksdb_drop_column_family(self.inner, *cf.unwrap()));
ffi_try!(ffi::rocksdb_drop_column_family(self.inner, cf.unwrap().inner));
}
Ok(())
}
/// Return the underlying column family handle.
pub fn cf_handle(&self, name: &str) -> Option<&*mut ffi::rocksdb_column_family_handle_t> {
self.cfs.get(name)
pub fn cf_handle(&self, name: &str) -> Option<ColumnFamily> {
self.cfs.get(name).map(|cf| *cf)
}
pub fn iterator(&self, mode: IteratorMode) -> DBIterator {
@ -541,7 +542,7 @@ impl DB {
}
pub fn iterator_cf(&self,
cf_handle: *mut ffi::rocksdb_column_family_handle_t,
cf_handle: ColumnFamily,
mode: IteratorMode)
-> Result<DBIterator, Error> {
let opts = ReadOptions::default();
@ -565,7 +566,7 @@ impl DB {
}
pub fn put_cf_opt(&self,
cf: *mut ffi::rocksdb_column_family_handle_t,
cf: ColumnFamily,
key: &[u8],
value: &[u8],
writeopts: &WriteOptions)
@ -573,7 +574,7 @@ impl DB {
unsafe {
ffi_try!(ffi::rocksdb_put_cf(self.inner,
writeopts.inner,
cf,
cf.inner,
key.as_ptr() as *const c_char,
key.len() as size_t,
value.as_ptr() as *const c_char,
@ -599,7 +600,7 @@ impl DB {
}
pub fn merge_cf_opt(&self,
cf: *mut ffi::rocksdb_column_family_handle_t,
cf: ColumnFamily,
key: &[u8],
value: &[u8],
writeopts: &WriteOptions)
@ -607,7 +608,7 @@ impl DB {
unsafe {
ffi_try!(ffi::rocksdb_merge_cf(self.inner,
writeopts.inner,
cf,
cf.inner,
key.as_ptr() as *const i8,
key.len() as size_t,
value.as_ptr() as *const i8,
@ -627,14 +628,14 @@ impl DB {
}
pub fn delete_cf_opt(&self,
cf: *mut ffi::rocksdb_column_family_handle_t,
cf: ColumnFamily,
key: &[u8],
writeopts: &WriteOptions)
-> Result<(), Error> {
unsafe {
ffi_try!(ffi::rocksdb_delete_cf(self.inner,
writeopts.inner,
cf,
cf.inner,
key.as_ptr() as *const c_char,
key.len() as size_t));
Ok(())
@ -646,7 +647,7 @@ impl DB {
}
pub fn put_cf(&self,
cf: *mut ffi::rocksdb_column_family_handle_t,
cf: ColumnFamily,
key: &[u8],
value: &[u8])
-> Result<(), Error> {
@ -658,7 +659,7 @@ impl DB {
}
pub fn merge_cf(&self,
cf: *mut ffi::rocksdb_column_family_handle_t,
cf: ColumnFamily,
key: &[u8],
value: &[u8])
-> Result<(), Error> {
@ -670,7 +671,7 @@ impl DB {
}
pub fn delete_cf(&self,
cf: *mut ffi::rocksdb_column_family_handle_t,
cf: ColumnFamily,
key: &[u8])
-> Result<(), Error> {
self.delete_cf_opt(cf, key, &WriteOptions::default())
@ -687,12 +688,12 @@ impl DB {
}
pub fn compact_range_cf(&self,
cf: *mut ffi::rocksdb_column_family_handle_t,
cf: ColumnFamily,
start: Option<&[u8]>,
end: Option<&[u8]>) {
unsafe {
ffi::rocksdb_compact_range_cf(self.inner,
cf,
cf.inner,
opt_bytes_to_ptr(start),
start.map_or(0, |s| s.len()) as size_t,
opt_bytes_to_ptr(end),
@ -723,13 +724,13 @@ impl WriteBatch {
}
pub fn put_cf(&mut self,
cf: *mut ffi::rocksdb_column_family_handle_t,
cf: ColumnFamily,
key: &[u8],
value: &[u8])
-> Result<(), Error> {
unsafe {
ffi::rocksdb_writebatch_put_cf(self.inner,
cf,
cf.inner,
key.as_ptr() as *const i8,
key.len() as size_t,
value.as_ptr() as *const i8,
@ -750,13 +751,13 @@ impl WriteBatch {
}
pub fn merge_cf(&mut self,
cf: *mut ffi::rocksdb_column_family_handle_t,
cf: ColumnFamily,
key: &[u8],
value: &[u8])
-> Result<(), Error> {
unsafe {
ffi::rocksdb_writebatch_merge_cf(self.inner,
cf,
cf.inner,
key.as_ptr() as *const i8,
key.len() as size_t,
value.as_ptr() as *const i8,
@ -778,12 +779,12 @@ impl WriteBatch {
}
pub fn delete_cf(&mut self,
cf: *mut ffi::rocksdb_column_family_handle_t,
cf: ColumnFamily,
key: &[u8])
-> Result<(), Error> {
unsafe {
ffi::rocksdb_writebatch_delete_cf(self.inner,
cf,
cf.inner,
key.as_ptr() as *const i8,
key.len() as size_t);
Ok(())
@ -807,7 +808,7 @@ impl Drop for DB {
fn drop(&mut self) {
unsafe {
for cf in self.cfs.values() {
ffi::rocksdb_column_family_handle_destroy(*cf);
ffi::rocksdb_column_family_handle_destroy(cf.inner);
}
ffi::rocksdb_close(self.inner);
}
@ -859,6 +860,10 @@ impl Default for ReadOptions {
}
/// Vector of bytes stored in the database.
///
/// This is a `C` allocated byte array and a length value.
/// Normal usage would be to utilize the fact it implements `Deref<[u8]>` and use it as
/// a slice.
pub struct DBVector {
base: *mut u8,
len: usize,
@ -881,18 +886,46 @@ impl Drop for DBVector {
}
impl DBVector {
pub fn from_c(val: *mut u8, val_len: size_t) -> DBVector {
/// Used internally to create a DBVector from a `C` memory block
///
/// # Unsafe
/// Requires that the ponter be allocated by a `malloc` derivative (all C libraries), and
/// `val_len` be the length of the C array to be safe (since `sizeof(u8) = 1`).
///
/// # Example
///
/// ```ignore
/// let buf_len: libc::size_t = unsafe { mem::uninitialized() };
/// // Assume the function fills buf_len with the length of the returned array
/// let buf: *mut u8 = unsafe { ffi_function_returning_byte_array(&buf_len) };
/// DBVector::from_c(buf, buf_len)
/// ```
pub unsafe fn from_c(val: *mut u8, val_len: size_t) -> DBVector {
DBVector {
base: val,
len: val_len as usize,
}
}
/// Convenience function to attempt to reinterperet value as string.
///
/// implemented as `str::from_utf8(&self[..])`
pub fn to_utf8(&self) -> Option<&str> {
str::from_utf8(self.deref()).ok()
}
}
#[test]
fn test_db_vector() {
use std::mem;
let len: size_t = 4;
let data: *mut u8 = unsafe { mem::transmute(libc::calloc(len, mem::size_of::<u8>())) };
let v = unsafe { DBVector::from_c(data, len) };
let ctrl = [0u8, 0, 0, 0];
assert_eq!(&*v, &ctrl[..]);
}
#[test]
fn external() {
let path = "_rust_rocksdb_externaltest";

@ -55,12 +55,16 @@ use std::fmt;
use std::path::PathBuf;
/// A RocksDB database.
///
/// See crate level documentation for a simple usage example.
pub struct DB {
inner: *mut ffi::rocksdb_t,
cfs: BTreeMap<String, *mut ffi::rocksdb_column_family_handle_t>,
cfs: BTreeMap<String, ColumnFamily>,
path: PathBuf,
}
/// A simple wrapper round a string, used for errors reported from
/// ffi calls.
#[derive(Debug, PartialEq)]
pub struct Error {
message: String,
@ -162,3 +166,10 @@ pub struct Options {
pub struct WriteOptions {
inner: *mut ffi::rocksdb_writeoptions_t,
}
/// An opaque type used to represent a column family. Returned from some functions, and used
/// in others
#[derive(Copy, Clone)]
pub struct ColumnFamily {
inner: *mut ffi::rocksdb_column_family_handle_t,
}

@ -94,7 +94,7 @@ fn test_merge_operator() {
}
Err(e) => panic!("failed to open db with column family: {}", e),
};
let cf1 = *db.cf_handle("cf1").unwrap();
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().unwrap().to_utf8().unwrap() == "v1");
let p = db.put_cf(cf1, b"k1", b"a");

Loading…
Cancel
Save