diff --git a/mediarepo-daemon/mediarepo-database/src/entities/hash.rs b/mediarepo-daemon/mediarepo-database/src/entities/hash.rs index f091d87..57292e2 100644 --- a/mediarepo-daemon/mediarepo-database/src/entities/hash.rs +++ b/mediarepo-daemon/mediarepo-database/src/entities/hash.rs @@ -5,11 +5,16 @@ use sea_orm::prelude::*; pub struct Model { #[sea_orm(primary_key)] pub id: u64, - pub value: String + pub value: String, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { +pub enum Relation {} + +impl Related for Entity { + fn to() -> RelationDef { + super::file::Relation::Hash.def().rev() + } } impl Related for Entity { @@ -32,4 +37,4 @@ impl Related for Entity { } } -impl ActiveModelBehavior for ActiveModel {} \ No newline at end of file +impl ActiveModelBehavior for ActiveModel {} diff --git a/mediarepo-daemon/mediarepo-model/src/models/file.rs b/mediarepo-daemon/mediarepo-model/src/models/file.rs index 9fbc572..aef89b3 100644 --- a/mediarepo-daemon/mediarepo-model/src/models/file.rs +++ b/mediarepo-daemon/mediarepo-model/src/models/file.rs @@ -9,6 +9,7 @@ use mediarepo_database::entities::hash; use mediarepo_database::entities::hash::Model as HashModel; use sea_orm::prelude::*; use sea_orm::{DatabaseConnection, Set}; +use tokio::io::BufReader; pub struct File { db: DatabaseConnection, @@ -35,6 +36,24 @@ impl File { } } + /// Finds the file by hash + pub async fn by_hash>( + db: DatabaseConnection, + hash: S, + ) -> RepoResult> { + if let Some((hash, Some(model))) = hash::Entity::find() + .filter(hash::Column::Value.eq(hash.as_ref())) + .find_also_related(file::Entity) + .one(&db) + .await? + { + let file = File::new(db, model, hash); + Ok(Some(file)) + } else { + Ok(None) + } + } + /// Returns the unique identifier of the file pub fn id(&self) -> u64 { self.model.id @@ -119,6 +138,13 @@ impl File { Ok(()) } + /// Returns the reader for the file + pub async fn get_reader(&self) -> RepoResult> { + let storage = self.storage().await?; + + storage.get_file_reader(&self.hash.value).await + } + /// Returns the active model of the file with only the id set fn get_active_model(&self) -> ActiveFile { ActiveFile { diff --git a/mediarepo-daemon/mediarepo-model/src/models/storage.rs b/mediarepo-daemon/mediarepo-model/src/models/storage.rs index b304aa5..d4ee185 100644 --- a/mediarepo-daemon/mediarepo-model/src/models/storage.rs +++ b/mediarepo-daemon/mediarepo-model/src/models/storage.rs @@ -1,4 +1,5 @@ use mediarepo_core::error::RepoResult; +use mediarepo_core::file_hash_store::FileHashStore; use mediarepo_database::entities::storage; use mediarepo_database::entities::storage::ActiveModel as ActiveStorage; use mediarepo_database::entities::storage::Model as StorageModel; @@ -6,15 +7,22 @@ use sea_orm::prelude::*; use sea_orm::{DatabaseConnection, Set, Unset}; use std::path::PathBuf; use tokio::fs; +use tokio::io::{AsyncRead, BufReader}; pub struct Storage { db: DatabaseConnection, model: StorageModel, + store: FileHashStore, } impl Storage { fn new(db: DatabaseConnection, model: StorageModel) -> Self { - Self { db, model } + let path = PathBuf::from(&model.path); + Self { + store: FileHashStore::new(path), + db, + model, + } } /// Returns the storage by id @@ -27,6 +35,7 @@ impl Storage { } } + /// Returns the storage by path pub async fn by_path(db: DatabaseConnection, path: S) -> RepoResult> { if let Some(model) = storage::Entity::find() .filter(storage::Column::Path.eq(path.to_string())) @@ -110,6 +119,21 @@ impl Storage { path.exists() } + /// Adds a file to the store + pub async fn add_file(&self, reader: R) -> RepoResult { + self.store.add_file(reader, None).await + } + + /// Returns the buf reader to the given hash + pub async fn get_file_reader( + &self, + hash: S, + ) -> RepoResult> { + let (_ext, reader) = self.store.get_file(hash.to_string()).await?; + + Ok(reader) + } + /// Returns the active model with only the ID filled so saves always perform an update fn get_active_model(&self) -> ActiveStorage { ActiveStorage {