mirror of
https://github.com/Drop-OSS/drop-app.git
synced 2025-11-10 04:22:13 +10:00
Fix for redownload invalid chunks (#84)
* feat: Redownloading invalid chunks Signed-off-by: quexeky <git@quexeky.dev> * fix: clippy * fix: clippy x2 --------- Signed-off-by: quexeky <git@quexeky.dev> Co-authored-by: quexeky <git@quexeky.dev>
This commit is contained in:
Submodule drop-base updated: 26698e5b06...04125e89be
@ -242,43 +242,47 @@ impl DownloadManagerBuilder {
|
||||
let app_handle = self.app_handle.clone();
|
||||
|
||||
*download_thread_lock = Some(spawn(move || {
|
||||
match download_agent.download(&app_handle) {
|
||||
// Ok(true) is for completed and exited properly
|
||||
Ok(true) => {
|
||||
debug!("download {:?} has completed", download_agent.metadata());
|
||||
match download_agent.validate() {
|
||||
Ok(true) => {
|
||||
download_agent.on_complete(&app_handle);
|
||||
sender
|
||||
.send(DownloadManagerSignal::Completed(download_agent.metadata()))
|
||||
.unwrap();
|
||||
}
|
||||
Ok(false) => {
|
||||
download_agent.on_incomplete(&app_handle);
|
||||
}
|
||||
Err(e) => {
|
||||
error!(
|
||||
"download {:?} has validation error {}",
|
||||
download_agent.metadata(),
|
||||
&e
|
||||
);
|
||||
download_agent.on_error(&app_handle, &e);
|
||||
sender.send(DownloadManagerSignal::Error(e)).unwrap();
|
||||
}
|
||||
loop {
|
||||
let download_result = match download_agent.download(&app_handle) {
|
||||
// Ok(true) is for completed and exited properly
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
error!("download {:?} has error {}", download_agent.metadata(), &e);
|
||||
download_agent.on_error(&app_handle, &e);
|
||||
sender.send(DownloadManagerSignal::Error(e)).unwrap();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Ok(false) is for incomplete but exited properly
|
||||
Ok(false) => {
|
||||
debug!("Donwload agent finished incomplete");
|
||||
};
|
||||
|
||||
// If the download gets cancel
|
||||
if !download_result {
|
||||
download_agent.on_incomplete(&app_handle);
|
||||
return;
|
||||
}
|
||||
Err(e) => {
|
||||
error!("download {:?} has error {}", download_agent.metadata(), &e);
|
||||
download_agent.on_error(&app_handle, &e);
|
||||
sender.send(DownloadManagerSignal::Error(e)).unwrap();
|
||||
|
||||
let validate_result = match download_agent.validate() {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
error!(
|
||||
"download {:?} has validation error {}",
|
||||
download_agent.metadata(),
|
||||
&e
|
||||
);
|
||||
download_agent.on_error(&app_handle, &e);
|
||||
sender.send(DownloadManagerSignal::Error(e)).unwrap();
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if validate_result {
|
||||
download_agent.on_complete(&app_handle);
|
||||
sender
|
||||
.send(DownloadManagerSignal::Completed(download_agent.metadata()))
|
||||
.unwrap();
|
||||
sender.send(DownloadManagerSignal::UpdateUIQueue).unwrap();
|
||||
return;
|
||||
}
|
||||
}
|
||||
sender.send(DownloadManagerSignal::UpdateUIQueue).unwrap();
|
||||
}));
|
||||
|
||||
self.set_status(DownloadManagerStatus::Downloading);
|
||||
|
||||
@ -4,7 +4,6 @@ use serde_with::SerializeDisplay;
|
||||
|
||||
#[derive(SerializeDisplay)]
|
||||
pub enum ProcessError {
|
||||
SetupRequired,
|
||||
NotInstalled,
|
||||
AlreadyRunning,
|
||||
NotDownloaded,
|
||||
@ -19,7 +18,6 @@ pub enum ProcessError {
|
||||
impl Display for ProcessError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let s = match self {
|
||||
ProcessError::SetupRequired => "Game not set up",
|
||||
ProcessError::NotInstalled => "Game not installed",
|
||||
ProcessError::AlreadyRunning => "Game already running",
|
||||
ProcessError::NotDownloaded => "Game not downloaded",
|
||||
|
||||
@ -18,7 +18,7 @@ use crate::remote::requests::make_request;
|
||||
use log::{debug, error, info};
|
||||
use rayon::ThreadPoolBuilder;
|
||||
use std::collections::HashMap;
|
||||
use std::fs::{create_dir_all, OpenOptions};
|
||||
use std::fs::{OpenOptions, create_dir_all};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::mpsc::Sender;
|
||||
use std::sync::{Arc, Mutex};
|
||||
@ -26,7 +26,7 @@ use std::time::Instant;
|
||||
use tauri::{AppHandle, Emitter};
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
use rustix::fs::{fallocate, FallocateFlags};
|
||||
use rustix::fs::{FallocateFlags, fallocate};
|
||||
|
||||
use super::download_logic::download_game_chunk;
|
||||
use super::drop_data::DropData;
|
||||
@ -187,10 +187,7 @@ impl GameDownloadAgent {
|
||||
self.generate_contexts()?;
|
||||
}
|
||||
|
||||
self.context_map
|
||||
.lock()
|
||||
.unwrap()
|
||||
.extend(self.stored_manifest.get_contexts());
|
||||
*self.context_map.lock().unwrap() = self.stored_manifest.get_contexts();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -423,6 +420,7 @@ impl Downloadable for GameDownloadAgent {
|
||||
app_handle,
|
||||
)
|
||||
.unwrap();
|
||||
println!("Attempting to redownload");
|
||||
}
|
||||
|
||||
fn on_cancelled(&self, _app_handle: &tauri::AppHandle) {}
|
||||
|
||||
@ -27,8 +27,9 @@ pub struct DropWriter<W: Write> {
|
||||
}
|
||||
impl DropWriter<File> {
|
||||
fn new(path: PathBuf) -> Self {
|
||||
let destination = OpenOptions::new().write(true).create(true).truncate(false).open(&path).unwrap();
|
||||
Self {
|
||||
destination: OpenOptions::new().write(true).open(path).unwrap(),
|
||||
destination,
|
||||
hasher: Context::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
use std::{
|
||||
fs::File,
|
||||
io::{Read, Write},
|
||||
path::PathBuf,
|
||||
collections::HashMap, fs::File, io::{Read, Write}, path::PathBuf
|
||||
};
|
||||
|
||||
use log::{debug, error, info, warn};
|
||||
@ -12,7 +10,7 @@ pub type DropData = v1::DropData;
|
||||
static DROP_DATA_PATH: &str = ".dropdata";
|
||||
|
||||
pub mod v1 {
|
||||
use std::{path::PathBuf, sync::Mutex};
|
||||
use std::{collections::HashMap, path::PathBuf, sync::Mutex};
|
||||
|
||||
use native_model::native_model;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -22,7 +20,7 @@ pub mod v1 {
|
||||
pub struct DropData {
|
||||
pub game_id: String,
|
||||
pub game_version: String,
|
||||
pub contexts: Mutex<Vec<(String, bool)>>,
|
||||
pub contexts: Mutex<HashMap<String, bool>>,
|
||||
pub base_path: PathBuf,
|
||||
}
|
||||
|
||||
@ -32,7 +30,7 @@ pub mod v1 {
|
||||
base_path,
|
||||
game_id,
|
||||
game_version,
|
||||
contexts: Mutex::new(Vec::new()),
|
||||
contexts: Mutex::new(HashMap::new()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -85,20 +83,23 @@ impl DropData {
|
||||
};
|
||||
}
|
||||
pub fn set_contexts(&self, completed_contexts: &[(String, bool)]) {
|
||||
*self.contexts.lock().unwrap() = completed_contexts.to_owned();
|
||||
*self.contexts.lock().unwrap() = completed_contexts.iter().map(|s| (s.0.clone(), s.1)).collect();
|
||||
}
|
||||
pub fn set_context(&self, context: String, state: bool) {
|
||||
self.contexts.lock().unwrap().entry(context).insert_entry(state);
|
||||
}
|
||||
pub fn get_completed_contexts(&self) -> Vec<String> {
|
||||
self.contexts
|
||||
.lock()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.filter_map(|x| if x.1 { Some(x.0.clone()) } else { None })
|
||||
.filter_map(|x| if *x.1 { Some(x.0.clone()) } else { None })
|
||||
.collect()
|
||||
}
|
||||
pub fn get_contexts(&self) -> Vec<(String, bool)> {
|
||||
pub fn get_contexts(&self) -> HashMap<String, bool> {
|
||||
info!(
|
||||
"Any contexts which are complete? {}",
|
||||
self.contexts.lock().unwrap().iter().any(|x| x.1)
|
||||
self.contexts.lock().unwrap().iter().any(|x| *x.1)
|
||||
);
|
||||
self.contexts.lock().unwrap().clone()
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use std::{
|
||||
fs::File,
|
||||
io::{self, BufWriter, Read, Seek, SeekFrom, Write},
|
||||
sync::{mpsc::Sender, Arc},
|
||||
sync::{Arc, mpsc::Sender},
|
||||
};
|
||||
|
||||
use log::{debug, error, info};
|
||||
@ -73,6 +73,7 @@ pub fn game_validate_logic(
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// If there are any contexts left which are false
|
||||
if !invalid_chunks.is_empty() {
|
||||
info!(
|
||||
@ -80,6 +81,13 @@ pub fn game_validate_logic(
|
||||
dropdata.game_id.clone(),
|
||||
invalid_chunks
|
||||
);
|
||||
|
||||
for context in invalid_chunks.iter() {
|
||||
dropdata.set_context(context.1.clone(), false);
|
||||
}
|
||||
|
||||
dropdata.write();
|
||||
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
@ -101,7 +109,9 @@ pub fn validate_game_chunk(
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let mut source = File::open(&ctx.path).unwrap();
|
||||
let Ok(mut source) = File::open(&ctx.path) else {
|
||||
return Ok(false);
|
||||
};
|
||||
|
||||
if ctx.offset != 0 {
|
||||
source
|
||||
|
||||
Reference in New Issue
Block a user