Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b8734d1

Browse files
stIncMalejyemin
andcommittedOct 22, 2024·
Create DualMessageSequences abstraction
This makes `CommandMessage` generic for any command with two sequences. The new abstraction adds: * The sequence identifiers for each sequence. * A field name validator for both sequences. * A `List<BsonElement>`` for any extra elements required by the splitting logic, so that `txnNumber` doesn't have to be treated specially. Make `SplittablePayload` extend `OpMsgSequence`. This brings SplittablePayload closer in design to `DualMessageSequences`, reducing a potential source of confusion for future readers. JAVA-5529 Co-authored-by: Jeff Yemin <[email protected]>
1 parent ea0633e commit b8734d1

File tree

14 files changed

+264
-231
lines changed

14 files changed

+264
-231
lines changed
 

‎driver-core/src/main/com/mongodb/internal/connection/BsonWriterHelper.java

Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616

1717
package com.mongodb.internal.connection;
1818

19-
import com.mongodb.internal.operation.ClientBulkWriteOperation.ClientBulkWriteCommand;
20-
import com.mongodb.internal.operation.ClientBulkWriteOperation.ClientBulkWriteCommand.OpsAndNsInfo.WritersProviderAndLimitsChecker;
19+
import com.mongodb.internal.connection.DualMessageSequences.EncodeDocumentsResult;
20+
import com.mongodb.internal.connection.DualMessageSequences.WritersProviderAndLimitsChecker;
2121
import com.mongodb.internal.validator.NoOpFieldNameValidator;
2222
import com.mongodb.lang.Nullable;
2323
import org.bson.BsonBinaryWriter;
@@ -38,6 +38,9 @@
3838
import java.util.List;
3939

4040
import static com.mongodb.assertions.Assertions.assertTrue;
41+
import static com.mongodb.internal.connection.DualMessageSequences.WritersProviderAndLimitsChecker.WriteResult.FAIL_LIMIT_EXCEEDED;
42+
import static com.mongodb.internal.connection.DualMessageSequences.WritersProviderAndLimitsChecker.WriteResult.OK_LIMIT_NOT_REACHED;
43+
import static com.mongodb.internal.connection.DualMessageSequences.WritersProviderAndLimitsChecker.WriteResult.OK_LIMIT_REACHED;
4144
import static com.mongodb.internal.connection.MessageSettings.DOCUMENT_HEADROOM_SIZE;
4245
import static java.lang.String.format;
4346
import static org.bson.codecs.configuration.CodecRegistries.fromProviders;
@@ -98,46 +101,46 @@ static void writePayload(final BsonWriter writer, final BsonOutput bsonOutput, f
98101
}
99102

100103
/**
101-
* @return See {@link ClientBulkWriteCommand.OpsAndNsInfo#encode(WritersProviderAndLimitsChecker)}.
104+
* @return See {@link DualMessageSequences#encodeDocuments(WritersProviderAndLimitsChecker)}.
102105
*/
103-
static ClientBulkWriteCommand.OpsAndNsInfo.EncodeResult writeOpsAndNsInfo(
104-
final ClientBulkWriteCommand.OpsAndNsInfo opsAndNsInfo,
106+
static EncodeDocumentsResult writeDocumentsOfDualMessageSequences(
107+
final DualMessageSequences dualMessageSequences,
105108
final int commandDocumentSizeInBytes,
106-
final BsonOutput opsOut,
107-
final BsonOutput nsInfoOut,
109+
final BsonOutput firstOutput,
110+
final BsonOutput secondOutput,
108111
final MessageSettings messageSettings,
109112
final boolean validateDocumentSizeLimits) {
110-
BinaryOpsBsonWriters opsWriters = new BinaryOpsBsonWriters(
111-
opsOut,
112-
opsAndNsInfo.getFieldNameValidator(),
113+
BinaryOrdinaryAndStoredBsonWriters firstWriters = new BinaryOrdinaryAndStoredBsonWriters(
114+
firstOutput,
115+
dualMessageSequences.getFirstFieldNameValidator(),
113116
validateDocumentSizeLimits ? messageSettings : null);
114-
BsonBinaryWriter nsInfoWriter = new BsonBinaryWriter(nsInfoOut, NoOpFieldNameValidator.INSTANCE);
117+
BsonBinaryWriter secondWriter = new BsonBinaryWriter(secondOutput, dualMessageSequences.getSecondFieldNameValidator());
115118
// the size of operation-agnostic command fields (a.k.a. extra elements) is counted towards `messageOverheadInBytes`
116119
int messageOverheadInBytes = 1000;
117-
int maxOpsAndNsInfoSizeInBytes = messageSettings.getMaxMessageSize() - (messageOverheadInBytes + commandDocumentSizeInBytes);
118-
int opsStart = opsOut.getPosition();
119-
int nsInfoStart = nsInfoOut.getPosition();
120+
int maxSizeInBytes = messageSettings.getMaxMessageSize() - (messageOverheadInBytes + commandDocumentSizeInBytes);
121+
int firstStart = firstOutput.getPosition();
122+
int secondStart = secondOutput.getPosition();
120123
int maxBatchCount = messageSettings.getMaxBatchCount();
121-
return opsAndNsInfo.encode(write -> {
122-
int opsBeforeWritePosition = opsOut.getPosition();
123-
int nsInfoBeforeWritePosition = nsInfoOut.getPosition();
124-
int batchCountAfterWrite = write.doAndGetBatchCount(opsWriters, nsInfoWriter);
124+
return dualMessageSequences.encodeDocuments(write -> {
125+
int firstBeforeWritePosition = firstOutput.getPosition();
126+
int secondBeforeWritePosition = secondOutput.getPosition();
127+
int batchCountAfterWrite = write.doAndGetBatchCount(firstWriters, secondWriter);
125128
assertTrue(batchCountAfterWrite <= maxBatchCount);
126-
int opsAndNsInfoSizeInBytes =
127-
opsOut.getPosition() - opsStart
128-
+ nsInfoOut.getPosition() - nsInfoStart;
129-
if (opsAndNsInfoSizeInBytes < maxOpsAndNsInfoSizeInBytes && batchCountAfterWrite < maxBatchCount) {
130-
return WritersProviderAndLimitsChecker.WriteResult.OK_LIMIT_NOT_REACHED;
131-
} else if (opsAndNsInfoSizeInBytes > maxOpsAndNsInfoSizeInBytes) {
132-
opsOut.truncateToPosition(opsBeforeWritePosition);
133-
nsInfoOut.truncateToPosition(nsInfoBeforeWritePosition);
129+
int writtenSizeInBytes =
130+
firstOutput.getPosition() - firstStart
131+
+ secondOutput.getPosition() - secondStart;
132+
if (writtenSizeInBytes < maxSizeInBytes && batchCountAfterWrite < maxBatchCount) {
133+
return OK_LIMIT_NOT_REACHED;
134+
} else if (writtenSizeInBytes > maxSizeInBytes) {
135+
firstOutput.truncateToPosition(firstBeforeWritePosition);
136+
secondOutput.truncateToPosition(secondBeforeWritePosition);
134137
if (batchCountAfterWrite == 1) {
135-
// we have failed to write a single model
138+
// we have failed to write a single document
136139
throw createBsonMaximumSizeExceededException(messageSettings.getMaxDocumentSize());
137140
}
138-
return WritersProviderAndLimitsChecker.WriteResult.FAIL_LIMIT_EXCEEDED;
141+
return FAIL_LIMIT_EXCEEDED;
139142
} else {
140-
return WritersProviderAndLimitsChecker.WriteResult.OK_LIMIT_REACHED;
143+
return OK_LIMIT_REACHED;
141144
}
142145
});
143146
}
@@ -233,14 +236,14 @@ private static boolean exceedsLimits(final MessageSettings settings, final int m
233236
private BsonWriterHelper() {
234237
}
235238

236-
private static final class BinaryOpsBsonWriters implements WritersProviderAndLimitsChecker.OpsBsonWriters {
239+
private static final class BinaryOrdinaryAndStoredBsonWriters implements WritersProviderAndLimitsChecker.OrdinaryAndStoredBsonWriters {
237240
private final BsonBinaryWriter writer;
238241
private final BsonWriter storedDocumentWriter;
239242

240243
/**
241244
* @param messageSettings Non-{@code null} iff the document size limits must be validated.
242245
*/
243-
BinaryOpsBsonWriters(
246+
BinaryOrdinaryAndStoredBsonWriters(
244247
final BsonOutput out,
245248
final FieldNameValidator validator,
246249
@Nullable final MessageSettings messageSettings) {

‎driver-core/src/main/com/mongodb/internal/connection/CommandMessage.java

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import com.mongodb.connection.ClusterConnectionMode;
2525
import com.mongodb.internal.TimeoutContext;
2626
import com.mongodb.internal.connection.MessageSequences.EmptyMessageSequences;
27-
import com.mongodb.internal.operation.ClientBulkWriteOperation.ClientBulkWriteCommand;
2827
import com.mongodb.internal.session.SessionContext;
2928
import com.mongodb.lang.Nullable;
3029
import org.bson.BsonArray;
@@ -57,7 +56,7 @@
5756
import static com.mongodb.connection.ServerType.STANDALONE;
5857
import static com.mongodb.internal.connection.BsonWriterHelper.appendElementsToDocument;
5958
import static com.mongodb.internal.connection.BsonWriterHelper.backpatchLength;
60-
import static com.mongodb.internal.connection.BsonWriterHelper.writeOpsAndNsInfo;
59+
import static com.mongodb.internal.connection.BsonWriterHelper.writeDocumentsOfDualMessageSequences;
6160
import static com.mongodb.internal.connection.BsonWriterHelper.writePayload;
6261
import static com.mongodb.internal.connection.ByteBufBsonDocument.createList;
6362
import static com.mongodb.internal.connection.ByteBufBsonDocument.createOne;
@@ -81,11 +80,11 @@ public final class CommandMessage extends RequestMessage {
8180
private final MessageSequences sequences;
8281
private final boolean responseExpected;
8382
/**
84-
* {@code null} iff either {@link #sequences} is not of the {@link ClientBulkWriteCommand.OpsAndNsInfo} type,
83+
* {@code null} iff either {@link #sequences} is not of the {@link DualMessageSequences} type,
8584
* or it is of that type, but it has not been {@linkplain #encodeMessageBodyWithMetadata(ByteBufferBsonOutput, OperationContext) encoded}.
8685
*/
8786
@Nullable
88-
private Boolean opsAndNsInfoRequireResponse;
87+
private Boolean dualMessageSequencesRequireResponse;
8988
private final ClusterConnectionMode clusterConnectionMode;
9089
private final ServerApi serverApi;
9190

@@ -122,7 +121,7 @@ public final class CommandMessage extends RequestMessage {
122121
this.commandFieldNameValidator = commandFieldNameValidator;
123122
this.readPreference = readPreference;
124123
this.responseExpected = responseExpected;
125-
opsAndNsInfoRequireResponse = null;
124+
dualMessageSequencesRequireResponse = null;
126125
this.exhaustAllowed = exhaustAllowed;
127126
this.sequences = sequences;
128127
this.clusterConnectionMode = notNull("clusterConnectionMode", clusterConnectionMode);
@@ -206,12 +205,11 @@ boolean isResponseExpected() {
206205
if (responseExpected) {
207206
return true;
208207
} else {
209-
if (sequences instanceof ValidatableSplittablePayload) {
210-
ValidatableSplittablePayload validatableSplittablePayload = (ValidatableSplittablePayload) sequences;
211-
SplittablePayload payload = validatableSplittablePayload.getSplittablePayload();
208+
if (sequences instanceof SplittablePayload) {
209+
SplittablePayload payload = (SplittablePayload) sequences;
212210
return payload.isOrdered() && payload.hasAnotherSplit();
213-
} else if (sequences instanceof ClientBulkWriteCommand.OpsAndNsInfo) {
214-
return assertNotNull(opsAndNsInfoRequireResponse);
211+
} else if (sequences instanceof DualMessageSequences) {
212+
return assertNotNull(dualMessageSequencesRequireResponse);
215213
} else if (!(sequences instanceof EmptyMessageSequences)) {
216214
fail(sequences.toString());
217215
}
@@ -233,38 +231,34 @@ protected EncodingMetadata encodeMessageBodyWithMetadata(final ByteBufferBsonOut
233231
bsonOutput.writeByte(0); // payload type
234232
commandStartPosition = bsonOutput.getPosition();
235233
ArrayList<BsonElement> extraElements = getExtraElements(operationContext);
236-
// `OpsAndNsInfo` requires validation only if no response is expected, otherwise we must rely on the server validation
237-
boolean validateDocumentSizeLimits = !(sequences instanceof ClientBulkWriteCommand.OpsAndNsInfo) || !responseExpected;
234+
// `DualMessageSequences` requires validation only if no response is expected, otherwise we must rely on the server validation
235+
boolean validateDocumentSizeLimits = !(sequences instanceof DualMessageSequences) || !responseExpected;
238236

239237
int commandDocumentSizeInBytes = writeDocument(command, bsonOutput, commandFieldNameValidator, validateDocumentSizeLimits);
240-
if (sequences instanceof ValidatableSplittablePayload) {
238+
if (sequences instanceof SplittablePayload) {
241239
appendElementsToDocument(bsonOutput, commandStartPosition, extraElements);
242-
ValidatableSplittablePayload validatableSplittablePayload = (ValidatableSplittablePayload) sequences;
243-
SplittablePayload payload = validatableSplittablePayload.getSplittablePayload();
240+
SplittablePayload payload = (SplittablePayload) sequences;
244241
writeOpMsgSectionWithPayloadType1(bsonOutput, payload.getPayloadName(), () -> {
245242
writePayload(
246-
new BsonBinaryWriter(bsonOutput, validatableSplittablePayload.getFieldNameValidator()),
243+
new BsonBinaryWriter(bsonOutput, payload.getFieldNameValidator()),
247244
bsonOutput, getSettings(), messageStartPosition, payload, getSettings().getMaxDocumentSize()
248245
);
249246
return null;
250247
});
251-
} else if (sequences instanceof ClientBulkWriteCommand.OpsAndNsInfo) {
252-
ClientBulkWriteCommand.OpsAndNsInfo opsAndNsInfo = (ClientBulkWriteCommand.OpsAndNsInfo) sequences;
248+
} else if (sequences instanceof DualMessageSequences) {
249+
DualMessageSequences dualMessageSequences = (DualMessageSequences) sequences;
253250
try (ByteBufferBsonOutput.Branch bsonOutputBranch2 = bsonOutput.branch();
254251
ByteBufferBsonOutput.Branch bsonOutputBranch1 = bsonOutput.branch()) {
255-
ClientBulkWriteCommand.OpsAndNsInfo.EncodeResult opsAndNsInfoEncodeResult = writeOpMsgSectionWithPayloadType1(
256-
bsonOutputBranch1, "ops", () ->
257-
writeOpMsgSectionWithPayloadType1(bsonOutputBranch2, "nsInfo", () ->
258-
writeOpsAndNsInfo(
259-
opsAndNsInfo, commandDocumentSizeInBytes, bsonOutputBranch1,
252+
DualMessageSequences.EncodeDocumentsResult encodeDocumentsResult = writeOpMsgSectionWithPayloadType1(
253+
bsonOutputBranch1, dualMessageSequences.getFirstSequenceId(), () ->
254+
writeOpMsgSectionWithPayloadType1(bsonOutputBranch2, dualMessageSequences.getSecondSequenceId(), () ->
255+
writeDocumentsOfDualMessageSequences(
256+
dualMessageSequences, commandDocumentSizeInBytes, bsonOutputBranch1,
260257
bsonOutputBranch2, getSettings(), validateDocumentSizeLimits)
261258
)
262259
);
263-
opsAndNsInfoRequireResponse = opsAndNsInfoEncodeResult.isServerResponseRequired();
264-
Long txnNumber = opsAndNsInfoEncodeResult.getTxnNumber();
265-
if (txnNumber != null) {
266-
extraElements.add(new BsonElement(TXN_NUMBER_KEY, new BsonInt64(txnNumber)));
267-
}
260+
dualMessageSequencesRequireResponse = encodeDocumentsResult.isServerResponseRequired();
261+
extraElements.addAll(encodeDocumentsResult.getExtraElements());
268262
appendElementsToDocument(bsonOutput, commandStartPosition, extraElements);
269263
}
270264
} else if (sequences instanceof EmptyMessageSequences) {
@@ -391,6 +385,11 @@ private void addReadConcernDocument(final List<BsonElement> extraElements, final
391385
}
392386
}
393387

388+
/**
389+
* @param sequenceId The identifier of the sequence contained in the {@code OP_MSG} section to be written.
390+
* @param writeDocumentsAction The action that writes the documents of the sequence.
391+
* @see <a href="https://github.com/mongodb/specifications/blob/master/source/message/OP_MSG.md">OP_MSG</a>
392+
*/
394393
private <R> R writeOpMsgSectionWithPayloadType1(
395394
final ByteBufferBsonOutput bsonOutput,
396395
final String sequenceId,
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*
2+
* Copyright 2008-present MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.mongodb.internal.connection;
18+
19+
import org.bson.BsonElement;
20+
import org.bson.BsonWriter;
21+
import org.bson.FieldNameValidator;
22+
import org.bson.io.BsonOutput;
23+
24+
import java.util.List;
25+
26+
/**
27+
* Two sequences that may either be coupled or independent.
28+
* <p>
29+
* This class is not part of the public API and may be removed or changed at any time.</p>
30+
*/
31+
public abstract class DualMessageSequences extends MessageSequences {
32+
33+
private final String firstSequenceId;
34+
private final FieldNameValidator firstFieldNameValidator;
35+
private final String secondSequenceId;
36+
private final FieldNameValidator secondFieldNameValidator;
37+
38+
protected DualMessageSequences(
39+
final String firstSequenceId,
40+
final FieldNameValidator firstFieldNameValidator,
41+
final String secondSequenceId,
42+
final FieldNameValidator secondFieldNameValidator) {
43+
this.firstSequenceId = firstSequenceId;
44+
this.firstFieldNameValidator = firstFieldNameValidator;
45+
this.secondSequenceId = secondSequenceId;
46+
this.secondFieldNameValidator = secondFieldNameValidator;
47+
}
48+
49+
FieldNameValidator getFirstFieldNameValidator() {
50+
return firstFieldNameValidator;
51+
}
52+
53+
FieldNameValidator getSecondFieldNameValidator() {
54+
return secondFieldNameValidator;
55+
}
56+
57+
String getFirstSequenceId() {
58+
return firstSequenceId;
59+
}
60+
61+
String getSecondSequenceId() {
62+
return secondSequenceId;
63+
}
64+
65+
protected abstract EncodeDocumentsResult encodeDocuments(WritersProviderAndLimitsChecker writersProviderAndLimitsChecker);
66+
67+
/**
68+
* @see #tryWrite(WriteAction)
69+
*/
70+
public interface WritersProviderAndLimitsChecker {
71+
/**
72+
* Provides writers to the specified {@link WriteAction},
73+
* {@linkplain WriteAction#doAndGetBatchCount(OrdinaryAndStoredBsonWriters, BsonWriter) executes} it,
74+
* checks the {@linkplain MessageSettings limits}.
75+
* <p>
76+
* May be called multiple times per {@link #encodeDocuments(WritersProviderAndLimitsChecker)}.</p>
77+
*/
78+
WriteResult tryWrite(WriteAction write);
79+
80+
/**
81+
* @see #doAndGetBatchCount(OrdinaryAndStoredBsonWriters, BsonWriter)
82+
*/
83+
interface WriteAction {
84+
/**
85+
* Writes documents to the sequences using the provided writers.
86+
*
87+
* @return The resulting batch count since the beginning of {@link #encodeDocuments(WritersProviderAndLimitsChecker)}.
88+
* It is generally allowed to be greater than {@link MessageSettings#getMaxBatchCount()}.
89+
*/
90+
// VAKOTODO pass OrdinaryAndStoredBsonWriters for both first and second?
91+
int doAndGetBatchCount(OrdinaryAndStoredBsonWriters firstWriter, BsonWriter secondWriter);
92+
}
93+
94+
interface OrdinaryAndStoredBsonWriters {
95+
BsonWriter getWriter();
96+
97+
/**
98+
* A {@link BsonWriter} to use for writing documents that are intended to be stored in a database.
99+
* Must write to the same {@linkplain BsonOutput output} as {@link #getWriter()} does.
100+
*/
101+
BsonWriter getStoredDocumentWriter();
102+
}
103+
104+
enum WriteResult {
105+
FAIL_LIMIT_EXCEEDED,
106+
OK_LIMIT_REACHED,
107+
OK_LIMIT_NOT_REACHED
108+
}
109+
}
110+
111+
public static final class EncodeDocumentsResult {
112+
private final boolean serverResponseRequired;
113+
private final List<BsonElement> extraElements;
114+
115+
/**
116+
* @param extraElements See {@link #getExtraElements()}.
117+
*/
118+
public EncodeDocumentsResult(final boolean serverResponseRequired, final List<BsonElement> extraElements) {
119+
this.serverResponseRequired = serverResponseRequired;
120+
this.extraElements = extraElements;
121+
}
122+
123+
boolean isServerResponseRequired() {
124+
return serverResponseRequired;
125+
}
126+
127+
/**
128+
* {@linkplain BsonElement Key/value pairs} to be added to the document contained in the {@code OP_MSG} section with payload type 0.
129+
*/
130+
List<BsonElement> getExtraElements() {
131+
return extraElements;
132+
}
133+
}
134+
}

‎driver-core/src/main/com/mongodb/internal/connection/MessageSequences.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@
1616
package com.mongodb.internal.connection;
1717

1818
/**
19-
* This class is not part of the public API and may be removed or changed at any time.
19+
* Zero or more identifiable sequences contained in the {@code OP_MSG} section with payload type 1.
20+
* <p>
21+
* This class is not part of the public API and may be removed or changed at any time.</p>
22+
* @see <a href="https://github.com/mongodb/specifications/blob/master/source/message/OP_MSG.md">OP_MSG</a>
2023
*/
2124
public abstract class MessageSequences {
2225
public static final class EmptyMessageSequences extends MessageSequences {

‎driver-core/src/main/com/mongodb/internal/connection/SplittablePayload.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.bson.BsonObjectId;
2727
import org.bson.BsonValue;
2828
import org.bson.BsonWriter;
29+
import org.bson.FieldNameValidator;
2930
import org.bson.codecs.BsonValueCodecProvider;
3031
import org.bson.codecs.Codec;
3132
import org.bson.codecs.Encoder;
@@ -54,8 +55,9 @@
5455
*
5556
* <p>This class is not part of the public API and may be removed or changed at any time</p>
5657
*/
57-
public final class SplittablePayload {
58+
public final class SplittablePayload extends MessageSequences {
5859
private static final CodecRegistry REGISTRY = fromProviders(new BsonValueCodecProvider());
60+
private final FieldNameValidator fieldNameValidator;
5961
private final WriteRequestEncoder writeRequestEncoder = new WriteRequestEncoder();
6062
private final Type payloadType;
6163
private final List<WriteRequestWithIndex> writeRequestWithIndexes;
@@ -94,10 +96,19 @@ public enum Type {
9496
* @param payloadType the payload type
9597
* @param writeRequestWithIndexes the writeRequests
9698
*/
97-
public SplittablePayload(final Type payloadType, final List<WriteRequestWithIndex> writeRequestWithIndexes, final boolean ordered) {
99+
public SplittablePayload(
100+
final Type payloadType,
101+
final List<WriteRequestWithIndex> writeRequestWithIndexes,
102+
final boolean ordered,
103+
final FieldNameValidator fieldNameValidator) {
98104
this.payloadType = notNull("batchType", payloadType);
99105
this.writeRequestWithIndexes = notNull("writeRequests", writeRequestWithIndexes);
100106
this.ordered = ordered;
107+
this.fieldNameValidator = notNull("fieldNameValidator", fieldNameValidator);
108+
}
109+
110+
public FieldNameValidator getFieldNameValidator() {
111+
return fieldNameValidator;
101112
}
102113

103114
/**
@@ -175,7 +186,7 @@ boolean isOrdered() {
175186
public SplittablePayload getNextSplit() {
176187
isTrue("hasAnotherSplit", hasAnotherSplit());
177188
List<WriteRequestWithIndex> nextPayLoad = writeRequestWithIndexes.subList(position, writeRequestWithIndexes.size());
178-
return new SplittablePayload(payloadType, nextPayLoad, ordered);
189+
return new SplittablePayload(payloadType, nextPayLoad, ordered, fieldNameValidator);
179190
}
180191

181192
/**

‎driver-core/src/main/com/mongodb/internal/connection/ValidatableSplittablePayload.java

Lines changed: 0 additions & 39 deletions
This file was deleted.

‎driver-core/src/main/com/mongodb/internal/operation/BulkWriteBatch.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ private BulkWriteBatch(final MongoNamespace namespace, final ConnectionDescripti
154154

155155
this.indexMap = indexMap;
156156
this.unprocessed = unprocessedItems;
157-
this.payload = new SplittablePayload(getPayloadType(batchType), payloadItems, ordered);
157+
this.payload = new SplittablePayload(getPayloadType(batchType), payloadItems, ordered, getFieldNameValidator());
158158
this.operationContext = operationContext;
159159
this.comment = comment;
160160
this.variables = variables;
@@ -270,7 +270,7 @@ BulkWriteBatch getNextBatch() {
270270
}
271271
}
272272

273-
FieldNameValidator getFieldNameValidator() {
273+
private FieldNameValidator getFieldNameValidator() {
274274
if (batchType == UPDATE || batchType == REPLACE) {
275275
Map<String, FieldNameValidator> rootMap;
276276
if (batchType == REPLACE) {

‎driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java

Lines changed: 20 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,11 @@
6969
import com.mongodb.internal.client.model.bulk.ConcreteClientUpdateResult;
7070
import com.mongodb.internal.client.model.bulk.UnacknowledgedClientBulkWriteResult;
7171
import com.mongodb.internal.connection.Connection;
72+
import com.mongodb.internal.connection.DualMessageSequences;
73+
import com.mongodb.internal.connection.DualMessageSequences.WritersProviderAndLimitsChecker.OrdinaryAndStoredBsonWriters;
7274
import com.mongodb.internal.connection.IdHoldingBsonWriter;
73-
import com.mongodb.internal.connection.MessageSettings;
7475
import com.mongodb.internal.connection.MongoWriteConcernWithResponseException;
75-
import com.mongodb.internal.connection.MessageSequences;
7676
import com.mongodb.internal.connection.OperationContext;
77-
import com.mongodb.internal.operation.ClientBulkWriteOperation.ClientBulkWriteCommand.OpsAndNsInfo.WritersProviderAndLimitsChecker.OpsBsonWriters;
7877
import com.mongodb.internal.operation.retry.AttachmentKeys;
7978
import com.mongodb.internal.session.SessionContext;
8079
import com.mongodb.internal.validator.NoOpFieldNameValidator;
@@ -84,15 +83,16 @@
8483
import org.bson.BsonArray;
8584
import org.bson.BsonBoolean;
8685
import org.bson.BsonDocument;
86+
import org.bson.BsonElement;
8787
import org.bson.BsonInt32;
88+
import org.bson.BsonInt64;
8889
import org.bson.BsonObjectId;
8990
import org.bson.BsonValue;
9091
import org.bson.BsonWriter;
9192
import org.bson.FieldNameValidator;
9293
import org.bson.codecs.Encoder;
9394
import org.bson.codecs.EncoderContext;
9495
import org.bson.codecs.configuration.CodecRegistry;
95-
import org.bson.io.BsonOutput;
9696

9797
import java.util.ArrayList;
9898
import java.util.Collection;
@@ -109,9 +109,9 @@
109109
import static com.mongodb.assertions.Assertions.assertNotNull;
110110
import static com.mongodb.assertions.Assertions.assertTrue;
111111
import static com.mongodb.assertions.Assertions.fail;
112+
import static com.mongodb.internal.connection.DualMessageSequences.WritersProviderAndLimitsChecker.WriteResult.FAIL_LIMIT_EXCEEDED;
113+
import static com.mongodb.internal.connection.DualMessageSequences.WritersProviderAndLimitsChecker.WriteResult.OK_LIMIT_NOT_REACHED;
112114
import static com.mongodb.internal.operation.BulkWriteBatch.logWriteModelDoesNotSupportRetries;
113-
import static com.mongodb.internal.operation.ClientBulkWriteOperation.ClientBulkWriteCommand.OpsAndNsInfo.WritersProviderAndLimitsChecker.WriteResult.FAIL_LIMIT_EXCEEDED;
114-
import static com.mongodb.internal.operation.ClientBulkWriteOperation.ClientBulkWriteCommand.OpsAndNsInfo.WritersProviderAndLimitsChecker.WriteResult.OK_LIMIT_NOT_REACHED;
115115
import static com.mongodb.internal.operation.CommandOperationHelper.commandWriteConcern;
116116
import static com.mongodb.internal.operation.CommandOperationHelper.initialRetryState;
117117
import static com.mongodb.internal.operation.CommandOperationHelper.shouldAttemptToRetryWriteAndAddRetryableLabel;
@@ -123,6 +123,7 @@
123123
import static com.mongodb.internal.operation.SyncOperationHelper.withSourceAndConnection;
124124
import static java.util.Collections.emptyList;
125125
import static java.util.Collections.emptyMap;
126+
import static java.util.Collections.singletonList;
126127
import static java.util.Optional.ofNullable;
127128
import static java.util.Spliterator.IMMUTABLE;
128129
import static java.util.Spliterator.ORDERED;
@@ -665,33 +666,29 @@ OpsAndNsInfo getOpsAndNsInfo() {
665666
return opsAndNsInfo;
666667
}
667668

668-
public static final class OpsAndNsInfo extends MessageSequences {
669+
public static final class OpsAndNsInfo extends DualMessageSequences {
669670
private final boolean effectiveRetryWrites;
670671
private final List<? extends ClientNamespacedWriteModel> models;
671672
private final BatchEncoder batchEncoder;
672673
private final ConcreteClientBulkWriteOptions options;
673674
private final Supplier<Long> doIfCommandIsRetryableAndAdvanceGetTxnNumber;
674-
private final FieldNameValidator validator;
675675

676676
OpsAndNsInfo(
677677
final boolean effectiveRetryWrites,
678678
final List<? extends ClientNamespacedWriteModel> models,
679679
final BatchEncoder batchEncoder,
680680
final ConcreteClientBulkWriteOptions options,
681681
final Supplier<Long> doIfCommandIsRetryableAndAdvanceGetTxnNumber) {
682+
super("ops", new OpsFieldNameValidator(models), "nsInfo", NoOpFieldNameValidator.INSTANCE);
682683
this.effectiveRetryWrites = effectiveRetryWrites;
683684
this.models = models;
684685
this.batchEncoder = batchEncoder;
685686
this.options = options;
686687
this.doIfCommandIsRetryableAndAdvanceGetTxnNumber = doIfCommandIsRetryableAndAdvanceGetTxnNumber;
687-
this.validator = new OpsFieldNameValidator(models);
688688
}
689689

690-
public FieldNameValidator getFieldNameValidator() {
691-
return validator;
692-
}
693-
694-
public EncodeResult encode(final WritersProviderAndLimitsChecker writersProviderAndLimitsChecker) {
690+
@Override
691+
public EncodeDocumentsResult encodeDocuments(final WritersProviderAndLimitsChecker writersProviderAndLimitsChecker) {
695692
// We must call `batchEncoder.reset` lazily, that is here, and not eagerly before a command retry attempt,
696693
// because a retry attempt may fail before encoding,
697694
// in which case we need the information gathered by `batchEncoder` at a previous attempt.
@@ -726,81 +723,18 @@ public EncodeResult encode(final WritersProviderAndLimitsChecker writersProvider
726723
}
727724
}
728725
}
729-
return new EncodeResult(
726+
return new EncodeDocumentsResult(
727+
// we will execute more batches, so we must request a response to maintain the order of individual write operations
730728
options.isOrdered() && maxModelIndexInBatch < models.size() - 1,
731-
commandIsRetryable ? doIfCommandIsRetryableAndAdvanceGetTxnNumber.get() : null);
729+
commandIsRetryable
730+
? singletonList(new BsonElement("txnNumber", new BsonInt64(doIfCommandIsRetryableAndAdvanceGetTxnNumber.get())))
731+
: emptyList());
732732
}
733733

734734
private static boolean doesNotSupportRetries(final AbstractClientNamespacedWriteModel model) {
735735
return model instanceof ConcreteClientNamespacedUpdateManyModel || model instanceof ConcreteClientNamespacedDeleteManyModel;
736736
}
737737

738-
public static final class EncodeResult {
739-
private final boolean serverResponseRequired;
740-
@Nullable
741-
private final Long txnNumber;
742-
743-
EncodeResult(final boolean serverResponseRequired, @Nullable final Long txnNumber) {
744-
this.serverResponseRequired = serverResponseRequired;
745-
this.txnNumber = txnNumber;
746-
}
747-
748-
/**
749-
* @return {@code true} iff the operation is {@linkplain ClientBulkWriteOptions#ordered(Boolean) ordered},
750-
* and not all {@linkplain ClientNamespacedWriteModel models} were written, that is, more
751-
* {@linkplain #executeBatch(int, WriteConcern, WriteBinding, ResultAccumulator) batches} are needed.
752-
*/
753-
public boolean isServerResponseRequired() {
754-
return serverResponseRequired;
755-
}
756-
757-
@Nullable
758-
public Long getTxnNumber() {
759-
return txnNumber;
760-
}
761-
}
762-
763-
/**
764-
* @see #tryWrite(WriteAction)
765-
*/
766-
public interface WritersProviderAndLimitsChecker {
767-
/**
768-
* Provides writers to the specified {@link WriteAction},
769-
* {@linkplain WriteAction#doAndGetBatchCount(OpsBsonWriters, BsonWriter) executes} it,
770-
* checks the {@linkplain MessageSettings limits}.
771-
*/
772-
WriteResult tryWrite(WriteAction write);
773-
774-
/**
775-
* @see #doAndGetBatchCount(OpsBsonWriters, BsonWriter)
776-
*/
777-
interface WriteAction {
778-
/**
779-
* Writes {@linkplain ClientNamespacedWriteModel models}
780-
* to the {@code ops} and {@code nsInfo} sequences using the provided writers.
781-
*
782-
* @return The resulting {@linkplain BatchEncoder.EncodedBatchInfo#getModelsCount() batch count}.
783-
*/
784-
int doAndGetBatchCount(OpsBsonWriters opsBsonWriters, BsonWriter nsInfoWriter);
785-
}
786-
787-
interface OpsBsonWriters {
788-
BsonWriter getWriter();
789-
790-
/**
791-
* A {@link BsonWriter} to use for writing documents that are intended to be stored in a database.
792-
* Must write to the same {@linkplain BsonOutput output} as {@link #getWriter()} does.
793-
*/
794-
BsonWriter getStoredDocumentWriter();
795-
}
796-
797-
enum WriteResult {
798-
FAIL_LIMIT_EXCEEDED,
799-
OK_LIMIT_REACHED,
800-
OK_LIMIT_NOT_REACHED
801-
}
802-
}
803-
804738
/**
805739
* The server supports only the {@code update} individual write operation in the {@code ops} array field, while the driver supports
806740
* {@link ClientNamespacedUpdateOneModel}, {@link ClientNamespacedUpdateOneModel}, {@link ClientNamespacedReplaceOneModel}.
@@ -1005,7 +939,7 @@ private final class BatchEncoder {
1005939
/**
1006940
* Must be called at most once.
1007941
* Must not be called before calling
1008-
* {@link #encodeWriteModel(OpsBsonWriters, ClientWriteModel, int, int)} at least once.
942+
* {@link #encodeWriteModel(OrdinaryAndStoredBsonWriters, ClientWriteModel, int, int)} at least once.
1009943
* Renders {@code this} unusable.
1010944
*/
1011945
EncodedBatchInfo intoEncodedBatchInfo() {
@@ -1026,7 +960,7 @@ void reset(final int modelIndexInBatch) {
1026960
}
1027961

1028962
void encodeWriteModel(
1029-
final OpsBsonWriters writers,
963+
final OrdinaryAndStoredBsonWriters writers,
1030964
final ClientWriteModel model,
1031965
final int modelIndexInBatch,
1032966
final int namespaceIndexInBatch) {
@@ -1061,7 +995,7 @@ void encodeWriteModel(
1061995
writer.writeEndDocument();
1062996
}
1063997

1064-
private void encodeWriteModelInternals(final OpsBsonWriters writers, final ConcreteClientInsertOneModel model, final int modelIndexInBatch) {
998+
private void encodeWriteModelInternals(final OrdinaryAndStoredBsonWriters writers, final ConcreteClientInsertOneModel model, final int modelIndexInBatch) {
1065999
writers.getWriter().writeName("document");
10661000
Object document = model.getDocument();
10671001
assertNotNull(encodedBatchInfo).insertModelDocumentIds.compute(modelIndexInBatch, (k, knownModelDocumentId) -> {
@@ -1105,7 +1039,7 @@ private void encodeWriteModelInternals(final BsonWriter writer, final AbstractCl
11051039
options.isUpsert().ifPresent(value -> writer.writeBoolean("upsert", value));
11061040
}
11071041

1108-
private void encodeWriteModelInternals(final OpsBsonWriters writers, final ConcreteClientReplaceOneModel model) {
1042+
private void encodeWriteModelInternals(final OrdinaryAndStoredBsonWriters writers, final ConcreteClientReplaceOneModel model) {
11091043
BsonWriter writer = writers.getWriter();
11101044
writer.writeBoolean("multi", false);
11111045
writer.writeName("filter");

‎driver-core/src/main/com/mongodb/internal/operation/MixedBulkWriteOperation.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
import com.mongodb.internal.connection.MongoWriteConcernWithResponseException;
4040
import com.mongodb.internal.connection.OperationContext;
4141
import com.mongodb.internal.connection.ProtocolHelper;
42-
import com.mongodb.internal.connection.ValidatableSplittablePayload;
4342
import com.mongodb.internal.operation.retry.AttachmentKeys;
4443
import com.mongodb.internal.session.SessionContext;
4544
import com.mongodb.internal.validator.NoOpFieldNameValidator;
@@ -422,8 +421,7 @@ private BsonDocument executeCommand(
422421
final Connection connection,
423422
final BulkWriteBatch batch) {
424423
return connection.command(namespace.getDatabaseName(), batch.getCommand(), NoOpFieldNameValidator.INSTANCE, null, batch.getDecoder(),
425-
operationContext, shouldExpectResponse(batch, effectiveWriteConcern),
426-
new ValidatableSplittablePayload(batch.getPayload(), batch.getFieldNameValidator()));
424+
operationContext, shouldExpectResponse(batch, effectiveWriteConcern), batch.getPayload());
427425
}
428426

429427
private void executeCommandAsync(
@@ -433,8 +431,7 @@ private void executeCommandAsync(
433431
final BulkWriteBatch batch,
434432
final SingleResultCallback<BsonDocument> callback) {
435433
connection.commandAsync(namespace.getDatabaseName(), batch.getCommand(), NoOpFieldNameValidator.INSTANCE, null, batch.getDecoder(),
436-
operationContext, shouldExpectResponse(batch, effectiveWriteConcern),
437-
new ValidatableSplittablePayload(batch.getPayload(), batch.getFieldNameValidator()), callback);
434+
operationContext, shouldExpectResponse(batch, effectiveWriteConcern), batch.getPayload(), callback);
438435
}
439436

440437
private boolean shouldExpectResponse(final BulkWriteBatch batch, final WriteConcern effectiveWriteConcern) {

‎driver-core/src/test/functional/com/mongodb/OperationFunctionalSpecification.groovy

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ import com.mongodb.internal.connection.AsyncConnection
4747
import com.mongodb.internal.connection.Connection
4848
import com.mongodb.internal.connection.ServerHelper
4949
import com.mongodb.internal.connection.SplittablePayload
50-
import com.mongodb.internal.connection.ValidatableSplittablePayload
5150
import com.mongodb.internal.operation.AsyncReadOperation
5251
import com.mongodb.internal.operation.AsyncWriteOperation
5352
import com.mongodb.internal.operation.MixedBulkWriteOperation
@@ -316,7 +315,7 @@ class OperationFunctionalSpecification extends Specification {
316315
1 * connection.command(*_) >> {
317316
assert it[1] == expectedCommand
318317
if (it.size() > 6) {
319-
SplittablePayload payload = ((ValidatableSplittablePayload) it[7]).getSplittablePayload()
318+
SplittablePayload payload = it[7]
320319
payload.setPosition(payload.size())
321320
}
322321
result
@@ -394,7 +393,7 @@ class OperationFunctionalSpecification extends Specification {
394393
1 * connection.commandAsync(*_) >> {
395394
assert it[1] == expectedCommand
396395
if (it.size() > 7) {
397-
SplittablePayload payload = ((ValidatableSplittablePayload) it[7]).getSplittablePayload()
396+
SplittablePayload payload = it[7]
398397
payload.setPosition(payload.size())
399398
}
400399
it.last().onResult(result, null)

‎driver-core/src/test/unit/com/mongodb/internal/connection/CommandMessageSpecification.groovy

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,7 @@ class CommandMessageSpecification extends Specification {
152152
given:
153153
def message = new CommandMessage(namespace, originalCommandDocument, fieldNameValidator, ReadPreference.primary(),
154154
MessageSettings.builder().maxWireVersion(maxWireVersion).build(), true,
155-
payload == null
156-
? MessageSequences.EmptyMessageSequences.INSTANCE
157-
: new ValidatableSplittablePayload(payload, NoOpFieldNameValidator.INSTANCE),
155+
payload == null ? MessageSequences.EmptyMessageSequences.INSTANCE : payload,
158156
ClusterConnectionMode.MULTIPLE, null)
159157
def output = new ByteBufferBsonOutput(new SimpleBufferProvider())
160158
message.encode(output, new OperationContext(IgnorableRequestContext.INSTANCE, NoOpSessionContext.INSTANCE,
@@ -177,7 +175,8 @@ class CommandMessageSpecification extends Specification {
177175
new BsonDocument('insert', new BsonString('coll')),
178176
new SplittablePayload(INSERT, [new BsonDocument('_id', new BsonInt32(1)),
179177
new BsonDocument('_id', new BsonInt32(2))]
180-
.withIndex().collect { doc, i -> new WriteRequestWithIndex(new InsertRequest(doc), i) }, true),
178+
.withIndex().collect { doc, i -> new WriteRequestWithIndex(new InsertRequest(doc), i) },
179+
true, NoOpFieldNameValidator.INSTANCE),
181180
],
182181
[
183182
LATEST_WIRE_VERSION,
@@ -198,9 +197,9 @@ class CommandMessageSpecification extends Specification {
198197
new BsonDocument('_id', new BsonInt32(3)).append('c', new BsonBinary(new byte[450])),
199198
new BsonDocument('_id', new BsonInt32(4)).append('b', new BsonBinary(new byte[441])),
200199
new BsonDocument('_id', new BsonInt32(5)).append('c', new BsonBinary(new byte[451]))]
201-
.withIndex().collect { doc, i -> new WriteRequestWithIndex(new InsertRequest(doc), i) }, true)
200+
.withIndex().collect { doc, i -> new WriteRequestWithIndex(new InsertRequest(doc), i) }, true, fieldNameValidator)
202201
def message = new CommandMessage(namespace, insertCommand, fieldNameValidator, ReadPreference.primary(), messageSettings,
203-
false, new ValidatableSplittablePayload(payload, fieldNameValidator), ClusterConnectionMode.MULTIPLE, null)
202+
false, payload, ClusterConnectionMode.MULTIPLE, null)
204203
def output = new ByteBufferBsonOutput(new SimpleBufferProvider())
205204
def sessionContext = Stub(SessionContext) {
206205
getReadConcern() >> ReadConcern.DEFAULT
@@ -224,7 +223,7 @@ class CommandMessageSpecification extends Specification {
224223
when:
225224
payload = payload.getNextSplit()
226225
message = new CommandMessage(namespace, insertCommand, fieldNameValidator, ReadPreference.primary(), messageSettings,
227-
false, new ValidatableSplittablePayload(payload, fieldNameValidator), ClusterConnectionMode.MULTIPLE, null)
226+
false, payload, ClusterConnectionMode.MULTIPLE, null)
228227
output.truncateToPosition(0)
229228
message.encode(output, new OperationContext(IgnorableRequestContext.INSTANCE, sessionContext, Stub(TimeoutContext), null))
230229
byteBuf = new ByteBufNIO(ByteBuffer.wrap(output.toByteArray()))
@@ -242,7 +241,7 @@ class CommandMessageSpecification extends Specification {
242241
when:
243242
payload = payload.getNextSplit()
244243
message = new CommandMessage(namespace, insertCommand, fieldNameValidator, ReadPreference.primary(), messageSettings,
245-
false, new ValidatableSplittablePayload(payload, fieldNameValidator), ClusterConnectionMode.MULTIPLE, null)
244+
false, payload, ClusterConnectionMode.MULTIPLE, null)
246245
output.truncateToPosition(0)
247246
message.encode(output, new OperationContext(IgnorableRequestContext.INSTANCE, sessionContext, Stub(TimeoutContext), null))
248247
byteBuf = new ByteBufNIO(ByteBuffer.wrap(output.toByteArray()))
@@ -260,7 +259,7 @@ class CommandMessageSpecification extends Specification {
260259
when:
261260
payload = payload.getNextSplit()
262261
message = new CommandMessage(namespace, insertCommand, fieldNameValidator, ReadPreference.primary(), messageSettings,
263-
false, new ValidatableSplittablePayload(payload, fieldNameValidator), ClusterConnectionMode.MULTIPLE, null)
262+
false, payload, ClusterConnectionMode.MULTIPLE, null)
264263
output.truncateToPosition(0)
265264
message.encode(output, new OperationContext(IgnorableRequestContext.INSTANCE,
266265
sessionContext,
@@ -288,9 +287,9 @@ class CommandMessageSpecification extends Specification {
288287
def payload = new SplittablePayload(INSERT, [new BsonDocument('a', new BsonBinary(new byte[900])),
289288
new BsonDocument('b', new BsonBinary(new byte[450])),
290289
new BsonDocument('c', new BsonBinary(new byte[450]))]
291-
.withIndex().collect { doc, i -> new WriteRequestWithIndex(new InsertRequest(doc), i) }, true)
290+
.withIndex().collect { doc, i -> new WriteRequestWithIndex(new InsertRequest(doc), i) }, true, fieldNameValidator)
292291
def message = new CommandMessage(namespace, command, fieldNameValidator, ReadPreference.primary(), messageSettings,
293-
false, new ValidatableSplittablePayload(payload, fieldNameValidator), ClusterConnectionMode.MULTIPLE, null)
292+
false, payload, ClusterConnectionMode.MULTIPLE, null)
294293
def output = new ByteBufferBsonOutput(new SimpleBufferProvider())
295294
def sessionContext = Stub(SessionContext) {
296295
getReadConcern() >> ReadConcern.DEFAULT
@@ -315,7 +314,7 @@ class CommandMessageSpecification extends Specification {
315314
when:
316315
payload = payload.getNextSplit()
317316
message = new CommandMessage(namespace, command, fieldNameValidator, ReadPreference.primary(), messageSettings,
318-
false, new ValidatableSplittablePayload(payload, fieldNameValidator), ClusterConnectionMode.MULTIPLE, null)
317+
false, payload, ClusterConnectionMode.MULTIPLE, null)
319318
output.truncateToPosition(0)
320319
message.encode(output, new OperationContext(IgnorableRequestContext.INSTANCE, sessionContext,
321320
Stub(TimeoutContext), null))
@@ -339,9 +338,9 @@ class CommandMessageSpecification extends Specification {
339338
def messageSettings = MessageSettings.builder().maxDocumentSize(900)
340339
.maxWireVersion(LATEST_WIRE_VERSION).build()
341340
def payload = new SplittablePayload(INSERT, [new BsonDocument('a', new BsonBinary(new byte[900]))]
342-
.withIndex().collect { doc, i -> new WriteRequestWithIndex(new InsertRequest(doc), i) }, true)
341+
.withIndex().collect { doc, i -> new WriteRequestWithIndex(new InsertRequest(doc), i) }, true, fieldNameValidator)
343342
def message = new CommandMessage(namespace, command, fieldNameValidator, ReadPreference.primary(), messageSettings,
344-
false, new ValidatableSplittablePayload(payload, fieldNameValidator), ClusterConnectionMode.MULTIPLE, null)
343+
false, payload, ClusterConnectionMode.MULTIPLE, null)
345344
def output = new ByteBufferBsonOutput(new SimpleBufferProvider())
346345
def sessionContext = Stub(SessionContext) {
347346
getReadConcern() >> ReadConcern.DEFAULT
@@ -362,9 +361,9 @@ class CommandMessageSpecification extends Specification {
362361
given:
363362
def messageSettings = MessageSettings.builder().serverType(ServerType.SHARD_ROUTER)
364363
.maxWireVersion(FOUR_DOT_ZERO_WIRE_VERSION).build()
365-
def payload = new SplittablePayload(INSERT, [new BsonDocument('a', new BsonInt32(1))], true)
364+
def payload = new SplittablePayload(INSERT, [new BsonDocument('a', new BsonInt32(1))], true, fieldNameValidator)
366365
def message = new CommandMessage(namespace, command, fieldNameValidator, ReadPreference.primary(), messageSettings,
367-
false, new ValidatableSplittablePayload(payload, fieldNameValidator), ClusterConnectionMode.MULTIPLE, null)
366+
false, payload, ClusterConnectionMode.MULTIPLE, null)
368367
def output = new ByteBufferBsonOutput(new SimpleBufferProvider())
369368
def sessionContext = Stub(SessionContext) {
370369
getReadConcern() >> ReadConcern.DEFAULT

‎driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/crypt/CryptConnection.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import com.mongodb.internal.connection.OperationContext;
2929
import com.mongodb.internal.connection.SplittablePayload;
3030
import com.mongodb.internal.connection.SplittablePayloadBsonWriter;
31-
import com.mongodb.internal.connection.ValidatableSplittablePayload;
3231
import com.mongodb.internal.time.Timeout;
3332
import com.mongodb.internal.validator.MappedFieldNameValidator;
3433
import com.mongodb.lang.Nullable;
@@ -114,10 +113,9 @@ public <T> void commandAsync(final String database, final BsonDocument command,
114113
try {
115114
SplittablePayload payload = null;
116115
FieldNameValidator payloadFieldNameValidator = null;
117-
if (sequences instanceof ValidatableSplittablePayload) {
118-
ValidatableSplittablePayload validatableSplittablePayload = (ValidatableSplittablePayload) sequences;
119-
payload = validatableSplittablePayload.getSplittablePayload();
120-
payloadFieldNameValidator = validatableSplittablePayload.getFieldNameValidator();
116+
if (sequences instanceof SplittablePayload) {
117+
payload = (SplittablePayload) sequences;
118+
payloadFieldNameValidator = payload.getFieldNameValidator();
121119
} else if (!(sequences instanceof EmptyMessageSequences)) {
122120
fail(sequences.toString());
123121
}

‎driver-sync/src/main/com/mongodb/client/internal/CryptConnection.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import com.mongodb.internal.connection.OperationContext;
2727
import com.mongodb.internal.connection.SplittablePayload;
2828
import com.mongodb.internal.connection.SplittablePayloadBsonWriter;
29-
import com.mongodb.internal.connection.ValidatableSplittablePayload;
3029
import com.mongodb.internal.time.Timeout;
3130
import com.mongodb.internal.validator.MappedFieldNameValidator;
3231
import com.mongodb.lang.Nullable;
@@ -102,10 +101,9 @@ public <T> T command(final String database, final BsonDocument command, final Fi
102101

103102
SplittablePayload payload = null;
104103
FieldNameValidator payloadFieldNameValidator = null;
105-
if (sequences instanceof ValidatableSplittablePayload) {
106-
ValidatableSplittablePayload validatableSplittablePayload = (ValidatableSplittablePayload) sequences;
107-
payload = validatableSplittablePayload.getSplittablePayload();
108-
payloadFieldNameValidator = validatableSplittablePayload.getFieldNameValidator();
104+
if (sequences instanceof SplittablePayload) {
105+
payload = (SplittablePayload) sequences;
106+
payloadFieldNameValidator = payload.getFieldNameValidator();
109107
} else if (!(sequences instanceof EmptyMessageSequences)) {
110108
fail(sequences.toString());
111109
}

‎driver-sync/src/test/unit/com/mongodb/client/internal/CryptConnectionSpecification.groovy

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import com.mongodb.internal.bulk.WriteRequestWithIndex
2929
import com.mongodb.internal.connection.Connection
3030
import com.mongodb.internal.connection.MessageSequences
3131
import com.mongodb.internal.connection.SplittablePayload
32-
import com.mongodb.internal.connection.ValidatableSplittablePayload
3332
import com.mongodb.internal.time.Timeout
3433
import com.mongodb.internal.validator.NoOpFieldNameValidator
3534
import org.bson.BsonArray
@@ -117,7 +116,7 @@ class CryptConnectionSpecification extends Specification {
117116
def payload = new SplittablePayload(INSERT, [
118117
new BsonDocumentWrapper(new Document('_id', 1).append('ssid', '555-55-5555').append('b', bytes), codec),
119118
new BsonDocumentWrapper(new Document('_id', 2).append('ssid', '666-66-6666').append('b', bytes), codec)
120-
].withIndex().collect { doc, i -> new WriteRequestWithIndex(new InsertRequest(doc), i) }, true)
119+
].withIndex().collect { doc, i -> new WriteRequestWithIndex(new InsertRequest(doc), i) }, true, NoOpFieldNameValidator.INSTANCE)
121120
def encryptedCommand = toRaw(new BsonDocument('insert', new BsonString('test')).append('documents', new BsonArray(
122121
[
123122
new BsonDocument('_id', new BsonInt32(1))
@@ -135,8 +134,7 @@ class CryptConnectionSpecification extends Specification {
135134
when:
136135
def response = cryptConnection.command('db',
137136
new BsonDocumentWrapper(new Document('insert', 'test'), codec),
138-
NoOpFieldNameValidator.INSTANCE, ReadPreference.primary(), new BsonDocumentCodec(),
139-
operationContext, true, new ValidatableSplittablePayload(payload, NoOpFieldNameValidator.INSTANCE))
137+
NoOpFieldNameValidator.INSTANCE, ReadPreference.primary(), new BsonDocumentCodec(), operationContext, true, payload)
140138

141139
then:
142140
_ * wrappedConnection.getDescription() >> {
@@ -174,7 +172,7 @@ class CryptConnectionSpecification extends Specification {
174172
new BsonDocumentWrapper(new Document('_id', 1), codec),
175173
new BsonDocumentWrapper(new Document('_id', 2), codec),
176174
new BsonDocumentWrapper(new Document('_id', 3), codec)
177-
].withIndex().collect { doc, i -> new WriteRequestWithIndex(new InsertRequest(doc), i) }, true)
175+
].withIndex().collect { doc, i -> new WriteRequestWithIndex(new InsertRequest(doc), i) }, true, NoOpFieldNameValidator.INSTANCE)
178176
def encryptedCommand = toRaw(new BsonDocument('insert', new BsonString('test')).append('documents', new BsonArray(
179177
[
180178
new BsonDocument('_id', new BsonInt32(1)),
@@ -192,8 +190,7 @@ class CryptConnectionSpecification extends Specification {
192190
when:
193191
def response = cryptConnection.command('db',
194192
new BsonDocumentWrapper(new Document('insert', 'test'), codec),
195-
NoOpFieldNameValidator.INSTANCE, ReadPreference.primary(), new BsonDocumentCodec(), operationContext, true,
196-
new ValidatableSplittablePayload(payload, NoOpFieldNameValidator.INSTANCE))
193+
NoOpFieldNameValidator.INSTANCE, ReadPreference.primary(), new BsonDocumentCodec(), operationContext, true, payload)
197194

198195
then:
199196
_ * wrappedConnection.getDescription() >> {

0 commit comments

Comments
 (0)
Please sign in to comment.