summaryrefslogtreecommitdiff
path: root/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_kv_engine_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_kv_engine_test.cpp')
-rw-r--r--src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_kv_engine_test.cpp497
1 files changed, 0 insertions, 497 deletions
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
deleted file mode 100644
index f129c04baa2..00000000000
--- a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_kv_engine_test.cpp
+++ /dev/null
@@ -1,497 +0,0 @@
-/**
- * Copyright (C) 2018-present MongoDB, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the Server Side Public License, version 1,
- * as published by MongoDB, Inc.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * Server Side Public License for more details.
- *
- * You should have received a copy of the Server Side Public License
- * along with this program. If not, see
- * <http://www.mongodb.com/licensing/server-side-public-license>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the Server Side Public License in all respects for
- * all of the code used other than as permitted herein. If you modify file(s)
- * with this exception, you may extend this exception to your version of the
- * file(s), but you are not obligated to do so. If you do not wish to do so,
- * delete this exception statement from your version. If you delete this
- * exception statement from all source files in the program, then also delete
- * it in the license file.
- */
-
-#include "mongo/platform/basic.h"
-
-#include "mongo/db/storage/kv/kv_engine_test_harness.h"
-
-#include <memory>
-
-#include "mongo/base/init.h"
-#include "mongo/db/operation_context_noop.h"
-#include "mongo/db/repl/replication_coordinator_mock.h"
-#include "mongo/db/service_context.h"
-#include "mongo/db/service_context_test_fixture.h"
-#include "mongo/db/storage/ephemeral_for_test/ephemeral_for_test_kv_engine.h"
-#include "mongo/unittest/unittest.h"
-
-namespace mongo {
-namespace ephemeral_for_test {
-
-class KVHarnessHelper : public mongo::KVHarnessHelper {
-public:
- KVHarnessHelper(ServiceContext* svcCtx) : _engine(std::make_unique<KVEngine>()) {
- repl::ReplicationCoordinator::set(
- svcCtx,
- std::unique_ptr<repl::ReplicationCoordinator>(new repl::ReplicationCoordinatorMock(
- getGlobalServiceContext(), repl::ReplSettings())));
- }
-
- virtual KVEngine* getEngine() override {
- return _engine.get();
- }
-
- virtual KVEngine* restartEngine() override {
- return _engine.get();
- }
-
-private:
- std::unique_ptr<KVEngine> _engine;
-};
-
-std::unique_ptr<mongo::KVHarnessHelper> makeHelper(ServiceContext* svcCtx) {
- return std::make_unique<KVHarnessHelper>(svcCtx);
-}
-
-MONGO_INITIALIZER(RegisterEphemeralForTestKVHarnessFactory)(InitializerContext*) {
- KVHarnessHelper::registerFactory(makeHelper);
-}
-
-class EphemeralForTestKVEngineTest : public ServiceContextTest {
-public:
- EphemeralForTestKVEngineTest() : _helper(getServiceContext()), _engine(_helper.getEngine()) {}
-
- ServiceContext::UniqueOperationContext makeOpCtx() {
- 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>>
- makeOpCtxs(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;
- }
-
-protected:
- std::unique_ptr<KVHarnessHelper> helper;
- KVHarnessHelper _helper;
- KVEngine* _engine;
-};
-
-TEST_F(EphemeralForTestKVEngineTest, AvailableHistoryUpdate) {
- NamespaceString nss("a.b");
- std::string ident = "collection-1234";
- std::string record = "abcd";
- CollectionOptions defaultCollectionOptions;
-
- std::unique_ptr<mongo::RecordStore> rs;
- {
- auto opCtx = makeOpCtx();
- ASSERT_OK(_engine->createRecordStore(opCtx.get(), nss, ident, defaultCollectionOptions));
- rs = _engine->getRecordStore(opCtx.get(), nss, ident, defaultCollectionOptions);
- ASSERT(rs);
- }
-
- Timestamp lastMaster;
- Timestamp currentMaster;
-
- ASSERT_EQ(1, _engine->getHistory_forTest().size());
- currentMaster = _engine->getHistory_forTest().rbegin()->first;
- ASSERT_EQ(_engine->getOldestTimestamp(), currentMaster);
-
- {
- auto opCtx = makeOpCtx();
- WriteUnitOfWork uow(opCtx.get());
- StatusWith<RecordId> res =
- rs->insertRecord(opCtx.get(), record.c_str(), record.length() + 1, Timestamp());
- ASSERT_OK(res.getStatus());
- uow.commit();
- }
-
- ASSERT_EQ(1, _engine->getHistory_forTest().size());
- lastMaster = currentMaster;
- currentMaster = _engine->getHistory_forTest().rbegin()->first;
- ASSERT_GT(currentMaster, lastMaster);
- ASSERT_EQ(_engine->getOldestTimestamp(), currentMaster);
-}
-
-TEST_F(EphemeralForTestKVEngineTest, PinningOldestTimestampWithReadTransaction) {
- NamespaceString nss("a.b");
- std::string ident = "collection-1234";
- std::string record = "abcd";
- CollectionOptions defaultCollectionOptions;
-
- std::unique_ptr<mongo::RecordStore> rs;
- {
- auto opCtx = makeOpCtx();
- ASSERT_OK(_engine->createRecordStore(opCtx.get(), nss, ident, defaultCollectionOptions));
- rs = _engine->getRecordStore(opCtx.get(), nss, ident, defaultCollectionOptions);
- ASSERT(rs);
- }
-
- // _availableHistory starts off with master.
- ASSERT_EQ(1, _engine->getHistory_forTest().size());
-
- RecordId loc;
- {
- auto opCtx = makeOpCtx();
- WriteUnitOfWork uow(opCtx.get());
- StatusWith<RecordId> res =
- rs->insertRecord(opCtx.get(), record.c_str(), record.length() + 1, Timestamp());
- ASSERT_OK(res.getStatus());
- loc = res.getValue();
- uow.commit();
- }
-
- auto opCtxs = makeOpCtxs(2);
-
- auto opCtxRead = opCtxs[0].second.get();
- RecordData rd;
- ASSERT(rs->findRecord(opCtxRead, loc, &rd));
-
- {
- auto opCtx = opCtxs[1].second.get();
- WriteUnitOfWork uow(opCtx);
- StatusWith<RecordId> res =
- rs->insertRecord(opCtx, record.c_str(), record.length() + 1, Timestamp());
- ASSERT_OK(res.getStatus());
- uow.commit();
- }
-
- // Open read transaction prevents deletion of history.
- ASSERT_EQ(2, _engine->getHistory_forTest().size());
- ASSERT_GT(_engine->getHistory_forTest().rbegin()->first, _engine->getOldestTimestamp());
-}
-
-TEST_F(EphemeralForTestKVEngineTest, SettingOldestTimestampClearsHistory) {
- NamespaceString nss("a.b");
- std::string ident = "collection-1234";
- std::string record = "abcd";
- CollectionOptions defaultCollectionOptions;
-
- std::unique_ptr<mongo::RecordStore> rs;
- {
- auto opCtx = makeOpCtx();
- ASSERT_OK(_engine->createRecordStore(opCtx.get(), nss, ident, defaultCollectionOptions));
- rs = _engine->getRecordStore(opCtx.get(), nss, ident, defaultCollectionOptions);
- ASSERT(rs);
- }
-
- // _availableHistory starts off with master.
- ASSERT_EQ(1, _engine->getHistory_forTest().size());
-
- RecordId loc;
- {
- auto opCtx = makeOpCtx();
- WriteUnitOfWork uow(opCtx.get());
- StatusWith<RecordId> res =
- rs->insertRecord(opCtx.get(), record.c_str(), record.length() + 1, Timestamp());
- ASSERT_OK(res.getStatus());
- loc = res.getValue();
- uow.commit();
- }
-
- auto opCtxs = makeOpCtxs(2);
-
- auto opCtxRead = opCtxs[0].second.get();
- RecordData rd;
- ASSERT(rs->findRecord(opCtxRead, loc, &rd));
-
- {
- auto opCtx = opCtxs[1].second.get();
- WriteUnitOfWork uow(opCtx);
- StatusWith<RecordId> res =
- rs->insertRecord(opCtx, record.c_str(), record.length() + 1, Timestamp());
- ASSERT_OK(res.getStatus());
- uow.commit();
- }
-
- ASSERT_EQ(2, _engine->getHistory_forTest().size());
- _engine->setOldestTimestamp(_engine->getHistory_forTest().rbegin()->first, false);
- ASSERT_EQ(1, _engine->getHistory_forTest().size());
-}
-
-TEST_F(EphemeralForTestKVEngineTest, SettingOldestTimestampToMax) {
- NamespaceString nss("a.b");
- std::string ident = "collection-1234";
- std::string record = "abcd";
- CollectionOptions defaultCollectionOptions;
-
- std::unique_ptr<mongo::RecordStore> rs;
- {
- auto opCtx = makeOpCtx();
- ASSERT_OK(_engine->createRecordStore(opCtx.get(), nss, ident, defaultCollectionOptions));
- rs = _engine->getRecordStore(opCtx.get(), nss, ident, defaultCollectionOptions);
- ASSERT(rs);
- }
-
- {
- auto opCtx = makeOpCtx();
- WriteUnitOfWork uow(opCtx.get());
- StatusWith<RecordId> res =
- rs->insertRecord(opCtx.get(), record.c_str(), record.length() + 1, Timestamp());
- ASSERT_OK(res.getStatus());
- uow.commit();
- }
-
- // Check that setting oldest to Timestamp::max() does not clear history.
- ASSERT_GTE(_engine->getHistory_forTest().size(), 1);
- ASSERT_LT(_engine->getHistory_forTest().rbegin()->first, Timestamp::max());
- _engine->setOldestTimestamp(Timestamp::max(), true);
- ASSERT_GTE(_engine->getHistory_forTest().size(), 1);
- ASSERT_EQ(Timestamp::max(), _engine->getHistory_forTest().rbegin()->first);
-}
-
-TEST_F(EphemeralForTestKVEngineTest, CleanHistoryWithOpenTransaction) {
- NamespaceString nss("a.b");
- std::string ident = "collection-1234";
- std::string record = "abcd";
- CollectionOptions defaultCollectionOptions;
-
- std::unique_ptr<mongo::RecordStore> rs;
- {
- auto opCtx = makeOpCtx();
- ASSERT_OK(_engine->createRecordStore(opCtx.get(), nss, ident, defaultCollectionOptions));
- rs = _engine->getRecordStore(opCtx.get(), nss, ident, defaultCollectionOptions);
- ASSERT(rs);
- }
-
- // _availableHistory starts off with master.
- ASSERT_EQ(1, _engine->getHistory_forTest().size());
-
- RecordId loc;
- {
- auto opCtx = makeOpCtx();
- WriteUnitOfWork uow(opCtx.get());
- StatusWith<RecordId> res =
- rs->insertRecord(opCtx.get(), record.c_str(), record.length() + 1, Timestamp());
- ASSERT_OK(res.getStatus());
- loc = res.getValue();
- uow.commit();
- }
-
- auto opCtxs = makeOpCtxs(2);
-
- auto opCtxRead = opCtxs[0].second.get();
- Timestamp readTime1 = _engine->getHistory_forTest().rbegin()->first;
- RecordData rd;
- ASSERT(rs->findRecord(opCtxRead, loc, &rd));
-
- {
- auto opCtx = opCtxs[1].second.get();
- WriteUnitOfWork uow(opCtx);
- StatusWith<RecordId> res =
- rs->insertRecord(opCtx, record.c_str(), record.length() + 1, Timestamp());
- ASSERT_OK(res.getStatus());
- uow.commit();
- }
-
- Timestamp readTime2 = _engine->getHistory_forTest().rbegin()->first;
-
- {
- auto opCtx = opCtxs[1].second.get();
- WriteUnitOfWork uow(opCtx);
- StatusWith<RecordId> res =
- rs->insertRecord(opCtx, record.c_str(), record.length() + 1, Timestamp());
- ASSERT_OK(res.getStatus());
- uow.commit();
- }
-
- // Destruct the client used for writes prior to checking use_count().
- opCtxs.pop_back();
-
- Timestamp readTime3 = _engine->getHistory_forTest().rbegin()->first;
- _engine->cleanHistory();
-
- // use_count() should be {2, 1, 2} without the copy from getHistory_forTest().
- ASSERT_EQ(3, _engine->getHistory_forTest().size());
- ASSERT_EQ(3, _engine->getHistory_forTest().at(readTime1).use_count());
- ASSERT_EQ(2, _engine->getHistory_forTest().at(readTime2).use_count());
- ASSERT_EQ(3, _engine->getHistory_forTest().at(readTime3).use_count());
-}
-
-TEST_F(EphemeralForTestKVEngineTest, ReadOlderSnapshotsSimple) {
- NamespaceString nss("a.b");
- std::string ident = "collection-1234";
- std::string record = "abcd";
- CollectionOptions defaultCollectionOptions;
-
- std::unique_ptr<mongo::RecordStore> rs;
- {
- auto opCtx = makeOpCtx();
- ASSERT_OK(_engine->createRecordStore(opCtx.get(), nss, ident, defaultCollectionOptions));
- rs = _engine->getRecordStore(opCtx.get(), nss, ident, defaultCollectionOptions);
- ASSERT(rs);
- }
-
- auto opCtxs = makeOpCtxs(2);
-
- // Pin oldest timestamp with a read transaction.
- auto pinningOldest = opCtxs[0].second.get();
- ASSERT(!rs->findRecord(pinningOldest, RecordId(1), nullptr));
-
- // Set readFrom to timestamp with no committed transactions.
- Timestamp readFrom = _engine->getHistory_forTest().rbegin()->first;
-
- auto opCtx = opCtxs[1].second.get();
- WriteUnitOfWork uow1(opCtx);
- StatusWith<RecordId> res1 =
- rs->insertRecord(opCtx, record.c_str(), record.length() + 1, Timestamp());
- ASSERT_OK(res1.getStatus());
- RecordId loc1 = res1.getValue();
- uow1.commit();
-
- WriteUnitOfWork uow2(opCtx);
- StatusWith<RecordId> res2 =
- rs->insertRecord(opCtx, record.c_str(), record.length() + 1, Timestamp());
- ASSERT_OK(res2.getStatus());
- RecordId loc2 = res2.getValue();
- uow2.commit();
-
- RecordData rd;
- opCtx->recoveryUnit()->abandonSnapshot();
- opCtx->recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kProvided, readFrom);
- ASSERT(!rs->findRecord(opCtx, loc1, &rd));
- ASSERT(!rs->findRecord(opCtx, loc2, &rd));
-
- opCtx->recoveryUnit()->abandonSnapshot();
- opCtx->recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kNoTimestamp);
- ASSERT(rs->findRecord(opCtx, loc1, &rd));
- ASSERT(rs->findRecord(opCtx, loc2, &rd));
-}
-
-TEST_F(EphemeralForTestKVEngineTest, ReadOutdatedSnapshot) {
- NamespaceString nss("a.b");
- std::string ident = "collection-1234";
- std::string record = "abcd";
- CollectionOptions defaultCollectionOptions;
-
- std::unique_ptr<mongo::RecordStore> rs;
- {
- auto opCtx = makeOpCtx();
- ASSERT_OK(_engine->createRecordStore(opCtx.get(), nss, ident, defaultCollectionOptions));
- rs = _engine->getRecordStore(opCtx.get(), nss, ident, defaultCollectionOptions);
- ASSERT(rs);
- }
-
- RecordId loc1;
- {
- auto opCtx = makeOpCtx();
- WriteUnitOfWork uow(opCtx.get());
- StatusWith<RecordId> res =
- rs->insertRecord(opCtx.get(), record.c_str(), record.length() + 1, Timestamp());
- ASSERT_OK(res.getStatus());
- loc1 = res.getValue();
- uow.commit();
- }
-
- auto opCtxs = makeOpCtxs(2);
-
- auto opCtxRead = opCtxs[0].second.get();
- RecordData rd;
- ASSERT(rs->findRecord(opCtxRead, loc1, &rd));
- Timestamp readFrom = _engine->getHistory_forTest().rbegin()->first;
-
- RecordId loc2;
- {
- auto opCtx = opCtxs[1].second.get();
- WriteUnitOfWork uow(opCtx);
- StatusWith<RecordId> res =
- rs->insertRecord(opCtx, record.c_str(), record.length() + 1, Timestamp());
- ASSERT_OK(res.getStatus());
- loc2 = res.getValue();
- uow.commit();
- }
-
- // Destruct the client used for writes prior to trying to get a snapshot too old.
- opCtxs.pop_back();
-
- ASSERT(rs->findRecord(opCtxRead, loc1, &rd));
- opCtxRead->recoveryUnit()->abandonSnapshot();
- opCtxRead->recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kProvided,
- readFrom);
- ASSERT_THROWS_CODE(
- rs->findRecord(opCtxRead, loc1, &rd), DBException, ErrorCodes::SnapshotTooOld);
-}
-
-TEST_F(EphemeralForTestKVEngineTest, SetReadTimestampBehindOldestTimestamp) {
- NamespaceString nss("a.b");
- std::string ident = "collection-1234";
- std::string record = "abcd";
- CollectionOptions defaultCollectionOptions;
-
- std::unique_ptr<mongo::RecordStore> rs;
- {
- auto opCtx = makeOpCtx();
- ASSERT_OK(_engine->createRecordStore(opCtx.get(), nss, ident, defaultCollectionOptions));
- rs = _engine->getRecordStore(opCtx.get(), nss, ident, defaultCollectionOptions);
- ASSERT(rs);
- }
-
- RecordId loc1;
- {
- auto opCtx = makeOpCtx();
- WriteUnitOfWork uow(opCtx.get());
- StatusWith<RecordId> res =
- rs->insertRecord(opCtx.get(), record.c_str(), record.length() + 1, Timestamp());
- ASSERT_OK(res.getStatus());
- loc1 = res.getValue();
- uow.commit();
- }
-
- RecordData rd;
- Timestamp readFrom = _engine->getHistory_forTest().begin()->first;
- auto opCtx = makeOpCtx();
- WriteUnitOfWork uow(opCtx.get());
- StatusWith<RecordId> res =
- rs->insertRecord(opCtx.get(), record.c_str(), record.length() + 1, Timestamp());
- ASSERT_OK(res.getStatus());
- RecordId loc2 = res.getValue();
- uow.commit();
-
- opCtx->recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kProvided, readFrom);
- _engine->setOldestTimestamp(Timestamp::max(), true);
- ASSERT_THROWS_CODE(
- rs->findRecord(opCtx.get(), loc2, &rd), DBException, ErrorCodes::SnapshotTooOld);
-
- opCtx->recoveryUnit()->abandonSnapshot();
- opCtx->recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kNoTimestamp);
- ASSERT(rs->findRecord(opCtx.get(), loc1, &rd));
- ASSERT(rs->findRecord(opCtx.get(), loc2, &rd));
-}
-
-} // namespace ephemeral_for_test
-} // namespace mongo