summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Noma <gregory.noma@gmail.com>2021-02-23 11:15:51 -0500
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-02-23 19:13:50 +0000
commit8b9744aea1d1bde164d0b0fcf6d184ec5161013f (patch)
tree21ccc0716218f3c13f45b5e3848a04cabbb5cc41
parent326d18d539d19a38df09e77c188401eadf62a25e (diff)
downloadmongo-8b9744aea1d1bde164d0b0fcf6d184ec5161013f.tar.gz
SERVER-52833 Perform capped deletes during startup recovery on documents inserted earlier in startup recovery
-rw-r--r--jstests/noPassthrough/capped_deletes_within_rollback.js39
-rw-r--r--jstests/noPassthrough/capped_deletes_within_startup_recovery.js35
-rw-r--r--src/mongo/db/server_recovery.h2
-rw-r--r--src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_kv_engine_test.cpp16
-rw-r--r--src/mongo/db/storage/kv/durable_catalog_feature_tracker_test.cpp14
-rw-r--r--src/mongo/db/storage/kv/kv_engine_test_harness.cpp585
-rw-r--r--src/mongo/db/storage/kv/kv_engine_test_harness.h5
-rw-r--r--src/mongo/db/storage/kv/kv_engine_timestamps_test.cpp2
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine_test.cpp42
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp9
10 files changed, 442 insertions, 307 deletions
diff --git a/jstests/noPassthrough/capped_deletes_within_rollback.js b/jstests/noPassthrough/capped_deletes_within_rollback.js
new file mode 100644
index 00000000000..7cf8c3235f3
--- /dev/null
+++ b/jstests/noPassthrough/capped_deletes_within_rollback.js
@@ -0,0 +1,39 @@
+/**
+ * Tests that capped deletes occur during rollback on documents inserted earlier in rollback.
+ *
+ * @tags: [
+ * requires_replication,
+ * ]
+ */
+(function() {
+'use strict';
+
+load('jstests/replsets/libs/rollback_test.js');
+
+const rollbackTest = new RollbackTest(jsTestName());
+
+const testDB = function() {
+ return rollbackTest.getPrimary().getDB('test');
+};
+
+const coll = function() {
+ return testDB().getCollection(jsTestName());
+};
+
+assert.commandWorked(
+ testDB().createCollection(coll().getName(), {capped: true, size: 100, max: 1}));
+assert.commandWorked(coll().insert({a: 1}));
+
+rollbackTest.transitionToRollbackOperations();
+rollbackTest.transitionToSyncSourceOperationsBeforeRollback();
+
+assert.commandWorked(coll().insert([{b: 1}, {b: 2}]));
+
+rollbackTest.transitionToSyncSourceOperationsDuringRollback();
+rollbackTest.transitionToSteadyStateOperations();
+
+// Stopping the test fixture runs validate with {enforceFastCount: true}. This will cause collection
+// validation to fail if rollback did not perform capped deletes on documents that were inserted
+// earlier in rollback.
+rollbackTest.stop();
+})(); \ No newline at end of file
diff --git a/jstests/noPassthrough/capped_deletes_within_startup_recovery.js b/jstests/noPassthrough/capped_deletes_within_startup_recovery.js
new file mode 100644
index 00000000000..9087dfebe67
--- /dev/null
+++ b/jstests/noPassthrough/capped_deletes_within_startup_recovery.js
@@ -0,0 +1,35 @@
+/**
+ * Tests that capped deletes occur during statup recovery on documents inserted earlier in startup
+ * recovery.
+ *
+ * @tags: [
+ * requires_replication,
+ * ]
+ */
+(function() {
+'use strict';
+
+load('jstests/libs/fail_point_util.js');
+
+const replTest = new ReplSetTest({nodes: 1});
+replTest.startSet();
+replTest.initiate();
+
+const primary = replTest.getPrimary();
+const testDB = primary.getDB('test');
+const coll = testDB.getCollection(jsTestName());
+
+assert.commandWorked(testDB.createCollection(coll.getName(), {capped: true, size: 100, max: 1}));
+
+const ts = assert.commandWorked(testDB.runCommand({insert: coll.getName(), documents: [{a: 1}]}))
+ .operationTime;
+configureFailPoint(primary, 'holdStableTimestampAtSpecificTimestamp', {timestamp: ts});
+
+assert.commandWorked(coll.insert([{b: 1}, {b: 2}]));
+replTest.restart(primary);
+
+// Stopping the test fixture runs validate with {enforceFastCount: true}. This will cause collection
+// validation to fail if startup recovery did not perform capped deletes on documents that were
+// inserted earlier in startup recovery.
+replTest.stopSet();
+})(); \ No newline at end of file
diff --git a/src/mongo/db/server_recovery.h b/src/mongo/db/server_recovery.h
index 52f9858ce4d..2d6d64206fd 100644
--- a/src/mongo/db/server_recovery.h
+++ b/src/mongo/db/server_recovery.h
@@ -81,7 +81,7 @@ public:
private:
mutable Mutex _mutex = MONGO_MAKE_LATCH("SizeRecoveryState::_mutex");
- std::set<std::string> _collectionsAlwaysNeedingSizeAdjustment;
+ StringSet _collectionsAlwaysNeedingSizeAdjustment;
};
/**
diff --git a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_kv_engine_test.cpp b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_kv_engine_test.cpp
index 76c5c843ff9..9ba140533fd 100644
--- a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_kv_engine_test.cpp
+++ b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_kv_engine_test.cpp
@@ -44,13 +44,11 @@
namespace mongo {
namespace ephemeral_for_test {
-class KVHarnessHelper : public mongo::KVHarnessHelper, public ScopedGlobalServiceContextForTest {
+class KVHarnessHelper : public mongo::KVHarnessHelper {
public:
- KVHarnessHelper() {
- invariant(hasGlobalServiceContext());
- _engine = std::make_unique<KVEngine>();
+ KVHarnessHelper(ServiceContext* svcCtx) : _engine(std::make_unique<KVEngine>()) {
repl::ReplicationCoordinator::set(
- getGlobalServiceContext(),
+ svcCtx,
std::unique_ptr<repl::ReplicationCoordinator>(new repl::ReplicationCoordinatorMock(
getGlobalServiceContext(), repl::ReplSettings())));
}
@@ -67,17 +65,17 @@ private:
std::unique_ptr<KVEngine> _engine;
};
-std::unique_ptr<mongo::KVHarnessHelper> makeHelper() {
- return std::make_unique<KVHarnessHelper>();
+std::unique_ptr<mongo::KVHarnessHelper> makeHelper(ServiceContext* svcCtx) {
+ return std::make_unique<KVHarnessHelper>(svcCtx);
}
MONGO_INITIALIZER(RegisterEphemeralForTestKVHarnessFactory)(InitializerContext*) {
KVHarnessHelper::registerFactory(makeHelper);
}
-class EphemeralForTestKVEngineTest : public unittest::Test {
+class EphemeralForTestKVEngineTest : public ServiceContextTest {
public:
- EphemeralForTestKVEngineTest() : _helper(), _engine(_helper.getEngine()) {}
+ EphemeralForTestKVEngineTest() : _helper(getServiceContext()), _engine(_helper.getEngine()) {}
protected:
std::unique_ptr<KVHarnessHelper> helper;
diff --git a/src/mongo/db/storage/kv/durable_catalog_feature_tracker_test.cpp b/src/mongo/db/storage/kv/durable_catalog_feature_tracker_test.cpp
index d5a2594b37c..e7cdf744c35 100644
--- a/src/mongo/db/storage/kv/durable_catalog_feature_tracker_test.cpp
+++ b/src/mongo/db/storage/kv/durable_catalog_feature_tracker_test.cpp
@@ -34,6 +34,7 @@
#include <memory>
#include "mongo/db/operation_context_noop.h"
+#include "mongo/db/service_context_test_fixture.h"
#include "mongo/db/storage/durable_catalog_feature_tracker.h"
#include "mongo/db/storage/kv/kv_engine.h"
#include "mongo/db/storage/record_store.h"
@@ -47,7 +48,7 @@ using NonRepairableFeatureMask = DurableCatalogImpl::FeatureTracker::NonRepairab
using RepairableFeature = DurableCatalogImpl::FeatureTracker::RepairableFeature;
using RepairableFeatureMask = DurableCatalogImpl::FeatureTracker::RepairableFeatureMask;
-class DurableCatalogFeatureTrackerTest : public unittest::Test {
+class DurableCatalogFeatureTrackerTest : public ServiceContextTest {
public:
static const NonRepairableFeature kNonRepairableFeature1 =
static_cast<NonRepairableFeature>(1 << 0);
@@ -64,10 +65,15 @@ public:
static const RepairableFeature kRepairableFeature3 = static_cast<RepairableFeature>(1 << 2);
- DurableCatalogFeatureTrackerTest() : _helper(KVHarnessHelper::create()) {}
+ DurableCatalogFeatureTrackerTest() : _helper(KVHarnessHelper::create(getServiceContext())) {}
- std::unique_ptr<OperationContext> newOperationContext() {
- return std::make_unique<OperationContextNoop>(_helper->getEngine()->newRecoveryUnit());
+ ServiceContext::UniqueOperationContext newOperationContext() {
+ auto opCtx = makeOperationContext();
+ opCtx->setRecoveryUnit(
+ std::unique_ptr<RecoveryUnit>(_helper->getEngine()->newRecoveryUnit()),
+ WriteUnitOfWork::RecoveryUnitState::kNotInUnitOfWork);
+ opCtx->swapLockState(std::make_unique<LockerNoop>(), WithLock::withoutLock());
+ return opCtx;
}
void setUp() final {
diff --git a/src/mongo/db/storage/kv/kv_engine_test_harness.cpp b/src/mongo/db/storage/kv/kv_engine_test_harness.cpp
index 54e3c8a8e86..093bca82166 100644
--- a/src/mongo/db/storage/kv/kv_engine_test_harness.cpp
+++ b/src/mongo/db/storage/kv/kv_engine_test_harness.cpp
@@ -32,6 +32,7 @@
#include "mongo/db/catalog/collection_impl.h"
#include "mongo/db/index/index_descriptor.h"
#include "mongo/db/operation_context_noop.h"
+#include "mongo/db/service_context_test_fixture.h"
#include "mongo/db/storage/durable_catalog_impl.h"
#include "mongo/db/storage/kv/kv_engine.h"
#include "mongo/db/storage/record_store.h"
@@ -61,10 +62,10 @@ public:
ServiceContext::UniqueOperationContext _opCtx;
};
-class DurableCatalogImplTest : public unittest::Test {
+class DurableCatalogImplTest : public ServiceContextTest {
protected:
void setUp() override {
- helper = KVHarnessHelper::create();
+ helper = KVHarnessHelper::create(getServiceContext());
invariant(hasGlobalServiceContext());
}
@@ -115,56 +116,82 @@ protected:
namespace {
-std::function<std::unique_ptr<KVHarnessHelper>()> basicFactory =
- []() -> std::unique_ptr<KVHarnessHelper> { fassertFailed(40355); };
+std::function<std::unique_ptr<KVHarnessHelper>(ServiceContext*)> basicFactory =
+ [](ServiceContext*) -> std::unique_ptr<KVHarnessHelper> { fassertFailed(40355); };
-class MyOperationContext : public OperationContextNoop {
-public:
- MyOperationContext(KVEngine* engine) : OperationContextNoop(engine->newRecoveryUnit()) {}
+class KVEngineTestHarness : public ServiceContextTest {
+protected:
+ ServiceContext::UniqueOperationContext _makeOperationContext(KVEngine* engine) {
+ auto opCtx = makeOperationContext();
+ opCtx->setRecoveryUnit(std::unique_ptr<RecoveryUnit>(engine->newRecoveryUnit()),
+ WriteUnitOfWork::RecoveryUnitState::kNotInUnitOfWork);
+ opCtx->swapLockState(std::make_unique<LockerNoop>(), WithLock::withoutLock());
+ return opCtx;
+ }
+
+ std::vector<std::pair<ServiceContext::UniqueClient, ServiceContext::UniqueOperationContext>>
+ _makeOperationContexts(KVEngine* engine, unsigned num) {
+ std::vector<std::pair<ServiceContext::UniqueClient, ServiceContext::UniqueOperationContext>>
+ opCtxs;
+ opCtxs.reserve(num);
+
+ for (unsigned i = 0; i < num; ++i) {
+ auto client = getServiceContext()->makeClient(std::to_string(i));
+
+ auto opCtx = client->makeOperationContext();
+ opCtx->setRecoveryUnit(std::unique_ptr<RecoveryUnit>(engine->newRecoveryUnit()),
+ WriteUnitOfWork::RecoveryUnitState::kNotInUnitOfWork);
+ opCtx->swapLockState(std::make_unique<LockerNoop>(), WithLock::withoutLock());
+
+ opCtxs.emplace_back(std::move(client), std::move(opCtx));
+ }
+
+ return opCtxs;
+ }
};
const std::unique_ptr<ClockSource> clock = std::make_unique<ClockSourceMock>();
-TEST(KVEngineTestHarness, SimpleRS1) {
- std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create());
+TEST_F(KVEngineTestHarness, SimpleRS1) {
+ std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create(getServiceContext()));
KVEngine* engine = helper->getEngine();
ASSERT(engine);
std::string ns = "a.b";
std::unique_ptr<RecordStore> rs;
{
- MyOperationContext opCtx(engine);
- ASSERT_OK(engine->createRecordStore(&opCtx, ns, ns, CollectionOptions()));
- rs = engine->getRecordStore(&opCtx, ns, ns, CollectionOptions());
+ auto opCtx = _makeOperationContext(engine);
+ ASSERT_OK(engine->createRecordStore(opCtx.get(), ns, ns, CollectionOptions()));
+ rs = engine->getRecordStore(opCtx.get(), ns, ns, CollectionOptions());
ASSERT(rs);
}
RecordId loc;
{
- MyOperationContext opCtx(engine);
- WriteUnitOfWork uow(&opCtx);
- StatusWith<RecordId> res = rs->insertRecord(&opCtx, "abc", 4, Timestamp());
+ auto opCtx = _makeOperationContext(engine);
+ WriteUnitOfWork uow(opCtx.get());
+ StatusWith<RecordId> res = rs->insertRecord(opCtx.get(), "abc", 4, Timestamp());
ASSERT_OK(res.getStatus());
loc = res.getValue();
uow.commit();
}
{
- MyOperationContext opCtx(engine);
- ASSERT_EQUALS(std::string("abc"), rs->dataFor(&opCtx, loc).data());
+ auto opCtx = _makeOperationContext(engine);
+ ASSERT_EQUALS(std::string("abc"), rs->dataFor(opCtx.get(), loc).data());
}
{
- MyOperationContext opCtx(engine);
- std::vector<std::string> all = engine->getAllIdents(&opCtx);
+ auto opCtx = _makeOperationContext(engine);
+ std::vector<std::string> all = engine->getAllIdents(opCtx.get());
ASSERT_EQUALS(1U, all.size());
ASSERT_EQUALS(ns, all[0]);
}
}
-TEST(KVEngineTestHarness, Restart1) {
- std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create());
+TEST_F(KVEngineTestHarness, Restart1) {
+ std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create(getServiceContext()));
KVEngine* engine = helper->getEngine();
ASSERT(engine);
@@ -175,24 +202,24 @@ TEST(KVEngineTestHarness, Restart1) {
{
std::unique_ptr<RecordStore> rs;
{
- MyOperationContext opCtx(engine);
- ASSERT_OK(engine->createRecordStore(&opCtx, ns, ns, CollectionOptions()));
- rs = engine->getRecordStore(&opCtx, ns, ns, CollectionOptions());
+ auto opCtx = _makeOperationContext(engine);
+ ASSERT_OK(engine->createRecordStore(opCtx.get(), ns, ns, CollectionOptions()));
+ rs = engine->getRecordStore(opCtx.get(), ns, ns, CollectionOptions());
ASSERT(rs);
}
{
- MyOperationContext opCtx(engine);
- WriteUnitOfWork uow(&opCtx);
- StatusWith<RecordId> res = rs->insertRecord(&opCtx, "abc", 4, Timestamp());
+ auto opCtx = _makeOperationContext(engine);
+ WriteUnitOfWork uow(opCtx.get());
+ StatusWith<RecordId> res = rs->insertRecord(opCtx.get(), "abc", 4, Timestamp());
ASSERT_OK(res.getStatus());
loc = res.getValue();
uow.commit();
}
{
- MyOperationContext opCtx(engine);
- ASSERT_EQUALS(std::string("abc"), rs->dataFor(&opCtx, loc).data());
+ auto opCtx = _makeOperationContext(engine);
+ ASSERT_EQUALS(std::string("abc"), rs->dataFor(opCtx.get(), loc).data());
}
}
@@ -200,15 +227,15 @@ TEST(KVEngineTestHarness, Restart1) {
{
std::unique_ptr<RecordStore> rs;
- MyOperationContext opCtx(engine);
- rs = engine->getRecordStore(&opCtx, ns, ns, CollectionOptions());
- ASSERT_EQUALS(std::string("abc"), rs->dataFor(&opCtx, loc).data());
+ auto opCtx = _makeOperationContext(engine);
+ rs = engine->getRecordStore(opCtx.get(), ns, ns, CollectionOptions());
+ ASSERT_EQUALS(std::string("abc"), rs->dataFor(opCtx.get(), loc).data());
}
}
-TEST(KVEngineTestHarness, SimpleSorted1) {
- std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create());
+TEST_F(KVEngineTestHarness, SimpleSorted1) {
+ std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create(getServiceContext()));
KVEngine* engine = helper->getEngine();
ASSERT(engine);
@@ -217,20 +244,21 @@ TEST(KVEngineTestHarness, SimpleSorted1) {
std::unique_ptr<RecordStore> rs;
{
- MyOperationContext opCtx(engine);
- WriteUnitOfWork uow(&opCtx);
- ASSERT_OK(engine->createRecordStore(&opCtx, "catalog", "catalog", CollectionOptions()));
- rs = engine->getRecordStore(&opCtx, "catalog", "catalog", CollectionOptions());
+ auto opCtx = _makeOperationContext(engine);
+ WriteUnitOfWork uow(opCtx.get());
+ ASSERT_OK(
+ engine->createRecordStore(opCtx.get(), "catalog", "catalog", CollectionOptions()));
+ rs = engine->getRecordStore(opCtx.get(), "catalog", "catalog", CollectionOptions());
uow.commit();
}
std::unique_ptr<Collection> collection;
{
- MyOperationContext opCtx(engine);
- WriteUnitOfWork uow(&opCtx);
- collection =
- std::make_unique<CollectionImpl>(&opCtx, ns, RecordId(0), UUID::gen(), std::move(rs));
+ auto opCtx = _makeOperationContext(engine);
+ WriteUnitOfWork uow(opCtx.get());
+ collection = std::make_unique<CollectionImpl>(
+ opCtx.get(), ns, RecordId(0), UUID::gen(), std::move(rs));
uow.commit();
}
@@ -239,86 +267,89 @@ TEST(KVEngineTestHarness, SimpleSorted1) {
<< BSON("a" << 1)));
std::unique_ptr<SortedDataInterface> sorted;
{
- MyOperationContext opCtx(engine);
- ASSERT_OK(engine->createSortedDataInterface(&opCtx, CollectionOptions(), ident, &desc));
- sorted = engine->getSortedDataInterface(&opCtx, CollectionOptions(), ident, &desc);
+ auto opCtx = _makeOperationContext(engine);
+ ASSERT_OK(
+ engine->createSortedDataInterface(opCtx.get(), CollectionOptions(), ident, &desc));
+ sorted = engine->getSortedDataInterface(opCtx.get(), CollectionOptions(), ident, &desc);
ASSERT(sorted);
}
{
- MyOperationContext opCtx(engine);
- WriteUnitOfWork uow(&opCtx);
+ auto opCtx = _makeOperationContext(engine);
+ WriteUnitOfWork uow(opCtx.get());
const RecordId recordId(6, 4);
const KeyString::Value keyString =
KeyString::HeapBuilder(
sorted->getKeyStringVersion(), BSON("" << 5), sorted->getOrdering(), recordId)
.release();
- ASSERT_OK(sorted->insert(&opCtx, keyString, true));
+ ASSERT_OK(sorted->insert(opCtx.get(), keyString, true));
uow.commit();
}
{
- MyOperationContext opCtx(engine);
- ASSERT_EQUALS(1, sorted->numEntries(&opCtx));
+ auto opCtx = _makeOperationContext(engine);
+ ASSERT_EQUALS(1, sorted->numEntries(opCtx.get()));
}
}
-TEST(KVEngineTestHarness, TemporaryRecordStoreSimple) {
- std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create());
+TEST_F(KVEngineTestHarness, TemporaryRecordStoreSimple) {
+ std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create(getServiceContext()));
KVEngine* engine = helper->getEngine();
ASSERT(engine);
std::string ident = "temptemp";
std::unique_ptr<RecordStore> rs;
{
- MyOperationContext opCtx(engine);
- rs = engine->makeTemporaryRecordStore(&opCtx, ident);
+ auto opCtx = _makeOperationContext(engine);
+ rs = engine->makeTemporaryRecordStore(opCtx.get(), ident);
ASSERT(rs);
}
RecordId loc;
{
- MyOperationContext opCtx(engine);
- WriteUnitOfWork uow(&opCtx);
- StatusWith<RecordId> res = rs->insertRecord(&opCtx, "abc", 4, Timestamp());
+ auto opCtx = _makeOperationContext(engine);
+ WriteUnitOfWork uow(opCtx.get());
+ StatusWith<RecordId> res = rs->insertRecord(opCtx.get(), "abc", 4, Timestamp());
ASSERT_OK(res.getStatus());
loc = res.getValue();
uow.commit();
}
{
- MyOperationContext opCtx(engine);
- ASSERT_EQUALS(std::string("abc"), rs->dataFor(&opCtx, loc).data());
+ auto opCtx = _makeOperationContext(engine);
+ ASSERT_EQUALS(std::string("abc"), rs->dataFor(opCtx.get(), loc).data());
- std::vector<std::string> all = engine->getAllIdents(&opCtx);
+ std::vector<std::string> all = engine->getAllIdents(opCtx.get());
ASSERT_EQUALS(1U, all.size());
ASSERT_EQUALS(ident, all[0]);
- WriteUnitOfWork wuow(&opCtx);
- ASSERT_OK(engine->dropIdent(opCtx.recoveryUnit(), ident));
+ WriteUnitOfWork wuow(opCtx.get());
+ ASSERT_OK(engine->dropIdent(opCtx->recoveryUnit(), ident));
wuow.commit();
}
}
-TEST(KVEngineTestHarness, AllDurableTimestamp) {
- std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create());
+TEST_F(KVEngineTestHarness, AllDurableTimestamp) {
+ std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create(getServiceContext()));
KVEngine* engine = helper->getEngine();
std::unique_ptr<RecordStore> rs;
{
- MyOperationContext opCtx(engine);
- WriteUnitOfWork uow(&opCtx);
+ auto opCtx = _makeOperationContext(engine);
+ WriteUnitOfWork uow(opCtx.get());
CollectionOptions options;
options.capped = true;
options.cappedSize = 10240;
options.cappedMaxDocs = -1;
NamespaceString oplogNss("local.oplog.rs");
- ASSERT_OK(engine->createRecordStore(&opCtx, oplogNss.ns(), "ident", options));
- rs = engine->getRecordStore(&opCtx, oplogNss.ns(), "ident", options);
+ ASSERT_OK(engine->createRecordStore(opCtx.get(), oplogNss.ns(), "ident", options));
+ rs = engine->getRecordStore(opCtx.get(), oplogNss.ns(), "ident", options);
ASSERT(rs);
}
{
+ auto opCtxs = _makeOperationContexts(engine, 2);
+
Timestamp t11(1, 1);
Timestamp t12(1, 2);
Timestamp t21(2, 1);
@@ -328,10 +359,10 @@ TEST(KVEngineTestHarness, AllDurableTimestamp) {
auto t21Doc = BSON("ts" << t21);
Timestamp allDurable = engine->getAllDurableTimestamp();
- MyOperationContext opCtx1(engine);
- WriteUnitOfWork uow1(&opCtx1);
+ auto opCtx1 = opCtxs[0].second.get();
+ WriteUnitOfWork uow1(opCtx1);
ASSERT_EQ(invariant(rs->insertRecord(
- &opCtx1, t11Doc.objdata(), t11Doc.objsize(), Timestamp::min())),
+ opCtx1, t11Doc.objdata(), t11Doc.objsize(), Timestamp::min())),
RecordId(1, 1));
Timestamp lastAllDurable = allDurable;
@@ -339,10 +370,10 @@ TEST(KVEngineTestHarness, AllDurableTimestamp) {
ASSERT_GTE(allDurable, lastAllDurable);
ASSERT_LT(allDurable, t11);
- MyOperationContext opCtx2(engine);
- WriteUnitOfWork uow2(&opCtx2);
+ auto opCtx2 = opCtxs[1].second.get();
+ WriteUnitOfWork uow2(opCtx2);
ASSERT_EQ(invariant(rs->insertRecord(
- &opCtx2, t21Doc.objdata(), t21Doc.objsize(), Timestamp::min())),
+ opCtx2, t21Doc.objdata(), t21Doc.objsize(), Timestamp::min())),
RecordId(2, 1));
uow2.commit();
@@ -352,7 +383,7 @@ TEST(KVEngineTestHarness, AllDurableTimestamp) {
ASSERT_LT(allDurable, t11);
ASSERT_EQ(invariant(rs->insertRecord(
- &opCtx1, t12Doc.objdata(), t12Doc.objsize(), Timestamp::min())),
+ opCtx1, t12Doc.objdata(), t12Doc.objsize(), Timestamp::min())),
RecordId(1, 2));
lastAllDurable = allDurable;
@@ -387,8 +418,8 @@ TEST(KVEngineTestHarness, AllDurableTimestamp) {
* | Rollback | |
* | | Rollback |
*/
-TEST(KVEngineTestHarness, PinningOldestWithAnotherSession) {
- std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create());
+TEST_F(KVEngineTestHarness, PinningOldestWithAnotherSession) {
+ std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create(getServiceContext()));
KVEngine* engine = helper->getEngine();
// TODO SERVER-48314: Remove after implementing correct behavior on biggie.
if (engine->isEphemeral())
@@ -397,42 +428,44 @@ TEST(KVEngineTestHarness, PinningOldestWithAnotherSession) {
std::string ns = "a.b";
std::unique_ptr<RecordStore> rs;
{
- MyOperationContext opCtx(engine);
- ASSERT_OK(engine->createRecordStore(&opCtx, ns, ns, CollectionOptions()));
- rs = engine->getRecordStore(&opCtx, ns, ns, CollectionOptions());
+ auto opCtx = _makeOperationContext(engine);
+ ASSERT_OK(engine->createRecordStore(opCtx.get(), ns, ns, CollectionOptions()));
+ rs = engine->getRecordStore(opCtx.get(), ns, ns, CollectionOptions());
ASSERT(rs);
}
- MyOperationContext opCtx1(engine);
- WriteUnitOfWork uow1(&opCtx1);
- StatusWith<RecordId> res = rs->insertRecord(&opCtx1, "abc", 4, Timestamp(10, 10));
+ auto opCtxs = _makeOperationContexts(engine, 2);
+
+ auto opCtx1 = opCtxs[0].second.get();
+ WriteUnitOfWork uow1(opCtx1);
+ StatusWith<RecordId> res = rs->insertRecord(opCtx1, "abc", 4, Timestamp(10, 10));
RecordId rid = res.getValue();
uow1.commit();
RecordData rd;
- opCtx1.recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kProvided,
- Timestamp(15, 15));
+ opCtx1->recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kProvided,
+ Timestamp(15, 15));
- MyOperationContext opCtx2(engine);
- WriteUnitOfWork uow2(&opCtx2);
+ auto opCtx2 = opCtxs[1].second.get();
+ WriteUnitOfWork uow2(opCtx2);
- ASSERT(rs->findRecord(&opCtx1, rid, &rd));
- ASSERT_OK(opCtx2.recoveryUnit()->setTimestamp(Timestamp(20, 20)));
- ASSERT_OK(rs->updateRecord(&opCtx2, rid, "updated", 8));
+ ASSERT(rs->findRecord(opCtx1, rid, &rd));
+ ASSERT_OK(opCtx2->recoveryUnit()->setTimestamp(Timestamp(20, 20)));
+ ASSERT_OK(rs->updateRecord(opCtx2, rid, "updated", 8));
- ASSERT(rs->findRecord(&opCtx1, rid, &rd));
+ ASSERT(rs->findRecord(opCtx1, rid, &rd));
ASSERT_EQUALS(std::string("abc"), rd.data());
uow2.commit();
- opCtx1.recoveryUnit()->abandonSnapshot();
- ASSERT(rs->findRecord(&opCtx1, rid, &rd));
+ opCtx1->recoveryUnit()->abandonSnapshot();
+ ASSERT(rs->findRecord(opCtx1, rid, &rd));
ASSERT_EQUALS(std::string("abc"), rd.data());
- opCtx2.recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kProvided,
- Timestamp(15, 15));
- ASSERT(rs->findRecord(&opCtx2, rid, &rd));
+ opCtx2->recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kProvided,
+ Timestamp(15, 15));
+ ASSERT(rs->findRecord(opCtx2, rid, &rd));
ASSERT_EQUALS(std::string("abc"), rd.data());
}
@@ -456,29 +489,31 @@ TEST(KVEngineTestHarness, PinningOldestWithAnotherSession) {
* | Timestamp :commit 25 | | |
* | | | QueryTimestamp :all_durable (30) |
*/
-TEST(KVEngineTestHarness, AllDurable) {
- std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create());
+TEST_F(KVEngineTestHarness, AllDurable) {
+ std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create(getServiceContext()));
KVEngine* engine = helper->getEngine();
std::string ns = "a.b";
std::unique_ptr<RecordStore> rs;
{
- MyOperationContext opCtx(engine);
- ASSERT_OK(engine->createRecordStore(&opCtx, ns, ns, CollectionOptions()));
- rs = engine->getRecordStore(&opCtx, ns, ns, CollectionOptions());
+ auto opCtx = _makeOperationContext(engine);
+ ASSERT_OK(engine->createRecordStore(opCtx.get(), ns, ns, CollectionOptions()));
+ rs = engine->getRecordStore(opCtx.get(), ns, ns, CollectionOptions());
ASSERT(rs);
}
{
+ auto opCtxs = _makeOperationContexts(engine, 4);
+
const Timestamp kInsertTimestamp1 = Timestamp(10, 10);
const Timestamp kInsertTimestamp2 = Timestamp(20, 20);
const Timestamp kInsertTimestamp3 = Timestamp(30, 30);
const Timestamp kInsertTimestamp4 = Timestamp(25, 25);
Timestamp allDurable = engine->getAllDurableTimestamp();
- MyOperationContext opCtx1(engine);
- WriteUnitOfWork uow1(&opCtx1);
- auto swRid = rs->insertRecord(&opCtx1, "abc", 4, kInsertTimestamp1);
+ auto opCtx1 = opCtxs[0].second.get();
+ WriteUnitOfWork uow1(opCtx1);
+ auto swRid = rs->insertRecord(opCtx1, "abc", 4, kInsertTimestamp1);
ASSERT_OK(swRid);
uow1.commit();
@@ -487,9 +522,9 @@ TEST(KVEngineTestHarness, AllDurable) {
ASSERT_GTE(allDurable, lastAllDurable);
ASSERT_LTE(allDurable, kInsertTimestamp1);
- MyOperationContext opCtx2(engine);
- WriteUnitOfWork uow2(&opCtx2);
- swRid = rs->insertRecord(&opCtx2, "abc", 4, kInsertTimestamp2);
+ auto opCtx2 = opCtxs[1].second.get();
+ WriteUnitOfWork uow2(opCtx2);
+ swRid = rs->insertRecord(opCtx2, "abc", 4, kInsertTimestamp2);
ASSERT_OK(swRid);
lastAllDurable = allDurable;
@@ -497,9 +532,9 @@ TEST(KVEngineTestHarness, AllDurable) {
ASSERT_GTE(allDurable, lastAllDurable);
ASSERT_LT(allDurable, kInsertTimestamp2);
- MyOperationContext opCtx3(engine);
- WriteUnitOfWork uow3(&opCtx3);
- swRid = rs->insertRecord(&opCtx3, "abc", 4, kInsertTimestamp3);
+ auto opCtx3 = opCtxs[2].second.get();
+ WriteUnitOfWork uow3(opCtx3);
+ swRid = rs->insertRecord(opCtx3, "abc", 4, kInsertTimestamp3);
ASSERT_OK(swRid);
uow3.commit();
@@ -515,9 +550,9 @@ TEST(KVEngineTestHarness, AllDurable) {
ASSERT_GTE(allDurable, lastAllDurable);
ASSERT_LTE(allDurable, kInsertTimestamp3);
- MyOperationContext opCtx4(engine);
- WriteUnitOfWork uow4(&opCtx4);
- swRid = rs->insertRecord(&opCtx4, "abc", 4, kInsertTimestamp4);
+ auto opCtx4 = opCtxs[3].second.get();
+ WriteUnitOfWork uow4(opCtx4);
+ swRid = rs->insertRecord(opCtx4, "abc", 4, kInsertTimestamp4);
ASSERT_OK(swRid);
lastAllDurable = allDurable;
@@ -543,8 +578,8 @@ TEST(KVEngineTestHarness, AllDurable) {
* | Begin :readAt 10 |
* | Read A (1) |
*/
-TEST(KVEngineTestHarness, BasicTimestampSingle) {
- std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create());
+TEST_F(KVEngineTestHarness, BasicTimestampSingle) {
+ std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create(getServiceContext()));
KVEngine* engine = helper->getEngine();
// TODO SERVER-48314: Remove after implementing correct behavior on biggie.
if (engine->isEphemeral())
@@ -553,28 +588,30 @@ TEST(KVEngineTestHarness, BasicTimestampSingle) {
std::string ns = "a.b";
std::unique_ptr<RecordStore> rs;
{
- MyOperationContext opCtx(engine);
- ASSERT_OK(engine->createRecordStore(&opCtx, ns, ns, CollectionOptions()));
- rs = engine->getRecordStore(&opCtx, ns, ns, CollectionOptions());
+ auto opCtx = _makeOperationContext(engine);
+ ASSERT_OK(engine->createRecordStore(opCtx.get(), ns, ns, CollectionOptions()));
+ rs = engine->getRecordStore(opCtx.get(), ns, ns, CollectionOptions());
ASSERT(rs);
}
const Timestamp kReadTimestamp = Timestamp(9, 9);
const Timestamp kInsertTimestamp = Timestamp(10, 10);
+ auto opCtxs = _makeOperationContexts(engine, 2);
+
// Start a read transaction.
- MyOperationContext opCtx1(engine);
+ auto opCtx1 = opCtxs[0].second.get();
- opCtx1.recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kProvided,
- kReadTimestamp);
- ASSERT(!rs->findRecord(&opCtx1, RecordId::minLong(), nullptr));
+ opCtx1->recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kProvided,
+ kReadTimestamp);
+ ASSERT(!rs->findRecord(opCtx1, RecordId::minLong(), nullptr));
// Insert a record at a later time.
RecordId rid;
{
- MyOperationContext opCtx2(engine);
- WriteUnitOfWork wuow(&opCtx2);
- auto swRid = rs->insertRecord(&opCtx2, "abc", 4, kInsertTimestamp);
+ auto opCtx2 = opCtxs[1].second.get();
+ WriteUnitOfWork wuow(opCtx2);
+ auto swRid = rs->insertRecord(opCtx2, "abc", 4, kInsertTimestamp);
ASSERT_OK(swRid);
rid = swRid.getValue();
wuow.commit();
@@ -582,16 +619,16 @@ TEST(KVEngineTestHarness, BasicTimestampSingle) {
// Should not see the record, even if we abandon the snapshot as the read timestamp is still
// earlier than the insert timestamp.
- ASSERT(!rs->findRecord(&opCtx1, rid, nullptr));
- opCtx1.recoveryUnit()->abandonSnapshot();
- ASSERT(!rs->findRecord(&opCtx1, rid, nullptr));
+ ASSERT(!rs->findRecord(opCtx1, rid, nullptr));
+ opCtx1->recoveryUnit()->abandonSnapshot();
+ ASSERT(!rs->findRecord(opCtx1, rid, nullptr));
- opCtx1.recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kProvided,
- kInsertTimestamp);
- opCtx1.recoveryUnit()->abandonSnapshot();
+ opCtx1->recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kProvided,
+ kInsertTimestamp);
+ opCtx1->recoveryUnit()->abandonSnapshot();
RecordData rd;
- ASSERT(rs->findRecord(&opCtx1, rid, &rd));
+ ASSERT(rs->findRecord(opCtx1, rid, &rd));
ASSERT_EQ(std::string("abc"), rd.data());
}
@@ -613,8 +650,8 @@ TEST(KVEngineTestHarness, BasicTimestampSingle) {
* | Begin :readAt 20 |
* | Read A (2) |
*/
-TEST(KVEngineTestHarness, BasicTimestampMultiple) {
- std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create());
+TEST_F(KVEngineTestHarness, BasicTimestampMultiple) {
+ std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create(getServiceContext()));
KVEngine* engine = helper->getEngine();
// TODO SERVER-48314: Remove after implementing correct behavior on biggie.
if (engine->isEphemeral())
@@ -623,9 +660,9 @@ TEST(KVEngineTestHarness, BasicTimestampMultiple) {
std::string ns = "a.b";
std::unique_ptr<RecordStore> rs;
{
- MyOperationContext opCtx(engine);
- ASSERT_OK(engine->createRecordStore(&opCtx, ns, ns, CollectionOptions()));
- rs = engine->getRecordStore(&opCtx, ns, ns, CollectionOptions());
+ auto opCtx = _makeOperationContext(engine);
+ ASSERT_OK(engine->createRecordStore(opCtx.get(), ns, ns, CollectionOptions()));
+ rs = engine->getRecordStore(opCtx.get(), ns, ns, CollectionOptions());
ASSERT(rs);
}
@@ -635,28 +672,28 @@ TEST(KVEngineTestHarness, BasicTimestampMultiple) {
RecordId rid;
{
// Initial insert of record.
- MyOperationContext opCtx(engine);
- WriteUnitOfWork wuow(&opCtx);
- auto swRid = rs->insertRecord(&opCtx, "abc", 4, t10);
+ auto opCtx = _makeOperationContext(engine);
+ WriteUnitOfWork wuow(opCtx.get());
+ auto swRid = rs->insertRecord(opCtx.get(), "abc", 4, t10);
ASSERT_OK(swRid);
rid = swRid.getValue();
// Update a record at a later time.
- ASSERT_OK(opCtx.recoveryUnit()->setTimestamp(t20));
- auto res = rs->updateRecord(&opCtx, rid, "updated", 8);
+ ASSERT_OK(opCtx->recoveryUnit()->setTimestamp(t20));
+ auto res = rs->updateRecord(opCtx.get(), rid, "updated", 8);
ASSERT_OK(res);
wuow.commit();
}
RecordData rd;
- MyOperationContext opCtx(engine);
- opCtx.recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kProvided, t10);
- ASSERT(rs->findRecord(&opCtx, rid, &rd));
+ auto opCtx = _makeOperationContext(engine);
+ opCtx->recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kProvided, t10);
+ ASSERT(rs->findRecord(opCtx.get(), rid, &rd));
ASSERT_EQUALS(std::string("abc"), rd.data());
- opCtx.recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kProvided, t20);
- opCtx.recoveryUnit()->abandonSnapshot();
- ASSERT(rs->findRecord(&opCtx, rid, &rd));
+ opCtx->recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kProvided, t20);
+ opCtx->recoveryUnit()->abandonSnapshot();
+ ASSERT(rs->findRecord(opCtx.get(), rid, &rd));
ASSERT_EQUALS(std::string("updated"), rd.data());
}
@@ -672,8 +709,8 @@ TEST(KVEngineTestHarness, BasicTimestampMultiple) {
* | | Abandon Snapshot |
* | | Read A (1) |
*/
-TEST(KVEngineTestHarness, SingleReadWithConflict) {
- std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create());
+TEST_F(KVEngineTestHarness, SingleReadWithConflict) {
+ std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create(getServiceContext()));
KVEngine* engine = helper->getEngine();
// TODO SERVER-48314: Remove after implementing correct behavior on biggie.
if (engine->isEphemeral())
@@ -682,35 +719,37 @@ TEST(KVEngineTestHarness, SingleReadWithConflict) {
std::string ns = "a.b";
std::unique_ptr<RecordStore> rs;
{
- MyOperationContext opCtx(engine);
- ASSERT_OK(engine->createRecordStore(&opCtx, ns, ns, CollectionOptions()));
- rs = engine->getRecordStore(&opCtx, ns, ns, CollectionOptions());
+ auto opCtx = _makeOperationContext(engine);
+ ASSERT_OK(engine->createRecordStore(opCtx.get(), ns, ns, CollectionOptions()));
+ rs = engine->getRecordStore(opCtx.get(), ns, ns, CollectionOptions());
ASSERT(rs);
}
- MyOperationContext opCtx2(engine);
- opCtx2.recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kProvided,
- Timestamp(20, 20));
+ auto opCtxs = _makeOperationContexts(engine, 2);
+
+ auto opCtx2 = opCtxs[1].second.get();
+ opCtx2->recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kProvided,
+ Timestamp(20, 20));
- MyOperationContext opCtx1(engine);
- WriteUnitOfWork uow1(&opCtx1);
- StatusWith<RecordId> res = rs->insertRecord(&opCtx1, "abc", 4, Timestamp(10, 10));
+ auto opCtx1 = opCtxs[0].second.get();
+ WriteUnitOfWork uow1(opCtx1);
+ StatusWith<RecordId> res = rs->insertRecord(opCtx1, "abc", 4, Timestamp(10, 10));
ASSERT_OK(res);
RecordId loc = res.getValue();
// Cannot find record before commit.
RecordData rd;
- ASSERT(!rs->findRecord(&opCtx2, loc, &rd));
+ ASSERT(!rs->findRecord(opCtx2, loc, &rd));
// Cannot find record after commit due to snapshot isolation.
uow1.commit();
- ASSERT(!rs->findRecord(&opCtx2, loc, &rd));
+ ASSERT(!rs->findRecord(opCtx2, loc, &rd));
// Abandon snapshot for visibility.
- opCtx2.recoveryUnit()->abandonSnapshot();
+ opCtx2->recoveryUnit()->abandonSnapshot();
- ASSERT(rs->findRecord(&opCtx2, loc, &rd));
- ASSERT_EQUALS(std::string("abc"), rs->dataFor(&opCtx2, loc).data());
+ ASSERT(rs->findRecord(opCtx2, loc, &rd));
+ ASSERT_EQUALS(std::string("abc"), rs->dataFor(opCtx2, loc).data());
}
/*
@@ -725,8 +764,8 @@ TEST(KVEngineTestHarness, SingleReadWithConflict) {
* | Read A (NOT_FOUND) |
* | Write A 1 (NOT_FOUND)|
*/
-DEATH_TEST_REGEX(KVEngineTestHarness, SnapshotHidesVisibility, ".*item not found.*") {
- std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create());
+DEATH_TEST_REGEX_F(KVEngineTestHarness, SnapshotHidesVisibility, ".*item not found.*") {
+ std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create(getServiceContext()));
KVEngine* engine = helper->getEngine();
// TODO: Remove after implementing correct behavior on biggie.
if (engine->isEphemeral())
@@ -735,29 +774,31 @@ DEATH_TEST_REGEX(KVEngineTestHarness, SnapshotHidesVisibility, ".*item not found
std::string ns = "a.b";
std::unique_ptr<RecordStore> rs;
{
- MyOperationContext opCtx(engine);
- ASSERT_OK(engine->createRecordStore(&opCtx, ns, ns, CollectionOptions()));
- rs = engine->getRecordStore(&opCtx, ns, ns, CollectionOptions());
+ auto opCtx = _makeOperationContext(engine);
+ ASSERT_OK(engine->createRecordStore(opCtx.get(), ns, ns, CollectionOptions()));
+ rs = engine->getRecordStore(opCtx.get(), ns, ns, CollectionOptions());
ASSERT(rs);
}
- MyOperationContext opCtx1(engine);
- WriteUnitOfWork uow1(&opCtx1);
- StatusWith<RecordId> res = rs->insertRecord(&opCtx1, "abc", 4, Timestamp(10, 10));
+ auto opCtxs = _makeOperationContexts(engine, 2);
+
+ auto opCtx1 = opCtxs[0].second.get();
+ WriteUnitOfWork uow1(opCtx1);
+ StatusWith<RecordId> res = rs->insertRecord(opCtx1, "abc", 4, Timestamp(10, 10));
ASSERT_OK(res);
RecordId loc = res.getValue();
uow1.commit();
// Snapshot was taken before the insert and will not find the record even after the commit.
RecordData rd;
- MyOperationContext opCtx2(engine);
- opCtx2.recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kProvided,
- Timestamp(9, 9));
- ASSERT(!rs->findRecord(&opCtx2, loc, &rd));
+ auto opCtx2 = opCtxs[1].second.get();
+ opCtx2->recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kProvided,
+ Timestamp(9, 9));
+ ASSERT(!rs->findRecord(opCtx2, loc, &rd));
// Trying to write in an outdated snapshot will cause item not found.
- WriteUnitOfWork uow2(&opCtx2);
- auto swRid = rs->updateRecord(&opCtx2, loc, "updated", 8);
+ WriteUnitOfWork uow2(opCtx2);
+ auto swRid = rs->updateRecord(opCtx2, loc, "updated", 8);
uow2.commit();
}
@@ -780,8 +821,8 @@ DEATH_TEST_REGEX(KVEngineTestHarness, SnapshotHidesVisibility, ".*item not found
* | Read A (1) |
* | Read Oplog (FOUND) |
*/
-TEST(KVEngineTestHarness, SingleReadWithConflictWithOplog) {
- std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create());
+TEST_F(KVEngineTestHarness, SingleReadWithConflictWithOplog) {
+ std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create(getServiceContext()));
KVEngine* engine = helper->getEngine();
// TODO SERVER-48314: Remove after implementing correct behavior on biggie.
if (engine->isEphemeral())
@@ -791,9 +832,9 @@ TEST(KVEngineTestHarness, SingleReadWithConflictWithOplog) {
std::unique_ptr<RecordStore> collectionRs;
std::unique_ptr<RecordStore> oplogRs;
{
- MyOperationContext opCtx(engine);
- ASSERT_OK(engine->createRecordStore(&opCtx, ns, ns, CollectionOptions()));
- collectionRs = engine->getRecordStore(&opCtx, ns, ns, CollectionOptions());
+ auto opCtx = _makeOperationContext(engine);
+ ASSERT_OK(engine->createRecordStore(opCtx.get(), ns, ns, CollectionOptions()));
+ collectionRs = engine->getRecordStore(opCtx.get(), ns, ns, CollectionOptions());
ASSERT(collectionRs);
CollectionOptions options;
@@ -802,8 +843,8 @@ TEST(KVEngineTestHarness, SingleReadWithConflictWithOplog) {
options.cappedMaxDocs = -1;
NamespaceString oplogNss("local.oplog.rs");
- ASSERT_OK(engine->createRecordStore(&opCtx, oplogNss.ns(), "ident", options));
- oplogRs = engine->getRecordStore(&opCtx, oplogNss.ns(), "ident", options);
+ ASSERT_OK(engine->createRecordStore(opCtx.get(), oplogNss.ns(), "ident", options));
+ oplogRs = engine->getRecordStore(opCtx.get(), oplogNss.ns(), "ident", options);
ASSERT(oplogRs);
}
@@ -813,11 +854,11 @@ TEST(KVEngineTestHarness, SingleReadWithConflictWithOplog) {
const Timestamp t9(9, 9);
const Timestamp t10(10, 10);
{
- MyOperationContext opCtx(engine);
- WriteUnitOfWork uow(&opCtx);
+ auto opCtx = _makeOperationContext(engine);
+ WriteUnitOfWork uow(opCtx.get());
// Insert into collectionRs.
- StatusWith<RecordId> res = collectionRs->insertRecord(&opCtx, "abc", 4, t10);
+ StatusWith<RecordId> res = collectionRs->insertRecord(opCtx.get(), "abc", 4, t10);
ASSERT_OK(res);
locCollection = res.getValue();
@@ -825,21 +866,21 @@ TEST(KVEngineTestHarness, SingleReadWithConflictWithOplog) {
auto t11Doc = BSON("ts" << t10);
ASSERT_EQ(invariant(oplogRs->insertRecord(
- &opCtx, t11Doc.objdata(), t11Doc.objsize(), Timestamp::min())),
+ opCtx.get(), t11Doc.objdata(), t11Doc.objsize(), Timestamp::min())),
RecordId(10, 10));
locOplog = RecordId(10, 10);
uow.commit();
}
- MyOperationContext opCtx(engine);
- opCtx.recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kProvided, t9);
- ASSERT(!collectionRs->findRecord(&opCtx, locCollection, &rd));
- ASSERT(!oplogRs->findRecord(&opCtx, locOplog, &rd));
+ auto opCtx = _makeOperationContext(engine);
+ opCtx->recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kProvided, t9);
+ ASSERT(!collectionRs->findRecord(opCtx.get(), locCollection, &rd));
+ ASSERT(!oplogRs->findRecord(opCtx.get(), locOplog, &rd));
- opCtx.recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kProvided, t10);
- opCtx.recoveryUnit()->abandonSnapshot();
- ASSERT(collectionRs->findRecord(&opCtx, locCollection, &rd));
- ASSERT(oplogRs->findRecord(&opCtx, locOplog, &rd));
+ opCtx->recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kProvided, t10);
+ opCtx->recoveryUnit()->abandonSnapshot();
+ ASSERT(collectionRs->findRecord(opCtx.get(), locCollection, &rd));
+ ASSERT(oplogRs->findRecord(opCtx.get(), locOplog, &rd));
}
/*
@@ -857,8 +898,8 @@ TEST(KVEngineTestHarness, SingleReadWithConflictWithOplog) {
* | Begin :readAt 15 | |
* | Read A (DB exception) | |
*/
-TEST(KVEngineTestHarness, PinningOldestTimestampWithReadConflict) {
- std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create());
+TEST_F(KVEngineTestHarness, PinningOldestTimestampWithReadConflict) {
+ std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create(getServiceContext()));
KVEngine* engine = helper->getEngine();
// TODO SERVER-48314: Remove after implementing correct behavior on biggie.
if (engine->isEphemeral())
@@ -867,27 +908,28 @@ TEST(KVEngineTestHarness, PinningOldestTimestampWithReadConflict) {
std::string ns = "a.b";
std::unique_ptr<RecordStore> rs;
{
- MyOperationContext opCtx(engine);
- ASSERT_OK(engine->createRecordStore(&opCtx, ns, ns, CollectionOptions()));
- rs = engine->getRecordStore(&opCtx, ns, ns, CollectionOptions());
+ auto opCtx = _makeOperationContext(engine);
+ ASSERT_OK(engine->createRecordStore(opCtx.get(), ns, ns, CollectionOptions()));
+ rs = engine->getRecordStore(opCtx.get(), ns, ns, CollectionOptions());
ASSERT(rs);
}
- MyOperationContext opCtx(engine);
- WriteUnitOfWork uow(&opCtx);
- StatusWith<RecordId> res = rs->insertRecord(&opCtx, "abc", 4, Timestamp(10, 10));
+ auto opCtx = _makeOperationContext(engine);
+ WriteUnitOfWork uow(opCtx.get());
+ StatusWith<RecordId> res = rs->insertRecord(opCtx.get(), "abc", 4, Timestamp(10, 10));
RecordId rid = res.getValue();
uow.commit();
RecordData rd;
- opCtx.recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kProvided,
- Timestamp(15, 15));
- ASSERT(rs->findRecord(&opCtx, rid, &rd));
+ opCtx->recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kProvided,
+ Timestamp(15, 15));
+ ASSERT(rs->findRecord(opCtx.get(), rid, &rd));
engine->setOldestTimestamp(Timestamp(20, 20), false);
- opCtx.recoveryUnit()->abandonSnapshot();
- ASSERT_THROWS_CODE(rs->findRecord(&opCtx, rid, &rd), DBException, ErrorCodes::SnapshotTooOld);
+ opCtx->recoveryUnit()->abandonSnapshot();
+ ASSERT_THROWS_CODE(
+ rs->findRecord(opCtx.get(), rid, &rd), DBException, ErrorCodes::SnapshotTooOld);
}
@@ -900,10 +942,10 @@ TEST(KVEngineTestHarness, PinningOldestTimestampWithReadConflict) {
* | Write A 1 | |
* | Commit :commit 2 (WCE) | |
*/
-DEATH_TEST_REGEX(KVEngineTestHarness,
- PinningOldestTimestampWithWriteConflict,
- ".*commit timestamp.*is less than the oldest timestamp.*") {
- std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create());
+DEATH_TEST_REGEX_F(KVEngineTestHarness,
+ PinningOldestTimestampWithWriteConflict,
+ ".*commit timestamp.*is less than the oldest timestamp.*") {
+ std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create(getServiceContext()));
KVEngine* engine = helper->getEngine();
// TODO SERVER-48314: Remove after implementing correct behavior on biggie.
if (engine->isEphemeral())
@@ -912,18 +954,18 @@ DEATH_TEST_REGEX(KVEngineTestHarness,
std::string ns = "a.b";
std::unique_ptr<RecordStore> rs;
{
- MyOperationContext opCtx(engine);
- ASSERT_OK(engine->createRecordStore(&opCtx, ns, ns, CollectionOptions()));
- rs = engine->getRecordStore(&opCtx, ns, ns, CollectionOptions());
+ auto opCtx = _makeOperationContext(engine);
+ ASSERT_OK(engine->createRecordStore(opCtx.get(), ns, ns, CollectionOptions()));
+ rs = engine->getRecordStore(opCtx.get(), ns, ns, CollectionOptions());
ASSERT(rs);
}
{
// A write transaction cannot insert records before the oldest timestamp.
engine->setOldestTimestamp(Timestamp(2, 2), false);
- MyOperationContext opCtx2(engine);
- WriteUnitOfWork uow2(&opCtx2);
- StatusWith<RecordId> res = rs->insertRecord(&opCtx2, "abc", 4, Timestamp(1, 1));
+ auto opCtx = _makeOperationContext(engine);
+ WriteUnitOfWork uow2(opCtx.get());
+ StatusWith<RecordId> res = rs->insertRecord(opCtx.get(), "abc", 4, Timestamp(1, 1));
uow2.commit();
}
}
@@ -943,8 +985,8 @@ DEATH_TEST_REGEX(KVEngineTestHarness,
* | Read A (1) | |
* | Read B (NOT_FOUND) | |
*/
-TEST(KVEngineTestHarness, RollingBackToLastStable) {
- std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create());
+TEST_F(KVEngineTestHarness, RollingBackToLastStable) {
+ std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create(getServiceContext()));
KVEngine* engine = helper->getEngine();
// TODO SERVER-48314: Remove after implementing correct behavior on biggie.
if (engine->isEphemeral())
@@ -955,21 +997,21 @@ TEST(KVEngineTestHarness, RollingBackToLastStable) {
std::string ns = "a.b";
std::unique_ptr<RecordStore> rs;
{
- MyOperationContext opCtx(engine);
- ASSERT_OK(engine->createRecordStore(&opCtx, ns, ns, CollectionOptions()));
- rs = engine->getRecordStore(&opCtx, ns, ns, CollectionOptions());
+ auto opCtx = _makeOperationContext(engine);
+ ASSERT_OK(engine->createRecordStore(opCtx.get(), ns, ns, CollectionOptions()));
+ rs = engine->getRecordStore(opCtx.get(), ns, ns, CollectionOptions());
ASSERT(rs);
}
RecordId ridA;
{
- MyOperationContext opCtx(engine);
- WriteUnitOfWork uow(&opCtx);
- auto res = rs->insertRecord(&opCtx, "abc", 4, Timestamp(1, 1));
+ auto opCtx = _makeOperationContext(engine);
+ WriteUnitOfWork uow(opCtx.get());
+ auto res = rs->insertRecord(opCtx.get(), "abc", 4, Timestamp(1, 1));
ASSERT_OK(res);
ridA = res.getValue();
uow.commit();
- ASSERT_EQUALS(1, rs->numRecords(&opCtx));
+ ASSERT_EQUALS(1, rs->numRecords(opCtx.get()));
}
{
@@ -981,38 +1023,38 @@ TEST(KVEngineTestHarness, RollingBackToLastStable) {
ASSERT(!engine->getLastStableRecoveryTimestamp());
// Force a checkpoint to be taken. This should advance the last stable timestamp.
- MyOperationContext opCtx(engine);
- engine->flushAllFiles(&opCtx, false);
+ auto opCtx = _makeOperationContext(engine);
+ engine->flushAllFiles(opCtx.get(), false);
ASSERT_EQ(engine->getLastStableRecoveryTimestamp(), Timestamp(1, 1));
}
RecordId ridB;
{
// Insert a record after the stable timestamp.
- MyOperationContext opCtx(engine);
- WriteUnitOfWork uow(&opCtx);
- StatusWith<RecordId> swRid = rs->insertRecord(&opCtx, "def", 4, Timestamp(3, 3));
+ auto opCtx = _makeOperationContext(engine);
+ WriteUnitOfWork uow(opCtx.get());
+ StatusWith<RecordId> swRid = rs->insertRecord(opCtx.get(), "def", 4, Timestamp(3, 3));
ASSERT_OK(swRid);
ridB = swRid.getValue();
- ASSERT_EQUALS(2, rs->numRecords(&opCtx));
+ ASSERT_EQUALS(2, rs->numRecords(opCtx.get()));
uow.commit();
}
{
// Rollback to the last stable timestamp.
- MyOperationContext opCtx(engine);
- StatusWith<Timestamp> swTimestamp = engine->recoverToStableTimestamp(&opCtx);
+ auto opCtx = _makeOperationContext(engine);
+ StatusWith<Timestamp> swTimestamp = engine->recoverToStableTimestamp(opCtx.get());
ASSERT_EQ(swTimestamp.getValue(), Timestamp(1, 1));
// Verify that we can find record A and can't find the record B inserted at Timestamp(3, 3)
// in the collection any longer. 'numRecords' will still show two as it's the fast count and
// doesn't get reflected during the rollback.
RecordData rd;
- opCtx.recoveryUnit()->abandonSnapshot();
- ASSERT(rs->findRecord(&opCtx, ridA, &rd));
+ opCtx->recoveryUnit()->abandonSnapshot();
+ ASSERT(rs->findRecord(opCtx.get(), ridA, &rd));
ASSERT_EQ(std::string("abc"), rd.data());
- ASSERT_FALSE(rs->findRecord(&opCtx, ridB, nullptr));
- ASSERT_EQUALS(2, rs->numRecords(&opCtx));
+ ASSERT_FALSE(rs->findRecord(opCtx.get(), ridB, nullptr));
+ ASSERT_EQUALS(2, rs->numRecords(opCtx.get()));
}
}
@@ -1025,10 +1067,10 @@ TEST(KVEngineTestHarness, RollingBackToLastStable) {
* | Write A 1 | |
* | Timestamp :commit 1 (ROLLBACK) | |
*/
-DEATH_TEST_REGEX(KVEngineTestHarness,
- CommitBehindStable,
- ".*commit timestamp.*is less than the stable timestamp.*") {
- std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create());
+DEATH_TEST_REGEX_F(KVEngineTestHarness,
+ CommitBehindStable,
+ ".*commit timestamp.*is less than the stable timestamp.*") {
+ std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create(getServiceContext()));
KVEngine* engine = helper->getEngine();
// TODO SERVER-48314: Remove after implementing correct behavior on biggie.
if (engine->isEphemeral())
@@ -1039,9 +1081,9 @@ DEATH_TEST_REGEX(KVEngineTestHarness,
std::string ns = "a.b";
std::unique_ptr<RecordStore> rs;
{
- MyOperationContext opCtx(engine);
- ASSERT_OK(engine->createRecordStore(&opCtx, ns, ns, CollectionOptions()));
- rs = engine->getRecordStore(&opCtx, ns, ns, CollectionOptions());
+ auto opCtx = _makeOperationContext(engine);
+ ASSERT_OK(engine->createRecordStore(opCtx.get(), ns, ns, CollectionOptions()));
+ rs = engine->getRecordStore(opCtx.get(), ns, ns, CollectionOptions());
ASSERT(rs);
}
@@ -1052,16 +1094,16 @@ DEATH_TEST_REGEX(KVEngineTestHarness,
ASSERT(!engine->getLastStableRecoveryTimestamp());
// Force a checkpoint to be taken. This should advance the last stable timestamp.
- MyOperationContext opCtx(engine);
- engine->flushAllFiles(&opCtx, false);
+ auto opCtx = _makeOperationContext(engine);
+ engine->flushAllFiles(opCtx.get(), false);
ASSERT_EQ(engine->getLastStableRecoveryTimestamp(), Timestamp(2, 2));
}
{
// Committing a behind the stable timestamp is not allowed.
- MyOperationContext opCtx(engine);
- WriteUnitOfWork uow(&opCtx);
- auto swRid = rs->insertRecord(&opCtx, "abc", 4, Timestamp(1, 1));
+ auto opCtx = _makeOperationContext(engine);
+ WriteUnitOfWork uow(opCtx.get());
+ auto swRid = rs->insertRecord(opCtx.get(), "abc", 4, Timestamp(1, 1));
uow.commit();
}
}
@@ -1075,8 +1117,8 @@ DEATH_TEST_REGEX(KVEngineTestHarness,
* | Write A 1 | |
* | Timestamp :commit 2 | |
*/
-TEST(KVEngineTestHarness, CommitAtStable) {
- std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create());
+TEST_F(KVEngineTestHarness, CommitAtStable) {
+ std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create(getServiceContext()));
KVEngine* engine = helper->getEngine();
// TODO SERVER-48314: Remove after implementing correct behavior on biggie.
if (engine->isEphemeral())
@@ -1087,9 +1129,9 @@ TEST(KVEngineTestHarness, CommitAtStable) {
std::string ns = "a.b";
std::unique_ptr<RecordStore> rs;
{
- MyOperationContext opCtx(engine);
- ASSERT_OK(engine->createRecordStore(&opCtx, ns, ns, CollectionOptions()));
- rs = engine->getRecordStore(&opCtx, ns, ns, CollectionOptions());
+ auto opCtx = _makeOperationContext(engine);
+ ASSERT_OK(engine->createRecordStore(opCtx.get(), ns, ns, CollectionOptions()));
+ rs = engine->getRecordStore(opCtx.get(), ns, ns, CollectionOptions());
ASSERT(rs);
}
@@ -1100,8 +1142,8 @@ TEST(KVEngineTestHarness, CommitAtStable) {
ASSERT(!engine->getLastStableRecoveryTimestamp());
// Force a checkpoint to be taken. This should advance the last stable timestamp.
- MyOperationContext opCtx(engine);
- engine->flushAllFiles(&opCtx, false);
+ auto opCtx = _makeOperationContext(engine);
+ engine->flushAllFiles(opCtx.get(), false);
ASSERT_EQ(engine->getLastStableRecoveryTimestamp(), Timestamp(2, 2));
}
@@ -1109,9 +1151,9 @@ TEST(KVEngineTestHarness, CommitAtStable) {
{
// For a non-prepared transaction, the commit timestamp can be equal to the stable
// timestamp.
- MyOperationContext opCtx(engine);
- WriteUnitOfWork uow(&opCtx);
- auto swRid = rs->insertRecord(&opCtx, "abc", 4, Timestamp(2, 2));
+ auto opCtx = _makeOperationContext(engine);
+ WriteUnitOfWork uow(opCtx.get());
+ auto swRid = rs->insertRecord(opCtx.get(), "abc", 4, Timestamp(2, 2));
ASSERT_OK(swRid);
rid = swRid.getValue();
uow.commit();
@@ -1119,15 +1161,15 @@ TEST(KVEngineTestHarness, CommitAtStable) {
{
// Rollback to the last stable timestamp.
- MyOperationContext opCtx(engine);
- StatusWith<Timestamp> swTimestamp = engine->recoverToStableTimestamp(&opCtx);
+ auto opCtx = _makeOperationContext(engine);
+ StatusWith<Timestamp> swTimestamp = engine->recoverToStableTimestamp(opCtx.get());
ASSERT_EQ(swTimestamp.getValue(), Timestamp(2, 2));
// Transaction with timestamps equal to lastStable will not be rolled back.
- opCtx.recoveryUnit()->abandonSnapshot();
+ opCtx->recoveryUnit()->abandonSnapshot();
RecordData data;
- ASSERT_TRUE(rs->findRecord(&opCtx, rid, &data));
- ASSERT_EQUALS(1, rs->numRecords(&opCtx));
+ ASSERT_TRUE(rs->findRecord(opCtx.get(), rid, &data));
+ ASSERT_EQUALS(1, rs->numRecords(opCtx.get()));
}
}
@@ -1478,11 +1520,12 @@ DEATH_TEST_REGEX_F(DurableCatalogImplTest,
} // namespace
-std::unique_ptr<KVHarnessHelper> KVHarnessHelper::create() {
- return basicFactory();
+std::unique_ptr<KVHarnessHelper> KVHarnessHelper::create(ServiceContext* svcCtx) {
+ return basicFactory(svcCtx);
};
-void KVHarnessHelper::registerFactory(std::function<std::unique_ptr<KVHarnessHelper>()> factory) {
+void KVHarnessHelper::registerFactory(
+ std::function<std::unique_ptr<KVHarnessHelper>(ServiceContext*)> factory) {
basicFactory = std::move(factory);
};
diff --git a/src/mongo/db/storage/kv/kv_engine_test_harness.h b/src/mongo/db/storage/kv/kv_engine_test_harness.h
index ed2f5d66d14..234c1462a6d 100644
--- a/src/mongo/db/storage/kv/kv_engine_test_harness.h
+++ b/src/mongo/db/storage/kv/kv_engine_test_harness.h
@@ -55,8 +55,9 @@ public:
virtual KVEngine* restartEngine() = 0;
- static std::unique_ptr<KVHarnessHelper> create();
- static void registerFactory(std::function<std::unique_ptr<KVHarnessHelper>()> factory);
+ static std::unique_ptr<KVHarnessHelper> create(ServiceContext* svcCtx);
+ static void registerFactory(
+ std::function<std::unique_ptr<KVHarnessHelper>(ServiceContext*)> factory);
};
} // namespace mongo
diff --git a/src/mongo/db/storage/kv/kv_engine_timestamps_test.cpp b/src/mongo/db/storage/kv/kv_engine_timestamps_test.cpp
index 034bd0e0318..0fc5665be32 100644
--- a/src/mongo/db/storage/kv/kv_engine_timestamps_test.cpp
+++ b/src/mongo/db/storage/kv/kv_engine_timestamps_test.cpp
@@ -197,7 +197,7 @@ public:
}
void setUp() override {
- helper = KVHarnessHelper::create();
+ helper = KVHarnessHelper::create(getGlobalServiceContext());
engine = helper->getEngine();
snapshotManager = helper->getEngine()->getSnapshotManager();
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine_test.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine_test.cpp
index 49619f6cee8..ce2b7c15a13 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine_test.cpp
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine_test.cpp
@@ -55,14 +55,13 @@
namespace mongo {
namespace {
-class WiredTigerKVHarnessHelper : public KVHarnessHelper, public ScopedGlobalServiceContextForTest {
+class WiredTigerKVHarnessHelper : public KVHarnessHelper {
public:
- WiredTigerKVHarnessHelper(bool forRepair = false)
+ WiredTigerKVHarnessHelper(ServiceContext* svcCtx, bool forRepair = false)
: _dbpath("wt-kv-harness"), _forRepair(forRepair), _engine(makeEngine()) {
- auto context = getGlobalServiceContext();
repl::ReplicationCoordinator::set(
- context,
- std::make_unique<repl::ReplicationCoordinatorMock>(context, repl::ReplSettings()));
+ svcCtx,
+ std::make_unique<repl::ReplicationCoordinatorMock>(svcCtx, repl::ReplSettings()));
_engine->notifyStartupComplete();
}
@@ -100,16 +99,21 @@ private:
std::unique_ptr<WiredTigerKVEngine> _engine;
};
-class WiredTigerKVEngineTest : public unittest::Test, public ScopedGlobalServiceContextForTest {
+class WiredTigerKVEngineTest : public ServiceContextTest {
public:
WiredTigerKVEngineTest(bool repair = false)
- : _helper(repair), _engine(_helper.getWiredTigerKVEngine()) {}
+ : _helper(getServiceContext(), repair), _engine(_helper.getWiredTigerKVEngine()) {}
- std::unique_ptr<OperationContext> makeOperationContext() {
- return std::make_unique<OperationContextNoop>(_engine->newRecoveryUnit());
+protected:
+ ServiceContext::UniqueOperationContext _makeOperationContext() {
+ auto opCtx = makeOperationContext();
+ opCtx->setRecoveryUnit(
+ std::unique_ptr<RecoveryUnit>(_helper.getEngine()->newRecoveryUnit()),
+ WriteUnitOfWork::RecoveryUnitState::kNotInUnitOfWork);
+ opCtx->swapLockState(std::make_unique<LockerNoop>(), WithLock::withoutLock());
+ return opCtx;
}
-protected:
WiredTigerKVHarnessHelper _helper;
WiredTigerKVEngine* _engine;
};
@@ -120,7 +124,7 @@ public:
};
TEST_F(WiredTigerKVEngineRepairTest, OrphanedDataFilesCanBeRecovered) {
- auto opCtxPtr = makeOperationContext();
+ auto opCtxPtr = _makeOperationContext();
NamespaceString nss("a.b");
std::string ident = "collection-1234";
@@ -178,7 +182,7 @@ TEST_F(WiredTigerKVEngineRepairTest, OrphanedDataFilesCanBeRecovered) {
}
TEST_F(WiredTigerKVEngineRepairTest, UnrecoverableOrphanedDataFilesAreRebuilt) {
- auto opCtxPtr = makeOperationContext();
+ auto opCtxPtr = _makeOperationContext();
NamespaceString nss("a.b");
std::string ident = "collection-1234";
@@ -246,7 +250,7 @@ TEST_F(WiredTigerKVEngineTest, TestOplogTruncation) {
std::unique_ptr<Checkpointer> checkpointer = std::make_unique<Checkpointer>(_engine);
checkpointer->go();
- auto opCtxPtr = makeOperationContext();
+ auto opCtxPtr = _makeOperationContext();
// The initial data timestamp has to be set to take stable checkpoints. The first stable
// timestamp greater than this will also trigger a checkpoint. The following loop of the
// CheckpointThread will observe the new `checkpointDelaySecs` value.
@@ -351,7 +355,7 @@ TEST_F(WiredTigerKVEngineTest, IdentDrop) {
return;
#endif
- auto opCtxPtr = makeOperationContext();
+ auto opCtxPtr = _makeOperationContext();
NamespaceString nss("a.b");
std::string ident = "collection-1234";
@@ -392,7 +396,7 @@ TEST_F(WiredTigerKVEngineTest, IdentDrop) {
}
TEST_F(WiredTigerKVEngineTest, TestBasicPinOldestTimestamp) {
- auto opCtxRaii = makeOperationContext();
+ auto opCtxRaii = _makeOperationContext();
const Timestamp initTs = Timestamp(1, 0);
// Initialize the oldest timestamp.
@@ -433,7 +437,7 @@ TEST_F(WiredTigerKVEngineTest, TestBasicPinOldestTimestamp) {
* of all active requests will be obeyed.
*/
TEST_F(WiredTigerKVEngineTest, TestMultiPinOldestTimestamp) {
- auto opCtxRaii = makeOperationContext();
+ auto opCtxRaii = _makeOperationContext();
const Timestamp initTs = Timestamp(1, 0);
_engine->setOldestTimestamp(initTs, false);
@@ -474,7 +478,7 @@ TEST_F(WiredTigerKVEngineTest, TestMultiPinOldestTimestamp) {
* relative to the current oldest timestamp.
*/
TEST_F(WiredTigerKVEngineTest, TestPinOldestTimestampErrors) {
- auto opCtxRaii = makeOperationContext();
+ auto opCtxRaii = _makeOperationContext();
const Timestamp initTs = Timestamp(10, 0);
_engine->setOldestTimestamp(initTs, false);
@@ -497,8 +501,8 @@ TEST_F(WiredTigerKVEngineTest, TestPinOldestTimestampErrors) {
}
-std::unique_ptr<KVHarnessHelper> makeHelper() {
- return std::make_unique<WiredTigerKVHarnessHelper>();
+std::unique_ptr<KVHarnessHelper> makeHelper(ServiceContext* svcCtx) {
+ return std::make_unique<WiredTigerKVHarnessHelper>(svcCtx);
}
MONGO_INITIALIZER(RegisterKVHarnessFactory)(InitializerContext*) {
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp
index 001d26dab60..1a8814c009d 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp
@@ -2073,6 +2073,15 @@ void WiredTigerRecordStore::_initNextIdIfNeeded(OperationContext* opCtx) {
return;
}
+ // During startup recovery, the collectionAlwaysNeedsSizeAdjustment flag is not set by default
+ // for the sake of efficiency. However, if we reach this point, we may need to set it in order
+ // to ensure that capped deletes can occur on documents inserted earlier in startup recovery.
+ if (inReplicationRecovery(opCtx->getServiceContext()) &&
+ !sizeRecoveryState(opCtx->getServiceContext())
+ .collectionAlwaysNeedsSizeAdjustment(getIdent())) {
+ checkSize(opCtx);
+ }
+
// Need to start at 1 so we are always higher than RecordId::minLong()
int64_t nextId = 1;