summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenety Goh <benety@mongodb.com>2017-03-23 21:30:24 -0400
committerBenety Goh <benety@mongodb.com>2017-03-31 16:05:32 -0400
commit5d8395f20499b39ee3889f6e7dac87d6e7ae6db0 (patch)
treeb74a6346889ea1373f4aa40333b04de46bbcaadb /src
parentaeae03f23b14e29d3c07a65762d57267d6bae0b9 (diff)
downloadmongo-5d8395f20499b39ee3889f6e7dac87d6e7ae6db0.tar.gz
SERVER-27834 applyOperation_inlock() fails index creation if collection is missing
(cherry picked from commit f54e89fa124ef679e25ca37b3bcf8e02572f38fd)
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/repl/oplog.cpp7
-rw-r--r--src/mongo/db/repl/sync_tail_test.cpp201
2 files changed, 132 insertions, 76 deletions
diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp
index 24700262de6..99567642a17 100644
--- a/src/mongo/db/repl/oplog.cpp
+++ b/src/mongo/db/repl/oplog.cpp
@@ -739,6 +739,13 @@ Status applyOperation_inlock(OperationContext* txn,
<< op,
nsToDatabaseSubstring(ns) == indexNss.db());
+ // Check if collection exists.
+ auto indexCollection = db->getCollection(indexNss);
+ uassert(ErrorCodes::NamespaceNotFound,
+ str::stream() << "Failed to create index due to missing collection: "
+ << op.toString(),
+ indexCollection);
+
opCounters->gotInsert();
if (!indexSpec["v"]) {
diff --git a/src/mongo/db/repl/sync_tail_test.cpp b/src/mongo/db/repl/sync_tail_test.cpp
index 90fc9ee21b6..d73a7593829 100644
--- a/src/mongo/db/repl/sync_tail_test.cpp
+++ b/src/mongo/db/repl/sync_tail_test.cpp
@@ -69,7 +69,7 @@ using namespace mongo::repl;
class SyncTailTest : public ServiceContextMongoDTest {
protected:
void _testSyncApplyInsertDocument(LockMode expectedMode);
- ServiceContext::UniqueOperationContext _txn;
+ ServiceContext::UniqueOperationContext _opCtx;
unsigned int _opsApplied;
SyncTail::ApplyOperationInLockFn _applyOp;
SyncTail::ApplyCommandInLockFn _applyCmd;
@@ -122,7 +122,7 @@ void SyncTailTest::setUp() {
const std::vector<BSONObj>&) { return Status::OK(); };
StorageInterface::set(serviceContext, std::move(storageInterface));
- _txn = cc().makeOperationContext();
+ _opCtx = cc().makeOperationContext();
_opsApplied = 0;
_applyOp = [](OperationContext* txn,
Database* db,
@@ -134,7 +134,7 @@ void SyncTailTest::setUp() {
}
void SyncTailTest::tearDown() {
- _txn.reset();
+ _opCtx.reset();
ServiceContextMongoDTest::tearDown();
_storageInterface = nullptr;
}
@@ -250,7 +250,23 @@ OplogEntry makeUpdateDocumentOplogEntry(OpTime opTime,
return OplogEntry(bob.obj());
}
-Status failedApplyCommand(OperationContext* txn, const BSONObj& theOperation, bool) {
+/**
+ * Creates an index creation entry with given optime and namespace.
+ */
+OplogEntry makeCreateIndexOplogEntry(OpTime opTime,
+ const NamespaceString& nss,
+ const std::string& indexName,
+ const BSONObj& keyPattern) {
+ BSONObjBuilder indexInfoBob;
+ indexInfoBob.append("v", 2);
+ indexInfoBob.append("key", keyPattern);
+ indexInfoBob.append("name", indexName);
+ indexInfoBob.append("ns", nss.ns());
+ return makeInsertDocumentOplogEntry(
+ opTime, NamespaceString(nss.getSystemIndexesCollection()), indexInfoBob.obj());
+}
+
+Status failedApplyCommand(OperationContext* opCtx, const BSONObj& theOperation, bool) {
FAIL("applyCommand unexpectedly invoked.");
return Status::OK();
}
@@ -258,12 +274,12 @@ Status failedApplyCommand(OperationContext* txn, const BSONObj& theOperation, bo
TEST_F(SyncTailTest, SyncApplyNoNamespaceBadOp) {
const BSONObj op = BSON("op"
<< "x");
- ASSERT_OK(SyncTail::syncApply(_txn.get(), op, false, _applyOp, _applyCmd, _incOps));
+ ASSERT_OK(SyncTail::syncApply(_opCtx.get(), op, false, _applyOp, _applyCmd, _incOps));
ASSERT_EQUALS(0U, _opsApplied);
}
TEST_F(SyncTailTest, SyncApplyNoNamespaceNoOp) {
- ASSERT_OK(SyncTail::syncApply(_txn.get(),
+ ASSERT_OK(SyncTail::syncApply(_opCtx.get(),
BSON("op"
<< "n"),
false));
@@ -275,8 +291,9 @@ TEST_F(SyncTailTest, SyncApplyBadOp) {
<< "x"
<< "ns"
<< "test.t");
- ASSERT_EQUALS(ErrorCodes::BadValue,
- SyncTail::syncApply(_txn.get(), op, false, _applyOp, _applyCmd, _incOps).code());
+ ASSERT_EQUALS(
+ ErrorCodes::BadValue,
+ SyncTail::syncApply(_opCtx.get(), op, false, _applyOp, _applyCmd, _incOps).code());
ASSERT_EQUALS(0U, _opsApplied);
}
@@ -301,9 +318,9 @@ TEST_F(SyncTailTest, SyncApplyNoOp) {
ASSERT_FALSE(inSteadyStateReplication);
return Status::OK();
};
- ASSERT_TRUE(_txn->writesAreReplicated());
- ASSERT_FALSE(documentValidationDisabled(_txn.get()));
- ASSERT_OK(SyncTail::syncApply(_txn.get(), op, false, applyOp, failedApplyCommand, _incOps));
+ ASSERT_TRUE(_opCtx->writesAreReplicated());
+ ASSERT_FALSE(documentValidationDisabled(_opCtx.get()));
+ ASSERT_OK(SyncTail::syncApply(_opCtx.get(), op, false, applyOp, failedApplyCommand, _incOps));
ASSERT_TRUE(applyOpCalled);
}
@@ -324,7 +341,7 @@ TEST_F(SyncTailTest, SyncApplyNoOpApplyOpThrowsException) {
}
return Status::OK();
};
- ASSERT_OK(SyncTail::syncApply(_txn.get(), op, false, applyOp, failedApplyCommand, _incOps));
+ ASSERT_OK(SyncTail::syncApply(_opCtx.get(), op, false, applyOp, failedApplyCommand, _incOps));
ASSERT_EQUALS(5, applyOpCalled);
}
@@ -350,9 +367,9 @@ void SyncTailTest::_testSyncApplyInsertDocument(LockMode expectedMode) {
ASSERT_TRUE(inSteadyStateReplication);
return Status::OK();
};
- ASSERT_TRUE(_txn->writesAreReplicated());
- ASSERT_FALSE(documentValidationDisabled(_txn.get()));
- ASSERT_OK(SyncTail::syncApply(_txn.get(), op, true, applyOp, failedApplyCommand, _incOps));
+ ASSERT_TRUE(_opCtx->writesAreReplicated());
+ ASSERT_FALSE(documentValidationDisabled(_opCtx.get()));
+ ASSERT_OK(SyncTail::syncApply(_opCtx.get(), op, true, applyOp, failedApplyCommand, _incOps));
ASSERT_TRUE(applyOpCalled);
}
@@ -362,9 +379,9 @@ TEST_F(SyncTailTest, SyncApplyInsertDocumentDatabaseMissing) {
TEST_F(SyncTailTest, SyncApplyInsertDocumentCollectionMissing) {
{
- Lock::GlobalWrite globalLock(_txn->lockState());
+ Lock::GlobalWrite globalLock(_opCtx->lockState());
bool justCreated = false;
- Database* db = dbHolder().openDb(_txn.get(), "test", &justCreated);
+ Database* db = dbHolder().openDb(_opCtx.get(), "test", &justCreated);
ASSERT_TRUE(db);
ASSERT_TRUE(justCreated);
}
@@ -373,12 +390,12 @@ TEST_F(SyncTailTest, SyncApplyInsertDocumentCollectionMissing) {
TEST_F(SyncTailTest, SyncApplyInsertDocumentCollectionExists) {
{
- Lock::GlobalWrite globalLock(_txn->lockState());
+ Lock::GlobalWrite globalLock(_opCtx->lockState());
bool justCreated = false;
- Database* db = dbHolder().openDb(_txn.get(), "test", &justCreated);
+ Database* db = dbHolder().openDb(_opCtx.get(), "test", &justCreated);
ASSERT_TRUE(db);
ASSERT_TRUE(justCreated);
- Collection* collection = db->createCollection(_txn.get(), "test.t");
+ Collection* collection = db->createCollection(_opCtx.get(), "test.t");
ASSERT_TRUE(collection);
}
_testSyncApplyInsertDocument(MODE_IX);
@@ -405,9 +422,9 @@ TEST_F(SyncTailTest, SyncApplyIndexBuild) {
ASSERT_FALSE(inSteadyStateReplication);
return Status::OK();
};
- ASSERT_TRUE(_txn->writesAreReplicated());
- ASSERT_FALSE(documentValidationDisabled(_txn.get()));
- ASSERT_OK(SyncTail::syncApply(_txn.get(), op, false, applyOp, failedApplyCommand, _incOps));
+ ASSERT_TRUE(_opCtx->writesAreReplicated());
+ ASSERT_FALSE(documentValidationDisabled(_opCtx.get()));
+ ASSERT_OK(SyncTail::syncApply(_opCtx.get(), op, false, applyOp, failedApplyCommand, _incOps));
ASSERT_TRUE(applyOpCalled);
}
@@ -435,9 +452,9 @@ TEST_F(SyncTailTest, SyncApplyCommand) {
ASSERT_BSONOBJ_EQ(op, theOperation);
return Status::OK();
};
- ASSERT_TRUE(_txn->writesAreReplicated());
- ASSERT_FALSE(documentValidationDisabled(_txn.get()));
- ASSERT_OK(SyncTail::syncApply(_txn.get(), op, false, applyOp, applyCmd, _incOps));
+ ASSERT_TRUE(_opCtx->writesAreReplicated());
+ ASSERT_FALSE(documentValidationDisabled(_opCtx.get()));
+ ASSERT_OK(SyncTail::syncApply(_opCtx.get(), op, false, applyOp, applyCmd, _incOps));
ASSERT_TRUE(applyCmdCalled);
ASSERT_EQUALS(1U, _opsApplied);
}
@@ -464,7 +481,7 @@ TEST_F(SyncTailTest, SyncApplyCommandThrowsException) {
}
return Status::OK();
};
- ASSERT_OK(SyncTail::syncApply(_txn.get(), op, false, applyOp, applyCmd, _incOps));
+ ASSERT_OK(SyncTail::syncApply(_opCtx.get(), op, false, applyOp, applyCmd, _incOps));
ASSERT_EQUALS(5, applyCmdCalled);
ASSERT_EQUALS(1U, _opsApplied);
}
@@ -479,14 +496,14 @@ TEST_F(SyncTailTest, MultiApplyReturnsBadValueOnNullOperationContext) {
TEST_F(SyncTailTest, MultiApplyReturnsBadValueOnNullWriterPool) {
auto op = makeCreateCollectionOplogEntry({Timestamp(Seconds(1), 0), 1LL});
- auto status = multiApply(_txn.get(), nullptr, {op}, noopApplyOperationFn).getStatus();
+ auto status = multiApply(_opCtx.get(), nullptr, {op}, noopApplyOperationFn).getStatus();
ASSERT_EQUALS(ErrorCodes::BadValue, status);
ASSERT_STRING_CONTAINS(status.reason(), "invalid worker pool");
}
TEST_F(SyncTailTest, MultiApplyReturnsEmptyArrayOperationWhenNoOperationsAreGiven) {
auto writerPool = SyncTail::makeWriterPool();
- auto status = multiApply(_txn.get(), writerPool.get(), {}, noopApplyOperationFn).getStatus();
+ auto status = multiApply(_opCtx.get(), writerPool.get(), {}, noopApplyOperationFn).getStatus();
ASSERT_EQUALS(ErrorCodes::EmptyArrayOperation, status);
ASSERT_STRING_CONTAINS(status.reason(), "no operations provided to multiApply");
}
@@ -495,7 +512,8 @@ TEST_F(SyncTailTest, MultiApplyReturnsBadValueOnNullApplyOperation) {
auto writerPool = SyncTail::makeWriterPool();
MultiApplier::ApplyOperationFn nullApplyOperationFn;
auto op = makeCreateCollectionOplogEntry({Timestamp(Seconds(1), 0), 1LL});
- auto status = multiApply(_txn.get(), writerPool.get(), {op}, nullApplyOperationFn).getStatus();
+ auto status =
+ multiApply(_opCtx.get(), writerPool.get(), {op}, nullApplyOperationFn).getStatus();
ASSERT_EQUALS(ErrorCodes::BadValue, status);
ASSERT_STRING_CONTAINS(status.reason(), "invalid apply operation function");
}
@@ -532,14 +550,14 @@ TEST_F(
SyncTailTest,
MultiApplyDoesNotSetOplogEntryIsForCappedCollectionWhenProcessingNonCappedCollectionInsertOperation) {
NamespaceString nss("local." + _agent.getSuiteName() + "_" + _agent.getTestName());
- ASSERT_FALSE(_testOplogEntryIsForCappedCollection(_txn.get(), nss, CollectionOptions()));
+ ASSERT_FALSE(_testOplogEntryIsForCappedCollection(_opCtx.get(), nss, CollectionOptions()));
}
TEST_F(SyncTailTest,
MultiApplySetsOplogEntryIsForCappedCollectionWhenProcessingCappedCollectionInsertOperation) {
NamespaceString nss("local." + _agent.getSuiteName() + "_" + _agent.getTestName());
ASSERT_TRUE(
- _testOplogEntryIsForCappedCollection(_txn.get(), nss, createOplogCollectionOptions()));
+ _testOplogEntryIsForCappedCollection(_opCtx.get(), nss, createOplogCollectionOptions()));
}
TEST_F(SyncTailTest, MultiApplyAssignsOperationsToWriterThreadsBasedOnNamespaceHash) {
@@ -577,7 +595,7 @@ TEST_F(SyncTailTest, MultiApplyAssignsOperationsToWriterThreadsBasedOnNamespaceH
};
auto lastOpTime =
- unittest::assertGet(multiApply(_txn.get(), &writerPool, {op1, op2}, applyOperationFn));
+ unittest::assertGet(multiApply(_opCtx.get(), &writerPool, {op1, op2}, applyOperationFn));
ASSERT_EQUALS(op2.getOpTime(), lastOpTime);
// Each writer thread should be given exactly one operation to apply.
@@ -606,13 +624,13 @@ TEST_F(SyncTailTest, MultiApplyAssignsOperationsToWriterThreadsBasedOnNamespaceH
TEST_F(SyncTailTest, MultiSyncApplyUsesSyncApplyToApplyOperation) {
NamespaceString nss("local." + _agent.getSuiteName() + "_" + _agent.getTestName());
auto op = makeCreateCollectionOplogEntry({Timestamp(Seconds(1), 0), 1LL}, nss);
- _txn.reset();
+ _opCtx.reset();
MultiApplier::OperationPtrs ops = {&op};
multiSyncApply(&ops, nullptr);
// Collection should be created after SyncTail::syncApply() processes operation.
- _txn = cc().makeOperationContext();
- ASSERT_TRUE(AutoGetCollectionForRead(_txn.get(), nss).getCollection());
+ _opCtx = cc().makeOperationContext();
+ ASSERT_TRUE(AutoGetCollectionForRead(_opCtx.get(), nss).getCollection());
}
TEST_F(SyncTailTest, MultiSyncApplyDisablesDocumentValidationWhileApplyingOperations) {
@@ -627,7 +645,7 @@ TEST_F(SyncTailTest, MultiSyncApplyDisablesDocumentValidationWhileApplyingOperat
auto op = makeUpdateDocumentOplogEntry(
{Timestamp(Seconds(1), 0), 1LL}, nss, BSON("_id" << 0), BSON("_id" << 0 << "x" << 2));
MultiApplier::OperationPtrs ops = {&op};
- ASSERT_OK(multiSyncApply_noAbort(_txn.get(), &ops, syncApply));
+ ASSERT_OK(multiSyncApply_noAbort(_opCtx.get(), &ops, syncApply));
}
TEST_F(SyncTailTest, MultiSyncApplyPassesThroughSyncApplyErrorAfterFailingToApplyOperation) {
@@ -640,7 +658,8 @@ TEST_F(SyncTailTest, MultiSyncApplyPassesThroughSyncApplyErrorAfterFailingToAppl
return {ErrorCodes::OperationFailed, ""};
};
MultiApplier::OperationPtrs ops = {&op};
- ASSERT_EQUALS(ErrorCodes::OperationFailed, multiSyncApply_noAbort(_txn.get(), &ops, syncApply));
+ ASSERT_EQUALS(ErrorCodes::OperationFailed,
+ multiSyncApply_noAbort(_opCtx.get(), &ops, syncApply));
}
TEST_F(SyncTailTest, MultiSyncApplyPassesThroughSyncApplyException) {
@@ -654,7 +673,8 @@ TEST_F(SyncTailTest, MultiSyncApplyPassesThroughSyncApplyException) {
MONGO_UNREACHABLE;
};
MultiApplier::OperationPtrs ops = {&op};
- ASSERT_EQUALS(ErrorCodes::OperationFailed, multiSyncApply_noAbort(_txn.get(), &ops, syncApply));
+ ASSERT_EQUALS(ErrorCodes::OperationFailed,
+ multiSyncApply_noAbort(_opCtx.get(), &ops, syncApply));
}
TEST_F(SyncTailTest, MultiSyncApplySortsOperationsStablyByNamespaceBeforeApplying) {
@@ -677,7 +697,7 @@ TEST_F(SyncTailTest, MultiSyncApplySortsOperationsStablyByNamespaceBeforeApplyin
return Status::OK();
};
MultiApplier::OperationPtrs ops = {&op4, &op1, &op3, &op2};
- ASSERT_OK(multiSyncApply_noAbort(_txn.get(), &ops, syncApply));
+ ASSERT_OK(multiSyncApply_noAbort(_opCtx.get(), &ops, syncApply));
ASSERT_EQUALS(4U, operationsApplied.size());
ASSERT_EQUALS(op1, operationsApplied[0]);
ASSERT_EQUALS(op2, operationsApplied[1]);
@@ -707,7 +727,7 @@ TEST_F(SyncTailTest, MultiSyncApplyGroupsInsertOperationByNamespaceBeforeApplyin
MultiApplier::OperationPtrs ops = {
&createOp1, &createOp2, &insertOp1a, &insertOp2a, &insertOp1b, &insertOp2b};
- ASSERT_OK(multiSyncApply_noAbort(_txn.get(), &ops, syncApply));
+ ASSERT_OK(multiSyncApply_noAbort(_opCtx.get(), &ops, syncApply));
ASSERT_EQUALS(4U, operationsApplied.size());
ASSERT_EQUALS(createOp1, operationsApplied[0]);
@@ -761,7 +781,7 @@ TEST_F(SyncTailTest, MultiSyncApplyUsesLimitWhenGroupingInsertOperation) {
for (auto&& op : operationsToApply) {
ops.push_back(&op);
}
- ASSERT_OK(multiSyncApply_noAbort(_txn.get(), &ops, syncApply));
+ ASSERT_OK(multiSyncApply_noAbort(_opCtx.get(), &ops, syncApply));
// multiSyncApply should combine operations as follows:
// {create}, {grouped_insert}, {insert_(limit+1)}
@@ -820,7 +840,7 @@ TEST_F(SyncTailTest, MultiSyncApplyFallsBackOnApplyingInsertsIndividuallyWhenGro
for (auto&& op : operationsToApply) {
ops.push_back(&op);
}
- ASSERT_OK(multiSyncApply_noAbort(_txn.get(), &ops, syncApply));
+ ASSERT_OK(multiSyncApply_noAbort(_opCtx.get(), &ops, syncApply));
// On failing to apply the grouped insert operation, multiSyncApply should apply the operations
// as given in "operationsToApply":
@@ -845,7 +865,7 @@ TEST_F(SyncTailTest, MultiInitialSyncApplyDisablesDocumentValidationWhileApplyin
{Timestamp(Seconds(1), 0), 1LL}, nss, BSON("_id" << 0), BSON("_id" << 0 << "x" << 2));
MultiApplier::OperationPtrs ops = {&op};
AtomicUInt32 fetchCount(0);
- ASSERT_OK(multiInitialSyncApply_noAbort(_txn.get(), &ops, &syncTail, &fetchCount));
+ ASSERT_OK(multiInitialSyncApply_noAbort(_opCtx.get(), &ops, &syncTail, &fetchCount));
ASSERT_EQUALS(fetchCount.load(), 1U);
}
@@ -858,11 +878,11 @@ TEST_F(SyncTailTest,
{Timestamp(Seconds(1), 0), 1LL}, nss, BSON("_id" << 0), BSON("_id" << 0 << "x" << 2));
MultiApplier::OperationPtrs ops = {&op};
AtomicUInt32 fetchCount(0);
- ASSERT_OK(multiInitialSyncApply_noAbort(_txn.get(), &ops, &syncTail, &fetchCount));
+ ASSERT_OK(multiInitialSyncApply_noAbort(_opCtx.get(), &ops, &syncTail, &fetchCount));
// Since the missing document is not found on the sync source, the collection referenced by
// the failed operation should not be automatically created.
- ASSERT_FALSE(AutoGetCollectionForRead(_txn.get(), nss).getCollection());
+ ASSERT_FALSE(AutoGetCollectionForRead(_opCtx.get(), nss).getCollection());
ASSERT_EQUALS(fetchCount.load(), 1U);
}
@@ -880,16 +900,44 @@ TEST_F(SyncTailTest, MultiInitialSyncApplySkipsDocumentOnNamespaceNotFound) {
auto op3 = makeInsertDocumentOplogEntry({Timestamp(Seconds(4), 0), 1LL}, nss, doc3);
MultiApplier::OperationPtrs ops = {&op0, &op1, &op2, &op3};
AtomicUInt32 fetchCount(0);
- ASSERT_OK(multiInitialSyncApply_noAbort(_txn.get(), &ops, &syncTail, &fetchCount));
+ ASSERT_OK(multiInitialSyncApply_noAbort(_opCtx.get(), &ops, &syncTail, &fetchCount));
ASSERT_EQUALS(fetchCount.load(), 0U);
- OplogInterfaceLocal collectionReader(_txn.get(), nss.ns());
+ OplogInterfaceLocal collectionReader(_opCtx.get(), nss.ns());
auto iter = collectionReader.makeIterator();
ASSERT_BSONOBJ_EQ(doc3, unittest::assertGet(iter->next()).first);
ASSERT_BSONOBJ_EQ(doc1, unittest::assertGet(iter->next()).first);
ASSERT_EQUALS(ErrorCodes::CollectionIsEmpty, iter->next().getStatus());
}
+TEST_F(SyncTailTest, MultiInitialSyncApplySkipsIndexCreationOnNamespaceNotFound) {
+ BSONObj emptyDoc;
+ SyncTailWithLocalDocumentFetcher syncTail(emptyDoc);
+ NamespaceString nss("local." + _agent.getSuiteName() + "_" + _agent.getTestName());
+ NamespaceString badNss("local." + _agent.getSuiteName() + "_" + _agent.getTestName() + "bad");
+ auto doc1 = BSON("_id" << 1);
+ auto keyPattern = BSON("a" << 1);
+ auto doc3 = BSON("_id" << 3);
+ auto op0 = makeCreateCollectionOplogEntry({Timestamp(Seconds(1), 0), 1LL}, nss);
+ auto op1 = makeInsertDocumentOplogEntry({Timestamp(Seconds(2), 0), 1LL}, nss, doc1);
+ auto op2 =
+ makeCreateIndexOplogEntry({Timestamp(Seconds(3), 0), 1LL}, badNss, "a_1", keyPattern);
+ auto op3 = makeInsertDocumentOplogEntry({Timestamp(Seconds(4), 0), 1LL}, nss, doc3);
+ MultiApplier::OperationPtrs ops = {&op0, &op1, &op2, &op3};
+ AtomicUInt32 fetchCount(0);
+ ASSERT_OK(multiInitialSyncApply_noAbort(_opCtx.get(), &ops, &syncTail, &fetchCount));
+ ASSERT_EQUALS(fetchCount.load(), 0U);
+
+ OplogInterfaceLocal collectionReader(_opCtx.get(), nss.ns());
+ auto iter = collectionReader.makeIterator();
+ ASSERT_BSONOBJ_EQ(doc3, unittest::assertGet(iter->next()).first);
+ ASSERT_BSONOBJ_EQ(doc1, unittest::assertGet(iter->next()).first);
+ ASSERT_EQUALS(ErrorCodes::CollectionIsEmpty, iter->next().getStatus());
+
+ // 'badNss' collection should not be implicitly created while attempting to create an index.
+ ASSERT_FALSE(AutoGetCollectionForRead(_opCtx.get(), badNss).getCollection());
+}
+
TEST_F(SyncTailTest, MultiInitialSyncApplyRetriesFailedUpdateIfDocumentIsAvailableFromSyncSource) {
SyncTailWithLocalDocumentFetcher syncTail(BSON("_id" << 0 << "x" << 1));
NamespaceString nss("local." + _agent.getSuiteName() + "_" + _agent.getTestName());
@@ -898,13 +946,13 @@ TEST_F(SyncTailTest, MultiInitialSyncApplyRetriesFailedUpdateIfDocumentIsAvailab
{Timestamp(Seconds(1), 0), 1LL}, nss, BSON("_id" << 0), updatedDocument);
MultiApplier::OperationPtrs ops = {&op};
AtomicUInt32 fetchCount(0);
- ASSERT_OK(multiInitialSyncApply_noAbort(_txn.get(), &ops, &syncTail, &fetchCount));
+ ASSERT_OK(multiInitialSyncApply_noAbort(_opCtx.get(), &ops, &syncTail, &fetchCount));
ASSERT_EQUALS(fetchCount.load(), 1U);
// The collection referenced by "ns" in the failed operation is automatically created to hold
// the missing document fetched from the sync source. We verify the contents of the collection
// with the OplogInterfaceLocal class.
- OplogInterfaceLocal collectionReader(_txn.get(), nss.ns());
+ OplogInterfaceLocal collectionReader(_opCtx.get(), nss.ns());
auto iter = collectionReader.makeIterator();
ASSERT_BSONOBJ_EQ(updatedDocument, unittest::assertGet(iter->next()).first);
ASSERT_EQUALS(ErrorCodes::CollectionIsEmpty, iter->next().getStatus());
@@ -920,7 +968,7 @@ TEST_F(SyncTailTest, MultiInitialSyncApplyPassesThroughSyncApplyErrorAfterFailin
MultiApplier::OperationPtrs ops = {&op};
AtomicUInt32 fetchCount(0);
ASSERT_EQUALS(ErrorCodes::BadValue,
- multiInitialSyncApply_noAbort(_txn.get(), &ops, &syncTail, &fetchCount));
+ multiInitialSyncApply_noAbort(_opCtx.get(), &ops, &syncTail, &fetchCount));
ASSERT_EQUALS(fetchCount.load(), 1U);
}
@@ -929,12 +977,13 @@ TEST_F(SyncTailTest, MultiInitialSyncApplyPassesThroughShouldSyncTailRetryError)
NamespaceString nss("local." + _agent.getSuiteName() + "_" + _agent.getTestName());
auto op = makeUpdateDocumentOplogEntry(
{Timestamp(Seconds(1), 0), 1LL}, nss, BSON("_id" << 0), BSON("_id" << 0 << "x" << 2));
- ASSERT_THROWS_CODE(
- syncTail.shouldRetry(_txn.get(), op.raw), mongo::UserException, ErrorCodes::FailedToParse);
+ ASSERT_THROWS_CODE(syncTail.shouldRetry(_opCtx.get(), op.raw),
+ mongo::UserException,
+ ErrorCodes::FailedToParse);
MultiApplier::OperationPtrs ops = {&op};
AtomicUInt32 fetchCount(0);
ASSERT_EQUALS(ErrorCodes::FailedToParse,
- multiInitialSyncApply_noAbort(_txn.get(), &ops, &syncTail, &fetchCount));
+ multiInitialSyncApply_noAbort(_opCtx.get(), &ops, &syncTail, &fetchCount));
ASSERT_EQUALS(fetchCount.load(), 1U);
}
@@ -970,7 +1019,7 @@ Status IdempotencyTest::runOps(std::initializer_list<OplogEntry> ops) {
opsPtrs.push_back(&op);
}
AtomicUInt32 fetchCount(0);
- return multiInitialSyncApply_noAbort(_txn.get(), &opsPtrs, &syncTail, &fetchCount);
+ return multiInitialSyncApply_noAbort(_opCtx.get(), &opsPtrs, &syncTail, &fetchCount);
}
OplogEntry IdempotencyTest::createCollection() {
@@ -1002,21 +1051,21 @@ OplogEntry IdempotencyTest::dropIndex(const std::string& indexName) {
}
std::string IdempotencyTest::validate() {
- auto collection = AutoGetCollectionForRead(_txn.get(), nss).getCollection();
+ auto collection = AutoGetCollectionForRead(_opCtx.get(), nss).getCollection();
if (!collection) {
return "CollectionNotFound";
}
ValidateResults validateResults;
BSONObjBuilder bob;
- Lock::DBLock lk(_txn->lockState(), nss.db(), MODE_IS);
- Lock::CollectionLock lock(_txn->lockState(), nss.ns(), MODE_IS);
- ASSERT_OK(collection->validate(_txn.get(), kValidateFull, &validateResults, &bob));
+ Lock::DBLock lk(_opCtx->lockState(), nss.db(), MODE_IS);
+ Lock::CollectionLock lock(_opCtx->lockState(), nss.ns(), MODE_IS);
+ ASSERT_OK(collection->validate(_opCtx.get(), kValidateFull, &validateResults, &bob));
ASSERT_TRUE(validateResults.valid);
- IndexDescriptor* desc = collection->getIndexCatalog()->findIdIndex(_txn.get());
+ IndexDescriptor* desc = collection->getIndexCatalog()->findIdIndex(_opCtx.get());
ASSERT_TRUE(desc);
- auto exec = InternalPlanner::indexScan(_txn.get(),
+ auto exec = InternalPlanner::indexScan(_opCtx.get(),
collection,
desc,
BSONObj(),
@@ -1041,7 +1090,7 @@ std::string IdempotencyTest::validate() {
}
TEST_F(IdempotencyTest, Geo2dsphereIndexFailedOnUpdate) {
- ReplicationCoordinator::get(_txn.get())->setFollowerMode(MemberState::RS_RECOVERING);
+ ReplicationCoordinator::get(_opCtx.get())->setFollowerMode(MemberState::RS_RECOVERING);
ASSERT_OK(runOp(createCollection()));
auto insertOp = insert(fromjson("{_id: 1, loc: 'hi'}"));
auto updateOp = update(1, fromjson("{$set: {loc: [1, 2]}}"));
@@ -1054,13 +1103,13 @@ TEST_F(IdempotencyTest, Geo2dsphereIndexFailedOnUpdate) {
ASSERT_OK(runOps(ops));
ASSERT_EQUALS(hash, validate());
- ReplicationCoordinator::get(_txn.get())->setFollowerMode(MemberState::RS_PRIMARY);
+ ReplicationCoordinator::get(_opCtx.get())->setFollowerMode(MemberState::RS_PRIMARY);
auto status = runOps(ops);
ASSERT_EQ(status.code(), 16755);
}
TEST_F(IdempotencyTest, Geo2dsphereIndexFailedOnIndexing) {
- ReplicationCoordinator::get(_txn.get())->setFollowerMode(MemberState::RS_RECOVERING);
+ ReplicationCoordinator::get(_opCtx.get())->setFollowerMode(MemberState::RS_RECOVERING);
ASSERT_OK(runOp(createCollection()));
auto indexOp = buildIndex(fromjson("{loc: '2dsphere'}"), BSON("2dsphereIndexVersion" << 3));
auto dropIndexOp = dropIndex("loc_index");
@@ -1073,13 +1122,13 @@ TEST_F(IdempotencyTest, Geo2dsphereIndexFailedOnIndexing) {
ASSERT_OK(runOps(ops));
ASSERT_EQUALS(hash, validate());
- ReplicationCoordinator::get(_txn.get())->setFollowerMode(MemberState::RS_PRIMARY);
+ ReplicationCoordinator::get(_opCtx.get())->setFollowerMode(MemberState::RS_PRIMARY);
auto status = runOps(ops);
ASSERT_EQ(status.code(), 16755);
}
TEST_F(IdempotencyTest, Geo2dIndex) {
- ReplicationCoordinator::get(_txn.get())->setFollowerMode(MemberState::RS_RECOVERING);
+ ReplicationCoordinator::get(_opCtx.get())->setFollowerMode(MemberState::RS_RECOVERING);
ASSERT_OK(runOp(createCollection()));
auto insertOp = insert(fromjson("{_id: 1, loc: [1]}"));
auto updateOp = update(1, fromjson("{$set: {loc: [1, 2]}}"));
@@ -1092,13 +1141,13 @@ TEST_F(IdempotencyTest, Geo2dIndex) {
ASSERT_OK(runOps(ops));
ASSERT_EQUALS(hash, validate());
- ReplicationCoordinator::get(_txn.get())->setFollowerMode(MemberState::RS_PRIMARY);
+ ReplicationCoordinator::get(_opCtx.get())->setFollowerMode(MemberState::RS_PRIMARY);
auto status = runOps(ops);
ASSERT_EQ(status.code(), 13068);
}
TEST_F(IdempotencyTest, UniqueKeyIndex) {
- ReplicationCoordinator::get(_txn.get())->setFollowerMode(MemberState::RS_RECOVERING);
+ ReplicationCoordinator::get(_opCtx.get())->setFollowerMode(MemberState::RS_RECOVERING);
ASSERT_OK(runOp(createCollection()));
auto insertOp = insert(fromjson("{_id: 1, x: 5}"));
auto updateOp = update(1, fromjson("{$set: {x: 6}}"));
@@ -1112,13 +1161,13 @@ TEST_F(IdempotencyTest, UniqueKeyIndex) {
ASSERT_OK(runOps(ops));
ASSERT_EQUALS(hash, validate());
- ReplicationCoordinator::get(_txn.get())->setFollowerMode(MemberState::RS_PRIMARY);
+ ReplicationCoordinator::get(_opCtx.get())->setFollowerMode(MemberState::RS_PRIMARY);
auto status = runOps(ops);
ASSERT_EQ(status.code(), ErrorCodes::DuplicateKey);
}
TEST_F(IdempotencyTest, ParallelArrayError) {
- ReplicationCoordinator::get(_txn.get())->setFollowerMode(MemberState::RS_RECOVERING);
+ ReplicationCoordinator::get(_opCtx.get())->setFollowerMode(MemberState::RS_RECOVERING);
ASSERT_OK(runOp(createCollection()));
ASSERT_OK(runOp(insert(fromjson("{_id: 1}"))));
@@ -1135,13 +1184,13 @@ TEST_F(IdempotencyTest, ParallelArrayError) {
ASSERT_OK(runOps(ops));
ASSERT_EQUALS(hash, validate());
- ReplicationCoordinator::get(_txn.get())->setFollowerMode(MemberState::RS_PRIMARY);
+ ReplicationCoordinator::get(_opCtx.get())->setFollowerMode(MemberState::RS_PRIMARY);
auto status = runOps(ops);
ASSERT_EQ(status.code(), ErrorCodes::CannotIndexParallelArrays);
}
TEST_F(IdempotencyTest, IndexKeyTooLongError) {
- ReplicationCoordinator::get(_txn.get())->setFollowerMode(MemberState::RS_RECOVERING);
+ ReplicationCoordinator::get(_opCtx.get())->setFollowerMode(MemberState::RS_RECOVERING);
ASSERT_OK(runOp(createCollection()));
ASSERT_OK(runOp(insert(fromjson("{_id: 1}"))));
@@ -1161,13 +1210,13 @@ TEST_F(IdempotencyTest, IndexKeyTooLongError) {
ASSERT_OK(runOps(ops));
ASSERT_EQUALS(hash, validate());
- ReplicationCoordinator::get(_txn.get())->setFollowerMode(MemberState::RS_PRIMARY);
+ ReplicationCoordinator::get(_opCtx.get())->setFollowerMode(MemberState::RS_PRIMARY);
auto status = runOps(ops);
ASSERT_EQ(status.code(), ErrorCodes::KeyTooLong);
}
TEST_F(IdempotencyTest, IndexWithDifferentOptions) {
- ReplicationCoordinator::get(_txn.get())->setFollowerMode(MemberState::RS_RECOVERING);
+ ReplicationCoordinator::get(_opCtx.get())->setFollowerMode(MemberState::RS_RECOVERING);
ASSERT_OK(runOp(createCollection()));
ASSERT_OK(runOp(insert(fromjson("{_id: 1, x: 'hi'}"))));
@@ -1183,7 +1232,7 @@ TEST_F(IdempotencyTest, IndexWithDifferentOptions) {
ASSERT_OK(runOps(ops));
ASSERT_EQUALS(hash, validate());
- ReplicationCoordinator::get(_txn.get())->setFollowerMode(MemberState::RS_PRIMARY);
+ ReplicationCoordinator::get(_opCtx.get())->setFollowerMode(MemberState::RS_PRIMARY);
auto status = runOps(ops);
ASSERT_EQ(status.code(), ErrorCodes::IndexOptionsConflict);
}
@@ -1328,7 +1377,7 @@ TEST_F(IdempotencyTest, CollModIndexNotFound) {
}
TEST_F(IdempotencyTest, ResyncOnRenameCollection) {
- ReplicationCoordinator::get(_txn.get())->setFollowerMode(MemberState::RS_RECOVERING);
+ ReplicationCoordinator::get(_opCtx.get())->setFollowerMode(MemberState::RS_RECOVERING);
auto cmd = BSON("renameCollection" << nss.ns() << "to"
<< "test.bar"