summaryrefslogtreecommitdiff
path: root/src/mongo/s/commands/cluster_write_cmd.cpp
diff options
context:
space:
mode:
authorLucas de Castro Borges <lucas@gnuabordo.com.br>2025-02-11 15:07:35 -0300
committerLucas de Castro Borges <lucas@gnuabordo.com.br>2025-02-11 15:07:35 -0300
commit4cb8841196d0625dfa3825aa326f071cd27c7b8b (patch)
tree1682a647d4463397c119183369ae6f750d5fdcff /src/mongo/s/commands/cluster_write_cmd.cpp
parentaa03c6362cbaa767638e6eed9b031d86dd2643d1 (diff)
parent8f0827553e09872941945a093b647a4211a9db7f (diff)
Update upstream source from tag 'upstream/6.0.0'master
Update to upstream version '6.0.0' with Debian dir 5604a80ec1c96ca76f25f40d78e6ef855abec322
Diffstat (limited to 'src/mongo/s/commands/cluster_write_cmd.cpp')
-rw-r--r--src/mongo/s/commands/cluster_write_cmd.cpp40
1 files changed, 40 insertions, 0 deletions
diff --git a/src/mongo/s/commands/cluster_write_cmd.cpp b/src/mongo/s/commands/cluster_write_cmd.cpp
index 8590832acc6..10d04ba0b82 100644
--- a/src/mongo/s/commands/cluster_write_cmd.cpp
+++ b/src/mongo/s/commands/cluster_write_cmd.cpp
@@ -145,6 +145,11 @@ boost::optional<WouldChangeOwningShardInfo> getWouldChangeOwningShardErrorInfo(
void handleWouldChangeOwningShardErrorRetryableWrite(OperationContext* opCtx,
BatchedCommandRequest* request,
BatchedCommandResponse* response) {
+ // Strip write concern because this command will be sent as part of a
+ // transaction and the write concern has already been loaded onto the opCtx and
+ // will be picked up by the transaction API.
+ request->unsetWriteConcern();
+
// Strip runtime constants because they will be added again when the API sends this command
// through the service entry point.
request->unsetLegacyRuntimeConstants();
@@ -313,6 +318,11 @@ bool handleWouldChangeOwningShardError(OperationContext* opCtx,
auto& readConcernArgs = repl::ReadConcernArgs::get(opCtx);
readConcernArgs = repl::ReadConcernArgs(repl::ReadConcernLevel::kLocalReadConcern);
+ // Ensure the retried operation does not include WC inside the transaction. The
+ // transaction commit will still use the WC, because it uses the WC from the opCtx
+ // (which has been set previously in Strategy).
+ request->unsetWriteConcern();
+
documentShardKeyUpdateUtil::startTransactionForShardKeyUpdate(opCtx);
// Clear the error details from the response object before sending the write again
response->unsetErrDetails();
@@ -497,6 +507,29 @@ bool ClusterWriteCmd::InvocationBase::runImpl(OperationContext* opCtx,
BatchWriteExecStats stats;
BatchedCommandResponse response;
+ // The batched request will only have WC if it was supplied by the client. Otherwise, the
+ // batched request should use the WC from the opCtx.
+ if (!batchedRequest.hasWriteConcern()) {
+ if (opCtx->getWriteConcern().usedDefaultConstructedWC) {
+ // Pass writeConcern: {}, rather than {w: 1, wtimeout: 0}, so as to not override the
+ // configsvr w:majority upconvert.
+ batchedRequest.setWriteConcern(BSONObj());
+ } else {
+ batchedRequest.setWriteConcern(opCtx->getWriteConcern().toBSON());
+ }
+ }
+
+ // Write ops are never allowed to have writeConcern inside transactions. Normally
+ // disallowing WC on non-terminal commands in a transaction is handled earlier, during
+ // command dispatch. However, if this is a regular write operation being automatically
+ // retried inside a transaction (such as changing a document's shard key across shards),
+ // then batchedRequest will have a writeConcern (added by the if() above) from when it was
+ // initially run outside a transaction. Thus it's necessary to unconditionally clear the
+ // writeConcern when in a transaction.
+ if (TransactionRouter::get(opCtx)) {
+ batchedRequest.unsetWriteConcern();
+ }
+
cluster::write(opCtx, batchedRequest, &stats, &response);
bool updatedShardKey = false;
@@ -522,17 +555,22 @@ bool ClusterWriteCmd::InvocationBase::runImpl(OperationContext* opCtx,
// TODO: increase opcounters by more than one
auto& debug = CurOp::get(opCtx)->debug();
+ auto catalogCache = Grid::get(opCtx)->catalogCache();
switch (_batchedRequest.getBatchType()) {
case BatchedCommandRequest::BatchType_Insert:
for (size_t i = 0; i < numAttempts; ++i) {
globalOpCounters.gotInsert();
}
+ catalogCache->checkAndRecordOperationBlockedByRefresh(opCtx,
+ mongo::LogicalOp::opInsert);
debug.additiveMetrics.ninserted = response.getN();
break;
case BatchedCommandRequest::BatchType_Update:
for (size_t i = 0; i < numAttempts; ++i) {
globalOpCounters.gotUpdate();
}
+ catalogCache->checkAndRecordOperationBlockedByRefresh(opCtx,
+ mongo::LogicalOp::opUpdate);
// The response.getN() count is the sum of documents matched and upserted.
if (response.isUpsertDetailsSet()) {
@@ -565,6 +603,8 @@ bool ClusterWriteCmd::InvocationBase::runImpl(OperationContext* opCtx,
for (size_t i = 0; i < numAttempts; ++i) {
globalOpCounters.gotDelete();
}
+ catalogCache->checkAndRecordOperationBlockedByRefresh(opCtx,
+ mongo::LogicalOp::opDelete);
debug.additiveMetrics.ndeleted = response.getN();
break;
}