diff options
Diffstat (limited to 'src/mongo/db')
-rw-r--r-- | src/mongo/db/catalog/apply_ops.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/repl/master_slave.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/repl/multiapplier.h | 2 | ||||
-rw-r--r-- | src/mongo/db/repl/oplog.cpp | 16 | ||||
-rw-r--r-- | src/mongo/db/repl/oplog.h | 8 | ||||
-rw-r--r-- | src/mongo/db/repl/sync_tail.cpp | 39 | ||||
-rw-r--r-- | src/mongo/db/repl/sync_tail.h | 16 | ||||
-rw-r--r-- | src/mongo/db/repl/sync_tail_test.cpp | 115 |
8 files changed, 120 insertions, 82 deletions
diff --git a/src/mongo/db/catalog/apply_ops.cpp b/src/mongo/db/catalog/apply_ops.cpp index 5b783fff7f4..0072d2ef0b0 100644 --- a/src/mongo/db/catalog/apply_ops.cpp +++ b/src/mongo/db/catalog/apply_ops.cpp @@ -158,7 +158,7 @@ Status _applyOps(OperationContext* txn, MONGO_WRITE_CONFLICT_RETRY_LOOP_BEGIN { if (*opType == 'c') { - status = repl::applyCommand_inlock(txn, opObj); + status = repl::applyCommand_inlock(txn, opObj, true); } else { OldClientContext ctx(txn, ns); diff --git a/src/mongo/db/repl/master_slave.cpp b/src/mongo/db/repl/master_slave.cpp index 353e81f2e60..c78dbba2c5d 100644 --- a/src/mongo/db/repl/master_slave.cpp +++ b/src/mongo/db/repl/master_slave.cpp @@ -640,14 +640,14 @@ bool ReplSource::handleDuplicateDbName(OperationContext* txn, void ReplSource::applyCommand(OperationContext* txn, const BSONObj& op) { try { - Status status = applyCommand_inlock(txn, op); + Status status = applyCommand_inlock(txn, op, true); if (!status.isOK()) { SyncTail sync(nullptr, SyncTail::MultiSyncApplyFunc()); sync.setHostname(hostName); if (sync.shouldRetry(txn, op)) { uassert(28639, "Failure retrying initial sync update", - applyCommand_inlock(txn, op).isOK()); + applyCommand_inlock(txn, op, true).isOK()); } } } catch (UserException& e) { diff --git a/src/mongo/db/repl/multiapplier.h b/src/mongo/db/repl/multiapplier.h index 66e9d150b60..3b994a00abd 100644 --- a/src/mongo/db/repl/multiapplier.h +++ b/src/mongo/db/repl/multiapplier.h @@ -67,7 +67,7 @@ public: /** * Type of function to to apply a single operation. In production, this function - * would have the same outcome as calling SyncTail::syncApply() ('convertUpdatesToUpserts' + * would have the same outcome as calling SyncTail::syncApply() ('inSteadyStateReplication' * value will be embedded in the function implementation). */ using ApplyOperationFn = stdx::function<Status(OperationPtrs*)>; diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp index bac3bc31e95..e2985ef6c91 100644 --- a/src/mongo/db/repl/oplog.cpp +++ b/src/mongo/db/repl/oplog.cpp @@ -654,7 +654,7 @@ std::map<std::string, ApplyOpMetadata> opsMap = { Status applyOperation_inlock(OperationContext* txn, Database* db, const BSONObj& op, - bool convertUpdateToUpsert, + bool inSteadyStateReplication, IncrementOpsAppliedStatsFn incrementOpsAppliedStats) { LOG(3) << "applying op: " << redact(op); @@ -870,7 +870,7 @@ Status applyOperation_inlock(OperationContext* txn, opCounters->gotUpdate(); BSONObj updateCriteria = o2; - const bool upsert = valueB || convertUpdateToUpsert; + const bool upsert = valueB || inSteadyStateReplication; uassert(ErrorCodes::NoSuchKey, str::stream() << "Failed to apply update due to missing _id: " << op.toString(), @@ -965,7 +965,9 @@ Status applyOperation_inlock(OperationContext* txn, return Status::OK(); } -Status applyCommand_inlock(OperationContext* txn, const BSONObj& op) { +Status applyCommand_inlock(OperationContext* txn, + const BSONObj& op, + bool inSteadyStateReplication) { const char* names[] = {"o", "ns", "op"}; BSONElement fields[3]; op.getFields(3, names, fields); @@ -998,6 +1000,14 @@ Status applyCommand_inlock(OperationContext* txn, const BSONObj& op) { } } + // Applying renameCollection during initial sync might lead to data corruption, so we restart + // the initial sync. + if (!inSteadyStateReplication && o.firstElementFieldName() == std::string("renameCollection")) { + return Status(ErrorCodes::OplogOperationUnsupported, + str::stream() << "Applying renameCollection not supported in initial sync: " + << redact(op)); + } + // Applying commands in repl is done under Global W-lock, so it is safe to not // perform the current DB checks after reacquiring the lock. invariant(txn->lockState()->isW()); diff --git a/src/mongo/db/repl/oplog.h b/src/mongo/db/repl/oplog.h index 6266cf6babb..b2078e93d28 100644 --- a/src/mongo/db/repl/oplog.h +++ b/src/mongo/db/repl/oplog.h @@ -106,22 +106,24 @@ using IncrementOpsAppliedStatsFn = stdx::function<void()>; /** * Take a non-command op and apply it locally * Used for applying from an oplog - * @param convertUpdateToUpsert convert some updates to upserts for idempotency reasons + * @param inSteadyStateReplication convert some updates to upserts for idempotency reasons * @param incrementOpsAppliedStats is called whenever an op is applied. * Returns failure status if the op was an update that could not be applied. */ Status applyOperation_inlock(OperationContext* txn, Database* db, const BSONObj& op, - bool convertUpdateToUpsert = false, + bool inSteadyStateReplication = false, IncrementOpsAppliedStatsFn incrementOpsAppliedStats = {}); /** * Take a command op and apply it locally * Used for applying from an oplog + * inSteadyStateReplication indicates whether we are in steady state replication, rather than + * initial sync. * Returns failure status if the op that could not be applied. */ -Status applyCommand_inlock(OperationContext* txn, const BSONObj& op); +Status applyCommand_inlock(OperationContext* txn, const BSONObj& op, bool inSteadyStateReplication); /** * Initializes the global Timestamp with the value from the timestamp of the last oplog entry. diff --git a/src/mongo/db/repl/sync_tail.cpp b/src/mongo/db/repl/sync_tail.cpp index 81ffc65518b..560584c415c 100644 --- a/src/mongo/db/repl/sync_tail.cpp +++ b/src/mongo/db/repl/sync_tail.cpp @@ -284,7 +284,7 @@ bool SyncTail::peek(OperationContext* txn, BSONObj* op) { // static Status SyncTail::syncApply(OperationContext* txn, const BSONObj& op, - bool convertUpdateToUpsert, + bool inSteadyStateReplication, ApplyOperationInLockFn applyOperationInLock, ApplyCommandInLockFn applyCommandInLock, IncrementOpsAppliedStatsFn incrementOpsAppliedStats) { @@ -316,7 +316,7 @@ Status SyncTail::syncApply(OperationContext* txn, Lock::GlobalWrite globalWriteLock(txn->lockState()); // special case apply for commands to avoid implicit database creation - Status status = applyCommandInLock(txn, op); + Status status = applyCommandInLock(txn, op, inSteadyStateReplication); incrementOpsAppliedStats(); return status; } @@ -330,7 +330,7 @@ Status SyncTail::syncApply(OperationContext* txn, DisableDocumentValidation validationDisabler(txn); Status status = - applyOperationInLock(txn, db, op, convertUpdateToUpsert, incrementOpsAppliedStats); + applyOperationInLock(txn, db, op, inSteadyStateReplication, incrementOpsAppliedStats); if (!status.isOK() && status.code() == ErrorCodes::WriteConflict) { throw WriteConflictException(); } @@ -390,10 +390,12 @@ Status SyncTail::syncApply(OperationContext* txn, return Status(ErrorCodes::BadValue, ss); } -Status SyncTail::syncApply(OperationContext* txn, const BSONObj& op, bool convertUpdateToUpsert) { +Status SyncTail::syncApply(OperationContext* txn, + const BSONObj& op, + bool inSteadyStateReplication) { return SyncTail::syncApply(txn, op, - convertUpdateToUpsert, + inSteadyStateReplication, applyOperation_inlock, applyCommand_inlock, stdx::bind(&Counter64::increment, &opsAppliedStats, 1ULL)); @@ -1045,8 +1047,8 @@ bool SyncTail::shouldRetry(OperationContext* txn, const BSONObj& o) { void multiSyncApply(MultiApplier::OperationPtrs* ops, SyncTail*) { initializeWriterThread(); auto txn = cc().makeOperationContext(); - auto syncApply = [](OperationContext* txn, const BSONObj& op, bool convertUpdateToUpsert) { - return SyncTail::syncApply(txn, op, convertUpdateToUpsert); + auto syncApply = [](OperationContext* txn, const BSONObj& op, bool inSteadyStateReplication) { + return SyncTail::syncApply(txn, op, inSteadyStateReplication); }; fassertNoTrace(16359, multiSyncApply_noAbort(txn.get(), ops, syncApply)); @@ -1067,7 +1069,9 @@ Status multiSyncApply_noAbort(OperationContext* txn, [](const OplogEntry* l, const OplogEntry* r) { return l->ns < r->ns; }); } - bool convertUpdatesToUpserts = true; + // This function is only called in steady state replication. + const bool inSteadyStateReplication = true; + // doNotGroupBeforePoint is used to prevent retrying bad group inserts by marking the final op // of a failed group and not allowing further group inserts until that op has been processed. auto doNotGroupBeforePoint = oplogEntryPointers->begin(); @@ -1116,7 +1120,7 @@ Status multiSyncApply_noAbort(OperationContext* txn, try { // Apply the group of inserts. uassertStatusOK( - syncApply(txn, groupedInsertBuilder.done(), convertUpdatesToUpserts)); + syncApply(txn, groupedInsertBuilder.done(), inSteadyStateReplication)); // It succeeded, advance the oplogEntriesIterator to the end of the // group of inserts. oplogEntriesIterator = endOfGroupableOpsIterator - 1; @@ -1136,7 +1140,7 @@ Status multiSyncApply_noAbort(OperationContext* txn, try { // Apply an individual (non-grouped) op. - const Status status = syncApply(txn, entry->raw, convertUpdatesToUpserts); + const Status status = syncApply(txn, entry->raw, inSteadyStateReplication); if (!status.isOK()) { severe() << "Error applying operation (" << redact(entry->raw) @@ -1175,15 +1179,24 @@ Status multiInitialSyncApply_noAbort(OperationContext* txn, // allow us to get through the magic barrier txn->lockState()->setShouldConflictWithSecondaryBatchApplication(false); - bool convertUpdatesToUpserts = false; + // This function is only called in initial sync, as its name suggests. + const bool inSteadyStateReplication = false; for (auto it = ops->begin(); it != ops->end(); ++it) { auto& entry = **it; try { - const Status s = SyncTail::syncApply(txn, entry.raw, convertUpdatesToUpserts); + const Status s = SyncTail::syncApply(txn, entry.raw, inSteadyStateReplication); if (!s.isOK()) { + // Don't retry on commands. + if (entry.isCommand()) { + error() << "Error applying command (" << redact(entry.raw) + << "): " << redact(s); + return s; + } + + // We might need to fetch the missing docs from the sync source. if (st->shouldRetry(txn, entry.raw)) { - const Status s2 = SyncTail::syncApply(txn, entry.raw, convertUpdatesToUpserts); + const Status s2 = SyncTail::syncApply(txn, entry.raw, inSteadyStateReplication); if (!s2.isOK()) { severe() << "Error applying operation (" << redact(entry.raw) << "): " << redact(s2); diff --git a/src/mongo/db/repl/sync_tail.h b/src/mongo/db/repl/sync_tail.h index b2b06bb59ec..1bd30076161 100644 --- a/src/mongo/db/repl/sync_tail.h +++ b/src/mongo/db/repl/sync_tail.h @@ -65,22 +65,26 @@ public: * Used for applying from an oplog. * 'db' is the database where the op will be applied. * 'opObj' is a BSONObj describing the op to be applied. - * 'convertUpdateToUpsert' indicates to convert some updates to upserts for idempotency reasons. + * 'inSteadyStateReplication' indicates to convert some updates to upserts for idempotency + * reasons. * 'opCounter' is used to update server status metrics. * Returns failure status if the op was an update that could not be applied. */ using ApplyOperationInLockFn = stdx::function<Status(OperationContext* txn, Database* db, const BSONObj& opObj, - bool convertUpdateToUpsert, + bool inSteadyStateReplication, IncrementOpsAppliedStatsFn opCounter)>; /** * Type of function that takes a command op and applies it locally. * Used for applying from an oplog. + * inSteadyStateReplication indicates whether we are in steady state replication, rather than + * initial sync. * Returns failure status if the op that could not be applied. */ - using ApplyCommandInLockFn = stdx::function<Status(OperationContext*, const BSONObj&)>; + using ApplyCommandInLockFn = + stdx::function<Status(OperationContext*, const BSONObj&, bool inSteadyStateReplication)>; SyncTail(BackgroundSync* q, MultiSyncApplyFunc func); SyncTail(BackgroundSync* q, MultiSyncApplyFunc func, std::unique_ptr<OldThreadPool> writerPool); @@ -98,12 +102,12 @@ public: */ static Status syncApply(OperationContext* txn, const BSONObj& o, - bool convertUpdateToUpsert, + bool inSteadyStateReplication, ApplyOperationInLockFn applyOperationInLock, ApplyCommandInLockFn applyCommandInLock, IncrementOpsAppliedStatsFn incrementOpsAppliedStats); - static Status syncApply(OperationContext* txn, const BSONObj& o, bool convertUpdateToUpsert); + static Status syncApply(OperationContext* txn, const BSONObj& o, bool inSteadyStateReplication); void oplogApplication(ReplicationCoordinator* replCoord); bool peek(OperationContext* txn, BSONObj* obj); @@ -266,7 +270,7 @@ Status multiInitialSyncApply(MultiApplier::OperationPtrs* ops, SyncTail* st); * SyncTail::syncApply. */ using SyncApplyFn = - stdx::function<Status(OperationContext* txn, const BSONObj& o, bool convertUpdateToUpsert)>; + stdx::function<Status(OperationContext* txn, const BSONObj& o, bool inSteadyStateReplication)>; Status multiSyncApply_noAbort(OperationContext* txn, MultiApplier::OperationPtrs* ops, SyncApplyFn syncApply); diff --git a/src/mongo/db/repl/sync_tail_test.cpp b/src/mongo/db/repl/sync_tail_test.cpp index d316a07217c..b3d560e96a1 100644 --- a/src/mongo/db/repl/sync_tail_test.cpp +++ b/src/mongo/db/repl/sync_tail_test.cpp @@ -124,9 +124,9 @@ void SyncTailTest::setUp() { _applyOp = [](OperationContext* txn, Database* db, const BSONObj& op, - bool convertUpdateToUpsert, + bool inSteadyStateReplication, stdx::function<void()>) { return Status::OK(); }; - _applyCmd = [](OperationContext* txn, const BSONObj& op) { return Status::OK(); }; + _applyCmd = [](OperationContext* txn, const BSONObj& op, bool) { return Status::OK(); }; _incOps = [this]() { _opsApplied++; }; } @@ -233,6 +233,11 @@ OplogEntry makeUpdateDocumentOplogEntry(OpTime opTime, return OplogEntry(bob.obj()); } +Status failedApplyCommand(OperationContext* txn, const BSONObj& theOperation, bool) { + FAIL("applyCommand unexpectedly invoked."); + return Status::OK(); +} + TEST_F(SyncTailTest, SyncApplyNoNamespaceBadOp) { const BSONObj op = BSON("op" << "x"); @@ -267,7 +272,7 @@ TEST_F(SyncTailTest, SyncApplyNoOp) { SyncTail::ApplyOperationInLockFn applyOp = [&](OperationContext* txn, Database* db, const BSONObj& theOperation, - bool convertUpdateToUpsert, + bool inSteadyStateReplication, stdx::function<void()>) { applyOpCalled = true; ASSERT_TRUE(txn); @@ -276,17 +281,12 @@ TEST_F(SyncTailTest, SyncApplyNoOp) { ASSERT_TRUE(documentValidationDisabled(txn)); ASSERT_TRUE(db); ASSERT_BSONOBJ_EQ(op, theOperation); - ASSERT_FALSE(convertUpdateToUpsert); - return Status::OK(); - }; - SyncTail::ApplyCommandInLockFn applyCmd = [&](OperationContext* txn, - const BSONObj& theOperation) { - FAIL("applyCommand unexpectedly invoked."); + ASSERT_FALSE(inSteadyStateReplication); return Status::OK(); }; ASSERT_TRUE(_txn->writesAreReplicated()); ASSERT_FALSE(documentValidationDisabled(_txn.get())); - ASSERT_OK(SyncTail::syncApply(_txn.get(), op, false, applyOp, applyCmd, _incOps)); + ASSERT_OK(SyncTail::syncApply(_txn.get(), op, false, applyOp, failedApplyCommand, _incOps)); ASSERT_TRUE(applyOpCalled); } @@ -299,7 +299,7 @@ TEST_F(SyncTailTest, SyncApplyNoOpApplyOpThrowsException) { SyncTail::ApplyOperationInLockFn applyOp = [&](OperationContext* txn, Database* db, const BSONObj& theOperation, - bool convertUpdateToUpsert, + bool inSteadyStateReplication, stdx::function<void()>) { applyOpCalled++; if (applyOpCalled < 5) { @@ -307,12 +307,7 @@ TEST_F(SyncTailTest, SyncApplyNoOpApplyOpThrowsException) { } return Status::OK(); }; - SyncTail::ApplyCommandInLockFn applyCmd = [&](OperationContext* txn, - const BSONObj& theOperation) { - FAIL("applyCommand unexpectedly invoked."); - return Status::OK(); - }; - ASSERT_OK(SyncTail::syncApply(_txn.get(), op, false, applyOp, applyCmd, _incOps)); + ASSERT_OK(SyncTail::syncApply(_txn.get(), op, false, applyOp, failedApplyCommand, _incOps)); ASSERT_EQUALS(5, applyOpCalled); } @@ -325,7 +320,7 @@ void SyncTailTest::_testSyncApplyInsertDocument(LockMode expectedMode) { SyncTail::ApplyOperationInLockFn applyOp = [&](OperationContext* txn, Database* db, const BSONObj& theOperation, - bool convertUpdateToUpsert, + bool inSteadyStateReplication, stdx::function<void()>) { applyOpCalled = true; ASSERT_TRUE(txn); @@ -335,17 +330,12 @@ void SyncTailTest::_testSyncApplyInsertDocument(LockMode expectedMode) { ASSERT_TRUE(documentValidationDisabled(txn)); ASSERT_TRUE(db); ASSERT_BSONOBJ_EQ(op, theOperation); - ASSERT_TRUE(convertUpdateToUpsert); - return Status::OK(); - }; - SyncTail::ApplyCommandInLockFn applyCmd = [&](OperationContext* txn, - const BSONObj& theOperation) { - FAIL("applyCommand unexpectedly invoked."); + ASSERT_TRUE(inSteadyStateReplication); return Status::OK(); }; ASSERT_TRUE(_txn->writesAreReplicated()); ASSERT_FALSE(documentValidationDisabled(_txn.get())); - ASSERT_OK(SyncTail::syncApply(_txn.get(), op, true, applyOp, applyCmd, _incOps)); + ASSERT_OK(SyncTail::syncApply(_txn.get(), op, true, applyOp, failedApplyCommand, _incOps)); ASSERT_TRUE(applyOpCalled); } @@ -386,7 +376,7 @@ TEST_F(SyncTailTest, SyncApplyIndexBuild) { SyncTail::ApplyOperationInLockFn applyOp = [&](OperationContext* txn, Database* db, const BSONObj& theOperation, - bool convertUpdateToUpsert, + bool inSteadyStateReplication, stdx::function<void()>) { applyOpCalled = true; ASSERT_TRUE(txn); @@ -395,17 +385,12 @@ TEST_F(SyncTailTest, SyncApplyIndexBuild) { ASSERT_TRUE(documentValidationDisabled(txn)); ASSERT_TRUE(db); ASSERT_BSONOBJ_EQ(op, theOperation); - ASSERT_FALSE(convertUpdateToUpsert); - return Status::OK(); - }; - SyncTail::ApplyCommandInLockFn applyCmd = [&](OperationContext* txn, - const BSONObj& theOperation) { - FAIL("applyCommand unexpectedly invoked."); + ASSERT_FALSE(inSteadyStateReplication); return Status::OK(); }; ASSERT_TRUE(_txn->writesAreReplicated()); ASSERT_FALSE(documentValidationDisabled(_txn.get())); - ASSERT_OK(SyncTail::syncApply(_txn.get(), op, false, applyOp, applyCmd, _incOps)); + ASSERT_OK(SyncTail::syncApply(_txn.get(), op, false, applyOp, failedApplyCommand, _incOps)); ASSERT_TRUE(applyOpCalled); } @@ -418,21 +403,21 @@ TEST_F(SyncTailTest, SyncApplyCommand) { SyncTail::ApplyOperationInLockFn applyOp = [&](OperationContext* txn, Database* db, const BSONObj& theOperation, - bool convertUpdateToUpsert, + bool inSteadyStateReplication, stdx::function<void()>) { FAIL("applyOperation unexpectedly invoked."); return Status::OK(); }; - SyncTail::ApplyCommandInLockFn applyCmd = [&](OperationContext* txn, - const BSONObj& theOperation) { - applyCmdCalled = true; - ASSERT_TRUE(txn); - ASSERT_TRUE(txn->lockState()->isW()); - ASSERT_TRUE(txn->writesAreReplicated()); - ASSERT_FALSE(documentValidationDisabled(txn)); - ASSERT_BSONOBJ_EQ(op, theOperation); - return Status::OK(); - }; + SyncTail::ApplyCommandInLockFn applyCmd = + [&](OperationContext* txn, const BSONObj& theOperation, bool inSteadyStateReplication) { + applyCmdCalled = true; + ASSERT_TRUE(txn); + ASSERT_TRUE(txn->lockState()->isW()); + ASSERT_TRUE(txn->writesAreReplicated()); + ASSERT_FALSE(documentValidationDisabled(txn)); + 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)); @@ -449,19 +434,19 @@ TEST_F(SyncTailTest, SyncApplyCommandThrowsException) { SyncTail::ApplyOperationInLockFn applyOp = [&](OperationContext* txn, Database* db, const BSONObj& theOperation, - bool convertUpdateToUpsert, + bool inSteadyStateReplication, stdx::function<void()>) { FAIL("applyOperation unexpectedly invoked."); return Status::OK(); }; - SyncTail::ApplyCommandInLockFn applyCmd = [&](OperationContext* txn, - const BSONObj& theOperation) { - applyCmdCalled++; - if (applyCmdCalled < 5) { - throw WriteConflictException(); - } - return Status::OK(); - }; + SyncTail::ApplyCommandInLockFn applyCmd = + [&](OperationContext* txn, const BSONObj& theOperation, bool inSteadyStateReplication) { + applyCmdCalled++; + if (applyCmdCalled < 5) { + throw WriteConflictException(); + } + return Status::OK(); + }; ASSERT_OK(SyncTail::syncApply(_txn.get(), op, false, applyOp, applyCmd, _incOps)); ASSERT_EQUALS(5, applyCmdCalled); ASSERT_EQUALS(1U, _opsApplied); @@ -923,4 +908,28 @@ TEST_F(SyncTailTest, MultiInitialSyncApplyPassesThroughShouldSyncTailRetryError) multiInitialSyncApply_noAbort(_txn.get(), &ops, &syncTail)); } +TEST_F(SyncTailTest, MultiInitialSyncApplyFailsOnRenameCollection) { + SyncTail syncTail(nullptr, SyncTail::MultiSyncApplyFunc(), nullptr); + + BSONObjBuilder bob; + bob.appendElements(OpTime(Timestamp(1, 0), 1LL).toBSON()); + bob.append("h", 1LL); + bob.append("op", "c"); + bob.append("ns", "test.$cmd"); + bob.append("o", + BSON("renameCollection" + << "test.foo" + << "to" + << "test.bar" + << "stayTemp" + << false + << "dropTarget" + << false)); + auto op = OplogEntry(bob.obj()); + + MultiApplier::OperationPtrs ops = {&op}; + ASSERT_EQUALS(ErrorCodes::OplogOperationUnsupported, + multiInitialSyncApply_noAbort(_txn.get(), &ops, &syncTail)); +} + } // namespace |