Skip to content

Commit db69b64

Browse files
committed
CSHARP-600: added support only sending read preference when using one other than primary and secondary preferred or when tags are present.
1 parent 84e6f61 commit db69b64

File tree

3 files changed

+56
-45
lines changed

3 files changed

+56
-45
lines changed

Driver/Core/MongoCursorEnumerator.cs

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ public class MongoCursorEnumerator<TDocument> : IEnumerator<TDocument>
4646
private int _replyIndex;
4747
private ResponseFlags _responseFlags;
4848
private long _openCursorId;
49+
private ReadPreference _readPreference;
50+
private QueryFlags _queryFlags;
4951

5052
// constructors
5153
/// <summary>
@@ -206,8 +208,24 @@ private MongoConnection AcquireConnection()
206208
{
207209
if (_serverInstance == null)
208210
{
211+
_readPreference = _cursor.ReadPreference;
212+
_queryFlags = _cursor.Flags;
213+
if (_readPreference.ReadPreferenceMode != ReadPreferenceMode.Primary && _cursor.Collection.Name == "$cmd")
214+
{
215+
var queryDocument = _cursor.Query.ToBsonDocument();
216+
var isSecondaryOk = MongoDefaults.CanCommandBeSentToSecondary(queryDocument);
217+
if (!isSecondaryOk)
218+
{
219+
// if the command can't be sent to a secondary, then we use primary here
220+
// regardless of the user's choice.
221+
_readPreference = ReadPreference.Primary;
222+
// remove the slaveOk bit from the flags
223+
_queryFlags &= ~QueryFlags.SlaveOk;
224+
}
225+
}
226+
209227
// first time we need a connection let Server.AcquireConnection pick the server instance
210-
var connection = _cursor.Server.AcquireConnection(_cursor.Database, _cursor.ReadPreference);
228+
var connection = _cursor.Server.AcquireConnection(_cursor.Database, _readPreference);
211229
_serverInstance = connection.ServerInstance;
212230
return connection;
213231
}
@@ -248,7 +266,7 @@ private MongoReplyMessage<TDocument> GetFirst()
248266
}
249267

250268
var writerSettings = _cursor.Collection.GetWriterSettings(connection);
251-
using (var message = new MongoQueryMessage(writerSettings, _cursor.Collection.FullName, _cursor.Flags, _cursor.Skip, numberToReturn, WrapQuery(), _cursor.Fields))
269+
using (var message = new MongoQueryMessage(writerSettings, _cursor.Collection.FullName, _queryFlags, _cursor.Skip, numberToReturn, WrapQuery(), _cursor.Fields))
252270
{
253271
return GetReply(connection, message);
254272
}
@@ -331,15 +349,14 @@ private void KillCursor()
331349
private IMongoQuery WrapQuery()
332350
{
333351
BsonDocument formattedReadPreference = null;
334-
if (_serverInstance.InstanceType == MongoServerInstanceType.ShardRouter)
352+
if (_serverInstance.InstanceType == MongoServerInstanceType.ShardRouter
353+
&& _readPreference.ReadPreferenceMode != ReadPreferenceMode.Primary)
335354
{
336-
var readPreference = _cursor.ReadPreference;
337-
338355
BsonArray tagSetsArray = null;
339-
if (readPreference.ReadPreferenceMode != ReadPreferenceMode.Primary && readPreference.TagSets != null)
356+
if (_readPreference.TagSets != null)
340357
{
341358
tagSetsArray = new BsonArray();
342-
foreach (var tagSet in readPreference.TagSets)
359+
foreach (var tagSet in _readPreference.TagSets)
343360
{
344361
var tagSetDocument = new BsonDocument();
345362
foreach (var tag in tagSet)
@@ -350,11 +367,14 @@ private IMongoQuery WrapQuery()
350367
}
351368
}
352369

353-
formattedReadPreference = new BsonDocument
370+
if (tagSetsArray != null || _readPreference.ReadPreferenceMode != ReadPreferenceMode.SecondaryPreferred)
354371
{
355-
{ "mode", MongoUtils.ToCamelCase(readPreference.ReadPreferenceMode.ToString()) },
356-
{ "tags", tagSetsArray, tagSetsArray != null } // optional
357-
};
372+
formattedReadPreference = new BsonDocument
373+
{
374+
{ "mode", MongoUtils.ToCamelCase(_readPreference.ReadPreferenceMode.ToString()) },
375+
{ "tags", tagSetsArray, tagSetsArray != null } // optional
376+
};
377+
}
358378
}
359379

