1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
use std::ffi::{CStr, CString};
use std::ptr;
use std::path::Path;

use crate::db::ColumnFamilyDescriptor;
use crate::options::{ColumnFamilyOptions, DBOptions};
use crate::to_raw::{FromRaw, ToRaw};
use crate::{Error, Result};

use rocks_sys as ll;

pub fn load_latest_options(path: &str) -> Result<(DBOptions, Vec<ColumnFamilyDescriptor>)> {
    let cpath = CString::new(path).unwrap();
    let db_opt = DBOptions::default();
    let mut cf_descs_len = 0_usize;
    let mut status = ptr::null_mut();
    let mut cf_descs: Vec<ColumnFamilyDescriptor> = Vec::new();

    let c_cf_descs =
        unsafe { ll::rocks_load_latest_options(cpath.as_ptr(), db_opt.raw(), &mut cf_descs_len, &mut status) };
    if let Err(error) = Error::from_ll(status) {
        return Err(error);
    }
    for i in 0..cf_descs_len {
        let c_cf_desc = unsafe { *c_cf_descs.offset(i as _) };
        let name = unsafe { CStr::from_ptr(ll::rocks_column_family_descriptor_get_name(c_cf_desc)) };
        let cfopt =
            unsafe { ColumnFamilyOptions::from_ll(ll::rocks_column_family_descriptor_get_cfoptions(c_cf_desc)) };
        cf_descs.push(ColumnFamilyDescriptor::new(
            name.to_str().expect("non-utf8 cf name"),
            cfopt,
        ));
    }
    unsafe { ll::rocks_load_options_destroy_cf_descs(c_cf_descs, cf_descs_len) };

    Ok((db_opt, cf_descs))
}


#[cfg(unix)]
#[inline]
pub(crate) fn path_to_bytes<P: AsRef<Path>>(path: P) -> Vec<u8> {
    use std::os::unix::ffi::OsStrExt;
    path.as_ref().as_os_str().as_bytes().to_vec()
}

#[cfg(not(unix))]
#[inline]
pub(crate) fn path_to_bytes<P: AsRef<Path>>(path: P) -> Vec<u8> {
    // On Windows, could use std::os::windows::ffi::OsStrExt to encode_wide(),
    // but you end up with a Vec<u16> instead of a Vec<u8>, so that doesn't
    // really help.
    path.as_ref().to_string_lossy().to_string().into_bytes()
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    #[ignore]
    fn load_options() {
        let (dbopt, cf_descs) = load_latest_options("./data").unwrap();
        println!("db opt => {:?}", dbopt);
        for cf_desc in cf_descs {
            println!("name => {:?}", cf_desc.name());
            println!("opt =>\n{:?}", cf_desc.options());
        }
    }
}