diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/base/error_codes.yml | 2 | ||||
-rw-r--r-- | src/mongo/db/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/index_builds_coordinator_mongod.cpp | 12 | ||||
-rw-r--r-- | src/mongo/db/s/SConscript | 3 | ||||
-rw-r--r-- | src/mongo/db/s/global_user_write_block_state.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/user_write_block_mode_op_observer.cpp | 107 | ||||
-rw-r--r-- | src/mongo/db/user_write_block_mode_op_observer.h | 110 | ||||
-rw-r--r-- | src/mongo/db/user_write_block_mode_op_observer_test.cpp | 119 |
8 files changed, 283 insertions, 75 deletions
diff --git a/src/mongo/base/error_codes.yml b/src/mongo/base/error_codes.yml index 809a76b89b9..23fbd301d72 100644 --- a/src/mongo/base/error_codes.yml +++ b/src/mongo/base/error_codes.yml @@ -482,6 +482,8 @@ error_codes: - {code: 369, name: FLETransactionAbort} - {code: 370, name: CannotDropShardKeyIndex} + - {code: 371, name: UserWritesBlocked} + # Error codes 4000-8999 are reserved. # Non-sequential error codes for compatibility only) diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript index 53d0a9067e9..043d2a0d512 100644 --- a/src/mongo/db/SConscript +++ b/src/mongo/db/SConscript @@ -1182,6 +1182,7 @@ env.Library( '$BUILD_DIR/mongo/db/catalog/collection_catalog', '$BUILD_DIR/mongo/db/catalog/index_build_entry_idl', '$BUILD_DIR/mongo/db/repl/tenant_migration_access_blocker', + '$BUILD_DIR/mongo/db/s/forwardable_operation_metadata', '$BUILD_DIR/mongo/db/storage/two_phase_index_build_knobs_idl', '$BUILD_DIR/mongo/executor/task_executor_interface', 'curop', diff --git a/src/mongo/db/index_builds_coordinator_mongod.cpp b/src/mongo/db/index_builds_coordinator_mongod.cpp index 233e9df2fa1..1b98e9c5f67 100644 --- a/src/mongo/db/index_builds_coordinator_mongod.cpp +++ b/src/mongo/db/index_builds_coordinator_mongod.cpp @@ -45,6 +45,7 @@ #include "mongo/db/index_build_entry_helpers.h" #include "mongo/db/operation_context.h" #include "mongo/db/repl/tenant_migration_access_blocker_util.h" +#include "mongo/db/s/forwardable_operation_metadata.h" #include "mongo/db/s/operation_sharding_state.h" #include "mongo/db/service_context.h" #include "mongo/db/stats/resource_consumption_metrics.h" @@ -64,6 +65,7 @@ namespace { MONGO_FAIL_POINT_DEFINE(hangAfterAcquiringIndexBuildSlot); MONGO_FAIL_POINT_DEFINE(hangBeforeInitializingIndexBuild); MONGO_FAIL_POINT_DEFINE(hangIndexBuildAfterSignalPrimaryForCommitReadiness); +MONGO_FAIL_POINT_DEFINE(hangBeforeRunningIndexBuild); const StringData kMaxNumActiveUserIndexBuildsServerParameterName = "maxNumActiveUserIndexBuilds"_sd; @@ -306,6 +308,7 @@ IndexBuildsCoordinatorMongod::_startIndexBuild(OperationContext* opCtx, // Since index builds occur in a separate thread, client attributes that are audited must be // extracted from the client object and passed into the thread separately. audit::ImpersonatedClientAttrs impersonatedClientAttrs(opCtx->getClient()); + ForwardableOperationMetadata forwardableOpMetadata(opCtx); // The thread pool task will be responsible for signalling the condition variable when the index // build thread is done running. @@ -324,7 +327,8 @@ IndexBuildsCoordinatorMongod::_startIndexBuild(OperationContext* opCtx, shardVersion = oss.getShardVersion(nss), dbVersion = oss.getDbVersion(dbName), resumeInfo, - impersonatedClientAttrs = std::move(impersonatedClientAttrs) + impersonatedClientAttrs = std::move(impersonatedClientAttrs), + forwardableOpMetadata = std::move(forwardableOpMetadata) ](auto status) mutable noexcept { ScopeGuard onScopeExitGuard([&] { stdx::unique_lock<Latch> lk(_throttlingMutex); @@ -341,6 +345,10 @@ IndexBuildsCoordinatorMongod::_startIndexBuild(OperationContext* opCtx, auto opCtx = Client::getCurrent()->makeOperationContext(); + // Forward the forwardable operation metadata from the external client to this thread's + // client. + forwardableOpMetadata.setOn(opCtx.get()); + // Load the external client's attributes into this thread's client for auditing. auto authSession = AuthorizationSession::get(opCtx->getClient()); if (authSession) { @@ -385,6 +393,8 @@ IndexBuildsCoordinatorMongod::_startIndexBuild(OperationContext* opCtx, // Signal that the index build started successfully. startPromise.setWith([] {}); + hangBeforeRunningIndexBuild.pauseWhileSet(opCtx.get()); + // Runs the remainder of the index build. Sets the promise result and cleans up the index // build. _runIndexBuild(opCtx.get(), buildUUID, indexBuildOptions, resumeInfo); diff --git a/src/mongo/db/s/SConscript b/src/mongo/db/s/SConscript index d16459c2c44..bf63a589862 100644 --- a/src/mongo/db/s/SConscript +++ b/src/mongo/db/s/SConscript @@ -231,6 +231,9 @@ env.Library( LIBDEPS=[ '$BUILD_DIR/mongo/base', '$BUILD_DIR/mongo/s/grid', + ], + LIBDEPS_PRIVATE=[ + '$BUILD_DIR/mongo/db/write_block_bypass', ] ) diff --git a/src/mongo/db/s/global_user_write_block_state.cpp b/src/mongo/db/s/global_user_write_block_state.cpp index 5bdd8e944c8..0b579d1fcf3 100644 --- a/src/mongo/db/s/global_user_write_block_state.cpp +++ b/src/mongo/db/s/global_user_write_block_state.cpp @@ -59,7 +59,7 @@ void GlobalUserWriteBlockState::disableUserWriteBlocking(OperationContext* opCtx void GlobalUserWriteBlockState::checkUserWritesAllowed(OperationContext* opCtx, const NamespaceString& nss) const { invariant(opCtx->lockState()->isLocked()); - uassert(ErrorCodes::OperationFailed, + uassert(ErrorCodes::UserWritesBlocked, "User writes blocked", !_globalUserWritesBlocked || WriteBlockBypass::get(opCtx).isWriteBlockBypassEnabled() || nss.isOnInternalDb() || nss.isTemporaryReshardingCollection()); @@ -81,7 +81,7 @@ void GlobalUserWriteBlockState::disableUserShardedDDLBlocking(OperationContext* void GlobalUserWriteBlockState::checkShardedDDLAllowedToStart(OperationContext* opCtx, const NamespaceString& nss) const { invariant(serverGlobalParams.clusterRole == ClusterRole::ShardServer); - uassert(ErrorCodes::OperationFailed, + uassert(ErrorCodes::UserWritesBlocked, "User writes blocked", !_userShardedDDLBlocked.load() || WriteBlockBypass::get(opCtx).isWriteBlockBypassEnabled() || nss.isOnInternalDb()); diff --git a/src/mongo/db/user_write_block_mode_op_observer.cpp b/src/mongo/db/user_write_block_mode_op_observer.cpp index 93a7fb2749c..2ef15e1ef20 100644 --- a/src/mongo/db/user_write_block_mode_op_observer.cpp +++ b/src/mongo/db/user_write_block_mode_op_observer.cpp @@ -175,6 +175,113 @@ void UserWriteBlockModeOpObserver::_onReplicationRollback(OperationContext* opCt } } +void UserWriteBlockModeOpObserver::onCreateIndex(OperationContext* opCtx, + const NamespaceString& nss, + const UUID& uuid, + BSONObj indexDoc, + bool fromMigrate) { + _checkWriteAllowed(opCtx, nss); +} + +void UserWriteBlockModeOpObserver::onStartIndexBuild(OperationContext* opCtx, + const NamespaceString& nss, + const UUID& collUUID, + const UUID& indexBuildUUID, + const std::vector<BSONObj>& indexes, + bool fromMigrate) { + _checkWriteAllowed(opCtx, nss); +} + +void UserWriteBlockModeOpObserver::onCommitIndexBuild(OperationContext* opCtx, + const NamespaceString& nss, + const UUID& collUUID, + const UUID& indexBuildUUID, + const std::vector<BSONObj>& indexes, + bool fromMigrate) { + _checkWriteAllowed(opCtx, nss); +} + +void UserWriteBlockModeOpObserver::onStartIndexBuildSinglePhase(OperationContext* opCtx, + const NamespaceString& nss) { + _checkWriteAllowed(opCtx, nss); +} + +void UserWriteBlockModeOpObserver::onCreateCollection(OperationContext* opCtx, + const CollectionPtr& coll, + const NamespaceString& collectionName, + const CollectionOptions& options, + const BSONObj& idIndex, + const OplogSlot& createOpTime, + bool fromMigrate) { + _checkWriteAllowed(opCtx, collectionName); +} + +void UserWriteBlockModeOpObserver::onCollMod(OperationContext* opCtx, + const NamespaceString& nss, + const UUID& uuid, + const BSONObj& collModCmd, + const CollectionOptions& oldCollOptions, + boost::optional<IndexCollModInfo> indexInfo) { + _checkWriteAllowed(opCtx, nss); +} + +void UserWriteBlockModeOpObserver::onDropDatabase(OperationContext* opCtx, + const std::string& dbName) { + _checkWriteAllowed(opCtx, NamespaceString(dbName)); +} + +repl::OpTime UserWriteBlockModeOpObserver::onDropCollection(OperationContext* opCtx, + const NamespaceString& collectionName, + const UUID& uuid, + std::uint64_t numRecords, + CollectionDropType dropType) { + _checkWriteAllowed(opCtx, collectionName); + return repl::OpTime(); +} + +void UserWriteBlockModeOpObserver::onDropIndex(OperationContext* opCtx, + const NamespaceString& nss, + const UUID& uuid, + const std::string& indexName, + const BSONObj& indexInfo) { + _checkWriteAllowed(opCtx, nss); +} + +repl::OpTime UserWriteBlockModeOpObserver::preRenameCollection( + OperationContext* opCtx, + const NamespaceString& fromCollection, + const NamespaceString& toCollection, + const UUID& uuid, + const boost::optional<UUID>& dropTargetUUID, + std::uint64_t numRecords, + bool stayTemp) { + _checkWriteAllowed(opCtx, fromCollection); + _checkWriteAllowed(opCtx, toCollection); + return repl::OpTime(); +} + +void UserWriteBlockModeOpObserver::onRenameCollection(OperationContext* opCtx, + const NamespaceString& fromCollection, + const NamespaceString& toCollection, + const UUID& uuid, + const boost::optional<UUID>& dropTargetUUID, + std::uint64_t numRecords, + bool stayTemp) { + _checkWriteAllowed(opCtx, fromCollection); + _checkWriteAllowed(opCtx, toCollection); +} + +void UserWriteBlockModeOpObserver::onImportCollection(OperationContext* opCtx, + const UUID& importUUID, + const NamespaceString& nss, + long long numRecords, + long long dataSize, + const BSONObj& catalogEntry, + const BSONObj& storageMetadata, + bool isDryRun) { + _checkWriteAllowed(opCtx, nss); +} + void UserWriteBlockModeOpObserver::_checkWriteAllowed(OperationContext* opCtx, const NamespaceString& nss) { // Evaluate write blocking only on replica set primaries. diff --git a/src/mongo/db/user_write_block_mode_op_observer.h b/src/mongo/db/user_write_block_mode_op_observer.h index 38f61233176..5c3e21f12b9 100644 --- a/src/mongo/db/user_write_block_mode_op_observer.h +++ b/src/mongo/db/user_write_block_mode_op_observer.h @@ -47,6 +47,7 @@ public: // Operations to check for allowed writes. + // CUD operations void onInserts(OperationContext* opCtx, const NamespaceString& nss, const UUID& uuid, @@ -62,55 +63,30 @@ public: StmtId stmtId, const OplogDeleteEntryArgs& args) final; - // Noop operations. - + // DDL operations void onCreateIndex(OperationContext* opCtx, const NamespaceString& nss, const UUID& uuid, BSONObj indexDoc, - bool fromMigrate) final {} + bool fromMigrate) final; + // We need to check the startIndexBuild ops because onCreateIndex is only called for empty + // collections. void onStartIndexBuild(OperationContext* opCtx, const NamespaceString& nss, const UUID& collUUID, const UUID& indexBuildUUID, const std::vector<BSONObj>& indexes, - bool fromMigrate) final {} - - void onStartIndexBuildSinglePhase(OperationContext* opCtx, const NamespaceString& nss) final {} - - void onAbortIndexBuildSinglePhase(OperationContext* opCtx, const NamespaceString& nss) final {} + bool fromMigrate) final; void onCommitIndexBuild(OperationContext* opCtx, const NamespaceString& nss, const UUID& collUUID, const UUID& indexBuildUUID, const std::vector<BSONObj>& indexes, - bool fromMigrate) final {} - - void onAbortIndexBuild(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& collUUID, - const UUID& indexBuildUUID, - const std::vector<BSONObj>& indexes, - const Status& cause, - bool fromMigrate) final {} - + bool fromMigrate) final; - void aboutToDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, - const BSONObj& doc) final; - - void onInternalOpMessage(OperationContext* opCtx, - const NamespaceString& nss, - const boost::optional<UUID>& uuid, - const BSONObj& msgObj, - const boost::optional<BSONObj> o2MsgObj, - const boost::optional<repl::OpTime> preImageOpTime, - const boost::optional<repl::OpTime> postImageOpTime, - const boost::optional<repl::OpTime> prevWriteOpTimeInTransaction, - const boost::optional<OplogSlot> slot) final {} + void onStartIndexBuildSinglePhase(OperationContext* opCtx, const NamespaceString& nss) final; void onCreateCollection(OperationContext* opCtx, const CollectionPtr& coll, @@ -118,31 +94,40 @@ public: const CollectionOptions& options, const BSONObj& idIndex, const OplogSlot& createOpTime, - bool fromMigrate) final {} + bool fromMigrate) final; void onCollMod(OperationContext* opCtx, const NamespaceString& nss, const UUID& uuid, const BSONObj& collModCmd, const CollectionOptions& oldCollOptions, - boost::optional<IndexCollModInfo> indexInfo) final {} + boost::optional<IndexCollModInfo> indexInfo) final; - void onDropDatabase(OperationContext* opCtx, const std::string& dbName) final {} + void onDropDatabase(OperationContext* opCtx, const std::string& dbName) final; using OpObserver::onDropCollection; repl::OpTime onDropCollection(OperationContext* opCtx, const NamespaceString& collectionName, const UUID& uuid, std::uint64_t numRecords, - CollectionDropType dropType) final { - return repl::OpTime(); - } + CollectionDropType dropType) final; void onDropIndex(OperationContext* opCtx, const NamespaceString& nss, const UUID& uuid, const std::string& indexName, - const BSONObj& indexInfo) final {} + const BSONObj& indexInfo) final; + + // onRenameCollection is only for renaming to a nonexistent target NS, so we need + // preRenameCollection too. + using OpObserver::preRenameCollection; + repl::OpTime preRenameCollection(OperationContext* opCtx, + const NamespaceString& fromCollection, + const NamespaceString& toCollection, + const UUID& uuid, + const boost::optional<UUID>& dropTargetUUID, + std::uint64_t numRecords, + bool stayTemp) final; using OpObserver::onRenameCollection; void onRenameCollection(OperationContext* opCtx, @@ -151,7 +136,7 @@ public: const UUID& uuid, const boost::optional<UUID>& dropTargetUUID, std::uint64_t numRecords, - bool stayTemp) final {} + bool stayTemp) final; void onImportCollection(OperationContext* opCtx, const UUID& importUUID, @@ -160,19 +145,40 @@ public: long long dataSize, const BSONObj& catalogEntry, const BSONObj& storageMetadata, - bool isDryRun) final {} + bool isDryRun) final; - using OpObserver::preRenameCollection; - repl::OpTime preRenameCollection(OperationContext* opCtx, - const NamespaceString& fromCollection, - const NamespaceString& toCollection, - const UUID& uuid, - const boost::optional<UUID>& dropTargetUUID, - std::uint64_t numRecords, - bool stayTemp) final { - return repl::OpTime(); - } + // Note aboutToDelete is unchecked, but defined. + void aboutToDelete(OperationContext* opCtx, + const NamespaceString& nss, + const UUID& uuid, + const BSONObj& doc) final; + + // Noop operations (don't perform any check). + + // At the moment we are leaving the onAbortIndexBuilds as unchecked. This is because they can be + // called from both user and internal codepaths, and we don't want to risk throwing an assert + // for the internal paths. + void onAbortIndexBuildSinglePhase(OperationContext* opCtx, const NamespaceString& nss) final {} + + void onAbortIndexBuild(OperationContext* opCtx, + const NamespaceString& nss, + const UUID& collUUID, + const UUID& indexBuildUUID, + const std::vector<BSONObj>& indexes, + const Status& cause, + bool fromMigrate) final {} + + void onInternalOpMessage(OperationContext* opCtx, + const NamespaceString& nss, + const boost::optional<UUID>& uuid, + const BSONObj& msgObj, + const boost::optional<BSONObj> o2MsgObj, + const boost::optional<repl::OpTime> preImageOpTime, + const boost::optional<repl::OpTime> postImageOpTime, + const boost::optional<repl::OpTime> prevWriteOpTimeInTransaction, + const boost::optional<OplogSlot> slot) final {} + // We don't need to check this and preRenameCollection (they are in the same WUOW). void postRenameCollection(OperationContext* opCtx, const NamespaceString& fromCollection, const NamespaceString& toCollection, @@ -180,6 +186,8 @@ public: const boost::optional<UUID>& dropTargetUUID, bool stayTemp) final {} + // The transaction commit related hooks don't need to be checked, because all of the operations + // inside the transaction are checked and they all execute in one WUOW. void onApplyOps(OperationContext* opCtx, const std::string& dbName, const BSONObj& applyOpCmd) final {} diff --git a/src/mongo/db/user_write_block_mode_op_observer_test.cpp b/src/mongo/db/user_write_block_mode_op_observer_test.cpp index 1f1f1b9a9b5..512f42b7003 100644 --- a/src/mongo/db/user_write_block_mode_op_observer_test.cpp +++ b/src/mongo/db/user_write_block_mode_op_observer_test.cpp @@ -62,12 +62,12 @@ public: } protected: - // Ensure that inserts, updates, and deletes with the given opCtx on the given namespace will - // succeed or fail depending on the value of shouldSucceed. + // Ensure that CUD ops with the given opCtx on the given namespace will succeed or fail + // depending on the value of shouldSucceed. void runCUD(OperationContext* opCtx, const NamespaceString& nss, bool shouldSucceed, - bool fromMigrate = false) { + bool fromMigrate) { UserWriteBlockModeOpObserver opObserver; std::vector<InsertStatement> inserts; CollectionUpdateArgs collectionUpdateArgs; @@ -78,7 +78,6 @@ protected: updateArgs.nss = nss; OplogDeleteEntryArgs deleteArgs; deleteArgs.fromMigrate = fromMigrate; - if (shouldSucceed) { try { opObserver.onInserts(opCtx, nss, uuid, inserts.begin(), inserts.end(), fromMigrate); @@ -98,6 +97,83 @@ protected: } } + // Ensure that all checked ops with the given opCtx on the given namespace will + // succeed or fail depending on the value of shouldSucceed. + void runCheckedOps(OperationContext* opCtx, + const NamespaceString& nss, + bool shouldSucceed, + bool fromMigrate = false) { + runCUD(opCtx, nss, shouldSucceed, fromMigrate); + UserWriteBlockModeOpObserver opObserver; + auto uuid = UUID::gen(); + NamespaceString adminNss = NamespaceString("admin"); + + if (shouldSucceed) { + try { + opObserver.onCreateIndex(opCtx, nss, uuid, BSONObj(), false); + opObserver.onStartIndexBuild(opCtx, nss, uuid, uuid, {}, false); + opObserver.onStartIndexBuildSinglePhase(opCtx, nss); + opObserver.onCreateCollection( + opCtx, nullptr, nss, {}, BSONObj(), OplogSlot(), false); + opObserver.onCollMod(opCtx, nss, uuid, BSONObj(), {}, boost::none); + opObserver.onDropDatabase(opCtx, std::string(nss.db())); + opObserver.onDropCollection( + opCtx, + nss, + uuid, + 0, + UserWriteBlockModeOpObserver::CollectionDropType::kOnePhase); + opObserver.onDropIndex(opCtx, nss, uuid, "", BSONObj()); + // For renames, make sure we check both from and to for the given namespace + opObserver.preRenameCollection(opCtx, nss, adminNss, uuid, boost::none, 0, false); + opObserver.preRenameCollection(opCtx, adminNss, nss, uuid, boost::none, 0, false); + opObserver.onRenameCollection(opCtx, nss, adminNss, uuid, boost::none, 0, false); + opObserver.onRenameCollection(opCtx, adminNss, nss, uuid, boost::none, 0, false); + opObserver.onImportCollection(opCtx, uuid, nss, 0, 0, BSONObj(), BSONObj(), false); + } catch (...) { + // Make it easier to see that this is where we failed. + ASSERT_OK(exceptionToStatus()); + } + } else { + ASSERT_THROWS(opObserver.onCreateIndex(opCtx, nss, uuid, BSONObj(), false), + AssertionException); + ASSERT_THROWS(opObserver.onStartIndexBuild(opCtx, nss, uuid, uuid, {}, false), + AssertionException); + ASSERT_THROWS(opObserver.onStartIndexBuildSinglePhase(opCtx, nss), AssertionException); + ASSERT_THROWS(opObserver.onCreateCollection( + opCtx, nullptr, nss, {}, BSONObj(), OplogSlot(), false), + AssertionException); + ASSERT_THROWS(opObserver.onCollMod(opCtx, nss, uuid, BSONObj(), {}, boost::none), + AssertionException); + ASSERT_THROWS(opObserver.onDropDatabase(opCtx, std::string(nss.db())), + AssertionException); + ASSERT_THROWS(opObserver.onDropCollection( + opCtx, + nss, + uuid, + 0, + UserWriteBlockModeOpObserver::CollectionDropType::kOnePhase), + AssertionException); + ASSERT_THROWS(opObserver.onDropIndex(opCtx, nss, uuid, "", BSONObj()), + AssertionException); + ASSERT_THROWS( + opObserver.preRenameCollection(opCtx, nss, adminNss, uuid, boost::none, 0, false), + AssertionException); + ASSERT_THROWS( + opObserver.preRenameCollection(opCtx, adminNss, nss, uuid, boost::none, 0, false), + AssertionException); + ASSERT_THROWS( + opObserver.onRenameCollection(opCtx, nss, adminNss, uuid, boost::none, 0, false), + AssertionException); + ASSERT_THROWS( + opObserver.onRenameCollection(opCtx, adminNss, nss, uuid, boost::none, 0, false), + AssertionException); + ASSERT_THROWS( + opObserver.onImportCollection(opCtx, uuid, nss, 0, 0, BSONObj(), BSONObj(), false), + AssertionException); + } + } + private: // Creates a reasonable set of ReplSettings for most tests. repl::ReplSettings createReplSettings() { @@ -117,10 +193,10 @@ TEST_F(UserWriteBlockModeOpObserverTest, WriteBlockingDisabledNoBypass) { ASSERT(!WriteBlockBypass::get(opCtx.get()).isWriteBlockBypassEnabled()); // Ensure writes succeed - runCUD(opCtx.get(), NamespaceString("a.b"), true); - runCUD(opCtx.get(), NamespaceString("admin"), true); - runCUD(opCtx.get(), NamespaceString("local"), true); - runCUD(opCtx.get(), NamespaceString("config"), true); + runCheckedOps(opCtx.get(), NamespaceString("a.b"), true); + runCheckedOps(opCtx.get(), NamespaceString("admin"), true); + runCheckedOps(opCtx.get(), NamespaceString("local"), true); + runCheckedOps(opCtx.get(), NamespaceString("config"), true); } TEST_F(UserWriteBlockModeOpObserverTest, WriteBlockingDisabledWithBypass) { @@ -137,10 +213,10 @@ TEST_F(UserWriteBlockModeOpObserverTest, WriteBlockingDisabledWithBypass) { ASSERT(WriteBlockBypass::get(opCtx.get()).isWriteBlockBypassEnabled()); // Ensure writes succeed - runCUD(opCtx.get(), NamespaceString("a.b"), true); - runCUD(opCtx.get(), NamespaceString("admin"), true); - runCUD(opCtx.get(), NamespaceString("local"), true); - runCUD(opCtx.get(), NamespaceString("config"), true); + runCheckedOps(opCtx.get(), NamespaceString("a.b"), true); + runCheckedOps(opCtx.get(), NamespaceString("admin"), true); + runCheckedOps(opCtx.get(), NamespaceString("local"), true); + runCheckedOps(opCtx.get(), NamespaceString("config"), true); } TEST_F(UserWriteBlockModeOpObserverTest, WriteBlockingEnabledNoBypass) { @@ -152,12 +228,12 @@ TEST_F(UserWriteBlockModeOpObserverTest, WriteBlockingEnabledNoBypass) { ASSERT(!WriteBlockBypass::get(opCtx.get()).isWriteBlockBypassEnabled()); // Ensure user writes now fail, while non-user writes still succeed - runCUD(opCtx.get(), NamespaceString("a.b"), false); - runCUD(opCtx.get(), NamespaceString("admin"), true); - runCUD(opCtx.get(), NamespaceString("local"), true); - runCUD(opCtx.get(), NamespaceString("config"), true); + runCheckedOps(opCtx.get(), NamespaceString("a.b"), false); + runCheckedOps(opCtx.get(), NamespaceString("admin"), true); + runCheckedOps(opCtx.get(), NamespaceString("local"), true); + runCheckedOps(opCtx.get(), NamespaceString("config"), true); - // Ensure that writes from migrations succeed + // Ensure that CUD ops from migrations succeed runCUD(opCtx.get(), NamespaceString("a.b"), true, true /* fromMigrate */); } @@ -175,10 +251,11 @@ TEST_F(UserWriteBlockModeOpObserverTest, WriteBlockingEnabledWithBypass) { ASSERT(WriteBlockBypass::get(opCtx.get()).isWriteBlockBypassEnabled()); // Ensure user writes succeed - runCUD(opCtx.get(), NamespaceString("a.b"), true); - runCUD(opCtx.get(), NamespaceString("admin"), true); - runCUD(opCtx.get(), NamespaceString("local"), true); - runCUD(opCtx.get(), NamespaceString("config"), true); + + runCheckedOps(opCtx.get(), NamespaceString("a.b"), true); + runCheckedOps(opCtx.get(), NamespaceString("admin"), true); + runCheckedOps(opCtx.get(), NamespaceString("local"), true); + runCheckedOps(opCtx.get(), NamespaceString("config"), true); } } // namespace |