Skip to content

Commit 46aac52

Browse files
authored
CSHARP-3516: Use hello command when API Version is declared. (#536)
1 parent a88aeb1 commit 46aac52

22 files changed

+341
-127
lines changed

src/MongoDB.Driver.Core/Core/Authentication/DefaultAuthenticator.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public void Authenticate(IConnection connection, ConnectionDescription descripti
8787
if (!description.IsMasterResult.HasSaslSupportedMechs
8888
&& Feature.ScramSha256Authentication.IsSupported(description.ServerVersion))
8989
{
90-
var command = CustomizeInitialIsMasterCommand(HelloHelper.CreateCommand());
90+
var command = CustomizeInitialIsMasterCommand(HelloHelper.CreateCommand(_serverApi));
9191
var helloProtocol = HelloHelper.CreateProtocol(command, _serverApi);
9292
var helloResult = HelloHelper.GetResult(connection, helloProtocol, cancellationToken);
9393
var mergedHelloResult = new IsMasterResult(description.IsMasterResult.Wrapped.Merge(helloResult.Wrapped));
@@ -113,7 +113,7 @@ public async Task AuthenticateAsync(IConnection connection, ConnectionDescriptio
113113
if (!description.IsMasterResult.HasSaslSupportedMechs
114114
&& Feature.ScramSha256Authentication.IsSupported(description.ServerVersion))
115115
{
116-
var command = CustomizeInitialIsMasterCommand(HelloHelper.CreateCommand());
116+
var command = CustomizeInitialIsMasterCommand(HelloHelper.CreateCommand(_serverApi));
117117
var helloProtocol = HelloHelper.CreateProtocol(command, _serverApi);
118118
var helloResult = await HelloHelper.GetResultAsync(connection, helloProtocol, cancellationToken).ConfigureAwait(false);
119119
var mergedHelloResult = new IsMasterResult(description.IsMasterResult.Wrapped.Merge(helloResult.Wrapped));

src/MongoDB.Driver.Core/Core/Connections/CommandEventHelper.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
using MongoDB.Bson.IO;
2424
using MongoDB.Bson.Serialization.Serializers;
2525
using MongoDB.Driver.Core.Events;
26+
using MongoDB.Driver.Core.Misc;
2627
using MongoDB.Driver.Core.WireProtocol.Messages;
2728
using MongoDB.Driver.Core.WireProtocol.Messages.Encoders;
2829
using MongoDB.Driver.Core.WireProtocol.Messages.Encoders.BinaryEncoders;
@@ -1109,7 +1110,8 @@ private static bool ShouldRedactCommand(BsonDocument command)
11091110
case "copydb":
11101111
return true;
11111112

1112-
case "ismaster":
1113+
case "hello":
1114+
case OppressiveLanguageConstants.LegacyHelloCommandNameLowerCase:
11131115
return command.Names.Any(n => n.ToLowerInvariant() == "speculativeauthenticate");
11141116

11151117
default:

src/MongoDB.Driver.Core/Core/Connections/ConnectionInitializer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ private CommandWireProtocol<BsonDocument> CreateGetLastErrorProtocol(ServerApi s
160160

161161
private BsonDocument CreateInitialHelloCommand(IReadOnlyList<IAuthenticator> authenticators)
162162
{
163-
var command = HelloHelper.CreateCommand();
163+
var command = HelloHelper.CreateCommand(_serverApi);
164164
HelloHelper.AddClientDocumentToCommand(command, _clientDocument);
165165
HelloHelper.AddCompressorsToCommand(command, _compressors);
166166
return HelloHelper.CustomizeCommand(command, authenticators);

src/MongoDB.Driver.Core/Core/Connections/HelloHelper.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,17 @@ internal static BsonDocument AddCompressorsToCommand(BsonDocument command, IEnum
4343
return command.Add("compression", compressorsArray);
4444
}
4545

46-
internal static BsonDocument CreateCommand(TopologyVersion topologyVersion = null, TimeSpan? maxAwaitTime = null)
46+
internal static BsonDocument CreateCommand(ServerApi serverApi, TopologyVersion topologyVersion = null, TimeSpan? maxAwaitTime = null)
4747
{
4848
Ensure.That(
4949
(topologyVersion == null && !maxAwaitTime.HasValue) ||
5050
(topologyVersion != null && maxAwaitTime.HasValue),
5151
$"Both {nameof(topologyVersion)} and {nameof(maxAwaitTime)} must be filled or null.");
5252

53+
var helloCommandName = serverApi != null ? "hello" : OppressiveLanguageConstants.LegacyHelloCommandName;
5354
return new BsonDocument
5455
{
55-
{ "isMaster", 1 },
56+
{ helloCommandName, 1 },
5657
{ "topologyVersion", () => topologyVersion.ToBsonDocument(), topologyVersion != null },
5758
{ "maxAwaitTimeMS", () => (long)maxAwaitTime.Value.TotalMilliseconds, maxAwaitTime.HasValue }
5859
};

src/MongoDB.Driver.Core/Core/Connections/IsMasterResult.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,8 @@ public ServerType ServerType
293293

294294
if (_wrapped.Contains("setName"))
295295
{
296-
if (_wrapped.GetValue("ismaster", false).ToBoolean())
296+
if (_wrapped.GetValue("isWritablePrimary", false).ToBoolean() ||
297+
_wrapped.GetValue(OppressiveLanguageConstants.LegacyHelloResponseIsWritablePrimaryFieldName, false).ToBoolean())
297298
{
298299
return ServerType.ReplicaSetPrimary;
299300
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/* Copyright 2021-present MongoDB Inc.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
namespace MongoDB.Driver.Core.Misc
17+
{
18+
internal static class OppressiveLanguageConstants
19+
{
20+
public const string LegacyHelloCommandName = "isMaster";
21+
public const string LegacyHelloCommandNameLowerCase = "ismaster";
22+
// The isMaster command response contains a boolean field ismaster (all lowercase)
23+
// to indicate whether the current node is the primary.
24+
public const string LegacyHelloResponseIsWritablePrimaryFieldName = "ismaster";
25+
}
26+
}

src/MongoDB.Driver.Core/Core/Servers/RoundTripTimeMonitor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public async Task RunAsync()
9797
}
9898
else
9999
{
100-
var helloCommand = HelloHelper.CreateCommand();
100+
var helloCommand = HelloHelper.CreateCommand(_serverApi);
101101
var helloProtocol = HelloHelper.CreateProtocol(helloCommand, _serverApi);
102102

103103
var stopwatch = Stopwatch.StartNew();

src/MongoDB.Driver.Core/Core/Servers/ServerMonitor.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,11 +178,11 @@ private CommandWireProtocol<BsonDocument> InitializeHelloProtocol(IConnection co
178178

179179
var veryLargeHeartbeatInterval = TimeSpan.FromDays(1); // the server doesn't support Infinite value, so we set just a big enough value
180180
var maxAwaitTime = _serverMonitorSettings.HeartbeatInterval == Timeout.InfiniteTimeSpan ? veryLargeHeartbeatInterval : _serverMonitorSettings.HeartbeatInterval;
181-
helloCommand = HelloHelper.CreateCommand(connection.Description.IsMasterResult.TopologyVersion, maxAwaitTime);
181+
helloCommand = HelloHelper.CreateCommand(_serverApi, connection.Description.IsMasterResult.TopologyVersion, maxAwaitTime);
182182
}
183183
else
184184
{
185-
helloCommand = HelloHelper.CreateCommand();
185+
helloCommand = HelloHelper.CreateCommand(_serverApi);
186186
}
187187

188188
return HelloHelper.CreateProtocol(helloCommand, _serverApi, commandResponseHandling);

src/MongoDB.Driver.Core/Core/WireProtocol/CommandUsingCommandMessageWireProtocol.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ public TCommandResult Execute(IConnection connection, CancellationToken cancella
147147
}
148148
catch (Exception exception)
149149
{
150-
AddErrorLabelIfRequired(exception, connection.Description.ServerVersion);
150+
AddErrorLabelIfRequired(exception, connection.Description?.ServerVersion);
151151

152152
TransactionHelper.UnpinServerIfNeededOnCommandException(_session, exception);
153153
throw;
@@ -201,7 +201,7 @@ public async Task<TCommandResult> ExecuteAsync(IConnection connection, Cancellat
201201
}
202202
catch (Exception exception)
203203
{
204-
AddErrorLabelIfRequired(exception, connection.Description.ServerVersion);
204+
AddErrorLabelIfRequired(exception, connection.Description?.ServerVersion);
205205

206206
TransactionHelper.UnpinServerIfNeededOnCommandException(_session, exception);
207207
throw;
@@ -324,7 +324,7 @@ private Type0CommandMessageSection<BsonDocument> CreateType0Section(ConnectionDe
324324

325325
AddIfNotAlreadyAdded("$db", _databaseNamespace.DatabaseName);
326326

327-
if (connectionDescription.IsMasterResult.ServerType != ServerType.Standalone
327+
if (connectionDescription?.IsMasterResult.ServerType != ServerType.Standalone
328328
&& _readPreference != null
329329
&& _readPreference != ReadPreference.Primary)
330330
{

src/MongoDB.Driver.Core/Core/WireProtocol/CommandWireProtocol.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,14 @@ private IWireProtocol<TCommandResult> CreateSupportedWireProtocol(IConnection co
188188
{
189189
_cachedConnectionId = connection.ConnectionId;
190190
var serverVersion = connection.Description?.ServerVersion;
191-
if (serverVersion != null && Feature.CommandMessage.IsSupported(serverVersion))
191+
// If server API versioning has been requested, then we SHOULD send the initial hello command
192+
// using OP_MSG. Since this is the first message and buildInfo hasn't been sent yet,
193+
// connection.Description will be null and we can't rely on the semver check to determine if
194+
// the server supports OP_MSG.
195+
// As well since server API versioning is supported on MongoDB 5.0+, we also know that
196+
// OP_MSG will be supported regardless and can skip the semver checks for other messages.
197+
if (_serverApi != null ||
198+
(serverVersion != null && Feature.CommandMessage.IsSupported(serverVersion)))
192199
{
193200
return _cachedWireProtocol = CreateCommandUsingCommandMessageWireProtocol();
194201
}

0 commit comments

Comments
 (0)