Repository navigation
fix(index): replace saved index files atomically - #189
Merged
Merged
Conversation
HNSW, IVF and SymphonyQG save to a temporary file beside the destination and rename it into place, so a failed save leaves an existing index unchanged and removes what it wrote. IVF renames its HNSW sidecar first. A replaced file keeps its permission bits, but not its owner or other hard links; symbolic links and other non-regular destinations are still written in place. HNSW now serializes one loaded point count instead of the bytes of the atomic counter.
…verse-edge locks IVF::reserve grows one cluster, so only that cluster's view needs to point at the new storage; rebuilding every view cost O(num_clusters) per call. QGBuilder allocated one mutex per point for each reverse-edge pass; 4096 striped locks keep the same mutual exclusion with memory independent of the point count.
Spell the construct default as every available thread (0 still auto-selects), document that one-thread add keeps links deterministic, and give Rotator dimensions a defined initial value.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
fix).savewrite to a temporary file beside the destination and rename it into place, so a failed save leaves an existing index unchanged and removes what it wrote. Previously a failure part-way through left a truncated file.perf).IVF::reserverefreshes only the grown cluster's view instead of rebuilding every view, which cost O(num_clusters) per call.constructdefault is now spelled as every available thread;0still auto-selects, so behavior is unchanged.addkeeps links deterministic.Rotatordimensions start initialized.No public API or saved-format changes. The save behavior is documented under the shared persistence conventions in
docs/docs/index/usage.md.Known limitation: if the index-file rename fails after the IVF sidecar rename succeeded, a new sidecar can remain beside the old index. This needs both renames in one directory to succeed and fail in turn (for example, a permission change in between). It is documented; a journaled two-file update is out of scope here.
Behavior change to note: saving over an existing read-only index file now succeeds, because a rename needs write access to the directory, not the file. The replacement keeps the read-only bits.
Testing
Linux x86-64 (GCC 14.3,
RABITQ_ENABLE_NATIVE_OPTIMIZATION=OFF):--no-tests=error): Release and ASan/UBSan, 424 passed each, 1 skipped (the placement test, which requires OpenMP binding). The first commit was also built and tested on its own.file_replacement_test):check-format.sh,check-python.sh, fullcheck-tidy.sh build-tidy(clang-tidy 23),mkdocs build --strictandgit diff --checkpass.Not run locally: Windows and macOS. On Windows the permission test is skipped, because only a read-only attribute exists there.