Skip to content

[diskann-garnet] Implement continue_search() - #1357

Merged
Jack Moffitt (metajack) merged 1 commit into
mainfrom
push-pssntsrowrpl
Sep 9, 2026
Merged

[diskann-garnet] Implement continue_search()#1357
Jack Moffitt (metajack) merged 1 commit into
mainfrom
push-pssntsrowrpl

Conversation

@metajack

Copy link
Copy Markdown
Contributor

Implements continue_search() in the Garnet FFI.

The buffers for ids that Garnet passes may be insufficient since external IDs are user-provided byte strings of arbitrary length. The distances buffer will always be correctly sized. In the case the id buffer is too small, a Continuation is boxed and returned, which can be used by potentially repeated calls to continue_search() to retrieve the rest of the results.

This set up is used all the search_X FFI methods. It is not used in random_members() since due to how other things are handled with that it can just use multiple calls to get more random members if needed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements continue_search() for the Garnet FFI by introducing an overflow/continuation mechanism to safely return variable-length external IDs when the caller-provided ID buffer is too small. It extends the existing search FFI surface to return a continuation pointer for subsequent calls, updates neighbor queries to use max_degree(), and bumps the diskann-garnet package version.

Changes:

  • Add Continuation and implement continue_search() to drain overflowed search results across multiple FFI calls.
  • Extend SearchResults to track k and store overflow IDs/distances when output buffers can’t fit all results.
  • Wire continuation out-parameters through search_vector, search_element, and search_neighbors, and update/extend tests accordingly; bump version to 5.0.1.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
diskann-garnet/src/provider.rsExposes max_degree() from the provider for neighbor retrieval sizing.
diskann-garnet/src/lib.rsImplements Continuation + continue_search(), adds overflow handling to SearchResults, and updates FFI search functions to return continuation pointers.
diskann-garnet/src/ffi_tests.rsUpdates FFI tests to use the new continuation out-parameter and adds coverage for continuation being written.
diskann-garnet/src/ffi_recall_tests.rsUpdates recall tests to pass and clean up continuation pointers.
diskann-garnet/src/dyn_index.rsExtends DynIndex with max_degree() and plumbs it to the provider.
diskann-garnet/diskann-garnet.nuspecBumps NuGet package version to 5.0.1.
diskann-garnet/Cargo.tomlBumps crate version to 5.0.1.
Cargo.lockUpdates locked version for diskann-garnet to 5.0.1.
Suppressed comments (4)

diskann-garnet/src/lib.rs:941

  • search_element does not initialize/validate the continuation out-parameter. On success without overflow it currently never writes to it (caller must pre-initialize), and on error returns it can leave the out-parameter stale/uninitialized.
 let index = unsafe { &*index_ptr.cast::<Index>() };
let id_bytes = unsafe { slice::from_raw_parts(id_data, id_len) };
let id = GarnetId::from(id_bytes);
let ctx = Context::new(ctx);

diskann-garnet/src/lib.rs:1021

  • continue_search only writes new_continuation when more results remain. If the continuation is exhausted, the out-parameter is left untouched, so callers that don't pre-initialize it may treat garbage as a live pointer (double-free/UB). Also, slice::from_raw_parts_mut is invoked unconditionally, which is UB if a C caller passes a null pointer with a 0 length (a common FFI pattern).
 if continuation.is_null() || new_continuation.is_null() {
return -1;
}
let output_ids = unsafe { slice::from_raw_parts_mut(output_ids, output_ids_len) };

diskann-garnet/src/lib.rs:850

  • search_vector writes through the continuation out-parameter on success, but it is never validated and it is not initialized on early-return error paths (e.g., failed interpret_vector). This can segfault if Garnet passes a null out-parameter, and it can leave the caller with an uninitialized/stale continuation pointer on errors.

This issue also appears in the following locations of the same file:

  • line 937
  • line 1017
  • line 1176
 continuation: *mut *mut c_void,
) -> i32 {
let index = unsafe { &*index_ptr.cast::<Index>() };
let v = if let Some(v) = interpret_vector(index.quant_type, &vector_data, vector_len) {

diskann-garnet/src/lib.rs:1179

  • search_neighbors can return -1 before it ever writes to the continuation out-parameter (e.g., if neighbors() fails), and it doesn't validate the out-parameter before writing on success. This can leave callers with stale/uninitialized continuation pointers or cause a segfault if a null out-parameter is passed.
 let index = unsafe { &*index_ptr.cast::<Index>() };
let ctx = Context::new(ctx);
let id_bytes = unsafe { slice::from_raw_parts(id_data, id_len) };
let id = GarnetId::from(id_bytes);

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment threaddiskann-garnet/src/lib.rs
Comment threaddiskann-garnet/src/lib.rs Fixed
Comment threaddiskann-garnet/src/lib.rs Fixed
Comment threaddiskann-garnet/src/lib.rs Fixed
Comment threaddiskann-garnet/src/lib.rs Fixed
Comment threaddiskann-garnet/src/lib.rs Fixed
@codecov-commenter

Codecov Comments Bot (codecov-commenter) commented Aug 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.14226% with 14 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.56%. Comparing base (158126e) to head (c9641a3).
⚠️ Report is 11 commits behind head on main.

Files with missing linesPatch %Lines
diskann-garnet/src/lib.rs93.83%14 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@ Coverage Diff @@## main #1357 +/- ##
==========================================
+ Coverage 91.55% 92.56% +1.00% 
==========================================
Files 521 522 +1 Lines 100371 101105 +734 ==========================================
+ Hits 91898 93586 +1688 + Misses 8473 7519 -954 
FlagCoverage Δ
miri92.56% <94.14%> (+1.00%)⬆️
unittests92.50% <94.14%> (+1.26%)⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing linesCoverage Δ
diskann-garnet/src/dyn_index.rs80.86% <100.00%> (+1.05%)⬆️
diskann-garnet/src/provider.rs79.01% <100.00%> (-0.12%)⬇️
diskann-garnet/src/lib.rs94.31% <93.83%> (-0.29%)⬇️

... and 100 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Jack - just a few small API questions!

Comment threaddiskann-garnet/src/lib.rs Outdated
Comment threaddiskann-garnet/src/lib.rs Outdated
Comment threaddiskann-garnet/src/lib.rs
Comment threaddiskann-garnet/src/lib.rs Outdated
Comment threaddiskann-garnet/src/lib.rs Fixed
Comment threaddiskann-garnet/src/lib.rs Outdated
Comment threaddiskann-garnet/src/lib.rs Outdated
@magdalendobson

Copy link
Copy Markdown
Contributor

Low stakes feedback but I think that continue_search and Continuation are potentially confusing names. They may make people think that DiskANN is doing more search in a paged search manner. Could we workshop a bit on naming, maybe something like continue_buffering and BufferContinuation?

@metajack

Copy link
Copy Markdown
ContributorAuthor

Good suggestion. I've renamed it to overflow_results and Overflow.

Comment threaddiskann-garnet/src/lib.rs Dismissed
@metajack
Jack Moffitt (metajack) merged commit e5fa8eb into mainSep 9, 2026
28 checks passed
@metajack
Jack Moffitt (metajack) deleted the push-pssntsrowrpl branch September 9, 2026 20:52
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@metajack@codecov-commenter@magdalendobson@hildebrandmw@github-advanced-security