minifly_litefs/
process.rs1use std::path::PathBuf;
2use std::process::{Child, Command, Stdio};
3use std::sync::Arc;
4use tokio::sync::Mutex;
5use tracing::{info, warn, error};
6use crate::config::LiteFSConfig;
7use minifly_core::Error;
8use crate::Result;
9
10pub struct LiteFSProcess {
11 child: Option<Child>,
12 config_path: PathBuf,
13 binary_path: PathBuf,
14 machine_id: String,
15}
16
17impl LiteFSProcess {
18 pub fn new(machine_id: String, binary_path: PathBuf, config_path: PathBuf) -> Self {
19 Self {
20 child: None,
21 config_path,
22 binary_path,
23 machine_id,
24 }
25 }
26
27 pub fn start(&mut self) -> Result<()> {
28 if self.child.is_some() {
29 return Err(Error::LiteFSError("LiteFS process already running".to_string()));
30 }
31
32 info!("Starting LiteFS for machine {}", self.machine_id);
33
34 let mut cmd = Command::new(&self.binary_path);
35 cmd.arg("mount")
36 .arg("-config")
37 .arg(&self.config_path)
38 .stdout(Stdio::piped())
39 .stderr(Stdio::piped());
40
41 match cmd.spawn() {
42 Ok(child) => {
43 info!("LiteFS process started with PID: {:?}", child.id());
44 self.child = Some(child);
45 Ok(())
46 }
47 Err(e) => {
48 error!("Failed to start LiteFS: {}", e);
49 Err(Error::LiteFSError(format!("Failed to start LiteFS: {}", e)))
50 }
51 }
52 }
53
54 pub fn stop(&mut self) -> Result<()> {
55 if let Some(mut child) = self.child.take() {
56 info!("Stopping LiteFS process for machine {}", self.machine_id);
57
58 match child.kill() {
59 Ok(_) => {
60 match child.wait() {
61 Ok(status) => {
62 info!("LiteFS process stopped with status: {:?}", status);
63 Ok(())
64 }
65 Err(e) => {
66 warn!("Error waiting for LiteFS process to stop: {}", e);
67 Ok(())
68 }
69 }
70 }
71 Err(e) => {
72 error!("Failed to stop LiteFS process: {}", e);
73 Err(Error::LiteFSError(format!("Failed to stop LiteFS: {}", e)))
74 }
75 }
76 } else {
77 Ok(())
78 }
79 }
80
81 pub fn is_running(&mut self) -> bool {
82 if let Some(ref mut child) = self.child {
83 match child.try_wait() {
84 Ok(Some(_)) => {
85 self.child = None;
87 false
88 }
89 Ok(None) => {
90 true
92 }
93 Err(_) => {
94 self.child = None;
96 false
97 }
98 }
99 } else {
100 false
101 }
102 }
103}
104
105impl Drop for LiteFSProcess {
106 fn drop(&mut self) {
107 if let Err(e) = self.stop() {
108 error!("Error stopping LiteFS process in drop: {}", e);
109 }
110 }
111}
112
113pub struct LiteFSProcessManager {
114 processes: Arc<Mutex<std::collections::HashMap<String, LiteFSProcess>>>,
115 binary_path: PathBuf,
116}
117
118impl LiteFSProcessManager {
119 pub fn new(binary_path: PathBuf) -> Self {
120 Self {
121 processes: Arc::new(Mutex::new(std::collections::HashMap::new())),
122 binary_path,
123 }
124 }
125
126 pub async fn start_litefs(&self, machine_id: &str, config: &LiteFSConfig, config_dir: &PathBuf) -> Result<()> {
127 let config_path = config_dir.join(format!("{}.yml", machine_id));
128
129 let yaml = config.to_yaml()
131 .map_err(|e| Error::LiteFSError(format!("Failed to serialize config: {}", e)))?;
132
133 tokio::fs::write(&config_path, yaml).await
134 .map_err(|e| Error::LiteFSError(format!("Failed to write config: {}", e)))?;
135
136 let mut processes = self.processes.lock().await;
137
138 let mut process = LiteFSProcess::new(
139 machine_id.to_string(),
140 self.binary_path.clone(),
141 config_path,
142 );
143
144 process.start()?;
145 processes.insert(machine_id.to_string(), process);
146
147 Ok(())
148 }
149
150 pub async fn stop_litefs(&self, machine_id: &str) -> Result<()> {
151 let mut processes = self.processes.lock().await;
152
153 if let Some(mut process) = processes.remove(machine_id) {
154 process.stop()?;
155 }
156
157 Ok(())
158 }
159
160 pub async fn is_running(&self, machine_id: &str) -> bool {
161 let mut processes = self.processes.lock().await;
162
163 if let Some(process) = processes.get_mut(machine_id) {
164 process.is_running()
165 } else {
166 false
167 }
168 }
169
170 pub async fn stop_all(&self) -> Result<()> {
171 let mut processes = self.processes.lock().await;
172
173 for (machine_id, mut process) in processes.drain() {
174 info!("Stopping LiteFS for machine {}", machine_id);
175 if let Err(e) = process.stop() {
176 error!("Failed to stop LiteFS for machine {}: {}", machine_id, e);
177 }
178 }
179
180 Ok(())
181 }
182}