32
32
import static org .apache .pulsar .common .util .Runnables .catchingAndLoggingThrowables ;
33
33
import com .google .common .annotations .VisibleForTesting ;
34
34
import io .netty .buffer .ByteBuf ;
35
+ import io .netty .util .AbstractReferenceCounted ;
35
36
import io .netty .util .Recycler ;
36
37
import io .netty .util .Recycler .Handle ;
37
38
import io .netty .util .ReferenceCountUtil ;
39
+ import io .netty .util .ReferenceCounted ;
38
40
import io .netty .util .Timeout ;
39
41
import io .netty .util .TimerTask ;
40
42
import io .netty .util .concurrent .ScheduledFuture ;
@@ -485,6 +487,7 @@ public void sendAsync(Message<?> message, SendCallback callback) {
485
487
sequenceId = msgMetadata .getSequenceId ();
486
488
}
487
489
String uuid = totalChunks > 1 ? String .format ("%s-%d" , producerName , sequenceId ) : null ;
490
+ ChunkedMessageCtx chunkedMessageCtx = totalChunks > 1 ? ChunkedMessageCtx .get (totalChunks ) : null ;
488
491
byte [] schemaVersion = totalChunks > 1 && msg .getMessageBuilder ().hasSchemaVersion () ?
489
492
msg .getMessageBuilder ().getSchemaVersion () : null ;
490
493
for (int chunkId = 0 ; chunkId < totalChunks ; chunkId ++) {
@@ -497,7 +500,7 @@ public void sendAsync(Message<?> message, SendCallback callback) {
497
500
}
498
501
serializeAndSendMessage (msg , payload , sequenceId , uuid , chunkId , totalChunks ,
499
502
readStartIndex , ClientCnx .getMaxMessageSize (), compressedPayload , compressed ,
500
- compressedPayload .readableBytes (), uncompressedSize , callback );
503
+ compressedPayload .readableBytes (), uncompressedSize , callback , chunkedMessageCtx );
501
504
readStartIndex = ((chunkId + 1 ) * ClientCnx .getMaxMessageSize ());
502
505
}
503
506
}
@@ -517,7 +520,7 @@ public int getNumOfPartitions() {
517
520
private void serializeAndSendMessage (MessageImpl <?> msg , ByteBuf payload ,
518
521
long sequenceId , String uuid , int chunkId , int totalChunks , int readStartIndex , int chunkMaxSizeInBytes , ByteBuf compressedPayload ,
519
522
boolean compressed , int compressedPayloadSize ,
520
- int uncompressedSize , SendCallback callback ) throws IOException , InterruptedException {
523
+ int uncompressedSize , SendCallback callback , ChunkedMessageCtx chunkedMessageCtx ) throws IOException , InterruptedException {
521
524
ByteBuf chunkPayload = compressedPayload ;
522
525
MessageMetadata msgMetadata = msg .getMessageBuilder ();
523
526
if (totalChunks > 1 && TopicName .get (topic ).isPersistent ()) {
@@ -612,6 +615,7 @@ private void serializeAndSendMessage(MessageImpl<?> msg, ByteBuf payload,
612
615
op .totalChunks = totalChunks ;
613
616
op .chunkId = chunkId ;
614
617
}
618
+ op .chunkedMessageCtx = chunkedMessageCtx ;
615
619
lastSendFuture = callback .getFuture ();
616
620
processOpSendMsg (op );
617
621
}
@@ -1022,6 +1026,16 @@ void ackReceived(ClientCnx cnx, long sequenceId, long highestSequenceId, long le
1022
1026
OpSendMsg finalOp = op ;
1023
1027
LAST_SEQ_ID_PUBLISHED_UPDATER .getAndUpdate (this , last -> Math .max (last , getHighestSequenceId (finalOp )));
1024
1028
op .setMessageId (ledgerId , entryId , partitionIndex );
1029
+ if (op .totalChunks > 1 ) {
1030
+ if (op .chunkId == 0 ) {
1031
+ op .chunkedMessageCtx .firstChunkMessageId = new MessageIdImpl (ledgerId , entryId , partitionIndex );
1032
+ } else if (op .chunkId == op .totalChunks - 1 ) {
1033
+ op .chunkedMessageCtx .lastChunkMessageId = new MessageIdImpl (ledgerId , entryId , partitionIndex );
1034
+ op .setMessageId (op .chunkedMessageCtx .getChunkMessageId ());
1035
+ }
1036
+ }
1037
+
1038
+
1025
1039
// if message is chunked then call callback only on last chunk
1026
1040
if (op .totalChunks <= 1 || (op .chunkId == op .totalChunks - 1 )) {
1027
1041
try {
@@ -1169,12 +1183,54 @@ protected boolean verifyLocalBufferIsNotCorrupted(OpSendMsg op) {
1169
1183
}
1170
1184
}
1171
1185
1186
+ static class ChunkedMessageCtx extends AbstractReferenceCounted {
1187
+ protected MessageIdImpl firstChunkMessageId ;
1188
+ protected MessageIdImpl lastChunkMessageId ;
1189
+
1190
+ public ChunkMessageIdImpl getChunkMessageId () {
1191
+ return new ChunkMessageIdImpl (firstChunkMessageId , lastChunkMessageId );
1192
+ }
1193
+
1194
+ private static final Recycler <ProducerImpl .ChunkedMessageCtx > RECYCLER =
1195
+ new Recycler <ProducerImpl .ChunkedMessageCtx >() {
1196
+ protected ProducerImpl .ChunkedMessageCtx newObject (
1197
+ Recycler .Handle <ProducerImpl .ChunkedMessageCtx > handle ) {
1198
+ return new ProducerImpl .ChunkedMessageCtx (handle );
1199
+ }
1200
+ };
1201
+
1202
+ public static ChunkedMessageCtx get (int totalChunks ) {
1203
+ ChunkedMessageCtx chunkedMessageCtx = RECYCLER .get ();
1204
+ chunkedMessageCtx .setRefCnt (totalChunks );
1205
+ return chunkedMessageCtx ;
1206
+ }
1207
+
1208
+ private final Handle <ProducerImpl .ChunkedMessageCtx > recyclerHandle ;
1209
+
1210
+ private ChunkedMessageCtx (Handle <ChunkedMessageCtx > recyclerHandle ) {
1211
+ this .recyclerHandle = recyclerHandle ;
1212
+ }
1213
+
1214
+ @ Override
1215
+ protected void deallocate () {
1216
+ this .firstChunkMessageId = null ;
1217
+ this .lastChunkMessageId = null ;
1218
+ recyclerHandle .recycle (this );
1219
+ }
1220
+
1221
+ @ Override
1222
+ public ReferenceCounted touch (Object hint ) {
1223
+ return this ;
1224
+ }
1225
+ }
1226
+
1172
1227
protected static final class OpSendMsg {
1173
1228
MessageImpl <?> msg ;
1174
1229
List <MessageImpl <?>> msgs ;
1175
1230
ByteBufPair cmd ;
1176
1231
SendCallback callback ;
1177
1232
Runnable rePopulate ;
1233
+ ChunkedMessageCtx chunkedMessageCtx ;
1178
1234
long uncompressedSize ;
1179
1235
long sequenceId ;
1180
1236
long createdAt ;
@@ -1277,6 +1333,8 @@ void recycle() {
1277
1333
retryCount = 0 ;
1278
1334
batchSizeByte = 0 ;
1279
1335
numMessagesInBatch = 1 ;
1336
+ ReferenceCountUtil .safeRelease (chunkedMessageCtx );
1337
+ chunkedMessageCtx = null ;
1280
1338
recyclerHandle .recycle (this );
1281
1339
}
1282
1340
@@ -1299,6 +1357,12 @@ void setMessageId(long ledgerId, long entryId, int partitionIndex) {
1299
1357
}
1300
1358
}
1301
1359
1360
+ void setMessageId (ChunkMessageIdImpl chunkMessageId ) {
1361
+ if (msg != null ) {
1362
+ msg .setMessageId (chunkMessageId );
1363
+ }
1364
+ }
1365
+
1302
1366
private OpSendMsg (Handle <OpSendMsg > recyclerHandle ) {
1303
1367
this .recyclerHandle = recyclerHandle ;
1304
1368
}
0 commit comments