1414
1515use std:: ffi:: CStr ;
1616use std:: path:: Path ;
17+ use std:: ptr:: null_mut;
18+ use std:: slice;
1719use std:: sync:: Arc ;
1820
1921use 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
3537fn new_cache ( capacity : size_t ) -> * mut ffi:: rocksdb_cache_t {
@@ -875,6 +877,76 @@ pub enum LogLevel {
875877}
876878
877879impl 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
0 commit comments