diff --git a/desktop/src-tauri/src/downloads/download_commands.rs b/desktop/src-tauri/src/downloads/download_commands.rs index 4f385144..a4f0f014 100644 --- a/desktop/src-tauri/src/downloads/download_commands.rs +++ b/desktop/src-tauri/src/downloads/download_commands.rs @@ -1,4 +1,4 @@ -use std::sync::{Arc, Mutex}; +use std::sync::{atomic::Ordering, Arc, Mutex}; use log::info; @@ -73,4 +73,17 @@ pub async fn start_game_download( download_agent.begin_download(max_threads).await?; Ok(()) +} + +#[tauri::command] +pub async fn stop_specific_game_download(state: tauri::State<'_, Mutex>, game_id: String) -> Result<(), String> { + let lock = state.lock().unwrap(); + let download_agent = lock.game_downloads.get(&game_id).unwrap(); + + let callback = download_agent.callback.clone(); + drop(lock); + + callback.store(true, Ordering::Release); + + return Ok(()) } \ No newline at end of file diff --git a/desktop/src-tauri/src/downloads/download_logic.rs b/desktop/src-tauri/src/downloads/download_logic.rs index 7d3848b0..8825c684 100644 --- a/desktop/src-tauri/src/downloads/download_logic.rs +++ b/desktop/src-tauri/src/downloads/download_logic.rs @@ -5,7 +5,7 @@ use crate::DB; use gxhash::{gxhash128, GxHasher}; use log::info; use md5::{Context, Digest}; -use std::{fs::{File, OpenOptions}, hash::Hasher, io::{self, Seek, SeekFrom, Write}, path::PathBuf, sync::{atomic::{AtomicBool, Ordering}, Arc}}; +use std::{fs::{File, OpenOptions}, hash::Hasher, io::{self, BufWriter, Error, ErrorKind, Seek, SeekFrom, Write}, path::PathBuf, sync::{atomic::{AtomicBool, Ordering}, Arc}}; use urlencoding::encode; pub struct DropFileWriter { @@ -26,10 +26,11 @@ impl DropFileWriter { Ok(self.hasher.compute()) } } +// TODO: Implement error handling impl Write for DropFileWriter { fn write(&mut self, buf: &[u8]) -> std::io::Result { if self.callback.load(Ordering::Acquire) { - + return Err(Error::new(ErrorKind::Interrupted, "Interrupt command recieved")); } self.hasher.write_all(buf).unwrap(); self.file.write(buf) @@ -71,7 +72,7 @@ pub fn download_game_chunk(ctx: DropDownloadContext, callback: Arc) .send() .unwrap(); - let mut file: DropFileWriter = DropFileWriter::new(ctx.path); + let mut file: DropFileWriter = DropFileWriter::new(ctx.path, callback); if ctx.offset != 0 { file @@ -79,12 +80,19 @@ pub fn download_game_chunk(ctx: DropDownloadContext, callback: Arc) .expect("Failed to seek to file offset"); } - // let mut stream = BufWriter::with_capacity(1024, file); + // Writing everything to disk directly is probably slightly faster because it balances out the writes, + // but this is better than the performance loss from constantly reading the callbacks - // Writing directly to disk to avoid write spikes that delay everything + let mut writer = BufWriter::with_capacity(1024 * 1024, file); - - response.copy_to(&mut file).unwrap(); + match response.copy_to(&mut writer) { + Ok(_) => {}, + Err(_) => { println!("Stopped printing chunk {}", ctx.file_name); return; } + }; + let file = match writer.into_inner() { + Ok(inner) => inner, + Err(_) => panic!("Failed to get BufWriter inner"), + }; let res = hex::encode(file.finish().unwrap().0); if res != ctx.checksum { info!("Checksum failed. Original: {}, Calculated: {} for {}", ctx.checksum, res, ctx.file_name); diff --git a/desktop/src-tauri/src/lib.rs b/desktop/src-tauri/src/lib.rs index da0413be..d9d78b69 100644 --- a/desktop/src-tauri/src/lib.rs +++ b/desktop/src-tauri/src/lib.rs @@ -4,13 +4,12 @@ mod library; mod remote; mod unpacker; mod downloads; -mod utils; #[cfg(test)] mod tests; use auth::{auth_initiate, generate_authorization_header, recieve_handshake}; use db::{DatabaseInterface, DATA_ROOT_DIR}; -use downloads::download_commands::{queue_game_download, start_game_downloads}; +use downloads::download_commands::{queue_game_download, start_game_downloads, stop_specific_game_download}; use env_logger::Env; use http::{header::*, response::Builder as ResponseBuilder}; use library::{fetch_game, fetch_library, Game}; @@ -115,7 +114,8 @@ pub fn run() { fetch_game, // Downloads queue_game_download, - start_game_downloads + start_game_downloads, + stop_specific_game_download ]) .plugin(tauri_plugin_shell::init()) .setup(|app| { diff --git a/desktop/src-tauri/src/tests/progress_tests.rs b/desktop/src-tauri/src/tests/progress_tests.rs index 9c41b15d..dea2c1fe 100644 --- a/desktop/src-tauri/src/tests/progress_tests.rs +++ b/desktop/src-tauri/src/tests/progress_tests.rs @@ -18,6 +18,6 @@ fn test_progress_parallel() { p.run_contexts_parallel_background((1..100).collect(), 10); } -fn test_fn(int: usize) { +fn test_fn(int: usize, callback: Arc) { println!("{}", int); } \ No newline at end of file