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/ 前缀)