#[cfg(feature = "async")]
use tokio::task;
use crate::{Fdinfo, LsofData, Result};
use std::collections::HashMap;
use std::path::Path;
use std::sync::{Arc, Mutex};
#[cfg(feature = "async")]
pub struct LsofAsync {
inner: Arc<Mutex<LsofData>>,
}
#[cfg(feature = "async")]
impl LsofAsync {
pub fn new() -> Self {
Self {
inner: Arc::new(Mutex::new(LsofData::new())),
}
}
pub async fn file_ls(&self) -> Result<HashMap<String, Fdinfo>> {
let inner = self.inner.clone();
task::spawn_blocking(move || {
let mut data = inner.lock().map_err(|_|
crate::Error::Other("Failed to acquire lock".to_string())
)?;
let result = data.file_ls().ok_or_else(||
crate::Error::Other("Failed to list all files".to_string())
)?;
Ok(result.clone())
}).await.map_err(|_| crate::Error::Other("Task join error".to_string()))?
}
pub async fn target_file_ls(&self, path: impl AsRef<Path> + Send + 'static) -> Result<Vec<Fdinfo>> {
let path_str = path.as_ref().to_string_lossy().to_string();
let inner = self.inner.clone();
task::spawn_blocking(move || {
let mut data = inner.lock().map_err(|_|
crate::Error::Other("Failed to acquire lock".to_string())
)?;
data.target_file_ls(path_str).ok_or_else(||
crate::Error::Other(format!("Failed to list file: {}", path.as_ref().display()))
)
}).await.map_err(|_| crate::Error::Other("Task join error".to_string()))?
}
pub async fn port_ls(&self, port: impl AsRef<str> + Send + 'static) -> Result<Vec<Fdinfo>> {
let port_str = port.as_ref().to_string();
let inner = self.inner.clone();
task::spawn_blocking(move || {
let mut data = inner.lock().map_err(|_|
crate::Error::Other("Failed to acquire lock".to_string())
)?;
data.port_ls(port_str).ok_or_else(||
crate::Error::Other(format!("Failed to list port: {}", port.as_ref()))
)
}).await.map_err(|_| crate::Error::Other("Task join error".to_string()))?
}
}
#[cfg(feature = "async")]
impl Default for LsofAsync {
fn default() -> Self {
Self::new()
}
}
#[cfg(all(test, feature = "async"))]
mod tests {
use super::*;
#[tokio::test]
async fn test_async_file_ls() {
let lsof = LsofAsync::new();
let result = lsof.file_ls().await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_async_target_file() {
let lsof = LsofAsync::new();
let result = lsof.target_file_ls("/etc/passwd").await;
if let Ok(processes) = &result {
println!("Found {} processes using /etc/passwd", processes.len());
}
}
#[tokio::test]
async fn test_async_port() {
let lsof = LsofAsync::new();
let result = lsof.port_ls("80").await;
if let Ok(processes) = &result {
println!("Found {} processes using port 80", processes.len());
}
}
}