From d820ef910db2f17825ec01144d4fc56438ee8e05 Mon Sep 17 00:00:00 2001 From: Sayan Nandan Date: Thu, 27 Jan 2022 21:13:19 -0800 Subject: [PATCH] Add config file impl using new config impl --- server/src/config/cfg2.rs | 39 ++++++++- server/src/config/cfgfile2.rs | 159 ++++++++++++++++++++++++++++++++++ server/src/config/mod.rs | 1 + 3 files changed, 196 insertions(+), 3 deletions(-) create mode 100644 server/src/config/cfgfile2.rs diff --git a/server/src/config/cfg2.rs b/server/src/config/cfg2.rs index 2c14bcae..01037c63 100644 --- a/server/src/config/cfg2.rs +++ b/server/src/config/cfg2.rs @@ -124,11 +124,15 @@ impl<'a, T: FromStr + 'a> TryFromConfigSource for Result { } #[derive(Debug)] +/// Since we have conflicting trait implementations, we define a custom `Option` type pub struct OptString { base: Option, } impl OptString { + pub const fn new(base: Option) -> Self { + Self { base } + } pub const fn new_null() -> Self { Self { base: None } } @@ -137,6 +141,12 @@ impl OptString { } } +impl From> for OptString { + fn from(base: Option) -> Self { + Self { base } + } +} + impl FromStr for OptString { type Err = (); fn from_str(st: &str) -> Result { @@ -146,6 +156,24 @@ impl FromStr for OptString { } } +impl TryFromConfigSource for OptString { + fn is_present(&self) -> bool { + self.base.is_some() + } + fn mutate_failed(self, target: &mut OptString, trip: &mut bool) -> bool { + if let Some(v) = self.base { + target.base = Some(v); + *trip = true; + } + false + } + fn try_parse(self) -> ConfigSourceParseResult { + self.base + .map(|v| ConfigSourceParseResult::Okay(OptString { base: Some(v) })) + .unwrap_or(ConfigSourceParseResult::Okay(OptString::new_null())) + } +} + #[derive(Debug)] /// A high-level configuration set that automatically handles errors, warnings and provides a convenient [`Result`] /// type that can be used @@ -179,9 +207,14 @@ impl Configset { pub fn new_cli() -> Self { Self::_new(Self::EMSG_CLI) } - /// Create a new configset for a config file + /// Create a new configset for config files pub fn new_file() -> Self { - Self::_new(Self::EMSG_FILE) + Self { + did_mutate: true, + cfg: ConfigurationSet::default(), + estack: ErrorStack::new(Self::EMSG_FILE), + wstack: WarningStack::new(Self::EMSG_FILE), + } } /// Mark the configset mutated fn mutated(&mut self) { @@ -425,7 +458,7 @@ impl Configset { "path to TLS cert passphrase", ); - let sslopts = SslOpts::new(key, cert, port, tls_pass.finish()); + let sslopts = SslOpts::new(key, cert, port, tls_pass.base); // now check if TLS only if tls_only { let host = self.cfg.ports.get_host(); diff --git a/server/src/config/cfgfile2.rs b/server/src/config/cfgfile2.rs new file mode 100644 index 00000000..6046fe6f --- /dev/null +++ b/server/src/config/cfgfile2.rs @@ -0,0 +1,159 @@ +/* + * Created on Fri Jan 28 2022 + * + * This file is a part of Skytable + * Skytable (formerly known as TerrabaseDB or Skybase) is a free and open-source + * NoSQL database written by Sayan Nandan ("the Author") with the + * vision to provide flexibility in data modelling without compromising + * on performance, queryability or scalability. + * + * Copyright (c) 2022, Sayan Nandan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * +*/ + +use super::cfg2::{ConfigSourceParseResult, Configset, OptString, TryFromConfigSource}; +use super::cfgfile::{Config as ConfigFile, ConfigKeyBGSAVE, ConfigKeySnapshot, KeySslOpts}; + +/// A custom non-null type for config files +pub struct NonNull { + val: T, +} + +impl From for NonNull { + fn from(val: T) -> Self { + Self { val } + } +} + +impl TryFromConfigSource for NonNull { + fn is_present(&self) -> bool { + true + } + fn mutate_failed(self, target: &mut T, trip: &mut bool) -> bool { + *target = self.val; + *trip = true; + false + } + fn try_parse(self) -> ConfigSourceParseResult { + ConfigSourceParseResult::Okay(self.val) + } +} + +pub struct Optional { + base: Option, +} + +impl Optional { + pub const fn some(val: T) -> Self { + Self { base: Some(val) } + } + pub const fn none() -> Self { + Self { base: None } + } +} + +impl From> for Optional { + fn from(base: Option) -> Self { + Self { base } + } +} + +impl TryFromConfigSource for Optional { + fn is_present(&self) -> bool { + self.base.is_some() + } + fn mutate_failed(self, target: &mut T, trip: &mut bool) -> bool { + if let Some(v) = self.base { + *trip = true; + *target = v; + } + false + } + fn try_parse(self) -> ConfigSourceParseResult { + match self.base { + Some(v) => ConfigSourceParseResult::Okay(v), + None => ConfigSourceParseResult::Absent, + } + } +} + +pub fn from_file(file: ConfigFile) -> Configset { + let mut set = Configset::new_file(); + let ConfigFile { + server, + bgsave, + snapshot, + ssl, + } = file; + // server settings + set.server_tcp( + Optional::some(server.host), + "server.host", + Optional::some(server.port), + "server.port", + ); + set.server_maxcon(Optional::from(server.maxclient), "server.maxcon"); + set.server_noart(Optional::from(server.noart), "server.noart"); + // bgsave settings + if let Some(bgsave) = bgsave { + let ConfigKeyBGSAVE { enabled, every } = bgsave; + set.bgsave_settings( + Optional::from(enabled), + "bgsave.enabled", + Optional::from(every), + "bgsave.every", + ); + } + // snapshot settings + if let Some(snapshot) = snapshot { + let ConfigKeySnapshot { + every, + atmost, + failsafe, + } = snapshot; + set.snapshot_settings( + NonNull::from(every), + "snapshot.every", + NonNull::from(atmost), + "snapshot.atmost", + Optional::from(failsafe), + "snapshot.failsafe", + ); + } + // TLS settings + if let Some(tls) = ssl { + let KeySslOpts { + key, + chain, + port, + only, + passin, + } = tls; + set.tls_settings( + NonNull::from(key), + "ssl.key", + NonNull::from(chain), + "ssl.chain", + NonNull::from(port), + "ssl.port", + Optional::from(only), + "ssl.only", + OptString::from(passin), + "ssl.passin", + ); + } + set +} diff --git a/server/src/config/mod.rs b/server/src/config/mod.rs index feff006c..356244cb 100644 --- a/server/src/config/mod.rs +++ b/server/src/config/mod.rs @@ -42,6 +42,7 @@ mod cfgfile; mod cfg2; mod cfgcli2; mod cfgenv2; +mod cfgfile2; mod eval; #[cfg(test)] mod tests;