Skip to content

Commit b8b4cf3

Browse files
authored
Add Options::load_latest() method to load latest options from RockDB path (tikv#724)
1 parent 548b425 commit b8b4cf3

File tree

3 files changed

+103
-3
lines changed

3 files changed

+103
-3
lines changed

src/column_family.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ impl ColumnFamilyDescriptor {
4141
options,
4242
}
4343
}
44+
45+
/// Get the name of the ColumnFamilyDescriptor.
46+
pub fn name(&self) -> &str {
47+
&self.name
48+
}
4449
}
4550

4651
/// An opaque type used to represent a column family. Returned from some functions, and used

src/db_options.rs

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
use std::ffi::CStr;
1616
use std::path::Path;
17+
use std::ptr::null_mut;
18+
use std::slice;
1719
use std::sync::Arc;
1820

1921
use libc::{self, c_char, c_double, c_int, c_uchar, c_uint, c_void, size_t};
@@ -24,12 +26,12 @@ use crate::{
2426
comparator::{self, ComparatorCallback, CompareFn},
2527
db::DBAccess,
2628
ffi,
27-
ffi_util::{to_cpath, CStrLike},
29+
ffi_util::{from_cstr, to_cpath, CStrLike},
2830
merge_operator::{
2931
self, full_merge_callback, partial_merge_callback, MergeFn, MergeOperatorCallback,
3032
},
3133
slice_transform::SliceTransform,
32-
Error, SnapshotWithThreadMode,
34+
ColumnFamilyDescriptor, Error, SnapshotWithThreadMode,
3335
};
3436

3537
fn new_cache(capacity: size_t) -> *mut ffi::rocksdb_cache_t {
@@ -875,6 +877,76 @@ pub enum LogLevel {
875877
}
876878

877879
impl Options {
880+
/// Constructs the DBOptions and ColumnFamilyDescriptors by loading the
881+
/// latest RocksDB options file stored in the specified rocksdb database.
882+
pub fn load_latest<P: AsRef<Path>>(
883+
path: P,
884+
env: Env,
885+
ignore_unknown_options: bool,
886+
cache: Cache,
887+
) -> Result<(Options, Vec<ColumnFamilyDescriptor>), Error> {
888+
let path = to_cpath(path)?;
889+
let mut db_options: *mut ffi::rocksdb_options_t = null_mut();
890+
let mut num_column_families: usize = 0;
891+
let mut column_family_names: *mut *mut c_char = null_mut();
892+
let mut column_family_options: *mut *mut ffi::rocksdb_options_t = null_mut();
893+
unsafe {
894+
ffi_try!(ffi::rocksdb_load_latest_options(
895+
path.as_ptr(),
896+
env.0.inner,
897+
ignore_unknown_options,
898+
cache.0.inner,
899+
&mut db_options,
900+
&mut num_column_families,
901+
&mut column_family_names,
902+
&mut column_family_options,
903+
));
904+
}
905+
let options = Options {
906+
inner: db_options,
907+
outlive: OptionsMustOutliveDB::default(),
908+
};
909+
let column_families = unsafe {
910+
Options::read_column_descriptors(
911+
num_column_families,
912+
column_family_names,
913+
column_family_options,
914+
)
915+
};
916+
Ok((options, column_families))
917+
}
918+
919+
/// read column descriptors from c pointers
920+
#[inline]
921+
unsafe fn read_column_descriptors(
922+
num_column_families: usize,
923+
column_family_names: *mut *mut c_char,
924+
column_family_options: *mut *mut ffi::rocksdb_options_t,
925+
) -> Vec<ColumnFamilyDescriptor> {
926+
let column_family_names_iter =
927+
slice::from_raw_parts(column_family_names, num_column_families)
928+
.iter()
929+
.map(|ptr| from_cstr(*ptr));
930+
let column_family_options_iter =
931+
slice::from_raw_parts(column_family_options, num_column_families)
932+
.iter()
933+
.map(|ptr| Options {
934+
inner: *ptr,
935+
outlive: OptionsMustOutliveDB::default(),
936+
});
937+
let column_descriptors = column_family_names_iter
938+
.zip(column_family_options_iter)
939+
.map(|(name, options)| ColumnFamilyDescriptor { name, options })
940+
.collect::<Vec<_>>();
941+
// free pointers
942+
slice::from_raw_parts(column_family_names, num_column_families)
943+
.iter()
944+
.for_each(|ptr| ffi::rocksdb_free(*ptr as *mut c_void));
945+
ffi::rocksdb_free(column_family_names as *mut c_void);
946+
ffi::rocksdb_free(column_family_options as *mut c_void);
947+
column_descriptors
948+
}
949+
878950
/// By default, RocksDB uses only one background thread for flush and
879951
/// compaction. Calling this function will set it up such that total of
880952
/// `total_threads` is used. Good value for `total_threads` is the number of

tests/test_rocksdb_options.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,32 @@ mod util;
1616

1717
use std::{fs, io::Read as _};
1818

19-
use rocksdb::{BlockBasedOptions, DBCompressionType, DataBlockIndexType, Options, ReadOptions, DB};
19+
use rocksdb::{
20+
BlockBasedOptions, Cache, DBCompressionType, DataBlockIndexType, Env, Options, ReadOptions, DB,
21+
};
2022
use util::DBPath;
2123

24+
#[test]
25+
fn test_load_latest() {
26+
let n = DBPath::new("_rust_rocksdb_test_load_latest");
27+
{
28+
let mut opts = Options::default();
29+
opts.create_if_missing(true);
30+
opts.create_missing_column_families(true);
31+
let _ = DB::open_cf(&opts, &n, vec!["cf0", "cf1"]).unwrap();
32+
}
33+
let (_, cfs) = Options::load_latest(
34+
&n,
35+
Env::new().unwrap(),
36+
true,
37+
Cache::new_lru_cache(1024 * 8).unwrap(),
38+
)
39+
.unwrap();
40+
assert!(cfs.iter().any(|cf| cf.name() == "default"));
41+
assert!(cfs.iter().any(|cf| cf.name() == "cf0"));
42+
assert!(cfs.iter().any(|cf| cf.name() == "cf1"));
43+
}
44+
2245
#[test]
2346
fn test_set_num_levels() {
2447
let n = DBPath::new("_rust_rocksdb_test_set_num_levels");

0 commit comments

Comments
 (0)