summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Schultz <william.schultz@mongodb.com>2019-10-01 21:24:44 +0000
committerevergreen <evergreen@mongodb.com>2019-10-01 21:24:44 +0000
commitffc20cf1b310ebc22bab64f9627f558b78d58d57 (patch)
tree55c5b388b08f041b9b69117c58a4288ab219bde3
parentf27579ad4400d5e8ab7a79fc607c1e39438eb146 (diff)
downloadmongo-ffc20cf1b310ebc22bab64f9627f558b78d58d57.tar.gz
SERVER-42484 Ensure we are inside a WriteUnitOfWork when writing index keys during initial sync collection cloning
(cherry picked from commit c41af3e315a115b04a53706837d36a729d174fc3)
-rw-r--r--jstests/replsets/initial_sync_clone_multikey.js36
-rw-r--r--src/mongo/db/repl/collection_bulk_loader_impl.cpp17
2 files changed, 50 insertions, 3 deletions
diff --git a/jstests/replsets/initial_sync_clone_multikey.js b/jstests/replsets/initial_sync_clone_multikey.js
new file mode 100644
index 00000000000..0cf39825261
--- /dev/null
+++ b/jstests/replsets/initial_sync_clone_multikey.js
@@ -0,0 +1,36 @@
+/**
+ * Test initial sync cloning of a collection that contains a multikey index when hybrid index builds
+ * are disabled.
+ */
+(function() {
+"use strict";
+
+const replTest = new ReplSetTest({nodes: 1});
+replTest.startSet();
+replTest.initiate();
+
+const dbName = jsTest.name();
+const collName = "test";
+
+const primary = replTest.getPrimary();
+const primaryDB = primary.getDB(dbName);
+
+jsTestLog("Creating the collection and an index.");
+assert.commandWorked(primaryDB.createCollection(collName));
+assert.commandWorked(primaryDB[collName].createIndex({"x": 1}, {background: true}));
+
+// Make the index multikey.
+primaryDB[collName].insert({x: [1, 2]});
+
+jsTestLog("Adding a secondary node to do the initial sync.");
+replTest.add({setParameter: "enableHybridIndexBuilds=false"});
+
+jsTestLog("Re-initiating replica set with the new secondary.");
+replTest.reInitiate();
+
+// Wait until initial sync completes.
+jsTestLog("Waiting until initial sync completes.");
+replTest.awaitSecondaryNodes();
+replTest.awaitReplication();
+replTest.stopSet();
+})(); \ No newline at end of file
diff --git a/src/mongo/db/repl/collection_bulk_loader_impl.cpp b/src/mongo/db/repl/collection_bulk_loader_impl.cpp
index 68f760d284a..56322162fe1 100644
--- a/src/mongo/db/repl/collection_bulk_loader_impl.cpp
+++ b/src/mongo/db/repl/collection_bulk_loader_impl.cpp
@@ -154,9 +154,20 @@ Status CollectionBulkLoaderImpl::insertDocuments(const std::vector<BSONObj>::con
}
if (loc) {
- // Inserts index entries into the external sorter. This will not update
- // pre-existing indexes.
- status = _addDocumentToIndexBlocks(doc, loc.get());
+ // Inserts index entries into the external sorter. This will not update pre-existing
+ // indexes. Wrap this in a WUOW since the index entry insertion may modify the
+ // durable record store which can throw a write conflict exception.
+ status =
+ writeConflictRetry(_opCtx.get(), "_addDocumentToIndexBlocks", _nss.ns(), [&] {
+ WriteUnitOfWork wunit(_opCtx.get());
+ status = _addDocumentToIndexBlocks(doc, loc.get());
+ // We only need to commit the unit of work if the index insertion was
+ // successful.
+ if (status.isOK()) {
+ wunit.commit();
+ }
+ return status;
+ });
}
if (!status.isOK()) {