use std::collections::HashMap;
use std::io::{BufRead, BufReader, Write};
use std::path::PathBuf;
use crate::error::ErrorKind::*;
use crate::error::*;
use crate::read_u64_from;
use crate::{
ControllIdentifier, ControllerInternal, Controllers, NetworkResources, Resources, Subsystem,
};
#[derive(Debug, Clone)]
pub struct NetPrioController {
base: PathBuf,
path: PathBuf,
}
impl ControllerInternal for NetPrioController {
fn control_type(&self) -> Controllers {
Controllers::NetPrio
}
fn get_path(&self) -> &PathBuf {
&self.path
}
fn get_path_mut(&mut self) -> &mut PathBuf {
&mut self.path
}
fn get_base(&self) -> &PathBuf {
&self.base
}
fn apply(&self, res: &Resources) -> Result<()> {
let res: &NetworkResources = &res.network;
for i in &res.priorities {
let _ = self.set_if_prio(&i.name, i.priority);
}
Ok(())
}
}
impl ControllIdentifier for NetPrioController {
fn controller_type() -> Controllers {
Controllers::NetPrio
}
}
impl<'a> From<&'a Subsystem> for &'a NetPrioController {
fn from(sub: &'a Subsystem) -> &'a NetPrioController {
unsafe {
match sub {
Subsystem::NetPrio(c) => c,
_ => {
assert_eq!(1, 0);
let v = std::mem::MaybeUninit::uninit();
v.assume_init()
}
}
}
}
}
impl NetPrioController {
pub fn new(root: PathBuf) -> Self {
Self {
base: root.clone(),
path: root,
}
}
pub fn prio_idx(&self) -> u64 {
self.open_path("net_prio.prioidx", false)
.and_then(read_u64_from)
.unwrap_or(0)
}
#[allow(clippy::iter_nth_zero, clippy::unnecessary_unwrap)]
pub fn ifpriomap(&self) -> Result<HashMap<String, u64>> {
self.open_path("net_prio.ifpriomap", false)
.and_then(|file| {
let bf = BufReader::new(file);
bf.lines().fold(Ok(HashMap::new()), |acc, line| {
if acc.is_err() {
acc
} else {
let mut acc = acc.unwrap();
let l = line.unwrap();
let mut sp = l.split_whitespace();
let ifname = sp.nth(0);
let ifprio = sp.nth(1);
if ifname.is_none() || ifprio.is_none() {
Err(Error::new(ParseError))
} else {
let ifname = ifname.unwrap();
let ifprio = ifprio.unwrap().trim().parse();
match ifprio {
Err(e) => Err(Error::with_cause(ParseError, e)),
Ok(_) => {
acc.insert(ifname.to_string(), ifprio.unwrap());
Ok(acc)
}
}
}
}
})
})
}
pub fn set_if_prio(&self, eif: &str, prio: u64) -> Result<()> {
self.open_path("net_prio.ifpriomap", true)
.and_then(|mut file| {
file.write_all(format!("{} {}", eif, prio).as_ref())
.map_err(|e| {
Error::with_cause(
WriteFailed(
"net_prio.ifpriomap".to_string(),
format!("{} {}", eif, prio),
),
e,
)
})
})
}
}