Folders and files are now deleted more comprehensively
This commit is contained in:
parent
7147f16042
commit
ace4bed0c6
13 changed files with 253 additions and 103 deletions
|
|
@ -4,6 +4,7 @@ use std::{
|
|||
};
|
||||
|
||||
use anyhow::Context;
|
||||
use tracing::warn;
|
||||
|
||||
use crate::{storage::StorageFactoryExt, torrent_state::ManagedTorrentInfo};
|
||||
|
||||
|
|
@ -17,45 +18,10 @@ pub struct FilesystemStorageFactory {}
|
|||
impl StorageFactory for FilesystemStorageFactory {
|
||||
type Storage = FilesystemStorage;
|
||||
|
||||
fn init_storage(&self, meta: &ManagedTorrentInfo) -> anyhow::Result<FilesystemStorage> {
|
||||
let mut files = Vec::<OpenedFile>::new();
|
||||
let output_folder = &meta.options.output_folder;
|
||||
for file_details in meta.info.iter_file_details(&meta.lengths)? {
|
||||
let mut full_path = output_folder.clone();
|
||||
let relative_path = file_details
|
||||
.filename
|
||||
.to_pathbuf()
|
||||
.context("error converting file to path")?;
|
||||
full_path.push(relative_path);
|
||||
|
||||
std::fs::create_dir_all(full_path.parent().context("bug: no parent")?)?;
|
||||
let file = if meta.options.allow_overwrite {
|
||||
OpenOptions::new()
|
||||
.create(true)
|
||||
.truncate(false)
|
||||
.read(true)
|
||||
.write(true)
|
||||
.open(&full_path)
|
||||
.with_context(|| format!("error opening {full_path:?} in read/write mode"))?
|
||||
} else {
|
||||
// create_new does not seem to work with read(true), so calling this twice.
|
||||
OpenOptions::new()
|
||||
.create_new(true)
|
||||
.write(true)
|
||||
.open(&full_path)
|
||||
.with_context(|| {
|
||||
format!(
|
||||
"error creating a new file (because allow_overwrite = false) {:?}",
|
||||
&full_path
|
||||
)
|
||||
})?;
|
||||
OpenOptions::new().read(true).write(true).open(&full_path)?
|
||||
};
|
||||
files.push(OpenedFile::new(file));
|
||||
}
|
||||
fn create(&self, meta: &ManagedTorrentInfo) -> anyhow::Result<FilesystemStorage> {
|
||||
Ok(FilesystemStorage {
|
||||
output_folder: output_folder.clone(),
|
||||
opened_files: files,
|
||||
output_folder: meta.options.output_folder.clone(),
|
||||
opened_files: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -142,4 +108,57 @@ impl TorrentStorage for FilesystemStorage {
|
|||
output_folder: self.output_folder.clone(),
|
||||
}))
|
||||
}
|
||||
|
||||
fn remove_directory_if_empty(&self, path: &Path) -> anyhow::Result<()> {
|
||||
let path = self.output_folder.join(path);
|
||||
if !path.is_dir() {
|
||||
anyhow::bail!("cannot remove dir: {path:?} is not a directory")
|
||||
}
|
||||
if std::fs::read_dir(&path)?.count() == 0 {
|
||||
std::fs::remove_dir(&path).with_context(|| format!("error removing {path:?}"))
|
||||
} else {
|
||||
warn!("did not remove {path:?} as it was not empty");
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn init(&mut self, meta: &ManagedTorrentInfo) -> anyhow::Result<()> {
|
||||
let mut files = Vec::<OpenedFile>::new();
|
||||
for file_details in meta.info.iter_file_details(&meta.lengths)? {
|
||||
let mut full_path = self.output_folder.clone();
|
||||
let relative_path = file_details
|
||||
.filename
|
||||
.to_pathbuf()
|
||||
.context("error converting file to path")?;
|
||||
full_path.push(relative_path);
|
||||
|
||||
std::fs::create_dir_all(full_path.parent().context("bug: no parent")?)?;
|
||||
let file = if meta.options.allow_overwrite {
|
||||
OpenOptions::new()
|
||||
.create(true)
|
||||
.truncate(false)
|
||||
.read(true)
|
||||
.write(true)
|
||||
.open(&full_path)
|
||||
.with_context(|| format!("error opening {full_path:?} in read/write mode"))?
|
||||
} else {
|
||||
// create_new does not seem to work with read(true), so calling this twice.
|
||||
OpenOptions::new()
|
||||
.create_new(true)
|
||||
.write(true)
|
||||
.open(&full_path)
|
||||
.with_context(|| {
|
||||
format!(
|
||||
"error creating a new file (because allow_overwrite = false) {:?}",
|
||||
&full_path
|
||||
)
|
||||
})?;
|
||||
OpenOptions::new().read(true).write(true).open(&full_path)?
|
||||
};
|
||||
files.push(OpenedFile::new(file));
|
||||
}
|
||||
|
||||
self.opened_files = files;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,19 +22,11 @@ fn dummy_mmap() -> anyhow::Result<MmapMut> {
|
|||
impl StorageFactory for MmapFilesystemStorageFactory {
|
||||
type Storage = MmapFilesystemStorage;
|
||||
|
||||
fn init_storage(&self, meta: &ManagedTorrentInfo) -> anyhow::Result<Self::Storage> {
|
||||
let fs_storage = FilesystemStorageFactory::default().init_storage(meta)?;
|
||||
let mut mmaps = Vec::new();
|
||||
for (idx, file) in fs_storage.opened_files.iter().enumerate() {
|
||||
let fg = file.file.write();
|
||||
fg.set_len(meta.file_infos[idx].len)
|
||||
.context("mmap storage: error setting length")?;
|
||||
let mmap = unsafe { MmapOptions::new().map_mut(&*fg) }.context("error mapping file")?;
|
||||
mmaps.push(RwLock::new(mmap));
|
||||
}
|
||||
fn create(&self, meta: &ManagedTorrentInfo) -> anyhow::Result<Self::Storage> {
|
||||
let fs_storage = FilesystemStorageFactory::default().create(meta)?;
|
||||
|
||||
Ok(MmapFilesystemStorage {
|
||||
opened_mmaps: mmaps,
|
||||
opened_mmaps: Vec::new(),
|
||||
fs: fs_storage,
|
||||
})
|
||||
}
|
||||
|
|
@ -82,6 +74,10 @@ impl TorrentStorage for MmapFilesystemStorage {
|
|||
self.fs.remove_file(file_id, filename)
|
||||
}
|
||||
|
||||
fn remove_directory_if_empty(&self, path: &Path) -> anyhow::Result<()> {
|
||||
self.fs.remove_directory_if_empty(path)
|
||||
}
|
||||
|
||||
fn ensure_file_length(&self, file_id: usize, len: u64) -> anyhow::Result<()> {
|
||||
self.fs.ensure_file_length(file_id, len)
|
||||
}
|
||||
|
|
@ -100,4 +96,19 @@ impl TorrentStorage for MmapFilesystemStorage {
|
|||
fs: self.fs.take_fs()?,
|
||||
}))
|
||||
}
|
||||
|
||||
fn init(&mut self, meta: &ManagedTorrentInfo) -> anyhow::Result<()> {
|
||||
self.fs.init(meta)?;
|
||||
let mut mmaps = Vec::new();
|
||||
for (idx, file) in self.fs.opened_files.iter().enumerate() {
|
||||
let fg = file.file.write();
|
||||
fg.set_len(meta.file_infos[idx].len)
|
||||
.context("mmap storage: error setting length")?;
|
||||
let mmap = unsafe { MmapOptions::new().map_mut(&*fg) }.context("error mapping file")?;
|
||||
mmaps.push(RwLock::new(mmap));
|
||||
}
|
||||
|
||||
self.opened_mmaps = mmaps;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue