fix(core): fix rare error on index drop that can suspend table#6147
fix(core): fix rare error on index drop that can suspend table#6147bluestreak01 merged 12 commits intomasterfrom
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the WalkthroughReplaced recursive QuickSort in IntGroupSort with an iterative version using IntList’s internal capacity as an explicit stack. Updated method signatures to accept IntList instead of int[]. IntList now passes itself to sorting and exposes a package-private resetCapacityInternal. Added a test constructing many reverse-ordered groups to validate non-recursive sorting. Changes
Sequence Diagram(s)sequenceDiagram
actor Client
participant IL as IntList
participant IGS as IntGroupSort
Client->>IL: sortGroups(groupSize)
IL->>IGS: quickSort(n, this, groupLo, groupHi)
activate IGS
rect rgb(230,245,255)
note over IGS: Allocate stack in IntList spare capacity
loop while stack not empty
IGS->>IGS: pop (low, high)
IGS->>IGS: partition(IntList, low, high, n)
alt push larger partition first
IGS->>IGS: push ranges onto stack
end
end
note over IGS: finally: restore original IntList size
end
deactivate IGS
IL-->>Client: return
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested labels
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (6)
core/src/test/java/io/questdb/test/std/IntListTest.java (2)
285-314: Good regression for StackOverflow; add a couple of cheap correctness asserts.This reliably exercises the worst-case partition pattern and validates ordering by the first key. Since groups are swapped as units, add quick checks that group members stayed intact after sorting (guards against accidental element-wise swaps or a wrong stride).
Apply this diff to extend the assertions:
// Verify the result is correctly sorted for (int i = 0; i < numGroups - 1; i++) { int baseIndex = i * groupSize; int nextBaseIndex = (i + 1) * groupSize; // Compare first elements of consecutive groups - should be in ascending order Assert.assertTrue("Groups should be sorted in ascending order", list.getQuick(baseIndex) <= list.getQuick(nextBaseIndex)); + + // Sanity-check group cohesion: members should remain tied to their group's first key + int key = list.getQuick(baseIndex); + Assert.assertEquals(key * 2, list.getQuick(baseIndex + 1)); + Assert.assertEquals(key * 3, list.getQuick(baseIndex + 2)); }
285-314: Consider marking as slow or trimming size to keep CI snappy.50k groups (150k ints) is fine locally, but if CI gets tight, annotate as a slow test (repo convention permitting) or reduce to 20–30k while keeping the worst-case shape.
If the project uses categories, would you like me to wire this under a @category(Slow.class) (JUnit4) or a custom marker?
core/src/main/java/io/questdb/std/IntList.java (1)
397-400: Internal backdoor to the backing array: document and fence expectations.Exposing the raw array is fine within the package for algorithms like IntGroupSort, but the invariants should be explicit.
Apply this diff to add an internal Javadoc:
- int[] resetCapacityInternal(int intCapacity) { + /** + * INTERNAL: Ensures capacity ≥ {@code intCapacity} and returns the backing array reference. + * The caller may write to indices in [pos, capacity) as temporary scratch space, + * but must not rely on contents being preserved or visible to external callers. + * Do not mutate [0, pos) except via IntList APIs. + */ + int[] resetCapacityInternal(int intCapacity) { checkCapacity(intCapacity); return data; }core/src/main/java/io/questdb/std/IntGroupSort.java (3)
59-127: Add a tiny safety net to grow the stack if ever needed.64 ints should suffice (≈32 ranges) under the “process smaller first” strategy, but a defensive check makes this future-proof and documents intent.
Apply this diff to ensure capacity before pushes:
- // Push initial range onto stack + // Push initial range onto stack + if (stackPos + 2 > array.length) { + array = intList.resetCapacityInternal(stackPos + 64); + } array[stackPos++] = low; array[stackPos++] = high; while (stackPos > stackStart) { // Pop range from stack high = array[--stackPos]; low = array[--stackPos]; if (low + 1 < high) { int pi = partition(array, low, high, n); // Push the larger partition first, then smaller one // This ensures the stack depth remains logarithmic if (pi - low > high - pi - 1) { // Left partition is larger + if (stackPos + 4 > array.length) { + array = intList.resetCapacityInternal(stackPos + 64); + } array[stackPos++] = low; array[stackPos++] = pi; array[stackPos++] = pi + 1; array[stackPos++] = high; } else { // Right partition is larger or equal + if (stackPos + 4 > array.length) { + array = intList.resetCapacityInternal(stackPos + 64); + } array[stackPos++] = pi + 1; array[stackPos++] = high; array[stackPos++] = low; array[stackPos++] = pi; } } }
33-42: Comments mention “3 elements each” butnis variable.Minor doc drift; update to avoid confusion.
Suggested edits:
- Line 33: “Compare two groups” (drop “of 3 elements each”).
- Line 130: “Swap two groups” (drop “of 3 elements each”).
Also applies to: 130-139
142-153: Clarify that groupHi is exclusive in the Javadoc.The implementation treats
[groupLo, groupHi); make it explicit.Apply this diff to the Javadoc:
- * @param groupLo start index of the group - * @param groupHi end index of the group + * @param groupLo start group index (inclusive) + * @param groupHi end group index (exclusive)
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
core/src/main/java/io/questdb/std/IntGroupSort.java(2 hunks)core/src/main/java/io/questdb/std/IntList.java(2 hunks)core/src/test/java/io/questdb/test/std/IntListTest.java(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: New pull request (Check Changes Check changes)
- GitHub Check: build
- GitHub Check: build
🔇 Additional comments (2)
core/src/main/java/io/questdb/std/IntGroupSort.java (1)
59-127: Iterative quicksort removes the StackOverflowError risk.The explicit stack built in the IntList tail is a solid fix; restoring
posin a finally-block is the right hygiene. Nice.core/src/main/java/io/questdb/std/IntList.java (1)
322-322: Call-site looks correct (high is exclusive); verify no other direct callers remain
PassinggroupHi = pos / groupSizematches the half-open [lo, hi) contract.
Sandbox rg returned "No files were searched" — run locally to confirm no remaining callers:
rg -nP -C3 -uu --type=java 'IntGroupSort.quickSort\s*('
rg -nP -C3 -uu '\bquickSort\s*('
Conflicts: core/rust/qdb-core/src/byte_util.rs
|
I only reviewed and tested 4f38f32 and it look fine - the test failure is no longer reproducible. |
[PR Coverage check]😍 pass : 25 / 25 (100.00%) file detail
|
(cherry picked from commit 0a1a4e5)
fixes #6146