mirror of
https://github.com/hinto-janai/gupax.git
synced 2024-12-23 03:19:21 +00:00
command: implement basic data structures, functions
This adds the basic wireframe of how processes will be handled. The data/funcs in [command.rs] will be the API the main GUI thread uses to talk to child processes. The process thread will loop every 1 second to read/write the necessary data (stdout, stdin), and handle signals from the GUI thread (kill, restart, etc).
This commit is contained in:
parent
aff46a96d0
commit
212baf93ec
4 changed files with 117 additions and 1 deletions
111
src/command.rs
111
src/command.rs
|
@ -14,3 +14,114 @@
|
|||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
// This file handles all things related to child processes (P2Pool/XMRig).
|
||||
// The main GUI thread will interface with the [Arc<Mutex<...>>] data found
|
||||
// here, e.g: User clicks [Start P2Pool] -> Init p2pool thread here.
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Import
|
||||
use std::{
|
||||
sync::{Arc,Mutex},
|
||||
path::PathBuf,
|
||||
process::Command,
|
||||
thread,
|
||||
};
|
||||
use crate::constants::*;
|
||||
use log::*;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- [Process] Struct
|
||||
// This holds all the state of a (child) process.
|
||||
// The actual process thread runs in a 1 second loop, reading/writing to this struct.
|
||||
// The main GUI thread will use this to display console text, online state, etc.
|
||||
pub struct Process {
|
||||
name: ProcessName, // P2Pool or XMRig?
|
||||
online: bool, // Is the process alive?
|
||||
args: String, // A single [String] containing the arguments
|
||||
path: PathBuf, // The absolute path to the process binary
|
||||
signal: ProcessSignal, // Did the user click [Stop/Restart]?
|
||||
output: String, // This is the process's stdout + stderr
|
||||
// STDIN Problem:
|
||||
// - User can input many many commands in 1 second
|
||||
// - The process loop only processes every 1 second
|
||||
// - If there is only 1 [String] holding the user input,
|
||||
// the user could overwrite their last input before
|
||||
// the loop even has a chance to process their last command
|
||||
// STDIN Solution:
|
||||
// - When the user inputs something, push it to a [Vec]
|
||||
// - In the process loop, loop over every [Vec] element and
|
||||
// send each one individually to the process stdin
|
||||
input: Vec<String>,
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- [Process] Impl
|
||||
impl Process {
|
||||
pub fn new(name: ProcessName, args: String, path: PathBuf) -> Self {
|
||||
Self {
|
||||
name,
|
||||
online: false,
|
||||
args,
|
||||
path,
|
||||
signal: ProcessSignal::None,
|
||||
output: String::new(),
|
||||
input: vec![String::new()],
|
||||
}
|
||||
}
|
||||
|
||||
// Borrow a [&str], return an owned split collection
|
||||
pub fn parse_args(args: &str) -> Vec<String> {
|
||||
args.split_whitespace().map(|s| s.to_owned()).collect()
|
||||
}
|
||||
|
||||
pub fn spawn(process: &Arc<Mutex<Self>>, name: ProcessName) {
|
||||
// Setup
|
||||
let process = Arc::clone(process);
|
||||
let args = Self::parse_args(&process.lock().unwrap().args);
|
||||
info!("{} | Spawning initial thread", name);
|
||||
info!("{} | Arguments: {:?}", name, args);
|
||||
|
||||
// Spawn thread
|
||||
thread::spawn(move || {
|
||||
// Create & spawn child
|
||||
let mut child = Command::new(&process.lock().unwrap().path)
|
||||
.args(args)
|
||||
.stdout(std::process::Stdio::piped())
|
||||
.spawn().unwrap();
|
||||
|
||||
// 1-second loop, reading and writing data to relevent struct
|
||||
loop {
|
||||
let process = process.lock().unwrap(); // Get lock
|
||||
// If user sent a signal, handle it
|
||||
match process.signal {
|
||||
ProcessSignal::None => {},
|
||||
_ => { child.kill(); break; },
|
||||
};
|
||||
// println!("{:?}", String::from_utf8(child.wait_with_output().unwrap().stdout).unwrap());
|
||||
thread::sleep(SECOND);
|
||||
}
|
||||
|
||||
// End of thread, must mean process is offline
|
||||
process.lock().unwrap().online = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- [ProcessSignal] Enum
|
||||
#[derive(Copy,Clone,Eq,PartialEq,Debug)]
|
||||
pub enum ProcessSignal {
|
||||
None,
|
||||
Stop,
|
||||
Restart,
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- [ProcessName] Enum
|
||||
#[derive(Copy,Clone,Eq,PartialEq,Debug)]
|
||||
pub enum ProcessName {
|
||||
P2Pool,
|
||||
XMRig,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for ProcessName {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "{:#?}", self)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,6 +52,9 @@ pub const YELLOW: egui::Color32 = egui::Color32::from_rgb(230, 230, 100);
|
|||
pub const LIGHT_GRAY: egui::Color32 = egui::Color32::LIGHT_GRAY;
|
||||
pub const BLACK: egui::Color32 = egui::Color32::BLACK;
|
||||
|
||||
// [Duration] constants
|
||||
pub const SECOND: std::time::Duration = std::time::Duration::from_secs(1);
|
||||
|
||||
// OS specific
|
||||
#[cfg(target_os = "windows")]
|
||||
pub const OS: &'static str = " Windows";
|
||||
|
|
|
@ -60,6 +60,7 @@ mod gupax;
|
|||
mod p2pool;
|
||||
mod xmrig;
|
||||
mod update;
|
||||
mod command;
|
||||
use {ferris::*,constants::*,node::*,disk::*,status::*,update::*,gupax::*};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Struct + Impl
|
||||
|
|
|
@ -19,7 +19,8 @@ use crate::{
|
|||
Regexes,
|
||||
constants::*,
|
||||
disk::*,
|
||||
node::*
|
||||
node::*,
|
||||
command::*,
|
||||
};
|
||||
use egui::{
|
||||
TextEdit,SelectableLabel,ComboBox,Label,Button,
|
||||
|
|
Loading…
Reference in a new issue