in resctl-demo/src/doc/markup_rd.rs [228:385]
fn parse(input: &str) -> Result<(RdCmd, Option<String>)> {
let mut args: Vec<&str> = input.split_whitespace().collect();
let mut cond = None;
if args.len() >= 2 {
let arg = args.last().unwrap();
if arg.starts_with("%") && arg.ends_with("%") {
cond = Some(arg[1..arg.len() - 1].to_string());
args.pop();
}
}
let cmd = match args[0] {
"id" => {
if args.len() != 2 {
bail!("invalid number of arguments");
}
RdCmd::Id(args[1].into())
}
"on" | "off" | "toggle" => {
if args.len() < 2 {
bail!("too few arguments");
}
let sw = match args[1] {
"bench-hashd" => RdSwitch::BenchHashd,
"bench-hashd-loop" => RdSwitch::BenchHashdLoop,
"bench-iocost" => RdSwitch::BenchIoCost,
"bench-needed" => RdSwitch::BenchNeeded,
"hashd" | "hashd-A" => RdSwitch::HashdA,
"hashd-B" => RdSwitch::HashdB,
"sideload" | "sysload" => {
if (args[0] == "off" && args.len() != 3)
|| (args[0] != "off" && args.len() != 4)
{
bail!("incorrect number of arguments");
}
let (tag, id) = match args[0] {
"off" => (args[2].to_string(), "".into()),
_ => (args[2].to_string(), args[3].to_string()),
};
if args[1] == "sideload" {
RdSwitch::Sideload(tag, id)
} else {
RdSwitch::Sysload(tag, id)
}
}
"cpu-resctl" => RdSwitch::CpuResCtl,
"mem-resctl" => RdSwitch::MemResCtl,
"io-resctl" => RdSwitch::IoResCtl,
"oomd" => RdSwitch::Oomd,
"oomd-work-mem-pressure" => RdSwitch::OomdWorkMemPressure,
"oomd-work-senpai" => RdSwitch::OomdWorkSenpai,
"oomd-sys-mem-pressure" => RdSwitch::OomdSysMemPressure,
"oomd-sys-senpai" => RdSwitch::OomdSysSenpai,
_ => bail!("invalid switch target"),
};
match &sw {
RdSwitch::Sideload(_, _) | RdSwitch::Sysload(_, _) => {}
_ if args.len() != 2 => bail!("too many arguments"),
_ => {}
}
match args[0] {
"on" => RdCmd::On(sw),
"off" => RdCmd::Off(sw),
"toggle" => RdCmd::Toggle(sw),
_ => bail!("???"),
}
}
"knob" => {
let val = match args.len() {
2 => -1.0,
3 => match args[2].parse() {
Ok(v) if v >= 0.0 && v <= 1.0 => v,
Ok(v) => bail!("{} is out of range [0.0, 1.0]", v),
Err(e) => bail!("failed to parse knob value ({:?})", &e),
},
_ => bail!("invalid number of arguments"),
};
let knob = match args[1] {
"hashd-load" | "hashd-A-load" => RdKnob::HashdALoad,
"hashd-lat-target-pct" | "hashd-A-lat-target-pct" => RdKnob::HashdALatTargetPct,
"hashd-lat-target" | "hashd-A-lat-target" => RdKnob::HashdALatTarget,
"hashd-mem" | "hashd-A-mem" => RdKnob::HashdAMem,
"hashd-file-addr-stdev" | "hashd-A-file-addr-stdev" => {
RdKnob::HashdAFileAddrStdev
}
"hashd-anon-addr-stdev" | "hashd-A-anon-addr-stdev" => {
RdKnob::HashdAAnonAddrStdev
}
"hashd-file" | "hashd-A-file" => RdKnob::HashdAFile,
"hashd-file-max" | "hashd-A-file-max" => RdKnob::HashdAFileMax,
"hashd-log-bps" | "hashd-A-write" => RdKnob::HashdALogBps,
"hashd-weight" | "hashd-A-weight" => RdKnob::HashdAWeight,
"hashd-B-load" => RdKnob::HashdBLoad,
"hashd-B-lat-target-pct" => RdKnob::HashdBLatTargetPct,
"hashd-B-lat-target" => RdKnob::HashdBLatTarget,
"hashd-B-mem" => RdKnob::HashdBMem,
"hashd-B-file-addr-stdev" => RdKnob::HashdBFileAddrStdev,
"hashd-B-anon-addr-stdev" => RdKnob::HashdBAnonAddrStdev,
"hashd-B-file" => RdKnob::HashdBFile,
"hashd-B-file-max" => RdKnob::HashdBFileMax,
"hashd-B-log-bps" => RdKnob::HashdBLogBps,
"hashd-B-weight" => RdKnob::HashdBWeight,
"sys-cpu-ratio" => RdKnob::SysCpuRatio,
"sys-io-ratio" => RdKnob::SysIoRatio,
"mem-margin" => RdKnob::MemMargin,
"balloon" => RdKnob::Balloon,
"cpu-headroom" => RdKnob::CpuHeadroom,
_ => bail!("invalid knob target"),
};
RdCmd::Knob(knob, val)
}
"graph" => match args.len() {
1 => RdCmd::Graph("".into()),
2 => RdCmd::Graph(args[1].into()),
_ => bail!("invalid number of arguments"),
},
"reset" => {
if args.len() != 2 {
bail!("invalid number of arguments");
}
let reset = match args[1] {
"benches" => RdReset::Benches,
"hashds" => RdReset::Hashds,
"hashd-params" => RdReset::HashdParams,
"sideloads" => RdReset::Sideloads,
"sysloads" => RdReset::Sysloads,
"resctl" => RdReset::ResCtl,
"resctl-params" => RdReset::ResCtlParams,
"oomd" => RdReset::Oomd,
"graph" => RdReset::Graph,
"secondaries" => RdReset::Secondaries,
"all-workloads" => RdReset::AllWorkloads,
"protections" => RdReset::Protections,
"all" => RdReset::All,
"params" => RdReset::Params,
"all-with-params" => RdReset::AllWithParams,
"prep" => RdReset::Prep,
_ => bail!("invalid reset target"),
};
RdCmd::Reset(reset)
}
"jump" => {
if args.len() != 2 {
bail!("invalid number of arguments");
}
RdCmd::Jump(args[1].into())
}
"(" | ")" => {
if args.len() != 1 {
bail!("invalid number of arguments");
}
RdCmd::Group(Vec::new())
}
_ => bail!("invalid command"),
};
Ok((cmd, cond))
}