Add support for opening a column family with options

Adds a new `DB::open_cf_descriptors` method that allows passing in Options for
each column family.  A new `ColumnFamilyDescriptor` type was added to contain
the congfiguration for each column family. This fixes an issue where a column
family was created with non-default options, and then fails to re-open due to a
config mismatch.
master
Gary Tierney 7 years ago
parent 9002fbda95
commit 9afa195a33
  1. 47
      src/db.rs
  2. 5
      src/lib.rs

@ -14,7 +14,7 @@
//
use {DB, Error, Options, WriteOptions, ColumnFamily};
use {DB, Error, Options, WriteOptions, ColumnFamily, ColumnFamilyDescriptor};
use ffi;
use ffi_util::opt_bytes_to_ptr;
@ -559,6 +559,16 @@ impl<'a> Drop for Snapshot<'a> {
}
}
impl ColumnFamilyDescriptor {
// Create a new column family descriptor with the specified name and options.
pub fn new<S>(name: S, options: Options) -> Self where S: Into<String> {
ColumnFamilyDescriptor {
name: name.into(),
options
}
}
}
impl DB {
/// Open a database with default options.
pub fn open_default<P: AsRef<Path>>(path: P) -> Result<DB, Error> {
@ -572,14 +582,20 @@ impl DB {
DB::open_cf(opts, path, &[])
}
/// Open a database with specified options and column family.
///
/// A column family must be created first by calling `DB::create_cf`.
/// Open a database with the given database options and column family names.
///
/// # Panics
///
/// * Panics if the column family doesn't exist.
/// Column families opened using this function will be created with default `Options`.
pub fn open_cf<P: AsRef<Path>>(opts: &Options, path: P, cfs: &[&str]) -> Result<DB, Error> {
let cfs_v = cfs.to_vec().iter().map(|name| ColumnFamilyDescriptor {
name: name.to_string(),
options: Options::default(),
}).collect();
DB::open_cf_descriptors(opts, path, cfs_v)
}
/// Open a database with the given database options and column family names/options.
pub fn open_cf_descriptors<P: AsRef<Path>>(opts: &Options, path: P, cfs: Vec<ColumnFamilyDescriptor>) -> Result<DB, Error> {
let path = path.as_ref();
let cpath = match CString::new(path.to_string_lossy().as_bytes()) {
Ok(c) => c,
@ -604,16 +620,18 @@ impl DB {
db = ffi_try!(ffi::rocksdb_open(opts.inner, cpath.as_ptr() as *const _));
}
} else {
let mut cfs_v = cfs.to_vec();
let mut cfs_v = cfs;
// Always open the default column family.
if !cfs_v.contains(&"default") {
cfs_v.push("default");
if !cfs_v.iter().any(|cf| cf.name == "default") {
cfs_v.push(ColumnFamilyDescriptor {
name: String::from("default"),
options: Options::default()
});
}
// We need to store our CStrings in an intermediate vector
// so that their pointers remain valid.
let c_cfs: Vec<CString> = cfs_v.iter()
.map(|cf| CString::new(cf.as_bytes()).unwrap())
.map(|cf| CString::new(cf.name.as_bytes()).unwrap())
.collect();
let cfnames: Vec<_> = c_cfs.iter().map(|cf| cf.as_ptr()).collect();
@ -621,9 +639,8 @@ impl DB {
// These handles will be populated by DB.
let mut cfhandles: Vec<_> = cfs_v.iter().map(|_| ptr::null_mut()).collect();
// TODO(tyler) allow options to be passed in.
let cfopts: Vec<_> = cfs_v.iter()
.map(|_| unsafe { ffi::rocksdb_options_create() as *const _ })
.map(|cf| cf.options.inner as *const _)
.collect();
unsafe {
@ -644,7 +661,7 @@ impl DB {
}
for (n, h) in cfs_v.iter().zip(cfhandles) {
cf_map.insert(n.to_string(), ColumnFamily { inner: h });
cf_map.insert(n.name.clone(), ColumnFamily { inner: h });
}
}

@ -63,6 +63,11 @@ pub struct DB {
path: PathBuf,
}
pub struct ColumnFamilyDescriptor {
name: String,
options: Options,
}
/// A simple wrapper round a string, used for errors reported from
/// ffi calls.
#[derive(Debug, Clone, PartialEq)]

Loading…
Cancel
Save