From 7031023a315a3c43cfcf5e24b4adf095f34ab60f Mon Sep 17 00:00:00 2001 From: Igor Katson Date: Thu, 2 May 2024 19:00:30 +0100 Subject: [PATCH] Move filesystem storage into a different folder --- crates/librqbit/src/storage/filesystem/fs.rs | 110 +++++++++++++++++ crates/librqbit/src/storage/filesystem/mod.rs | 112 +----------------- 2 files changed, 112 insertions(+), 110 deletions(-) create mode 100644 crates/librqbit/src/storage/filesystem/fs.rs diff --git a/crates/librqbit/src/storage/filesystem/fs.rs b/crates/librqbit/src/storage/filesystem/fs.rs new file mode 100644 index 0000000..ae99843 --- /dev/null +++ b/crates/librqbit/src/storage/filesystem/fs.rs @@ -0,0 +1,110 @@ +use std::{ + fs::OpenOptions, + io::{Read, Seek, SeekFrom, Write}, + path::{Path, PathBuf}, +}; + +use anyhow::Context; + +use crate::torrent_state::ManagedTorrentInfo; + +use crate::storage::{StorageFactory, TorrentStorage}; + +use super::opened_file::OpenedFile; + +#[derive(Default)] +pub struct FilesystemStorageFactory {} + +impl StorageFactory for FilesystemStorageFactory { + type Storage = FilesystemStorage; + + fn init_storage(&self, meta: &ManagedTorrentInfo) -> anyhow::Result { + let mut files = Vec::::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)); + } + Ok(FilesystemStorage { + output_folder: output_folder.clone(), + opened_files: files, + }) + } +} + +pub struct FilesystemStorage { + output_folder: PathBuf, + opened_files: Vec, +} + +impl TorrentStorage for FilesystemStorage { + fn pread_exact(&self, file_id: usize, offset: u64, buf: &mut [u8]) -> anyhow::Result<()> { + let mut g = self + .opened_files + .get(file_id) + .context("no such file")? + .file + .lock(); + g.seek(SeekFrom::Start(offset))?; + Ok(g.read_exact(buf)?) + } + + fn pwrite_all(&self, file_id: usize, offset: u64, buf: &[u8]) -> anyhow::Result<()> { + let mut g = self + .opened_files + .get(file_id) + .context("no such file")? + .file + .lock(); + g.seek(SeekFrom::Start(offset))?; + Ok(g.write_all(buf)?) + } + + fn remove_file(&self, _file_id: usize, filename: &Path) -> anyhow::Result<()> { + Ok(std::fs::remove_file(self.output_folder.join(filename))?) + } + + fn ensure_file_length(&self, file_id: usize, len: u64) -> anyhow::Result<()> { + Ok(self.opened_files[file_id].file.lock().set_len(len)?) + } + + fn take(&self) -> anyhow::Result> { + Ok(Box::new(Self { + opened_files: self + .opened_files + .iter() + .map(|f| f.take_clone()) + .collect::>>()?, + output_folder: self.output_folder.clone(), + })) + } +} diff --git a/crates/librqbit/src/storage/filesystem/mod.rs b/crates/librqbit/src/storage/filesystem/mod.rs index 3ce2315..eb634b5 100644 --- a/crates/librqbit/src/storage/filesystem/mod.rs +++ b/crates/librqbit/src/storage/filesystem/mod.rs @@ -1,112 +1,4 @@ +mod fs; mod opened_file; -use std::{ - fs::OpenOptions, - io::{Read, Seek, SeekFrom, Write}, - path::{Path, PathBuf}, -}; - -use anyhow::Context; - -use crate::torrent_state::ManagedTorrentInfo; - -use self::opened_file::OpenedFile; - -use super::{StorageFactory, TorrentStorage}; - -#[derive(Default)] -pub struct FilesystemStorageFactory {} - -impl StorageFactory for FilesystemStorageFactory { - type Storage = FilesystemStorage; - - fn init_storage(&self, meta: &ManagedTorrentInfo) -> anyhow::Result { - let mut files = Vec::::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)); - } - Ok(FilesystemStorage { - output_folder: output_folder.clone(), - opened_files: files, - }) - } -} - -pub struct FilesystemStorage { - output_folder: PathBuf, - opened_files: Vec, -} - -impl TorrentStorage for FilesystemStorage { - fn pread_exact(&self, file_id: usize, offset: u64, buf: &mut [u8]) -> anyhow::Result<()> { - let mut g = self - .opened_files - .get(file_id) - .context("no such file")? - .file - .lock(); - g.seek(SeekFrom::Start(offset))?; - Ok(g.read_exact(buf)?) - } - - fn pwrite_all(&self, file_id: usize, offset: u64, buf: &[u8]) -> anyhow::Result<()> { - let mut g = self - .opened_files - .get(file_id) - .context("no such file")? - .file - .lock(); - g.seek(SeekFrom::Start(offset))?; - Ok(g.write_all(buf)?) - } - - fn remove_file(&self, _file_id: usize, filename: &Path) -> anyhow::Result<()> { - Ok(std::fs::remove_file(self.output_folder.join(filename))?) - } - - fn ensure_file_length(&self, file_id: usize, len: u64) -> anyhow::Result<()> { - Ok(self.opened_files[file_id].file.lock().set_len(len)?) - } - - fn take(&self) -> anyhow::Result> { - Ok(Box::new(Self { - opened_files: self - .opened_files - .iter() - .map(|f| f.take_clone()) - .collect::>>()?, - output_folder: self.output_folder.clone(), - })) - } -} +pub use fs::{FilesystemStorage, FilesystemStorageFactory};