From 457e5c533301ac40527508ccb18a6bbf08d29604 Mon Sep 17 00:00:00 2001 From: zqm Date: Fri, 10 Apr 2026 14:06:19 +0800 Subject: [PATCH] =?UTF-8?q?handle=5Fapp=5Ffile=5Fchunk=20=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E5=9C=A8=E5=88=9B=E5=BB=BA=20.tmp=20=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E6=97=B6=EF=BC=8C=E4=BD=BF=E7=94=A8=20file=5Fname()?= =?UTF-8?q?=20=E6=8F=90=E5=8F=96=E7=BA=AF=E6=96=87=E4=BB=B6=E5=90=8D?= =?UTF-8?q?=EF=BC=8C=E5=AF=BC=E8=87=B4=E4=B8=A2=E5=A4=B1=E4=BA=86=E5=AD=90?= =?UTF-8?q?=E7=9B=AE=E5=BD=95=E4=BF=A1=E6=81=AF=EF=BC=88=E5=A6=82=20x64/?= =?UTF-8?q?=E3=80=81x86/=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Windows/CS/Framework4.0/Updater/src/main.rs | 55 +++++++++++---------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/Windows/CS/Framework4.0/Updater/src/main.rs b/Windows/CS/Framework4.0/Updater/src/main.rs index 0988cfb..0c0fc9e 100644 --- a/Windows/CS/Framework4.0/Updater/src/main.rs +++ b/Windows/CS/Framework4.0/Updater/src/main.rs @@ -6,7 +6,7 @@ use std::sync::{Arc, Mutex}; /// 日志文件(Mutex 确保线程安全写入) static LOG_FILE: std::sync::Mutex> = std::sync::Mutex::new(None); -/// 初始化日志文件(以追加方式打开) +/// 初始化日志文件(启动时清除当天日志,然后以追加方式打开) fn init_log_file() { let mut guard = LOG_FILE.lock().unwrap(); if guard.is_some() { @@ -23,7 +23,10 @@ fn init_log_file() { }; let log_name = format!("Updater_{}.log", chrono::Local::now().format("%Y%m%d")); - let log_path = log_dir.join(log_name); + let log_path = log_dir.join(&log_name); + + // 启动时清除当天的日志文件 + let _ = std::fs::remove_file(&log_path); match std::fs::OpenOptions::new() .create(true) @@ -814,6 +817,16 @@ fn send_next_download(ctx: &Arc, sender: &cube_lib::websocket::Me request_download_for_app(sender, &app_name, &filename, offset); } else { *ctx.is_downloading.lock().unwrap() = false; + + // 队列为空,检查是否所有应用都处理完了 + let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); + let pending_apps = ctx.pending_allfile_apps.lock().unwrap(); + if pending_apps.is_empty() { + log_print!("{} [下载] 所有应用文件下载完成,进入 Complete 阶段", ts); + *ctx.current_phase.lock().unwrap() = UpdatePhase::Complete; + } else { + log_print!("{} [下载] 队列为空,等待 {} 个应用完成 AllFile 响应", ts, pending_apps.len()); + } } } @@ -863,17 +876,14 @@ fn handle_app_file_chunk( } app_map.remove(&key); - // filename 可能含路径分隔符,取纯文件名部分 - let tmp_filename = std::path::Path::new(filename) - .file_name() - .and_then(|n| n.to_str()) - .unwrap_or(filename); - + // relative_path 已经是去掉 app_name/ 前缀的相对路径(如 "x64/SQLite.Interop.dll") + // 直接用它构建路径,保留子目录信息 let temp_path = get_updater_data_dir() .join("Updater") .join("UpGrade") .join(app_name) - .join(format!("{}.tmp", tmp_filename)); + .join(&relative_path) + .with_extension("tmp"); let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); println!("{} [应用] 新文件: filename={}, tmp_path={:?}, parent_exists={}", @@ -935,15 +945,8 @@ fn handle_app_file_chunk( let final_offset = app_map.get(&key).map(|s| s.offset).unwrap_or(0); if let Some(ref temp) = temp_path { - // filename 来自服务端消息,可能含路径前缀(如 "sticker/app_config.json") - // 只取纯文件名,与 DownloadComplete 处理器保持路径一致 - let final_filename = std::path::Path::new(filename) - .file_name() - .and_then(|n| n.to_str()) - .unwrap_or(filename); - // final_path 与 tmp 文件同一目录(升级目录),不是 app_data_dir - let upgrade_dir = temp.parent().unwrap(); - let final_path = upgrade_dir.join(final_filename); + // final_path 是 temp_path 去掉 ".tmp" 后缀,直接在同一目录 + let final_path = temp.with_extension(""); // 去掉 .tmp 后缀 let _ = fs::create_dir_all(final_path.parent().unwrap()); // 重命名(同步操作,Windows 上不会异步) @@ -991,14 +994,8 @@ fn handle_app_download_complete( let temp_path = app_map.get(&key).and_then(|s| s.temp_path.clone()); if let Some(ref temp) = temp_path { - // filename 可能含路径分隔符,取纯文件名部分以避免路径重复 - let tmp_filename = std::path::Path::new(filename) - .file_name() - .and_then(|n| n.to_str()) - .unwrap_or(filename); - // final_path 与 tmp 文件同一目录(升级目录),与 handle_app_file_chunk 的 is_last 块保持一致 - let upgrade_dir = temp.parent().unwrap(); - let final_path = upgrade_dir.join(tmp_filename); + // final_path 是 temp_path 去掉 ".tmp" 后缀,直接在同一目录 + let final_path = temp.with_extension(""); // 去掉 .tmp 后缀 let _ = fs::create_dir_all(final_path.parent().unwrap()); if let Err(e) = fs::rename(temp, &final_path) { @@ -1928,6 +1925,11 @@ async fn run_updater(debug_mode: bool) -> bool { let file_size = data_obj.get("file_size").and_then(|v| v.as_u64()).unwrap_or(0); let chunk_size = 4096u64; + // 调试:打印队列状态 + let queue_len = ctx_clone.download_queue.lock().unwrap().len(); + let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); + log_print!("{} [FileChunk] is_last={}, queue_len={}", ts, is_last, queue_len); + let candidates = ctx_clone.candidates.lock().unwrap().clone(); for (app_name, _) in &candidates { let result = handle_app_file_chunk(&ctx_clone, app_name, data_obj, debug_msg); @@ -1939,6 +1941,7 @@ async fn run_updater(debug_mode: bool) -> bool { println!("{} [应用] {} / {} 下载完成", ts, app_name, filename); } ctx_clone.app_completed_set.lock().unwrap().insert(format!("{}/{}", app_name, filename)); + log_print!("{} [FileChunk] 调用 send_next_download, queue_len={}", ts, queue_len); send_next_download(&ctx_clone, &sender); } else { // 非最后一块,立即请求下一块(用 relative_path,不带 app_name/ 前缀)