38
38
import java .util .Map ;
39
39
40
40
import static com .mongodb .ReadPreference .primary ;
41
+ import static com .mongodb .ReadPreference .primaryPreferred ;
41
42
import static com .mongodb .assertions .Assertions .isTrue ;
42
43
import static com .mongodb .connection .BsonWriterHelper .writePayload ;
44
+ import static com .mongodb .connection .ClusterConnectionMode .MULTIPLE ;
45
+ import static com .mongodb .connection .ClusterConnectionMode .SINGLE ;
46
+ import static com .mongodb .connection .ServerType .SHARD_ROUTER ;
43
47
44
48
/**
45
49
* A command message that uses OP_MSG or OP_QUERY to send the command.
@@ -52,15 +56,18 @@ final class CommandMessage extends RequestMessage {
52
56
private final SplittablePayload payload ;
53
57
private final FieldNameValidator payloadFieldNameValidator ;
54
58
private final boolean responseExpected ;
59
+ private final ClusterConnectionMode clusterConnectionMode ;
55
60
56
61
CommandMessage (final MongoNamespace namespace , final BsonDocument command , final FieldNameValidator commandFieldNameValidator ,
57
62
final ReadPreference readPreference , final MessageSettings settings ) {
58
- this (namespace , command , commandFieldNameValidator , readPreference , settings , true , null , null );
63
+ this (namespace , command , commandFieldNameValidator , readPreference , settings , true , null , null ,
64
+ MULTIPLE );
59
65
}
60
66
61
67
CommandMessage (final MongoNamespace namespace , final BsonDocument command , final FieldNameValidator commandFieldNameValidator ,
62
68
final ReadPreference readPreference , final MessageSettings settings , final boolean responseExpected ,
63
- final SplittablePayload payload , final FieldNameValidator payloadFieldNameValidator ) {
69
+ final SplittablePayload payload , final FieldNameValidator payloadFieldNameValidator ,
70
+ final ClusterConnectionMode clusterConnectionMode ) {
64
71
super (namespace .getFullName (), getOpCode (settings ), settings );
65
72
this .namespace = namespace ;
66
73
this .command = command ;
@@ -69,6 +76,7 @@ final class CommandMessage extends RequestMessage {
69
76
this .responseExpected = responseExpected ;
70
77
this .payload = payload ;
71
78
this .payloadFieldNameValidator = payloadFieldNameValidator ;
79
+ this .clusterConnectionMode = clusterConnectionMode ;
72
80
}
73
81
74
82
BsonDocument getCommandDocument (final ByteBufferBsonOutput bsonOutput ) {
@@ -102,7 +110,7 @@ boolean containsPayload() {
102
110
103
111
boolean isResponseExpected () {
104
112
isTrue ("The message must be encoded before determining if a response is expected" , getEncodingMetadata () != null );
105
- return calculateIsResponseExpected ();
113
+ return ! useOpMsg () || requireOpMsgResponse ();
106
114
}
107
115
108
116
ReadPreference getReadPreference () {
@@ -134,9 +142,9 @@ protected EncodingMetadata encodeMessageBodyWithMetadata(final BsonOutput bsonOu
134
142
}
135
143
136
144
// Write the flag bits
137
- bsonOutput .writeInt32 (flagPosition , getFlagBits ());
145
+ bsonOutput .writeInt32 (flagPosition , getOpMsgFlagBits ());
138
146
} else {
139
- bsonOutput .writeInt32 (0 );
147
+ bsonOutput .writeInt32 (getOpQueryFlagBits () );
140
148
bsonOutput .writeCString (namespace .getFullName ());
141
149
bsonOutput .writeInt32 (0 );
142
150
bsonOutput .writeInt32 (-1 );
@@ -167,20 +175,44 @@ private void addDocumentWithPayload(final BsonOutput bsonOutput, final int messa
167
175
getCodec (commandToEncode ).encode (bsonWriter , commandToEncode , EncoderContext .builder ().build ());
168
176
}
169
177
170
- private int getFlagBits () {
171
- if (calculateIsResponseExpected ()) {
178
+ private int getOpMsgFlagBits () {
179
+ return getOpMsgResponseExpectedFlagBit ();
180
+ }
181
+
182
+ private int getOpMsgResponseExpectedFlagBit () {
183
+ if (requireOpMsgResponse ()) {
172
184
return 0 ;
173
185
} else {
174
186
return 1 << 1 ;
175
187
}
176
188
}
177
189
178
- private boolean calculateIsResponseExpected () {
179
- // If there is another message in the payload require that the response is acknowledged
180
- if (!responseExpected && useOpMsg () && payload != null && payload .hasAnotherSplit ()) {
190
+ private boolean requireOpMsgResponse () {
191
+ if (responseExpected ) {
181
192
return true ;
193
+ } else {
194
+ return payload != null && payload .hasAnotherSplit ();
182
195
}
183
- return responseExpected ;
196
+ }
197
+
198
+ private int getOpQueryFlagBits () {
199
+ return getOpQuerySlaveOkFlagBit ();
200
+ }
201
+
202
+ private int getOpQuerySlaveOkFlagBit () {
203
+ if (isSlaveOk ()) {
204
+ return 1 << 2 ;
205
+ } else {
206
+ return 0 ;
207
+ }
208
+ }
209
+
210
+ private boolean isSlaveOk () {
211
+ return readPreference .isSlaveOk () || isDirectConnectionToNonShardRouter ();
212
+ }
213
+
214
+ private boolean isDirectConnectionToNonShardRouter () {
215
+ return clusterConnectionMode == SINGLE && getSettings ().getServerType () != SHARD_ROUTER ;
184
216
}
185
217
186
218
private boolean useOpMsg () {
@@ -206,10 +238,13 @@ private List<BsonElement> getExtraElements(final SessionContext sessionContext)
206
238
}
207
239
if (!isDefaultReadPreference (getReadPreference ())) {
208
240
extraElements .add (new BsonElement ("$readPreference" , getReadPreference ().toDocument ()));
241
+ } else if (isDirectConnectionToNonShardRouter ()) {
242
+ extraElements .add (new BsonElement ("$readPreference" , primaryPreferred ().toDocument ()));
209
243
}
210
244
return extraElements ;
211
245
}
212
246
247
+ @ SuppressWarnings ("BooleanMethodIsAlwaysInverted" )
213
248
private boolean isDefaultReadPreference (final ReadPreference readPreference ) {
214
249
return readPreference .equals (primary ());
215
250
}
0 commit comments