feat: repair 重传后自动复核 (前置校验等级验证重传文件)
This commit is contained in:
1 parent
4defbf8b1e
commit
30419c9aae
3 files changed
+100
No files matched your search
+60
@@ -209,6 +209,40 @@ def build_repair_cmd(src: str, dst: str, list_file: str,
|
||||
return cmd, list_file
|
||||
|
||||
|
||||
def verify_files_list(src_dir: str, dst_dir: str, rels: list[str],
|
||||
level: str = "slow",
|
||||
on_progress=None) -> tuple[list[str], list[str]]:
|
||||
"""复核指定文件列表: 按校验等级验证源/目标一致性
|
||||
|
||||
- ultrafast: 仅大小
|
||||
- fast: 大小+mtime
|
||||
- normal/slow/full: md5 内容校验
|
||||
返回 (通过列表, 失败列表); on_progress(i, total) 进度回调
|
||||
"""
|
||||
ok: list[str] = []
|
||||
fail: list[str] = []
|
||||
total = len(rels)
|
||||
for i, rel in enumerate(rels, 1):
|
||||
sp = os.path.join(src_dir, rel)
|
||||
tp = os.path.join(dst_dir, rel)
|
||||
if not os.path.isfile(sp):
|
||||
continue
|
||||
if not os.path.isfile(tp):
|
||||
fail.append(rel)
|
||||
elif level == "ultrafast":
|
||||
(ok if os.path.getsize(sp) == os.path.getsize(tp) else fail).append(rel)
|
||||
elif level == "fast":
|
||||
sst, tst = os.stat(sp), os.stat(tp)
|
||||
good = (sst.st_size == tst.st_size
|
||||
and int(sst.st_mtime) == int(tst.st_mtime))
|
||||
(ok if good else fail).append(rel)
|
||||
else:
|
||||
(ok if files_identical(sp, tp) else fail).append(rel)
|
||||
if on_progress:
|
||||
on_progress(i, total)
|
||||
return ok, fail
|
||||
|
||||
|
||||
def read_proc_io(pid: int) -> int:
|
||||
"""读取进程累计读字节数 (/proc/pid/io read_bytes)"""
|
||||
try:
|
||||
@@ -954,6 +988,32 @@ class TaskRunner:
|
||||
self.on_log("[green]✔ 问题文件已重传[/]")
|
||||
else:
|
||||
self.on_log(f"[red]✘ 重传失败 rc={rc}: {errs.strip()[:200]}[/]")
|
||||
# 重传后复核: 用前置校验等级再验一遍重传的文件
|
||||
if rc == 0 and issues:
|
||||
self._recheck_repaired(issues)
|
||||
|
||||
def _recheck_repaired(self, issues: list[str]) -> None:
|
||||
"""重传后用前置校验等级复核问题文件"""
|
||||
src_dir = self.cfg.source.rstrip("/")
|
||||
dst_dir = self.cfg.dest.rstrip("/")
|
||||
self.lm.write(f"repair: 复核 {len(issues)} 个重传文件 "
|
||||
f"(level={self.cfg.verify_level})")
|
||||
if self.on_log:
|
||||
self.on_log(f"[cyan]复核重传文件 ({self.cfg.verify_level})...[/]")
|
||||
|
||||
def on_progress(i: int, total: int) -> None:
|
||||
self._emit_verify_progress(i, total)
|
||||
|
||||
ok, fail = verify_files_list(src_dir, dst_dir, issues,
|
||||
self.cfg.verify_level,
|
||||
on_progress=on_progress)
|
||||
self.lm.write(f"repair: 复核完成 通过={len(ok)} 失败={len(fail)}")
|
||||
if self.on_log:
|
||||
if not fail:
|
||||
self.on_log(f"[green]✔ 复核通过: {len(ok)} 个重传文件完整[/]")
|
||||
else:
|
||||
self.on_log(f"[red]✘ 复核发现 {len(fail)} 个文件仍未修复: "
|
||||
f"{', '.join(os.path.basename(f) for f in fail[:5])}[/]")
|
||||
|
||||
def _emit_verify_progress(self, i: int, total: int) -> None:
|
||||
"""校验进度: 复用 stats 驱动进度条 + 每 5% 打日志"""
|
||||
|
||||
Reference in new issue
Block a user