From: Ian Jackson Date: Fri, 13 Nov 2020 21:26:35 +0000 (+0000) Subject: break out config module X-Git-Tag: otter-0.2.0~522 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=2950f961fac33e3082b852a0278653cc663579d3;p=otter.git break out config module Signed-off-by: Ian Jackson --- diff --git a/src/bin/otter.rs b/src/bin/otter.rs index 11d6f2d3..aac62c3b 100644 --- a/src/bin/otter.rs +++ b/src/bin/otter.rs @@ -197,7 +197,7 @@ fn main() { let config = Thunk::new(||{ ServerConfig::read(config_filename.as_ref().map(String::as_str)) .context("read config file")?; - Ok::<_,AE>(otter::global::config()) + Ok::<_,AE>(otter::config::config()) }); let socket_path = socket_path.map(Ok::<_,APE>).unwrap_or_else(||{ Ok(config.as_ref()?.command_socket.clone()) diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 00000000..a05841a8 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,130 @@ +// Copyright 2020 Ian Jackson +// SPDX-License-Identifier: AGPL-3.0-or-later +// There is NO WARRANTY. + +use crate::imports::*; + +const DEFAULT_CONFIG_FILENAME : &str = "server.toml"; + +const DEFAULT_SAVE_DIRECTORY : &str = "save"; +const DEFAULT_COMMAND_SOCKET : &str = "command.socket"; // in save dir +const DEFAULT_TEMPLATE_DIR : &str = "templates"; +const DEFAULT_LIBRARY_DIR : &str = "library"; +const DEFAULT_WASM_DIR : &str = "target/packed-wasm"; + +#[derive(Deserialize,Debug,Clone)] +pub struct ServerConfigSpec { + pub save_directory: Option, + pub command_socket: Option, + pub debug: Option, + pub http_port: Option, + pub rocket_workers: Option, + pub template_dir: Option, + pub wasm_dir: Option, + pub log: Option, + pub bundled_sources: Option, + pub shapelibs: Option>, +} + +#[derive(Debug,Clone)] +pub struct ServerConfig { + pub save_directory: String, + pub command_socket: String, + pub debug: bool, + pub http_port: Option, + pub rocket_workers: u16, + pub template_dir: String, + pub wasm_dir: String, + pub log: LogSpecification, + pub bundled_sources: String, + pub shapelibs: Vec, +} + +impl TryFrom for ServerConfig { + type Error = AE; + #[throws(Self::Error)] + fn try_from(spec: ServerConfigSpec) -> ServerConfig { + let ServerConfigSpec { + save_directory, command_socket, debug, + http_port, rocket_workers, template_dir, wasm_dir, + log, bundled_sources, shapelibs, + } = spec; + + let save_directory = save_directory + .unwrap_or_else(|| DEFAULT_SAVE_DIRECTORY.to_owned()); + + let mut command_socket = command_socket + .unwrap_or_else(|| DEFAULT_COMMAND_SOCKET.to_owned()); + if !command_socket.starts_with('/') { + command_socket = format!("{}/{}", save_directory, command_socket); + } + + let debug = debug.unwrap_or(cfg!(debug_assertions)); + let rocket_workers = rocket_workers.unwrap_or( + if debug { 20 } else { 1000 }); + + let template_dir = template_dir + .unwrap_or_else(|| DEFAULT_TEMPLATE_DIR.to_owned()); + + let log = { + use toml::Value::Table; + match log { + None => Table(Default::default()), + Some(log @Table(_)) => log, + Some(x) => throw!(anyhow!( + r#"wanted table for "log" config key, not {}"#, + x.type_str()) + ), + } + }; + let log = toml::to_string(&log)?; + let log = LogSpecification::from_toml(&log) + .context("log specification")?; + + let bundled_sources = bundled_sources + .unwrap_or_else(|| save_directory.clone()); + + let shapelibs = shapelibs.unwrap_or_else( + ||vec![ shapelib::Config1::PathGlob( + format!("{}/*.toml", DEFAULT_LIBRARY_DIR) + )]); + + let wasm_dir = wasm_dir.unwrap_or_else(|| DEFAULT_WASM_DIR.to_owned()); + + ServerConfig { + save_directory, command_socket, debug, + http_port, rocket_workers, template_dir, wasm_dir, + log, bundled_sources, shapelibs, + } + } +} + +pub fn config() -> Arc { + GLOBAL.config.read().unwrap().clone() +} + +fn set_config(config: ServerConfig) { + *GLOBAL.config.write().unwrap() = Arc::new(config) +} + +impl ServerConfig { + #[throws(StartupError)] + pub fn read(config_filename: Option<&str>) { + let config_filename = config_filename + .unwrap_or_else(|| DEFAULT_CONFIG_FILENAME); + let mut buf = String::new(); + File::open(&config_filename).with_context(||config_filename.to_string())? + .read_to_string(&mut buf)?; + let config : ServerConfigSpec = toml::de::from_str(&buf)?; + let config = config.try_into()?; + set_config(config); + } +} + +impl Default for ServerConfig { + fn default() -> ServerConfig { + let spec : ServerConfigSpec = toml::de::from_str("") + .expect("parse empty string as ServerConfigSpec"); + spec.try_into().expect("empty spec into config") + } +} diff --git a/src/global.rs b/src/global.rs index b480129c..64fd7f67 100644 --- a/src/global.rs +++ b/src/global.rs @@ -196,7 +196,7 @@ pub struct Global { // inner locks which the game needs: dirty : Mutex>, - config : RwLock>, + pub config: RwLock>, // fast global lookups players : RwLock>, @@ -1354,130 +1354,3 @@ pub fn logs_periodic_expiry() { global_expire_old_logs(); } } - -// ========== server config ========== - -const DEFAULT_CONFIG_FILENAME : &str = "server.toml"; - -const DEFAULT_SAVE_DIRECTORY : &str = "save"; -const DEFAULT_COMMAND_SOCKET : &str = "command.socket"; // in save dir -const DEFAULT_TEMPLATE_DIR : &str = "templates"; -const DEFAULT_LIBRARY_DIR : &str = "library"; -const DEFAULT_WASM_DIR : &str = "target/packed-wasm"; - -#[derive(Deserialize,Debug,Clone)] -pub struct ServerConfigSpec { - pub save_directory: Option, - pub command_socket: Option, - pub debug: Option, - pub http_port: Option, - pub rocket_workers: Option, - pub template_dir: Option, - pub wasm_dir: Option, - pub log: Option, - pub bundled_sources: Option, - pub shapelibs: Option>, -} - -#[derive(Debug,Clone)] -pub struct ServerConfig { - pub save_directory: String, - pub command_socket: String, - pub debug: bool, - pub http_port: Option, - pub rocket_workers: u16, - pub template_dir: String, - pub wasm_dir: String, - pub log: LogSpecification, - pub bundled_sources: String, - pub shapelibs: Vec, -} - -impl TryFrom for ServerConfig { - type Error = AE; - #[throws(Self::Error)] - fn try_from(spec: ServerConfigSpec) -> ServerConfig { - let ServerConfigSpec { - save_directory, command_socket, debug, - http_port, rocket_workers, template_dir, wasm_dir, - log, bundled_sources, shapelibs, - } = spec; - - let save_directory = save_directory - .unwrap_or_else(|| DEFAULT_SAVE_DIRECTORY.to_owned()); - - let mut command_socket = command_socket - .unwrap_or_else(|| DEFAULT_COMMAND_SOCKET.to_owned()); - if !command_socket.starts_with('/') { - command_socket = format!("{}/{}", save_directory, command_socket); - } - - let debug = debug.unwrap_or(cfg!(debug_assertions)); - let rocket_workers = rocket_workers.unwrap_or( - if debug { 20 } else { 1000 }); - - let template_dir = template_dir - .unwrap_or_else(|| DEFAULT_TEMPLATE_DIR.to_owned()); - - let log = { - use toml::Value::Table; - match log { - None => Table(Default::default()), - Some(log @Table(_)) => log, - Some(x) => throw!(anyhow!( - r#"wanted table for "log" config key, not {}"#, - x.type_str()) - ), - } - }; - let log = toml::to_string(&log)?; - let log = LogSpecification::from_toml(&log) - .context("log specification")?; - - let bundled_sources = bundled_sources - .unwrap_or_else(|| save_directory.clone()); - - let shapelibs = shapelibs.unwrap_or_else( - ||vec![ shapelib::Config1::PathGlob( - format!("{}/*.toml", DEFAULT_LIBRARY_DIR) - )]); - - let wasm_dir = wasm_dir.unwrap_or_else(|| DEFAULT_WASM_DIR.to_owned()); - - ServerConfig { - save_directory, command_socket, debug, - http_port, rocket_workers, template_dir, wasm_dir, - log, bundled_sources, shapelibs, - } - } -} - -pub fn config() -> Arc { - GLOBAL.config.read().unwrap().clone() -} - -fn set_config(config: ServerConfig) { - *GLOBAL.config.write().unwrap() = Arc::new(config) -} - -impl ServerConfig { - #[throws(StartupError)] - pub fn read(config_filename: Option<&str>) { - let config_filename = config_filename - .unwrap_or_else(|| DEFAULT_CONFIG_FILENAME); - let mut buf = String::new(); - File::open(&config_filename).with_context(||config_filename.to_string())? - .read_to_string(&mut buf)?; - let config : ServerConfigSpec = toml::de::from_str(&buf)?; - let config = config.try_into()?; - set_config(config); - } -} - -impl Default for ServerConfig { - fn default() -> ServerConfig { - let spec : ServerConfigSpec = toml::de::from_str("") - .expect("parse empty string as ServerConfigSpec"); - spec.try_into().expect("empty spec into config") - } -} diff --git a/src/imports.rs b/src/imports.rs index c0f3c489..3edb9429 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -128,6 +128,7 @@ pub use crate::spec::*; pub use crate::debugreader::DebugReader; pub use crate::shapelib; pub use crate::tz::*; +pub use crate::config::*; pub use crate::accounts::*; pub use crate::accounts::loaded_acl::{self,LoadedAcl,EffectiveACL,PermSet}; diff --git a/src/lib.rs b/src/lib.rs index 51c5a11c..8bf731e7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,4 +26,5 @@ pub mod debugreader; pub mod shapelib; pub mod tz; pub mod accounts; +pub mod config; #[path="slotmap-slot-idx.rs"] pub mod slotmap_slot_idx;