diff options
author | Mathias Stearn <mathias@10gen.com> | 2015-11-24 14:01:31 -0500 |
---|---|---|
committer | Mathias Stearn <mathias@10gen.com> | 2015-11-30 19:50:09 -0500 |
commit | 0e4d706953cd4db25fc9ffa4abf106541157f971 (patch) | |
tree | 6d06dbefd2fdd80493d8b5fcc53fe4e56d3451b7 /src | |
parent | 6e545bce06f1c5caa8fc3e021d71b19dff393f54 (diff) | |
download | mongo-0e4d706953cd4db25fc9ffa4abf106541157f971.tar.gz |
SERVER-21645 RS rollback should set _oplog_highestSeen
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp | 19 | ||||
-rw-r--r-- | src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test.cpp | 73 |
2 files changed, 84 insertions, 8 deletions
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp index 7567a37562a..8c5c34385dd 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp @@ -1696,15 +1696,23 @@ void WiredTigerRecordStore::temp_cappedTruncateAfter(OperationContext* txn, int64_t recordsRemoved = 0; int64_t bytesRemoved = 0; - RecordId firstRemovedId = end; - - if (!inclusive) { + RecordId lastKeptId; + RecordId firstRemovedId; + + if (inclusive) { + Cursor reverseCursor(txn, *this, false); + invariant(reverseCursor.seekExact(end)); + auto prev = reverseCursor.next(); + lastKeptId = prev ? prev->id : RecordId(); + firstRemovedId = end; + } else { // If not deleting the record located at 'end', then advance the cursor to the first record // that is being deleted. record = cursor.next(); if (!record) { return; // No records to delete. } + lastKeptId = end; firstRemovedId = record->id; } @@ -1733,6 +1741,11 @@ void WiredTigerRecordStore::temp_cappedTruncateAfter(OperationContext* txn, wuow.commit(); + if (_useOplogHack) { + // Forget that we've ever seen a higher timestamp than we now have. + _oplog_highestSeen = lastKeptId; + } + if (_oplogStones) { _oplogStones->updateStonesAfterCappedTruncateAfter( recordsRemoved, bytesRemoved, firstRemovedId); diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test.cpp index 5a6b2d44978..7dcc4033f70 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test.cpp @@ -795,10 +795,70 @@ TEST(WiredTigerRecordStoreTest, OplogOrder) { } { - // now we insert 2 docs, but commit the 2nd one fiirst - // we make sure we can't find the 2nd until the first is commited + // now we insert 2 docs, but commit the 2nd one first. + // we make sure we can't find the 2nd until the first is commited. + unique_ptr<OperationContext> earlyReader(harnessHelper->newOperationContext()); + auto earlyCursor = rs->getCursor(earlyReader.get()); + ASSERT_EQ(earlyCursor->seekExact(id1)->id, id1); + earlyCursor->save(); + earlyReader->recoveryUnit()->abandonSnapshot(); + unique_ptr<OperationContext> t1(harnessHelper->newOperationContext()); - unique_ptr<WriteUnitOfWork> w1(new WriteUnitOfWork(t1.get())); + WriteUnitOfWork w1(t1.get()); + _oplogOrderInsertOplog(t1.get(), rs, 20); + // do not commit yet + + { // create 2nd doc + unique_ptr<OperationContext> t2(harnessHelper->newOperationContext()); + { + WriteUnitOfWork w2(t2.get()); + _oplogOrderInsertOplog(t2.get(), rs, 30); + w2.commit(); + } + } + + { // Other operations should not be able to see 2nd doc until w1 commits. + earlyCursor->restore(); + ASSERT(!earlyCursor->next()); + + unique_ptr<OperationContext> opCtx(harnessHelper->newOperationContext()); + auto cursor = rs->getCursor(opCtx.get()); + auto record = cursor->seekExact(id1); + ASSERT_EQ(id1, record->id); + ASSERT(!cursor->next()); + } + + w1.commit(); + } + + { // now all 3 docs should be visible + unique_ptr<OperationContext> opCtx(harnessHelper->newOperationContext()); + auto cursor = rs->getCursor(opCtx.get()); + auto record = cursor->seekExact(id1); + ASSERT_EQ(id1, record->id); + ASSERT(cursor->next()); + ASSERT(cursor->next()); + ASSERT(!cursor->next()); + } + + // Rollback the last two oplog entries, then insert entries with older optimes and ensure that + // the visibility rules aren't violated. See SERVER-21645 + { + unique_ptr<OperationContext> txn(harnessHelper->newOperationContext()); + rs->temp_cappedTruncateAfter(txn.get(), id1, /*inclusive*/ false); + } + + { + // Now we insert 2 docs with timestamps earlier than before, but commit the 2nd one first. + // We make sure we can't find the 2nd until the first is commited. + unique_ptr<OperationContext> earlyReader(harnessHelper->newOperationContext()); + auto earlyCursor = rs->getCursor(earlyReader.get()); + ASSERT_EQ(earlyCursor->seekExact(id1)->id, id1); + earlyCursor->save(); + earlyReader->recoveryUnit()->abandonSnapshot(); + + unique_ptr<OperationContext> t1(harnessHelper->newOperationContext()); + WriteUnitOfWork w1(t1.get()); _oplogOrderInsertOplog(t1.get(), rs, 2); // do not commit yet @@ -811,7 +871,10 @@ TEST(WiredTigerRecordStoreTest, OplogOrder) { } } - { // state should be the same + { // Other operations should not be able to see 2nd doc until w1 commits. + ASSERT(earlyCursor->restore()); + ASSERT(!earlyCursor->next()); + unique_ptr<OperationContext> opCtx(harnessHelper->newOperationContext()); auto cursor = rs->getCursor(opCtx.get()); auto record = cursor->seekExact(id1); @@ -819,7 +882,7 @@ TEST(WiredTigerRecordStoreTest, OplogOrder) { ASSERT(!cursor->next()); } - w1->commit(); + w1.commit(); } { // now all 3 docs should be visible |