Repository navigation
fix(store): harden MultiListIterator close and next - #3445
Open
vaidikgarg-bit wants to merge 1 commit into
Open
vaidikgarg-bit wants to merge 1 commit into
vaidikgarg-bit wants to merge 1 commit into
Conversation
close() now closes every sub-iterator and clears the list even when one close() throws a RuntimeException or Error, then rethrows the first failure with later ones suppressed. next() moves on to the next sub-iterator itself and throws NoSuchElementException instead of NullPointerException when nothing is left. After close(), hasNext() and isValid() return false without probing any source, and a second close() does nothing. close apache#3444
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #3445 +/- ##
============================================
+ Coverage 57.27% 57.67% +0.40%
+ Complexity 6577 2589 -3988
============================================
Files 776 779 +3
Lines 68881 69161 +280
Branches 9431 9506 +75
============================================
+ Hits 39449 39887 +438
+ Misses 25804 25616 -188
- Partials 3628 3658 +30
*This pull request uses carry forward flags. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
bitflicker64
approved these changes
Oct 31, 2026
bitflicker64
left a comment
Contributor
There was a problem hiding this comment.
Blocking: no. Score: 9/10. Summary: close() closes every sub-iterator and clears the list even when one close() throws, next() advances through hasNext() and throws NoSuchElementException when exhausted or closed, and the five new FilterIteratorContractTest cases cover each path and pass in pd_store / store at this head.
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.
Purpose of the PR
#3437 made
MultiListIterator.close()close every sub-iterator when it runs before the firsthasNext(). Three problems remained in the same class:close()closes the sub-iterators with notry/finally. When oneclose()throws, the remaining sub-iterators stay open and the list is never cleared.next()dereferencesinnerIterator, which is only set byhasNext()/isValid(). Callingnext()first, or afterhasNext()has returnedfalse, throwsNullPointerException. Repeatednext()calls withouthasNext()also never move past the current sub-iterator.close()leavesinnerIteratorpointing at the source it just closed. The nexthasNext()orisValid()calls into that closed source and can close it again.Main Changes
closedflag, asUnionFilterIteratorandIntersectionFilterIteratorhave. Once it is set,hasNext()andisValid()returnfalsewithout touching any source, and a secondclose()does nothing.close()drops its reference to the current sub-iterator and keeps going when a sub-iterator'sclose()throws aRuntimeExceptionor anError(RocksDBScanIterator.close()rethrows both). It clears the list and then rethrows the first failure, with any later failures added as suppressed exceptions.next()callshasNext()first, so it moves on to the next sub-iterator by itself and throwsNoSuchElementExceptionwhen nothing is left, including afterclose(). With the usualhasNext()/next()loop this costs one extrahasNext()on the current sub-iterator per row (forRocksDBScanIterator, one moreisOwningHandle()/isValid()/key()round trip and key filter).Not changed here:
position()has no closed check, so after closing mid-iteration it now throwsNullPointerExceptioninstead of reading the closed source (before iteration it already threw on master). A close failure raised whilehasNext()moves past an exhausted sub-iterator is also left as is.Verifying these changes
FilterIteratorContractTest: aRuntimeExceptionclose failure before iteration, anErrorclose failure before iteration, a close failure during iteration,next()withouthasNext(), andhasNext()/isValid()/next()/close()after closing mid-iteration. All five fail on master.store-server-test(202),store-core-test(113) andstore-rocksdb-test(19) pass locally on8e327b8f3, andmvn editorconfig:checkis clean for the changed modules.Does this PR potentially affect the following parts?
Documentation Status
Select one option and provide the documentation location when applicable.
Doc - TODO: required documentation is pending; complete it before merging.Doc - Done: documentation is included here or linked below.Doc - No Need: no user-visible documentation is affected.Documentation files in this PR or paired hugegraph-doc PR:
Visual overview
Explicit close() marks the iterator closed, detaches the current source, attempts the current and remaining source closes despite RuntimeException/Error, clears the list, and rethrows the first failure with later failures suppressed when a failure occurred. Subsequent probes stop and repeated close() is a no-op. next() checks availability itself and throws NoSuchElementException when exhausted or closed. position() and advance-time close failures remain outside this fix; the additional hasNext() call per row has no bounded performance measurement here. This illustrates the current diff, not independent test, CI or release acceptance. Reviewed: 2026-10-31.