|
|
@ -14,6 +14,8 @@ |
|
|
|
|
|
|
|
|
|
|
|
use std::ffi::CStr; |
|
|
|
use std::ffi::CStr; |
|
|
|
use std::path::Path; |
|
|
|
use std::path::Path; |
|
|
|
|
|
|
|
use std::ptr::null_mut; |
|
|
|
|
|
|
|
use std::slice; |
|
|
|
use std::sync::Arc; |
|
|
|
use std::sync::Arc; |
|
|
|
|
|
|
|
|
|
|
|
use libc::{self, c_char, c_double, c_int, c_uchar, c_uint, c_void, size_t}; |
|
|
|
use libc::{self, c_char, c_double, c_int, c_uchar, c_uint, c_void, size_t}; |
|
|
@ -24,12 +26,12 @@ use crate::{ |
|
|
|
comparator::{self, ComparatorCallback, CompareFn}, |
|
|
|
comparator::{self, ComparatorCallback, CompareFn}, |
|
|
|
db::DBAccess, |
|
|
|
db::DBAccess, |
|
|
|
ffi, |
|
|
|
ffi, |
|
|
|
ffi_util::{to_cpath, CStrLike}, |
|
|
|
ffi_util::{from_cstr, to_cpath, CStrLike}, |
|
|
|
merge_operator::{ |
|
|
|
merge_operator::{ |
|
|
|
self, full_merge_callback, partial_merge_callback, MergeFn, MergeOperatorCallback, |
|
|
|
self, full_merge_callback, partial_merge_callback, MergeFn, MergeOperatorCallback, |
|
|
|
}, |
|
|
|
}, |
|
|
|
slice_transform::SliceTransform, |
|
|
|
slice_transform::SliceTransform, |
|
|
|
Error, SnapshotWithThreadMode, |
|
|
|
ColumnFamilyDescriptor, Error, SnapshotWithThreadMode, |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
fn new_cache(capacity: size_t) -> *mut ffi::rocksdb_cache_t { |
|
|
|
fn new_cache(capacity: size_t) -> *mut ffi::rocksdb_cache_t { |
|
|
@ -875,6 +877,76 @@ pub enum LogLevel { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
impl Options { |
|
|
|
impl Options { |
|
|
|
|
|
|
|
/// Constructs the DBOptions and ColumnFamilyDescriptors by loading the
|
|
|
|
|
|
|
|
/// latest RocksDB options file stored in the specified rocksdb database.
|
|
|
|
|
|
|
|
pub fn load_latest<P: AsRef<Path>>( |
|
|
|
|
|
|
|
path: P, |
|
|
|
|
|
|
|
env: Env, |
|
|
|
|
|
|
|
ignore_unknown_options: bool, |
|
|
|
|
|
|
|
cache: Cache, |
|
|
|
|
|
|
|
) -> Result<(Options, Vec<ColumnFamilyDescriptor>), Error> { |
|
|
|
|
|
|
|
let path = to_cpath(path)?; |
|
|
|
|
|
|
|
let mut db_options: *mut ffi::rocksdb_options_t = null_mut(); |
|
|
|
|
|
|
|
let mut num_column_families: usize = 0; |
|
|
|
|
|
|
|
let mut column_family_names: *mut *mut c_char = null_mut(); |
|
|
|
|
|
|
|
let mut column_family_options: *mut *mut ffi::rocksdb_options_t = null_mut(); |
|
|
|
|
|
|
|
unsafe { |
|
|
|
|
|
|
|
ffi_try!(ffi::rocksdb_load_latest_options( |
|
|
|
|
|
|
|
path.as_ptr(), |
|
|
|
|
|
|
|
env.0.inner, |
|
|
|
|
|
|
|
ignore_unknown_options, |
|
|
|
|
|
|
|
cache.0.inner, |
|
|
|
|
|
|
|
&mut db_options, |
|
|
|
|
|
|
|
&mut num_column_families, |
|
|
|
|
|
|
|
&mut column_family_names, |
|
|
|
|
|
|
|
&mut column_family_options, |
|
|
|
|
|
|
|
)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
let options = Options { |
|
|
|
|
|
|
|
inner: db_options, |
|
|
|
|
|
|
|
outlive: OptionsMustOutliveDB::default(), |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
let column_families = unsafe { |
|
|
|
|
|
|
|
Options::read_column_descriptors( |
|
|
|
|
|
|
|
num_column_families, |
|
|
|
|
|
|
|
column_family_names, |
|
|
|
|
|
|
|
column_family_options, |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
Ok((options, column_families)) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// read column descriptors from c pointers
|
|
|
|
|
|
|
|
#[inline] |
|
|
|
|
|
|
|
unsafe fn read_column_descriptors( |
|
|
|
|
|
|
|
num_column_families: usize, |
|
|
|
|
|
|
|
column_family_names: *mut *mut c_char, |
|
|
|
|
|
|
|
column_family_options: *mut *mut ffi::rocksdb_options_t, |
|
|
|
|
|
|
|
) -> Vec<ColumnFamilyDescriptor> { |
|
|
|
|
|
|
|
let column_family_names_iter = |
|
|
|
|
|
|
|
slice::from_raw_parts(column_family_names, num_column_families) |
|
|
|
|
|
|
|
.iter() |
|
|
|
|
|
|
|
.map(|ptr| from_cstr(*ptr)); |
|
|
|
|
|
|
|
let column_family_options_iter = |
|
|
|
|
|
|
|
slice::from_raw_parts(column_family_options, num_column_families) |
|
|
|
|
|
|
|
.iter() |
|
|
|
|
|
|
|
.map(|ptr| Options { |
|
|
|
|
|
|
|
inner: *ptr, |
|
|
|
|
|
|
|
outlive: OptionsMustOutliveDB::default(), |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
let column_descriptors = column_family_names_iter |
|
|
|
|
|
|
|
.zip(column_family_options_iter) |
|
|
|
|
|
|
|
.map(|(name, options)| ColumnFamilyDescriptor { name, options }) |
|
|
|
|
|
|
|
.collect::<Vec<_>>(); |
|
|
|
|
|
|
|
// free pointers
|
|
|
|
|
|
|
|
slice::from_raw_parts(column_family_names, num_column_families) |
|
|
|
|
|
|
|
.iter() |
|
|
|
|
|
|
|
.for_each(|ptr| ffi::rocksdb_free(*ptr as *mut c_void)); |
|
|
|
|
|
|
|
ffi::rocksdb_free(column_family_names as *mut c_void); |
|
|
|
|
|
|
|
ffi::rocksdb_free(column_family_options as *mut c_void); |
|
|
|
|
|
|
|
column_descriptors |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// By default, RocksDB uses only one background thread for flush and
|
|
|
|
/// By default, RocksDB uses only one background thread for flush and
|
|
|
|
/// compaction. Calling this function will set it up such that total of
|
|
|
|
/// compaction. Calling this function will set it up such that total of
|
|
|
|
/// `total_threads` is used. Good value for `total_threads` is the number of
|
|
|
|
/// `total_threads` is used. Good value for `total_threads` is the number of
|
|
|
|