Skip to content

Commit 64bce88

Browse files
committed
CSHARP-2226: Unable to send replSetInitiate to uninitiated replica set using direct connection
1 parent 557df86 commit 64bce88

File tree

8 files changed

+308
-32
lines changed

8 files changed

+308
-32
lines changed

src/MongoDB.Driver.Core/Core/Clusters/ClusterDescription.cs

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ namespace MongoDB.Driver.Core.Clusters
2929
public sealed class ClusterDescription : IEquatable<ClusterDescription>
3030
{
3131
#region static
32-
// static methods
32+
// internal static methods
3333
internal static ClusterDescription CreateInitial(ClusterId clusterId, ClusterConnectionMode connectionMode)
3434
{
3535
return new ClusterDescription(
@@ -38,6 +38,40 @@ internal static ClusterDescription CreateInitial(ClusterId clusterId, ClusterCon
3838
ClusterType.Unknown,
3939
Enumerable.Empty<ServerDescription>());
4040
}
41+
42+
// private static methods
43+
private static TimeSpan? CalculateLogicalSessionTimeout(ClusterConnectionMode connectionMode, IEnumerable<ServerDescription> servers)
44+
{
45+
TimeSpan? logicalSessionTimeout = null;
46+
47+
foreach (var server in SelectServersThatDetermineWhetherSessionsAreSupported(connectionMode, servers))
48+
{
49+
if (server.LogicalSessionTimeout == null)
50+
{
51+
return null;
52+
}
53+
54+
if (logicalSessionTimeout == null || server.LogicalSessionTimeout.Value < logicalSessionTimeout.Value)
55+
{
56+
logicalSessionTimeout = server.LogicalSessionTimeout;
57+
}
58+
}
59+
60+
return logicalSessionTimeout;
61+
}
62+
63+
private static IEnumerable<ServerDescription> SelectServersThatDetermineWhetherSessionsAreSupported(ClusterConnectionMode connectionMode, IEnumerable<ServerDescription> servers)
64+
{
65+
var connectedServers = servers.Where(s => s.State == ServerState.Connected);
66+
if (connectionMode == ClusterConnectionMode.Direct)
67+
{
68+
return connectedServers;
69+
}
70+
else
71+
{
72+
return connectedServers.Where(s => s.IsDataBearing);
73+
}
74+
}
4175
#endregion
4276

4377
// fields
@@ -65,7 +99,7 @@ public ClusterDescription(
6599
_connectionMode = connectionMode;
66100
_type = type;
67101
_servers = (servers ?? new ServerDescription[0]).OrderBy(n => n.EndPoint, new ToStringComparer<EndPoint>()).ToList();
68-
_logicalSessionTimeout = CalculateLogicalSessionTimeout(_servers);
102+
_logicalSessionTimeout = CalculateLogicalSessionTimeout(_connectionMode, _servers);
69103
}
70104

71105
// properties
@@ -240,29 +274,5 @@ public ClusterDescription WithType(ClusterType value)
240274
{
241275
return _type == value ? this : new ClusterDescription(_clusterId, _connectionMode, value, _servers);
242276
}
243-
244-
// private methods
245-
private TimeSpan? CalculateLogicalSessionTimeout(IEnumerable<ServerDescription> servers)
246-
{
247-
TimeSpan? logicalSessionTimeout = null;
248-
249-
foreach (var server in servers)
250-
{
251-
if (server.IsDataBearing)
252-
{
253-
if (server.LogicalSessionTimeout == null)
254-
{
255-
return null;
256-
}
257-
258-
if (logicalSessionTimeout == null || server.LogicalSessionTimeout.Value < logicalSessionTimeout.Value)
259-
{
260-
logicalSessionTimeout = server.LogicalSessionTimeout;
261-
}
262-
}
263-
}
264-
265-
return logicalSessionTimeout;
266-
}
267277
}
268278
}

