From: Ian Jackson Date: Fri, 23 Jul 2021 23:33:45 +0000 (+0100) Subject: wip resolve X-Git-Tag: hippotat/1.0.0~507 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=hippotat.git;a=commitdiff_plain;h=dc51e2fc65960d8986d848d28cc9688000870558 wip resolve Signed-off-by: Ian Jackson --- diff --git a/README.config b/README.config index 37142b8..4afc45a 100644 --- a/README.config +++ b/README.config @@ -3,18 +3,20 @@ Sections [ ] - [ LIMIT] [] [] often [SERVER] - [LIMIT] [COMMON] - [DEFAULT] Keys are looked up in that order, unless otherwise specified. is the client's virtual address. must be a valid lowercase DNS hostname and not look like an address, or be COMMON, DEFAULT or SERVER. +There are also: + + [ LIMIT] + [LIMIT] + Things not in a section are an error. diff --git a/src/config.rs b/src/config.rs index 63665f9..60c090b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -26,16 +26,16 @@ pub struct CidrString(pub String); pub struct InstanceConfig { // Exceptional settings pub server: String, - pub secret: String, + pub secret: String, // make a newytpe pub ipif: String, // Capped settings: pub max_batch_down: u32, pub max_queue_time: Duration, pub http_timeout: Duration, + pub target_requests_outstanding: u32, // Ordinary settings: - pub target_requests_outstanding: u32, pub addrs: Vec, pub vnetwork: Vec, pub vaddr: Vec, @@ -59,7 +59,7 @@ pub struct InstanceConfig { #[derive(Debug,Clone,Hash,Eq,PartialEq)] pub enum SectionName { - Link { server: ServerName, client: ClientName }, + Link(LinkName), Client(ClientName), Server(ServerName), // includes SERVER, which is slightly special ServerLimit(ServerName), @@ -69,6 +69,12 @@ pub enum SectionName { } pub use SectionName as SN; +#[derive(Debug,Clone,Hash,Eq,PartialEq)] +struct LinkName { + server: ServerName, + client: ClientName, +} + #[derive(Debug,Clone)] struct RawVal { val: Option, loc: Arc } type SectionMap = HashMap; @@ -116,7 +122,7 @@ impl FromStr for SectionName { let server = server.parse().context("server name in link section name")?; if client == "LIMIT" { return SN::ServerLimit(server) } let client = client.parse().context("client name in link section name")?; - SN::Link { server, client } + SN::Link(LinkName { server, client }) } } @@ -252,6 +258,102 @@ impl Aggregate { } } +enum LinkEnd { Server, Client } + +struct ResolveContext<'c> { + agg: &'c Aggregate, + link: &'c LinkName, + end: LinkEnd, +} + +impl<'c> ResolveContext<'c> { + fn first_of_raw(&self, key: &str, + sections: &[ &dyn Fn() -> SectionName ]) + -> Option<&'c RawVal> { + for section in sections { + if let Some(raw) = self.agg.sections + .get(§ion()) + .and_then(|vars: &SectionMap| vars.get(key)) + { + return Some(raw) + } + } + None + } + + #[throws(AE)] + fn first_of(&self, key: &str, + sections: &[ &dyn Fn() -> SectionName ]) + -> Option + where T: FromStr + { + match self.first_of_raw(key, sections) { + None => None, + Some(raw) => Some({ + raw.val.parse() + .context(key) + .context(r#"in section "{}""#, &raw.section) + .dcontext(&raw.loc)? + }), + } + } + + pub fn ordinary(&self, key: &str) -> T where T: FromStr + Default { + self.first_of(key, &[ + || SN::Link(self.link.clone()), + || SN::Client(self.link.client.clone()), + || SN::Server(self.link.server.clone()), + || SN::Common, + ])? + .unwrap_or_default() + } + + pub fn limited(&self, key: &str) -> T + where T: FromStr + Default + PartialOrd + { + let val = self.ordinary(key); + if let Some(limit) = self.first_of(key, &[ + || SN::LimitServer(self.link.server.clone()), + || SN::LimitGlobal, + ])? { + val = min(val, limit) + } + val + } + + pub fn client(&self, key: &str) -> T where T: FromStr + Default { + match self.end { + LinkEnd::Client => self.ordinary(key)?, + LinkEnd::Server => default(), + } + } + pub fn server(&self, key: &str) -> T where T: FromStr + Default { + match self.end { + LinkEnd::Server => self.ordinary(key)?, + LinkEnd::Client => default(), + } + } + + pub fn special_ipif(&self, key: &str) -> T where T: FromStr + Default { + match self.end { + LinkEnd::Client => self.ordinary(key)?, + LinkEnd::Server => { + self.first_of(key, &[ + || SN::Common, + || SN::Server(self.link.server.clone()), + ])? + }, + } + } +} + +/* +fn resolve_instance_config() { + InstanceConfig { + max_batch_down: resolve::limited(&agg, "max_batch_down") + } +} +*/ #[throws(AE)] pub fn read() { diff --git a/src/prelude.rs b/src/prelude.rs index bac8d9d..29336ff 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -3,6 +3,7 @@ // There is NO WARRANTY. pub use std::collections::HashMap; +pub use std::cmp::{min, max}; pub use std::fs; pub use std::fmt::Debug; pub use std::io::{self, ErrorKind, Read as _}; @@ -28,3 +29,5 @@ pub use crate::types::*; pub use anyhow::Error as AE; pub use ErrorKind as EK; + +pub fn default() -> T { Default::default() }