summaryrefslogtreecommitdiff
path: root/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit_test.cpp')
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit_test.cpp83
1 files changed, 83 insertions, 0 deletions
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit_test.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit_test.cpp
index 314a524063e..1f440d319b7 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit_test.cpp
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit_test.cpp
@@ -163,11 +163,14 @@ public:
clientAndCtx2 = makeClientAndOpCtx(harnessHelper.get(), "reader");
ru1 = checked_cast<WiredTigerRecoveryUnit*>(clientAndCtx1.second->recoveryUnit());
ru2 = checked_cast<WiredTigerRecoveryUnit*>(clientAndCtx2.second->recoveryUnit());
+ snapshotManager = dynamic_cast<WiredTigerSnapshotManager*>(
+ harnessHelper->getEngine()->getSnapshotManager());
}
std::unique_ptr<WiredTigerRecoveryUnitHarnessHelper> harnessHelper;
ClientAndCtx clientAndCtx1, clientAndCtx2;
WiredTigerRecoveryUnit *ru1, *ru2;
+ WiredTigerSnapshotManager* snapshotManager;
private:
const char* wt_uri = "table:prepare_transaction";
@@ -180,6 +183,86 @@ TEST_F(WiredTigerRecoveryUnitTestFixture, SetReadSource) {
ASSERT_EQ(Timestamp(1, 1), ru1->getPointInTimeReadTimestamp());
}
+TEST_F(WiredTigerRecoveryUnitTestFixture, NoOverlapReadSource) {
+ OperationContext* opCtx1 = clientAndCtx1.second.get();
+ std::unique_ptr<RecordStore> rs(harnessHelper->createRecordStore(opCtx1, "a.b"));
+
+ const std::string str = str::stream() << "test";
+ const Timestamp ts1{1, 1};
+ const Timestamp ts2{1, 2};
+ const Timestamp ts3{1, 2};
+
+ RecordId rid1;
+ {
+ WriteUnitOfWork wuow(opCtx1);
+ StatusWith<RecordId> res = rs->insertRecord(opCtx1, str.c_str(), str.size() + 1, ts1);
+ ASSERT_OK(res);
+ wuow.commit();
+ rid1 = res.getValue();
+ snapshotManager->setLastApplied(ts1);
+ }
+
+ // Read without a timestamp. The write should be visible.
+ ASSERT_EQ(opCtx1->recoveryUnit()->getTimestampReadSource(), RecoveryUnit::ReadSource::kUnset);
+ RecordData unused;
+ ASSERT_TRUE(rs->findRecord(opCtx1, rid1, &unused));
+
+ // Read with kNoOverlap. The write should be visible.
+ opCtx1->recoveryUnit()->abandonSnapshot();
+ opCtx1->recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kNoOverlap);
+ ASSERT_TRUE(rs->findRecord(opCtx1, rid1, &unused));
+
+ RecordId rid2, rid3;
+ {
+ // Start, but do not commit a transaction with opCtx2. This sets a timestamp at ts2, which
+ // creates a hole. kNoOverlap, which is a function of all_durable, will only be able to read
+ // at the time immediately before.
+ OperationContext* opCtx2 = clientAndCtx2.second.get();
+ WriteUnitOfWork wuow(opCtx2);
+ StatusWith<RecordId> res =
+ rs->insertRecord(opCtx2, str.c_str(), str.size() + 1, Timestamp());
+ ASSERT_OK(opCtx2->recoveryUnit()->setTimestamp(ts2));
+ ASSERT_OK(res);
+
+ // While holding open a transaction with opCtx2, perform an insert at ts3 with opCtx1. This
+ // creates a "hole".
+ {
+ WriteUnitOfWork wuow(opCtx1);
+ StatusWith<RecordId> res = rs->insertRecord(opCtx1, str.c_str(), str.size() + 1, ts3);
+ ASSERT_OK(res);
+ wuow.commit();
+ rid3 = res.getValue();
+ snapshotManager->setLastApplied(ts3);
+ }
+
+ // Read without a timestamp, and we should see the first and third records.
+ opCtx1->recoveryUnit()->abandonSnapshot();
+ opCtx1->recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kUnset);
+ ASSERT_TRUE(rs->findRecord(opCtx1, rid1, &unused));
+ ASSERT_FALSE(rs->findRecord(opCtx1, rid2, &unused));
+ ASSERT_TRUE(rs->findRecord(opCtx1, rid3, &unused));
+
+ // Now read at kNoOverlap. Since the transaction at ts2 has not committed, all_durable is
+ // held back to ts1. LastApplied has advanced to ts3, but because kNoOverlap is the minimum,
+ // we should only see one record.
+ opCtx1->recoveryUnit()->abandonSnapshot();
+ opCtx1->recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kNoOverlap);
+ ASSERT_TRUE(rs->findRecord(opCtx1, rid1, &unused));
+ ASSERT_FALSE(rs->findRecord(opCtx1, rid2, &unused));
+ ASSERT_FALSE(rs->findRecord(opCtx1, rid3, &unused));
+
+ wuow.commit();
+ rid2 = res.getValue();
+ }
+
+ // Now that the hole has been closed, kNoOverlap should see all 3 records.
+ opCtx1->recoveryUnit()->abandonSnapshot();
+ opCtx1->recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kNoOverlap);
+ ASSERT_TRUE(rs->findRecord(opCtx1, rid1, &unused));
+ ASSERT_TRUE(rs->findRecord(opCtx1, rid2, &unused));
+ ASSERT_TRUE(rs->findRecord(opCtx1, rid3, &unused));
+}
+
TEST_F(WiredTigerRecoveryUnitTestFixture, CreateAndCheckForCachePressure) {
int time = 1;