Skip to content

Commit ae5f570

Browse files
committed
modify code
1 parent 3fa1c64 commit ae5f570

2 files changed

Lines changed: 52 additions & 15 deletions

File tree

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/source/dataregion/realtime/disruptor/BatchEventProcessor.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ public void run() {
7171
T event = null;
7272
long nextSequence = sequence.get() + 1L;
7373

74-
// CORE: Batch processing loop (MUST keep identical logic)
7574
while (running) {
7675
try {
7776
// Wait for available sequence

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/source/dataregion/realtime/disruptor/MultiProducerSequencer.java

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,51 @@
1919

2020
package org.apache.iotdb.db.pipe.source.dataregion.realtime.disruptor;
2121

22+
import java.util.concurrent.atomic.AtomicIntegerArray;
2223
import java.util.concurrent.locks.LockSupport;
2324

2425
public final class MultiProducerSequencer {
2526

27+
/** Ring buffer size (must be power of 2) - immutable after construction */
2628
private final int bufferSize;
29+
30+
/**
31+
* Producer cursor tracking highest claimed sequence Updated via CAS in next() method Volatile
32+
* reads/writes handled by Sequence class
33+
*/
2734
private final Sequence cursor = new Sequence();
35+
36+
/**
37+
* Array of consumer sequences for backpressure control MUST be volatile for safe publication when
38+
* modified by SequenceGroups Array reference is replaced atomically via
39+
* AtomicReferenceFieldUpdater
40+
*/
2841
volatile Sequence[] gatingSequences;
2942

30-
// CRITICAL: Cache to avoid repeated getMinimumSequence calls
43+
/**
44+
* Cached minimum gating sequence to reduce contention Updated opportunistically in next() to
45+
* avoid expensive array scan Does not need to be perfectly accurate (conservative is safe)
46+
*/
3147
private final Sequence gatingSequenceCache = new Sequence();
3248

33-
// CRITICAL: Available buffer tracks published sequences
34-
private final int[] availableBuffer;
49+
/**
50+
* CRITICAL: Availability flags for tracking published sequences
51+
*
52+
* <p>Handles out-of-order publishing in multi-producer scenario: - Thread A claims seq 10, still
53+
* writing - Thread B claims seq 11, finishes and publishes - Consumer MUST wait for seq 10 before
54+
* reading seq 11
55+
*
56+
* <p>Memory visibility guarantees: - Writers use lazySet() for store-store barrier (cheaper than
57+
* volatile write) - Readers use get() for volatile read (ensures visibility across threads)
58+
*
59+
* <p>AtomicIntegerArray provides same semantics as Unsafe without reflection
60+
*/
61+
private final AtomicIntegerArray availableBuffer;
62+
63+
/** Mask for fast modulo: sequence & indexMask == sequence % bufferSize */
3564
private final int indexMask;
65+
66+
/** Shift for calculating wrap count: sequence >>> indexShift */
3667
private final int indexShift;
3768

3869
public MultiProducerSequencer(int bufferSize, Sequence[] gatingSequences) {
@@ -45,7 +76,7 @@ public MultiProducerSequencer(int bufferSize, Sequence[] gatingSequences) {
4576

4677
this.bufferSize = bufferSize;
4778
this.gatingSequences = gatingSequences != null ? gatingSequences : new Sequence[0];
48-
this.availableBuffer = new int[bufferSize];
79+
this.availableBuffer = new AtomicIntegerArray(bufferSize);
4980
this.indexMask = bufferSize - 1;
5081
this.indexShift = log2(bufferSize);
5182

@@ -73,8 +104,8 @@ public long next(int n) {
73104
current = cursor.get();
74105
next = current + n;
75106

76-
long wrapPoint = next - bufferSize;
77-
long cachedGatingSequence = gatingSequenceCache.get();
107+
final long wrapPoint = next - bufferSize;
108+
final long cachedGatingSequence = gatingSequenceCache.get();
78109

79110
if (wrapPoint > cachedGatingSequence || cachedGatingSequence > current) {
80111
long gatingSequence = Sequence.getMinimumSequence(gatingSequences, current);
@@ -105,11 +136,14 @@ public void publish(long lo, long hi) {
105136
}
106137
}
107138

108-
/** CORE: Check if available - MUST use Unsafe.getIntVolatile */
139+
/**
140+
* CORE: Check if sequence is available for consumption Uses volatile read to ensure visibility of
141+
* published sequences
142+
*/
109143
public boolean isAvailable(long sequence) {
110144
int index = calculateIndex(sequence);
111145
int flag = calculateAvailabilityFlag(sequence);
112-
return availableBuffer[index] == flag;
146+
return availableBuffer.get(index) == flag;
113147
}
114148

115149
/** CORE: Get highest published - exact same algorithm */
@@ -178,25 +212,29 @@ public SequenceBarrier newBarrier(Sequence... sequencesToTrack) {
178212

179213
/** Initialize available buffer */
180214
private void initialiseAvailableBuffer() {
181-
for (int i = availableBuffer.length - 1; i != 0; i--) {
215+
for (int i = availableBuffer.length() - 1; i != 0; i--) {
182216
setAvailableBufferValue(i, -1);
183217
}
184218
setAvailableBufferValue(0, -1);
185219
}
186220

187221
/**
188-
* CORE: Set available - MUST use Unsafe.putOrderedInt
222+
* CORE: Mark sequence as available for consumption
189223
*
190-
* <p>putOrderedInt provides: - Store-store barrier (not full fence) - Cheaper than volatile write
191-
* - Sufficient for this use case
224+
* <p>Uses lazySet() which provides: - Store-store barrier (ensures all prior writes are visible)
225+
* - Cheaper than full volatile write (no store-load barrier) - Sufficient for this use case
226+
* (readers use volatile get)
192227
*/
193228
private void setAvailable(final long sequence) {
194229
setAvailableBufferValue(calculateIndex(sequence), calculateAvailabilityFlag(sequence));
195230
}
196231

197-
/** CRITICAL: Use Unsafe.putOrderedInt for correct memory semantics */
232+
/**
233+
* Set availability flag with release semantics lazySet() ensures previous event writes are
234+
* visible before flag update
235+
*/
198236
private void setAvailableBufferValue(int index, int flag) {
199-
availableBuffer[index] = flag;
237+
availableBuffer.lazySet(index, flag);
200238
}
201239

202240
/** Calculate availability flag */

0 commit comments

Comments
 (0)