Commit 3f98352
Close the remaining four correctness holes in SF recovery
C5. The foreground send loop CONSUMED the engine's recovery sources --
pd.takeLoadedEntries() plus engine.releaseRecoveredSymbolStorage() --
making the hand-off one-shot while leaving a second construction
reachable: ensureConnected's catch closes and nulls cursorSendLoop
precisely so a caller can retry, and `connected` is set only at the very
end. Neither call cleared the counts that gate re-seeding, so the retry
saw recoveredSize() > 0 with loadedEntriesLen() == 0, left sentDictCount
at 0, and then either tripped the baseline mismatch or latched the
torn-dictionary terminal on a healthy slot. Both policies now BORROW, as
the orphan drainer already did; the engine frees at close. Lifetime holds
in both directions because QwpWebSocketSender.close() and
BackgroundDrainer's finally both close the loop before the engine. The
two transfer methods had no other caller and are deleted.
C6. A pre-21 unsafe-access fault is delivered asynchronously, so one
taken while scanning a segment can surface at MmapSegment.openExisting's
RETURN -- in SegmentRing's frame, before `seg = openExisting(...)` ever
assigns. The segment was fully constructed, so its fd and whole-file
mapping leaked with nothing referencing them, while the log claimed a
skip that had not happened. openExisting now publishes the segment into
a caller-supplied holder immediately before returning, and SegmentRing's
finally closes whichever handle survived. The holder is cleared at every
ownership transfer, so it can never close a segment `opened` now holds.
C7. accept() checkpoints committedRawLen/Count only at a commit-bearing
frame, while foldDelta's gap-reset rewinds runningRawLen/Count to 0
without touching them -- so the next appendRaw overwrites the committed
bytes in place. Harmless when a commit-bearing frame follows, but a reset
inside an uncommitted deferred tail never gets that refresh and finish()
then published the old counts over the tail's bytes: recovery decoded the
tail's symbol under the committed id while the frame that actually
replays registered a different one. finish() now detects the rewind and
fails clean instead.
C8. markFailed is best-effort and returns silently when it cannot open
the sentinel -- and a full or read-only disk, the condition that makes a
slot unreplayable, is exactly the condition that makes writing it fail.
Twelve lines after quarantining, the same build() dispatches its orphan
drainers, and the quarantined copy was still a candidate: unbounded churn
against data explicitly declared human-in-the-loop, repeating on every
restart. OrphanScanner now excludes quarantined slots BY NAME, and owns
the reserved infix that Sender.build() renames with.
Regression tests, each verified to fail with its fix reverted:
testForegroundLoopReSeedsAfterAClosedFirstAttempt (UnreplayableSlot
"recovery symbol baseline mismatch [expected=2, actual=0]"),
testGapResetInsideTheDeferredTailFailsCleanInsteadOfMisattributing
(expected:<-1> but was:<1>), and
testQuarantinedSlotIsNotACandidateEvenWithoutTheFailedSentinel. The two
MirrorLeakTest cases that pinned the old ownership transfer now pin
borrowing, including that closing a borrowed loop leaves the engine's
buffer alive.
C6 has no regression test: reproducing it needs a fault delivered at one
specific instruction boundary on a pre-21 JIT, which is the same
JIT-dependent delivery the existing MmapSegmentRecoveryFaultTest guards
cannot pin either. The change is a strict improvement over having no
handle at all, and the existing multi-segment recovery tests cover the
double-close risk it introduces.
Full client suite: 2693 tests green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>1 parent 66bdc0f commit 3f98352
11 files changed
Lines changed: 274 additions & 50 deletions
File tree
- core/src
- main/java/io/questdb/client
- cutlass/qwp/client/sf/cursor
- test/java/io/questdb/client/test/cutlass/qwp/client/sf/cursor
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1026 | 1026 | | |
1027 | 1027 | | |
1028 | 1028 | | |
1029 | | - | |
| 1029 | + | |
| 1030 | + | |
1030 | 1031 | | |
1031 | 1032 | | |
1032 | 1033 | | |
| |||
Lines changed: 0 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
809 | 809 | | |
810 | 810 | | |
811 | 811 | | |
812 | | - | |
813 | | - | |
814 | | - | |
815 | | - | |
816 | | - | |
817 | | - | |
818 | 812 | | |
819 | 813 | | |
820 | 814 | | |
| |||
Lines changed: 18 additions & 20 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
725 | 725 | | |
726 | 726 | | |
727 | 727 | | |
728 | | - | |
729 | 728 | | |
730 | 729 | | |
731 | 730 | | |
| |||
734 | 733 | | |
735 | 734 | | |
736 | 735 | | |
737 | | - | |
738 | 736 | | |
739 | 737 | | |
740 | 738 | | |
| |||
803 | 801 | | |
804 | 802 | | |
805 | 803 | | |
806 | | - | |
807 | | - | |
808 | | - | |
809 | | - | |
810 | | - | |
811 | | - | |
812 | | - | |
813 | | - | |
814 | | - | |
815 | | - | |
816 | | - | |
817 | | - | |
818 | | - | |
819 | | - | |
820 | | - | |
821 | | - | |
822 | | - | |
823 | | - | |
| 804 | + | |
| 805 | + | |
| 806 | + | |
| 807 | + | |
| 808 | + | |
| 809 | + | |
| 810 | + | |
| 811 | + | |
| 812 | + | |
| 813 | + | |
| 814 | + | |
| 815 | + | |
| 816 | + | |
| 817 | + | |
| 818 | + | |
| 819 | + | |
| 820 | + | |
| 821 | + | |
824 | 822 | | |
825 | 823 | | |
826 | 824 | | |
| |||
Lines changed: 22 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
335 | 335 | | |
336 | 336 | | |
337 | 337 | | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
338 | 355 | | |
339 | 356 | | |
340 | 357 | | |
| |||
382 | 399 | | |
383 | 400 | | |
384 | 401 | | |
385 | | - | |
| 402 | + | |
386 | 403 | | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
387 | 408 | | |
388 | 409 | | |
389 | 410 | | |
| |||
Lines changed: 31 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
61 | 61 | | |
62 | 62 | | |
63 | 63 | | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
64 | 78 | | |
65 | 79 | | |
66 | 80 | | |
| |||
271 | 285 | | |
272 | 286 | | |
273 | 287 | | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
274 | 291 | | |
275 | 292 | | |
276 | 293 | | |
277 | 294 | | |
278 | 295 | | |
279 | 296 | | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
280 | 311 | | |
281 | 312 | | |
282 | 313 | | |
| |||
Lines changed: 0 additions & 12 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
567 | 567 | | |
568 | 568 | | |
569 | 569 | | |
570 | | - | |
571 | | - | |
572 | | - | |
573 | | - | |
574 | | - | |
575 | | - | |
576 | | - | |
577 | | - | |
578 | | - | |
579 | | - | |
580 | | - | |
581 | | - | |
582 | 570 | | |
583 | 571 | | |
584 | 572 | | |
| |||
Lines changed: 24 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
51 | 51 | | |
52 | 52 | | |
53 | 53 | | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
54 | 58 | | |
55 | 59 | | |
56 | 60 | | |
| |||
92 | 96 | | |
93 | 97 | | |
94 | 98 | | |
| 99 | + | |
95 | 100 | | |
96 | 101 | | |
97 | 102 | | |
| |||
142 | 147 | | |
143 | 148 | | |
144 | 149 | | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
145 | 162 | | |
146 | 163 | | |
147 | 164 | | |
| |||
274 | 291 | | |
275 | 292 | | |
276 | 293 | | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
277 | 301 | | |
278 | 302 | | |
279 | 303 | | |
| |||
Lines changed: 17 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
205 | 205 | | |
206 | 206 | | |
207 | 207 | | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
208 | 212 | | |
209 | 213 | | |
210 | 214 | | |
211 | 215 | | |
212 | 216 | | |
213 | 217 | | |
214 | 218 | | |
| 219 | + | |
215 | 220 | | |
216 | | - | |
| 221 | + | |
217 | 222 | | |
218 | 223 | | |
219 | 224 | | |
| |||
238 | 243 | | |
239 | 244 | | |
240 | 245 | | |
| 246 | + | |
241 | 247 | | |
242 | 248 | | |
243 | 249 | | |
| |||
246 | 252 | | |
247 | 253 | | |
248 | 254 | | |
| 255 | + | |
249 | 256 | | |
250 | 257 | | |
251 | 258 | | |
| |||
285 | 292 | | |
286 | 293 | | |
287 | 294 | | |
288 | | - | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
289 | 303 | | |
290 | | - | |
| 304 | + | |
291 | 305 | | |
292 | 306 | | |
293 | 307 | | |
| |||
0 commit comments