diem_config/config/
mod.rs

1// Copyright (c) The Diem Core Contributors
2// SPDX-License-Identifier: Apache-2.0
3
4// Copyright 2021 Conflux Foundation. All rights reserved.
5// Conflux is free software and distributed under GNU General Public License.
6// See http://www.gnu.org/licenses/
7
8use serde::{de::DeserializeOwned, Deserialize, Serialize};
9use std::{
10    collections::HashMap,
11    fs::File,
12    io::{Read, Write},
13    path::{Path, PathBuf},
14};
15
16mod consensus_config;
17pub use consensus_config::*;
18mod error;
19pub use error::*;
20mod logger_config;
21pub use logger_config::*;
22mod mempool_config;
23pub use mempool_config::*;
24mod secure_backend_config;
25pub use secure_backend_config::*;
26mod storage_config;
27pub use storage_config::*;
28mod safety_rules_config;
29pub use safety_rules_config::*;
30
31/// Config pulls in configuration information from the config file.
32/// This is used to set up the nodes and configure various parameters.
33/// The config file is broken up into sections for each module
34/// so that only that module can be passed around
35#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
36#[serde(deny_unknown_fields)]
37pub struct NodeConfig {
38    #[serde(default)]
39    pub base: BaseConfig,
40    #[serde(default)]
41    pub consensus: ConsensusConfig,
42    #[serde(default)]
43    pub logger: LoggerConfig,
44    #[serde(default)]
45    pub mempool: MempoolConfig,
46    #[serde(default)]
47    pub storage: StorageConfig,
48    #[serde(default)]
49    pub failpoints: Option<HashMap<String, String>>,
50}
51
52#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
53#[serde(default, deny_unknown_fields)]
54pub struct BaseConfig {
55    data_dir: PathBuf,
56}
57
58impl Default for BaseConfig {
59    fn default() -> BaseConfig {
60        BaseConfig {
61            data_dir: PathBuf::from("./pos_db"),
62        }
63    }
64}
65
66impl NodeConfig {
67    pub fn data_dir(&self) -> &Path { &self.base.data_dir }
68
69    pub fn set_data_dir(&mut self, data_dir: PathBuf) {
70        self.base.data_dir = data_dir.clone();
71        self.consensus.set_data_dir(data_dir.clone());
72        self.storage.set_data_dir(data_dir);
73    }
74
75    /// Reads the config file and returns the configuration object in addition
76    /// to doing some post-processing of the config
77    /// Paths used in the config are either absolute or relative to the config
78    /// location
79    pub fn load<P: AsRef<Path>>(input_path: P) -> Result<Self, Error> {
80        let config = Self::load_config(&input_path)?;
81        Ok(config)
82    }
83
84    pub fn save<P: AsRef<Path>>(
85        &mut self, output_path: P,
86    ) -> Result<(), Error> {
87        self.save_config(&output_path)?;
88        Ok(())
89    }
90}
91
92pub trait PersistableConfig: Serialize + DeserializeOwned {
93    fn load_config<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
94        let mut file = File::open(&path).map_err(|e| {
95            Error::IO(path.as_ref().to_str().unwrap().to_string(), e)
96        })?;
97        let mut contents = String::new();
98        file.read_to_string(&mut contents).map_err(|e| {
99            Error::IO(path.as_ref().to_str().unwrap().to_string(), e)
100        })?;
101        Self::parse(&contents)
102    }
103
104    fn save_config<P: AsRef<Path>>(&self, output_file: P) -> Result<(), Error> {
105        let contents = yaml_serde::to_string(&self)
106            .map_err(|e| {
107                Error::Yaml(
108                    output_file.as_ref().to_str().unwrap().to_string(),
109                    e,
110                )
111            })?
112            .into_bytes();
113        let mut file = File::create(output_file.as_ref()).map_err(|e| {
114            Error::IO(output_file.as_ref().to_str().unwrap().to_string(), e)
115        })?;
116        file.write_all(&contents).map_err(|e| {
117            Error::IO(output_file.as_ref().to_str().unwrap().to_string(), e)
118        })?;
119        Ok(())
120    }
121
122    fn parse(serialized: &str) -> Result<Self, Error> {
123        yaml_serde::from_str(&serialized)
124            .map_err(|e| Error::Yaml("config".to_string(), e))
125    }
126}
127
128impl<T: ?Sized> PersistableConfig for T where T: Serialize + DeserializeOwned {}
129
130#[derive(Debug)]
131pub struct RootPath {
132    root_path: PathBuf,
133}
134
135impl RootPath {
136    pub fn new<P: AsRef<Path>>(path: P) -> Self {
137        let root_path = if let Some(parent) = path.as_ref().parent() {
138            parent.to_path_buf()
139        } else {
140            PathBuf::from("")
141        };
142
143        Self { root_path }
144    }
145
146    /// This function assumes that the path is already a directory
147    pub fn new_path<P: AsRef<Path>>(path: P) -> Self {
148        let root_path = path.as_ref().to_path_buf();
149        Self { root_path }
150    }
151
152    /// This adds a full path when loading / storing if one is not specified
153    pub fn full_path(&self, file_path: &Path) -> PathBuf {
154        if file_path.is_relative() {
155            self.root_path.join(file_path)
156        } else {
157            file_path.to_path_buf()
158        }
159    }
160}