summaryrefslogtreecommitdiff
path: root/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test.cpp')
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test.cpp355
1 files changed, 20 insertions, 335 deletions
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 75b5c11e673..5261cfc73ba 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test.cpp
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test.cpp
@@ -45,7 +45,6 @@
#include "mongo/db/storage/wiredtiger/wiredtiger_record_store.h"
#include "mongo/db/storage/wiredtiger/wiredtiger_record_store_oplog_stones.h"
#include "mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.h"
-#include "mongo/db/storage/wiredtiger/wiredtiger_session_cache.h"
#include "mongo/db/storage/wiredtiger/wiredtiger_size_storer.h"
#include "mongo/db/storage/wiredtiger/wiredtiger_util.h"
#include "mongo/stdx/memory.h"
@@ -222,179 +221,6 @@ StatusWith<RecordId> insertBSON(ServiceContext::UniqueOperationContext& opCtx,
return res;
}
-// TODO make generic
-TEST(WiredTigerRecordStoreTest, OplogHack) {
- std::unique_ptr<RecordStoreHarnessHelper> harnessHelper = newRecordStoreHarnessHelper();
- // Use a large enough cappedMaxSize so that the limit is not reached by doing the inserts within
- // the test itself.
- const int64_t cappedMaxSize = 10 * 1024; // 10KB
- unique_ptr<RecordStore> rs(
- harnessHelper->newCappedRecordStore("local.oplog.foo", cappedMaxSize, -1));
- {
- ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
-
- // always illegal
- ASSERT_EQ(insertBSON(opCtx, rs, Timestamp(2, -1)).getStatus(), ErrorCodes::BadValue);
-
- {
- BSONObj obj = BSON("not_ts" << Timestamp(2, 1));
- ASSERT_EQ(
- rs->insertRecord(opCtx.get(), obj.objdata(), obj.objsize(), false).getStatus(),
- ErrorCodes::BadValue);
-
- obj = BSON("ts"
- << "not a Timestamp");
- ASSERT_EQ(
- rs->insertRecord(opCtx.get(), obj.objdata(), obj.objsize(), false).getStatus(),
- ErrorCodes::BadValue);
- }
-
- // currently dasserts
- // ASSERT_EQ(insertBSON(opCtx, rs, BSON("ts" << Timestamp(-2,1))).getStatus(),
- // ErrorCodes::BadValue);
-
- // success cases
- ASSERT_EQ(insertBSON(opCtx, rs, Timestamp(1, 1)).getValue(), RecordId(1, 1));
-
- ASSERT_EQ(insertBSON(opCtx, rs, Timestamp(1, 2)).getValue(), RecordId(1, 2));
-
- ASSERT_EQ(insertBSON(opCtx, rs, Timestamp(2, 2)).getValue(), RecordId(2, 2));
- }
-
- {
- ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
- // find start
- ASSERT_EQ(rs->oplogStartHack(opCtx.get(), RecordId(0, 1)), RecordId()); // nothing <=
- ASSERT_EQ(rs->oplogStartHack(opCtx.get(), RecordId(2, 1)), RecordId(1, 2)); // between
- ASSERT_EQ(rs->oplogStartHack(opCtx.get(), RecordId(2, 2)), RecordId(2, 2)); // ==
- ASSERT_EQ(rs->oplogStartHack(opCtx.get(), RecordId(2, 3)), RecordId(2, 2)); // > highest
- }
-
- {
- ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
- rs->cappedTruncateAfter(opCtx.get(), RecordId(2, 2), false); // no-op
- }
-
- {
- ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
- ASSERT_EQ(rs->oplogStartHack(opCtx.get(), RecordId(2, 3)), RecordId(2, 2));
- }
-
- {
- ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
- rs->cappedTruncateAfter(opCtx.get(), RecordId(1, 2), false); // deletes 2,2
- }
-
- {
- ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
- ASSERT_EQ(rs->oplogStartHack(opCtx.get(), RecordId(2, 3)), RecordId(1, 2));
- }
-
- {
- ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
- rs->cappedTruncateAfter(opCtx.get(), RecordId(1, 2), true); // deletes 1,2
- }
-
- {
- ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
- ASSERT_EQ(rs->oplogStartHack(opCtx.get(), RecordId(2, 3)), RecordId(1, 1));
- }
-
- {
- ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
- WriteUnitOfWork wuow(opCtx.get());
- ASSERT_OK(rs->truncate(opCtx.get())); // deletes 1,1 and leaves collection empty
- wuow.commit();
- }
-
- {
- ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
- ASSERT_EQ(rs->oplogStartHack(opCtx.get(), RecordId(2, 3)), RecordId());
- }
-}
-
-TEST(WiredTigerRecordStoreTest, OplogHackOnNonOplog) {
- std::unique_ptr<RecordStoreHarnessHelper> harnessHelper = newRecordStoreHarnessHelper();
- unique_ptr<RecordStore> rs(harnessHelper->newNonCappedRecordStore("local.NOT_oplog.foo"));
-
- ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
-
- BSONObj obj = BSON("ts" << Timestamp(2, -1));
- {
- WriteUnitOfWork wuow(opCtx.get());
- ASSERT_OK(rs->insertRecord(opCtx.get(), obj.objdata(), obj.objsize(), false).getStatus());
- wuow.commit();
- }
- ASSERT_EQ(rs->oplogStartHack(opCtx.get(), RecordId(0, 1)), boost::none);
-}
-
-TEST(WiredTigerRecordStoreTest, CappedOrder) {
- unique_ptr<RecordStoreHarnessHelper> harnessHelper(newRecordStoreHarnessHelper());
- unique_ptr<RecordStore> rs(harnessHelper->newCappedRecordStore("a.b", 100000, 10000));
-
- RecordId id1;
-
- { // first insert a document
- ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
- {
- WriteUnitOfWork uow(opCtx.get());
- StatusWith<RecordId> res = rs->insertRecord(opCtx.get(), "a", 2, false);
- ASSERT_OK(res.getStatus());
- id1 = res.getValue();
- uow.commit();
- }
- }
-
- {
- ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
- auto cursor = rs->getCursor(opCtx.get());
- auto record = cursor->seekExact(id1);
- ASSERT_EQ(id1, record->id);
- ASSERT(!cursor->next());
- }
-
- {
- // 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
- ServiceContext::UniqueOperationContext t1(harnessHelper->newOperationContext());
- unique_ptr<WriteUnitOfWork> w1(new WriteUnitOfWork(t1.get()));
- rs->insertRecord(t1.get(), "b", 2, false).status_with_transitional_ignore();
- // do not commit yet
-
- { // create 2nd doc
- auto client2 = harnessHelper->serviceContext()->makeClient("c2");
- auto t2 = harnessHelper->newOperationContext(client2.get());
- {
- WriteUnitOfWork w2(t2.get());
- rs->insertRecord(t2.get(), "c", 2, false).status_with_transitional_ignore();
- w2.commit();
- }
- }
-
- { // state should be the same
- auto client2 = harnessHelper->serviceContext()->makeClient("c2");
- auto opCtx = harnessHelper->newOperationContext(client2.get());
- 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
- auto client2 = harnessHelper->serviceContext()->makeClient("c2");
- auto opCtx = harnessHelper->newOperationContext(client2.get());
- 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());
- }
-}
-
TEST(WiredTigerRecordStoreTest, CappedCursorRollover) {
unique_ptr<RecordStoreHarnessHelper> harnessHelper(newRecordStoreHarnessHelper());
unique_ptr<RecordStore> rs(harnessHelper->newCappedRecordStore("a.b", 10000, 5));
@@ -438,8 +264,7 @@ RecordId _oplogOrderInsertOplog(OperationContext* opCtx,
const unique_ptr<RecordStore>& rs,
int inc) {
Timestamp opTime = Timestamp(5, inc);
- WiredTigerRecordStore* wrs = checked_cast<WiredTigerRecordStore*>(rs.get());
- Status status = wrs->oplogDiskLocRegister(opCtx, opTime);
+ Status status = rs->oplogDiskLocRegister(opCtx, opTime);
ASSERT_OK(status);
BSONObj obj = BSON("ts" << opTime);
StatusWith<RecordId> res = rs->insertRecord(opCtx, obj.objdata(), obj.objsize(), false);
@@ -447,149 +272,6 @@ RecordId _oplogOrderInsertOplog(OperationContext* opCtx,
return res.getValue();
}
-TEST(WiredTigerRecordStoreTest, OplogOrder) {
- unique_ptr<RecordStoreHarnessHelper> harnessHelper(newRecordStoreHarnessHelper());
- unique_ptr<RecordStore> rs(harnessHelper->newCappedRecordStore("local.oplog.foo", 100000, -1));
-
- {
- const WiredTigerRecordStore* wrs = checked_cast<WiredTigerRecordStore*>(rs.get());
- ASSERT(wrs->isOplog());
- ASSERT(wrs->usingOplogHack());
- }
-
- RecordId id1;
-
- { // first insert a document
- ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
- {
- WriteUnitOfWork uow(opCtx.get());
- id1 = _oplogOrderInsertOplog(opCtx.get(), rs, 1);
- uow.commit();
- }
- }
-
- {
- ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
- auto cursor = rs->getCursor(opCtx.get());
- auto record = cursor->seekExact(id1);
- ASSERT_EQ(id1, record->id);
- ASSERT(!cursor->next());
- }
-
- {
- // 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.
- ServiceContext::UniqueOperationContext earlyReader(harnessHelper->newOperationContext());
- auto earlyCursor = rs->getCursor(earlyReader.get());
- ASSERT_EQ(earlyCursor->seekExact(id1)->id, id1);
- earlyCursor->save();
- earlyReader->recoveryUnit()->abandonSnapshot();
-
- auto client1 = harnessHelper->serviceContext()->makeClient("c1");
- auto t1 = harnessHelper->newOperationContext(client1.get());
- WriteUnitOfWork w1(t1.get());
- _oplogOrderInsertOplog(t1.get(), rs, 20);
- // do not commit yet
-
- { // create 2nd doc
- auto client2 = harnessHelper->serviceContext()->makeClient("c2");
- auto t2 = harnessHelper->newOperationContext(client2.get());
- {
- 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());
-
- auto client2 = harnessHelper->serviceContext()->makeClient("c2");
- auto opCtx = harnessHelper->newOperationContext(client2.get());
- auto cursor = rs->getCursor(opCtx.get());
- auto record = cursor->seekExact(id1);
- ASSERT_EQ(id1, record->id);
- ASSERT(!cursor->next());
- }
-
- w1.commit();
- }
-
- rs->waitForAllEarlierOplogWritesToBeVisible(harnessHelper->newOperationContext().get());
-
- { // now all 3 docs should be visible
- auto client2 = harnessHelper->serviceContext()->makeClient("c2");
- auto opCtx = harnessHelper->newOperationContext(client2.get());
- 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
- {
- auto client2 = harnessHelper->serviceContext()->makeClient("c2");
- auto opCtx = harnessHelper->newOperationContext(client2.get());
- rs->cappedTruncateAfter(opCtx.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.
- ServiceContext::UniqueOperationContext earlyReader(harnessHelper->newOperationContext());
- auto earlyCursor = rs->getCursor(earlyReader.get());
- ASSERT_EQ(earlyCursor->seekExact(id1)->id, id1);
- earlyCursor->save();
- earlyReader->recoveryUnit()->abandonSnapshot();
-
- auto client1 = harnessHelper->serviceContext()->makeClient("c1");
- auto t1 = harnessHelper->newOperationContext(client1.get());
- WriteUnitOfWork w1(t1.get());
- _oplogOrderInsertOplog(t1.get(), rs, 2);
- // do not commit yet
-
- { // create 2nd doc
- auto client2 = harnessHelper->serviceContext()->makeClient("c2");
- auto t2 = harnessHelper->newOperationContext(client2.get());
- {
- WriteUnitOfWork w2(t2.get());
- _oplogOrderInsertOplog(t2.get(), rs, 3);
- w2.commit();
- }
- }
-
- { // Other operations should not be able to see 2nd doc until w1 commits.
- ASSERT(earlyCursor->restore());
- ASSERT(!earlyCursor->next());
-
- auto client2 = harnessHelper->serviceContext()->makeClient("c2");
- auto opCtx = harnessHelper->newOperationContext(client2.get());
- auto cursor = rs->getCursor(opCtx.get());
- auto record = cursor->seekExact(id1);
- ASSERT_EQ(id1, record->id);
- ASSERT(!cursor->next());
- }
-
- w1.commit();
- }
-
- rs->waitForAllEarlierOplogWritesToBeVisible(harnessHelper->newOperationContext().get());
-
- { // now all 3 docs should be visible
- ServiceContext::UniqueOperationContext 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());
- }
-}
-
// Test that even when the oplog durability loop is paused, we can still advance the commit point as
// long as the commit for each insert comes before the next insert starts.
TEST(WiredTigerRecordStoreTest, OplogDurableVisibilityInOrder) {
@@ -597,25 +279,25 @@ TEST(WiredTigerRecordStoreTest, OplogDurableVisibilityInOrder) {
WTPausePrimaryOplogDurabilityLoop.setMode(FailPoint::alwaysOn);
unique_ptr<RecordStoreHarnessHelper> harnessHelper(newRecordStoreHarnessHelper());
- unique_ptr<RecordStore> rs(harnessHelper->newCappedRecordStore("local.oplog.foo", 100000, -1));
+ unique_ptr<RecordStore> rs(harnessHelper->newCappedRecordStore("local.oplog.rs", 100000, -1));
auto wtrs = checked_cast<WiredTigerRecordStore*>(rs.get());
{
ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
WriteUnitOfWork uow(opCtx.get());
RecordId id = _oplogOrderInsertOplog(opCtx.get(), rs, 1);
- ASSERT(wtrs->isCappedHidden(id));
+ ASSERT(wtrs->isOpHidden_forTest(id));
uow.commit();
- ASSERT(!wtrs->isCappedHidden(id));
+ ASSERT(wtrs->isOpHidden_forTest(id));
}
{
ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
WriteUnitOfWork uow(opCtx.get());
RecordId id = _oplogOrderInsertOplog(opCtx.get(), rs, 2);
- ASSERT(wtrs->isCappedHidden(id));
+ ASSERT(wtrs->isOpHidden_forTest(id));
uow.commit();
- ASSERT(!wtrs->isCappedHidden(id));
+ ASSERT(wtrs->isOpHidden_forTest(id));
}
}
@@ -626,14 +308,14 @@ TEST(WiredTigerRecordStoreTest, OplogDurableVisibilityOutOfOrder) {
WTPausePrimaryOplogDurabilityLoop.setMode(FailPoint::alwaysOn);
unique_ptr<RecordStoreHarnessHelper> harnessHelper(newRecordStoreHarnessHelper());
- unique_ptr<RecordStore> rs(harnessHelper->newCappedRecordStore("local.oplog.foo", 100000, -1));
+ unique_ptr<RecordStore> rs(harnessHelper->newCappedRecordStore("local.oplog.rs", 100000, -1));
auto wtrs = checked_cast<WiredTigerRecordStore*>(rs.get());
ServiceContext::UniqueOperationContext longLivedOp(harnessHelper->newOperationContext());
WriteUnitOfWork uow(longLivedOp.get());
RecordId id1 = _oplogOrderInsertOplog(longLivedOp.get(), rs, 1);
- ASSERT(wtrs->isCappedHidden(id1));
+ ASSERT(wtrs->isOpHidden_forTest(id1));
RecordId id2;
@@ -643,29 +325,29 @@ TEST(WiredTigerRecordStoreTest, OplogDurableVisibilityOutOfOrder) {
harnessHelper->newOperationContext(innerClient.get()));
WriteUnitOfWork uow(opCtx.get());
id2 = _oplogOrderInsertOplog(opCtx.get(), rs, 2);
- ASSERT(wtrs->isCappedHidden(id2));
+ ASSERT(wtrs->isOpHidden_forTest(id2));
uow.commit();
}
- ASSERT(wtrs->isCappedHidden(id1));
- ASSERT(wtrs->isCappedHidden(id2));
+ ASSERT(wtrs->isOpHidden_forTest(id1));
+ ASSERT(wtrs->isOpHidden_forTest(id2));
uow.commit();
- ASSERT(wtrs->isCappedHidden(id1));
- ASSERT(wtrs->isCappedHidden(id2));
+ ASSERT(wtrs->isOpHidden_forTest(id1));
+ ASSERT(wtrs->isOpHidden_forTest(id2));
// Wait a bit and check again to make sure they don't become visible automatically.
sleepsecs(1);
- ASSERT(wtrs->isCappedHidden(id1));
- ASSERT(wtrs->isCappedHidden(id2));
+ ASSERT(wtrs->isOpHidden_forTest(id1));
+ ASSERT(wtrs->isOpHidden_forTest(id2));
WTPausePrimaryOplogDurabilityLoop.setMode(FailPoint::off);
rs->waitForAllEarlierOplogWritesToBeVisible(longLivedOp.get());
- ASSERT(!wtrs->isCappedHidden(id1));
- ASSERT(!wtrs->isCappedHidden(id2));
+ ASSERT(!wtrs->isOpHidden_forTest(id1));
+ ASSERT(!wtrs->isOpHidden_forTest(id2));
}
TEST(WiredTigerRecordStoreTest, AppendCustomStatsMetadata) {
@@ -963,6 +645,9 @@ TEST(WiredTigerRecordStoreTest, OplogStones_CappedTruncateAfter) {
ASSERT_EQ(300, oplogStones->currentBytes());
}
+ // Make sure all are visible.
+ rs->waitForAllEarlierOplogWritesToBeVisible(harnessHelper->newOperationContext().get());
+
// Truncate data using an inclusive RecordId that exists inside the stone currently being
// filled.
{