PowerTools/backend/src/api/cpu.rs

283 lines
11 KiB
Rust
Raw Normal View History

use std::sync::mpsc::{Sender, self};
use std::sync::{Arc, Mutex};
use usdpl_back::core::serdes::Primitive;
use usdpl_back::AsyncCallable;
use crate::settings::{Cpus, SettingError, SettingVariant, MinMax};
//use crate::utility::{unwrap_lock, unwrap_maybe_fatal};
use super::handler::{ApiMessage, CpuMessage};
/// Available CPUs web method
pub fn max_cpus(_: super::ApiParameterType) -> super::ApiParameterType {
super::utility::map_result(
Cpus::cpu_count()
.map(|x| x as u64)
.ok_or_else(
|| SettingError {
msg: "Failed to parse CPU count".to_owned(),
setting: SettingVariant::Cpu,
}
)
)
}
/// Generate set CPU online web method
pub fn set_cpu_online(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |index: usize, value: bool|
sender.lock()
.unwrap()
.send(ApiMessage::Cpu(CpuMessage::SetCpuOnline(index, value))).expect("set_cpu_online send failed");
move |params_in: super::ApiParameterType| {
if let Some(&Primitive::F64(index)) = params_in.get(0) {
//let mut settings_lock = unwrap_lock(settings.lock(), "cpu");
if let Some(&Primitive::Bool(online)) = params_in.get(1) {
setter(index as usize, online);
vec![online.into()]
} else {
vec!["set_cpu_online missing parameter 1".into()]
}
} else {
vec!["set_cpu_online missing parameter 0".into()]
}
}
}
pub fn set_cpus_online(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |values: Vec<bool>|
sender.lock()
.unwrap()
.send(ApiMessage::Cpu(CpuMessage::SetCpusOnline(values))).expect("set_cpus_online send failed");
move |params_in: super::ApiParameterType| {
let mut result = Vec::with_capacity(params_in.len());
let mut values = Vec::with_capacity(params_in.len());
for i in 0..params_in.len() {
if let Primitive::Bool(online) = params_in[i] {
values.push(online);
result.push(online.into());
} else {
values.push(true);
result.push(format!("Invalid parameter {}", i).into())
}
}
setter(values);
result
}
}
/*pub fn get_cpus_online(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let getter = move || {
let (tx, rx) = mpsc::channel();
let callback = move |values: Vec<bool>| tx.send(values).expect("get_cpus_online callback send failed");
sender.lock().unwrap().send(ApiMessage::Cpu(CpuMessage::GetCpusOnline(Box::new(callback)))).expect("get_cpus_online send failed");
rx.recv().expect("get_cpus_online callback recv failed")
};
move |_: super::ApiParameterType| {
let result = getter();
let mut output = Vec::with_capacity(result.len());
for &status in result.as_slice() {
output.push(status.into());
}
output
}
}*/
pub fn set_smt(
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || {
let sender2 = sender.clone();
move |smt: bool| {
let (tx, rx) = mpsc::channel();
let callback = move |values: Vec<bool>| tx.send(values).expect("set_smt callback send failed");
sender2.lock().unwrap().send(ApiMessage::Cpu(CpuMessage::SetSmt(smt, Box::new(callback)))).expect("set_smt send failed");
rx.recv().expect("set_smt callback recv failed")
}
};
super::async_utils::AsyncIsh {
trans_setter: |params| {
if let Some(&Primitive::Bool(smt_value)) = params.get(0) {
Ok(smt_value)
} else {
Err("set_smt missing/invalid parameter 0".to_owned())
}
},
set_get: getter,
trans_getter: |result| {
let mut output = Vec::with_capacity(result.len());
for &status in result.as_slice() {
output.push(status.into());
}
output
}
}
}
pub fn get_cpus_online(
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || {
let sender2 = sender.clone();
move || {
let (tx, rx) = mpsc::channel();
let callback = move |values: Vec<bool>| tx.send(values).expect("get_cpus_online callback send failed");
sender2.lock().unwrap().send(ApiMessage::Cpu(CpuMessage::GetCpusOnline(Box::new(callback)))).expect("get_cpus_online send failed");
rx.recv().expect("get_cpus_online callback recv failed")
}
};
super::async_utils::AsyncIshGetter {
set_get: getter,
trans_getter: |result| {
let mut output = Vec::with_capacity(result.len());
for &status in result.as_slice() {
output.push(status.into());
}
output
}
}
}
pub fn set_clock_limits(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |index: usize, value: MinMax<u64>|
sender.lock()
.unwrap()
.send(ApiMessage::Cpu(CpuMessage::SetClockLimits(index, Some(value)))).expect("set_clock_limits send failed");
move |params_in: super::ApiParameterType| {
if let Some(&Primitive::F64(index)) = params_in.get(0) {
if let Some(&Primitive::F64(min)) = params_in.get(1) {
if let Some(&Primitive::F64(max)) = params_in.get(2) {
setter(index as usize, MinMax {min: min as u64, max: max as u64});
vec![min.into(), max.into()]
} else {
vec!["set_clock_limits missing parameter 2".into()]
}
} else {
vec!["set_clock_limits missing parameter 1".into()]
}
} else {
vec!["set_clock_limits missing parameter 0".into()]
}
}
}
pub fn get_clock_limits(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let getter = move |index: usize| {
let (tx, rx) = mpsc::channel();
let callback = move |values: Option<MinMax<u64>>| tx.send(values).expect("get_clock_limits callback send failed");
sender.lock().unwrap().send(ApiMessage::Cpu(CpuMessage::GetClockLimits(index, Box::new(callback)))).expect("get_clock_limits send failed");
rx.recv().expect("get_clock_limits callback recv failed")
};
move |params_in: super::ApiParameterType| {
if let Some(&Primitive::F64(index)) = params_in.get(0) {
if let Some(min_max) = getter(index as usize) {
vec![min_max.min.into(), min_max.max.into()]
} else {
vec![Primitive::Empty, Primitive::Empty]
}
} else {
vec!["get_clock_limits missing parameter 0".into()]
}
}
}
pub fn unset_clock_limits(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |index: usize|
sender.lock()
.unwrap()
.send(ApiMessage::Cpu(CpuMessage::SetClockLimits(index, None))).expect("unset_clock_limits send failed");
move |params_in: super::ApiParameterType| {
if let Some(&Primitive::F64(index)) = params_in.get(0) {
setter(index as usize);
vec![true.into()]
} else {
vec!["get_clock_limits missing parameter 0".into()]
}
}
}
pub fn set_cpu_governor(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |index: usize, governor: String|
sender.lock()
.unwrap()
.send(ApiMessage::Cpu(CpuMessage::SetCpuGovernor(index, governor))).expect("set_cpu_governor send failed");
move |params_in: super::ApiParameterType| {
if let Some(&Primitive::F64(index)) = params_in.get(0) {
if let Some(Primitive::String(governor)) = params_in.get(1) {
setter(index as usize, governor.to_owned());
vec![(governor as &str).into()]
} else {
vec!["set_cpu_governor missing parameter 1".into()]
}
} else {
vec!["set_cpu_governor missing parameter 0".into()]
}
}
}
pub fn set_cpus_governors(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |governors: Vec<String>|
sender.lock()
.unwrap()
.send(ApiMessage::Cpu(CpuMessage::SetCpusGovernor(governors))).expect("set_cpus_governor send failed");
move |params_in: super::ApiParameterType| {
let mut result = Vec::with_capacity(params_in.len());
let mut values = Vec::with_capacity(params_in.len());
for i in 0..params_in.len() {
if let Primitive::String(gov) = &params_in[i] {
values.push(gov.to_owned());
result.push((gov as &str).into());
} else {
//values.push(true);
result.push(format!("Invalid parameter {}", i).into())
}
}
setter(values);
result
}
}
pub fn get_cpu_governors(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let getter = move || {
let (tx, rx) = mpsc::channel();
let callback = move |values: Vec<String>| tx.send(values).expect("get_cpu_governors callback send failed");
sender.lock().unwrap().send(ApiMessage::Cpu(CpuMessage::GetCpusGovernor(Box::new(callback)))).expect("get_cpu_governors send failed");
rx.recv().expect("get_cpu_governors callback recv failed")
};
move |_: super::ApiParameterType| {
let result = getter();
let mut output = Vec::with_capacity(result.len());
for cpu in result.as_slice() {
output.push(cpu.clone().into());
}
output
}
}