summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db')
-rw-r--r--src/mongo/db/cloner.cpp5
-rw-r--r--src/mongo/db/dbdirectclient.cpp15
-rw-r--r--src/mongo/db/dbdirectclient.h19
-rw-r--r--src/mongo/db/pipeline/process_interface/replica_set_node_process_interface.cpp5
-rw-r--r--src/mongo/db/pipeline/process_interface/shardsvr_process_interface.cpp46
-rw-r--r--src/mongo/db/pipeline/sharded_agg_helpers.cpp17
-rw-r--r--src/mongo/db/query/query_request.cpp4
-rw-r--r--src/mongo/db/read_concern_mongod.cpp4
-rw-r--r--src/mongo/db/repl/SConscript1
-rw-r--r--src/mongo/db/repl/collection_cloner.cpp10
-rw-r--r--src/mongo/db/repl/initial_syncer.cpp3
-rw-r--r--src/mongo/db/repl/oplog_interface_remote.cpp11
-rw-r--r--src/mongo/db/repl/read_concern_args.cpp5
-rw-r--r--src/mongo/db/repl/read_concern_args.h2
-rw-r--r--src/mongo/db/repl/replication_info.cpp10
-rw-r--r--src/mongo/db/repl/roll_back_local_operations_test.cpp3
-rw-r--r--src/mongo/db/repl/rollback_source_impl.cpp9
-rw-r--r--src/mongo/db/repl/sync_source_resolver.cpp8
-rw-r--r--src/mongo/db/s/add_shard_cmd.cpp2
-rw-r--r--src/mongo/db/s/balancer/migration_manager.cpp11
-rw-r--r--src/mongo/db/s/migration_chunk_cloner_source_legacy.cpp22
-rw-r--r--src/mongo/db/s/migration_util.cpp4
-rw-r--r--src/mongo/db/s/shard_key_util.cpp3
-rw-r--r--src/mongo/db/sessions_collection.cpp12
-rw-r--r--src/mongo/db/write_concern_options.cpp6
-rw-r--r--src/mongo/db/write_concern_options.h1
26 files changed, 157 insertions, 81 deletions
diff --git a/src/mongo/db/cloner.cpp b/src/mongo/db/cloner.cpp
index 4f444b9f755..c76f86163b3 100644
--- a/src/mongo/db/cloner.cpp
+++ b/src/mongo/db/cloner.cpp
@@ -58,6 +58,7 @@
#include "mongo/db/op_observer.h"
#include "mongo/db/ops/insert.h"
#include "mongo/db/repl/isself.h"
+#include "mongo/db/repl/read_concern_args.h"
#include "mongo/db/repl/replication_coordinator.h"
#include "mongo/db/service_context.h"
#include "mongo/db/storage/durable_catalog.h"
@@ -311,7 +312,9 @@ void Cloner::copy(OperationContext* opCtx,
from_collection,
query,
nullptr,
- options);
+ options,
+ 0 /* batchSize */,
+ repl::ReadConcernArgs::kImplicitDefault);
}
uassert(ErrorCodes::PrimarySteppedDown,
diff --git a/src/mongo/db/dbdirectclient.cpp b/src/mongo/db/dbdirectclient.cpp
index 84818dcf8c4..6c8a8d3d43e 100644
--- a/src/mongo/db/dbdirectclient.cpp
+++ b/src/mongo/db/dbdirectclient.cpp
@@ -166,15 +166,22 @@ unique_ptr<DBClientCursor> DBDirectClient::query(const NamespaceStringOrUUID& ns
int nToSkip,
const BSONObj* fieldsToReturn,
int queryOptions,
- int batchSize) {
+ int batchSize,
+ boost::optional<BSONObj> readConcernObj) {
+ invariant(!readConcernObj, "passing readConcern to DBDirectClient functions is not supported");
return DBClientBase::query(
nsOrUuid, query, nToReturn, nToSkip, fieldsToReturn, queryOptions, batchSize);
}
-long long DBDirectClient::count(
- const NamespaceStringOrUUID nsOrUuid, const BSONObj& query, int options, int limit, int skip) {
+long long DBDirectClient::count(const NamespaceStringOrUUID nsOrUuid,
+ const BSONObj& query,
+ int options,
+ int limit,
+ int skip,
+ boost::optional<BSONObj> readConcernObj) {
+ invariant(!readConcernObj, "passing readConcern to DBDirectClient functions is not supported");
DirectClientScope directClientScope(_opCtx);
- BSONObj cmdObj = _countCmd(nsOrUuid, query, options, limit, skip);
+ BSONObj cmdObj = _countCmd(nsOrUuid, query, options, limit, skip, boost::none);
auto dbName = (nsOrUuid.uuid() ? nsOrUuid.dbname() : (*nsOrUuid.nss()).db().toString());
diff --git a/src/mongo/db/dbdirectclient.h b/src/mongo/db/dbdirectclient.h
index 9ff0dc9cd80..0554334d6fd 100644
--- a/src/mongo/db/dbdirectclient.h
+++ b/src/mongo/db/dbdirectclient.h
@@ -58,13 +58,15 @@ public:
// XXX: is this valid or useful?
void setOpCtx(OperationContext* opCtx);
- virtual std::unique_ptr<DBClientCursor> query(const NamespaceStringOrUUID& nsOrUuid,
- Query query,
- int nToReturn = 0,
- int nToSkip = 0,
- const BSONObj* fieldsToReturn = nullptr,
- int queryOptions = 0,
- int batchSize = 0);
+ virtual std::unique_ptr<DBClientCursor> query(
+ const NamespaceStringOrUUID& nsOrUuid,
+ Query query,
+ int nToReturn = 0,
+ int nToSkip = 0,
+ const BSONObj* fieldsToReturn = nullptr,
+ int queryOptions = 0,
+ int batchSize = 0,
+ boost::optional<BSONObj> readConcernObj = boost::none);
virtual bool isFailed() const;
@@ -85,7 +87,8 @@ public:
const BSONObj& query = BSONObj(),
int options = 0,
int limit = 0,
- int skip = 0);
+ int skip = 0,
+ boost::optional<BSONObj> readConcernObj = boost::none);
virtual ConnectionString::ConnectionType type() const;
diff --git a/src/mongo/db/pipeline/process_interface/replica_set_node_process_interface.cpp b/src/mongo/db/pipeline/process_interface/replica_set_node_process_interface.cpp
index 009168fd88d..70720b4442b 100644
--- a/src/mongo/db/pipeline/process_interface/replica_set_node_process_interface.cpp
+++ b/src/mongo/db/pipeline/process_interface/replica_set_node_process_interface.cpp
@@ -210,10 +210,7 @@ StatusWith<BSONObj> ReplicaSetNodeProcessInterface::_executeCommandOnPrimary(
void ReplicaSetNodeProcessInterface::_attachGenericCommandArgs(OperationContext* opCtx,
BSONObjBuilder* cmd) const {
- auto writeConcern = opCtx->getWriteConcern();
- if (!writeConcern.usedDefault) {
- cmd->append(WriteConcernOptions::kWriteConcernField, writeConcern.toBSON());
- }
+ cmd->append(WriteConcernOptions::kWriteConcernField, opCtx->getWriteConcern().toBSON());
logical_session_id_helpers::serializeLsidAndTxnNumber(opCtx, cmd);
}
diff --git a/src/mongo/db/pipeline/process_interface/shardsvr_process_interface.cpp b/src/mongo/db/pipeline/process_interface/shardsvr_process_interface.cpp
index 9fa7b4fc59d..dcca4ab8dd6 100644
--- a/src/mongo/db/pipeline/process_interface/shardsvr_process_interface.cpp
+++ b/src/mongo/db/pipeline/process_interface/shardsvr_process_interface.cpp
@@ -59,18 +59,6 @@ using write_ops::Insert;
using write_ops::Update;
using write_ops::UpdateOpEntry;
-namespace {
-
-// Attaches the write concern to the given batch request. If it looks like 'writeConcern' has
-// been default initialized to {w: 0, wtimeout: 0} then we do not bother attaching it.
-void attachWriteConcern(const WriteConcernOptions& writeConcern, BatchedCommandRequest* request) {
- if (!writeConcern.wMode.empty() || writeConcern.wNumNodes > 0) {
- request->setWriteConcern(writeConcern.toBSON());
- }
-}
-
-} // namespace
-
bool ShardServerProcessInterface::isSharded(OperationContext* opCtx, const NamespaceString& nss) {
Lock::DBLock dbLock(opCtx, nss.db(), MODE_IS);
Lock::CollectionLock collLock(opCtx, nss, MODE_IS);
@@ -123,8 +111,7 @@ Status ShardServerProcessInterface::insert(const boost::intrusive_ptr<Expression
BatchedCommandRequest insertCommand(
buildInsertOp(ns, std::move(objs), expCtx->bypassDocumentValidation));
- // If applicable, attach a write concern to the batched command request.
- attachWriteConcern(wc, &insertCommand);
+ insertCommand.setWriteConcern(wc.toBSON());
ClusterWriter::write(expCtx->opCtx, insertCommand, &stats, &response, targetEpoch);
@@ -144,8 +131,7 @@ StatusWith<MongoProcessInterface::UpdateResult> ShardServerProcessInterface::upd
BatchedCommandRequest updateCommand(buildUpdateOp(expCtx, ns, std::move(batch), upsert, multi));
- // If applicable, attach a write concern to the batched command request.
- attachWriteConcern(wc, &updateCommand);
+ updateCommand.setWriteConcern(wc.toBSON());
ClusterWriter::write(expCtx->opCtx, updateCommand, &stats, &response, targetEpoch);
@@ -176,10 +162,8 @@ void ShardServerProcessInterface::renameIfOptionsAndIndexesHaveNotChanged(
auto newCmdObj = CommonMongodProcessInterface::_convertRenameToInternalRename(
opCtx, renameCommandObj, originalCollectionOptions, originalIndexes);
BSONObjBuilder newCmdWithWriteConcernBuilder(std::move(newCmdObj));
- if (!opCtx->getWriteConcern().usedDefault) {
- newCmdWithWriteConcernBuilder.append(WriteConcernOptions::kWriteConcernField,
- opCtx->getWriteConcern().toBSON());
- }
+ newCmdWithWriteConcernBuilder.append(WriteConcernOptions::kWriteConcernField,
+ opCtx->getWriteConcern().toBSON());
newCmdObj = newCmdWithWriteConcernBuilder.done();
auto cachedDbInfo =
uassertStatusOK(Grid::get(opCtx)->catalogCache()->getDatabase(opCtx, destinationNs.db()));
@@ -226,12 +210,10 @@ void ShardServerProcessInterface::createCollection(OperationContext* opCtx,
const BSONObj& cmdObj) {
auto cachedDbInfo =
uassertStatusOK(Grid::get(opCtx)->catalogCache()->getDatabase(opCtx, dbName));
- BSONObj finalCmdObj = cmdObj;
- if (!opCtx->getWriteConcern().usedDefault) {
- auto writeObj =
- BSON(WriteConcernOptions::kWriteConcernField << opCtx->getWriteConcern().toBSON());
- finalCmdObj = cmdObj.addField(writeObj.getField(WriteConcernOptions::kWriteConcernField));
- }
+ BSONObjBuilder finalCmdBuilder(cmdObj);
+ finalCmdBuilder.append(WriteConcernOptions::kWriteConcernField,
+ opCtx->getWriteConcern().toBSON());
+ BSONObj finalCmdObj = finalCmdBuilder.obj();
auto response =
executeCommandAgainstDatabasePrimary(opCtx,
dbName,
@@ -256,10 +238,8 @@ void ShardServerProcessInterface::createIndexesOnEmptyCollection(
BSONObjBuilder newCmdBuilder;
newCmdBuilder.append("createIndexes", ns.coll());
newCmdBuilder.append("indexes", indexSpecs);
- if (!opCtx->getWriteConcern().usedDefault) {
- newCmdBuilder.append(WriteConcernOptions::kWriteConcernField,
- opCtx->getWriteConcern().toBSON());
- }
+ newCmdBuilder.append(WriteConcernOptions::kWriteConcernField,
+ opCtx->getWriteConcern().toBSON());
auto cmdObj = newCmdBuilder.done();
auto response =
executeCommandAgainstDatabasePrimary(opCtx,
@@ -285,10 +265,8 @@ void ShardServerProcessInterface::dropCollection(OperationContext* opCtx,
uassertStatusOK(Grid::get(opCtx)->catalogCache()->getDatabase(opCtx, ns.db()));
BSONObjBuilder newCmdBuilder;
newCmdBuilder.append("drop", ns.coll());
- if (!opCtx->getWriteConcern().usedDefault) {
- newCmdBuilder.append(WriteConcernOptions::kWriteConcernField,
- opCtx->getWriteConcern().toBSON());
- }
+ newCmdBuilder.append(WriteConcernOptions::kWriteConcernField,
+ opCtx->getWriteConcern().toBSON());
auto cmdObj = newCmdBuilder.done();
auto response =
executeCommandAgainstDatabasePrimary(opCtx,
diff --git a/src/mongo/db/pipeline/sharded_agg_helpers.cpp b/src/mongo/db/pipeline/sharded_agg_helpers.cpp
index 5b3556b6089..eeb614813ef 100644
--- a/src/mongo/db/pipeline/sharded_agg_helpers.cpp
+++ b/src/mongo/db/pipeline/sharded_agg_helpers.cpp
@@ -108,13 +108,16 @@ RemoteCursor openChangeStreamNewShardMonitor(const boost::intrusive_ptr<Expressi
aggReq.setFromMongos(true);
aggReq.setNeedsMerge(true);
aggReq.setBatchSize(0);
- auto configCursor =
- establishCursors(expCtx->opCtx,
- expCtx->mongoProcessInterface->taskExecutor,
- aggReq.getNamespaceString(),
- ReadPreferenceSetting{ReadPreference::PrimaryPreferred},
- {{configShard->getId(), aggReq.serializeToCommandObj().toBson()}},
- false);
+ auto cmdObjWithRWC = applyReadWriteConcern(expCtx->opCtx,
+ true, /* appendRC */
+ !expCtx->explain, /* appendWC */
+ aggReq.serializeToCommandObj().toBson());
+ auto configCursor = establishCursors(expCtx->opCtx,
+ expCtx->mongoProcessInterface->taskExecutor,
+ aggReq.getNamespaceString(),
+ ReadPreferenceSetting{ReadPreference::PrimaryPreferred},
+ {{configShard->getId(), cmdObjWithRWC}},
+ false);
invariant(configCursor.size() == 1);
return std::move(*configCursor.begin());
}
diff --git a/src/mongo/db/query/query_request.cpp b/src/mongo/db/query/query_request.cpp
index cd308aae77a..dd80516535c 100644
--- a/src/mongo/db/query/query_request.cpp
+++ b/src/mongo/db/query/query_request.cpp
@@ -835,6 +835,10 @@ Status QueryRequest::init(int ntoskip,
} else {
_filter = queryObj.getOwned();
}
+ // It's not possible to specify readConcern in a legacy query message, so initialize it to
+ // an empty readConcern object, ie. equivalent to `readConcern: {}`. This ensures that
+ // mongos passes this empty readConcern to shards.
+ _readConcern = BSONObj();
} else {
// This is the debugging code path.
_filter = queryObj.getOwned();
diff --git a/src/mongo/db/read_concern_mongod.cpp b/src/mongo/db/read_concern_mongod.cpp
index 54588856e58..dbe4ba193cf 100644
--- a/src/mongo/db/read_concern_mongod.cpp
+++ b/src/mongo/db/read_concern_mongod.cpp
@@ -180,7 +180,9 @@ Status makeNoopWriteIfNeeded(OperationContext* opCtx, LogicalTime clusterTime) {
"admin",
BSON("appendOplogNote"
<< 1 << "maxClusterTime" << clusterTime.asTimestamp() << "data"
- << BSON("noop write for afterClusterTime read concern" << 1)),
+ << BSON("noop write for afterClusterTime read concern" << 1)
+ << WriteConcernOptions::kWriteConcernField
+ << WriteConcernOptions::kImplicitDefault),
Shard::RetryPolicy::kIdempotent);
status = swRes.getStatus();
std::get<1>(myWriteRequest)->set(status);
diff --git a/src/mongo/db/repl/SConscript b/src/mongo/db/repl/SConscript
index e983f6acbd4..4425209c8db 100644
--- a/src/mongo/db/repl/SConscript
+++ b/src/mongo/db/repl/SConscript
@@ -895,6 +895,7 @@ env.Library(
LIBDEPS=[
'oplog_entry',
'optime',
+ 'read_concern_args',
'$BUILD_DIR/mongo/base',
'$BUILD_DIR/mongo/client/fetcher',
'$BUILD_DIR/mongo/db/namespace_string',
diff --git a/src/mongo/db/repl/collection_cloner.cpp b/src/mongo/db/repl/collection_cloner.cpp
index b4c54057e31..c98cb47d034 100644
--- a/src/mongo/db/repl/collection_cloner.cpp
+++ b/src/mongo/db/repl/collection_cloner.cpp
@@ -132,7 +132,12 @@ BaseCloner::AfterStageBehavior CollectionCloner::CollectionClonerStage::run() {
}
BaseCloner::AfterStageBehavior CollectionCloner::countStage() {
- auto count = getClient()->count(_sourceDbAndUuid, {} /* Query */, QueryOption_SlaveOk);
+ auto count = getClient()->count(_sourceDbAndUuid,
+ {} /* Query */,
+ QueryOption_SlaveOk,
+ 0 /* limit */,
+ 0 /* skip */,
+ ReadConcernArgs::kImplicitDefault);
// The count command may return a negative value after an unclean shutdown,
// so we set it to zero here to avoid aborting the collection clone.
@@ -231,7 +236,8 @@ void CollectionCloner::runQuery() {
nullptr /* fieldsToReturn */,
QueryOption_NoCursorTimeout | QueryOption_SlaveOk |
(collectionClonerUsesExhaust ? QueryOption_Exhaust : 0),
- _collectionClonerBatchSize);
+ _collectionClonerBatchSize,
+ ReadConcernArgs::kImplicitDefault);
} catch (...) {
auto status = exceptionToStatus();
diff --git a/src/mongo/db/repl/initial_syncer.cpp b/src/mongo/db/repl/initial_syncer.cpp
index 6bc07e723b7..39ad438a288 100644
--- a/src/mongo/db/repl/initial_syncer.cpp
+++ b/src/mongo/db/repl/initial_syncer.cpp
@@ -1736,7 +1736,8 @@ void InitialSyncer::_finishCallback(StatusWith<OpTimeAndWallTime> lastApplied) {
Status InitialSyncer::_scheduleLastOplogEntryFetcher_inlock(
Fetcher::CallbackFn callback, LastOplogEntryFetcherRetryStrategy retryStrategy) {
BSONObj query = BSON("find" << _opts.remoteOplogNS.coll() << "sort" << BSON("$natural" << -1)
- << "limit" << 1);
+ << "limit" << 1 << ReadConcernArgs::kReadConcernFieldName
+ << ReadConcernArgs::kImplicitDefault);
_lastOplogEntryFetcher = std::make_unique<Fetcher>(
_exec,
diff --git a/src/mongo/db/repl/oplog_interface_remote.cpp b/src/mongo/db/repl/oplog_interface_remote.cpp
index a71aae7cb15..883596318b9 100644
--- a/src/mongo/db/repl/oplog_interface_remote.cpp
+++ b/src/mongo/db/repl/oplog_interface_remote.cpp
@@ -34,6 +34,7 @@
#include "mongo/client/dbclient_base.h"
#include "mongo/client/dbclient_cursor.h"
#include "mongo/db/jsobj.h"
+#include "mongo/db/repl/read_concern_args.h"
#include "mongo/util/str.h"
namespace mongo {
@@ -83,8 +84,14 @@ std::unique_ptr<OplogInterface::Iterator> OplogInterfaceRemote::makeIterator() c
const Query query = Query().sort(BSON("$natural" << -1));
const BSONObj fields = BSON("ts" << 1 << "t" << 1);
return std::unique_ptr<OplogInterface::Iterator>(
- new OplogIteratorRemote(_getConnection()->query(
- NamespaceString(_collectionName), query, 0, 0, &fields, 0, _batchSize)));
+ new OplogIteratorRemote(_getConnection()->query(NamespaceString(_collectionName),
+ query,
+ 0,
+ 0,
+ &fields,
+ 0,
+ _batchSize,
+ ReadConcernArgs::kImplicitDefault)));
}
std::unique_ptr<TransactionHistoryIteratorBase>
diff --git a/src/mongo/db/repl/read_concern_args.cpp b/src/mongo/db/repl/read_concern_args.cpp
index 2ef071a38cc..0c446ce4780 100644
--- a/src/mongo/db/repl/read_concern_args.cpp
+++ b/src/mongo/db/repl/read_concern_args.cpp
@@ -57,6 +57,11 @@ const ReadConcernArgs& ReadConcernArgs::get(const OperationContext* opCtx) {
}
+// The "kImplicitDefault" read concern, used by internal operations, is deliberately empty (no
+// 'level' specified). This allows internal operations to specify a read concern, while still
+// allowing it to be either local or available on sharded secondaries.
+const BSONObj ReadConcernArgs::kImplicitDefault;
+
ReadConcernArgs::ReadConcernArgs() : _specified(false) {}
ReadConcernArgs::ReadConcernArgs(boost::optional<ReadConcernLevel> level)
diff --git a/src/mongo/db/repl/read_concern_args.h b/src/mongo/db/repl/read_concern_args.h
index 1adba9777fc..46353040528 100644
--- a/src/mongo/db/repl/read_concern_args.h
+++ b/src/mongo/db/repl/read_concern_args.h
@@ -55,6 +55,8 @@ public:
static constexpr StringData kAtClusterTimeFieldName = "atClusterTime"_sd;
static constexpr StringData kLevelFieldName = "level"_sd;
+ static const BSONObj kImplicitDefault;
+
/**
* Represents the internal mechanism an operation uses to satisfy 'majority' read concern.
*/
diff --git a/src/mongo/db/repl/replication_info.cpp b/src/mongo/db/repl/replication_info.cpp
index fd8ce22e8d0..bf33e4334d7 100644
--- a/src/mongo/db/repl/replication_info.cpp
+++ b/src/mongo/db/repl/replication_info.cpp
@@ -185,9 +185,15 @@ TopologyVersion appendReplicationInfo(OperationContext* opCtx,
DBClientConnection* cliConn = dynamic_cast<DBClientConnection*>(&conn.conn());
if (cliConn && replAuthenticate(cliConn).isOK()) {
BSONObj first = conn->findOne((string) "local.oplog.$" + sourcename,
- Query().sort(BSON("$natural" << 1)));
+ Query().sort(BSON("$natural" << 1)),
+ nullptr /* fieldsToReturn */,
+ 0 /* queryOptions */,
+ ReadConcernArgs::kImplicitDefault);
BSONObj last = conn->findOne((string) "local.oplog.$" + sourcename,
- Query().sort(BSON("$natural" << -1)));
+ Query().sort(BSON("$natural" << -1)),
+ nullptr /* fieldsToReturn */,
+ 0 /* queryOptions */,
+ ReadConcernArgs::kImplicitDefault);
bb.appendDate("masterFirst", first["ts"].timestampTime());
bb.appendDate("masterLast", last["ts"].timestampTime());
const auto lag = (last["ts"].timestampTime() - s["syncedTo"].timestampTime());
diff --git a/src/mongo/db/repl/roll_back_local_operations_test.cpp b/src/mongo/db/repl/roll_back_local_operations_test.cpp
index f51e5404d4b..6862dbf20bb 100644
--- a/src/mongo/db/repl/roll_back_local_operations_test.cpp
+++ b/src/mongo/db/repl/roll_back_local_operations_test.cpp
@@ -326,7 +326,8 @@ public:
int nToSkip,
const BSONObj* fieldsToReturn,
int queryOptions,
- int batchSize) override {
+ int batchSize,
+ boost::optional<BSONObj> readConcernObj) override {
if (_initFailuresLeft > 0) {
_initFailuresLeft--;
LOGV2(21657,
diff --git a/src/mongo/db/repl/rollback_source_impl.cpp b/src/mongo/db/repl/rollback_source_impl.cpp
index 8d06503b597..bc111c75397 100644
--- a/src/mongo/db/repl/rollback_source_impl.cpp
+++ b/src/mongo/db/repl/rollback_source_impl.cpp
@@ -35,6 +35,7 @@
#include "mongo/db/cloner.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/namespace_string.h"
+#include "mongo/db/repl/read_concern_args.h"
#include "mongo/db/repl/replication_auth.h"
#include "mongo/util/assert_util.h"
#include "mongo/util/str.h"
@@ -68,19 +69,21 @@ int RollbackSourceImpl::getRollbackId() const {
BSONObj RollbackSourceImpl::getLastOperation() const {
const Query query = Query().sort(BSON("$natural" << -1));
- return _getConnection()->findOne(_collectionName, query, nullptr, QueryOption_SlaveOk);
+ return _getConnection()->findOne(
+ _collectionName, query, nullptr, QueryOption_SlaveOk, ReadConcernArgs::kImplicitDefault);
}
BSONObj RollbackSourceImpl::findOne(const NamespaceString& nss, const BSONObj& filter) const {
return _getConnection()
- ->findOne(nss.toString(), filter, nullptr, QueryOption_SlaveOk)
+ ->findOne(
+ nss.toString(), filter, nullptr, QueryOption_SlaveOk, ReadConcernArgs::kImplicitDefault)
.getOwned();
}
std::pair<BSONObj, NamespaceString> RollbackSourceImpl::findOneByUUID(const std::string& db,
UUID uuid,
const BSONObj& filter) const {
- return _getConnection()->findOneByUUID(db, uuid, filter);
+ return _getConnection()->findOneByUUID(db, uuid, filter, ReadConcernArgs::kImplicitDefault);
}
void RollbackSourceImpl::copyCollectionFromRemote(OperationContext* opCtx,
diff --git a/src/mongo/db/repl/sync_source_resolver.cpp b/src/mongo/db/repl/sync_source_resolver.cpp
index a7e289e3996..e75c1782192 100644
--- a/src/mongo/db/repl/sync_source_resolver.cpp
+++ b/src/mongo/db/repl/sync_source_resolver.cpp
@@ -173,9 +173,7 @@ std::unique_ptr<Fetcher> SyncSourceResolver::_makeFirstOplogEntryFetcher(
<< "projection"
<< BSON(OplogEntryBase::kTimestampFieldName
<< 1 << OplogEntryBase::kTermFieldName << 1)
- << "readConcern"
- << BSON("level"
- << "local")),
+ << ReadConcernArgs::kReadConcernFieldName << ReadConcernArgs::kImplicitDefault),
[=](const StatusWith<Fetcher::QueryResponse>& response,
Fetcher::NextAction*,
BSONObjBuilder*) {
@@ -198,9 +196,7 @@ std::unique_ptr<Fetcher> SyncSourceResolver::_makeRequiredOpTimeFetcher(HostAndP
BSON("find" << kLocalOplogNss.coll() << "oplogReplay" << true << "filter"
<< BSON("ts" << BSON("$gte" << _requiredOpTime.getTimestamp() << "$lte"
<< _requiredOpTime.getTimestamp()))
- << "readConcern"
- << BSON("level"
- << "local")),
+ << ReadConcernArgs::kReadConcernFieldName << ReadConcernArgs::kImplicitDefault),
[=](const StatusWith<Fetcher::QueryResponse>& response,
Fetcher::NextAction*,
BSONObjBuilder*) {
diff --git a/src/mongo/db/s/add_shard_cmd.cpp b/src/mongo/db/s/add_shard_cmd.cpp
index c2e8e3684a2..aab1f4d7b79 100644
--- a/src/mongo/db/s/add_shard_cmd.cpp
+++ b/src/mongo/db/s/add_shard_cmd.cpp
@@ -79,7 +79,7 @@ public:
private:
bool supportsWriteConcern() const override {
- return true;
+ return false;
}
// The command parameter happens to be string so it's historically been interpreted
diff --git a/src/mongo/db/s/balancer/migration_manager.cpp b/src/mongo/db/s/balancer/migration_manager.cpp
index 4a1d614d34d..100855905b7 100644
--- a/src/mongo/db/s/balancer/migration_manager.cpp
+++ b/src/mongo/db/s/balancer/migration_manager.cpp
@@ -469,6 +469,17 @@ shared_ptr<Notification<RemoteCommandResponse>> MigrationManager::_schedule(
waitForDelete,
migrateInfo.forceJumbo);
+ // In 4.4, commands sent to shards that accept writeConcern, must always have writeConcern.
+ // So if the MoveChunkRequest didn't add writeConcern (from secondaryThrottle), then we add
+ // the implicit server default writeConcern.
+ if (!builder.hasField(WriteConcernOptions::kWriteConcernField) &&
+ serverGlobalParams.featureCompatibility.isVersionInitialized() &&
+ serverGlobalParams.featureCompatibility.getVersion() ==
+ ServerGlobalParams::FeatureCompatibility::Version::kFullyUpgradedTo44) {
+ builder.append(WriteConcernOptions::kWriteConcernField,
+ WriteConcernOptions::kImplicitDefault);
+ }
+
stdx::lock_guard<Latch> lock(_mutex);
if (_state != State::kEnabled && _state != State::kRecovering) {
diff --git a/src/mongo/db/s/migration_chunk_cloner_source_legacy.cpp b/src/mongo/db/s/migration_chunk_cloner_source_legacy.cpp
index a3941cfde46..98766413fac 100644
--- a/src/mongo/db/s/migration_chunk_cloner_source_legacy.cpp
+++ b/src/mongo/db/s/migration_chunk_cloner_source_legacy.cpp
@@ -296,6 +296,17 @@ Status MigrationChunkClonerSourceLegacy::startClone(OperationContext* opCtx,
_shardKeyPattern.toBSON(),
_args.getSecondaryThrottle());
+ if (serverGlobalParams.featureCompatibility.isVersion(
+ ServerGlobalParams::FeatureCompatibility::Version::kFullyUpgradedTo44)) {
+ // In 4.4, commands sent to shards that accept writeConcern, must always have writeConcern.
+ // So if the StartChunkCloneRequest didn't add writeConcern (from secondaryThrottle), then
+ // we add the implicit server default writeConcern.
+ if (!cmdBuilder.hasField(WriteConcernOptions::kWriteConcernField)) {
+ cmdBuilder.append(WriteConcernOptions::kWriteConcernField,
+ WriteConcernOptions::kImplicitDefault);
+ }
+ }
+
auto startChunkCloneResponseStatus = _callRecipient(cmdBuilder.obj());
if (!startChunkCloneResponseStatus.isOK()) {
return startChunkCloneResponseStatus.getStatus();
@@ -367,6 +378,17 @@ Status MigrationChunkClonerSourceLegacy::startClone(OperationContext* opCtx) {
_shardKeyPattern.toBSON(),
_args.getSecondaryThrottle());
+ if (serverGlobalParams.featureCompatibility.isVersion(
+ ServerGlobalParams::FeatureCompatibility::Version::kFullyUpgradedTo44)) {
+ // In 4.4, commands sent to shards that accept writeConcern, must always have writeConcern.
+ // So if the StartChunkCloneRequest didn't add writeConcern (from secondaryThrottle), then
+ // we add the implicit server default writeConcern.
+ if (!cmdBuilder.hasField(WriteConcernOptions::kWriteConcernField)) {
+ cmdBuilder.append(WriteConcernOptions::kWriteConcernField,
+ WriteConcernOptions::kImplicitDefault);
+ }
+ }
+
auto startChunkCloneResponseStatus = _callRecipient(cmdBuilder.obj());
if (!startChunkCloneResponseStatus.isOK()) {
return startChunkCloneResponseStatus.getStatus();
diff --git a/src/mongo/db/s/migration_util.cpp b/src/mongo/db/s/migration_util.cpp
index ead3d722055..02d7e5bcc31 100644
--- a/src/mongo/db/s/migration_util.cpp
+++ b/src/mongo/db/s/migration_util.cpp
@@ -41,6 +41,7 @@
#include "mongo/client/query.h"
#include "mongo/db/catalog/collection_catalog_helper.h"
#include "mongo/db/catalog_raii.h"
+#include "mongo/db/commands.h"
#include "mongo/db/dbdirectclient.h"
#include "mongo/db/logical_session_cache.h"
#include "mongo/db/namespace_string.h"
@@ -693,7 +694,8 @@ void ensureChunkVersionIsGreaterThan(OperationContext* opCtx,
newOpCtx,
ReadPreferenceSetting{ReadPreference::PrimaryOnly},
"admin",
- ensureChunkVersionIsGreaterThanRequestBSON,
+ CommandHelpers::appendMajorityWriteConcern(
+ ensureChunkVersionIsGreaterThanRequestBSON),
Shard::RetryPolicy::kIdempotent);
const auto ensureChunkVersionIsGreaterThanStatus =
Shard::CommandResponse::getEffectiveStatus(ensureChunkVersionIsGreaterThanResponse);
diff --git a/src/mongo/db/s/shard_key_util.cpp b/src/mongo/db/s/shard_key_util.cpp
index 906757d353c..62c67614e2e 100644
--- a/src/mongo/db/s/shard_key_util.cpp
+++ b/src/mongo/db/s/shard_key_util.cpp
@@ -167,7 +167,8 @@ void validateShardKeyAgainstExistingIndexes(OperationContext* opCtx,
}
}
- auto countCmd = BSON("count" << nss.coll());
+ auto countCmd = BSON("count" << nss.coll() << repl::ReadConcernArgs::kReadConcernFieldName
+ << repl::ReadConcernArgs::kImplicitDefault);
auto countRes =
uassertStatusOK(primaryShard->runCommand(opCtx,
ReadPreferenceSetting(ReadPreference::PrimaryOnly),
diff --git a/src/mongo/db/sessions_collection.cpp b/src/mongo/db/sessions_collection.cpp
index 4e0e121abaf..b883bebf76c 100644
--- a/src/mongo/db/sessions_collection.cpp
+++ b/src/mongo/db/sessions_collection.cpp
@@ -40,6 +40,7 @@
#include "mongo/db/create_indexes_gen.h"
#include "mongo/db/logical_session_id.h"
#include "mongo/db/ops/write_ops.h"
+#include "mongo/db/repl/read_concern_args.h"
#include "mongo/rpc/get_status_from_command_result.h"
#include "mongo/s/write_ops/batched_command_response.h"
@@ -234,7 +235,10 @@ LogicalSessionIdSet SessionsCollection::_doFindRemoved(
LogicalSessionIdSet removed{sessions.begin(), sessions.end()};
auto wrappedSend = [&](BSONObj batch) {
- auto swBatchResult = send(batch);
+ BSONObjBuilder batchWithReadConcernLocal(batch);
+ batchWithReadConcernLocal.append(repl::ReadConcernArgs::kReadConcernFieldName,
+ repl::ReadConcernArgs::kImplicitDefault);
+ auto swBatchResult = send(batchWithReadConcernLocal.obj());
auto result =
SessionsCollectionFetchResult::parse("SessionsCollectionFetchResult"_sd, swBatchResult);
@@ -279,7 +283,9 @@ BSONObj SessionsCollection::generateCreateIndexesCmd() {
createIndexes.setCreateIndexes(NamespaceString::kLogicalSessionsNamespace.coll());
createIndexes.setIndexes(std::move(indexes));
- return createIndexes.toBSON();
+ return BSONObjBuilder(createIndexes.toBSON())
+ .append(WriteConcernOptions::kWriteConcernField, WriteConcernOptions::kImplicitDefault)
+ .obj();
}
BSONObj SessionsCollection::generateCollModCmd() {
@@ -292,6 +298,8 @@ BSONObj SessionsCollection::generateCollModCmd() {
indexBuilder << "expireAfterSeconds" << localLogicalSessionTimeoutMinutes * 60;
indexBuilder.done();
+ collModCmdBuilder.append(WriteConcernOptions::kWriteConcernField,
+ WriteConcernOptions::kImplicitDefault);
collModCmdBuilder.done();
return collModCmdBuilder.obj();
diff --git a/src/mongo/db/write_concern_options.cpp b/src/mongo/db/write_concern_options.cpp
index 298941fbdef..7ff06c9d224 100644
--- a/src/mongo/db/write_concern_options.cpp
+++ b/src/mongo/db/write_concern_options.cpp
@@ -72,6 +72,12 @@ const BSONObj WriteConcernOptions::Default = BSONObj();
const BSONObj WriteConcernOptions::Acknowledged(BSON("w" << W_NORMAL));
const BSONObj WriteConcernOptions::Unacknowledged(BSON("w" << W_NONE));
const BSONObj WriteConcernOptions::Majority(BSON("w" << WriteConcernOptions::kMajority));
+
+// The "kImplicitDefault" write concern, used by internal operations, is deliberately empty (no
+// 'w' or 'wtimeout' specified). This allows internal operations to specify a write concern, while
+// still allowing it to be either w:1 or automatically upconverted to w:majority on configsvrs.
+const BSONObj WriteConcernOptions::kImplicitDefault;
+
constexpr Seconds WriteConcernOptions::kWriteConcernTimeoutSystem;
constexpr Seconds WriteConcernOptions::kWriteConcernTimeoutMigration;
constexpr Seconds WriteConcernOptions::kWriteConcernTimeoutSharding;
diff --git a/src/mongo/db/write_concern_options.h b/src/mongo/db/write_concern_options.h
index 07cd6a6e1d7..0d9cca66889 100644
--- a/src/mongo/db/write_concern_options.h
+++ b/src/mongo/db/write_concern_options.h
@@ -54,6 +54,7 @@ public:
static const BSONObj Unacknowledged;
static const BSONObj Majority;
static const BSONObj ConfigMajority;
+ static const BSONObj kImplicitDefault;
static constexpr StringData kWriteConcernField = "writeConcern"_sd;
static const char kMajority[]; // = "majority"