Skip to content

Commit fdef549

Browse files
committed
JAVA-2692: Only attempt to send command started event when there is a command listener and the connection handshake is complete
1 parent 94990d7 commit fdef549

File tree

1 file changed

+58
-37
lines changed

1 file changed

+58
-37
lines changed

driver-core/src/main/com/mongodb/connection/InternalStreamConnection.java

Lines changed: 58 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -237,19 +237,20 @@ public boolean isClosed() {
237237

238238
@Override
239239
public <T> T sendAndReceive(final CommandMessage message, final Decoder<T> decoder, final SessionContext sessionContext) {
240-
CommandEventSender commandEventSender = new CommandEventSender(message);
241-
242240
ByteBufferBsonOutput bsonOutput = new ByteBufferBsonOutput(this);
241+
LazyCommandDocument lazyCommandDocument = new LazyCommandDocument(message, bsonOutput);
242+
CommandEventSender commandEventSender = new CommandEventSender(message, lazyCommandDocument);
243+
243244
try {
244245
message.encode(bsonOutput, sessionContext);
245-
commandEventSender.sendStartedEvent(bsonOutput);
246+
commandEventSender.sendStartedEvent();
246247
} catch (RuntimeException e) {
247248
bsonOutput.close();
248249
throw e;
249250
}
250251

251252
try {
252-
sendCommandMessage(message, commandEventSender, bsonOutput, sessionContext);
253+
sendCommandMessage(message, lazyCommandDocument, bsonOutput, sessionContext);
253254
if (message.isResponseExpected()) {
254255
return receiveCommandMessageResponse(message, decoder, commandEventSender, sessionContext);
255256
} else {
@@ -262,10 +263,10 @@ public <T> T sendAndReceive(final CommandMessage message, final Decoder<T> decod
262263
}
263264
}
264265

265-
private void sendCommandMessage(final CommandMessage message, final CommandEventSender commandEventSender,
266+
private void sendCommandMessage(final CommandMessage message, final LazyCommandDocument lazyCommandDocument,
266267
final ByteBufferBsonOutput bsonOutput, final SessionContext sessionContext) {
267268
try {
268-
if (sendCompressor == null || SECURITY_SENSITIVE_COMMANDS.contains(commandEventSender.getCommandName())) {
269+
if (sendCompressor == null || SECURITY_SENSITIVE_COMMANDS.contains(lazyCommandDocument.getName())) {
269270
sendMessage(bsonOutput.getByteBuffers(), message.getId());
270271
} else {
271272
CompressedMessage compressedMessage = new CompressedMessage(message.getOpCode(), bsonOutput.getByteBuffers(),
@@ -318,10 +319,11 @@ public <T> void sendAndReceiveAsync(final CommandMessage message, final Decoder<
318319

319320
try {
320321
message.encode(bsonOutput, sessionContext);
321-
CommandEventSender commandEventSender = new CommandEventSender(message);
322-
commandEventSender.sendStartedEvent(bsonOutput);
322+
LazyCommandDocument lazyCommandDocument = new LazyCommandDocument(message, bsonOutput);
323+
CommandEventSender commandEventSender = new CommandEventSender(message, lazyCommandDocument);
324+
commandEventSender.sendStartedEvent();
323325

324-
if (sendCompressor == null || SECURITY_SENSITIVE_COMMANDS.contains(commandEventSender.getCommandName())) {
326+
if (sendCompressor == null || SECURITY_SENSITIVE_COMMANDS.contains(lazyCommandDocument.getName())) {
325327
sendCommandMessageAsync(message.getId(), decoder, sessionContext, callback, bsonOutput, commandEventSender,
326328
message.isResponseExpected());
327329
} else {
@@ -657,60 +659,79 @@ public void onResult(final ByteBuf result, final Throwable t) {
657659
private class CommandEventSender {
658660
private final long startTimeNanos;
659661
private final CommandMessage message;
660-
private String commandName;
662+
private final LazyCommandDocument lazyCommandDocument;
661663

662-
CommandEventSender(final CommandMessage message) {
664+
CommandEventSender(final CommandMessage message, final LazyCommandDocument lazyCommandDocument) {
663665
this.startTimeNanos = System.nanoTime();
664666
this.message = message;
667+
this.lazyCommandDocument = lazyCommandDocument;
665668
}
666669

667-
// Call after sendStartedEvent. Returns null unless there's either a command listener or a sendCompress configured. Otherwise,
668-
// there's no need to compute the command name
669-
public String getCommandName() {
670-
if (commandName == null) {
671-
throw new MongoInternalException("Attempting to use the command name when it has not been determined");
672-
}
673-
return commandName;
674-
}
675-
676-
public void sendStartedEvent(final ByteBufferBsonOutput bsonOutput) {
677-
if ((commandListener != null || sendCompressor != null) && opened()) {
678-
679-
BsonDocument commandDocument = message.getCommandDocument(bsonOutput);
680-
commandName = commandDocument.getFirstKey();
681-
682-
BsonDocument commandDocumentForEvent = (SECURITY_SENSITIVE_COMMANDS.contains(commandName))
683-
? new BsonDocument() : commandDocument;
684-
sendCommandStartedEvent(message, new MongoNamespace(message.getCollectionName()).getDatabaseName(), commandName,
685-
commandDocumentForEvent, getDescription(), commandListener);
670+
public void sendStartedEvent() {
671+
if (commandListener != null && opened()) {
672+
BsonDocument commandDocumentForEvent = (SECURITY_SENSITIVE_COMMANDS.contains(lazyCommandDocument.getName()))
673+
? new BsonDocument() : lazyCommandDocument.getDocument();
674+
sendCommandStartedEvent(message, new MongoNamespace(message.getCollectionName()).getDatabaseName(),
675+
lazyCommandDocument.getName(), commandDocumentForEvent, getDescription(), commandListener);
686676
}
687677
}
688678

689679
public void sendFailedEvent(final Throwable t) {
690680
if (commandListener != null && opened()) {
691681
Throwable commandEventException = t;
692-
if (t instanceof MongoCommandException && (SECURITY_SENSITIVE_COMMANDS.contains(commandName))) {
682+
if (t instanceof MongoCommandException && (SECURITY_SENSITIVE_COMMANDS.contains(lazyCommandDocument.getName()))) {
693683
commandEventException = new MongoCommandException(new BsonDocument(), description.getServerAddress());
694684
}
695-
sendCommandFailedEvent(message, commandName, description, startTimeNanos, commandEventException, commandListener);
685+
sendCommandFailedEvent(message, lazyCommandDocument.getName(), description, startTimeNanos, commandEventException,
686+
commandListener);
696687
}
697688
}
698689

699690
public void sendSucceededEvent(final ResponseBuffers responseBuffers) {
700691
if (commandListener != null && opened()) {
701-
BsonDocument responseDocumentForEvent = (SECURITY_SENSITIVE_COMMANDS.contains(commandName))
702-
? new BsonDocument()
703-
: getResponseDocument(responseBuffers, message.getId(),
692+
BsonDocument responseDocumentForEvent = (SECURITY_SENSITIVE_COMMANDS.contains(lazyCommandDocument.getName()))
693+
? new BsonDocument()
694+
: getResponseDocument(responseBuffers, message.getId(),
704695
new RawBsonDocumentCodec());
705-
sendCommandSucceededEvent(message, commandName, responseDocumentForEvent, description, startTimeNanos, commandListener);
696+
sendCommandSucceededEvent(message, lazyCommandDocument.getName(), responseDocumentForEvent, description,
697+
startTimeNanos, commandListener);
706698
}
707699
}
708700

709701
public void sendSucceededEventForOneWayCommand() {
710702
if (commandListener != null && opened()) {
711703
BsonDocument responseDocumentForEvent = new BsonDocument("ok", new BsonInt32(1));
712-
sendCommandSucceededEvent(message, commandName, responseDocumentForEvent, description, startTimeNanos, commandListener);
704+
sendCommandSucceededEvent(message, lazyCommandDocument.getName(), responseDocumentForEvent, description,
705+
startTimeNanos, commandListener);
706+
}
707+
}
708+
}
709+
710+
// Lazily determine the command document and command name, since they're only needed if either a command listener or compression
711+
// is enabled
712+
private static final class LazyCommandDocument {
713+
private final CommandMessage commandMessage;
714+
private final ByteBufferBsonOutput bsonOutput;
715+
private BsonDocument commandDocument;
716+
private String commandName;
717+
718+
private LazyCommandDocument(final CommandMessage commandMessage, final ByteBufferBsonOutput bsonOutput) {
719+
this.commandMessage = commandMessage;
720+
this.bsonOutput = bsonOutput;
721+
}
722+
723+
public String getName() {
724+
if (commandName == null) {
725+
commandName = getDocument().getFirstKey();
726+
}
727+
return commandName;
728+
}
729+
730+
private BsonDocument getDocument() {
731+
if (commandDocument == null) {
732+
commandDocument = commandMessage.getCommandDocument(bsonOutput);
713733
}
734+
return commandDocument;
714735
}
715736
}
716737
}

0 commit comments

Comments
 (0)