1use log::error;
3use serde::{Deserialize, Serialize};
4use std::io;
5
6use rd_util::*;
7
8pub mod args;
9pub mod bandit_report;
10pub mod bench;
11pub mod cmd;
12pub mod cmd_ack;
13pub mod index;
14pub mod oomd;
15pub mod report;
16pub mod side_defs;
17pub mod slices;
18pub mod sysreqs;
19
20pub use args::{Args, Bandit, BanditMemHogArgs, EnforceConfig};
21pub use bandit_report::BanditMemHogReport;
22pub use bench::{BenchKnobs, HashdKnobs, IoCostKnobs, BENCH_FILENAME};
23pub use cmd::{Cmd, HashdCmd, SideloaderCmd};
24pub use cmd_ack::CmdAck;
25pub use index::Index;
26pub use oomd::{OomdKnobs, OomdSliceMemPressureKnobs, OomdSliceSenpaiKnobs};
27pub use report::{
28    BenchHashdReport, BenchIoCostReport, HashdReport, IoCostModelReport, IoCostQoSReport,
29    IoCostReport, IoLatReport, OomdReport, Report, ReportIter, ReportPathIter, ResCtlReport,
30    SideloadReport, SideloaderReport, StatMap, SvcReport, SvcStateReport, SysloadReport,
31    UsageReport,
32};
33pub use side_defs::{SideloadDefs, SideloadSpec};
34pub use slices::{DisableSeqKnobs, MemoryKnob, Slice, SliceConfig, SliceKnobs, ROOT_SLICE};
35pub use sysreqs::{MissedSysReqs, SysReq, SysReqsReport, ALL_SYSREQS_SET};
36
37lazy_static::lazy_static! {
38    pub static ref VERSION: &'static str = env!("CARGO_PKG_VERSION");
39    pub static ref FULL_VERSION: String = full_version(*VERSION);
40}
41
42#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
43pub enum RunnerState {
44    Idle,
45    Running,
46    BenchHashd,
47    BenchIoCost,
48}
49
50pub const AGENT_SVC_NAME: &str = "rd-agent.service";
51pub const HASHD_BENCH_SVC_NAME: &str = "rd-hashd-bench.service";
52pub const IOCOST_BENCH_SVC_NAME: &str = "rd-iocost-bench.service";
53pub const HASHD_A_SVC_NAME: &str = "rd-hashd-A.service";
54pub const HASHD_B_SVC_NAME: &str = "rd-hashd-B.service";
55pub const OOMD_SVC_NAME: &str = "rd-oomd.service";
56pub const SIDELOADER_SVC_NAME: &str = "rd-sideloader.service";
57pub const SIDELOAD_SVC_PREFIX: &str = "rd-sideload-";
58pub const SYSLOAD_SVC_PREFIX: &str = "rd-sysload-";
59
60pub fn sysload_svc_name(name: &str) -> String {
61    format!("{}{}.service", SYSLOAD_SVC_PREFIX, name)
62}
63
64pub fn sideload_svc_name(name: &str) -> String {
65    format!("{}{}.service", SIDELOAD_SVC_PREFIX, name)
66}
67
68#[derive(Default)]
69pub struct AgentFiles {
70    pub args_path: String,
71    pub index_path: String,
72    pub args: JsonConfigFile<Args>,
73    pub index: JsonConfigFile<Index>,
74    pub cmd: JsonConfigFile<Cmd>,
75    pub cmd_ack: JsonConfigFile<CmdAck>,
76    pub sysreqs: JsonConfigFile<SysReqsReport>,
77    pub report: JsonConfigFile<Report>,
78    pub bench: JsonConfigFile<BenchKnobs>,
79    pub slices: JsonConfigFile<SliceKnobs>,
80    pub oomd: JsonConfigFile<OomdKnobs>,
81}
82
83impl AgentFiles {
84    pub fn new(dir: &str) -> Self {
85        Self {
86            args_path: dir.to_string() + "/args.json",
87            index_path: dir.to_string() + "/index.json",
88            ..Default::default()
89        }
90    }
91
92    fn refresh_one<T>(file: &mut JsonConfigFile<T>, path: &str) -> bool
93    where
94        T: JsonLoad + JsonSave,
95    {
96        match &file.path {
97            None => match JsonConfigFile::<T>::load(path) {
98                Ok(v) => {
99                    *file = v;
100                    true
101                }
102                Err(e) => {
103                    match e.downcast_ref::<io::Error>() {
104                        Some(e) if e.raw_os_error() == Some(libc::ENOENT) => (),
105                        _ => error!("Failed to read {:?} ({:?})", path, &e),
106                    }
107                    false
108                }
109            },
110            Some(_) => match file.maybe_reload() {
111                Ok(v) => v,
112                Err(e) => {
113                    match e.downcast_ref::<io::Error>() {
114                        Some(e) if e.raw_os_error() == Some(libc::ENOENT) => (),
115                        _ => error!("Failed to reload {:?} ({:?})", path, &e),
116                    }
117                    false
118                }
119            },
120        }
121    }
122
123    pub fn refresh(&mut self) {
124        Self::refresh_one(&mut self.args, &self.args_path);
125
126        if Self::refresh_one(&mut self.index, &self.index_path) {
127            self.cmd = Default::default();
128            self.cmd_ack = Default::default();
129            self.sysreqs = Default::default();
130            self.report = Default::default();
131            self.bench = Default::default();
132            self.slices = Default::default();
133            self.oomd = Default::default();
134        }
135        if let None = self.index.path {
136            return;
137        }
138
139        let index = &self.index.data;
140
141        Self::refresh_one(&mut self.cmd, &index.cmd);
142        Self::refresh_one(&mut self.cmd_ack, &index.cmd_ack);
143        Self::refresh_one(&mut self.sysreqs, &index.sysreqs);
144        Self::refresh_one(&mut self.report, &index.report);
145        Self::refresh_one(&mut self.bench, &index.bench);
146        Self::refresh_one(&mut self.slices, &index.slices);
147        Self::refresh_one(&mut self.oomd, &index.oomd);
148    }
149}