Commit d6099740 authored by nanamicat's avatar nanamicat

Update

parent 9d847083
...@@ -95,23 +95,18 @@ pub struct Database { ...@@ -95,23 +95,18 @@ pub struct Database {
pub connections: BTreeMap<RouterID, BTreeMap<RouterID, Connection>>, pub connections: BTreeMap<RouterID, BTreeMap<RouterID, Connection>>,
} }
pub static DATABASE: std::sync::LazyLock<Database> = std::sync::LazyLock::new(|| Database::load()); pub static DATABASE: std::sync::LazyLock<Database> = std::sync::LazyLock::new(|| Database {
routers: register(load_file("import/data/Router.json"), |r| r.id.0, |r| r.name.clone(), &ROUTER_ID_REGISTRY),
gateways: load_file("import/data/Gateway.json"),
gateway_groups: load_file("import/data/GatewayGroup.json"),
regions: load_file("import/data/Region.json"),
connections: load_file("import/connections.json"),
});
static ROUTER_ID_REGISTRY: OnceLock<StringInterner<StringBackend<RouterID>>> = OnceLock::new(); static ROUTER_ID_REGISTRY: OnceLock<StringInterner<StringBackend<RouterID>>> = OnceLock::new();
impl Database { fn load_file<T: serde::de::DeserializeOwned>(path: &str) -> T {
pub fn load() -> Self { serde_json::from_str(&std::fs::read_to_string(path).unwrap()).unwrap()
Self {
routers: register(Self::load_file("import/data/Router.json"), |r| r.id.0, |r| r.name.clone(), &ROUTER_ID_REGISTRY),
gateways: Self::load_file("import/data/Gateway.json"),
gateway_groups: Self::load_file("import/data/GatewayGroup.json"),
regions: Self::load_file("import/data/Region.json"),
connections: Self::load_file("import/connections.json"),
}
}
fn load_file<T: serde::de::DeserializeOwned>(path: &str) -> T {
serde_json::from_str(&std::fs::read_to_string(path).unwrap()).unwrap()
}
} }
pub fn register<T, I, N, S, Sym>(mut data: Vec<T>, num: N, str: S, registry: &OnceLock<StringInterner<StringBackend<Sym>>>) -> Vec<T> pub fn register<T, I, N, S, Sym>(mut data: Vec<T>, num: N, str: S, registry: &OnceLock<StringInterner<StringBackend<Sym>>>) -> Vec<T>
...@@ -147,18 +142,22 @@ fn deserialize_router_id<'de, D>(deserializer: D) -> Result<RouterID, D::Error> ...@@ -147,18 +142,22 @@ fn deserialize_router_id<'de, D>(deserializer: D) -> Result<RouterID, D::Error>
where where
D: serde::Deserializer<'de>, D: serde::Deserializer<'de>,
{ {
let s = String::deserialize(deserializer)?; ROUTER_ID_REGISTRY
ROUTER_ID_REGISTRY.get().unwrap().get(&s).ok_or_else(|| serde::de::Error::custom(format!("Unknown router: {s}"))) .get()
.unwrap()
.get(&String::deserialize(deserializer)?)
.ok_or_else(|| serde::de::Error::custom(format!("Unknown router")))
} }
fn serialize_router_id<S>(id: &RouterID, serializer: S) -> Result<S::Ok, S::Error> fn serialize_router_id<S>(id: &RouterID, serializer: S) -> Result<S::Ok, S::Error>
where where
S: serde::Serializer, S: serde::Serializer,
{ {
let s = ROUTER_ID_REGISTRY serializer.serialize_str(
.get() ROUTER_ID_REGISTRY
.unwrap() .get()
.resolve(*id) .unwrap()
.ok_or_else(|| serde::ser::Error::custom(format!("Unknown id: {}", id.0)))?; .resolve(*id)
serializer.serialize_str(s) .ok_or_else(|| serde::ser::Error::custom(format!("Unknown id: {}", id.0)))?,
)
} }
...@@ -33,7 +33,6 @@ async fn main() -> Result<()> { ...@@ -33,7 +33,6 @@ async fn main() -> Result<()> {
tracing_subscriber::fmt::init(); tracing_subscriber::fmt::init();
let config: Settings = Config::builder().add_source(Environment::default()).build()?.try_deserialize()?; let config: Settings = Config::builder().add_source(Environment::default()).build()?.try_deserialize()?;
let regions: Vec<RegionID> = DATABASE.regions.iter().enumerate().map(|(i, _)| RegionID(i as u8)).collect();
let gateways_group: BTreeMap<GatewayGroupID, Vec<&data::Gateway>> = DATABASE let gateways_group: BTreeMap<GatewayGroupID, Vec<&data::Gateway>> = DATABASE
.gateway_groups .gateway_groups
.iter() .iter()
...@@ -43,7 +42,7 @@ async fn main() -> Result<()> { ...@@ -43,7 +42,7 @@ async fn main() -> Result<()> {
}) })
.collect(); .collect();
let routers: BTreeMap<RouterID, Router> = DATABASE.routers.iter().map(|c| (c.id, Router::new(c, &regions, &gateways_group))).collect(); let routers: BTreeMap<RouterID, Router> = DATABASE.routers.iter().map(|c| (c.id, Router::new(c, &gateways_group))).collect();
let routers = Arc::new(RwLock::new(routers)); let routers = Arc::new(RwLock::new(routers));
let listener = tokio::net::TcpListener::bind(config.http_bind).await?; let listener = tokio::net::TcpListener::bind(config.http_bind).await?;
...@@ -88,7 +87,7 @@ async fn main() -> Result<()> { ...@@ -88,7 +87,7 @@ async fn main() -> Result<()> {
&& let Some(router) = routers.get(&uplink.id) && let Some(router) = routers.get(&uplink.id)
&& router.is_online() && router.is_online()
&& router.last_update != now && router.last_update != now
&& let Some(downlink) = router.update(now, &routers, &regions, &gateways_group) && let Some(downlink) = router.update(now, &routers, &gateways_group)
{ {
updating.router_id = router.id; updating.router_id = router.id;
updating.message = downlink; updating.message = downlink;
......
...@@ -34,7 +34,7 @@ impl PartialEq<Self> for Router { ...@@ -34,7 +34,7 @@ impl PartialEq<Self> for Router {
impl Eq for Router {} impl Eq for Router {}
impl Router { impl Router {
pub fn new(data: &data::Router, regions: &Vec<RegionID>, gateway_groups: &BTreeMap<GatewayGroupID, Vec<&data::Gateway>>) -> Self { pub fn new(data: &data::Router, gateway_groups: &BTreeMap<GatewayGroupID, Vec<&data::Gateway>>) -> Self {
Self { Self {
id: data.id, id: data.id,
version: rand::random(), version: rand::random(),
...@@ -45,14 +45,16 @@ impl Router { ...@@ -45,14 +45,16 @@ impl Router {
.map(|(&from, _)| (from, Default::default())) .map(|(&from, _)| (from, Default::default()))
.collect(), .collect(),
via: DATABASE.routers.iter().filter(|r| r.id != data.id).map(|r| (r.id, r.id)).collect(), via: DATABASE.routers.iter().filter(|r| r.id != data.id).map(|r| (r.id, r.id)).collect(),
plan: regions plan: DATABASE
.regions
.iter() .iter()
.map(|&region| { .enumerate()
.map(|(r, _)| {
( (
region, RegionID(r as u8),
gateway_groups gateway_groups
.iter() .iter()
.map(|(&gid, gws)| (gid, gws.iter().min_by_key(|gw| Self::guess_metric(data, gw, &region)).unwrap().id)) .map(|(&gid, gws)| (gid, gws.iter().min_by_key(|gw| Self::guess_metric(data, gw, r)).unwrap().id))
.collect(), .collect(),
) )
}) })
...@@ -63,10 +65,8 @@ impl Router { ...@@ -63,10 +65,8 @@ impl Router {
} }
} }
fn guess_metric(data: &data::Router, gw: &data::Gateway, region: &RegionID) -> i32 { fn guess_metric(data: &data::Router, gw: &data::Gateway, region: usize) -> i32 {
gw.metrics[region.0 as usize] gw.metrics[region].saturating_add(gw.cost_outbound).saturating_add(if gw.router == data.id { 0 } else { 100 })
.saturating_add(gw.cost_outbound)
.saturating_add(if gw.router == data.id { 0 } else { 100 })
} }
pub fn online(&mut self, addr: SocketAddr, now: Instant) { pub fn online(&mut self, addr: SocketAddr, now: Instant) {
...@@ -144,7 +144,7 @@ impl Router { ...@@ -144,7 +144,7 @@ impl Router {
} }
} }
pub fn update(&self, now: Instant, routers: &BTreeMap<RouterID, Router>, regions: &Vec<RegionID>, gateway_groups: &BTreeMap<GatewayGroupID, Vec<&data::Gateway>>) -> Option<Downlink> { pub fn update(&self, now: Instant, routers: &BTreeMap<RouterID, Router>, gateway_groups: &BTreeMap<GatewayGroupID, Vec<&data::Gateway>>) -> Option<Downlink> {
let penalty = PENALTY_MIN + (PENALTY as f32 * f32::exp2(-now.duration_since(self.last_update).div_duration_f32(HALF_LIFE))) as i32; let penalty = PENALTY_MIN + (PENALTY as f32 * f32::exp2(-now.duration_since(self.last_update).div_duration_f32(HALF_LIFE))) as i32;
let mut changed_via = BTreeMap::new(); let mut changed_via = BTreeMap::new();
let mut changed_plan = BTreeMap::new(); let mut changed_plan = BTreeMap::new();
...@@ -179,14 +179,15 @@ impl Router { ...@@ -179,14 +179,15 @@ impl Router {
} }
// Plan updates (Gateways) // Plan updates (Gateways)
for &region in regions { for (r, _) in DATABASE.regions.iter().enumerate() {
let region_id = RegionID(r as u8);
for (&gid, gateways) in gateway_groups { for (&gid, gateways) in gateway_groups {
let current_gw = self.plan[&region][&gid]; let current_gw = self.plan[&region_id][&gid];
let current_metric = metrics[&DATABASE.gateways.iter().find(|f| f.id == current_gw).unwrap().router]; let current_metric = metrics[&DATABASE.gateways.iter().find(|f| f.id == current_gw).unwrap().router];
let (best_gw, best_metric) = gateways let (best_gw, best_metric) = gateways
.iter() .iter()
.map(|g| (g, metrics[&g.router].saturating_add(g.cost_outbound).saturating_add(g.metrics[region.0 as usize]))) .map(|g| (g, metrics[&g.router].saturating_add(g.cost_outbound).saturating_add(g.metrics[r])))
.min_by_key(|(_, m)| *m) .min_by_key(|(_, m)| *m)
.unwrap(); .unwrap();
...@@ -194,7 +195,7 @@ impl Router { ...@@ -194,7 +195,7 @@ impl Router {
if best_metric.saturating_add(penalty) < current_metric { if best_metric.saturating_add(penalty) < current_metric {
overcome = true; overcome = true;
} }
changed_plan.entry(region).or_insert_with(BTreeMap::new).insert(gid, best_gw.id); changed_plan.entry(region_id).or_insert_with(BTreeMap::new).insert(gid, best_gw.id);
} }
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment