parent
f99788afa1
commit
61c78c89ee
@ -0,0 +1,47 @@
|
||||
//! Handle deletion
|
||||
//!
|
||||
//! # Handling paths
|
||||
//! Deletion of single files is trivial, deletion of directories is not as trivial.
|
||||
//! Other types of filesystem object are ignored.
|
||||
//!
|
||||
//! ## Directories
|
||||
//! With directories the deletion processes all files containing recursively.
|
||||
//! See `restore` for restoration of directories
|
||||
use super::*;
|
||||
use std::{
|
||||
path::{
|
||||
Path,
|
||||
PathBuf,
|
||||
},
|
||||
};
|
||||
|
||||
/// Process a single file.
|
||||
///
|
||||
/// `path` is known to be a file at this point.
|
||||
async fn process_single(state: Arc<state::State>, path: &Path) -> eyre::Result<()>
|
||||
{
|
||||
let _g = state.lock().await;
|
||||
debug!("{:?} Processing", path);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Process this path
|
||||
///
|
||||
/// This will not return until all its children finish too (if any)
|
||||
pub async fn process(state: Arc<state::State>, path: impl AsRef<Path>) -> eyre::Result<()>
|
||||
{
|
||||
let path = path.as_ref();
|
||||
if path.is_dir() {
|
||||
trace!("{:?} Spawning children", path);
|
||||
//TODO! Walk dir tree
|
||||
todo!()
|
||||
} else if path.is_file() {
|
||||
process_single(state, path).await
|
||||
.wrap_err(eyre!("Processing file failed"))
|
||||
.with_section(|| format!("{:?}", path).header("Path was"))
|
||||
} else {
|
||||
error!("{:?} is not a recognised FS object", path);
|
||||
return Err(eyre!("Unsupported FS object"))
|
||||
.with_section(|| format!("{:?}", path).header("Path was"))
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
//! Handles restoration
|
||||
//!
|
||||
//! # Handling paths
|
||||
//! For single files, restoration is trivial.
|
||||
//!
|
||||
//! ## Directories
|
||||
//! In restoration, directories are restored recursively. All deleted children of a directory path are restored in this operation.
|
||||
//!
|
||||
//! # Process
|
||||
//! When determining if the recursive (directory) stratergy is needed, this happens
|
||||
//! * If the path does not exist in the database as its own atom
|
||||
//! * If there are one or more atoms prefixed with this exact path
|
||||
//!
|
||||
//! Then we use the directory stratergy
|
||||
//! ## Issues
|
||||
//! This can cause issues if a file is deleted and replaced with a directory which is then deleted. The file will be recovered before the directory.
|
||||
//! This is a bug or design flaw. (Maybe we can mitigate this with a flag to prefer the directory stratergy, or check timestamps to determine if the file or the directory was the newest one.)
|
||||
use super::*;
|
@ -0,0 +1,47 @@
|
||||
//! Keeping state
|
||||
use super::*;
|
||||
use tokio::{
|
||||
sync::{
|
||||
Semaphore,
|
||||
SemaphorePermit,
|
||||
},
|
||||
};
|
||||
use futures::{
|
||||
future::OptionFuture,
|
||||
};
|
||||
|
||||
/// Contains state for a set of operations
|
||||
#[derive(Debug)]
|
||||
pub struct State
|
||||
{
|
||||
cfg: config::Config,
|
||||
mtx: Option<Semaphore>,
|
||||
}
|
||||
|
||||
/// Guard for operations inside state
|
||||
#[derive(Debug)]
|
||||
pub struct Permit<'a>(Option<SemaphorePermit<'a>>);
|
||||
|
||||
impl State
|
||||
{
|
||||
/// Create a new state
|
||||
pub fn new(cfg: config::Config) -> Self
|
||||
{
|
||||
Self {
|
||||
mtx: cfg.limit.map(|x| Semaphore::new(x.into())),
|
||||
cfg,
|
||||
}
|
||||
}
|
||||
|
||||
/// Acquire a permit for concurrent work, yielding the task if needed.
|
||||
pub async fn lock(&self) -> Permit<'_>
|
||||
{
|
||||
Permit(OptionFuture::from(self.mtx.as_ref().map(Semaphore::acquire)).await)
|
||||
}
|
||||
|
||||
/// The config object
|
||||
#[inline] pub fn config(&self) -> &config::Config
|
||||
{
|
||||
&self.cfg
|
||||
}
|
||||
}
|
Loading…
Reference in new issue