Conversation
…orgbackup#10364 The repository uses the index ArchiveChecker builds instead of loading or building a second one.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #10368 +/- ##
=======================================
Coverage 88.06% 88.06%
=======================================
Files 103 103
Lines 18913 18915 +2
Branches 2919 2919
=======================================
+ Hits 16655 16657 +2
Misses 1565 1565
Partials 693 693 ☔ View full report in Codecov by Harness. |
|
Reviewed on the PR base What I verifiedThe memory claim, measured. Build counts alone can't show this (they're mostly the same as master), so I counted non-empty
Peak is one index everywhere, including the repair-with-changed-packs case that master had at three. "The one-liner alone is not enough". With only Tests. The two new tests pass locally (local + remote kinds); Reasoning I checked and agree with. Nothing in the checker reads Comments
Out of scope, noted for later
🤖 Review drafted with Claude Code |
Description
borg checkholds the chunk index in memory twice. Refs #10364, same change as #10359 does forborg compact.Where the second index comes from:
Repository.check()loads the index from theindex/fragments and keeps it asrepository.chunks.ArchiveChecker.check()then builds its own index while that one is still in memory.--archives-only:ArchiveChecker.check()builds its index, then the firstrepository.get()builds a second one through theRepository.chunksproperty.--repairwith changed packs:finish()rebuilds the index from the packs while the checker's index is still in memory.Changes in
ArchiveChecker:check(): callsrepository.invalidate_chunk_index()before building the index, then setsrepository.chunks = self.chunks.get(),put()anddelete()of the repository use this index from then on.check()with--repair: callsself.chunks.clear_new()after the rebuild from the packs. The rebuild setsF_NEW(entry not stored in theindex/fragments yet) on every entry, andRepository.close()stores allF_NEWentries as a new fragment.finish()stores the complete index.add_reference(): with--repair, only callsrepository.put(), which adds the entry to the index and sets its pack location. Callingself.chunks.add()beforeput()on the same index fails theassert v.size == 0 or v.size == sizeinChunkIndex.add(). Without--repair, it does not change the index: entries without a pack location (F_PENDING) in the repository's index makeRepository.close()fail withAssertionError: chunk ... has no pack location yet.verify_data()with--repair: removesdel self.chunks[defect_chunk].repository.delete()already removes the entry from the index, so thedelraisesKeyError.finish()with changed packs: callsrepository.invalidate_chunk_index()and setsself.chunks = Nonebefore rebuilding the index from the packs.Tests:
test_check_holds_a_single_chunk_index, for--archives-only, full check and--repair, on a repo with a missing item metadata chunk. It asserts thatrepository.chunksis not loaded when the checker builds an index, thatrepository.chunksis the checker's index inrebuild_archives(), and that theRepository.chunksproperty builds no index. All three cases fail on master.test_check_without_repair_leaves_the_chunk_index_alone: a check without--repairon the same kind of repo does not change theindex/fragments or the chunk ids in the index.repository.chunks = self.chunksadded to master, 10 tests incheck_cmd_test.pyfail with theAssertionErrors and theKeyErrorabove, among them the existingtest_verify_data,test_missing_file_chunkandtest_missing_archive_item_chunk.Full test suite: 3061 passed, 1128 skipped.
Checklist
master(or maintenance branch if only applicable there)toxor the relevant test subset)