diff --git a/crates/librqbit/src/session.rs b/crates/librqbit/src/session.rs index 2d38ccf..97f927a 100644 --- a/crates/librqbit/src/session.rs +++ b/crates/librqbit/src/session.rs @@ -16,10 +16,7 @@ use crate::{ peer_connection::PeerConnectionOptions, read_buf::ReadBuf, spawn_utils::BlockingSpawner, - storage::{ - filesystem::{FilesystemStorageFactory, MmapFilesystemStorageFactory}, - BoxStorageFactory, StorageFactoryExt, - }, + storage::{filesystem::FilesystemStorageFactory, BoxStorageFactory, StorageFactoryExt}, torrent_state::{ ManagedTorrentBuilder, ManagedTorrentHandle, ManagedTorrentState, TorrentStateLive, }, @@ -193,7 +190,7 @@ pub struct Session { default_defer_writes: bool, - // default_storage_factory: Option, + default_storage_factory: Option, // This is stored for all tasks to stop when session is dropped. _cancellation_token_drop_guard: DropGuard, @@ -430,7 +427,8 @@ pub struct SessionOptions { // If true, will write to disk in separate threads. The downside is additional allocations. // May be useful if the disk is slow. pub default_defer_writes: bool, - // pub default_storage_factory: Option, + + pub default_storage_factory: Option, } async fn create_tcp_listener( @@ -530,6 +528,7 @@ impl Session { cancellation_token: token, tcp_listen_port, default_defer_writes: opts.default_defer_writes, + default_storage_factory: opts.default_storage_factory, }); if let Some(tcp_listener) = tcp_listener { @@ -1023,9 +1022,8 @@ impl Session { let storage_factory = opts .storage_factory .take() - // .unwrap_or_else(|| self.default_storage_factory.clone()) - // .unwrap_or_else(|| FilesystemStorageFactory::default().boxed()); - .unwrap_or_else(|| MmapFilesystemStorageFactory::default().boxed()); + .or_else(|| self.default_storage_factory.as_ref().map(|f| f.clone_box())) + .unwrap_or_else(|| FilesystemStorageFactory::default().boxed()); if opts.list_only { return Ok(AddTorrentResponse::ListOnly(ListOnlyResponse { diff --git a/crates/librqbit/src/storage/examples/inmemory.rs b/crates/librqbit/src/storage/examples/inmemory.rs index 38a279f..d725995 100644 --- a/crates/librqbit/src/storage/examples/inmemory.rs +++ b/crates/librqbit/src/storage/examples/inmemory.rs @@ -6,7 +6,7 @@ use parking_lot::RwLock; use crate::type_aliases::FileInfos; -use crate::storage::{StorageFactory, TorrentStorage}; +use crate::storage::{StorageFactory, StorageFactoryExt, TorrentStorage}; struct InMemoryPiece { bytes: Box<[u8]>, @@ -19,7 +19,7 @@ impl InMemoryPiece { } } -#[derive(Default)] +#[derive(Default, Clone)] pub struct InMemoryExampleStorageFactory {} impl StorageFactory for InMemoryExampleStorageFactory { @@ -31,6 +31,10 @@ impl StorageFactory for InMemoryExampleStorageFactory { ) -> anyhow::Result { InMemoryExampleStorage::new(info.lengths, info.file_infos.clone()) } + + fn clone_box(&self) -> crate::storage::BoxStorageFactory { + self.clone().boxed() + } } pub struct InMemoryExampleStorage { diff --git a/crates/librqbit/src/storage/examples/mmap.rs b/crates/librqbit/src/storage/examples/mmap.rs index 290cef7..5f40a1c 100644 --- a/crates/librqbit/src/storage/examples/mmap.rs +++ b/crates/librqbit/src/storage/examples/mmap.rs @@ -3,11 +3,11 @@ use memmap2::{MmapMut, MmapOptions}; use parking_lot::RwLock; use crate::{ - storage::{StorageFactory, TorrentStorage}, + storage::{StorageFactory, StorageFactoryExt, TorrentStorage}, FileInfos, ManagedTorrentInfo, }; -#[derive(Default)] +#[derive(Default, Clone)] pub struct MmapStorageFactory {} pub struct MmapStorage { @@ -28,6 +28,10 @@ impl StorageFactory for MmapStorageFactory { file_infos: info.file_infos.clone(), }) } + + fn clone_box(&self) -> crate::storage::BoxStorageFactory { + self.clone().boxed() + } } impl TorrentStorage for MmapStorage { diff --git a/crates/librqbit/src/storage/filesystem/fs.rs b/crates/librqbit/src/storage/filesystem/fs.rs index dd63448..36e57ab 100644 --- a/crates/librqbit/src/storage/filesystem/fs.rs +++ b/crates/librqbit/src/storage/filesystem/fs.rs @@ -6,13 +6,13 @@ use std::{ use anyhow::Context; -use crate::torrent_state::ManagedTorrentInfo; +use crate::{storage::StorageFactoryExt, torrent_state::ManagedTorrentInfo}; use crate::storage::{StorageFactory, TorrentStorage}; use super::opened_file::OpenedFile; -#[derive(Default)] +#[derive(Default, Clone, Copy)] pub struct FilesystemStorageFactory {} impl StorageFactory for FilesystemStorageFactory { @@ -59,6 +59,10 @@ impl StorageFactory for FilesystemStorageFactory { opened_files: files, }) } + + fn clone_box(&self) -> crate::storage::BoxStorageFactory { + self.boxed() + } } pub struct FilesystemStorage { diff --git a/crates/librqbit/src/storage/filesystem/mmap.rs b/crates/librqbit/src/storage/filesystem/mmap.rs index 87dc044..731db70 100644 --- a/crates/librqbit/src/storage/filesystem/mmap.rs +++ b/crates/librqbit/src/storage/filesystem/mmap.rs @@ -6,11 +6,11 @@ use parking_lot::RwLock; use crate::torrent_state::ManagedTorrentInfo; -use crate::storage::{StorageFactory, TorrentStorage}; +use crate::storage::{StorageFactory, StorageFactoryExt, TorrentStorage}; use super::{FilesystemStorage, FilesystemStorageFactory}; -#[derive(Default)] +#[derive(Default, Clone, Copy)] pub struct MmapFilesystemStorageFactory {} type OpenedMmap = RwLock; @@ -36,6 +36,10 @@ impl StorageFactory for MmapFilesystemStorageFactory { fs: fs_storage, }) } + + fn clone_box(&self) -> crate::storage::BoxStorageFactory { + self.boxed() + } } pub struct MmapFilesystemStorage { diff --git a/crates/librqbit/src/storage/middleware/slow.rs b/crates/librqbit/src/storage/middleware/slow.rs index 4e42ba2..d588574 100644 --- a/crates/librqbit/src/storage/middleware/slow.rs +++ b/crates/librqbit/src/storage/middleware/slow.rs @@ -2,8 +2,9 @@ use std::time::Duration; use rand_distr::Distribution; -use crate::storage::{StorageFactory, TorrentStorage}; +use crate::storage::{StorageFactory, StorageFactoryExt, TorrentStorage}; +#[derive(Clone)] pub struct SlowStorageFactory { underlying_factory: U, } @@ -16,7 +17,7 @@ impl SlowStorageFactory { } } -impl StorageFactory for SlowStorageFactory { +impl StorageFactory for SlowStorageFactory { type Storage = SlowStorage; fn init_storage(&self, info: &crate::ManagedTorrentInfo) -> anyhow::Result { @@ -28,6 +29,10 @@ impl StorageFactory for SlowStorageFactory { fn is_type_id(&self, type_id: std::any::TypeId) -> bool { self.underlying_factory.is_type_id(type_id) } + + fn clone_box(&self) -> crate::storage::BoxStorageFactory { + self.clone().boxed() + } } pub struct SlowStorage { diff --git a/crates/librqbit/src/storage/middleware/timing.rs b/crates/librqbit/src/storage/middleware/timing.rs index 9d3210b..9012384 100644 --- a/crates/librqbit/src/storage/middleware/timing.rs +++ b/crates/librqbit/src/storage/middleware/timing.rs @@ -1,5 +1,6 @@ -use crate::storage::{StorageFactory, TorrentStorage}; +use crate::storage::{StorageFactory, StorageFactoryExt, TorrentStorage}; +#[derive(Clone)] pub struct TimingStorageFactory { name: String, underlying_factory: U, @@ -14,7 +15,7 @@ impl TimingStorageFactory { } } -impl StorageFactory for TimingStorageFactory { +impl StorageFactory for TimingStorageFactory { type Storage = TimingStorage; fn init_storage(&self, info: &crate::ManagedTorrentInfo) -> anyhow::Result { @@ -27,6 +28,10 @@ impl StorageFactory for TimingStorageFactory { fn is_type_id(&self, type_id: std::any::TypeId) -> bool { self.underlying_factory.is_type_id(type_id) } + + fn clone_box(&self) -> crate::storage::BoxStorageFactory { + self.clone().boxed() + } } pub struct TimingStorage { diff --git a/crates/librqbit/src/storage/mod.rs b/crates/librqbit/src/storage/mod.rs index 063d280..33c89f3 100644 --- a/crates/librqbit/src/storage/mod.rs +++ b/crates/librqbit/src/storage/mod.rs @@ -16,6 +16,7 @@ pub trait StorageFactory: Send + Sync + Any { fn is_type_id(&self, type_id: TypeId) -> bool { Self::type_id(self) == type_id } + fn clone_box(&self) -> BoxStorageFactory; } pub type BoxStorageFactory = Box>>; @@ -41,6 +42,10 @@ impl StorageFactoryExt for SF { fn is_type_id(&self, type_id: TypeId) -> bool { self.sf.type_id() == type_id } + + fn clone_box(&self) -> BoxStorageFactory { + self.sf.clone_box() + } } Box::new(Wrapper { sf: self }) @@ -53,6 +58,10 @@ impl StorageFactory for Box { fn init_storage(&self, info: &ManagedTorrentInfo) -> anyhow::Result { (**self).init_storage(info) } + + fn clone_box(&self) -> BoxStorageFactory { + (**self).clone_box() + } } pub trait TorrentStorage: Send + Sync { diff --git a/crates/librqbit/src/tests/e2e.rs b/crates/librqbit/src/tests/e2e.rs index 86f615b..d994a78 100644 --- a/crates/librqbit/src/tests/e2e.rs +++ b/crates/librqbit/src/tests/e2e.rs @@ -73,6 +73,7 @@ async fn test_e2e() { listen_port_range: Some(15100..17000), enable_upnp_port_forwarding: false, default_defer_writes: false, + default_storage_factory: None, }, ) .await diff --git a/crates/rqbit/src/main.rs b/crates/rqbit/src/main.rs index 28471ff..ce1719a 100644 --- a/crates/rqbit/src/main.rs +++ b/crates/rqbit/src/main.rs @@ -297,6 +297,13 @@ async fn async_main(opts: Opts) -> anyhow::Result<()> { }, enable_upnp_port_forwarding: !opts.disable_upnp, default_defer_writes: opts.defer_writes, + default_storage_factory: Some({ + if opts.experimental_mmap_storage { + MmapFilesystemStorageFactory::default().boxed() + } else { + FilesystemStorageFactory::default().boxed() + } + }), }; let stats_printer = |session: Arc| async move {