Refactor API processing to apply settings from single thread and queue API calls instead of locking
This commit is contained in:
parent
357a7cfe37
commit
1610f18278
17 changed files with 822 additions and 452 deletions
33
backend/Cargo.lock
generated
33
backend/Cargo.lock
generated
|
@ -38,6 +38,28 @@ dependencies = [
|
|||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-recursion"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2cda8f4bcc10624c4e85bc66b3f452cca98cfa5ca002dc83a16aad2367641bea"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
|
@ -567,12 +589,14 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "powertools-rs"
|
||||
version = "1.0.5"
|
||||
version = "1.1.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"log",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"simplelog",
|
||||
"tokio",
|
||||
"usdpl-back",
|
||||
]
|
||||
|
||||
|
@ -1053,12 +1077,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "usdpl-back"
|
||||
version = "0.6.0"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cbbc0781e83ba990f8239142e33173a2d2548701775f3db66702d1af4fd0319a"
|
||||
checksum = "4ca96dac4ee471e9534940f99cb36f5212cbfaf4e7779eb3ba970d3c511d9583"
|
||||
dependencies = [
|
||||
"async-recursion",
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"hex",
|
||||
"log",
|
||||
"obfstr",
|
||||
"tokio",
|
||||
"usdpl-core",
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
[package]
|
||||
name = "powertools-rs"
|
||||
version = "1.0.5"
|
||||
version = "1.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
usdpl-back = { version = "0.6.0", features = ["blocking"]}
|
||||
usdpl-back = { version = "0.7.0", features = ["blocking"]}
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
|
||||
# async
|
||||
tokio = { version = "*", features = ["time"] }
|
||||
async-trait = { version = "0.1" }
|
||||
|
||||
# logging
|
||||
log = "0.4"
|
||||
simplelog = "0.12"
|
||||
|
|
65
backend/src/api/async_utils.rs
Normal file
65
backend/src/api/async_utils.rs
Normal file
|
@ -0,0 +1,65 @@
|
|||
//use usdpl_back::core::serdes::Primitive;
|
||||
use usdpl_back::AsyncCallable;
|
||||
|
||||
/*pub struct AsyncIsh<T: Send,
|
||||
TS: (Fn(super::ApiParameterType) -> Result<T, String>) + Send + Sync,
|
||||
SG: (Fn(T) -> T) + Send + Sync + 'static,
|
||||
TG: (Fn(T) -> super::ApiParameterType) + Send + Sync> {
|
||||
pub trans_setter: TS, // assumed to be pretty fast
|
||||
pub set_get: SG, // probably has locks (i.e. slow)
|
||||
pub trans_getter: TG, // assumed to be pretty fast
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl <T: Send,
|
||||
TS: (Fn(super::ApiParameterType) -> Result<T, String>) + Send + Sync,
|
||||
SG: (Fn(T) -> T) + Send + Sync + 'static,
|
||||
TG: (Fn(T) -> super::ApiParameterType) + Send + Sync>
|
||||
AsyncCallable for AsyncIsh<T, TS, SG, TG> {
|
||||
async fn call(&self, params: super::ApiParameterType) -> super::ApiParameterType {
|
||||
let t_to_set = match (self.trans_setter)(params) {
|
||||
Ok(t) => t,
|
||||
Err(e) => return vec![e.into()]
|
||||
};
|
||||
let t_got = match tokio::task::spawn_blocking(|| (self.set_get)(t_to_set)).await {
|
||||
Ok(t) => t,
|
||||
Err(e) => return vec![e.to_string().into()],
|
||||
};
|
||||
(self.trans_getter)(t_got)
|
||||
}
|
||||
}*/
|
||||
|
||||
pub struct AsyncIshGetter<T: Send + 'static,
|
||||
Gen: (Fn() -> G) + Send + Sync,
|
||||
G: (Fn() -> T) + Send + Sync + 'static,
|
||||
TG: (Fn(T) -> super::ApiParameterType) + Send + Sync> {
|
||||
pub set_get: Gen, // probably has locks (i.e. slow)
|
||||
pub trans_getter: TG, // assumed to be pretty fast
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl <T: Send + 'static,
|
||||
Gen: (Fn() -> G) + Send + Sync,
|
||||
G: (Fn() -> T) + Send + Sync + 'static,
|
||||
TG: (Fn(T) -> super::ApiParameterType) + Send + Sync>
|
||||
AsyncCallable for AsyncIshGetter<T, Gen, G, TG> {
|
||||
async fn call(&self, _params: super::ApiParameterType) -> super::ApiParameterType {
|
||||
let getter = (self.set_get)();
|
||||
let t_got = match tokio::task::spawn_blocking(move || getter()).await {
|
||||
Ok(t) => t,
|
||||
Err(e) => return vec![e.to_string().into()],
|
||||
};
|
||||
(self.trans_getter)(t_got)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Blocking<F: (Fn(super::ApiParameterType) -> super::ApiParameterType) + Send + Sync> {
|
||||
pub func: F,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl <F: (Fn(super::ApiParameterType) -> super::ApiParameterType) + Send + Sync> AsyncCallable for Blocking<F> {
|
||||
async fn call(&self, params: super::ApiParameterType) -> super::ApiParameterType {
|
||||
(self.func)(params)
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
use std::sync::{mpsc::Sender, Arc, Mutex};
|
||||
use std::sync::mpsc::{Sender, self};
|
||||
use std::sync::Mutex;
|
||||
use usdpl_back::core::serdes::Primitive;
|
||||
|
||||
use crate::settings::{Battery, OnSet};
|
||||
use crate::utility::{unwrap_lock, unwrap_maybe_fatal};
|
||||
use super::handler::{ApiMessage, BatteryMessage};
|
||||
|
||||
/// Current current (ha!) web method
|
||||
pub fn current_now(_: super::ApiParameterType) -> super::ApiParameterType {
|
||||
|
@ -26,22 +26,18 @@ pub fn charge_design(_: super::ApiParameterType) -> super::ApiParameterType {
|
|||
|
||||
/// Generate set battery charge rate web method
|
||||
pub fn set_charge_rate(
|
||||
settings: Arc<Mutex<Battery>>,
|
||||
saver: Sender<()>,
|
||||
sender: Sender<ApiMessage>,
|
||||
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
|
||||
let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety
|
||||
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
|
||||
let setter = move |rate: f64|
|
||||
sender.lock()
|
||||
.unwrap()
|
||||
.send(ApiMessage::Battery(BatteryMessage::SetChargeRate(Some(rate as u64))))
|
||||
.expect("set_charge_rate send failed");
|
||||
move |params_in: super::ApiParameterType| {
|
||||
if let Some(Primitive::F64(new_val)) = params_in.get(0) {
|
||||
let mut settings_lock = unwrap_lock(settings.lock(), "battery");
|
||||
settings_lock.charge_rate = Some(*new_val as _);
|
||||
unwrap_maybe_fatal(
|
||||
unwrap_lock(saver.lock(), "save channel").send(()),
|
||||
"Failed to send on save channel",
|
||||
);
|
||||
super::utility::map_empty_result(
|
||||
settings_lock.on_set(),
|
||||
settings_lock.charge_rate.unwrap(),
|
||||
)
|
||||
if let Some(&Primitive::F64(new_val)) = params_in.get(0) {
|
||||
setter(new_val);
|
||||
vec![(new_val).into()]
|
||||
} else {
|
||||
vec!["set_charge_rate missing parameter".into()]
|
||||
}
|
||||
|
@ -50,30 +46,28 @@ pub fn set_charge_rate(
|
|||
|
||||
/// Generate get battery charge rate web method
|
||||
pub fn get_charge_rate(
|
||||
settings: Arc<Mutex<Battery>>,
|
||||
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 |rate: Option<u64>| tx.send(rate).expect("get_charge_rate callback send failed");
|
||||
sender.lock().unwrap().send(ApiMessage::Battery(BatteryMessage::GetChargeRate(Box::new(callback)))).expect("get_charge_rate send failed");
|
||||
rx.recv().expect("get_charge_rate callback recv failed")
|
||||
};
|
||||
move |_: super::ApiParameterType| {
|
||||
let settings_lock = unwrap_lock(settings.lock(), "battery");
|
||||
vec![settings_lock
|
||||
.charge_rate
|
||||
.map(|x| x.into())
|
||||
.unwrap_or(Primitive::Empty)]
|
||||
vec![getter().map(|x| x.into()).unwrap_or(Primitive::Empty)]
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate unset battery charge rate web method
|
||||
pub fn unset_charge_rate(
|
||||
settings: Arc<Mutex<Battery>>,
|
||||
saver: Sender<()>,
|
||||
sender: Sender<ApiMessage>,
|
||||
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
|
||||
let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety
|
||||
move |_: super::ApiParameterType| {
|
||||
let mut settings_lock = unwrap_lock(settings.lock(), "battery");
|
||||
settings_lock.charge_rate = None;
|
||||
unwrap_maybe_fatal(
|
||||
unwrap_lock(saver.lock(), "save channel").send(()),
|
||||
"Failed to send on save channel",
|
||||
);
|
||||
super::utility::map_empty_result(settings_lock.on_set(), true)
|
||||
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
|
||||
let setter = move || sender.lock().unwrap().send(ApiMessage::Battery(BatteryMessage::SetChargeRate(None))).expect("unset_charge_rate send failed");
|
||||
move |_params_in: super::ApiParameterType| {
|
||||
setter();
|
||||
vec![true.into()]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
use std::sync::{mpsc::Sender, Arc, Mutex};
|
||||
use std::sync::mpsc::{Sender, self};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use usdpl_back::core::serdes::Primitive;
|
||||
use usdpl_back::AsyncCallable;
|
||||
|
||||
use crate::settings::{Cpu, OnSet, SettingError, SettingVariant, MinMax};
|
||||
use crate::utility::{unwrap_lock, unwrap_maybe_fatal};
|
||||
use crate::settings::{Cpu, 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 {
|
||||
|
@ -20,30 +23,22 @@ pub fn max_cpus(_: super::ApiParameterType) -> super::ApiParameterType {
|
|||
|
||||
/// Generate set CPU online web method
|
||||
pub fn set_cpu_online(
|
||||
settings: Arc<Mutex<Vec<Cpu>>>,
|
||||
saver: Sender<()>,
|
||||
sender: Sender<ApiMessage>,
|
||||
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
|
||||
let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety
|
||||
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(cpu) = settings_lock.get_mut(*index as usize) {
|
||||
if let Some(Primitive::Bool(online)) = params_in.get(1) {
|
||||
cpu.online = *online;
|
||||
unwrap_maybe_fatal(
|
||||
unwrap_lock(saver.lock(), "save channel").send(()),
|
||||
"Failed to send on save channel",
|
||||
);
|
||||
super::utility::map_empty_result(
|
||||
cpu.on_set(),
|
||||
cpu.online,
|
||||
)
|
||||
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 cpu index out of bounds".into()]
|
||||
}
|
||||
} else {
|
||||
vec!["set_cpu_online missing parameter 0".into()]
|
||||
}
|
||||
|
@ -51,82 +46,95 @@ pub fn set_cpu_online(
|
|||
}
|
||||
|
||||
pub fn set_cpus_online(
|
||||
settings: Arc<Mutex<Vec<Cpu>>>,
|
||||
saver: Sender<()>,
|
||||
sender: Sender<ApiMessage>,
|
||||
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
|
||||
let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety
|
||||
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 settings_lock = unwrap_lock(settings.lock(), "cpu");
|
||||
let mut values = Vec::with_capacity(params_in.len());
|
||||
for i in 0..params_in.len() {
|
||||
if let Primitive::Bool(online) = params_in[i] {
|
||||
if let Some(cpu) = settings_lock.get_mut(i) {
|
||||
cpu.online = online;
|
||||
match cpu.on_set() {
|
||||
Ok(_) => result.push(cpu.online.into()),
|
||||
Err(e) => result.push(e.msg.into())
|
||||
}
|
||||
}
|
||||
values.push(online);
|
||||
result.push(online.into());
|
||||
} else {
|
||||
values.push(true);
|
||||
result.push(format!("Invalid parameter {}", i).into())
|
||||
}
|
||||
}
|
||||
unwrap_maybe_fatal(
|
||||
unwrap_lock(saver.lock(), "save channel").send(()),
|
||||
"Failed to send on save channel",
|
||||
);
|
||||
setter(values);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_cpus_online(
|
||||
settings: Arc<Mutex<Vec<Cpu>>>,
|
||||
/*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 settings_lock = unwrap_lock(settings.lock(), "cpu");
|
||||
let mut output = Vec::with_capacity(settings_lock.len());
|
||||
for cpu in settings_lock.as_slice() {
|
||||
output.push(cpu.online.into());
|
||||
let result = getter();
|
||||
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(
|
||||
settings: Arc<Mutex<Vec<Cpu>>>,
|
||||
saver: Sender<()>,
|
||||
sender: Sender<ApiMessage>,
|
||||
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
|
||||
let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety
|
||||
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) {
|
||||
let mut settings_lock = unwrap_lock(settings.lock(), "cpu");
|
||||
if let Some(cpu) = settings_lock.get_mut(*index as usize) {
|
||||
if let Some(Primitive::F64(min)) = params_in.get(1) {
|
||||
if let Some(Primitive::F64(max)) = params_in.get(2) {
|
||||
cpu.clock_limits = Some(MinMax {
|
||||
min: *min as _,
|
||||
max: *max as _,
|
||||
});
|
||||
unwrap_maybe_fatal(
|
||||
unwrap_lock(saver.lock(), "save channel").send(()),
|
||||
"Failed to send on save channel",
|
||||
);
|
||||
match cpu.on_set() {
|
||||
Ok(_) => vec![
|
||||
cpu.clock_limits.as_ref().unwrap().min.into(),
|
||||
cpu.clock_limits.as_ref().unwrap().max.into(),
|
||||
],
|
||||
Err(e) => vec![e.msg.into()]
|
||||
}
|
||||
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 cpu index out of bounds".into()]
|
||||
}
|
||||
} else {
|
||||
vec!["set_clock_limits missing parameter 0".into()]
|
||||
}
|
||||
|
@ -134,20 +142,22 @@ pub fn set_clock_limits(
|
|||
}
|
||||
|
||||
pub fn get_clock_limits(
|
||||
settings: Arc<Mutex<Vec<Cpu>>>,
|
||||
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) {
|
||||
let mut settings_lock = unwrap_lock(settings.lock(), "cpu");
|
||||
if let Some(cpu) = settings_lock.get_mut(*index as usize) {
|
||||
if let Some(min_max) = &cpu.clock_limits {
|
||||
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 cpu index out of bounds".into()]
|
||||
}
|
||||
} else {
|
||||
vec!["get_clock_limits missing parameter 0".into()]
|
||||
}
|
||||
|
@ -155,23 +165,17 @@ pub fn get_clock_limits(
|
|||
}
|
||||
|
||||
pub fn unset_clock_limits(
|
||||
settings: Arc<Mutex<Vec<Cpu>>>,
|
||||
saver: Sender<()>,
|
||||
sender: Sender<ApiMessage>,
|
||||
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
|
||||
let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety
|
||||
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) {
|
||||
let mut settings_lock = unwrap_lock(settings.lock(), "cpu");
|
||||
if let Some(cpu) = settings_lock.get_mut(*index as usize) {
|
||||
cpu.clock_limits = None;
|
||||
unwrap_maybe_fatal(
|
||||
unwrap_lock(saver.lock(), "save channel").send(()),
|
||||
"Failed to send on save channel",
|
||||
);
|
||||
super::utility::map_empty_result(cpu.on_set(), true)
|
||||
} else {
|
||||
vec!["get_clock_limits cpu index out of bounds".into()]
|
||||
}
|
||||
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()]
|
||||
}
|
||||
|
@ -179,44 +183,67 @@ pub fn unset_clock_limits(
|
|||
}
|
||||
|
||||
pub fn set_cpu_governor(
|
||||
settings: Arc<Mutex<Vec<Cpu>>>,
|
||||
saver: Sender<()>,
|
||||
sender: Sender<ApiMessage>,
|
||||
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
|
||||
let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety
|
||||
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) {
|
||||
let mut settings_lock = unwrap_lock(settings.lock(), "cpu");
|
||||
if let Some(cpu) = settings_lock.get_mut(*index as usize) {
|
||||
if let Some(&Primitive::F64(index)) = params_in.get(0) {
|
||||
if let Some(Primitive::String(governor)) = params_in.get(1) {
|
||||
cpu.governor = governor.to_owned();
|
||||
unwrap_maybe_fatal(
|
||||
unwrap_lock(saver.lock(), "save channel").send(()),
|
||||
"Failed to send on save channel",
|
||||
);
|
||||
super::utility::map_empty_result(
|
||||
cpu.on_set(),
|
||||
&cpu.governor as &str,
|
||||
)
|
||||
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 cpu index out of bounds".into()]
|
||||
}
|
||||
} else {
|
||||
vec!["set_cpu_governor missing parameter 0".into()]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_cpu_governors(
|
||||
settings: Arc<Mutex<Vec<Cpu>>>,
|
||||
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) = ¶ms_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 settings_lock = unwrap_lock(settings.lock(), "cpu");
|
||||
let mut output = Vec::with_capacity(settings_lock.len());
|
||||
for cpu in settings_lock.as_slice() {
|
||||
output.push(cpu.governor.clone().into());
|
||||
let result = getter();
|
||||
let mut output = Vec::with_capacity(result.len());
|
||||
for cpu in result.as_slice() {
|
||||
output.push(cpu.clone().into());
|
||||
}
|
||||
output
|
||||
}
|
||||
|
|
|
@ -1,29 +1,25 @@
|
|||
use std::sync::{mpsc::Sender, Arc, Mutex};
|
||||
use std::sync::mpsc::{Sender, self};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use usdpl_back::core::serdes::Primitive;
|
||||
use usdpl_back::AsyncCallable;
|
||||
|
||||
use crate::settings::{General, Settings, OnSet};
|
||||
use crate::utility::{unwrap_lock, unwrap_maybe_fatal};
|
||||
//use crate::utility::{unwrap_lock, unwrap_maybe_fatal};
|
||||
use super::handler::{ApiMessage, GeneralMessage};
|
||||
|
||||
/// Generate set persistent web method
|
||||
pub fn set_persistent(
|
||||
settings: Arc<Mutex<General>>,
|
||||
saver: Sender<()>,
|
||||
sender: Sender<ApiMessage>,
|
||||
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
|
||||
let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety
|
||||
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
|
||||
let setter = move |pers: bool|
|
||||
sender.lock()
|
||||
.unwrap()
|
||||
.send(ApiMessage::General(GeneralMessage::SetPersistent(pers))).expect("set_persistent send failed");
|
||||
move |params_in: super::ApiParameterType| {
|
||||
if let Some(Primitive::Bool(new_val)) = params_in.get(0) {
|
||||
let mut settings_lock = unwrap_lock(settings.lock(), "general");
|
||||
settings_lock.persistent = *new_val;
|
||||
unwrap_maybe_fatal(
|
||||
unwrap_lock(saver.lock(), "save channel").send(()),
|
||||
"Failed to send on save channel",
|
||||
);
|
||||
let result = super::utility::map_empty_result(
|
||||
settings_lock.on_set(),
|
||||
settings_lock.persistent,
|
||||
);
|
||||
log::debug!("Persistent is now {}", settings_lock.persistent);
|
||||
result
|
||||
if let Some(&Primitive::Bool(new_val)) = params_in.get(0) {
|
||||
setter(new_val);
|
||||
//log::debug!("Persistent is now {}", settings_lock.persistent);
|
||||
vec![new_val.into()]
|
||||
} else {
|
||||
vec!["set_persistent missing parameter".into()]
|
||||
}
|
||||
|
@ -32,30 +28,34 @@ pub fn set_persistent(
|
|||
|
||||
/// Generate get persistent save mode web method
|
||||
pub fn get_persistent(
|
||||
settings: Arc<Mutex<General>>,
|
||||
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 |value: bool| tx.send(value).expect("get_persistent callback send failed");
|
||||
sender.lock().unwrap().send(ApiMessage::General(GeneralMessage::GetPersistent(Box::new(callback)))).expect("get_persistent send failed");
|
||||
rx.recv().expect("get_persistent callback recv failed")
|
||||
};
|
||||
move |_: super::ApiParameterType| {
|
||||
let settings_lock = unwrap_lock(settings.lock(), "general");
|
||||
vec![settings_lock
|
||||
.persistent.into()]
|
||||
vec![getter().into()]
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate load app settings from file web method
|
||||
pub fn load_settings(
|
||||
settings: Settings,
|
||||
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 |path: String, name: String|
|
||||
sender.lock()
|
||||
.unwrap()
|
||||
.send(ApiMessage::LoadSettings(path, name)).expect("load_settings send failed");
|
||||
move |params_in: super::ApiParameterType| {
|
||||
if let Some(Primitive::String(path)) = params_in.get(0) {
|
||||
if let Some(Primitive::String(name)) = params_in.get(1) {
|
||||
match settings.load_file(path.into(), name.to_owned(), false) {
|
||||
Err(e) => vec![e.msg.into()],
|
||||
Ok(success) =>
|
||||
super::utility::map_empty_result(
|
||||
settings.clone().on_set(),
|
||||
success
|
||||
)
|
||||
}
|
||||
setter(path.to_owned(), name.to_owned());
|
||||
vec![true.into()]
|
||||
} else {
|
||||
vec!["load_settings missing name parameter".into()]
|
||||
}
|
||||
|
@ -68,10 +68,17 @@ pub fn load_settings(
|
|||
|
||||
/// Generate load default settings from file web method
|
||||
pub fn load_default_settings(
|
||||
settings: Settings,
|
||||
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 ||
|
||||
sender.lock()
|
||||
.unwrap()
|
||||
.send(ApiMessage::LoadMainSettings).expect("load_default_settings send failed");
|
||||
move |_: super::ApiParameterType| {
|
||||
match settings.load_file(
|
||||
setter();
|
||||
vec![true.into()]
|
||||
/*match settings.load_file(
|
||||
crate::consts::DEFAULT_SETTINGS_FILE.into(),
|
||||
crate::consts::DEFAULT_SETTINGS_NAME.to_owned(),
|
||||
true
|
||||
|
@ -81,32 +88,76 @@ pub fn load_default_settings(
|
|||
settings.clone().on_set(),
|
||||
success
|
||||
)
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate load system default settings from file web method
|
||||
pub fn load_system_settings(
|
||||
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 ||
|
||||
sender.lock()
|
||||
.unwrap()
|
||||
.send(ApiMessage::LoadSystemSettings).expect("load_default_settings send failed");
|
||||
move |_: super::ApiParameterType| {
|
||||
setter();
|
||||
vec![true.into()]
|
||||
/*match settings.load_file(
|
||||
crate::consts::DEFAULT_SETTINGS_FILE.into(),
|
||||
crate::consts::DEFAULT_SETTINGS_NAME.to_owned(),
|
||||
true
|
||||
) {
|
||||
Err(e) => vec![e.msg.into()],
|
||||
Ok(success) => super::utility::map_empty_result(
|
||||
settings.clone().on_set(),
|
||||
success
|
||||
)
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate get current settings name
|
||||
pub fn get_name(
|
||||
settings: Arc<Mutex<General>>,
|
||||
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
|
||||
move |_: super::ApiParameterType| {
|
||||
let settings_lock = unwrap_lock(settings.lock(), "general");
|
||||
vec![settings_lock
|
||||
.name
|
||||
.clone()
|
||||
.into()]
|
||||
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 |name: String| tx.send(name).expect("get_name callback send failed");
|
||||
sender2.lock().unwrap().send(ApiMessage::General(GeneralMessage::GetCurrentProfileName(Box::new(callback)))).expect("get_name send failed");
|
||||
rx.recv().expect("get_name callback recv failed")
|
||||
}
|
||||
};
|
||||
super::async_utils::AsyncIshGetter {
|
||||
set_get: getter,
|
||||
trans_getter: |result| {
|
||||
vec![result.into()]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate wait for all locks to be available web method
|
||||
pub fn lock_unlock_all(
|
||||
settings: Settings,
|
||||
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
|
||||
move |_: super::ApiParameterType| {
|
||||
let _lock = unwrap_lock(settings.general.lock(), "general");
|
||||
let _lock = unwrap_lock(settings.cpus.lock(), "cpus");
|
||||
let _lock = unwrap_lock(settings.gpu.lock(), "gpu");
|
||||
let _lock = unwrap_lock(settings.battery.lock(), "battery");
|
||||
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 |x| tx.send(x).expect("lock_unlock_all callback send failed");
|
||||
sender2.lock().unwrap().send(ApiMessage::WaitForEmptyQueue(Box::new(callback))).expect("lock_unlock_all send failed");
|
||||
rx.recv().expect("lock_unlock_all callback recv failed")
|
||||
}
|
||||
};
|
||||
super::async_utils::AsyncIshGetter {
|
||||
set_get: getter,
|
||||
trans_getter: |_| {
|
||||
vec![true.into()]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,31 +1,25 @@
|
|||
use std::sync::{mpsc::Sender, Arc, Mutex};
|
||||
use std::sync::mpsc::{Sender, self};
|
||||
use std::sync::{Mutex, Arc};
|
||||
use usdpl_back::core::serdes::Primitive;
|
||||
use usdpl_back::AsyncCallable;
|
||||
|
||||
use crate::settings::{Gpu, OnSet, MinMax};
|
||||
use crate::utility::{unwrap_lock, unwrap_maybe_fatal};
|
||||
use crate::settings::MinMax;
|
||||
//use crate::utility::{unwrap_lock, unwrap_maybe_fatal};
|
||||
use super::handler::{ApiMessage, GpuMessage};
|
||||
|
||||
pub fn set_ppt(
|
||||
settings: Arc<Mutex<Gpu>>,
|
||||
saver: Sender<()>,
|
||||
sender: Sender<ApiMessage>,
|
||||
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
|
||||
let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety
|
||||
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
|
||||
let setter = move |fast: u64, slow: u64|
|
||||
sender.lock()
|
||||
.unwrap()
|
||||
.send(ApiMessage::Gpu(GpuMessage::SetPpt(Some(fast), Some(slow)))).expect("set_ppt send failed");
|
||||
move |params_in: super::ApiParameterType| {
|
||||
if let Some(Primitive::F64(fast_ppt)) = params_in.get(0) {
|
||||
if let Some(Primitive::F64(slow_ppt)) = params_in.get(1) {
|
||||
let mut settings_lock = unwrap_lock(settings.lock(), "gpu");
|
||||
settings_lock.fast_ppt = Some(*fast_ppt as u64);
|
||||
settings_lock.slow_ppt = Some(*slow_ppt as u64);
|
||||
unwrap_maybe_fatal(
|
||||
unwrap_lock(saver.lock(), "save channel").send(()),
|
||||
"Failed to send on save channel",
|
||||
);
|
||||
match settings_lock.on_set() {
|
||||
Ok(_) => vec![
|
||||
settings_lock.fast_ppt.unwrap().into(),
|
||||
settings_lock.slow_ppt.unwrap().into()
|
||||
],
|
||||
Err(e) => vec![e.msg.into()],
|
||||
}
|
||||
if let Some(&Primitive::F64(fast_ppt)) = params_in.get(0) {
|
||||
if let Some(&Primitive::F64(slow_ppt)) = params_in.get(1) {
|
||||
setter(fast_ppt as u64, slow_ppt as u64);
|
||||
vec![(fast_ppt as u64).into(), (slow_ppt as u64).into()]
|
||||
} else {
|
||||
vec!["set_ppt missing parameter 1".into()]
|
||||
}
|
||||
|
@ -36,60 +30,59 @@ pub fn set_ppt(
|
|||
}
|
||||
|
||||
pub fn get_ppt(
|
||||
settings: Arc<Mutex<Gpu>>,
|
||||
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
|
||||
move |_: super::ApiParameterType| {
|
||||
let settings_lock = unwrap_lock(settings.lock(), "gpu");
|
||||
let fast_ppt = settings_lock.fast_ppt.map(|x| x.into()).unwrap_or(Primitive::Empty);
|
||||
let slow_ppt = settings_lock.slow_ppt.map(|x| x.into()).unwrap_or(Primitive::Empty);
|
||||
vec![fast_ppt, slow_ppt]
|
||||
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 |ppt: (Option<u64>, Option<u64>)| tx.send(ppt).expect("get_ppt callback send failed");
|
||||
sender2.lock().unwrap().send(ApiMessage::Gpu(GpuMessage::GetPpt(Box::new(callback)))).expect("get_ppt send failed");
|
||||
rx.recv().expect("get_ppt callback recv failed")
|
||||
}
|
||||
};
|
||||
super::async_utils::AsyncIshGetter {
|
||||
set_get: getter,
|
||||
trans_getter: |(fast, slow): (Option<u64>, Option<u64>)| {
|
||||
vec![
|
||||
fast.map(|x| x.into()).unwrap_or(Primitive::Empty),
|
||||
slow.map(|x| x.into()).unwrap_or(Primitive::Empty),
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unset_ppt(
|
||||
settings: Arc<Mutex<Gpu>>,
|
||||
saver: Sender<()>,
|
||||
sender: Sender<ApiMessage>,
|
||||
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
|
||||
let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety
|
||||
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
|
||||
let setter = move ||
|
||||
sender.lock()
|
||||
.unwrap()
|
||||
.send(ApiMessage::Gpu(GpuMessage::SetPpt(None, None))).expect("set_ppt send failed");
|
||||
move |_: super::ApiParameterType| {
|
||||
let mut settings_lock = unwrap_lock(settings.lock(), "gpu");
|
||||
settings_lock.fast_ppt = None;
|
||||
settings_lock.slow_ppt = None;
|
||||
unwrap_maybe_fatal(
|
||||
unwrap_lock(saver.lock(), "save channel").send(()),
|
||||
"Failed to send on save channel",
|
||||
);
|
||||
super::utility::map_empty_result(
|
||||
settings_lock.on_set(),
|
||||
Primitive::Empty,
|
||||
)
|
||||
setter();
|
||||
vec![true.into()]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_clock_limits(
|
||||
settings: Arc<Mutex<Gpu>>,
|
||||
saver: Sender<()>,
|
||||
sender: Sender<ApiMessage>,
|
||||
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
|
||||
let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety
|
||||
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
|
||||
let setter = move |value: MinMax<u64>|
|
||||
sender.lock()
|
||||
.unwrap()
|
||||
.send(ApiMessage::Gpu(GpuMessage::SetClockLimits(Some(value)))).expect("set_clock_limits send failed");
|
||||
move |params_in: super::ApiParameterType| {
|
||||
if let Some(Primitive::F64(min)) = params_in.get(0) {
|
||||
if let Some(Primitive::F64(max)) = params_in.get(1) {
|
||||
let mut settings_lock = unwrap_lock(settings.lock(), "gpu");
|
||||
settings_lock.clock_limits = Some(MinMax {
|
||||
min: *min as _,
|
||||
max: *max as _,
|
||||
if let Some(&Primitive::F64(min)) = params_in.get(0) {
|
||||
if let Some(&Primitive::F64(max)) = params_in.get(1) {
|
||||
setter(MinMax {
|
||||
min: min as _,
|
||||
max: max as _,
|
||||
});
|
||||
unwrap_maybe_fatal(
|
||||
unwrap_lock(saver.lock(), "save channel").send(()),
|
||||
"Failed to send on save channel",
|
||||
);
|
||||
match settings_lock.on_set() {
|
||||
Ok(_) => vec![
|
||||
settings_lock.clock_limits.as_ref().unwrap().min.into(),
|
||||
settings_lock.clock_limits.as_ref().unwrap().max.into(),
|
||||
],
|
||||
Err(e) => vec![e.msg.into()]
|
||||
}
|
||||
vec![(min as u64).into(), (max as u64).into()]
|
||||
} else {
|
||||
vec!["set_clock_limits missing parameter 1".into()]
|
||||
}
|
||||
|
@ -100,51 +93,54 @@ pub fn set_clock_limits(
|
|||
}
|
||||
|
||||
pub fn get_clock_limits(
|
||||
settings: Arc<Mutex<Gpu>>,
|
||||
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
|
||||
move |_: super::ApiParameterType| {
|
||||
let settings_lock = unwrap_lock(settings.lock(), "gpu");
|
||||
if let Some(min_max) = &settings_lock.clock_limits {
|
||||
vec![min_max.min.into(), min_max.max.into()]
|
||||
} else {
|
||||
vec![Primitive::Empty, Primitive::Empty]
|
||||
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 |clocks: Option<MinMax<u64>>| tx.send(clocks).expect("get_clock_limits callback send failed");
|
||||
sender2.lock().unwrap().send(ApiMessage::Gpu(GpuMessage::GetClockLimits(Box::new(callback)))).expect("get_clock_limits send failed");
|
||||
rx.recv().expect("get_clock_limits callback recv failed")
|
||||
}
|
||||
};
|
||||
super::async_utils::AsyncIshGetter {
|
||||
set_get: getter,
|
||||
trans_getter: |clocks: Option<MinMax<u64>>| {
|
||||
clocks.map(|x| vec![
|
||||
x.min.into(), x.max.into()
|
||||
]).unwrap_or_else(|| vec![Primitive::Empty, Primitive::Empty])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unset_clock_limits(
|
||||
settings: Arc<Mutex<Gpu>>,
|
||||
saver: Sender<()>,
|
||||
sender: Sender<ApiMessage>,
|
||||
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
|
||||
let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety
|
||||
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
|
||||
let setter = move ||
|
||||
sender.lock()
|
||||
.unwrap()
|
||||
.send(ApiMessage::Gpu(GpuMessage::SetClockLimits(None))).expect("unset_clock_limits send failed");
|
||||
move |_: super::ApiParameterType| {
|
||||
let mut settings_lock = unwrap_lock(settings.lock(), "gpu");
|
||||
settings_lock.clock_limits = None;
|
||||
unwrap_maybe_fatal(
|
||||
unwrap_lock(saver.lock(), "save channel").send(()),
|
||||
"Failed to send on save channel",
|
||||
);
|
||||
super::utility::map_empty_result(settings_lock.on_set(), true)
|
||||
setter();
|
||||
vec![true.into()]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_slow_memory(
|
||||
settings: Arc<Mutex<Gpu>>,
|
||||
saver: Sender<()>,
|
||||
sender: Sender<ApiMessage>,
|
||||
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
|
||||
let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety
|
||||
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
|
||||
let setter = move |value: bool|
|
||||
sender.lock()
|
||||
.unwrap()
|
||||
.send(ApiMessage::Gpu(GpuMessage::SetSlowMemory(value))).expect("unset_clock_limits send failed");
|
||||
move |params_in: super::ApiParameterType| {
|
||||
if let Some(Primitive::Bool(memory_is_slow)) = params_in.get(0) {
|
||||
let mut settings_lock = unwrap_lock(settings.lock(), "gpu");
|
||||
settings_lock.slow_memory = *memory_is_slow;
|
||||
unwrap_maybe_fatal(
|
||||
unwrap_lock(saver.lock(), "save channel").send(()),
|
||||
"Failed to send on save channel",
|
||||
);
|
||||
super::utility::map_empty_result(
|
||||
settings_lock.on_set(),
|
||||
settings_lock.slow_memory,
|
||||
)
|
||||
if let Some(&Primitive::Bool(memory_is_slow)) = params_in.get(0) {
|
||||
setter(memory_is_slow);
|
||||
vec![memory_is_slow.into()]
|
||||
} else {
|
||||
vec!["set_slow_memory missing parameter 0".into()]
|
||||
}
|
||||
|
@ -152,10 +148,22 @@ pub fn set_slow_memory(
|
|||
}
|
||||
|
||||
pub fn get_slow_memory(
|
||||
settings: Arc<Mutex<Gpu>>,
|
||||
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
|
||||
move |_: super::ApiParameterType| {
|
||||
let settings_lock = unwrap_lock(settings.lock(), "cpu");
|
||||
vec![settings_lock.slow_memory.into()]
|
||||
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 |value: bool| tx.send(value).expect("get_slow_memory callback send failed");
|
||||
sender2.lock().unwrap().send(ApiMessage::Gpu(GpuMessage::GetSlowMemory(Box::new(callback)))).expect("get_slow_memory send failed");
|
||||
rx.recv().expect("get_slow_memory callback recv failed")
|
||||
}
|
||||
};
|
||||
super::async_utils::AsyncIshGetter {
|
||||
set_get: getter,
|
||||
trans_getter: |value: bool| {
|
||||
vec![value.into()]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
199
backend/src/api/handler.rs
Normal file
199
backend/src/api/handler.rs
Normal file
|
@ -0,0 +1,199 @@
|
|||
use std::sync::mpsc::{self, Receiver, Sender};
|
||||
|
||||
use crate::settings::{Settings, Cpu, Gpu, Battery, General, OnSet, OnResume, MinMax};
|
||||
use crate::persist::SettingsJson;
|
||||
use crate::utility::unwrap_maybe_fatal;
|
||||
|
||||
type Callback<T> = Box<dyn FnOnce(T) + Send>;
|
||||
|
||||
pub enum ApiMessage {
|
||||
Battery(BatteryMessage),
|
||||
Cpu(CpuMessage),
|
||||
Gpu(GpuMessage),
|
||||
General(GeneralMessage),
|
||||
OnResume,
|
||||
WaitForEmptyQueue(Callback<()>),
|
||||
LoadSettings(String, String), // (path, name)
|
||||
LoadMainSettings,
|
||||
LoadSystemSettings,
|
||||
}
|
||||
|
||||
pub enum BatteryMessage {
|
||||
SetChargeRate(Option<u64>),
|
||||
GetChargeRate(Callback<Option<u64>>),
|
||||
}
|
||||
|
||||
impl BatteryMessage {
|
||||
fn process(self, settings: &mut Battery) {
|
||||
match self {
|
||||
Self::SetChargeRate(rate) => settings.charge_rate = rate,
|
||||
Self::GetChargeRate(cb) => cb(settings.charge_rate),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum CpuMessage {
|
||||
SetCpuOnline(usize, bool),
|
||||
SetCpusOnline(Vec<bool>),
|
||||
GetCpusOnline(Callback<Vec<bool>>),
|
||||
SetClockLimits(usize, Option<MinMax<u64>>),
|
||||
GetClockLimits(usize, Callback<Option<MinMax<u64>>>),
|
||||
SetCpuGovernor(usize, String),
|
||||
SetCpusGovernor(Vec<String>),
|
||||
GetCpusGovernor(Callback<Vec<String>>),
|
||||
}
|
||||
|
||||
impl CpuMessage {
|
||||
fn process(self, settings: &mut Vec<Cpu>) {
|
||||
match self {
|
||||
Self::SetCpuOnline(index, status) => {settings.get_mut(index).map(|c| c.online = status);},
|
||||
Self::SetCpusOnline(cpus) => {
|
||||
for i in 0..cpus.len() {
|
||||
settings.get_mut(i).map(|c| c.online = cpus[i]);
|
||||
}
|
||||
},
|
||||
Self::GetCpusOnline(cb) => {
|
||||
let mut result = Vec::with_capacity(settings.len());
|
||||
for cpu in settings {
|
||||
result.push(cpu.online);
|
||||
}
|
||||
cb(result);
|
||||
},
|
||||
Self::SetClockLimits(index, clocks) => {settings.get_mut(index).map(|c| c.clock_limits = clocks);},
|
||||
Self::GetClockLimits(index, cb) => {settings.get(index).map(|c| cb(c.clock_limits.clone()));},
|
||||
Self::SetCpuGovernor(index, gov) => {settings.get_mut(index).map(|c| c.governor = gov);},
|
||||
Self::SetCpusGovernor(govs) => {
|
||||
for i in 0..govs.len() {
|
||||
settings.get_mut(i).map(|c| c.governor = govs[i].clone());
|
||||
}
|
||||
},
|
||||
Self::GetCpusGovernor(cb) => {
|
||||
let mut result = Vec::with_capacity(settings.len());
|
||||
for cpu in settings {
|
||||
result.push(cpu.governor.clone());
|
||||
}
|
||||
cb(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum GpuMessage {
|
||||
SetPpt(Option<u64>, Option<u64>), // (fast, slow)
|
||||
GetPpt(Callback<(Option<u64>, Option<u64>)>),
|
||||
SetClockLimits(Option<MinMax<u64>>),
|
||||
GetClockLimits(Callback<Option<MinMax<u64>>>),
|
||||
SetSlowMemory(bool),
|
||||
GetSlowMemory(Callback<bool>),
|
||||
}
|
||||
|
||||
impl GpuMessage {
|
||||
fn process(self, settings: &mut Gpu) {
|
||||
match self {
|
||||
Self::SetPpt(fast, slow) => {
|
||||
settings.fast_ppt = fast;
|
||||
settings.slow_ppt = slow;
|
||||
},
|
||||
Self::GetPpt(cb) => cb((settings.fast_ppt, settings.slow_ppt)),
|
||||
Self::SetClockLimits(clocks) => settings.clock_limits = clocks,
|
||||
Self::GetClockLimits(cb) => cb(settings.clock_limits.clone()),
|
||||
Self::SetSlowMemory(val) => settings.slow_memory = val,
|
||||
Self::GetSlowMemory(cb) => cb(settings.slow_memory),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum GeneralMessage {
|
||||
SetPersistent(bool),
|
||||
GetPersistent(Callback<bool>),
|
||||
GetCurrentProfileName(Callback<String>),
|
||||
}
|
||||
|
||||
impl GeneralMessage {
|
||||
fn process(self, settings: &mut General) {
|
||||
match self {
|
||||
Self::SetPersistent(val) => settings.persistent = val,
|
||||
Self::GetPersistent(cb) => cb(settings.persistent),
|
||||
Self::GetCurrentProfileName(cb) => cb(settings.name.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ApiMessageHandler {
|
||||
intake: Receiver<ApiMessage>,
|
||||
on_empty: Vec<Callback<()>>,
|
||||
}
|
||||
|
||||
impl ApiMessageHandler {
|
||||
pub fn process_forever(&mut self, settings: &mut Settings) {
|
||||
while let Ok(msg) = self.intake.recv() {
|
||||
self.process(settings, msg);
|
||||
while let Ok(msg) = self.intake.try_recv() {
|
||||
self.process(settings, msg);
|
||||
}
|
||||
// run on_set
|
||||
if let Err(e) = settings.on_set() {
|
||||
log::error!("Settings on_set() err: {}", e);
|
||||
}
|
||||
// do callbacks
|
||||
for func in self.on_empty.drain(..) {
|
||||
func(());
|
||||
}
|
||||
// save
|
||||
log::debug!("api_worker is saving...");
|
||||
let is_persistent = settings.general.persistent;
|
||||
if is_persistent {
|
||||
let save_path = crate::utility::settings_dir()
|
||||
.join(settings.general.path.clone());
|
||||
let settings_clone = settings.clone();
|
||||
let save_json: SettingsJson = settings_clone.into();
|
||||
unwrap_maybe_fatal(save_json.save(&save_path), "Failed to save settings");
|
||||
log::debug!("Saved settings to {}", save_path.display());
|
||||
} else {
|
||||
log::debug!("Ignored save request for non-persistent settings");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn process(&mut self, settings: &mut Settings, message: ApiMessage) {
|
||||
match message {
|
||||
ApiMessage::Battery(x) => x.process(&mut settings.battery),
|
||||
ApiMessage::Cpu(x) => x.process(&mut settings.cpus),
|
||||
ApiMessage::Gpu(x) => x.process(&mut settings.gpu),
|
||||
ApiMessage::General(x) => x.process(&mut settings.general),
|
||||
ApiMessage::OnResume => {
|
||||
if let Err(e) = settings.on_resume() {
|
||||
log::error!("Settings on_resume() err: {}", e);
|
||||
}
|
||||
}
|
||||
ApiMessage::WaitForEmptyQueue(callback) => self.on_empty.push(callback),
|
||||
ApiMessage::LoadSettings(path, name) => {
|
||||
match settings.load_file(path.into(), name, false) {
|
||||
Ok(success) => log::info!("Loaded settings file? {}", success),
|
||||
Err(e) => log::warn!("Load file err: {}", e),
|
||||
}
|
||||
}
|
||||
ApiMessage::LoadMainSettings => {
|
||||
match settings.load_file(
|
||||
crate::consts::DEFAULT_SETTINGS_FILE.into(),
|
||||
crate::consts::DEFAULT_SETTINGS_NAME.to_owned(),
|
||||
true
|
||||
) {
|
||||
Ok(success) => log::info!("Loaded main settings file? {}", success),
|
||||
Err(e) => log::warn!("Load file err: {}", e),
|
||||
}
|
||||
}
|
||||
ApiMessage::LoadSystemSettings => {
|
||||
settings.load_system_default();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new() -> (Self, Sender<ApiMessage>) {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
(Self {
|
||||
intake: rx,
|
||||
on_empty: Vec::with_capacity(4),
|
||||
}, tx)
|
||||
}
|
||||
}
|
|
@ -2,6 +2,8 @@ pub mod battery;
|
|||
pub mod cpu;
|
||||
pub mod general;
|
||||
pub mod gpu;
|
||||
pub mod handler;
|
||||
mod async_utils;
|
||||
mod utility;
|
||||
|
||||
pub(super) type ApiParameterType = Vec<usdpl_back::core::serdes::Primitive>;
|
||||
|
|
|
@ -14,7 +14,7 @@ pub fn map_result<T: Into<Primitive>>(result: Result<T, SettingError>) -> super:
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/*#[inline]
|
||||
pub fn map_empty_result<T: Into<Primitive>>(
|
||||
result: Result<(), SettingError>,
|
||||
success: T,
|
||||
|
@ -26,4 +26,4 @@ pub fn map_empty_result<T: Into<Primitive>>(
|
|||
vec![e.msg.into()]
|
||||
},
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
|
13
backend/src/api_worker.rs
Normal file
13
backend/src/api_worker.rs
Normal file
|
@ -0,0 +1,13 @@
|
|||
use std::thread::{self, JoinHandle};
|
||||
|
||||
use crate::settings::Settings;
|
||||
//use crate::utility::{unwrap_lock, unwrap_maybe_fatal};
|
||||
use crate::api::handler::ApiMessageHandler;
|
||||
|
||||
pub fn spawn(mut settings: Settings, mut handler: ApiMessageHandler) -> JoinHandle<()> {
|
||||
thread::spawn(move || {
|
||||
log::info!("api_worker starting...");
|
||||
handler.process_forever(&mut settings);
|
||||
log::warn!("api_worker completed!");
|
||||
})
|
||||
}
|
|
@ -4,4 +4,4 @@ pub const PACKAGE_NAME: &'static str = env!("CARGO_PKG_NAME");
|
|||
pub const PACKAGE_VERSION: &'static str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
pub const DEFAULT_SETTINGS_FILE: &str = "default_settings.json";
|
||||
pub const DEFAULT_SETTINGS_NAME: &str = "Default";
|
||||
pub const DEFAULT_SETTINGS_NAME: &str = "Main";
|
||||
|
|
|
@ -6,7 +6,8 @@ mod state;
|
|||
mod consts;
|
||||
use consts::*;
|
||||
mod resume_worker;
|
||||
mod save_worker;
|
||||
//mod save_worker;
|
||||
mod api_worker;
|
||||
mod utility;
|
||||
|
||||
use settings::OnSet;
|
||||
|
@ -49,14 +50,16 @@ fn main() -> Result<(), ()> {
|
|||
|
||||
log::debug!("Settings: {:?}", loaded_settings);
|
||||
|
||||
let (_save_handle, save_sender) = save_worker::spawn(loaded_settings.clone());
|
||||
let _resume_handle = resume_worker::spawn(loaded_settings.clone());
|
||||
let (api_handler, api_sender) = crate::api::handler::ApiMessageHandler::new();
|
||||
|
||||
//let (_save_handle, save_sender) = save_worker::spawn(loaded_settings.clone());
|
||||
let _resume_handle = resume_worker::spawn(api_sender.clone());
|
||||
|
||||
if let Err(e) = loaded_settings.on_set() {
|
||||
log::error!("Startup Settings.on_set() error: {}", e);
|
||||
}
|
||||
|
||||
Instance::new(PORT)
|
||||
let instance = Instance::new(PORT)
|
||||
.register("V_INFO", |_: Vec<Primitive>| {
|
||||
vec![format!("{} v{}", PACKAGE_NAME, PACKAGE_VERSION).into()]
|
||||
})
|
||||
|
@ -67,107 +70,119 @@ fn main() -> Result<(), ()> {
|
|||
.register("BATTERY_charge_design", api::battery::charge_design)
|
||||
.register(
|
||||
"BATTERY_set_charge_rate",
|
||||
api::battery::set_charge_rate(loaded_settings.battery.clone(), save_sender.clone()),
|
||||
api::battery::set_charge_rate(api_sender.clone()),
|
||||
)
|
||||
.register(
|
||||
"BATTERY_get_charge_rate",
|
||||
api::battery::get_charge_rate(loaded_settings.battery.clone()),
|
||||
api::battery::get_charge_rate(api_sender.clone()),
|
||||
)
|
||||
.register(
|
||||
"BATTERY_unset_charge_rate",
|
||||
api::battery::unset_charge_rate(loaded_settings.battery.clone(), save_sender.clone()),
|
||||
api::battery::unset_charge_rate(api_sender.clone()),
|
||||
)
|
||||
// cpu API functions
|
||||
.register("CPU_count", api::cpu::max_cpus)
|
||||
.register(
|
||||
"CPU_set_online",
|
||||
api::cpu::set_cpu_online(loaded_settings.cpus.clone(), save_sender.clone())
|
||||
api::cpu::set_cpu_online(api_sender.clone())
|
||||
)
|
||||
.register(
|
||||
"CPU_set_onlines",
|
||||
api::cpu::set_cpus_online(loaded_settings.cpus.clone(), save_sender.clone())
|
||||
api::cpu::set_cpus_online(api_sender.clone())
|
||||
)
|
||||
.register(
|
||||
.register_async(
|
||||
"CPU_get_onlines",
|
||||
api::cpu::get_cpus_online(loaded_settings.cpus.clone())
|
||||
api::cpu::get_cpus_online(api_sender.clone())
|
||||
)
|
||||
.register(
|
||||
"CPU_set_clock_limits",
|
||||
api::cpu::set_clock_limits(loaded_settings.cpus.clone(), save_sender.clone())
|
||||
api::cpu::set_clock_limits(api_sender.clone())
|
||||
)
|
||||
.register(
|
||||
"CPU_get_clock_limits",
|
||||
api::cpu::get_clock_limits(loaded_settings.cpus.clone())
|
||||
api::cpu::get_clock_limits(api_sender.clone())
|
||||
)
|
||||
.register(
|
||||
"CPU_unset_clock_limits",
|
||||
api::cpu::unset_clock_limits(loaded_settings.cpus.clone(), save_sender.clone())
|
||||
api::cpu::unset_clock_limits(api_sender.clone())
|
||||
)
|
||||
.register(
|
||||
"CPU_set_governor",
|
||||
api::cpu::set_cpu_governor(loaded_settings.cpus.clone(), save_sender.clone())
|
||||
api::cpu::set_cpu_governor(api_sender.clone())
|
||||
)
|
||||
.register(
|
||||
"CPU_set_governors",
|
||||
api::cpu::set_cpus_governors(api_sender.clone())
|
||||
)
|
||||
.register(
|
||||
"CPU_get_governors",
|
||||
api::cpu::get_cpu_governors(loaded_settings.cpus.clone())
|
||||
api::cpu::get_cpu_governors(api_sender.clone())
|
||||
)
|
||||
// gpu API functions
|
||||
.register(
|
||||
"GPU_set_ppt",
|
||||
api::gpu::set_ppt(loaded_settings.gpu.clone(), save_sender.clone())
|
||||
api::gpu::set_ppt(api_sender.clone())
|
||||
)
|
||||
.register(
|
||||
.register_async(
|
||||
"GPU_get_ppt",
|
||||
api::gpu::get_ppt(loaded_settings.gpu.clone())
|
||||
api::gpu::get_ppt(api_sender.clone())
|
||||
)
|
||||
.register(
|
||||
"GPU_unset_ppt",
|
||||
api::gpu::unset_ppt(loaded_settings.gpu.clone(), save_sender.clone())
|
||||
api::gpu::unset_ppt(api_sender.clone())
|
||||
)
|
||||
.register(
|
||||
"GPU_set_clock_limits",
|
||||
api::gpu::set_clock_limits(loaded_settings.gpu.clone(), save_sender.clone())
|
||||
api::gpu::set_clock_limits(api_sender.clone())
|
||||
)
|
||||
.register(
|
||||
.register_async(
|
||||
"GPU_get_clock_limits",
|
||||
api::gpu::get_clock_limits(loaded_settings.gpu.clone())
|
||||
api::gpu::get_clock_limits(api_sender.clone())
|
||||
)
|
||||
.register(
|
||||
"GPU_unset_clock_limits",
|
||||
api::gpu::unset_clock_limits(loaded_settings.gpu.clone(), save_sender.clone())
|
||||
api::gpu::unset_clock_limits(api_sender.clone())
|
||||
)
|
||||
.register(
|
||||
"GPU_set_slow_memory",
|
||||
api::gpu::set_slow_memory(loaded_settings.gpu.clone(), save_sender.clone())
|
||||
api::gpu::set_slow_memory(api_sender.clone())
|
||||
)
|
||||
.register(
|
||||
.register_async(
|
||||
"GPU_get_slow_memory",
|
||||
api::gpu::get_slow_memory(loaded_settings.gpu.clone())
|
||||
api::gpu::get_slow_memory(api_sender.clone())
|
||||
)
|
||||
// general API functions
|
||||
.register(
|
||||
"GENERAL_set_persistent",
|
||||
api::general::set_persistent(loaded_settings.general.clone(), save_sender.clone())
|
||||
api::general::set_persistent(api_sender.clone())
|
||||
)
|
||||
.register(
|
||||
"GENERAL_get_persistent",
|
||||
api::general::get_persistent(loaded_settings.general.clone())
|
||||
api::general::get_persistent(api_sender.clone())
|
||||
)
|
||||
.register(
|
||||
"GENERAL_load_settings",
|
||||
api::general::load_settings(loaded_settings.clone())
|
||||
api::general::load_settings(api_sender.clone())
|
||||
)
|
||||
.register(
|
||||
"GENERAL_load_default_settings",
|
||||
api::general::load_default_settings(loaded_settings.clone())
|
||||
api::general::load_default_settings(api_sender.clone())
|
||||
)
|
||||
.register(
|
||||
"GENERAL_load_system_settings",
|
||||
api::general::load_system_settings(api_sender.clone())
|
||||
)
|
||||
.register_async(
|
||||
"GENERAL_get_name",
|
||||
api::general::get_name(loaded_settings.general.clone())
|
||||
api::general::get_name(api_sender.clone())
|
||||
)
|
||||
.register(
|
||||
.register_async(
|
||||
"GENERAL_wait_for_unlocks",
|
||||
api::general::lock_unlock_all(loaded_settings.clone())
|
||||
)
|
||||
api::general::lock_unlock_all(api_sender.clone())
|
||||
);
|
||||
|
||||
api_worker::spawn(loaded_settings, api_handler);
|
||||
|
||||
instance
|
||||
.run_blocking()
|
||||
}
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
use std::thread::{self, JoinHandle};
|
||||
use std::time::{Duration, Instant};
|
||||
use std::sync::mpsc::Sender;
|
||||
|
||||
use crate::settings::{OnResume, Settings};
|
||||
use crate::utility::unwrap_maybe_fatal;
|
||||
use crate::api::handler::ApiMessage;
|
||||
//use crate::utility::unwrap_maybe_fatal;
|
||||
|
||||
const ALLOWED_ERROR: f64 = 100.0; // period of 10ms with 100x means sleep has to be >= 1s to be detected
|
||||
|
||||
pub fn spawn(settings: Settings) -> JoinHandle<()> {
|
||||
pub fn spawn(sender: Sender<ApiMessage>) -> JoinHandle<()> {
|
||||
thread::spawn(move || {
|
||||
log::info!("resume_worker starting...");
|
||||
let duration = Duration::from_millis(10); // very low so it detects before Steam client does
|
||||
|
@ -18,7 +19,7 @@ pub fn spawn(settings: Settings) -> JoinHandle<()> {
|
|||
if old_start.as_secs_f64() > duration.as_secs_f64() * (1.0 + ALLOWED_ERROR) {
|
||||
// has just resumed from sleep
|
||||
log::info!("Resume detected");
|
||||
unwrap_maybe_fatal(settings.on_resume(), "On resume failure");
|
||||
sender.send(ApiMessage::OnResume).expect("resume_worker send failed");
|
||||
log::debug!(
|
||||
"OnResume completed after sleeping for {}s",
|
||||
old_start.as_secs_f32()
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use std::convert::Into;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::{Arc, Mutex};
|
||||
//use std::sync::{Arc, Mutex};
|
||||
|
||||
use super::{Battery, Cpu, Gpu};
|
||||
use super::{OnResume, OnSet, SettingError};
|
||||
use crate::persist::{CpuJson, SettingsJson};
|
||||
use crate::utility::unwrap_lock;
|
||||
//use crate::utility::unwrap_lock;
|
||||
|
||||
const LATEST_VERSION: u64 = 0;
|
||||
|
||||
|
@ -43,24 +43,20 @@ impl OnSet for General {
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Settings {
|
||||
pub general: Arc<Mutex<General>>,
|
||||
pub cpus: Arc<Mutex<Vec<Cpu>>>,
|
||||
pub gpu: Arc<Mutex<Gpu>>,
|
||||
pub battery: Arc<Mutex<Battery>>,
|
||||
pub general: General,
|
||||
pub cpus: Vec<Cpu>,
|
||||
pub gpu: Gpu,
|
||||
pub battery: Battery,
|
||||
}
|
||||
|
||||
impl OnSet for Settings {
|
||||
fn on_set(&mut self) -> Result<(), SettingError> {
|
||||
unwrap_lock(self.battery.lock(), "battery").on_set()?;
|
||||
{
|
||||
// cpu lock scope
|
||||
let mut cpu_lock = unwrap_lock(self.cpus.lock(), "cpu");
|
||||
for cpu in cpu_lock.iter_mut() {
|
||||
self.battery.on_set()?;
|
||||
for cpu in self.cpus.iter_mut() {
|
||||
cpu.on_set()?;
|
||||
}
|
||||
}
|
||||
unwrap_lock(self.gpu.lock(), "gpu").on_set()?;
|
||||
unwrap_lock(self.general.lock(), "general").on_set()?;
|
||||
self.gpu.on_set()?;
|
||||
self.general.on_set()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -70,24 +66,24 @@ impl Settings {
|
|||
pub fn from_json(other: SettingsJson, json_path: PathBuf) -> Self {
|
||||
match other.version {
|
||||
0 => Self {
|
||||
general: Arc::new(Mutex::new(General {
|
||||
general: General {
|
||||
persistent: other.persistent,
|
||||
path: json_path,
|
||||
name: other.name,
|
||||
})),
|
||||
cpus: Arc::new(Mutex::new(Self::convert_cpus(other.cpus, other.version))),
|
||||
gpu: Arc::new(Mutex::new(Gpu::from_json(other.gpu, other.version))),
|
||||
battery: Arc::new(Mutex::new(Battery::from_json(other.battery, other.version))),
|
||||
},
|
||||
cpus: Self::convert_cpus(other.cpus, other.version),
|
||||
gpu: Gpu::from_json(other.gpu, other.version),
|
||||
battery: Battery::from_json(other.battery, other.version),
|
||||
},
|
||||
_ => Self {
|
||||
general: Arc::new(Mutex::new(General {
|
||||
general: General {
|
||||
persistent: other.persistent,
|
||||
path: json_path,
|
||||
name: other.name,
|
||||
})),
|
||||
cpus: Arc::new(Mutex::new(Self::convert_cpus(other.cpus, other.version))),
|
||||
gpu: Arc::new(Mutex::new(Gpu::from_json(other.gpu, other.version))),
|
||||
battery: Arc::new(Mutex::new(Battery::from_json(other.battery, other.version))),
|
||||
},
|
||||
cpus: Self::convert_cpus(other.cpus, other.version),
|
||||
gpu: Gpu::from_json(other.gpu, other.version),
|
||||
battery: Battery::from_json(other.battery, other.version),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -117,35 +113,26 @@ impl Settings {
|
|||
|
||||
pub fn system_default(json_path: PathBuf) -> Self {
|
||||
Self {
|
||||
general: Arc::new(Mutex::new(General {
|
||||
general: General {
|
||||
persistent: false,
|
||||
path: json_path,
|
||||
name: crate::consts::DEFAULT_SETTINGS_NAME.to_owned(),
|
||||
})),
|
||||
cpus: Arc::new(Mutex::new(Cpu::system_default())),
|
||||
gpu: Arc::new(Mutex::new(Gpu::system_default())),
|
||||
battery: Arc::new(Mutex::new(Battery::system_default())),
|
||||
},
|
||||
cpus: Cpu::system_default(),
|
||||
gpu: Gpu::system_default(),
|
||||
battery: Battery::system_default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn load_system_default(&self) {
|
||||
{
|
||||
let mut cpu_lock = unwrap_lock(self.cpus.lock(), "cpu");
|
||||
*cpu_lock = Cpu::system_default();
|
||||
}
|
||||
{
|
||||
let mut gpu_lock = unwrap_lock(self.gpu.lock(), "gpu");
|
||||
*gpu_lock = Gpu::system_default();
|
||||
}
|
||||
{
|
||||
let mut battery_lock = unwrap_lock(self.battery.lock(), "battery");
|
||||
*battery_lock = Battery::system_default();
|
||||
}
|
||||
pub fn load_system_default(&mut self) {
|
||||
self.cpus = Cpu::system_default();
|
||||
self.gpu = Gpu::system_default();
|
||||
self.battery = Battery::system_default();
|
||||
}
|
||||
|
||||
pub fn load_file(&self, filename: PathBuf, name: String, system_defaults: bool) -> Result<bool, SettingError> {
|
||||
pub fn load_file(&mut self, filename: PathBuf, name: String, system_defaults: bool) -> Result<bool, SettingError> {
|
||||
let json_path = crate::utility::settings_dir().join(filename);
|
||||
let mut general_lock = unwrap_lock(self.general.lock(), "general");
|
||||
//let mut general_lock = unwrap_lock(self.general.lock(), "general");
|
||||
if json_path.exists() {
|
||||
let settings_json = SettingsJson::open(&json_path).map_err(|e| SettingError {
|
||||
msg: e.to_string(),
|
||||
|
@ -153,53 +140,38 @@ impl Settings {
|
|||
})?;
|
||||
if !settings_json.persistent {
|
||||
log::warn!("Loaded persistent config `{}` ({}) with persistent=false", &settings_json.name, json_path.display());
|
||||
general_lock.persistent = false;
|
||||
general_lock.name = name;
|
||||
self.general.persistent = false;
|
||||
self.general.name = name;
|
||||
} else {
|
||||
let new_cpus = Self::convert_cpus(settings_json.cpus, settings_json.version);
|
||||
let new_gpu = Gpu::from_json(settings_json.gpu, settings_json.version);
|
||||
let new_battery = Battery::from_json(settings_json.battery, settings_json.version);
|
||||
{
|
||||
let mut cpu_lock = unwrap_lock(self.cpus.lock(), "cpu");
|
||||
*cpu_lock = new_cpus;
|
||||
}
|
||||
{
|
||||
let mut gpu_lock = unwrap_lock(self.gpu.lock(), "gpu");
|
||||
*gpu_lock = new_gpu;
|
||||
}
|
||||
{
|
||||
let mut battery_lock = unwrap_lock(self.battery.lock(), "battery");
|
||||
*battery_lock = new_battery;
|
||||
}
|
||||
general_lock.persistent = true;
|
||||
general_lock.name = settings_json.name;
|
||||
self.cpus = Self::convert_cpus(settings_json.cpus, settings_json.version);
|
||||
self.gpu = Gpu::from_json(settings_json.gpu, settings_json.version);
|
||||
self.battery = Battery::from_json(settings_json.battery, settings_json.version);
|
||||
self.general.persistent = true;
|
||||
self.general.name = settings_json.name;
|
||||
}
|
||||
} else {
|
||||
if system_defaults {
|
||||
self.load_system_default();
|
||||
}
|
||||
general_lock.persistent = false;
|
||||
general_lock.name = name;
|
||||
self.general.persistent = false;
|
||||
self.general.name = name;
|
||||
}
|
||||
general_lock.path = json_path;
|
||||
Ok(general_lock.persistent)
|
||||
self.general.path = json_path;
|
||||
Ok(self.general.persistent)
|
||||
}
|
||||
}
|
||||
|
||||
impl OnResume for Settings {
|
||||
fn on_resume(&self) -> Result<(), SettingError> {
|
||||
log::debug!("Locking settings for on_resume");
|
||||
unwrap_lock(self.battery.lock(), "battery").on_resume()?;
|
||||
log::debug!("Got battery lock");
|
||||
{
|
||||
let cpu_lock = unwrap_lock(self.cpus.lock(), "cpu");
|
||||
log::debug!("Got cpus lock");
|
||||
for cpu in cpu_lock.iter() {
|
||||
log::debug!("Applying settings for on_resume");
|
||||
self.battery.on_resume()?;
|
||||
log::debug!("Resumed battery");
|
||||
for cpu in self.cpus.iter() {
|
||||
cpu.on_resume()?;
|
||||
}
|
||||
}
|
||||
unwrap_lock(self.gpu.lock(), "gpu").on_resume()?;
|
||||
log::debug!("Got gpu lock");
|
||||
log::debug!("Resumed CPUs");
|
||||
self.gpu.on_resume()?;
|
||||
log::debug!("Resumed GPU");
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -207,26 +179,18 @@ impl OnResume for Settings {
|
|||
impl Into<SettingsJson> for Settings {
|
||||
#[inline]
|
||||
fn into(self) -> SettingsJson {
|
||||
log::debug!("Locking settings to convert into json");
|
||||
let gen_lock = unwrap_lock(self.general.lock(), "general");
|
||||
log::debug!("Got general lock");
|
||||
let cpu_lock = unwrap_lock(self.cpus.lock(), "cpu");
|
||||
log::debug!("Got cpus lock");
|
||||
let gpu_lock = unwrap_lock(self.gpu.lock(), "gpu");
|
||||
log::debug!("Got gpu lock");
|
||||
let batt_lock = unwrap_lock(self.battery.lock(), "battery");
|
||||
log::debug!("Got battery lock");
|
||||
log::debug!("Converting into json");
|
||||
SettingsJson {
|
||||
version: LATEST_VERSION,
|
||||
name: gen_lock.name.clone(),
|
||||
persistent: gen_lock.persistent,
|
||||
cpus: cpu_lock
|
||||
name: self.general.name.clone(),
|
||||
persistent: self.general.persistent,
|
||||
cpus: self.cpus
|
||||
.clone()
|
||||
.drain(..)
|
||||
.map(|cpu| cpu.into())
|
||||
.collect(),
|
||||
gpu: gpu_lock.clone().into(),
|
||||
battery: batt_lock.clone().into(),
|
||||
gpu: self.gpu.clone().into(),
|
||||
battery: self.battery.clone().into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use std::fmt::Display;
|
||||
use std::sync::{LockResult, MutexGuard};
|
||||
//use std::sync::{LockResult, MutexGuard};
|
||||
|
||||
pub fn unwrap_maybe_fatal<T: Sized, E: Display>(result: Result<T, E>, message: &str) -> T {
|
||||
match result {
|
||||
|
@ -11,7 +11,7 @@ pub fn unwrap_maybe_fatal<T: Sized, E: Display>(result: Result<T, E>, message: &
|
|||
}
|
||||
}
|
||||
|
||||
pub fn unwrap_lock<'a, T: Sized>(
|
||||
/*pub fn unwrap_lock<'a, T: Sized>(
|
||||
result: LockResult<MutexGuard<'a, T>>,
|
||||
lock_name: &str,
|
||||
) -> MutexGuard<'a, T> {
|
||||
|
@ -22,7 +22,7 @@ pub fn unwrap_lock<'a, T: Sized>(
|
|||
panic!("Failed to acquire {} lock: {}", lock_name, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
pub fn settings_dir() -> std::path::PathBuf {
|
||||
usdpl_back::api::dirs::home()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "PowerTools",
|
||||
"version": "1.0.5",
|
||||
"version": "1.1.0",
|
||||
"description": "Power tweaks for power users",
|
||||
"scripts": {
|
||||
"build": "shx rm -rf dist && rollup -c",
|
||||
|
|
Loading…
Reference in a new issue