summaryrefslogtreecommitdiff
path: root/src/mongo/db/ops
diff options
context:
space:
mode:
authorKaloian Manassiev <kaloian.manassiev@mongodb.com>2017-10-12 18:17:31 -0400
committerKaloian Manassiev <kaloian.manassiev@mongodb.com>2017-10-17 09:25:40 -0400
commitd77201bbde61bf9e19eca81d73bbcb8bd85c757c (patch)
tree74d3ab587646f620aadd8c6ad92730a17a32d907 /src/mongo/db/ops
parent5eb95437e55acb07680c72a8a14a2f485bce94d7 (diff)
downloadmongo-d77201bbde61bf9e19eca81d73bbcb8bd85c757c.tar.gz
SERVER-30532 Remove IDL-generated parser for the findAndModify result
Instead only use a generator, but not parser. Also adds lastErrorObject.upserted to the findAndModify retry result.
Diffstat (limited to 'src/mongo/db/ops')
-rw-r--r--src/mongo/db/ops/find_and_modify_result.cpp77
-rw-r--r--src/mongo/db/ops/find_and_modify_result.h50
-rw-r--r--src/mongo/db/ops/update_result.cpp12
-rw-r--r--src/mongo/db/ops/update_result.h16
-rw-r--r--src/mongo/db/ops/write_ops_retryability.cpp78
-rw-r--r--src/mongo/db/ops/write_ops_retryability.h12
-rw-r--r--src/mongo/db/ops/write_ops_retryability_test.cpp242
7 files changed, 296 insertions, 191 deletions
diff --git a/src/mongo/db/ops/find_and_modify_result.cpp b/src/mongo/db/ops/find_and_modify_result.cpp
new file mode 100644
index 00000000000..30f8dad9b6d
--- /dev/null
+++ b/src/mongo/db/ops/find_and_modify_result.cpp
@@ -0,0 +1,77 @@
+/**
+ * Copyright (C) 2017 MongoDB Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the GNU Affero General Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kWrite
+
+#include "mongo/platform/basic.h"
+
+#include "mongo/db/ops/find_and_modify_result.h"
+
+#include "mongo/bson/bsonobjbuilder.h"
+#include "mongo/db/lasterror.h"
+
+namespace mongo {
+namespace find_and_modify {
+namespace {
+
+void appendValue(const boost::optional<BSONObj>& value, BSONObjBuilder* builder) {
+ if (value) {
+ builder->append("value", *value);
+ } else {
+ builder->appendNull("value");
+ }
+}
+
+} // namespace
+
+void serializeRemove(size_t n, const boost::optional<BSONObj>& value, BSONObjBuilder* builder) {
+ BSONObjBuilder lastErrorObjBuilder(builder->subobjStart("lastErrorObject"));
+ builder->appendNumber("n", n);
+ lastErrorObjBuilder.doneFast();
+
+ appendValue(value, builder);
+}
+
+void serializeUpsert(size_t n,
+ const boost::optional<BSONObj>& value,
+ bool updatedExisting,
+ const BSONObj& objInserted,
+ BSONObjBuilder* builder) {
+ BSONObjBuilder lastErrorObjBuilder(builder->subobjStart("lastErrorObject"));
+ lastErrorObjBuilder.appendNumber("n", n);
+ lastErrorObjBuilder.appendBool("updatedExisting", updatedExisting);
+ if (!objInserted.isEmpty()) {
+ lastErrorObjBuilder.appendAs(objInserted["_id"], kUpsertedFieldName);
+ }
+ lastErrorObjBuilder.doneFast();
+
+ appendValue(value, builder);
+}
+
+} // namespace find_and_modify
+} // namespace mongo
diff --git a/src/mongo/db/ops/find_and_modify_result.h b/src/mongo/db/ops/find_and_modify_result.h
new file mode 100644
index 00000000000..c335c5022fd
--- /dev/null
+++ b/src/mongo/db/ops/find_and_modify_result.h
@@ -0,0 +1,50 @@
+/**
+ * Copyright (C) 2017 MongoDB Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the GNU Affero General Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#pragma once
+
+#include <boost/optional.hpp>
+
+#include "mongo/bson/bsonobj.h"
+
+namespace mongo {
+
+class BSONObjBuilder;
+
+namespace find_and_modify {
+
+void serializeRemove(size_t n, const boost::optional<BSONObj>& value, BSONObjBuilder* builder);
+
+void serializeUpsert(size_t n,
+ const boost::optional<BSONObj>& value,
+ bool updatedExisting,
+ const BSONObj& objInserted,
+ BSONObjBuilder* builder);
+
+} // namespace find_and_modify
+} // namespace mongo
diff --git a/src/mongo/db/ops/update_result.cpp b/src/mongo/db/ops/update_result.cpp
index 97a5a5332df..93a9e152030 100644
--- a/src/mongo/db/ops/update_result.cpp
+++ b/src/mongo/db/ops/update_result.cpp
@@ -1,7 +1,5 @@
-//@file update_result.cpp
-
/**
- * Copyright (C) 2008-2014 MongoDB Inc.
+ * Copyright (C) 2017 MongoDB Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
@@ -28,6 +26,7 @@
* it in the license file.
*/
+
#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kWrite
#include "mongo/platform/basic.h"
@@ -36,6 +35,7 @@
#include "mongo/db/lasterror.h"
#include "mongo/util/log.h"
+#include "mongo/util/mongoutils/str.h"
namespace mongo {
@@ -55,4 +55,10 @@ UpdateResult::UpdateResult(bool existing_,
LOG(4) << "UpdateResult -- " << redact(toString());
}
+std::string UpdateResult::toString() const {
+ return str::stream() << " upserted: " << upserted << " modifiers: " << modifiers
+ << " existing: " << existing << " numDocsModified: " << numDocsModified
+ << " numMatched: " << numMatched;
+}
+
} // namespace mongo
diff --git a/src/mongo/db/ops/update_result.h b/src/mongo/db/ops/update_result.h
index 2c3107e3ea1..1b0a40520ee 100644
--- a/src/mongo/db/ops/update_result.h
+++ b/src/mongo/db/ops/update_result.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2013 10gen Inc.
+ * Copyright (C) 2017 MongoDB Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
@@ -28,15 +28,10 @@
#pragma once
-#include "mongo/db/curop.h"
-#include "mongo/db/jsobj.h"
-#include "mongo/db/namespace_string.h"
-#include "mongo/util/mongoutils/str.h"
+#include "mongo/bson/bsonobj.h"
namespace mongo {
-namespace str = mongoutils::str;
-
struct UpdateResult {
UpdateResult(bool existing_,
bool modifiers_,
@@ -44,6 +39,7 @@ struct UpdateResult {
unsigned long long numMatched_,
const BSONObj& upsertedObject_);
+ std::string toString() const;
// if existing objects were modified
const bool existing;
@@ -59,12 +55,6 @@ struct UpdateResult {
// if something was upserted, the new _id of the object
BSONObj upserted;
-
- const std::string toString() const {
- return str::stream() << " upserted: " << upserted << " modifiers: " << modifiers
- << " existing: " << existing << " numDocsModified: " << numDocsModified
- << " numMatched: " << numMatched;
- }
};
} // namespace mongo
diff --git a/src/mongo/db/ops/write_ops_retryability.cpp b/src/mongo/db/ops/write_ops_retryability.cpp
index 3d4fc90fb7e..28ce5bed8be 100644
--- a/src/mongo/db/ops/write_ops_retryability.cpp
+++ b/src/mongo/db/ops/write_ops_retryability.cpp
@@ -28,18 +28,16 @@
#include "mongo/platform/basic.h"
+#include "mongo/db/ops/write_ops_retryability.h"
+
#include "mongo/db/dbdirectclient.h"
#include "mongo/db/namespace_string.h"
-#include "mongo/db/operation_context.h"
-#include "mongo/db/ops/single_write_result_gen.h"
-#include "mongo/db/ops/write_ops.h"
+#include "mongo/db/ops/find_and_modify_result.h"
#include "mongo/db/ops/write_ops_exec.h"
-#include "mongo/db/ops/write_ops_retryability.h"
#include "mongo/db/query/find_and_modify_request.h"
#include "mongo/logger/redaction.h"
namespace mongo {
-
namespace {
/**
@@ -141,47 +139,26 @@ BSONObj extractPreOrPostImage(OperationContext* opCtx, const repl::OplogEntry& o
* previous execution of the command. In the case of nested oplog entry where the correct links
* are in the top level oplog, oplogWithCorrectLinks can be used to specify the outer oplog.
*/
-FindAndModifyResult parseOplogEntryForFindAndModify(OperationContext* opCtx,
- const FindAndModifyRequest& request,
- const repl::OplogEntry& oplogEntry,
- const repl::OplogEntry& oplogWithCorrectLinks) {
- const auto opType = oplogEntry.getOpType();
-
+void parseOplogEntryForFindAndModify(OperationContext* opCtx,
+ const FindAndModifyRequest& request,
+ const repl::OplogEntry& oplogEntry,
+ const repl::OplogEntry& oplogWithCorrectLinks,
+ BSONObjBuilder* builder) {
validateFindAndModifyRetryability(request, oplogEntry, oplogWithCorrectLinks);
- FindAndModifyResult result;
-
- if (opType == repl::OpTypeEnum::kDelete) {
- FindAndModifyLastError lastError;
- lastError.setN(1);
- result.setLastErrorObject(std::move(lastError));
- result.setValue(extractPreOrPostImage(opCtx, oplogWithCorrectLinks));
-
- return result;
+ switch (oplogEntry.getOpType()) {
+ case repl::OpTypeEnum::kInsert:
+ return find_and_modify::serializeUpsert(
+ 1, oplogEntry.getObject(), false, oplogEntry.getObject(), builder);
+ case repl::OpTypeEnum::kUpdate:
+ return find_and_modify::serializeUpsert(
+ 1, extractPreOrPostImage(opCtx, oplogWithCorrectLinks), true, {}, builder);
+ case repl::OpTypeEnum::kDelete:
+ return find_and_modify::serializeRemove(
+ 1, extractPreOrPostImage(opCtx, oplogWithCorrectLinks), builder);
+ default:
+ MONGO_UNREACHABLE;
}
-
- // Upsert case
- if (opType == repl::OpTypeEnum::kInsert) {
- FindAndModifyLastError lastError;
- lastError.setN(1);
- lastError.setUpdatedExisting(false);
- // TODO: SERVER-30532 set upserted
-
- result.setLastErrorObject(std::move(lastError));
- result.setValue(oplogEntry.getObject().getOwned());
-
- return result;
- }
-
- // Update case
- FindAndModifyLastError lastError;
- lastError.setN(1);
- lastError.setUpdatedExisting(true);
-
- result.setLastErrorObject(std::move(lastError));
- result.setValue(extractPreOrPostImage(opCtx, oplogWithCorrectLinks));
-
- return result;
}
repl::OplogEntry getInnerNestedOplogEntry(const repl::OplogEntry& entry) {
@@ -267,16 +244,17 @@ SingleWriteResult parseOplogEntryForDelete(const repl::OplogEntry& entry) {
return res;
}
-FindAndModifyResult parseOplogEntryForFindAndModify(OperationContext* opCtx,
- const FindAndModifyRequest& request,
- const repl::OplogEntry& oplogEntry) {
+void parseOplogEntryForFindAndModify(OperationContext* opCtx,
+ const FindAndModifyRequest& request,
+ const repl::OplogEntry& oplogEntry,
+ BSONObjBuilder* builder) {
// Migrated op case.
if (oplogEntry.getOpType() == repl::OpTypeEnum::kNoop) {
- return parseOplogEntryForFindAndModify(
- opCtx, request, getInnerNestedOplogEntry(oplogEntry), oplogEntry);
+ parseOplogEntryForFindAndModify(
+ opCtx, request, getInnerNestedOplogEntry(oplogEntry), oplogEntry, builder);
+ } else {
+ parseOplogEntryForFindAndModify(opCtx, request, oplogEntry, oplogEntry, builder);
}
-
- return parseOplogEntryForFindAndModify(opCtx, request, oplogEntry, oplogEntry);
}
} // namespace mongo
diff --git a/src/mongo/db/ops/write_ops_retryability.h b/src/mongo/db/ops/write_ops_retryability.h
index 37f87a0d742..fa73a4d34ed 100644
--- a/src/mongo/db/ops/write_ops_retryability.h
+++ b/src/mongo/db/ops/write_ops_retryability.h
@@ -28,13 +28,13 @@
#pragma once
-#include "mongo/db/commands/find_and_modify_gen.h"
#include "mongo/db/ops/single_write_result_gen.h"
#include "mongo/db/ops/write_ops.h"
#include "mongo/db/repl/oplog_entry.h"
namespace mongo {
+class BSONObjBuilder;
class FindAndModifyRequest;
class OperationContext;
@@ -49,10 +49,12 @@ SingleWriteResult parseOplogEntryForUpdate(const repl::OplogEntry& entry);
SingleWriteResult parseOplogEntryForDelete(const repl::OplogEntry& entry);
/**
- * Returns the result of a findAndModify based on the oplog entries generated by the operation.
+ * Populates the passed-in builder with the result of a findAndModify based on the oplog entries
+ * generated by the operation.
*/
-FindAndModifyResult parseOplogEntryForFindAndModify(OperationContext* opCtx,
- const FindAndModifyRequest& request,
- const repl::OplogEntry& oplogEntry);
+void parseOplogEntryForFindAndModify(OperationContext* opCtx,
+ const FindAndModifyRequest& request,
+ const repl::OplogEntry& oplogEntry,
+ BSONObjBuilder* builder);
} // namespace mongo
diff --git a/src/mongo/db/ops/write_ops_retryability_test.cpp b/src/mongo/db/ops/write_ops_retryability_test.cpp
index 41774472760..4c6268c8c7f 100644
--- a/src/mongo/db/ops/write_ops_retryability_test.cpp
+++ b/src/mongo/db/ops/write_ops_retryability_test.cpp
@@ -29,16 +29,12 @@
#include "mongo/platform/basic.h"
#include "mongo/bson/bsonmisc.h"
-#include "mongo/db/curop.h"
-#include "mongo/db/db_raii.h"
-#include "mongo/db/dbdirectclient.h"
#include "mongo/db/namespace_string.h"
#include "mongo/db/ops/write_ops.h"
#include "mongo/db/ops/write_ops_retryability.h"
#include "mongo/db/query/find_and_modify_request.h"
#include "mongo/db/repl/mock_repl_coord_server_fixture.h"
#include "mongo/db/repl/oplog_entry.h"
-#include "mongo/db/repl/replication_coordinator_mock.h"
#include "mongo/db/service_context.h"
#include "mongo/db/service_context_d_test_fixture.h"
#include "mongo/unittest/unittest.h"
@@ -46,21 +42,22 @@
namespace mongo {
namespace {
-using WriteOpsRetryability = ServiceContextMongoDTest;
+using unittest::assertGet;
const BSONObj kNestedOplog(BSON("$sessionMigrateInfo" << 1));
+using WriteOpsRetryability = ServiceContextMongoDTest;
+
TEST_F(WriteOpsRetryability, ParseOplogEntryForInsert) {
- auto entry =
+ const auto entry = assertGet(
repl::OplogEntry::parse(BSON("ts" << Timestamp(50, 10) << "t" << 1LL << "h" << 0LL << "op"
<< "i"
<< "ns"
<< "a.b"
<< "o"
- << BSON("_id" << 1 << "x" << 5)));
- ASSERT(entry.isOK());
+ << BSON("_id" << 1 << "x" << 5))));
- auto res = mongo::parseOplogEntryForInsert(entry.getValue());
+ auto res = parseOplogEntryForInsert(entry);
ASSERT_EQ(res.getN(), 1);
ASSERT_EQ(res.getNModified(), 0);
@@ -80,7 +77,7 @@ TEST_F(WriteOpsRetryability, ParseOplogEntryForNestedInsert) {
kNestedOplog,
innerOplog.toBSON());
- auto res = mongo::parseOplogEntryForInsert(insertOplog);
+ auto res = parseOplogEntryForInsert(insertOplog);
ASSERT_EQ(res.getN(), 1);
ASSERT_EQ(res.getNModified(), 0);
@@ -88,7 +85,7 @@ TEST_F(WriteOpsRetryability, ParseOplogEntryForNestedInsert) {
}
TEST_F(WriteOpsRetryability, ParseOplogEntryForUpdate) {
- auto entry =
+ const auto entry = assertGet(
repl::OplogEntry::parse(BSON("ts" << Timestamp(50, 10) << "t" << 1LL << "h" << 0LL << "op"
<< "u"
<< "ns"
@@ -96,10 +93,9 @@ TEST_F(WriteOpsRetryability, ParseOplogEntryForUpdate) {
<< "o"
<< BSON("_id" << 1 << "x" << 5)
<< "o2"
- << BSON("_id" << 1)));
- ASSERT(entry.isOK());
+ << BSON("_id" << 1))));
- auto res = mongo::parseOplogEntryForUpdate(entry.getValue());
+ auto res = parseOplogEntryForUpdate(entry);
ASSERT_EQ(res.getN(), 1);
ASSERT_EQ(res.getNModified(), 1);
@@ -120,7 +116,7 @@ TEST_F(WriteOpsRetryability, ParseOplogEntryForNestedUpdate) {
kNestedOplog,
innerOplog.toBSON());
- auto res = mongo::parseOplogEntryForUpdate(updateOplog);
+ auto res = parseOplogEntryForUpdate(updateOplog);
ASSERT_EQ(res.getN(), 1);
ASSERT_EQ(res.getNModified(), 1);
@@ -128,16 +124,15 @@ TEST_F(WriteOpsRetryability, ParseOplogEntryForNestedUpdate) {
}
TEST_F(WriteOpsRetryability, ParseOplogEntryForUpsert) {
- auto entry =
+ const auto entry = assertGet(
repl::OplogEntry::parse(BSON("ts" << Timestamp(50, 10) << "t" << 1LL << "h" << 0LL << "op"
<< "i"
<< "ns"
<< "a.b"
<< "o"
- << BSON("_id" << 1 << "x" << 5)));
- ASSERT(entry.isOK());
+ << BSON("_id" << 1 << "x" << 5))));
- auto res = mongo::parseOplogEntryForUpdate(entry.getValue());
+ auto res = parseOplogEntryForUpdate(entry);
ASSERT_EQ(res.getN(), 1);
ASSERT_EQ(res.getNModified(), 0);
@@ -157,7 +152,7 @@ TEST_F(WriteOpsRetryability, ParseOplogEntryForNestedUpsert) {
kNestedOplog,
innerOplog.toBSON());
- auto res = mongo::parseOplogEntryForUpdate(insertOplog);
+ auto res = parseOplogEntryForUpdate(insertOplog);
ASSERT_EQ(res.getN(), 1);
ASSERT_EQ(res.getNModified(), 0);
@@ -165,16 +160,15 @@ TEST_F(WriteOpsRetryability, ParseOplogEntryForNestedUpsert) {
}
TEST_F(WriteOpsRetryability, ParseOplogEntryForDelete) {
- auto entry =
+ const auto entry = assertGet(
repl::OplogEntry::parse(BSON("ts" << Timestamp(50, 10) << "t" << 1LL << "h" << 0LL << "op"
<< "d"
<< "ns"
<< "a.b"
<< "o"
- << BSON("_id" << 1 << "x" << 5)));
- ASSERT(entry.isOK());
+ << BSON("_id" << 1 << "x" << 5))));
- auto res = mongo::parseOplogEntryForDelete(entry.getValue());
+ auto res = parseOplogEntryForDelete(entry);
ASSERT_EQ(res.getN(), 1);
ASSERT_EQ(res.getNModified(), 0);
@@ -194,7 +188,7 @@ TEST_F(WriteOpsRetryability, ParseOplogEntryForNestedDelete) {
kNestedOplog,
innerOplog.toBSON());
- auto res = mongo::parseOplogEntryForDelete(deleteOplog);
+ auto res = parseOplogEntryForDelete(deleteOplog);
ASSERT_EQ(res.getN(), 1);
ASSERT_EQ(res.getNModified(), 0);
@@ -231,31 +225,57 @@ TEST_F(WriteOpsRetryability, ShouldFailIfParsingInsertOplogForDelete) {
ASSERT_THROWS(parseOplogEntryForDelete(insertOplog), AssertionException);
}
-using FindAndModifyRetryability = MockReplCoordServerFixture;
-
-NamespaceString kNs("test.user");
+class FindAndModifyRetryability : public MockReplCoordServerFixture {
+public:
+ FindAndModifyRetryability() = default;
+
+protected:
+ /**
+ * Helper function to return a fully-constructed BSONObj instead of having to use
+ * BSONObjBuilder.
+ */
+ static BSONObj constructFindAndModifyRetryResult(OperationContext* opCtx,
+ const FindAndModifyRequest& request,
+ const repl::OplogEntry& oplogEntry) {
+ BSONObjBuilder builder;
+ parseOplogEntryForFindAndModify(opCtx, request, oplogEntry, &builder);
+ return builder.obj();
+ }
+};
+
+const NamespaceString kNs("test.user");
TEST_F(FindAndModifyRetryability, BasicUpsert) {
auto request = FindAndModifyRequest::makeUpdate(kNs, BSONObj(), BSONObj());
request.setUpsert(true);
- repl::OplogEntry insertOplog(repl::OpTime(), 0, repl::OpTypeEnum::kInsert, kNs, BSON("x" << 1));
-
- auto result = parseOplogEntryForFindAndModify(nullptr, request, insertOplog);
-
- auto lastError = result.getLastErrorObject();
- ASSERT_EQ(1, lastError.getN());
- ASSERT_TRUE(lastError.getUpdatedExisting());
- ASSERT_FALSE(lastError.getUpdatedExisting().value());
-
- ASSERT_BSONOBJ_EQ(BSON("x" << 1), result.getValue());
+ repl::OplogEntry insertOplog(repl::OpTime(),
+ 0,
+ repl::OpTypeEnum::kInsert,
+ kNs,
+ BSON("_id"
+ << "ID value"
+ << "x"
+ << 1));
+
+ auto result = constructFindAndModifyRetryResult(opCtx(), request, insertOplog);
+ ASSERT_BSONOBJ_EQ(BSON("lastErrorObject"
+ << BSON("n" << 1 << "updatedExisting" << false << "upserted"
+ << "ID value")
+ << "value"
+ << BSON("_id"
+ << "ID value"
+ << "x"
+ << 1)),
+ result);
}
TEST_F(FindAndModifyRetryability, NestedUpsert) {
auto request = FindAndModifyRequest::makeUpdate(kNs, BSONObj(), BSONObj());
request.setUpsert(true);
- repl::OplogEntry innerOplog(repl::OpTime(), 0, repl::OpTypeEnum::kInsert, kNs, BSON("x" << 1));
+ repl::OplogEntry innerOplog(
+ repl::OpTime(), 0, repl::OpTypeEnum::kInsert, kNs, BSON("_id" << 1));
repl::OplogEntry insertOplog(repl::OpTime(Timestamp(60, 10), 1),
0,
repl::OpTypeEnum::kNoop,
@@ -263,23 +283,22 @@ TEST_F(FindAndModifyRetryability, NestedUpsert) {
kNestedOplog,
innerOplog.toBSON());
- auto result = parseOplogEntryForFindAndModify(nullptr, request, insertOplog);
-
- auto lastError = result.getLastErrorObject();
- ASSERT_EQ(1, lastError.getN());
- ASSERT_TRUE(lastError.getUpdatedExisting());
- ASSERT_FALSE(lastError.getUpdatedExisting().value());
-
- ASSERT_BSONOBJ_EQ(BSON("x" << 1), result.getValue());
+ auto result = constructFindAndModifyRetryResult(opCtx(), request, insertOplog);
+ ASSERT_BSONOBJ_EQ(BSON("lastErrorObject"
+ << BSON("n" << 1 << "updatedExisting" << false << "upserted" << 1)
+ << "value"
+ << BSON("_id" << 1)),
+ result);
}
TEST_F(FindAndModifyRetryability, AttemptingToRetryUpsertWithUpdateWithoutUpsertErrors) {
auto request = FindAndModifyRequest::makeUpdate(kNs, BSONObj(), BSONObj());
request.setUpsert(false);
- repl::OplogEntry insertOplog(repl::OpTime(), 0, repl::OpTypeEnum::kInsert, kNs, BSON("x" << 1));
+ repl::OplogEntry insertOplog(
+ repl::OpTime(), 0, repl::OpTypeEnum::kInsert, kNs, BSON("_id" << 1));
- ASSERT_THROWS(parseOplogEntryForFindAndModify(opCtx(), request, insertOplog),
+ ASSERT_THROWS(constructFindAndModifyRetryResult(opCtx(), request, insertOplog),
AssertionException);
}
@@ -289,7 +308,7 @@ TEST_F(FindAndModifyRetryability, ErrorIfRequestIsPostImageButOplogHasPre) {
repl::OpTime imageOpTime(Timestamp(120, 3), 1);
repl::OplogEntry noteOplog(
- imageOpTime, 0, repl::OpTypeEnum::kNoop, kNs, BSON("x" << 1 << "z" << 1));
+ imageOpTime, 0, repl::OpTypeEnum::kNoop, kNs, BSON("_id" << 1 << "z" << 1));
insertOplogEntry(noteOplog);
@@ -297,11 +316,11 @@ TEST_F(FindAndModifyRetryability, ErrorIfRequestIsPostImageButOplogHasPre) {
0,
repl::OpTypeEnum::kUpdate,
kNs,
- BSON("x" << 1 << "y" << 1),
- BSON("x" << 1));
+ BSON("_id" << 1 << "y" << 1),
+ BSON("_id" << 1));
updateOplog.setPreImageOpTime(imageOpTime);
- ASSERT_THROWS(parseOplogEntryForFindAndModify(opCtx(), request, updateOplog),
+ ASSERT_THROWS(constructFindAndModifyRetryResult(opCtx(), request, updateOplog),
AssertionException);
}
@@ -311,14 +330,14 @@ TEST_F(FindAndModifyRetryability, ErrorIfRequestIsUpdateButOplogIsDelete) {
repl::OpTime imageOpTime(Timestamp(120, 3), 1);
repl::OplogEntry noteOplog(
- imageOpTime, 0, repl::OpTypeEnum::kNoop, kNs, BSON("x" << 1 << "z" << 1));
+ imageOpTime, 0, repl::OpTypeEnum::kNoop, kNs, BSON("_id" << 1 << "z" << 1));
insertOplogEntry(noteOplog);
repl::OplogEntry oplog(repl::OpTime(), 0, repl::OpTypeEnum::kDelete, kNs, BSON("_id" << 1));
oplog.setPreImageOpTime(imageOpTime);
- ASSERT_THROWS(parseOplogEntryForFindAndModify(opCtx(), request, oplog), AssertionException);
+ ASSERT_THROWS(constructFindAndModifyRetryResult(opCtx(), request, oplog), AssertionException);
}
TEST_F(FindAndModifyRetryability, ErrorIfRequestIsPreImageButOplogHasPost) {
@@ -327,7 +346,7 @@ TEST_F(FindAndModifyRetryability, ErrorIfRequestIsPreImageButOplogHasPost) {
repl::OpTime imageOpTime(Timestamp(120, 3), 1);
repl::OplogEntry noteOplog(
- imageOpTime, 0, repl::OpTypeEnum::kNoop, kNs, BSON("x" << 1 << "z" << 1));
+ imageOpTime, 0, repl::OpTypeEnum::kNoop, kNs, BSON("_id" << 1 << "z" << 1));
insertOplogEntry(noteOplog);
@@ -335,11 +354,11 @@ TEST_F(FindAndModifyRetryability, ErrorIfRequestIsPreImageButOplogHasPost) {
0,
repl::OpTypeEnum::kUpdate,
kNs,
- BSON("x" << 1 << "y" << 1),
- BSON("x" << 1));
+ BSON("_id" << 1 << "y" << 1),
+ BSON("_id" << 1));
updateOplog.setPostImageOpTime(imageOpTime);
- ASSERT_THROWS(parseOplogEntryForFindAndModify(opCtx(), request, updateOplog),
+ ASSERT_THROWS(constructFindAndModifyRetryResult(opCtx(), request, updateOplog),
AssertionException);
}
@@ -349,7 +368,7 @@ TEST_F(FindAndModifyRetryability, UpdateWithPreImage) {
repl::OpTime imageOpTime(Timestamp(120, 3), 1);
repl::OplogEntry noteOplog(
- imageOpTime, 0, repl::OpTypeEnum::kNoop, kNs, BSON("x" << 1 << "z" << 1));
+ imageOpTime, 0, repl::OpTypeEnum::kNoop, kNs, BSON("_id" << 1 << "z" << 1));
insertOplogEntry(noteOplog);
@@ -357,18 +376,15 @@ TEST_F(FindAndModifyRetryability, UpdateWithPreImage) {
0,
repl::OpTypeEnum::kUpdate,
kNs,
- BSON("x" << 1 << "y" << 1),
- BSON("x" << 1));
+ BSON("_id" << 1 << "y" << 1),
+ BSON("_id" << 1));
updateOplog.setPreImageOpTime(imageOpTime);
- auto result = parseOplogEntryForFindAndModify(opCtx(), request, updateOplog);
-
- auto lastError = result.getLastErrorObject();
- ASSERT_EQ(1, lastError.getN());
- ASSERT_TRUE(lastError.getUpdatedExisting());
- ASSERT_TRUE(lastError.getUpdatedExisting().value());
-
- ASSERT_BSONOBJ_EQ(BSON("x" << 1 << "z" << 1), result.getValue());
+ auto result = constructFindAndModifyRetryResult(opCtx(), request, updateOplog);
+ ASSERT_BSONOBJ_EQ(BSON("lastErrorObject" << BSON("n" << 1 << "updatedExisting" << true)
+ << "value"
+ << BSON("_id" << 1 << "z" << 1)),
+ result);
}
TEST_F(FindAndModifyRetryability, NestedUpdateWithPreImage) {
@@ -377,7 +393,7 @@ TEST_F(FindAndModifyRetryability, NestedUpdateWithPreImage) {
repl::OpTime imageOpTime(Timestamp(120, 3), 1);
repl::OplogEntry noteOplog(
- imageOpTime, 0, repl::OpTypeEnum::kNoop, kNs, BSON("x" << 1 << "z" << 1));
+ imageOpTime, 0, repl::OpTypeEnum::kNoop, kNs, BSON("_id" << 1 << "z" << 1));
insertOplogEntry(noteOplog);
@@ -385,8 +401,8 @@ TEST_F(FindAndModifyRetryability, NestedUpdateWithPreImage) {
0,
repl::OpTypeEnum::kUpdate,
kNs,
- BSON("x" << 1 << "y" << 1),
- BSON("x" << 1));
+ BSON("_id" << 1 << "y" << 1),
+ BSON("_id" << 1));
repl::OplogEntry updateOplog(repl::OpTime(Timestamp(60, 10), 1),
0,
@@ -396,14 +412,11 @@ TEST_F(FindAndModifyRetryability, NestedUpdateWithPreImage) {
innerOplog.toBSON());
updateOplog.setPreImageOpTime(imageOpTime);
- auto result = parseOplogEntryForFindAndModify(opCtx(), request, updateOplog);
-
- auto lastError = result.getLastErrorObject();
- ASSERT_EQ(1, lastError.getN());
- ASSERT_TRUE(lastError.getUpdatedExisting());
- ASSERT_TRUE(lastError.getUpdatedExisting().value());
-
- ASSERT_BSONOBJ_EQ(BSON("x" << 1 << "z" << 1), result.getValue());
+ auto result = constructFindAndModifyRetryResult(opCtx(), request, updateOplog);
+ ASSERT_BSONOBJ_EQ(BSON("lastErrorObject" << BSON("n" << 1 << "updatedExisting" << true)
+ << "value"
+ << BSON("_id" << 1 << "z" << 1)),
+ result);
}
TEST_F(FindAndModifyRetryability, UpdateWithPostImage) {
@@ -420,18 +433,15 @@ TEST_F(FindAndModifyRetryability, UpdateWithPostImage) {
0,
repl::OpTypeEnum::kUpdate,
kNs,
- BSON("x" << 1 << "y" << 1),
- BSON("x" << 1));
+ BSON("_id" << 1 << "y" << 1),
+ BSON("_id" << 1));
updateOplog.setPostImageOpTime(imageOpTime);
- auto result = parseOplogEntryForFindAndModify(opCtx(), request, updateOplog);
-
- auto lastError = result.getLastErrorObject();
- ASSERT_EQ(1, lastError.getN());
- ASSERT_TRUE(lastError.getUpdatedExisting());
- ASSERT_TRUE(lastError.getUpdatedExisting().value());
-
- ASSERT_BSONOBJ_EQ(BSON("a" << 1 << "b" << 1), result.getValue());
+ auto result = constructFindAndModifyRetryResult(opCtx(), request, updateOplog);
+ ASSERT_BSONOBJ_EQ(BSON("lastErrorObject" << BSON("n" << 1 << "updatedExisting" << true)
+ << "value"
+ << BSON("a" << 1 << "b" << 1)),
+ result);
}
TEST_F(FindAndModifyRetryability, NestedUpdateWithPostImage) {
@@ -448,8 +458,8 @@ TEST_F(FindAndModifyRetryability, NestedUpdateWithPostImage) {
0,
repl::OpTypeEnum::kUpdate,
kNs,
- BSON("x" << 1 << "y" << 1),
- BSON("x" << 1));
+ BSON("_id" << 1 << "y" << 1),
+ BSON("_id" << 1));
repl::OplogEntry updateOplog(repl::OpTime(Timestamp(60, 10), 1),
0,
@@ -459,14 +469,11 @@ TEST_F(FindAndModifyRetryability, NestedUpdateWithPostImage) {
innerOplog.toBSON());
updateOplog.setPostImageOpTime(imageOpTime);
- auto result = parseOplogEntryForFindAndModify(opCtx(), request, updateOplog);
-
- auto lastError = result.getLastErrorObject();
- ASSERT_EQ(1, lastError.getN());
- ASSERT_TRUE(lastError.getUpdatedExisting());
- ASSERT_TRUE(lastError.getUpdatedExisting().value());
-
- ASSERT_BSONOBJ_EQ(BSON("a" << 1 << "b" << 1), result.getValue());
+ auto result = constructFindAndModifyRetryResult(opCtx(), request, updateOplog);
+ ASSERT_BSONOBJ_EQ(BSON("lastErrorObject" << BSON("n" << 1 << "updatedExisting" << true)
+ << "value"
+ << BSON("a" << 1 << "b" << 1)),
+ result);
}
TEST_F(FindAndModifyRetryability, UpdateWithPostImageButOplogDoesNotExistShouldError) {
@@ -478,11 +485,11 @@ TEST_F(FindAndModifyRetryability, UpdateWithPostImageButOplogDoesNotExistShouldE
0,
repl::OpTypeEnum::kUpdate,
kNs,
- BSON("x" << 1 << "y" << 1),
- BSON("x" << 1));
+ BSON("_id" << 1 << "y" << 1),
+ BSON("_id" << 1));
updateOplog.setPostImageOpTime(imageOpTime);
- ASSERT_THROWS(parseOplogEntryForFindAndModify(opCtx(), request, updateOplog),
+ ASSERT_THROWS(constructFindAndModifyRetryResult(opCtx(), request, updateOplog),
AssertionException);
}
@@ -499,13 +506,10 @@ TEST_F(FindAndModifyRetryability, BasicRemove) {
repl::OpTime(), 0, repl::OpTypeEnum::kDelete, kNs, BSON("_id" << 20));
removeOplog.setPreImageOpTime(imageOpTime);
- auto result = parseOplogEntryForFindAndModify(opCtx(), request, removeOplog);
-
- auto lastError = result.getLastErrorObject();
- ASSERT_EQ(1, lastError.getN());
- ASSERT_FALSE(lastError.getUpdatedExisting());
-
- ASSERT_BSONOBJ_EQ(BSON("_id" << 20 << "a" << 1), result.getValue());
+ auto result = constructFindAndModifyRetryResult(opCtx(), request, removeOplog);
+ ASSERT_BSONOBJ_EQ(
+ BSON("lastErrorObject" << BSON("n" << 1) << "value" << BSON("_id" << 20 << "a" << 1)),
+ result);
}
TEST_F(FindAndModifyRetryability, NestedRemove) {
@@ -528,21 +532,19 @@ TEST_F(FindAndModifyRetryability, NestedRemove) {
innerOplog.toBSON());
removeOplog.setPreImageOpTime(imageOpTime);
- auto result = parseOplogEntryForFindAndModify(opCtx(), request, removeOplog);
-
- auto lastError = result.getLastErrorObject();
- ASSERT_EQ(1, lastError.getN());
- ASSERT_FALSE(lastError.getUpdatedExisting());
-
- ASSERT_BSONOBJ_EQ(BSON("_id" << 20 << "a" << 1), result.getValue());
+ auto result = constructFindAndModifyRetryResult(opCtx(), request, removeOplog);
+ ASSERT_BSONOBJ_EQ(
+ BSON("lastErrorObject" << BSON("n" << 1) << "value" << BSON("_id" << 20 << "a" << 1)),
+ result);
}
TEST_F(FindAndModifyRetryability, AttemptingToRetryUpsertWithRemoveErrors) {
auto request = FindAndModifyRequest::makeRemove(kNs, BSONObj());
- repl::OplogEntry insertOplog(repl::OpTime(), 0, repl::OpTypeEnum::kInsert, kNs, BSON("x" << 1));
+ repl::OplogEntry insertOplog(
+ repl::OpTime(), 0, repl::OpTypeEnum::kInsert, kNs, BSON("_id" << 1));
- ASSERT_THROWS(parseOplogEntryForFindAndModify(opCtx(), request, insertOplog),
+ ASSERT_THROWS(constructFindAndModifyRetryResult(opCtx(), request, insertOplog),
AssertionException);
}