360380
if (_cursor.Options == null && formattedReadPreference == null)

Driver/MongoDefaults.cs

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -265,26 +265,17 @@ private static bool CanCommandBeSendToSecondaryDefault(BsonDocument document)
265265
return false;
266266
}
267267

268-
var command = document.GetElement(0);
268+
var commandName = document.GetElement(0).Name;
269269

270-
if (__secondaryOkCommands.Contains(command.Name))
270+
if (__secondaryOkCommands.Contains(commandName))
271271
{
272272
return true;
273273
}
274274

275-
if (!command.Value.IsBsonDocument)
275+
BsonValue outValue;
276+
if (document.TryGetValue("out", out outValue) && outValue.IsBsonDocument)
276277
{
277-
return false;
278-
}
279-
280-
if (command.Name.Equals("mapreduce", StringComparison.InvariantCultureIgnoreCase))
281-
{
282-
var options = command.Value.AsBsonDocument;
283-
BsonValue outValue;
284-
if (options.TryGetValue("out", out outValue) && outValue.IsBsonDocument)
285-
{
286-
return outValue.AsBsonDocument.Contains("inline");
287-
}
278+
return outValue.AsBsonDocument.Contains("inline");
288279
}
289280

290281
return false;

DriverUnitTests/MongoDefaultsTests.cs

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ public void TestCanSendCommandToSecondary(string command, bool expectedResult)
2929
[Test]
3030
public void TestCanSendInlineMapReduceToSecondary()
3131
{
32-
var doc = new BsonDocument("mapreduce",
33-
new BsonDocument
34-
{
35-
{ "map", "emit()" },
36-
{ "reduce", "return 1" },
37-
{ "out", new BsonDocument("inline", 1) }
38-
});
32+
var doc = new BsonDocument
33+
{
34+
{ "mapreduce", "col" },
35+
{ "map", "emit()" },
36+
{ "reduce", "return 1" },
37+
{ "out", new BsonDocument("inline", 1) }
38+
};
3939

4040
var result = MongoDefaults.CanCommandBeSentToSecondary(doc);
4141

@@ -45,12 +45,12 @@ public void TestCanSendInlineMapReduceToSecondary()
4545
[Test]
4646
public void TestCannotSendNonInlineMapReduceToSecondary()
4747
{
48-
var doc = new BsonDocument("mapreduce",
49-
new BsonDocument
50-
{
51-
{ "map", "emit()" },
52-
{ "reduce", "return 1" }
53-
});
48+
var doc = new BsonDocument
49+
{
50+
{ "mapreduce", "col" },
51+
{ "map", "emit()" },
52+
{ "reduce", "return 1" }
53+
};
5454

5555
var result = MongoDefaults.CanCommandBeSentToSecondary(doc);
5656

@@ -60,13 +60,13 @@ public void TestCannotSendNonInlineMapReduceToSecondary()
6060
[Test]
6161
public void TestCannotSendNonInlineMapReduceToSecondary2()
6262
{
63-
var doc = new BsonDocument("mapreduce",
64-
new BsonDocument
65-
{
66-
{ "map", "emit()" },
67-
{ "reduce", "return 1" },
68-
{ "out", new BsonDocument("merge", "foo") }
69-
});
63+
var doc = new BsonDocument
64+
{
65+
{ "mapreduce", "col" },
66+
{ "map", "emit()" },
67+
{ "reduce", "return 1" },
68+
{ "out", new BsonDocument("merge", "funny") }
69+
};
7070

7171
var result = MongoDefaults.CanCommandBeSentToSecondary(doc);
7272

0 commit comments

Comments
 (0)