summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias Stearn <mathias@10gen.com>2015-11-24 14:01:31 -0500
committerMathias Stearn <mathias@10gen.com>2015-11-30 19:50:09 -0500
commit0e4d706953cd4db25fc9ffa4abf106541157f971 (patch)
tree6d06dbefd2fdd80493d8b5fcc53fe4e56d3451b7
parent6e545bce06f1c5caa8fc3e021d71b19dff393f54 (diff)
downloadmongo-0e4d706953cd4db25fc9ffa4abf106541157f971.tar.gz
SERVER-21645 RS rollback should set _oplog_highestSeen
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp19
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test.cpp73
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