Merge pull request #197 from aleksuss/immutable-op-cf

Methods `create_cf` and `drop_cf` are immutable.
master
Jordan Terrell 6 years ago committed by GitHub
commit d7e5fbfe83
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 59
      src/db.rs
  2. 5
      src/lib.rs
  3. 4
      tests/test_column_family.rs

@ -19,8 +19,7 @@ use {ColumnFamily, ColumnFamilyDescriptor, Error, Options, WriteOptions, DB};
use libc::{self, c_char, c_int, c_uchar, c_void, size_t}; use libc::{self, c_char, c_int, c_uchar, c_void, size_t};
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::ffi::CStr; use std::ffi::{CStr, CString};
use std::ffi::CString;
use std::fmt; use std::fmt;
use std::fs; use std::fs;
use std::ops::Deref; use std::ops::Deref;
@ -28,6 +27,7 @@ use std::path::Path;
use std::ptr; use std::ptr;
use std::slice; use std::slice;
use std::str; use std::str;
use std::sync::{Arc, RwLock};
pub fn new_bloom_filter(bits: c_int) -> *mut ffi::rocksdb_filterpolicy_t { pub fn new_bloom_filter(bits: c_int) -> *mut ffi::rocksdb_filterpolicy_t {
unsafe { ffi::rocksdb_filterpolicy_create_bloom(bits) } unsafe { ffi::rocksdb_filterpolicy_create_bloom(bits) }
@ -386,7 +386,7 @@ impl DBRawIterator {
/// if the iterator's seek position is ever moved by any of the seek commands or the /// if the iterator's seek position is ever moved by any of the seek commands or the
/// ``.next()`` and ``.previous()`` methods as the underlying buffer may be reused /// ``.next()`` and ``.previous()`` methods as the underlying buffer may be reused
/// for something else or freed entirely. /// for something else or freed entirely.
pub unsafe fn key_inner<'a>(&'a self) -> Option<&'a [u8]> { pub unsafe fn key_inner(&self) -> Option<&[u8]> {
if self.valid() { if self.valid() {
let mut key_len: size_t = 0; let mut key_len: size_t = 0;
let key_len_ptr: *mut size_t = &mut key_len; let key_len_ptr: *mut size_t = &mut key_len;
@ -410,7 +410,7 @@ impl DBRawIterator {
/// if the iterator's seek position is ever moved by any of the seek commands or the /// if the iterator's seek position is ever moved by any of the seek commands or the
/// ``.next()`` and ``.previous()`` methods as the underlying buffer may be reused /// ``.next()`` and ``.previous()`` methods as the underlying buffer may be reused
/// for something else or freed entirely. /// for something else or freed entirely.
pub unsafe fn value_inner<'a>(&'a self) -> Option<&'a [u8]> { pub unsafe fn value_inner(&self) -> Option<&[u8]> {
if self.valid() { if self.valid() {
let mut val_len: size_t = 0; let mut val_len: size_t = 0;
let val_len_ptr: *mut size_t = &mut val_len; let val_len_ptr: *mut size_t = &mut val_len;
@ -454,7 +454,7 @@ impl DBIterator {
mode: IteratorMode, mode: IteratorMode,
) -> Result<DBIterator, Error> { ) -> Result<DBIterator, Error> {
let mut rv = DBIterator { let mut rv = DBIterator {
raw: try!(DBRawIterator::new_cf(db, cf_handle, readopts)), raw: DBRawIterator::new_cf(db, cf_handle, readopts)?,
direction: Direction::Forward, // blown away by set_mode() direction: Direction::Forward, // blown away by set_mode()
just_seeked: false, just_seeked: false,
}; };
@ -647,7 +647,7 @@ impl DB {
} }
let db: *mut ffi::rocksdb_t; let db: *mut ffi::rocksdb_t;
let mut cf_map = BTreeMap::new(); let cf_map = Arc::new(RwLock::new(BTreeMap::new()));
if cfs.len() == 0 { if cfs.len() == 0 {
unsafe { unsafe {
@ -701,7 +701,9 @@ impl DB {
} }
for (n, h) in cfs_v.iter().zip(cfhandles) { for (n, h) in cfs_v.iter().zip(cfhandles) {
cf_map.insert(n.name.clone(), ColumnFamily { inner: h }); cf_map.write()
.map_err(|e| Error::new(e.to_string()))?
.insert(n.name.clone(), ColumnFamily { inner: h });
} }
} }
@ -856,7 +858,7 @@ impl DB {
self.get_cf_opt(cf, key, &ReadOptions::default()) self.get_cf_opt(cf, key, &ReadOptions::default())
} }
pub fn create_cf(&mut self, name: &str, opts: &Options) -> Result<ColumnFamily, Error> { pub fn create_cf(&self, name: &str, opts: &Options) -> Result<ColumnFamily, Error> {
let cname = match CString::new(name.as_bytes()) { let cname = match CString::new(name.as_bytes()) {
Ok(c) => c, Ok(c) => c,
Err(_) => { Err(_) => {
@ -874,31 +876,30 @@ impl DB {
cname.as_ptr(), cname.as_ptr(),
)); ));
let cf = ColumnFamily { inner: cf_handler }; let cf = ColumnFamily { inner: cf_handler };
self.cfs.insert(name.to_string(), cf); self.cfs.write().map_err(|e| Error::new(e.to_string()))?
.insert(name.to_string(), cf);
cf cf
}; };
Ok(cf) Ok(cf)
} }
pub fn drop_cf(&mut self, name: &str) -> Result<(), Error> { pub fn drop_cf(&self, name: &str) -> Result<(), Error> {
let cf = self.cfs.get(name); if let Some(cf) = self.cfs.write().map_err(|e| Error::new(e.to_string()))?
if cf.is_none() { .remove(name) {
return Err(Error::new( unsafe {
format!("Invalid column family: {}", name).to_owned(), ffi_try!(ffi::rocksdb_drop_column_family(self.inner, cf.inner,));
)); }
} Ok(())
unsafe { } else {
ffi_try!(ffi::rocksdb_drop_column_family( Err(Error::new(
self.inner, format!("Invalid column family: {}", name).to_owned()
cf.unwrap().inner, ))
));
} }
Ok(())
} }
/// Return the underlying column family handle. /// Return the underlying column family handle.
pub fn cf_handle(&self, name: &str) -> Option<ColumnFamily> { pub fn cf_handle(&self, name: &str) -> Option<ColumnFamily> {
self.cfs.get(name).cloned() self.cfs.read().ok()?.get(name).cloned()
} }
pub fn iterator(&self, mode: IteratorMode) -> DBIterator { pub fn iterator(&self, mode: IteratorMode) -> DBIterator {
@ -915,7 +916,7 @@ impl DB {
DBIterator::new(self, &opts, mode) DBIterator::new(self, &opts, mode)
} }
pub fn prefix_iterator<'a>(&self, prefix: &'a [u8]) -> DBIterator { pub fn prefix_iterator(&self, prefix: &[u8]) -> DBIterator {
let mut opts = ReadOptions::default(); let mut opts = ReadOptions::default();
opts.set_prefix_same_as_start(true); opts.set_prefix_same_as_start(true);
DBIterator::new(self, &opts, IteratorMode::From(prefix, Direction::Forward)) DBIterator::new(self, &opts, IteratorMode::From(prefix, Direction::Forward))
@ -940,10 +941,10 @@ impl DB {
DBIterator::new_cf(self, cf_handle, &opts, mode) DBIterator::new_cf(self, cf_handle, &opts, mode)
} }
pub fn prefix_iterator_cf<'a>( pub fn prefix_iterator_cf(
&self, &self,
cf_handle: ColumnFamily, cf_handle: ColumnFamily,
prefix: &'a [u8], prefix: &[u8]
) -> Result<DBIterator, Error> { ) -> Result<DBIterator, Error> {
let mut opts = ReadOptions::default(); let mut opts = ReadOptions::default();
opts.set_prefix_same_as_start(true); opts.set_prefix_same_as_start(true);
@ -1241,8 +1242,10 @@ impl Drop for WriteBatch {
impl Drop for DB { impl Drop for DB {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
for cf in self.cfs.values() { if let Ok(cfs) = self.cfs.read() {
ffi::rocksdb_column_family_handle_destroy(cf.inner); for cf in cfs.values() {
ffi::rocksdb_column_family_handle_destroy(cf.inner);
}
} }
ffi::rocksdb_close(self.inner); ffi::rocksdb_close(self.inner);
} }

@ -74,13 +74,14 @@ use std::collections::BTreeMap;
use std::error; use std::error;
use std::fmt; use std::fmt;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::{Arc, RwLock};
/// A RocksDB database. /// A RocksDB database.
/// ///
/// See crate level documentation for a simple usage example. /// See crate level documentation for a simple usage example.
pub struct DB { pub struct DB {
inner: *mut ffi::rocksdb_t, inner: *mut ffi::rocksdb_t,
cfs: BTreeMap<String, ColumnFamily>, cfs: Arc<RwLock<BTreeMap<String, ColumnFamily>>>,
path: PathBuf, path: PathBuf,
} }
@ -101,7 +102,7 @@ pub struct Error {
impl Error { impl Error {
fn new(message: String) -> Error { fn new(message: String) -> Error {
Error { message: message } Error { message }
} }
pub fn to_string(self) -> String { pub fn to_string(self) -> String {

@ -27,7 +27,7 @@ pub fn test_column_family() {
let mut opts = Options::default(); let mut opts = Options::default();
opts.create_if_missing(true); opts.create_if_missing(true);
opts.set_merge_operator("test operator", test_provided_merge, None); opts.set_merge_operator("test operator", test_provided_merge, None);
let mut db = DB::open(&opts, &n).unwrap(); let db = DB::open(&opts, &n).unwrap();
let opts = Options::default(); let opts = Options::default();
match db.create_cf("cf1", &opts) { match db.create_cf("cf1", &opts) {
Ok(_db) => println!("cf1 created successfully"), Ok(_db) => println!("cf1 created successfully"),
@ -80,7 +80,7 @@ pub fn test_column_family() {
{} {}
// should b able to drop a cf // should b able to drop a cf
{ {
let mut db = DB::open_cf(&Options::default(), &n, &["cf1"]).unwrap(); let db = DB::open_cf(&Options::default(), &n, &["cf1"]).unwrap();
match db.drop_cf("cf1") { match db.drop_cf("cf1") {
Ok(_) => println!("cf1 successfully dropped."), Ok(_) => println!("cf1 successfully dropped."),
Err(e) => panic!("failed to drop column family: {}", e), Err(e) => panic!("failed to drop column family: {}", e),

Loading…
Cancel
Save