Skip to content

Commit 2cd3b07

Browse files
authored
[Pipe] Fix stalled region ordering after TsFile-to-Tablet conversion (#19243)
* [Pipe] Fix stalled region ordering after TsFile-to-Tablet conversion * [Pipe] Track processed tablet descendants for TsFile completion
1 parent 47b08dc commit 2cd3b07

4 files changed

Lines changed: 347 additions & 19 deletions

File tree

‎iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/agent/task/connection/PipeEventCollector.java‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -286,11 +286,11 @@ private void collectEvent(final Event event) {
286286
}
287287

288288
if (event instanceof PipeRawTabletInsertionEvent
289-
&& ((PipeRawTabletInsertionEvent) event).getSourceEvent()
290-
instanceof PipeTsFileInsertionEvent) {
289+
&& ((PipeRawTabletInsertionEvent) event).getSourceTsFileInsertionEvent() != null) {
291290
// Register before publishing to the queue so a concurrent queue cleanup can report a
292291
// generated tablet as discarded instead of racing with registration.
293-
((PipeTsFileInsertionEvent) ((PipeRawTabletInsertionEvent) event).getSourceEvent())
292+
((PipeRawTabletInsertionEvent) event)
293+
.getSourceTsFileInsertionEvent()
294294
.registerGeneratedTabletInsertionEvent((PipeRawTabletInsertionEvent) event);
295295
}
296296

‎iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/event/common/tablet/PipeRawTabletInsertionEvent.java‎

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ public class PipeRawTabletInsertionEvent extends PipeInsertionEvent
6666
private final boolean isAligned;
6767

6868
private final EnrichedEvent sourceEvent;
69+
private final PipeTsFileInsertionEvent sourceTsFileInsertionEvent;
6970
private final AtomicBoolean generatedEventRegisteredWithSource = new AtomicBoolean(false);
7071
private final AtomicBoolean generatedEventOutcomeReported = new AtomicBoolean(false);
7172
private boolean needToReport;
@@ -115,6 +116,12 @@ private PipeRawTabletInsertionEvent(
115116
this.tablet = Objects.requireNonNull(tablet);
116117
this.isAligned = isAligned;
117118
this.sourceEvent = sourceEvent;
119+
this.sourceTsFileInsertionEvent =
120+
sourceEvent instanceof PipeTsFileInsertionEvent
121+
? (PipeTsFileInsertionEvent) sourceEvent
122+
: sourceEvent instanceof PipeRawTabletInsertionEvent
123+
? ((PipeRawTabletInsertionEvent) sourceEvent).getSourceTsFileInsertionEvent()
124+
: null;
118125
this.needToReport = needToReport;
119126
inheritSourceEventReportSkippingIfNecessary();
120127

@@ -135,18 +142,17 @@ private PipeRawTabletInsertionEvent(
135142
parentMemoryBlock);
136143
this.allocatedMemoryBlock.setAssigner(this);
137144

138-
if (needToReport || sourceEvent instanceof PipeTsFileInsertionEvent) {
145+
if (needToReport || sourceTsFileInsertionEvent != null) {
139146
addOnCommittedHook(
140147
() -> {
141148
// The last generated tablet still owns the progress-index cleanup. Other generated
142149
// tablets only contribute to the transfer completion of their source TsFile.
143150
if (shouldReportOnCommit && needToReport) {
144151
eliminateProgressIndex();
145152
}
146-
if (sourceEvent instanceof PipeTsFileInsertionEvent
153+
if (sourceTsFileInsertionEvent != null
147154
&& generatedEventOutcomeReported.compareAndSet(false, true)) {
148-
((PipeTsFileInsertionEvent) sourceEvent)
149-
.markGeneratedTabletInsertionEventAsTransferred();
155+
sourceTsFileInsertionEvent.markGeneratedTabletInsertionEventAsTransferred();
150156
}
151157
});
152158
}
@@ -366,8 +372,8 @@ public boolean clearReferenceCount(final String holderMessage) {
366372
final boolean cleared = super.clearReferenceCount(holderMessage);
367373
if (generatedEventRegisteredWithSource.get()
368374
&& generatedEventOutcomeReported.compareAndSet(false, true)
369-
&& sourceEvent instanceof PipeTsFileInsertionEvent) {
370-
((PipeTsFileInsertionEvent) sourceEvent).markGeneratedTabletInsertionEventAsDiscarded();
375+
&& sourceTsFileInsertionEvent != null) {
376+
sourceTsFileInsertionEvent.markGeneratedTabletInsertionEventAsDiscarded();
371377
}
372378
return cleared;
373379
}
@@ -494,6 +500,11 @@ public EnrichedEvent getSourceEvent() {
494500
return sourceEvent;
495501
}
496502

503+
/** Returns the original TsFile, including when a processor has transformed its tablets. */
504+
public PipeTsFileInsertionEvent getSourceTsFileInsertionEvent() {
505+
return sourceTsFileInsertionEvent;
506+
}
507+
497508
@Override
498509
public boolean isShouldReportOnCommit() {
499510
return shouldReportOnCommit && needToReport;

‎iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/event/common/tsfile/PipeTsFileInsertionEvent.java‎

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,18 @@ public boolean internallyDecreaseResourceReferenceCount(final String holderMessa
592592
return isSuccessful;
593593
}
594594

595+
@Override
596+
public synchronized boolean decreaseReferenceCount(
597+
final String holderMessage, final boolean shouldReport) {
598+
final boolean decreased = super.decreaseReferenceCount(holderMessage, shouldReport);
599+
if (decreased && isReleased() && Objects.isNull(getCommitterKey())) {
600+
// A split TsFile may only commit its generated tablets. Releasing that original event ends
601+
// its processing, but the transfer hook must still wait for parsing and all tablet commits.
602+
markAsTransferredIfGeneratedTabletEventsCompleted();
603+
}
604+
return decreased;
605+
}
606+
595607
@Override
596608
public boolean clearReferenceCount(final String holderMessage) {
597609
final boolean cleared = super.clearReferenceCount(holderMessage);
@@ -698,14 +710,12 @@ private void markAsTransferredIfGeneratedTabletEventsCompleted() {
698710
final boolean generationBoundaryReached =
699711
!generatedTabletInsertionEventsParsingStarted.get()
700712
|| generatedTabletInsertionEventsParsingCompleted.get();
701-
// The normal processor path does not retain a tablet iterable unless parsing has explicitly
702-
// been marked as started. In that path, registering the generated tablets and reaching the
703-
// generation boundary is sufficient to establish the transfer boundary (the source TsFile
704-
// commit may be reported separately or may be intentionally skipped). Once an iterable has
705-
// been retained, however, the source TsFile commit must also be observed before the generated
706-
// tablet counts can release the TsFile. This distinction keeps deferred parsing safe without
707-
// delaying the established non-deferred path.
708-
if ((isTsFileEventCommitted.get() || !generatedTabletInsertionEventsParsingStarted.get())
713+
// The collector only assigns commit ids to the generated tablets when it splits a TsFile.
714+
// The original event then finishes processing without entering the commit queue. If the
715+
// original event does enter that queue, resource release alone must not bypass its commit.
716+
if ((isTsFileEventCommitted.get()
717+
|| (isReleased() && Objects.isNull(getCommitterKey()))
718+
|| !generatedTabletInsertionEventsParsingStarted.get())
709719
&& generationBoundaryReached
710720
&& transferredGeneratedTabletInsertionEventCount.get()
711721
+ discardedGeneratedTabletInsertionEventCount.get()

0 commit comments

Comments
 (0)