src/MongoDB.Driver/MongoClient.cs

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,22 @@ namespace MongoDB.Driver
3333
/// <inheritdoc/>
3434
public class MongoClient : MongoClientBase
3535
{
36+
#region static
37+
// private static methods
38+
private static IEnumerable<ServerDescription> SelectServersThatDetermineWhetherSessionsAreSupported(ClusterConnectionMode connectionMode, IEnumerable<ServerDescription> servers)
39+
{
40+
var connectedServers = servers.Where(s => s.State == ServerState.Connected);
41+
if (connectionMode == ClusterConnectionMode.Direct)
42+
{
43+
return connectedServers;
44+
}
45+
else
46+
{
47+
return connectedServers.Where(s => s.IsDataBearing);
48+
}
49+
}
50+
#endregion
51+
3652
// private fields
3753
private readonly ICluster _cluster;
3854
private readonly IOperationExecutor _operationExecutor;
@@ -267,13 +283,21 @@ private async Task<bool> AreSessionsSupportedAsync(CancellationToken cancellatio
267283

268284
private bool? AreSessionsSupported(ClusterDescription clusterDescription)
269285
{
270-
if (clusterDescription.Servers.Any(s => s.IsDataBearing))
286+
if (clusterDescription.LogicalSessionTimeout.HasValue)
271287
{
272-
return clusterDescription.LogicalSessionTimeout.HasValue;
288+
return true;
273289
}
274290
else
275291
{
276-
return null;
292+
var selectedServers = SelectServersThatDetermineWhetherSessionsAreSupported(clusterDescription.ConnectionMode, clusterDescription.Servers).ToList();
293+
if (selectedServers.Count == 0)
294+
{
295+
return null;
296+
}
297+
else
298+
{
299+
return false;
300+
}
277301
}
278302
}
279303

@@ -407,7 +431,7 @@ private class AreSessionsSupportedServerSelector : IServerSelector
407431
public IEnumerable<ServerDescription> SelectServers(ClusterDescription cluster, IEnumerable<ServerDescription> servers)
408432
{
409433
ClusterDescription = cluster;
410-
return servers.Where(s => s.IsDataBearing);
434+
return SelectServersThatDetermineWhetherSessionsAreSupported(cluster.ConnectionMode, servers);
411435
}
412436
}
413437
}

