db_core/system/
config.rs

1//! Configuration management.
2
3
4use crate::common::errors::Error;
5use std::fs::OpenOptions;
6use std::io::{BufRead, BufReader};
7use std::sync::Arc;
8use std::sync::Mutex;
9use std::sync::MutexGuard;
10use log::warn;
11
12
13#[derive(Clone)]
14/// Global configuration with multithreading support.
15pub struct ConfigMt {
16    conf: Arc<Mutex<Config>>,
17}
18
19impl ConfigMt {
20    /// Create a new configuration instance.
21    pub fn new() -> ConfigMt {
22        ConfigMt {
23            conf: Arc::new(Mutex::new(Config::new()))
24        }
25    }
26
27    /// Lock and return configration for reading or modification.
28    pub fn get_conf(&self) -> MutexGuard<Config> {
29        self.conf.lock().unwrap()
30    }
31}
32
33macro_rules! gen_config {
34    ( $( $name:ident, $data_type:ty, $default_val:expr, $get_fn:ident, $set_fn:ident, $str_name:literal, $conv_fn:path ), *) => {
35        /// Struct to access configuration values.
36        pub struct Config {
37            $(
38                $name: $data_type,
39            )*
40        }
41
42        impl Config {
43        
44            /// Create a new configuration instance.
45            pub fn new() -> Config {
46                Config {
47                    $(
48                        $name: $default_val, 
49                    )*
50                }
51            }
52
53            $(
54                /// Get value of a parameter.
55                pub fn $get_fn(&self) -> &$data_type {
56                    &self.$name
57                }
58
59                /// Set value of a parameter.
60                pub fn $set_fn(&mut self, $name: $data_type) {
61                    self.$name = $name;
62                }
63            )*
64
65            fn process_config_file_entry(&mut self, name: &str, val: &str) -> Result<(), Error> {
66
67                match name {
68                    $(
69                        $str_name => { self.$name = $conv_fn(val)?; },
70                    )*
71                    _ => warn!("Skipping unexpected config entry: {}", name)
72                };
73
74                Ok(())
75            }
76        }
77    }
78}
79
80
81impl Config {
82
83    /// Load configuration from a file.
84    pub fn load(&mut self, file_path: &str) -> Result<(), Error> {
85        let f = BufReader::new(OpenOptions::new()
86            .create(false)
87            .write(false)
88            .read(true)
89            .truncate(false)
90            .open(file_path)?);
91
92        for line in f.lines() {
93            if let Ok(line) = line {
94                if let Ok((name, val)) = Self::process_config_file_line(&line) {
95                    self.process_config_file_entry(name, val)?;
96                }
97            }
98        }
99
100        Ok(())
101    }
102
103    fn process_config_file_line<'a>(s: &'a str) -> Result<(&'a str, &'a str), ()> {
104        let line = s.as_bytes();
105        let mut p = 0;
106
107        // skip space
108        while line[p] == b' ' || line[p] == b'\t' { p += 1; };
109
110        // check for comment line
111        if line[p] == b'#' { return Err(()) }
112
113        // read 'name' part
114        let p1 = p;
115        while (line[p] >= b'a' && line[p] <= b'z') 
116            || (line[p] >= b'A' && line[p] <= b'Z')
117            || (line[p] >= b'0' && line[p] <= b'9')
118            || line[p] == b'_' || line[p] == b'-' 
119        {
120                p+= 1;
121        }
122        if p == p1 { return Err(()) }
123        let p2 = p;
124
125        // read '='
126        while line[p] == b' ' || line[p] == b'\t' { p += 1; };
127        if line[p] != b'=' { return Err(()) }
128        while line[p] == b' ' || line[p] == b'\t' { p += 1; };
129
130        // return 'name' and 'val'
131        Ok((&s[p1..p2], &s[p..]))
132    }
133
134    fn load_string(value: &str) -> Result<String, Error> {
135        Ok(String::from(value))
136    }
137
138    fn load_u32_val(value: &str) -> Result<u32, Error> {
139        let ret = str::parse::<u32>(value)?;
140        Ok(ret)
141    }
142
143    fn load_u64_val(value: &str) -> Result<u64, Error> {
144        let ret = str::parse::<u64>(value)?;
145        Ok(ret)
146    }
147}
148
149gen_config![log_dir,            String, "trnlog".to_owned(),    get_log_dir,                   set_log_dir,                   "log_dir", Config::load_string,
150    datastore_path,             String, ".".to_owned(),         get_datastore_path,            set_datastore_path,            "datastore_path", Config::load_string,
151    max_log_file_size,          u32,    10*1024*1024,           get_max_log_file_size,         set_max_log_file_size,         "max_log_file_size", Config::load_u32_val,
152    log_writer_buf_size,        u32,    1048576,                get_log_writer_buf_size,       set_log_writer_buf_size,       "log_writer_buf_size", Config::load_u32_val,
153    tran_mgr_n_buckets,         u32,    128,                    get_tran_mgr_n_buckets,        set_tran_mgr_n_buckets,        "tran_mgr_n_buckets", Config::load_u32_val,
154    tran_mgr_n_tran,            u32,    1024,                   get_tran_mgr_n_tran,           set_tran_mgr_n_tran,           "tran_mgr_n_tran", Config::load_u32_val,
155    tran_mgr_n_obj_buckets,     u32,    128,                    get_tran_mgr_n_obj_buckets,    set_tran_mgr_n_obj_buckets,    "tran_mgr_n_obj_buckets", Config::load_u32_val,
156    tran_mgr_n_obj_lock,        u32,    1024,                   get_tran_mgr_n_obj_lock,       set_tran_mgr_n_obj_lock,       "tran_mgr_n_obj_lock", Config::load_u32_val,
157    block_mgr_n_lock,           u32,    1024,                   get_block_mgr_n_lock,          set_block_mgr_n_lock,          "block_mgr_n_lock", Config::load_u32_val,
158    free_info_n_file_lock,      u32,    16,                     get_free_info_n_file_lock,     set_free_info_n_file_lock,     "free_info_n_file_lock", Config::load_u32_val,
159    free_info_n_extent_lock,    u32,    128,                    get_free_info_n_extent_lock,   set_free_info_n_extent_lock,   "free_info_n_extent_lock", Config::load_u32_val,
160    block_buf_size,             u64,    32*1024*1024,           get_block_buf_size,            set_block_buf_size,            "block_buf_size", Config::load_u64_val,
161    checkpoint_data_threshold,  u64,    10*1024*1024,           get_checkpoint_data_threshold, set_checkpoint_data_threshold, "checkpoint_data_threshold", Config::load_u64_val,
162    version_retain_time,        u32,    3600,                   get_version_retain_time,       set_version_retain_time,       "version_retain_time", Config::load_u32_val,
163    block_fill_ratio,           u32,    80,                     get_block_fill_ratio,          set_block_fill_ratio,          "block_fill_ratio", Config::load_u32_val,
164    writer_num,                 u32,    2,                      get_writer_num,                set_writer_num,                "writer_num", Config::load_u32_val];
165
166        
167
168