summaryrefslogtreecommitdiff
path: root/src/mongo/s
diff options
context:
space:
mode:
authorMathias Stearn <mathias@10gen.com>2017-06-13 17:06:03 -0400
committerMathias Stearn <mathias@10gen.com>2017-06-19 19:02:31 -0400
commit8b0121efcdb798c18cc4519594bfa52531623932 (patch)
treeb65e0f78e331e65232f0ae7781fba5b0178b33ac /src/mongo/s
parent9938d658c44140555245943a292e9e33dc75d9c5 (diff)
downloadmongo-8b0121efcdb798c18cc4519594bfa52531623932.tar.gz
SERVER-29319 mongos write commands support document sequences
Diffstat (limited to 'src/mongo/s')
-rw-r--r--src/mongo/s/catalog/dist_lock_catalog_impl_test.cpp3
-rw-r--r--src/mongo/s/catalog/sharding_catalog_add_shard_test.cpp14
-rw-r--r--src/mongo/s/catalog/sharding_catalog_remove_shard_test.cpp8
-rw-r--r--src/mongo/s/catalog/sharding_catalog_shard_collection_test.cpp8
-rw-r--r--src/mongo/s/catalog/sharding_catalog_test.cpp12
-rw-r--r--src/mongo/s/catalog/sharding_catalog_write_retry_test.cpp28
-rw-r--r--src/mongo/s/commands/cluster_write_cmd.cpp37
-rw-r--r--src/mongo/s/sharding_test_fixture.cpp12
-rw-r--r--src/mongo/s/write_ops/SConscript1
-rw-r--r--src/mongo/s/write_ops/batch_write_exec_test.cpp12
-rw-r--r--src/mongo/s/write_ops/batched_command_request.cpp49
-rw-r--r--src/mongo/s/write_ops/batched_command_request.h3
-rw-r--r--src/mongo/s/write_ops/batched_command_request_test.cpp25
-rw-r--r--src/mongo/s/write_ops/batched_delete_request.cpp63
-rw-r--r--src/mongo/s/write_ops/batched_delete_request.h3
-rw-r--r--src/mongo/s/write_ops/batched_delete_request_test.cpp32
-rw-r--r--src/mongo/s/write_ops/batched_insert_request.cpp64
-rw-r--r--src/mongo/s/write_ops/batched_insert_request.h3
-rw-r--r--src/mongo/s/write_ops/batched_insert_request_test.cpp12
-rw-r--r--src/mongo/s/write_ops/batched_update_request.cpp72
-rw-r--r--src/mongo/s/write_ops/batched_update_request.h3
-rw-r--r--src/mongo/s/write_ops/batched_update_request_test.cpp52
22 files changed, 267 insertions, 249 deletions
diff --git a/src/mongo/s/catalog/dist_lock_catalog_impl_test.cpp b/src/mongo/s/catalog/dist_lock_catalog_impl_test.cpp
index f54a806cdec..f60ab000ce6 100644
--- a/src/mongo/s/catalog/dist_lock_catalog_impl_test.cpp
+++ b/src/mongo/s/catalog/dist_lock_catalog_impl_test.cpp
@@ -1121,9 +1121,8 @@ TEST_F(DistLockCatalogFixture, BasicUnlockAll) {
ASSERT_EQUALS(dummyHost, request.target);
ASSERT_EQUALS("config", request.dbname);
- std::string errmsg;
BatchedUpdateRequest batchRequest;
- ASSERT(batchRequest.parseBSON("config", request.cmdObj, &errmsg));
+ batchRequest.parseRequest(OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj));
ASSERT_EQUALS(LocksType::ConfigNS, batchRequest.getNS().toString());
ASSERT_BSONOBJ_EQ(BSON("w" << 1 << "wtimeout" << 0), batchRequest.getWriteConcern());
auto updates = batchRequest.getUpdates();
diff --git a/src/mongo/s/catalog/sharding_catalog_add_shard_test.cpp b/src/mongo/s/catalog/sharding_catalog_add_shard_test.cpp
index 1bbc85e887d..2b018ac7e1a 100644
--- a/src/mongo/s/catalog/sharding_catalog_add_shard_test.cpp
+++ b/src/mongo/s/catalog/sharding_catalog_add_shard_test.cpp
@@ -157,8 +157,7 @@ protected:
// Get the BatchedUpdateRequest from the upsert command.
BatchedCommandRequest request(BatchedCommandRequest::BatchType::BatchType_Update);
- std::string errMsg;
- invariant(request.parseBSON("admin", upsertCmdObj, &errMsg) || !request.isValid(&errMsg));
+ request.parseRequest(OpMsgRequest::fromDBAndBody("admin", upsertCmdObj));
expectUpdatesReturnSuccess(expectedHost,
NamespaceString(NamespaceString::kServerConfigurationNamespace),
@@ -174,8 +173,7 @@ protected:
// Get the BatchedUpdateRequest from the upsert command.
BatchedCommandRequest request(BatchedCommandRequest::BatchType::BatchType_Update);
- std::string errMsg;
- invariant(request.parseBSON("admin", upsertCmdObj, &errMsg) || !request.isValid(&errMsg));
+ request.parseRequest(OpMsgRequest::fromDBAndBody("admin", upsertCmdObj));
expectUpdatesReturnFailure(expectedHost,
NamespaceString(NamespaceString::kServerConfigurationNamespace),
@@ -198,8 +196,8 @@ protected:
ASSERT_EQUALS(expectedNss.db(), request.dbname);
BatchedUpdateRequest actualBatchedUpdates;
- std::string errmsg;
- ASSERT_TRUE(actualBatchedUpdates.parseBSON(request.dbname, request.cmdObj, &errmsg));
+ actualBatchedUpdates.parseRequest(
+ OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj));
// Check that the db and collection names in the BatchedUpdateRequest match the
// expected.
@@ -244,8 +242,8 @@ protected:
ASSERT_EQUALS(expectedNss.db(), request.dbname);
BatchedUpdateRequest actualBatchedUpdates;
- std::string errmsg;
- ASSERT_TRUE(actualBatchedUpdates.parseBSON(request.dbname, request.cmdObj, &errmsg));
+ actualBatchedUpdates.parseRequest(
+ OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj));
// Check that the db and collection names in the BatchedUpdateRequest match the
// expected.
diff --git a/src/mongo/s/catalog/sharding_catalog_remove_shard_test.cpp b/src/mongo/s/catalog/sharding_catalog_remove_shard_test.cpp
index 2b53cc8c51e..5197b4ba3cd 100644
--- a/src/mongo/s/catalog/sharding_catalog_remove_shard_test.cpp
+++ b/src/mongo/s/catalog/sharding_catalog_remove_shard_test.cpp
@@ -159,8 +159,8 @@ TEST_F(RemoveShardTest, RemoveShardStartDraining) {
rpc::TrackingMetadata::removeTrackingData(request.metadata));
BatchedUpdateRequest actualBatchedUpdate;
- std::string errmsg;
- ASSERT_TRUE(actualBatchedUpdate.parseBSON(request.dbname, request.cmdObj, &errmsg));
+ actualBatchedUpdate.parseRequest(
+ OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj));
ASSERT_EQUALS(ShardType::ConfigNS, actualBatchedUpdate.getNS().ns());
auto updates = actualBatchedUpdate.getUpdates();
ASSERT_EQUALS(1U, updates.size());
@@ -335,8 +335,8 @@ TEST_F(RemoveShardTest, RemoveShardCompletion) {
rpc::TrackingMetadata::removeTrackingData(request.metadata));
BatchedDeleteRequest actualBatchedDelete;
- std::string errmsg;
- ASSERT_TRUE(actualBatchedDelete.parseBSON(request.dbname, request.cmdObj, &errmsg));
+ actualBatchedDelete.parseRequest(
+ OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj));
ASSERT_EQUALS(ShardType::ConfigNS, actualBatchedDelete.getNS().ns());
auto deletes = actualBatchedDelete.getDeletes();
ASSERT_EQUALS(1U, deletes.size());
diff --git a/src/mongo/s/catalog/sharding_catalog_shard_collection_test.cpp b/src/mongo/s/catalog/sharding_catalog_shard_collection_test.cpp
index 2332ee83ed0..23d967020f4 100644
--- a/src/mongo/s/catalog/sharding_catalog_shard_collection_test.cpp
+++ b/src/mongo/s/catalog/sharding_catalog_shard_collection_test.cpp
@@ -124,8 +124,8 @@ public:
rpc::TrackingMetadata::removeTrackingData(request.metadata));
BatchedInsertRequest actualBatchedInsert;
- std::string errmsg;
- ASSERT_TRUE(actualBatchedInsert.parseBSON(request.dbname, request.cmdObj, &errmsg));
+ actualBatchedInsert.parseRequest(
+ OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj));
ASSERT_EQUALS(ChunkType::ConfigNS, actualBatchedInsert.getNS().ns());
auto inserts = actualBatchedInsert.getDocuments();
ASSERT_EQUALS(1U, inserts.size());
@@ -163,8 +163,8 @@ public:
rpc::TrackingMetadata::removeTrackingData(request.metadata));
BatchedUpdateRequest actualBatchedUpdate;
- std::string errmsg;
- ASSERT_TRUE(actualBatchedUpdate.parseBSON(request.dbname, request.cmdObj, &errmsg));
+ actualBatchedUpdate.parseRequest(
+ OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj));
ASSERT_EQUALS(CollectionType::ConfigNS, actualBatchedUpdate.getNS().ns());
auto updates = actualBatchedUpdate.getUpdates();
ASSERT_EQUALS(1U, updates.size());
diff --git a/src/mongo/s/catalog/sharding_catalog_test.cpp b/src/mongo/s/catalog/sharding_catalog_test.cpp
index 23a790ff052..a102171f6a4 100644
--- a/src/mongo/s/catalog/sharding_catalog_test.cpp
+++ b/src/mongo/s/catalog/sharding_catalog_test.cpp
@@ -1122,8 +1122,8 @@ TEST_F(ShardingCatalogClientTest, UpdateDatabase) {
rpc::TrackingMetadata::removeTrackingData(request.metadata));
BatchedUpdateRequest actualBatchedUpdate;
- std::string errmsg;
- ASSERT_TRUE(actualBatchedUpdate.parseBSON(request.dbname, request.cmdObj, &errmsg));
+ actualBatchedUpdate.parseRequest(
+ OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj));
ASSERT_EQUALS(DatabaseType::ConfigNS, actualBatchedUpdate.getNS().ns());
auto updates = actualBatchedUpdate.getUpdates();
ASSERT_EQUALS(1U, updates.size());
@@ -1432,8 +1432,8 @@ TEST_F(ShardingCatalogClientTest, createDatabaseSuccess) {
rpc::TrackingMetadata::removeTrackingData(request.metadata));
BatchedInsertRequest actualBatchedInsert;
- std::string errmsg;
- ASSERT_TRUE(actualBatchedInsert.parseBSON(request.dbname, request.cmdObj, &errmsg));
+ actualBatchedInsert.parseRequest(
+ OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj));
ASSERT_EQUALS(DatabaseType::ConfigNS, actualBatchedInsert.getNS().ns());
auto inserts = actualBatchedInsert.getDocuments();
ASSERT_EQUALS(1U, inserts.size());
@@ -1719,8 +1719,8 @@ TEST_F(ShardingCatalogClientTest, createDatabaseDuplicateKeyOnInsert) {
rpc::TrackingMetadata::removeTrackingData(request.metadata));
BatchedInsertRequest actualBatchedInsert;
- std::string errmsg;
- ASSERT_TRUE(actualBatchedInsert.parseBSON(request.dbname, request.cmdObj, &errmsg));
+ actualBatchedInsert.parseRequest(
+ OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj));
ASSERT_EQUALS(DatabaseType::ConfigNS, actualBatchedInsert.getNS().ns());
auto inserts = actualBatchedInsert.getDocuments();
ASSERT_EQUALS(1U, inserts.size());
diff --git a/src/mongo/s/catalog/sharding_catalog_write_retry_test.cpp b/src/mongo/s/catalog/sharding_catalog_write_retry_test.cpp
index 322ea3b464d..aa64208f387 100644
--- a/src/mongo/s/catalog/sharding_catalog_write_retry_test.cpp
+++ b/src/mongo/s/catalog/sharding_catalog_write_retry_test.cpp
@@ -275,8 +275,8 @@ TEST_F(InsertRetryTest, DuplicateKeyErrorAfterWriteConcernFailureMatch) {
onCommand([&](const RemoteCommandRequest& request) {
BatchedInsertRequest actualBatchedInsert;
- std::string errmsg;
- ASSERT_TRUE(actualBatchedInsert.parseBSON(request.dbname, request.cmdObj, &errmsg));
+ actualBatchedInsert.parseRequest(
+ OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj));
ASSERT_EQUALS(kTestNamespace.ns(), actualBatchedInsert.getNS().ns());
BatchedCommandResponse response;
@@ -337,8 +337,8 @@ TEST_F(UpdateRetryTest, Success) {
onCommand([&](const RemoteCommandRequest& request) {
BatchedUpdateRequest actualBatchedUpdate;
- std::string errmsg;
- ASSERT_TRUE(actualBatchedUpdate.parseBSON(request.dbname, request.cmdObj, &errmsg));
+ actualBatchedUpdate.parseRequest(
+ OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj));
ASSERT_EQUALS(kTestNamespace.ns(), actualBatchedUpdate.getNS().ns());
BatchedCommandResponse response;
@@ -449,8 +449,8 @@ TEST_F(UpdateRetryTest, NotMasterOnceSuccessAfterRetry) {
onCommand([&](const RemoteCommandRequest& request) {
BatchedUpdateRequest actualBatchedUpdate;
- std::string errmsg;
- ASSERT_TRUE(actualBatchedUpdate.parseBSON(request.dbname, request.cmdObj, &errmsg));
+ actualBatchedUpdate.parseRequest(
+ OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj));
ASSERT_EQUALS(kTestNamespace.ns(), actualBatchedUpdate.getNS().ns());
BatchedCommandResponse response;
@@ -484,8 +484,8 @@ TEST_F(UpdateRetryTest, OperationInterruptedDueToPrimaryStepDown) {
onCommand([&](const RemoteCommandRequest& request) {
BatchedUpdateRequest actualBatchedUpdate;
- std::string errmsg;
- ASSERT_TRUE(actualBatchedUpdate.parseBSON(request.dbname, request.cmdObj, &errmsg));
+ actualBatchedUpdate.parseRequest(
+ OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj));
ASSERT_EQUALS(kTestNamespace.ns(), actualBatchedUpdate.getNS().ns());
BatchedCommandResponse response;
@@ -501,8 +501,8 @@ TEST_F(UpdateRetryTest, OperationInterruptedDueToPrimaryStepDown) {
onCommand([&](const RemoteCommandRequest& request) {
BatchedUpdateRequest actualBatchedUpdate;
- std::string errmsg;
- ASSERT_TRUE(actualBatchedUpdate.parseBSON(request.dbname, request.cmdObj, &errmsg));
+ actualBatchedUpdate.parseRequest(
+ OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj));
ASSERT_EQUALS(kTestNamespace.ns(), actualBatchedUpdate.getNS().ns());
BatchedCommandResponse response;
@@ -536,8 +536,8 @@ TEST_F(UpdateRetryTest, WriteConcernFailure) {
onCommand([&](const RemoteCommandRequest& request) {
BatchedUpdateRequest actualBatchedUpdate;
- std::string errmsg;
- ASSERT_TRUE(actualBatchedUpdate.parseBSON(request.dbname, request.cmdObj, &errmsg));
+ actualBatchedUpdate.parseRequest(
+ OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj));
ASSERT_EQUALS(kTestNamespace.ns(), actualBatchedUpdate.getNS().ns());
BatchedCommandResponse response;
@@ -562,8 +562,8 @@ TEST_F(UpdateRetryTest, WriteConcernFailure) {
onCommand([&](const RemoteCommandRequest& request) {
BatchedUpdateRequest actualBatchedUpdate;
- std::string errmsg;
- ASSERT_TRUE(actualBatchedUpdate.parseBSON(request.dbname, request.cmdObj, &errmsg));
+ actualBatchedUpdate.parseRequest(
+ OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj));
ASSERT_EQUALS(kTestNamespace.ns(), actualBatchedUpdate.getNS().ns());
BatchedCommandResponse response;
diff --git a/src/mongo/s/commands/cluster_write_cmd.cpp b/src/mongo/s/commands/cluster_write_cmd.cpp
index e2aee6e42de..400dc400ce1 100644
--- a/src/mongo/s/commands/cluster_write_cmd.cpp
+++ b/src/mongo/s/commands/cluster_write_cmd.cpp
@@ -97,15 +97,19 @@ public:
const BSONObj& cmdObj,
ExplainOptions::Verbosity verbosity,
BSONObjBuilder* out) const {
- BatchedCommandRequest request(_writeType);
-
- string errMsg;
- if (!request.parseBSON(dbname, cmdObj, &errMsg) || !request.isValid(&errMsg)) {
+ BatchedCommandRequest batchedRequest(_writeType);
+ OpMsgRequest request;
+ request.body = cmdObj;
+ invariant(request.getDatabase() == dbname); // Ensured by explain command's run() method.
+ batchedRequest.parseRequest(request);
+
+ std::string errMsg;
+ if (!batchedRequest.isValid(&errMsg)) {
return Status(ErrorCodes::FailedToParse, errMsg);
}
// We can only explain write batches of size 1.
- if (request.sizeWriteOps() != 1U) {
+ if (batchedRequest.sizeWriteOps() != 1U) {
return Status(ErrorCodes::InvalidLength, "explained write batches must be of size 1");
}
@@ -115,7 +119,7 @@ public:
Timer timer;
// Target the command to the shards based on the singleton batch item.
- BatchItemRef targetingBatchItem(&request, 0);
+ BatchItemRef targetingBatchItem(&batchedRequest, 0);
vector<Strategy::CommandResult> shardResults;
Status status =
_commandOpWrite(opCtx, dbname, explainCmd, targetingBatchItem, &shardResults);
@@ -127,12 +131,11 @@ public:
opCtx, shardResults, ClusterExplain::kWriteOnShards, timer.millis(), out);
}
- virtual bool run(OperationContext* opCtx,
- const string& dbname,
- const BSONObj& cmdObj,
+ bool enhancedRun(OperationContext* opCtx,
+ const OpMsgRequest& request,
string& errmsg,
- BSONObjBuilder& result) {
- BatchedCommandRequest request(_writeType);
+ BSONObjBuilder& result) final {
+ BatchedCommandRequest batchedRequest(_writeType);
BatchedCommandResponse response;
ClusterWriter writer(true, 0);
@@ -142,14 +145,14 @@ public:
{
// Disable the last error object for the duration of the write
LastError::Disabled disableLastError(cmdLastError);
-
- if (!request.parseBSON(dbname, cmdObj, &errmsg) || !request.isValid(&errmsg)) {
+ batchedRequest.parseRequest(request);
+ if (!batchedRequest.isValid(&errmsg)) {
// Batch parse failure
response.setOk(false);
response.setErrCode(ErrorCodes::FailedToParse);
response.setErrMessage(errmsg);
} else {
- writer.write(opCtx, request, &response);
+ writer.write(opCtx, batchedRequest, &response);
}
dassert(response.isValid(NULL));
@@ -157,17 +160,17 @@ public:
// Populate the lastError object based on the write response
cmdLastError->reset();
- batchErrorToLastError(request, response, cmdLastError);
+ batchErrorToLastError(batchedRequest, response, cmdLastError);
size_t numAttempts;
if (!response.getOk()) {
numAttempts = 0;
- } else if (request.getOrdered() && response.isErrDetailsSet()) {
+ } else if (batchedRequest.getOrdered() && response.isErrDetailsSet()) {
// Add one failed attempt
numAttempts = response.getErrDetailsAt(0)->getIndex() + 1;
} else {
- numAttempts = request.sizeWriteOps();
+ numAttempts = batchedRequest.sizeWriteOps();
}
// TODO: increase opcounters by more than one
diff --git a/src/mongo/s/sharding_test_fixture.cpp b/src/mongo/s/sharding_test_fixture.cpp
index a203d24d518..c0ed6210782 100644
--- a/src/mongo/s/sharding_test_fixture.cpp
+++ b/src/mongo/s/sharding_test_fixture.cpp
@@ -328,8 +328,8 @@ void ShardingTestFixture::expectInserts(const NamespaceString& nss,
ASSERT_EQUALS(nss.db(), request.dbname);
BatchedInsertRequest actualBatchedInsert;
- std::string errmsg;
- ASSERT_TRUE(actualBatchedInsert.parseBSON(request.dbname, request.cmdObj, &errmsg));
+ actualBatchedInsert.parseRequest(
+ OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj));
ASSERT_EQUALS(nss.toString(), actualBatchedInsert.getNS().toString());
@@ -383,8 +383,8 @@ void ShardingTestFixture::expectConfigCollectionInsert(const HostAndPort& config
ASSERT_EQUALS("config", request.dbname);
BatchedInsertRequest actualBatchedInsert;
- std::string errmsg;
- ASSERT_TRUE(actualBatchedInsert.parseBSON(request.dbname, request.cmdObj, &errmsg));
+ actualBatchedInsert.parseRequest(
+ OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj));
ASSERT_EQ("config", actualBatchedInsert.getNS().db());
ASSERT_EQ(collName, actualBatchedInsert.getNS().coll());
@@ -448,8 +448,8 @@ void ShardingTestFixture::expectUpdateCollection(const HostAndPort& expectedHost
ASSERT_EQUALS("config", request.dbname);
BatchedUpdateRequest actualBatchedUpdate;
- std::string errmsg;
- ASSERT_TRUE(actualBatchedUpdate.parseBSON(request.dbname, request.cmdObj, &errmsg));
+ actualBatchedUpdate.parseRequest(
+ OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj));
ASSERT_EQUALS(CollectionType::ConfigNS, actualBatchedUpdate.getNS().ns());
auto updates = actualBatchedUpdate.getUpdates();
ASSERT_EQUALS(1U, updates.size());
diff --git a/src/mongo/s/write_ops/SConscript b/src/mongo/s/write_ops/SConscript
index 69df543a930..a5f54bb1f3f 100644
--- a/src/mongo/s/write_ops/SConscript
+++ b/src/mongo/s/write_ops/SConscript
@@ -66,6 +66,7 @@ env.CppUnitTest(
],
LIBDEPS=[
'batch_write_types',
+ '$BUILD_DIR/mongo/db/ops/write_ops_parsers_test_helpers',
]
)
diff --git a/src/mongo/s/write_ops/batch_write_exec_test.cpp b/src/mongo/s/write_ops/batch_write_exec_test.cpp
index 290596ceed3..1a063281385 100644
--- a/src/mongo/s/write_ops/batch_write_exec_test.cpp
+++ b/src/mongo/s/write_ops/batch_write_exec_test.cpp
@@ -98,8 +98,8 @@ public:
ASSERT_EQUALS(nss.db(), request.dbname);
BatchedInsertRequest actualBatchedInsert;
- std::string errmsg;
- ASSERT_TRUE(actualBatchedInsert.parseBSON(request.dbname, request.cmdObj, &errmsg));
+ actualBatchedInsert.parseRequest(
+ OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj));
ASSERT_EQUALS(nss.toString(), actualBatchedInsert.getNS().toString());
@@ -128,8 +128,8 @@ public:
ASSERT_EQUALS(nss.db(), request.dbname);
BatchedInsertRequest actualBatchedInsert;
- std::string errmsg;
- ASSERT_TRUE(actualBatchedInsert.parseBSON(request.dbname, request.cmdObj, &errmsg));
+ actualBatchedInsert.parseRequest(
+ OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj));
ASSERT_EQUALS(nss.toString(), actualBatchedInsert.getNS().toString());
@@ -235,8 +235,8 @@ TEST_F(BatchWriteExecTest, SingleOpError) {
ASSERT_EQUALS(nss.db(), request.dbname);
BatchedInsertRequest actualBatchedInsert;
- std::string errmsg;
- ASSERT_TRUE(actualBatchedInsert.parseBSON(request.dbname, request.cmdObj, &errmsg));
+ actualBatchedInsert.parseRequest(
+ OpMsgRequest::fromDBAndBody(request.dbname, request.cmdObj));
ASSERT_EQUALS(nss.toString(), actualBatchedInsert.getNS().toString());
diff --git a/src/mongo/s/write_ops/batched_command_request.cpp b/src/mongo/s/write_ops/batched_command_request.cpp
index 48c77723db3..f66e00fa70d 100644
--- a/src/mongo/s/write_ops/batched_command_request.cpp
+++ b/src/mongo/s/write_ops/batched_command_request.cpp
@@ -162,55 +162,38 @@ BSONObj BatchedCommandRequest::toBSON() const {
return builder.obj();
}
-bool BatchedCommandRequest::parseBSON(StringData dbName,
- const BSONObj& source,
- std::string* errMsg) {
- bool succeeded;
+void BatchedCommandRequest::parseRequest(const OpMsgRequest& request) {
switch (getBatchType()) {
case BatchedCommandRequest::BatchType_Insert:
- succeeded = _insertReq->parseBSON(dbName, source, errMsg);
+ _insertReq->parseRequest(request);
break;
case BatchedCommandRequest::BatchType_Update:
- succeeded = _updateReq->parseBSON(dbName, source, errMsg);
+ _updateReq->parseRequest(request);
break;
case BatchedCommandRequest::BatchType_Delete:
- succeeded = _deleteReq->parseBSON(dbName, source, errMsg);
+ _deleteReq->parseRequest(request);
break;
default:
MONGO_UNREACHABLE;
}
- if (!succeeded)
- return false;
-
- // Parse the command's shard version
- auto chunkVersion = ChunkVersion::parseFromBSONForCommands(source);
- if (chunkVersion.isOK()) {
- _shardVersion = chunkVersion.getValue();
- } else if (chunkVersion != ErrorCodes::NoSuchKey) {
- *errMsg = chunkVersion.getStatus().toString();
- return false;
+ // Now parse out the chunk version and optime.
+ auto chunkVersion = ChunkVersion::parseFromBSONForCommands(request.body);
+ if (chunkVersion != ErrorCodes::NoSuchKey) {
+ _shardVersion = uassertStatusOK(chunkVersion);
}
// Parse the command's transaction info and do extra validation not done by the parser
- try {
- _txnInfo = WriteOpTxnInfo::parse(IDLParserErrorContext("WriteOpTxnInfo"), source);
-
- const auto& stmtIds = _txnInfo.getStmtIds();
- uassert(ErrorCodes::BadValue,
- str::stream() << "The size of the statement ids array (" << stmtIds->size()
- << ") does not match the number of operations ("
- << sizeWriteOps()
- << ")",
- !stmtIds || stmtIds->size() == sizeWriteOps());
- } catch (const DBException& ex) {
- *errMsg = str::stream() << "Failed to parse the write op retriability information due to "
- << ex.toString();
- return false;
- }
+ _txnInfo = WriteOpTxnInfo::parse(IDLParserErrorContext("WriteOpTxnInfo"), request.body);
- return true;
+ const auto& stmtIds = _txnInfo.getStmtIds();
+ uassert(ErrorCodes::BadValue,
+ str::stream() << "The size of the statement ids array (" << stmtIds->size()
+ << ") does not match the number of operations ("
+ << sizeWriteOps()
+ << ")",
+ !stmtIds || stmtIds->size() == sizeWriteOps());
}
std::string BatchedCommandRequest::toString() const {
diff --git a/src/mongo/s/write_ops/batched_command_request.h b/src/mongo/s/write_ops/batched_command_request.h
index 036f9362494..ea0c4c43aae 100644
--- a/src/mongo/s/write_ops/batched_command_request.h
+++ b/src/mongo/s/write_ops/batched_command_request.h
@@ -36,6 +36,7 @@
#include "mongo/s/write_ops/batched_insert_request.h"
#include "mongo/s/write_ops/batched_update_request.h"
#include "mongo/s/write_ops/write_ops_gen.h"
+#include "mongo/util/net/op_msg.h"
namespace mongo {
@@ -79,7 +80,7 @@ public:
bool isValid(std::string* errMsg) const;
BSONObj toBSON() const;
- bool parseBSON(StringData dbName, const BSONObj& source, std::string* errMsg);
+ void parseRequest(const OpMsgRequest& request);
std::string toString() const;
//
diff --git a/src/mongo/s/write_ops/batched_command_request_test.cpp b/src/mongo/s/write_ops/batched_command_request_test.cpp
index 6bbd024f4df..82bbd4a3172 100644
--- a/src/mongo/s/write_ops/batched_command_request_test.cpp
+++ b/src/mongo/s/write_ops/batched_command_request_test.cpp
@@ -29,6 +29,7 @@
#include "mongo/platform/basic.h"
#include "mongo/bson/json.h"
+#include "mongo/db/ops/write_ops_parsers_test_helpers.h"
#include "mongo/s/write_ops/batched_command_request.h"
#include "mongo/stdx/memory.h"
#include "mongo/unittest/unittest.h"
@@ -48,12 +49,13 @@ TEST(BatchedCommandRequest, BasicInsert) {
<< "ordered"
<< true);
- std::string errMsg;
- BatchedCommandRequest insertRequest(BatchedCommandRequest::BatchType_Insert);
- ASSERT_TRUE(insertRequest.parseBSON("TestDB", origInsertRequestObj, &errMsg));
+ for (auto docSeq : {false, true}) {
+ BatchedCommandRequest insertRequest(BatchedCommandRequest::BatchType_Insert);
+ insertRequest.parseRequest(toOpMsg("TestDB", origInsertRequestObj, docSeq));
- ASSERT_EQ("TestDB.test", insertRequest.getInsertRequest()->getNS().toString());
- ASSERT(!insertRequest.hasShardVersion());
+ ASSERT_EQ("TestDB.test", insertRequest.getInsertRequest()->getNS().toString());
+ ASSERT(!insertRequest.hasShardVersion());
+ }
}
TEST(BatchedCommandRequest, InsertWithShardVersion) {
@@ -72,13 +74,14 @@ TEST(BatchedCommandRequest, InsertWithShardVersion) {
<< "shardVersion"
<< BSON_ARRAY(Timestamp(1, 2) << epoch));
- std::string errMsg;
- BatchedCommandRequest insertRequest(BatchedCommandRequest::BatchType_Insert);
- ASSERT_TRUE(insertRequest.parseBSON("TestDB", origInsertRequestObj, &errMsg));
+ for (auto docSeq : {false, true}) {
+ BatchedCommandRequest insertRequest(BatchedCommandRequest::BatchType_Insert);
+ insertRequest.parseRequest(toOpMsg("TestDB", origInsertRequestObj, docSeq));
- ASSERT_EQ("TestDB.test", insertRequest.getInsertRequest()->getNS().toString());
- ASSERT(insertRequest.hasShardVersion());
- ASSERT_EQ(ChunkVersion(1, 2, epoch).toString(), insertRequest.getShardVersion().toString());
+ ASSERT_EQ("TestDB.test", insertRequest.getInsertRequest()->getNS().toString());
+ ASSERT(insertRequest.hasShardVersion());
+ ASSERT_EQ(ChunkVersion(1, 2, epoch).toString(), insertRequest.getShardVersion().toString());
+ }
}
TEST(BatchedCommandRequest, InsertCloneWithId) {
diff --git a/src/mongo/s/write_ops/batched_delete_request.cpp b/src/mongo/s/write_ops/batched_delete_request.cpp
index 58a4f47fff2..ae5f22d24da 100644
--- a/src/mongo/s/write_ops/batched_delete_request.cpp
+++ b/src/mongo/s/write_ops/batched_delete_request.cpp
@@ -99,48 +99,59 @@ BSONObj BatchedDeleteRequest::toBSON() const {
return builder.obj();
}
-bool BatchedDeleteRequest::parseBSON(StringData dbName, const BSONObj& source, string* errMsg) {
+void BatchedDeleteRequest::parseRequest(const OpMsgRequest& request) {
clear();
- std::string dummy;
- if (!errMsg)
- errMsg = &dummy;
+ for (BSONElement field : request.body) {
+ auto extractField = [&](const auto& fieldDesc, auto* valOut, auto* isSetOut) {
+ std::string errMsg;
+ FieldParser::FieldState fieldState =
+ FieldParser::extract(field, fieldDesc, valOut, &errMsg);
+ if (fieldState == FieldParser::FIELD_INVALID) {
+ uasserted(ErrorCodes::FailedToParse, errMsg);
+ }
+ *isSetOut = fieldState == FieldParser::FIELD_SET;
+ };
- FieldParser::FieldState fieldState;
- for (BSONElement field : source) {
const StringData fieldName = field.fieldNameStringData();
if (fieldName == collName.name()) {
std::string collNameTemp;
- fieldState = FieldParser::extract(field, collName, &collNameTemp, errMsg);
- if (fieldState == FieldParser::FIELD_INVALID)
- return false;
- _ns = NamespaceString(dbName, collNameTemp);
+ extractField(collName, &collNameTemp, &_isNSSet);
+ _ns = NamespaceString(request.getDatabase(), collNameTemp);
uassert(ErrorCodes::InvalidNamespace,
str::stream() << "Invalid namespace: " << _ns.ns(),
_ns.isValid());
- _isNSSet = fieldState == FieldParser::FIELD_SET;
} else if (fieldName == deletes.name()) {
- fieldState = FieldParser::extract(field, deletes, &_deletes, errMsg);
- if (fieldState == FieldParser::FIELD_INVALID)
- return false;
- _isDeletesSet = fieldState == FieldParser::FIELD_SET;
+ extractField(deletes, &_deletes, &_isDeletesSet);
} else if (fieldName == writeConcern.name()) {
- fieldState = FieldParser::extract(field, writeConcern, &_writeConcern, errMsg);
- if (fieldState == FieldParser::FIELD_INVALID)
- return false;
- _isWriteConcernSet = fieldState == FieldParser::FIELD_SET;
+ extractField(writeConcern, &_writeConcern, &_isWriteConcernSet);
} else if (fieldName == ordered.name()) {
- fieldState = FieldParser::extract(field, ordered, &_ordered, errMsg);
- if (fieldState == FieldParser::FIELD_INVALID)
- return false;
- _isOrderedSet = fieldState == FieldParser::FIELD_SET;
+ extractField(ordered, &_ordered, &_isOrderedSet);
} else if (!Command::isGenericArgument(fieldName)) {
- *errMsg = str::stream() << "Unknown option to delete command: " << fieldName;
- return false;
+ uasserted(ErrorCodes::FailedToParse,
+ str::stream() << "Unknown option to delete command: " << fieldName);
}
}
- return true;
+ for (auto&& seq : request.sequences) {
+ uassert(ErrorCodes::FailedToParse,
+ str::stream() << "Unknown document sequence option to " << request.getCommandName()
+ << " command: "
+ << seq.name,
+ seq.name == deletes());
+ uassert(ErrorCodes::FailedToParse,
+ str::stream() << "Duplicate document sequence " << deletes(),
+ !_isDeletesSet);
+ _isDeletesSet = true;
+
+ for (auto&& obj : seq.objs) {
+ _deletes.push_back(new BatchedDeleteDocument()); // _deletes takes ownership.
+ std::string errMsg;
+ uassert(ErrorCodes::FailedToParse,
+ errMsg,
+ _deletes.back()->parseBSON(obj, &errMsg) && _deletes.back()->isValid(&errMsg));
+ }
+ }
}
void BatchedDeleteRequest::clear() {
diff --git a/src/mongo/s/write_ops/batched_delete_request.h b/src/mongo/s/write_ops/batched_delete_request.h
index c539ad7d766..cb8cae589f9 100644
--- a/src/mongo/s/write_ops/batched_delete_request.h
+++ b/src/mongo/s/write_ops/batched_delete_request.h
@@ -35,6 +35,7 @@
#include "mongo/db/jsobj.h"
#include "mongo/db/namespace_string.h"
#include "mongo/s/write_ops/batched_delete_document.h"
+#include "mongo/util/net/op_msg.h"
namespace mongo {
@@ -68,7 +69,7 @@ public:
bool isValid(std::string* errMsg) const;
BSONObj toBSON() const;
- bool parseBSON(StringData dbName, const BSONObj& source, std::string* errMsg);
+ void parseRequest(const OpMsgRequest& request);
void clear();
std::string toString() const;
diff --git a/src/mongo/s/write_ops/batched_delete_request_test.cpp b/src/mongo/s/write_ops/batched_delete_request_test.cpp
index 24b6edbdb9a..5ec55960020 100644
--- a/src/mongo/s/write_ops/batched_delete_request_test.cpp
+++ b/src/mongo/s/write_ops/batched_delete_request_test.cpp
@@ -31,6 +31,7 @@
#include <string>
#include "mongo/db/jsobj.h"
+#include "mongo/db/ops/write_ops_parsers_test_helpers.h"
#include "mongo/s/write_ops/batched_delete_document.h"
#include "mongo/s/write_ops/batched_delete_request.h"
#include "mongo/unittest/unittest.h"
@@ -52,12 +53,14 @@ TEST(BatchedDeleteRequest, Basic) {
<< BatchedDeleteRequest::ordered(true));
string errMsg;
- BatchedDeleteRequest request;
- ASSERT_TRUE(request.parseBSON("foo", origDeleteRequestObj, &errMsg));
+ for (auto docSeq : {false, true}) {
+ BatchedDeleteRequest request;
+ request.parseRequest(toOpMsg("foo", origDeleteRequestObj, docSeq));
- ASSERT_EQ("foo.test", request.getNS().ns());
+ ASSERT_EQ("foo.test", request.getNS().ns());
- ASSERT_BSONOBJ_EQ(origDeleteRequestObj, request.toBSON());
+ ASSERT_BSONOBJ_EQ(origDeleteRequestObj, request.toBSON());
+ }
}
TEST(BatchedDeleteRequest, CloneBatchedDeleteDocCopiesAllFields) {
@@ -130,18 +133,19 @@ TEST(BatchedDeleteRequest, CollationFieldParsesFromBSONCorrectly) {
BSONObj origDeleteRequestObj = BSON(
BatchedDeleteRequest::collName("test") << BatchedDeleteRequest::deletes() << deleteArray);
- std::string errMsg;
- BatchedDeleteRequest request;
- ASSERT_TRUE(request.parseBSON("foo", origDeleteRequestObj, &errMsg));
+ for (auto docSeq : {false, true}) {
+ BatchedDeleteRequest request;
+ request.parseRequest(toOpMsg("foo", origDeleteRequestObj, docSeq));
- ASSERT_EQ(1U, request.sizeDeletes());
- ASSERT_TRUE(request.getDeletesAt(0)->isCollationSet());
- ASSERT_BSONOBJ_EQ(BSON("locale"
- << "en_US"),
- request.getDeletesAt(0)->getCollation());
+ ASSERT_EQ(1U, request.sizeDeletes());
+ ASSERT_TRUE(request.getDeletesAt(0)->isCollationSet());
+ ASSERT_BSONOBJ_EQ(BSON("locale"
+ << "en_US"),
+ request.getDeletesAt(0)->getCollation());
- // Ensure we re-serialize to the original BSON request.
- ASSERT_BSONOBJ_EQ(origDeleteRequestObj, request.toBSON());
+ // Ensure we re-serialize to the original BSON request.
+ ASSERT_BSONOBJ_EQ(origDeleteRequestObj, request.toBSON());
+ }
}
} // namespace
diff --git a/src/mongo/s/write_ops/batched_insert_request.cpp b/src/mongo/s/write_ops/batched_insert_request.cpp
index 39849a45fd9..c8a6de58766 100644
--- a/src/mongo/s/write_ops/batched_insert_request.cpp
+++ b/src/mongo/s/write_ops/batched_insert_request.cpp
@@ -100,59 +100,57 @@ static void extractIndexNSS(const BSONObj& indexDesc, NamespaceString* indexNSS)
*indexNSS = NamespaceString(indexDesc["ns"].str());
}
-bool BatchedInsertRequest::parseBSON(StringData dbName, const BSONObj& source, string* errMsg) {
+void BatchedInsertRequest::parseRequest(const OpMsgRequest& request) {
clear();
- std::string dummy;
- if (!errMsg)
- errMsg = &dummy;
-
- BSONObjIterator sourceIt(source);
-
- while (sourceIt.more()) {
- BSONElement sourceEl = sourceIt.next();
+ for (auto&& sourceEl : request.body) {
const auto fieldName = sourceEl.fieldNameStringData();
+ auto extractField = [&](const auto& field, auto* valOut, auto* isSetOut) {
+ std::string errMsg;
+ FieldParser::FieldState fieldState =
+ FieldParser::extract(sourceEl, field, valOut, &errMsg);
+ if (fieldState == FieldParser::FIELD_INVALID) {
+ uasserted(ErrorCodes::FailedToParse, errMsg);
+ }
+ *isSetOut = fieldState == FieldParser::FIELD_SET;
+ };
+
if (fieldName == collName()) {
std::string temp;
- FieldParser::FieldState fieldState =
- FieldParser::extract(sourceEl, collName, &temp, errMsg);
- if (fieldState == FieldParser::FIELD_INVALID)
- return false;
- _ns = NamespaceString(dbName, temp);
+ extractField(collName, &temp, &_isNSSet);
+ _ns = NamespaceString(request.getDatabase(), temp);
uassert(ErrorCodes::InvalidNamespace,
str::stream() << "Invalid namespace: " << _ns.ns(),
_ns.isValid());
- _isNSSet = fieldState == FieldParser::FIELD_SET;
} else if (fieldName == documents()) {
- FieldParser::FieldState fieldState =
- FieldParser::extract(sourceEl, documents, &_documents, errMsg);
- if (fieldState == FieldParser::FIELD_INVALID)
- return false;
- _isDocumentsSet = fieldState == FieldParser::FIELD_SET;
+ extractField(documents, &_documents, &_isDocumentsSet);
if (_documents.size() >= 1)
extractIndexNSS(_documents.at(0), &_targetNSS);
} else if (fieldName == writeConcern()) {
- FieldParser::FieldState fieldState =
- FieldParser::extract(sourceEl, writeConcern, &_writeConcern, errMsg);
- if (fieldState == FieldParser::FIELD_INVALID)
- return false;
- _isWriteConcernSet = fieldState == FieldParser::FIELD_SET;
+ extractField(writeConcern, &_writeConcern, &_isWriteConcernSet);
} else if (fieldName == ordered()) {
- FieldParser::FieldState fieldState =
- FieldParser::extract(sourceEl, ordered, &_ordered, errMsg);
- if (fieldState == FieldParser::FIELD_INVALID)
- return false;
- _isOrderedSet = fieldState == FieldParser::FIELD_SET;
+ extractField(ordered, &_ordered, &_isOrderedSet);
} else if (fieldName == bypassDocumentValidationCommandOption()) {
_shouldBypassValidation = sourceEl.trueValue();
} else if (!Command::isGenericArgument(fieldName)) {
- *errMsg = str::stream() << "Unknown option to insert command: " << sourceEl.fieldName();
- return false;
+ uasserted(ErrorCodes::FailedToParse,
+ str::stream() << "Unknown option to insert command: " << fieldName);
}
}
- return true;
+ for (auto&& seq : request.sequences) {
+ uassert(ErrorCodes::FailedToParse,
+ str::stream() << "Unknown document sequence option to " << request.getCommandName()
+ << " command: "
+ << seq.name,
+ seq.name == documents());
+ uassert(ErrorCodes::FailedToParse,
+ str::stream() << "Duplicate document sequence " << documents(),
+ !_isDocumentsSet);
+ _isDocumentsSet = true;
+ _documents = seq.objs;
+ }
}
void BatchedInsertRequest::clear() {
diff --git a/src/mongo/s/write_ops/batched_insert_request.h b/src/mongo/s/write_ops/batched_insert_request.h
index 6d642f248e1..18b45a2d241 100644
--- a/src/mongo/s/write_ops/batched_insert_request.h
+++ b/src/mongo/s/write_ops/batched_insert_request.h
@@ -34,6 +34,7 @@
#include "mongo/base/string_data.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/namespace_string.h"
+#include "mongo/util/net/op_msg.h"
namespace mongo {
@@ -69,7 +70,7 @@ public:
bool isValid(std::string* errMsg) const;
BSONObj toBSON() const;
- bool parseBSON(StringData dbName, const BSONObj& source, std::string* errMsg);
+ void parseRequest(const OpMsgRequest& request);
void clear();
std::string toString() const;
diff --git a/src/mongo/s/write_ops/batched_insert_request_test.cpp b/src/mongo/s/write_ops/batched_insert_request_test.cpp
index 94976195c59..e9dc7c01963 100644
--- a/src/mongo/s/write_ops/batched_insert_request_test.cpp
+++ b/src/mongo/s/write_ops/batched_insert_request_test.cpp
@@ -31,6 +31,7 @@
#include <string>
#include "mongo/db/jsobj.h"
+#include "mongo/db/ops/write_ops_parsers_test_helpers.h"
#include "mongo/s/write_ops/batched_command_request.h"
#include "mongo/s/write_ops/batched_insert_request.h"
#include "mongo/unittest/unittest.h"
@@ -50,13 +51,14 @@ TEST(BatchedInsertRequest, Basic) {
<< BatchedInsertRequest::writeConcern(BSON("w" << 1))
<< BatchedInsertRequest::ordered(true));
- string errMsg;
- BatchedInsertRequest request;
- ASSERT_TRUE(request.parseBSON("foo", origInsertRequestObj, &errMsg));
+ for (auto docSeq : {false, true}) {
+ BatchedInsertRequest request;
+ request.parseRequest(toOpMsg("foo", origInsertRequestObj, docSeq));
- ASSERT_EQ("foo.test", request.getNS().ns());
+ ASSERT_EQ("foo.test", request.getNS().ns());
- ASSERT_BSONOBJ_EQ(origInsertRequestObj, request.toBSON());
+ ASSERT_BSONOBJ_EQ(origInsertRequestObj, request.toBSON());
+ }
}
TEST(BatchedInsertRequest, GenIDAll) {
diff --git a/src/mongo/s/write_ops/batched_update_request.cpp b/src/mongo/s/write_ops/batched_update_request.cpp
index 6da2498ec14..3740d0e3531 100644
--- a/src/mongo/s/write_ops/batched_update_request.cpp
+++ b/src/mongo/s/write_ops/batched_update_request.cpp
@@ -103,53 +103,61 @@ BSONObj BatchedUpdateRequest::toBSON() const {
return builder.obj();
}
-bool BatchedUpdateRequest::parseBSON(StringData dbName, const BSONObj& source, string* errMsg) {
+void BatchedUpdateRequest::parseRequest(const OpMsgRequest& request) {
clear();
- std::string dummy;
- if (!errMsg)
- errMsg = &dummy;
-
- FieldParser::FieldState fieldState;
-
- BSONObjIterator it(source);
- while (it.more()) {
- const BSONElement& elem = it.next();
- StringData fieldName = elem.fieldNameStringData();
-
+ for (auto&& elem : request.body) {
+ auto extractField = [&](const auto& fieldDesc, auto* valOut, auto* isSetOut) {
+ std::string errMsg;
+ FieldParser::FieldState fieldState =
+ FieldParser::extract(elem, fieldDesc, valOut, &errMsg);
+ if (fieldState == FieldParser::FIELD_INVALID) {
+ uasserted(ErrorCodes::FailedToParse, errMsg);
+ }
+ *isSetOut = fieldState == FieldParser::FIELD_SET;
+ };
+
+ const StringData fieldName = elem.fieldNameStringData();
if (fieldName == collName.name()) {
std::string collNameTemp;
- fieldState = FieldParser::extract(elem, collName, &collNameTemp, errMsg);
- if (fieldState == FieldParser::FIELD_INVALID)
- return false;
- _ns = NamespaceString(dbName, collNameTemp);
+ extractField(collName, &collNameTemp, &_isNSSet);
+ _ns = NamespaceString(request.getDatabase(), collNameTemp);
uassert(ErrorCodes::InvalidNamespace,
str::stream() << "Invalid namespace: " << _ns.ns(),
_ns.isValid());
- _isNSSet = fieldState == FieldParser::FIELD_SET;
} else if (fieldName == updates.name()) {
- fieldState = FieldParser::extract(elem, updates, &_updates, errMsg);
- if (fieldState == FieldParser::FIELD_INVALID)
- return false;
- _isUpdatesSet = fieldState == FieldParser::FIELD_SET;
+ extractField(updates, &_updates, &_isUpdatesSet);
} else if (fieldName == writeConcern.name()) {
- fieldState = FieldParser::extract(elem, writeConcern, &_writeConcern, errMsg);
- if (fieldState == FieldParser::FIELD_INVALID)
- return false;
- _isWriteConcernSet = fieldState == FieldParser::FIELD_SET;
+ extractField(writeConcern, &_writeConcern, &_isWriteConcernSet);
} else if (fieldName == ordered.name()) {
- fieldState = FieldParser::extract(elem, ordered, &_ordered, errMsg);
- if (fieldState == FieldParser::FIELD_INVALID)
- return false;
- _isOrderedSet = fieldState == FieldParser::FIELD_SET;
+ extractField(ordered, &_ordered, &_isOrderedSet);
} else if (fieldName == bypassDocumentValidationCommandOption()) {
_shouldBypassValidation = elem.trueValue();
} else if (!Command::isGenericArgument(fieldName)) {
- *errMsg = str::stream() << "Unknown option to update command: " << fieldName;
- return false;
+ uasserted(ErrorCodes::FailedToParse,
+ str::stream() << "Unknown option to update command: " << fieldName);
+ }
+ }
+
+ for (auto&& seq : request.sequences) {
+ uassert(ErrorCodes::FailedToParse,
+ str::stream() << "Unknown document sequence option to " << request.getCommandName()
+ << " command: "
+ << seq.name,
+ seq.name == updates());
+ uassert(ErrorCodes::FailedToParse,
+ str::stream() << "Duplicate document sequence " << updates(),
+ !_isUpdatesSet);
+ _isUpdatesSet = true;
+
+ for (auto&& obj : seq.objs) {
+ _updates.push_back(new BatchedUpdateDocument()); // _updates takes ownership.
+ std::string errMsg;
+ uassert(ErrorCodes::FailedToParse,
+ errMsg,
+ _updates.back()->parseBSON(obj, &errMsg) && _updates.back()->isValid(&errMsg));
}
}
- return true;
}
void BatchedUpdateRequest::clear() {
diff --git a/src/mongo/s/write_ops/batched_update_request.h b/src/mongo/s/write_ops/batched_update_request.h
index 88a8f1ef929..ebfcf1902c0 100644
--- a/src/mongo/s/write_ops/batched_update_request.h
+++ b/src/mongo/s/write_ops/batched_update_request.h
@@ -35,6 +35,7 @@
#include "mongo/db/jsobj.h"
#include "mongo/db/namespace_string.h"
#include "mongo/s/write_ops/batched_update_document.h"
+#include "mongo/util/net/op_msg.h"
namespace mongo {
@@ -68,7 +69,7 @@ public:
bool isValid(std::string* errMsg) const;
BSONObj toBSON() const;
- bool parseBSON(StringData dbName, const BSONObj& source, std::string* errMsg);
+ void parseRequest(const OpMsgRequest& request);
void clear();
std::string toString() const;
diff --git a/src/mongo/s/write_ops/batched_update_request_test.cpp b/src/mongo/s/write_ops/batched_update_request_test.cpp
index c198584e317..da1ab6f9a04 100644
--- a/src/mongo/s/write_ops/batched_update_request_test.cpp
+++ b/src/mongo/s/write_ops/batched_update_request_test.cpp
@@ -31,6 +31,7 @@
#include <string>
#include "mongo/db/jsobj.h"
+#include "mongo/db/ops/write_ops_parsers_test_helpers.h"
#include "mongo/s/write_ops/batched_update_document.h"
#include "mongo/s/write_ops/batched_update_request.h"
#include "mongo/unittest/unittest.h"
@@ -57,13 +58,14 @@ TEST(BatchedUpdateRequest, Basic) {
<< BatchedUpdateRequest::writeConcern(BSON("w" << 1))
<< BatchedUpdateRequest::ordered(true));
- string errMsg;
- BatchedUpdateRequest request;
- ASSERT_TRUE(request.parseBSON("foo", origUpdateRequestObj, &errMsg));
+ for (auto docSeq : {false, true}) {
+ BatchedUpdateRequest request;
+ request.parseRequest(toOpMsg("foo", origUpdateRequestObj, docSeq));
- ASSERT_EQ("foo.test", request.getNS().ns());
+ ASSERT_EQ("foo.test", request.getNS().ns());
- ASSERT_BSONOBJ_EQ(origUpdateRequestObj, request.toBSON());
+ ASSERT_BSONOBJ_EQ(origUpdateRequestObj, request.toBSON());
+ }
}
TEST(BatchedUpdateRequest, CloneBatchedUpdateDocCopiesAllFields) {
@@ -150,18 +152,19 @@ TEST(BatchedUpdateRequest, CollationFieldParsesFromBSONCorrectly) {
BSONObj origUpdateRequestObj = BSON(
BatchedUpdateRequest::collName("test") << BatchedUpdateRequest::updates() << updateArray);
- std::string errMsg;
- BatchedUpdateRequest request;
- ASSERT_TRUE(request.parseBSON("foo", origUpdateRequestObj, &errMsg));
+ for (auto docSeq : {false, true}) {
+ BatchedUpdateRequest request;
+ request.parseRequest(toOpMsg("foo", origUpdateRequestObj, docSeq));
- ASSERT_EQ(1U, request.sizeUpdates());
- ASSERT_TRUE(request.getUpdatesAt(0)->isCollationSet());
- ASSERT_BSONOBJ_EQ(BSON("locale"
- << "en_US"),
- request.getUpdatesAt(0)->getCollation());
+ ASSERT_EQ(1U, request.sizeUpdates());
+ ASSERT_TRUE(request.getUpdatesAt(0)->isCollationSet());
+ ASSERT_BSONOBJ_EQ(BSON("locale"
+ << "en_US"),
+ request.getUpdatesAt(0)->getCollation());
- // Ensure we re-serialize to the original BSON request.
- ASSERT_BSONOBJ_EQ(origUpdateRequestObj, request.toBSON());
+ // Ensure we re-serialize to the original BSON request.
+ ASSERT_BSONOBJ_EQ(origUpdateRequestObj, request.toBSON());
+ }
}
TEST(BatchedUpdateRequest, CanSetAndRetrieveArrayFiltersField) {
@@ -214,17 +217,18 @@ TEST(BatchedUpdateRequest, ArrayFiltersFieldParsesFromBSONCorrectly) {
BSONObj origUpdateRequestObj = BSON(
BatchedUpdateRequest::collName("test") << BatchedUpdateRequest::updates() << updateArray);
- std::string errMsg;
- BatchedUpdateRequest request;
- ASSERT_TRUE(request.parseBSON("foo", origUpdateRequestObj, &errMsg));
+ for (auto docSeq : {false, true}) {
+ BatchedUpdateRequest request;
+ request.parseRequest(toOpMsg("foo", origUpdateRequestObj, docSeq));
- ASSERT_EQ(1U, request.sizeUpdates());
- ASSERT_TRUE(request.getUpdatesAt(0)->isArrayFiltersSet());
- ASSERT_EQ(1U, request.getUpdatesAt(0)->getArrayFilters().size());
- ASSERT_BSONOBJ_EQ(BSON("i" << 5), request.getUpdatesAt(0)->getArrayFilters()[0]);
+ ASSERT_EQ(1U, request.sizeUpdates());
+ ASSERT_TRUE(request.getUpdatesAt(0)->isArrayFiltersSet());
+ ASSERT_EQ(1U, request.getUpdatesAt(0)->getArrayFilters().size());
+ ASSERT_BSONOBJ_EQ(BSON("i" << 5), request.getUpdatesAt(0)->getArrayFilters()[0]);
- // Ensure we re-serialize to the original BSON request.
- ASSERT_BSONOBJ_EQ(origUpdateRequestObj, request.toBSON());
+ // Ensure we re-serialize to the original BSON request.
+ ASSERT_BSONOBJ_EQ(origUpdateRequestObj, request.toBSON());
+ }
}
} // namespace