tests/MongoDB.Bson.TestHelpers/Reflector.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ namespace MongoDB.Bson.TestHelpers
2020
{
2121
public static class Reflector
2222
{
23-
public static object GetFieldValue(object obj, string name)
23+
public static object GetFieldValue(object obj, string name, BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance)
2424
{
25-
var fieldInfo = obj.GetType().GetField(name, BindingFlags.NonPublic | BindingFlags.Instance);
25+
var fieldInfo = obj.GetType().GetField(name, flags);
2626
return fieldInfo.GetValue(obj);
2727
}
2828

@@ -33,5 +33,14 @@ public static object Invoke(object obj, string name)
3333
.Single();
3434
return methodInfo.Invoke(obj, new object[] { });
3535
}
36+
37+
public static object Invoke<T1>(object obj, string name, T1 arg1)
38+
{
39+
var parameterTypes = new[] { typeof(T1) };
40+
var methodInfo = obj.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
41+
.Where(m => m.Name == name && m.GetParameters().Select(p => p.ParameterType).SequenceEqual(parameterTypes))
42+
.Single();
43+
return methodInfo.Invoke(obj, new object[] { arg1 });
44+
}
3645
}
3746
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/* Copyright 2018-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+
using System;
17+
using System.Collections.Generic;
18+
using MongoDB.Bson;
19+
using MongoDB.Driver.Core.Clusters;
20+
using MongoDB.Driver.Core.Servers;
21+
22+
namespace MongoDB.Driver.Core.TestHelpers
23+
{
24+
public static class ClusterDescriptionParser
25+
{
26+
public static ClusterDescription Parse(BsonDocument args)
27+
{
28+
var clusterId = new ClusterId(args.GetValue("clusterId", 1).ToInt32());
29+
var connectionMode = (ClusterConnectionMode)Enum.Parse(typeof(ClusterConnectionMode), args.GetValue("connectionMode", "Automatic").AsString);
30+
var clusterType = (ClusterType)Enum.Parse(typeof(ClusterType), args["clusterType"].AsString);
31+
32+
var numberOfServers = args["servers"].AsBsonArray.Count;
33+
var servers = new List<ServerDescription>(numberOfServers);
34+
for (var index = 0; index < numberOfServers; index++)
35+
{
36+
var serverArgs = args["servers"].AsBsonArray[index].AsBsonDocument;
37+
if (!serverArgs.Contains("clusterId"))
38+
{
39+
serverArgs["clusterId"] = clusterId.Value;
40+
}
41+
if (!serverArgs.Contains("endPoint"))
42+
{
43+
var port = 27017 + index;
44+
serverArgs["endPoint"] = $"localhost:{port}";
45+
}
46+
47+
var server = ServerDescriptionParser.Parse(serverArgs);
48+
servers.Add(server);
49+
}
50+
51+
return new ClusterDescription(clusterId, connectionMode, clusterType, servers);
52+
}
53+
54+
public static ClusterDescription Parse(string json)
55+
{
56+
var args = BsonDocument.Parse(json);
57+
return Parse(args);
58+
}
59+
}
60+
}

tests/MongoDB.Driver.Core.TestHelpers/MongoDB.Driver.Core.TestHelpers.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,13 @@
5858
</Reference>
5959
</ItemGroup>
6060
<ItemGroup>
61+
<Compile Include="ClusterDescriptionParser.cs" />
6162
<Compile Include="CoreTestConfiguration.cs" />
6263
<Compile Include="EventCapturer.cs" />
6364
<Compile Include="ICoreSessionHandleExtensions.cs" />
6465
<Compile Include="Properties\AssemblyInfo.cs" />
6566
<Compile Include="TestCoreSession.cs" />
67+
<Compile Include="ServerDescriptionParser.cs" />
6668
<Compile Include="XunitExtensions\RequireServer.cs" />
6769
</ItemGroup>
6870
<ItemGroup>
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/* Copyright 2018-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+
using System;
17+
using System.Net;
18+
using System.Text.RegularExpressions;
19+
using MongoDB.Bson;
20+
using MongoDB.Driver.Core.Clusters;
21+
using MongoDB.Driver.Core.Servers;
22+
23+
namespace MongoDB.Driver.Core.TestHelpers
24+
{
25+
public static class ServerDescriptionParser
26+
{
27+
public static ServerDescription Parse(BsonDocument args)
28+
{
29+
var clusterId = new ClusterId(args.GetValue("clusterId", 1).ToInt32());
30+
var endPoint = ParseEndPoint(args.GetValue("endPoint", "localhost:27017").AsString);
31+
var serverId = new ServerId(clusterId, endPoint);
32+
var logicalSessionTimeoutMinutes = args.GetValue("logicalSessionTimeoutMinutes", BsonNull.Value);
33+
var logicalSessionTimeout = logicalSessionTimeoutMinutes.IsBsonNull ? (TimeSpan?)null : TimeSpan.FromMinutes(logicalSessionTimeoutMinutes.ToInt32());
34+
var state = (ServerState)Enum.Parse(typeof(ServerState), args["state"].AsString);
35+
var serverType = (ServerType)Enum.Parse(typeof(ServerType), args["type"].AsString);
36+
37+
return new ServerDescription(
38+
serverId,
39+
endPoint,
40+
logicalSessionTimeout: logicalSessionTimeout,
41+
state: state,
42+
type: serverType);
43+
}
44+
45+
public static ServerDescription Parse(string json)
46+
{
47+
var args = BsonDocument.Parse(json);
48+
return Parse(args);
49+
}
50+
51+
// private methods
52+
private static EndPoint ParseEndPoint(string value)
53+
{
54+
var colon = value.IndexOf(':');
55+
if (colon == -1)
56+
{
57+
return new DnsEndPoint(value, 27017);
58+
}
59+
else
60+
{
61+
var host = value.Substring(0, colon);
62+
var port = int.Parse(value.Substring(colon + 1));
63+
return new DnsEndPoint(host, port);
64+
}
65+
}
66+
}
67+
}

0 commit comments

Comments
 (0)