Skip to content

Commit 75bacb1

Browse files
committed
Fix consensus subscription replay dedup
1 parent aa6810e commit 75bacb1

14 files changed

Lines changed: 142 additions & 158 deletions

File tree

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2850,7 +2850,8 @@ public SettableFuture<ConfigTaskResult> createTopic(
28502850
PipeDataNodeAgent.plugin()
28512851
.validate(
28522852
"fakePipeName",
2853-
// TODO: currently use root to create topic
2853+
// Topic validation uses the admin name because topic creation has no user context
2854+
// here.
28542855
temporaryTopicMeta.generateExtractorAttributes(
28552856
CommonDescriptor.getInstance().getConfig().getDefaultAdminName()),
28562857
temporaryTopicMeta.generateProcessorAttributes(),

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/wal/io/ProgressWALReader.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ public long getCurrentEntryLocalSeq() {
7070
return delegate.getCurrentEntryLocalSeq();
7171
}
7272

73+
public long getCurrentEntrySearchIndex() {
74+
return delegate.getCurrentEntrySearchIndex();
75+
}
76+
7377
public int getCurrentEntryIndex() {
7478
return delegate.getCurrentEntryIndex();
7579
}

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/wal/io/WALByteBufReader.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
package org.apache.iotdb.db.storageengine.dataregion.wal.io;
2121

22+
import org.apache.iotdb.consensus.iot.log.ConsensusReqReader;
2223
import org.apache.iotdb.db.storageengine.dataregion.wal.buffer.WALEntry;
2324

2425
import java.io.Closeable;
@@ -144,6 +145,14 @@ public long getCurrentEntryLocalSeq() {
144145
return metaData.getFirstSearchIndex() + currentEntryIndex;
145146
}
146147

148+
public long getCurrentEntrySearchIndex() {
149+
final long firstSearchIndex = metaData.getFirstSearchIndex();
150+
if (firstSearchIndex == ConsensusReqReader.DEFAULT_SEARCH_INDEX) {
151+
return ConsensusReqReader.DEFAULT_SEARCH_INDEX;
152+
}
153+
return firstSearchIndex + currentEntryIndex;
154+
}
155+
147156
/** Returns the current entry index (0-based). */
148157
public int getCurrentEntryIndex() {
149158
return currentEntryIndex;

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/wal/utils/WALFileUtils.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,10 @@ public static long findSearchIndexAfterWriterProgress(
306306
}
307307

308308
private interface SearchableRequestVisitor {
309+
/**
310+
* @return {@code true} to continue scanning the following searchable requests, {@code false} to
311+
* stop immediately.
312+
*/
309313
boolean onRequest(SearchableRequestMeta request);
310314
}
311315

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/subscription/agent/SubscriptionBrokerAgent.java

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -734,13 +734,7 @@ public void unbindPrefetchingQueue(final String consumerGroupId, final String to
734734
"Subscription: broker bound to consumer group [{}] does not exist", consumerGroupId);
735735
return;
736736
}
737-
if (broker instanceof ConsensusSubscriptionBroker) {
738-
((ConsensusSubscriptionBroker) broker).unbindConsensusPrefetchingQueue(topicName);
739-
} else if (broker instanceof SubscriptionBroker) {
740-
((SubscriptionBroker) broker).unbindPrefetchingQueue(topicName);
741-
} else {
742-
broker.removeQueue(topicName);
743-
}
737+
broker.unbind(topicName);
744738
prefetchingQueueCount.invalidate();
745739
}
746740

@@ -789,11 +783,7 @@ public Map<String, Long> getConsensusLagSummary() {
789783
for (final Map.Entry<String, List<ISubscriptionBroker>> entry :
790784
consumerGroupIdToBrokers.entrySet()) {
791785
for (final ISubscriptionBroker broker : entry.getValue()) {
792-
if (!(broker instanceof ConsensusSubscriptionBroker)) {
793-
continue;
794-
}
795-
for (final Map.Entry<String, Long> lag :
796-
((ConsensusSubscriptionBroker) broker).getLagSummary().entrySet()) {
786+
for (final Map.Entry<String, Long> lag : broker.getLagSummary().entrySet()) {
797787
result.put(entry.getKey() + "/" + lag.getKey(), lag.getValue());
798788
}
799789
}

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/subscription/broker/ConsensusSubscriptionBroker.java

Lines changed: 15 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -210,9 +210,7 @@ public List<SubscriptionEvent> pollTablets(
210210
return Collections.emptyList();
211211
}
212212

213-
final ConsensusPrefetchingQueue assignedQueue =
214-
getAssignedQueueForConsumer(
215-
queues, topicName, consumerId, commitContext.getRegionId(), "pollTablets");
213+
final ConsensusPrefetchingQueue assignedQueue = getQueueForCommitContext(queues, commitContext);
216214
if (Objects.isNull(assignedQueue)) {
217215
return Collections.emptyList();
218216
}
@@ -245,8 +243,7 @@ public List<SubscriptionCommitContext> commit(
245243
}
246244

247245
final ConsensusPrefetchingQueue assignedQueue =
248-
getAssignedQueueForConsumer(
249-
queues, topicName, consumerId, commitContext.getRegionId(), nack ? "nack" : "ack");
246+
getQueueForCommitContext(queues, commitContext);
250247
boolean handled = false;
251248
if (Objects.nonNull(assignedQueue)) {
252249
final boolean success;
@@ -285,8 +282,7 @@ public int refreshInFlightEventLeases(
285282
}
286283

287284
final ConsensusPrefetchingQueue assignedQueue =
288-
getAssignedQueueForConsumer(
289-
queues, topicName, consumerId, commitContext.getRegionId(), "refresh lease");
285+
getQueueForCommitContext(queues, commitContext);
290286
if (Objects.nonNull(assignedQueue)
291287
&& assignedQueue.refreshInFlightEventLease(consumerId, commitContext)) {
292288
refreshedCount++;
@@ -537,34 +533,19 @@ private List<ConsensusPrefetchingQueue> buildPollOrderForAssignedQueues(
537533
return orderedQueues;
538534
}
539535

540-
private ConsensusPrefetchingQueue getAssignedQueueForConsumer(
541-
final List<ConsensusPrefetchingQueue> queues,
542-
final String topicName,
543-
final String consumerId,
544-
final String regionId,
545-
final String action) {
546-
final TopicOwnershipSnapshot ownershipSnapshot =
547-
refreshAndGetTopicOwnership(topicName, queues, consumerId);
536+
private ConsensusPrefetchingQueue getQueueForCommitContext(
537+
final List<ConsensusPrefetchingQueue> queues, final SubscriptionCommitContext commitContext) {
538+
final String regionId = commitContext.getRegionId();
548539
for (final ConsensusPrefetchingQueue queue : queues) {
549540
if (queue.isClosed()) {
550541
continue;
551542
}
552-
if (!regionId.isEmpty() && !regionId.equals(queue.getConsensusGroupId().toString())) {
543+
if (Objects.nonNull(regionId)
544+
&& !regionId.isEmpty()
545+
&& !regionId.equals(queue.getConsensusGroupId().toString())) {
553546
continue;
554547
}
555-
if (consumerId.equals(
556-
ownershipSnapshot.getOwnerConsumerId(queue.getConsensusGroupId().toString()))) {
557-
return queue;
558-
}
559-
LOGGER.debug(
560-
"ConsensusSubscriptionBroker [{}]: consumer [{}] skipped {} on topic [{}], region [{}] is currently owned by [{}]",
561-
brokerId,
562-
consumerId,
563-
action,
564-
topicName,
565-
queue.getConsensusGroupId(),
566-
ownershipSnapshot.getOwnerConsumerId(queue.getConsensusGroupId().toString()));
567-
return null;
548+
return queue;
568549
}
569550
return null;
570551
}
@@ -657,6 +638,11 @@ public void unbindConsensusPrefetchingQueue(final String topicName) {
657638
closeAndRemoveConsensusPrefetchingQueues(topicName, true);
658639
}
659640

641+
@Override
642+
public void unbind(final String topicName) {
643+
unbindConsensusPrefetchingQueue(topicName);
644+
}
645+
660646
public int unbindByRegion(final ConsensusGroupId regionId) {
661647
final List<ConsensusPrefetchingQueue> queuesToClose = new ArrayList<>();
662648
final List<String> topicNamesToLog = new ArrayList<>();

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/subscription/broker/ISubscriptionBroker.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@ default boolean acceptsCommitContext(final SubscriptionCommitContext commitConte
7979

8080
int getQueueCount();
8181

82+
default Map<String, Long> getLagSummary() {
83+
return Collections.emptyMap();
84+
}
85+
86+
void unbind(String topicName);
87+
8288
void removeQueue(String topicName);
8389

8490
boolean isEmpty();

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/subscription/broker/SubscriptionBroker.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,11 @@ public void unbindPrefetchingQueue(final String topicName) {
496496
brokerId);
497497
}
498498

499+
@Override
500+
public void unbind(final String topicName) {
501+
unbindPrefetchingQueue(topicName);
502+
}
503+
499504
@Override
500505
public void removeQueue(final String topicName) {
501506
removePrefetchingQueue(topicName);

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/subscription/broker/consensus/ConsensusLogToTabletConverter.java

Lines changed: 10 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -297,25 +297,17 @@ private List<Tablet> convertInsertTabletNode(final InsertTabletNode node) {
297297
schemas.add(new MeasurementSchema(measurements[colIdx], dataTypes[colIdx]));
298298
}
299299

300-
// Reuse complete tablets on the server-side read path. Column filtering changes tablet shape
301-
// and still needs copies for the selected columns.
302-
final long[] newTimes = allColumnsMatch ? times : Arrays.copyOf(times, rowCount);
300+
// Column filtering changes only the tablet shape. The selected value arrays come from WAL
301+
// InsertNodes and are reused by the subscription read path.
302+
final long[] newTimes = times;
303303
final Object[] newColumns = new Object[columnCount];
304304
final BitMap[] newBitMaps = new BitMap[columnCount];
305305

306306
for (int i = 0; i < columnCount; i++) {
307307
final int originalColIdx = allColumnsMatch ? i : matchedColumnIndices.get(i);
308-
newColumns[i] =
309-
allColumnsMatch
310-
? columns[originalColIdx]
311-
: copyColumnArray(dataTypes[originalColIdx], columns[originalColIdx], rowCount);
308+
newColumns[i] = columns[originalColIdx];
312309
if (bitMaps != null && bitMaps[originalColIdx] != null) {
313-
if (allColumnsMatch) {
314-
newBitMaps[i] = bitMaps[originalColIdx];
315-
} else {
316-
newBitMaps[i] = new BitMap(rowCount);
317-
BitMap.copyOfRange(bitMaps[originalColIdx], 0, newBitMaps[i], 0, rowCount);
318-
}
310+
newBitMaps[i] = bitMaps[originalColIdx];
319311
}
320312
}
321313

@@ -534,25 +526,17 @@ private List<Tablet> convertRelationalInsertTabletNode(final RelationalInsertTab
534526
columnTypes.add(toTsFileColumnCategory(node.getColumnCategories(), originalColIdx));
535527
}
536528

537-
// Reuse complete tablets on the server-side read path. Column filtering changes tablet shape
538-
// and still needs copies for the selected columns.
539-
final long[] newTimes = allColumnsMatch ? times : Arrays.copyOf(times, rowCount);
529+
// Column filtering changes only the tablet shape. The selected value arrays come from WAL
530+
// InsertNodes and are reused by the subscription read path.
531+
final long[] newTimes = times;
540532
final Object[] newColumns = new Object[columnCount];
541533
final BitMap[] newBitMaps = new BitMap[columnCount];
542534

543535
for (int colIdx = 0; colIdx < columnCount; colIdx++) {
544536
final int originalColIdx = allColumnsMatch ? colIdx : matchedColumnIndices.get(colIdx);
545-
newColumns[colIdx] =
546-
allColumnsMatch
547-
? columns[originalColIdx]
548-
: copyColumnArray(dataTypes[originalColIdx], columns[originalColIdx], rowCount);
537+
newColumns[colIdx] = columns[originalColIdx];
549538
if (bitMaps != null && bitMaps[originalColIdx] != null) {
550-
if (allColumnsMatch) {
551-
newBitMaps[colIdx] = bitMaps[originalColIdx];
552-
} else {
553-
newBitMaps[colIdx] = new BitMap(rowCount);
554-
BitMap.copyOfRange(bitMaps[originalColIdx], 0, newBitMaps[colIdx], 0, rowCount);
555-
}
539+
newBitMaps[colIdx] = bitMaps[originalColIdx];
556540
}
557541
}
558542

@@ -655,65 +639,6 @@ private ColumnCategory toTsFileColumnCategory(
655639
: ColumnCategory.FIELD;
656640
}
657641

658-
/**
659-
* Bulk-copies a typed column array using System.arraycopy. Returns a new array of the same type
660-
* containing the first {@code rowCount} elements.
661-
*/
662-
private Object copyColumnArray(
663-
final TSDataType dataType, final Object sourceColumn, final int rowCount) {
664-
switch (dataType) {
665-
case BOOLEAN:
666-
{
667-
final boolean[] src = (boolean[]) sourceColumn;
668-
final boolean[] dst = new boolean[rowCount];
669-
System.arraycopy(src, 0, dst, 0, rowCount);
670-
return dst;
671-
}
672-
case INT32:
673-
case DATE:
674-
{
675-
final int[] src = (int[]) sourceColumn;
676-
final int[] dst = new int[rowCount];
677-
System.arraycopy(src, 0, dst, 0, rowCount);
678-
return dst;
679-
}
680-
case INT64:
681-
case TIMESTAMP:
682-
{
683-
final long[] src = (long[]) sourceColumn;
684-
final long[] dst = new long[rowCount];
685-
System.arraycopy(src, 0, dst, 0, rowCount);
686-
return dst;
687-
}
688-
case FLOAT:
689-
{
690-
final float[] src = (float[]) sourceColumn;
691-
final float[] dst = new float[rowCount];
692-
System.arraycopy(src, 0, dst, 0, rowCount);
693-
return dst;
694-
}
695-
case DOUBLE:
696-
{
697-
final double[] src = (double[]) sourceColumn;
698-
final double[] dst = new double[rowCount];
699-
System.arraycopy(src, 0, dst, 0, rowCount);
700-
return dst;
701-
}
702-
case TEXT:
703-
case BLOB:
704-
case STRING:
705-
{
706-
final Binary[] src = (Binary[]) sourceColumn;
707-
final Binary[] dst = new Binary[rowCount];
708-
System.arraycopy(src, 0, dst, 0, rowCount);
709-
return dst;
710-
}
711-
default:
712-
LOGGER.warn("Unsupported data type for bulk copy: {}", dataType);
713-
return sourceColumn;
714-
}
715-
}
716-
717642
/**
718643
* Adds a single value to the tablet at the specified position.
719644
*

0 commit comments

Comments
 (0)