diff options
Diffstat (limited to 'src/mongo')
7 files changed, 96 insertions, 26 deletions
diff --git a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_record_store_test.cpp b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_record_store_test.cpp index 15ebe93cad0..f5b66a36c16 100644 --- a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_record_store_test.cpp +++ b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_record_store_test.cpp @@ -95,7 +95,8 @@ public: } }; -std::unique_ptr<mongo::RecordStoreHarnessHelper> makeRecordStoreHarnessHelper() { +std::unique_ptr<mongo::RecordStoreHarnessHelper> makeRecordStoreHarnessHelper( + RecordStoreHarnessHelper::Options options) { return std::make_unique<RecordStoreHarnessHelper>(); } diff --git a/src/mongo/db/storage/record_store_test_harness.cpp b/src/mongo/db/storage/record_store_test_harness.cpp index 00f937ac8be..f026681a77d 100644 --- a/src/mongo/db/storage/record_store_test_harness.cpp +++ b/src/mongo/db/storage/record_store_test_harness.cpp @@ -39,16 +39,19 @@ namespace mongo { namespace { -std::function<std::unique_ptr<RecordStoreHarnessHelper>()> recordStoreHarnessFactory; +std::function<std::unique_ptr<RecordStoreHarnessHelper>(RecordStoreHarnessHelper::Options)> + recordStoreHarnessFactory; } void registerRecordStoreHarnessHelperFactory( - std::function<std::unique_ptr<RecordStoreHarnessHelper>()> factory) { + std::function<std::unique_ptr<RecordStoreHarnessHelper>(RecordStoreHarnessHelper::Options)> + factory) { recordStoreHarnessFactory = std::move(factory); } -auto newRecordStoreHarnessHelper() -> std::unique_ptr<RecordStoreHarnessHelper> { - return recordStoreHarnessFactory(); +auto newRecordStoreHarnessHelper(RecordStoreHarnessHelper::Options options) + -> std::unique_ptr<RecordStoreHarnessHelper> { + return recordStoreHarnessFactory(options); } namespace { diff --git a/src/mongo/db/storage/record_store_test_harness.h b/src/mongo/db/storage/record_store_test_harness.h index 72f087463bf..4cae8fa740c 100644 --- a/src/mongo/db/storage/record_store_test_harness.h +++ b/src/mongo/db/storage/record_store_test_harness.h @@ -45,6 +45,8 @@ class RecoveryUnit; class RecordStoreHarnessHelper : public HarnessHelper { public: + enum class Options { Standalone, ReplicationEnabled }; + virtual std::unique_ptr<RecordStore> newRecordStore() = 0; std::unique_ptr<RecordStore> newRecordStore(const std::string& ns) { @@ -61,8 +63,11 @@ public: }; void registerRecordStoreHarnessHelperFactory( - std::function<std::unique_ptr<RecordStoreHarnessHelper>()> factory); + std::function<std::unique_ptr<RecordStoreHarnessHelper>(RecordStoreHarnessHelper::Options)> + factory); -std::unique_ptr<RecordStoreHarnessHelper> newRecordStoreHarnessHelper(); +std::unique_ptr<RecordStoreHarnessHelper> newRecordStoreHarnessHelper( + RecordStoreHarnessHelper::Options options = + RecordStoreHarnessHelper::Options::ReplicationEnabled); } // namespace mongo diff --git a/src/mongo/db/storage/record_store_test_oplog.cpp b/src/mongo/db/storage/record_store_test_oplog.cpp index 368ba88278d..6c61f93ee76 100644 --- a/src/mongo/db/storage/record_store_test_oplog.cpp +++ b/src/mongo/db/storage/record_store_test_oplog.cpp @@ -509,5 +509,54 @@ TEST(RecordStoreTestHarness, OplogOrder) { ASSERT(!nextRecord) << stringifyForDebug(opCtx.get(), nextRecord, cursor.get()); } } + +TEST(RecordStoreTestHarness, OplogVisibilityStandalone) { + std::unique_ptr<RecordStoreHarnessHelper> harnessHelper( + newRecordStoreHarnessHelper(RecordStoreHarnessHelper::Options::Standalone)); + std::unique_ptr<RecordStore> rs(harnessHelper->newOplogRecordStore()); + + RecordId id1; + + // insert a document + { + ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext()); + { + WriteUnitOfWork uow(opCtx.get()); + // We must have a "ts" field with a timestamp. + Timestamp ts(5, 1); + BSONObj obj = BSON("ts" << ts); + // However, the insert is not timestamped in standalone mode. + StatusWith<RecordId> res = + rs->insertRecord(opCtx.get(), obj.objdata(), obj.objsize(), Timestamp()); + ASSERT_OK(res.getStatus()); + id1 = res.getValue(); + StatusWith<RecordId> expectedId = record_id_helpers::keyForOptime(ts); + ASSERT_OK(expectedId.getStatus()); + // RecordId should be extracted from 'ts' field when inserting into oplog namespace + ASSERT(expectedId.getValue().compare(id1) == 0); + + uow.commit(); + } + } + + // verify that we can read it + { + ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext()); + auto cursor = rs->getCursor(opCtx.get()); + auto record = cursor->seekExact(id1); + ASSERT(record); + ASSERT_EQ(id1, record->id); + ASSERT(!cursor->next()); + } + + { + ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext()); + auto cursor = rs->getCursor(opCtx.get()); + auto record = cursor->seekNear(RecordId(id1.getLong() + 1)); + ASSERT(record); + ASSERT_EQ(id1, record->id); + ASSERT(!cursor->next()); + } +} } // namespace } // namespace mongo diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_oplog_manager.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_oplog_manager.cpp index 332f3bb0519..fb3bc211faa 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_oplog_manager.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_oplog_manager.cpp @@ -34,6 +34,7 @@ #include <cstring> #include "mongo/db/concurrency/lock_state.h" +#include "mongo/db/repl/replication_coordinator.h" #include "mongo/db/storage/wiredtiger/wiredtiger_kv_engine.h" #include "mongo/db/storage/wiredtiger/wiredtiger_oplog_manager.h" #include "mongo/db/storage/wiredtiger/wiredtiger_util.h" @@ -69,9 +70,14 @@ void WiredTigerOplogManager::startVisibilityThread(OperationContext* opCtx, 1, "Initializing the oplog read timestamp (oplog visibility).", "oplogReadTimestamp"_attr = topOfOplogTimestamp); - } else { + } else if (repl::ReplicationCoordinator::get(opCtx)->isReplEnabled()) { // Avoid setting oplog visibility to 0. That means "everything is visible". setOplogReadTimestamp(Timestamp(StorageEngine::kMinimumTimestamp)); + } else { + // Use max Timestamp to disable oplog visibility in standalone mode. The read timestamp may + // be interpreted as signed so we need to use signed int64_t max to make sure it is always + // larger than any user 'ts' field. + setOplogReadTimestamp(Timestamp(std::numeric_limits<int64_t>::max())); } // Need to obtain the mutex before starting the thread, as otherwise it may race ahead diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test_harness.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test_harness.cpp index 70912221539..0b64d1c2974 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test_harness.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test_harness.cpp @@ -42,7 +42,7 @@ std::string _testLoggingSettings(std::string extraStrings) { } } // namespace -WiredTigerHarnessHelper::WiredTigerHarnessHelper(StringData extraStrings) +WiredTigerHarnessHelper::WiredTigerHarnessHelper(Options options, StringData extraStrings) : _dbpath("wt_test"), _lockerNoopClientObserverRegisterer(getServiceContext()), _engine(kWiredTigerEngineName, @@ -57,14 +57,17 @@ WiredTigerHarnessHelper::WiredTigerHarnessHelper(StringData extraStrings) false) { repl::ReplicationCoordinator::set( serviceContext(), - std::make_unique<repl::ReplicationCoordinatorMock>(serviceContext(), repl::ReplSettings())); + options == Options::ReplicationEnabled + ? std::make_unique<repl::ReplicationCoordinatorMock>(serviceContext()) + : std::make_unique<repl::ReplicationCoordinatorMock>(serviceContext(), + repl::ReplSettings())); _engine.notifyStartupComplete(); } std::unique_ptr<RecordStore> WiredTigerHarnessHelper::newRecordStore( const std::string& ns, const CollectionOptions& collOptions, KeyFormat keyFormat) { - WiredTigerRecoveryUnit* ru = checked_cast<WiredTigerRecoveryUnit*>(_engine.newRecoveryUnit()); - OperationContextNoop opCtx(ru); + ServiceContext::UniqueOperationContext opCtx(newOperationContext()); + WiredTigerRecoveryUnit* ru = checked_cast<WiredTigerRecoveryUnit*>(opCtx->recoveryUnit()); std::string uri = WiredTigerKVEngine::kTableUriPrefix + ns; StringData ident = ns; NamespaceString nss(ns); @@ -81,7 +84,7 @@ std::unique_ptr<RecordStore> WiredTigerHarnessHelper::newRecordStore( std::string config = result.getValue(); { - WriteUnitOfWork uow(&opCtx); + WriteUnitOfWork uow(opCtx.get()); WT_SESSION* s = ru->getSession()->getSession(); invariantWTOK(s->create(s, uri.c_str(), config.c_str()), s); uow.commit(); @@ -102,22 +105,21 @@ std::unique_ptr<RecordStore> WiredTigerHarnessHelper::newRecordStore( params.tracksSizeAdjustments = true; params.forceUpdateWithFullDocument = collOptions.timeseries != boost::none; - auto ret = std::make_unique<StandardWiredTigerRecordStore>(&_engine, &opCtx, params); - ret->postConstructorInit(&opCtx); + auto ret = std::make_unique<StandardWiredTigerRecordStore>(&_engine, opCtx.get(), params); + ret->postConstructorInit(opCtx.get()); return std::move(ret); } std::unique_ptr<RecordStore> WiredTigerHarnessHelper::newOplogRecordStore() { auto ret = newOplogRecordStoreNoInit(); - auto* ru = _engine.newRecoveryUnit(); - OperationContextNoop opCtx(ru); - dynamic_cast<WiredTigerRecordStore*>(ret.get())->postConstructorInit(&opCtx); + ServiceContext::UniqueOperationContext opCtx(newOperationContext()); + dynamic_cast<WiredTigerRecordStore*>(ret.get())->postConstructorInit(opCtx.get()); return ret; } std::unique_ptr<RecordStore> WiredTigerHarnessHelper::newOplogRecordStoreNoInit() { - WiredTigerRecoveryUnit* ru = dynamic_cast<WiredTigerRecoveryUnit*>(_engine.newRecoveryUnit()); - OperationContextNoop opCtx(ru); + ServiceContext::UniqueOperationContext opCtx(newOperationContext()); + WiredTigerRecoveryUnit* ru = checked_cast<WiredTigerRecoveryUnit*>(opCtx->recoveryUnit()); std::string ident = NamespaceString::kRsOplogNamespace.ns(); std::string uri = WiredTigerKVEngine::kTableUriPrefix + ident; @@ -137,7 +139,7 @@ std::unique_ptr<RecordStore> WiredTigerHarnessHelper::newOplogRecordStoreNoInit( std::string config = result.getValue(); { - WriteUnitOfWork uow(&opCtx); + WriteUnitOfWork uow(opCtx.get()); WT_SESSION* s = ru->getSession()->getSession(); invariantWTOK(s->create(s, uri.c_str(), config.c_str()), s); uow.commit(); @@ -159,15 +161,16 @@ std::unique_ptr<RecordStore> WiredTigerHarnessHelper::newOplogRecordStoreNoInit( params.isReadOnly = false; params.tracksSizeAdjustments = true; params.forceUpdateWithFullDocument = false; - return std::make_unique<StandardWiredTigerRecordStore>(&_engine, &opCtx, params); + return std::make_unique<StandardWiredTigerRecordStore>(&_engine, opCtx.get(), params); } std::unique_ptr<RecoveryUnit> WiredTigerHarnessHelper::newRecoveryUnit() { return std::unique_ptr<RecoveryUnit>(_engine.newRecoveryUnit()); } -std::unique_ptr<RecordStoreHarnessHelper> makeWTRSHarnessHelper() { - return std::make_unique<WiredTigerHarnessHelper>(); +std::unique_ptr<RecordStoreHarnessHelper> makeWTRSHarnessHelper( + RecordStoreHarnessHelper::Options options) { + return std::make_unique<WiredTigerHarnessHelper>(options); } MONGO_INITIALIZER(RegisterRecordStoreHarnessFactory)(InitializerContext* const) { diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test_harness.h b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test_harness.h index 97e9b2ad7b4..8a9ef19b16e 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test_harness.h +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test_harness.h @@ -39,9 +39,12 @@ namespace mongo { class WiredTigerHarnessHelper final : public RecordStoreHarnessHelper { public: - WiredTigerHarnessHelper() : WiredTigerHarnessHelper(""_sd) {} + WiredTigerHarnessHelper() : WiredTigerHarnessHelper(Options::ReplicationEnabled, ""_sd) {} + WiredTigerHarnessHelper(Options options) : WiredTigerHarnessHelper(options, ""_sd) {} + WiredTigerHarnessHelper(StringData extraStrings) + : WiredTigerHarnessHelper(Options::ReplicationEnabled, extraStrings) {} - WiredTigerHarnessHelper(StringData extraStrings); + WiredTigerHarnessHelper(Options options, StringData extraStrings); ~WiredTigerHarnessHelper() {} virtual std::unique_ptr<RecordStore> newRecordStore() override { |