From 2ec351f20e3ea1e23c186550687e304f46d0f46c Mon Sep 17 00:00:00 2001 From: DecDuck Date: Fri, 25 Oct 2024 10:28:58 +1100 Subject: [PATCH] fixed multi-chunk downloads --- src-tauri/Cargo.lock | 1 + src-tauri/Cargo.toml | 1 + src-tauri/src/downloads/download_logic.rs | 14 ++++++++------ src-tauri/src/downloads/download_manager.rs | 13 +++++++++---- src-tauri/src/downloads/manifest.rs | 3 ++- 5 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 622e924..8e498ad 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1028,6 +1028,7 @@ dependencies = [ "rayon", "reqwest", "rustbreak", + "rustix", "serde", "serde_json", "structured-logger", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index edbcbbb..21ada3f 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -40,6 +40,7 @@ http = "1.1.0" tokio = { version = "1.40.0", features = ["rt", "tokio-macros"] } versions = { version = "6.3.2", features = ["serde"] } urlencoding = "2.1.3" +rustix = "0.38.37" [dependencies.uuid] version = "1.10.0" diff --git a/src-tauri/src/downloads/download_logic.rs b/src-tauri/src/downloads/download_logic.rs index fa64f1c..cf999bf 100644 --- a/src-tauri/src/downloads/download_logic.rs +++ b/src-tauri/src/downloads/download_logic.rs @@ -3,8 +3,8 @@ use crate::db::DatabaseImpls; use crate::downloads::manifest::DropDownloadContext; use crate::DB; use log::info; +use std::{fs::OpenOptions, io::{BufWriter, Seek, SeekFrom, Write}}; use urlencoding::encode; -use std::io::{BufWriter, Seek, SeekFrom, Write}; pub fn download_game_chunk(ctx: DropDownloadContext) { let base_url = DB.fetch_base_url(); @@ -14,7 +14,10 @@ pub fn download_game_chunk(ctx: DropDownloadContext) { .join(&format!( "/api/v1/client/chunk?id={}&version={}&name={}&chunk={}", // Encode the parts we don't trust - ctx.game_id, encode(&ctx.version), encode(&ctx.file_name), ctx.index + ctx.game_id, + encode(&ctx.version), + encode(&ctx.file_name), + ctx.index )) .unwrap(); @@ -26,16 +29,15 @@ pub fn download_game_chunk(ctx: DropDownloadContext) { .send() .unwrap(); - let mut file_lock = ctx.file.lock().unwrap(); + let mut file = OpenOptions::new().write(true).open(ctx.path).unwrap(); if ctx.offset != 0 { - file_lock + file .seek(SeekFrom::Start(ctx.offset)) .expect("Failed to seek to file offset"); } - let mut stream = BufWriter::with_capacity(1024 * 1024, file_lock.try_clone().unwrap()); - drop(file_lock); + let mut stream = BufWriter::with_capacity(1024 * 1024, file); response.copy_to(&mut stream).unwrap(); } diff --git a/src-tauri/src/downloads/download_manager.rs b/src-tauri/src/downloads/download_manager.rs index 50af71d..0d0662a 100644 --- a/src-tauri/src/downloads/download_manager.rs +++ b/src-tauri/src/downloads/download_manager.rs @@ -5,6 +5,7 @@ use crate::downloads::manifest::{DropDownloadContext, DropManifest}; use crate::downloads::progress::ProgressChecker; use crate::{AppState, DB}; use log::info; +use rustix::fs::{fallocate, FallocateFlags}; use serde::{Deserialize, Serialize}; use std::fs::{create_dir_all, File}; use std::path::Path; @@ -64,7 +65,7 @@ impl GameDownloadManager { } self.ensure_manifest_exists().await } - + pub fn begin_download( &self, max_threads: usize, @@ -143,7 +144,7 @@ pub fn generate_job_contexts( let container = path.parent().unwrap(); create_dir_all(container).unwrap(); - let file = Arc::new(Mutex::new(File::create(path).unwrap())); + let file = File::create(path.clone()).unwrap(); let mut running_offset = 0; for i in 0..chunk.ids.len() { @@ -153,10 +154,12 @@ pub fn generate_job_contexts( offset: running_offset, index: i, game_id: game_id.to_string(), - file: file.clone(), + path: path.clone(), }); running_offset += chunk.lengths[i] as u64; } + + fallocate(file, FallocateFlags::empty(), 0, running_offset); } contexts } @@ -184,7 +187,9 @@ pub async fn start_game_download( let contexts = generate_job_contexts(&local_manifest, game_version.clone(), game_id); - let _ = download_manager.begin_download(max_threads, contexts); + download_manager + .begin_download(max_threads, contexts) + .unwrap(); Ok(()) } diff --git a/src-tauri/src/downloads/manifest.rs b/src-tauri/src/downloads/manifest.rs index 7feb45c..f03a706 100644 --- a/src-tauri/src/downloads/manifest.rs +++ b/src-tauri/src/downloads/manifest.rs @@ -1,5 +1,6 @@ use std::collections::HashMap; use std::fs::File; +use std::path::PathBuf; use std::sync::{Arc, Mutex}; use serde::{Deserialize, Serialize}; @@ -19,5 +20,5 @@ pub struct DropDownloadContext { pub index: usize, pub offset: u64, pub game_id: String, - pub file: Arc> + pub path: PathBuf } \ No newline at end of file