diff options
author | Misha Tyulenev <misha@mongodb.com> | 2015-10-13 10:50:52 -0400 |
---|---|---|
committer | Misha Tyulenev <misha@mongodb.com> | 2015-10-13 11:25:41 -0400 |
commit | 920517cb2d6ca9eaf48b5be9b0f00360457667ca (patch) | |
tree | 57720a21f91eb2638a11b5c590853d058eaaaeba /src | |
parent | cda9ac3ae9c629fbbd04819fecc8a74126ed6ea0 (diff) | |
download | mongo-920517cb2d6ca9eaf48b5be9b0f00360457667ca.tar.gz |
SERVER-20082 add maxTimeMs to config catalog operations
Diffstat (limited to 'src')
27 files changed, 497 insertions, 308 deletions
diff --git a/src/mongo/db/auth/user_management_commands_parser.cpp b/src/mongo/db/auth/user_management_commands_parser.cpp index 54109d14bf7..da0714f12a3 100644 --- a/src/mongo/db/auth/user_management_commands_parser.cpp +++ b/src/mongo/db/auth/user_management_commands_parser.cpp @@ -166,6 +166,7 @@ Status parseRolePossessionManipulationCommands(const BSONObj& cmdObj, validFieldNames.insert(cmdName.toString()); validFieldNames.insert("roles"); validFieldNames.insert("writeConcern"); + validFieldNames.insert("maxTimeMS"); Status status = _checkNoExtraFields(cmdObj, cmdName, validFieldNames); if (!status.isOK()) { @@ -212,6 +213,7 @@ Status parseCreateOrUpdateUserCommands(const BSONObj& cmdObj, validFieldNames.insert("pwd"); validFieldNames.insert("roles"); validFieldNames.insert("writeConcern"); + validFieldNames.insert("maxTimeMS"); Status status = _checkNoExtraFields(cmdObj, cmdName, validFieldNames); if (!status.isOK()) { @@ -296,6 +298,7 @@ Status parseAndValidateDropUserCommand(const BSONObj& cmdObj, unordered_set<std::string> validFieldNames; validFieldNames.insert("dropUser"); validFieldNames.insert("writeConcern"); + validFieldNames.insert("maxTimeMS"); Status status = _checkNoExtraFields(cmdObj, "dropUser", validFieldNames); if (!status.isOK()) { @@ -324,6 +327,7 @@ Status parseFromDatabaseCommand(const BSONObj& cmdObj, unordered_set<std::string> validFieldNames; validFieldNames.insert(command); validFieldNames.insert("writeConcern"); + validFieldNames.insert("maxTimeMS"); Status status = _checkNoExtraFields(cmdObj, command, validFieldNames); if (!status.isOK()) { @@ -348,6 +352,7 @@ Status parseUsersInfoCommand(const BSONObj& cmdObj, StringData dbname, UsersInfo validFieldNames.insert("usersInfo"); validFieldNames.insert("showPrivileges"); validFieldNames.insert("showCredentials"); + validFieldNames.insert("maxTimeMS"); Status status = _checkNoExtraFields(cmdObj, "usersInfo", validFieldNames); if (!status.isOK()) { @@ -394,6 +399,7 @@ Status parseRolesInfoCommand(const BSONObj& cmdObj, StringData dbname, RolesInfo validFieldNames.insert("rolesInfo"); validFieldNames.insert("showPrivileges"); validFieldNames.insert("showBuiltinRoles"); + validFieldNames.insert("maxTimeMS"); Status status = _checkNoExtraFields(cmdObj, "rolesInfo", validFieldNames); if (!status.isOK()) { @@ -477,6 +483,7 @@ Status parseCreateOrUpdateRoleCommands(const BSONObj& cmdObj, validFieldNames.insert("privileges"); validFieldNames.insert("roles"); validFieldNames.insert("writeConcern"); + validFieldNames.insert("maxTimeMS"); Status status = _checkNoExtraFields(cmdObj, cmdName, validFieldNames); if (!status.isOK()) { @@ -537,6 +544,7 @@ Status parseAndValidateRolePrivilegeManipulationCommands(const BSONObj& cmdObj, validFieldNames.insert(cmdName.toString()); validFieldNames.insert("privileges"); validFieldNames.insert("writeConcern"); + validFieldNames.insert("maxTimeMS"); Status status = _checkNoExtraFields(cmdObj, cmdName, validFieldNames); if (!status.isOK()) { @@ -584,6 +592,7 @@ Status parseDropRoleCommand(const BSONObj& cmdObj, unordered_set<std::string> validFieldNames; validFieldNames.insert("dropRole"); validFieldNames.insert("writeConcern"); + validFieldNames.insert("maxTimeMS"); Status status = _checkNoExtraFields(cmdObj, "dropRole", validFieldNames); if (!status.isOK()) { @@ -620,6 +629,7 @@ Status parseMergeAuthzCollectionsCommand(const BSONObj& cmdObj, validFieldNames.insert("db"); validFieldNames.insert("drop"); validFieldNames.insert("writeConcern"); + validFieldNames.insert("maxTimeMS"); Status status = _checkNoExtraFields(cmdObj, "_mergeAuthzCollections", validFieldNames); if (!status.isOK()) { @@ -673,6 +683,7 @@ Status parseAuthSchemaUpgradeCommand(const BSONObj& cmdObj, validFieldNames.insert("maxSteps"); validFieldNames.insert("upgradeShards"); validFieldNames.insert("writeConcern"); + validFieldNames.insert("maxTimeMS"); Status status = _checkNoExtraFields(cmdObj, "authSchemaUpgrade", validFieldNames); if (!status.isOK()) { diff --git a/src/mongo/s/catalog/catalog_manager_common.cpp b/src/mongo/s/catalog/catalog_manager_common.cpp index 92f9f6def61..14f2c3e5c8c 100644 --- a/src/mongo/s/catalog/catalog_manager_common.cpp +++ b/src/mongo/s/catalog/catalog_manager_common.cpp @@ -425,7 +425,7 @@ Status CatalogManagerCommon::createDatabase(OperationContext* txn, const std::st // Lock the database globally to prevent conflicts with simultaneous database creation. auto scopedDistLock = - getDistLockManager()->lock(dbName, "createDatabase", Seconds{5}, Milliseconds{500}); + getDistLockManager()->lock(txn, dbName, "createDatabase", Seconds{5}, Milliseconds{500}); if (!scopedDistLock.isOK()) { return scopedDistLock.getStatus(); } @@ -509,7 +509,7 @@ Status CatalogManagerCommon::enableSharding(OperationContext* txn, const std::st // Lock the database globally to prevent conflicts with simultaneous database // creation/modification. auto scopedDistLock = - getDistLockManager()->lock(dbName, "enableSharding", Seconds{5}, Milliseconds{500}); + getDistLockManager()->lock(txn, dbName, "enableSharding", Seconds{5}, Milliseconds{500}); if (!scopedDistLock.isOK()) { return scopedDistLock.getStatus(); } diff --git a/src/mongo/s/catalog/dist_lock_catalog.h b/src/mongo/s/catalog/dist_lock_catalog.h index 3c83e0433a7..516cff281d4 100644 --- a/src/mongo/s/catalog/dist_lock_catalog.h +++ b/src/mongo/s/catalog/dist_lock_catalog.h @@ -36,6 +36,7 @@ namespace mongo { class LockpingsType; class LocksType; +class OperationContext; class Status; template <typename T> class StatusWith; @@ -66,13 +67,13 @@ public: * Returns the ping document of the specified processID. * Common status errors include socket errors. */ - virtual StatusWith<LockpingsType> getPing(StringData processID) = 0; + virtual StatusWith<LockpingsType> getPing(OperationContext* txn, StringData processID) = 0; /** * Updates the ping document. Creates a new entry if it does not exists. * Common status errors include socket errors. */ - virtual Status ping(StringData processID, Date_t ping) = 0; + virtual Status ping(OperationContext* txn, StringData processID, Date_t ping) = 0; /** * Attempts to update the owner of a lock identified by lockID to lockSessionID. @@ -90,7 +91,8 @@ public: * * Common status errors include socket and duplicate key errors. */ - virtual StatusWith<LocksType> grabLock(StringData lockID, + virtual StatusWith<LocksType> grabLock(OperationContext* txn, + StringData lockID, const OID& lockSessionID, StringData who, StringData processId, @@ -112,7 +114,8 @@ public: * * Common status errors include socket errors. */ - virtual StatusWith<LocksType> overtakeLock(StringData lockID, + virtual StatusWith<LocksType> overtakeLock(OperationContext* txn, + StringData lockID, const OID& lockSessionID, const OID& currentHolderTS, StringData who, @@ -124,31 +127,31 @@ public: * Attempts to set the state of the lock document with lockSessionID to unlocked. * Common status errors include socket errors. */ - virtual Status unlock(const OID& lockSessionID) = 0; + virtual Status unlock(OperationContext* txn, const OID& lockSessionID) = 0; /** * Get some information from the config server primary. * Common status errors include socket errors. */ - virtual StatusWith<ServerInfo> getServerInfo() = 0; + virtual StatusWith<ServerInfo> getServerInfo(OperationContext* txn) = 0; /** * Returns the lock document. * Returns LockNotFound if lock document doesn't exist. * Common status errors include socket errors. */ - virtual StatusWith<LocksType> getLockByTS(const OID& lockSessionID) = 0; + virtual StatusWith<LocksType> getLockByTS(OperationContext* txn, const OID& lockSessionID) = 0; /** * Returns the lock document. * Common status errors include socket errors. */ - virtual StatusWith<LocksType> getLockByName(StringData name) = 0; + virtual StatusWith<LocksType> getLockByName(OperationContext* txn, StringData name) = 0; /** * Attempts to delete the ping document corresponding to the given processId. * Common status errors include socket errors. */ - virtual Status stopPing(StringData processId) = 0; + virtual Status stopPing(OperationContext* txn, StringData processId) = 0; }; } diff --git a/src/mongo/s/catalog/dist_lock_catalog_impl.cpp b/src/mongo/s/catalog/dist_lock_catalog_impl.cpp index 87c41729056..46108e3cf13 100644 --- a/src/mongo/s/catalog/dist_lock_catalog_impl.cpp +++ b/src/mongo/s/catalog/dist_lock_catalog_impl.cpp @@ -153,9 +153,10 @@ DistLockCatalogImpl::DistLockCatalogImpl(ShardRegistry* shardRegistry, DistLockCatalogImpl::~DistLockCatalogImpl() = default; -StatusWith<LockpingsType> DistLockCatalogImpl::getPing(StringData processID) { +StatusWith<LockpingsType> DistLockCatalogImpl::getPing(OperationContext* txn, + StringData processID) { auto findResult = _findOnConfig( - kReadPref, _lockPingNS, BSON(LockpingsType::process() << processID), BSONObj(), 1); + txn, kReadPref, _lockPingNS, BSON(LockpingsType::process() << processID), BSONObj(), 1); if (!findResult.isOK()) { return findResult.getStatus(); @@ -179,7 +180,7 @@ StatusWith<LockpingsType> DistLockCatalogImpl::getPing(StringData processID) { return pingDocResult.getValue(); } -Status DistLockCatalogImpl::ping(StringData processID, Date_t ping) { +Status DistLockCatalogImpl::ping(OperationContext* txn, StringData processID, Date_t ping) { auto request = FindAndModifyRequest::makeUpdate(_lockPingNS, BSON(LockpingsType::process() << processID), @@ -187,8 +188,8 @@ Status DistLockCatalogImpl::ping(StringData processID, Date_t ping) { request.setUpsert(true); request.setWriteConcern(_writeConcern); - auto resultStatus = - _client->runCommandOnConfigWithNotMasterRetries(_locksNS.db().toString(), request.toBSON()); + auto resultStatus = _client->runCommandOnConfigWithNotMasterRetries( + txn, _locksNS.db().toString(), request.toBSON()); if (!resultStatus.isOK()) { return resultStatus.getStatus(); @@ -199,7 +200,8 @@ Status DistLockCatalogImpl::ping(StringData processID, Date_t ping) { return findAndModifyStatus.getStatus(); } -StatusWith<LocksType> DistLockCatalogImpl::grabLock(StringData lockID, +StatusWith<LocksType> DistLockCatalogImpl::grabLock(OperationContext* txn, + StringData lockID, const OID& lockSessionID, StringData who, StringData processId, @@ -218,8 +220,8 @@ StatusWith<LocksType> DistLockCatalogImpl::grabLock(StringData lockID, request.setShouldReturnNew(true); request.setWriteConcern(_writeConcern); - auto resultStatus = - _client->runCommandOnConfigWithNotMasterRetries(_locksNS.db().toString(), request.toBSON()); + auto resultStatus = _client->runCommandOnConfigWithNotMasterRetries( + txn, _locksNS.db().toString(), request.toBSON()); if (!resultStatus.isOK()) { return resultStatus.getStatus(); @@ -249,7 +251,8 @@ StatusWith<LocksType> DistLockCatalogImpl::grabLock(StringData lockID, return locksTypeResult.getValue(); } -StatusWith<LocksType> DistLockCatalogImpl::overtakeLock(StringData lockID, +StatusWith<LocksType> DistLockCatalogImpl::overtakeLock(OperationContext* txn, + StringData lockID, const OID& lockSessionID, const OID& currentHolderTS, StringData who, @@ -271,8 +274,8 @@ StatusWith<LocksType> DistLockCatalogImpl::overtakeLock(StringData lockID, request.setShouldReturnNew(true); request.setWriteConcern(_writeConcern); - auto resultStatus = - _client->runCommandOnConfigWithNotMasterRetries(_locksNS.db().toString(), request.toBSON()); + auto resultStatus = _client->runCommandOnConfigWithNotMasterRetries( + txn, _locksNS.db().toString(), request.toBSON()); if (!resultStatus.isOK()) { return resultStatus.getStatus(); @@ -296,15 +299,15 @@ StatusWith<LocksType> DistLockCatalogImpl::overtakeLock(StringData lockID, return locksTypeResult.getValue(); } -Status DistLockCatalogImpl::unlock(const OID& lockSessionID) { +Status DistLockCatalogImpl::unlock(OperationContext* txn, const OID& lockSessionID) { auto request = FindAndModifyRequest::makeUpdate( _locksNS, BSON(LocksType::lockID(lockSessionID)), BSON("$set" << BSON(LocksType::state(LocksType::UNLOCKED)))); request.setWriteConcern(_writeConcern); - auto resultStatus = - _client->runCommandOnConfigWithNotMasterRetries(_locksNS.db().toString(), request.toBSON()); + auto resultStatus = _client->runCommandOnConfigWithNotMasterRetries( + txn, _locksNS.db().toString(), request.toBSON()); if (!resultStatus.isOK()) { return resultStatus.getStatus(); @@ -324,8 +327,9 @@ Status DistLockCatalogImpl::unlock(const OID& lockSessionID) { return findAndModifyStatus; } -StatusWith<DistLockCatalog::ServerInfo> DistLockCatalogImpl::getServerInfo() { - auto resultStatus = _client->runCommandOnConfig(kReadPref, "admin", BSON("serverStatus" << 1)); +StatusWith<DistLockCatalog::ServerInfo> DistLockCatalogImpl::getServerInfo(OperationContext* txn) { + auto resultStatus = + _client->runCommandOnConfig(txn, kReadPref, "admin", BSON("serverStatus" << 1)); if (!resultStatus.isOK()) { return resultStatus.getStatus(); @@ -356,9 +360,10 @@ StatusWith<DistLockCatalog::ServerInfo> DistLockCatalogImpl::getServerInfo() { return DistLockCatalog::ServerInfo(localTimeElem.date(), electionIdStatus.getValue()); } -StatusWith<LocksType> DistLockCatalogImpl::getLockByTS(const OID& lockSessionID) { - auto findResult = - _findOnConfig(kReadPref, _locksNS, BSON(LocksType::lockID(lockSessionID)), BSONObj(), 1); +StatusWith<LocksType> DistLockCatalogImpl::getLockByTS(OperationContext* txn, + const OID& lockSessionID) { + auto findResult = _findOnConfig( + txn, kReadPref, _locksNS, BSON(LocksType::lockID(lockSessionID)), BSONObj(), 1); if (!findResult.isOK()) { return findResult.getStatus(); @@ -382,9 +387,9 @@ StatusWith<LocksType> DistLockCatalogImpl::getLockByTS(const OID& lockSessionID) return locksTypeResult.getValue(); } -StatusWith<LocksType> DistLockCatalogImpl::getLockByName(StringData name) { +StatusWith<LocksType> DistLockCatalogImpl::getLockByName(OperationContext* txn, StringData name) { auto findResult = - _findOnConfig(kReadPref, _locksNS, BSON(LocksType::name() << name), BSONObj(), 1); + _findOnConfig(txn, kReadPref, _locksNS, BSON(LocksType::name() << name), BSONObj(), 1); if (!findResult.isOK()) { return findResult.getStatus(); @@ -408,13 +413,13 @@ StatusWith<LocksType> DistLockCatalogImpl::getLockByName(StringData name) { return locksTypeResult.getValue(); } -Status DistLockCatalogImpl::stopPing(StringData processId) { +Status DistLockCatalogImpl::stopPing(OperationContext* txn, StringData processId) { auto request = FindAndModifyRequest::makeRemove(_lockPingNS, BSON(LockpingsType::process() << processId)); request.setWriteConcern(_writeConcern); - auto resultStatus = - _client->runCommandOnConfigWithNotMasterRetries(_locksNS.db().toString(), request.toBSON()); + auto resultStatus = _client->runCommandOnConfigWithNotMasterRetries( + txn, _locksNS.db().toString(), request.toBSON()); if (!resultStatus.isOK()) { return resultStatus.getStatus(); @@ -427,13 +432,15 @@ Status DistLockCatalogImpl::stopPing(StringData processId) { } StatusWith<vector<BSONObj>> DistLockCatalogImpl::_findOnConfig( + OperationContext* txn, const ReadPreferenceSetting& readPref, const NamespaceString& nss, const BSONObj& query, const BSONObj& sort, boost::optional<long long> limit) { repl::ReadConcernArgs readConcern(boost::none, repl::ReadConcernLevel::kMajorityReadConcern); - auto result = _client->exhaustiveFindOnConfig(readPref, nss, query, sort, limit, readConcern); + auto result = + _client->exhaustiveFindOnConfig(txn, readPref, nss, query, sort, limit, readConcern); if (!result.isOK()) { return result.getStatus(); diff --git a/src/mongo/s/catalog/dist_lock_catalog_impl.h b/src/mongo/s/catalog/dist_lock_catalog_impl.h index a38aaf088f7..61047943dd6 100644 --- a/src/mongo/s/catalog/dist_lock_catalog_impl.h +++ b/src/mongo/s/catalog/dist_lock_catalog_impl.h @@ -51,18 +51,20 @@ public: virtual ~DistLockCatalogImpl(); - virtual StatusWith<LockpingsType> getPing(StringData processID) override; + virtual StatusWith<LockpingsType> getPing(OperationContext* txn, StringData processID) override; - virtual Status ping(StringData processID, Date_t ping) override; + virtual Status ping(OperationContext* txn, StringData processID, Date_t ping) override; - virtual StatusWith<LocksType> grabLock(StringData lockID, + virtual StatusWith<LocksType> grabLock(OperationContext* txn, + StringData lockID, const OID& lockSessionID, StringData who, StringData processId, Date_t time, StringData why) override; - virtual StatusWith<LocksType> overtakeLock(StringData lockID, + virtual StatusWith<LocksType> overtakeLock(OperationContext* txn, + StringData lockID, const OID& lockSessionID, const OID& currentHolderTS, StringData who, @@ -70,18 +72,20 @@ public: Date_t time, StringData why) override; - virtual Status unlock(const OID& lockSessionID) override; + virtual Status unlock(OperationContext* txn, const OID& lockSessionID) override; - virtual StatusWith<ServerInfo> getServerInfo() override; + virtual StatusWith<ServerInfo> getServerInfo(OperationContext* txn) override; - virtual StatusWith<LocksType> getLockByTS(const OID& lockSessionID) override; + virtual StatusWith<LocksType> getLockByTS(OperationContext* txn, + const OID& lockSessionID) override; - virtual StatusWith<LocksType> getLockByName(StringData name) override; + virtual StatusWith<LocksType> getLockByName(OperationContext* txn, StringData name) override; - virtual Status stopPing(StringData processId) override; + virtual Status stopPing(OperationContext* txn, StringData processId) override; private: - StatusWith<std::vector<BSONObj>> _findOnConfig(const ReadPreferenceSetting& readPref, + StatusWith<std::vector<BSONObj>> _findOnConfig(OperationContext* txn, + const ReadPreferenceSetting& readPref, const NamespaceString& nss, const BSONObj& query, const BSONObj& sort, diff --git a/src/mongo/s/catalog/dist_lock_catalog_impl_test.cpp b/src/mongo/s/catalog/dist_lock_catalog_impl_test.cpp index 88e6c7db50a..45d3f8cecdb 100644 --- a/src/mongo/s/catalog/dist_lock_catalog_impl_test.cpp +++ b/src/mongo/s/catalog/dist_lock_catalog_impl_test.cpp @@ -37,6 +37,7 @@ #include "mongo/client/remote_command_targeter_mock.h" #include "mongo/db/commands.h" #include "mongo/db/jsobj.h" +#include "mongo/db/operation_context_noop.h" #include "mongo/db/query/find_and_modify_request.h" #include "mongo/db/repl/read_concern_args.h" #include "mongo/executor/network_interface_mock.h" @@ -103,6 +104,10 @@ public: } } + OperationContext* txn() { + return &_txn; + } + private: void setUp() override { auto networkUniquePtr = stdx::make_unique<executor::NetworkInterfaceMock>(); @@ -139,6 +144,7 @@ private: std::unique_ptr<ShardRegistry> _shardRegistry; std::unique_ptr<DistLockCatalogImpl> _distLockCatalog; + OperationContextNoop _txn; }; void checkReadConcern(const BSONObj& findCmd) { @@ -150,7 +156,7 @@ void checkReadConcern(const BSONObj& findCmd) { TEST_F(DistLockCatalogFixture, BasicPing) { auto future = launchAsync([this] { Date_t ping(dateFromISOString("2014-03-11T09:17:18.098Z").getValue()); - auto status = catalog()->ping("abcd", ping); + auto status = catalog()->ping(txn(), "abcd", ping); ASSERT_OK(status); }); @@ -167,7 +173,8 @@ TEST_F(DistLockCatalogFixture, BasicPing) { } }, upsert: true, - writeConcern: { w: "majority", wtimeout: 100 } + writeConcern: { w: "majority", wtimeout: 100 }, + maxTimeMS: 30000 })")); ASSERT_EQUALS(expectedCmd, request.cmdObj); @@ -186,21 +193,21 @@ TEST_F(DistLockCatalogFixture, BasicPing) { TEST_F(DistLockCatalogFixture, PingTargetError) { targeter()->setFindHostReturnValue({ErrorCodes::InternalError, "can't target"}); - auto status = catalog()->ping("abcd", Date_t::now()); + auto status = catalog()->ping(txn(), "abcd", Date_t::now()); ASSERT_NOT_OK(status); } TEST_F(DistLockCatalogFixture, PingRunCmdError) { shutdownShardRegistry(); - auto status = catalog()->ping("abcd", Date_t::now()); + auto status = catalog()->ping(txn(), "abcd", Date_t::now()); ASSERT_EQUALS(ErrorCodes::ShutdownInProgress, status.code()); ASSERT_FALSE(status.reason().empty()); } TEST_F(DistLockCatalogFixture, PingCommandError) { auto future = launchAsync([this] { - auto status = catalog()->ping("abcd", Date_t::now()); + auto status = catalog()->ping(txn(), "abcd", Date_t::now()); ASSERT_EQUALS(ErrorCodes::FailedToParse, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -218,7 +225,7 @@ TEST_F(DistLockCatalogFixture, PingCommandError) { TEST_F(DistLockCatalogFixture, PingWriteError) { auto future = launchAsync([this] { - auto status = catalog()->ping("abcd", Date_t::now()); + auto status = catalog()->ping(txn(), "abcd", Date_t::now()); ASSERT_EQUALS(ErrorCodes::Unauthorized, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -236,7 +243,7 @@ TEST_F(DistLockCatalogFixture, PingWriteError) { TEST_F(DistLockCatalogFixture, PingWriteConcernError) { auto future = launchAsync([this] { - auto status = catalog()->ping("abcd", Date_t::now()); + auto status = catalog()->ping(txn(), "abcd", Date_t::now()); ASSERT_EQUALS(ErrorCodes::WriteConcernFailed, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -257,7 +264,7 @@ TEST_F(DistLockCatalogFixture, PingWriteConcernError) { TEST_F(DistLockCatalogFixture, PingUnsupportedWriteConcernResponse) { auto future = launchAsync([this] { - auto status = catalog()->ping("abcd", Date_t::now()); + auto status = catalog()->ping(txn(), "abcd", Date_t::now()); ASSERT_EQUALS(ErrorCodes::UnsupportedFormat, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -279,7 +286,7 @@ TEST_F(DistLockCatalogFixture, PingUnsupportedWriteConcernResponse) { TEST_F(DistLockCatalogFixture, PingUnsupportedResponseFormat) { auto future = launchAsync([this] { - auto status = catalog()->ping("abcd", Date_t::now()); + auto status = catalog()->ping(txn(), "abcd", Date_t::now()); ASSERT_EQUALS(ErrorCodes::UnsupportedFormat, status.code()); }); @@ -296,7 +303,7 @@ TEST_F(DistLockCatalogFixture, GrabLockNoOp) { OID myID("555f80be366c194b13fb0372"); Date_t now(dateFromISOString("2015-05-22T19:17:18.098Z").getValue()); auto resultStatus = - catalog()->grabLock("test", myID, "me", "mongos", now, "because").getStatus(); + catalog()->grabLock(txn(), "test", myID, "me", "mongos", now, "because").getStatus(); ASSERT_EQUALS(ErrorCodes::LockStateChangeFailed, resultStatus.code()); }); @@ -320,7 +327,8 @@ TEST_F(DistLockCatalogFixture, GrabLockNoOp) { }, upsert: true, new: true, - writeConcern: { w: "majority", wtimeout: 100 } + writeConcern: { w: "majority", wtimeout: 100 }, + maxTimeMS: 30000 })")); ASSERT_EQUALS(expectedCmd, request.cmdObj); @@ -335,7 +343,8 @@ TEST_F(DistLockCatalogFixture, GrabLockWithNewDoc) { auto future = launchAsync([this] { OID myID("555f80be366c194b13fb0372"); Date_t now(dateFromISOString("2015-05-22T19:17:18.098Z").getValue()); - auto resultStatus = catalog()->grabLock("test", myID, "me", "mongos", now, "because"); + auto resultStatus = + catalog()->grabLock(txn(), "test", myID, "me", "mongos", now, "because"); ASSERT_OK(resultStatus.getStatus()); const auto& lockDoc = resultStatus.getValue(); @@ -366,7 +375,8 @@ TEST_F(DistLockCatalogFixture, GrabLockWithNewDoc) { }, upsert: true, new: true, - writeConcern: { w: "majority", wtimeout: 100 } + writeConcern: { w: "majority", wtimeout: 100 }, + maxTimeMS: 30000 })")); ASSERT_EQUALS(expectedCmd, request.cmdObj); @@ -396,7 +406,7 @@ TEST_F(DistLockCatalogFixture, GrabLockWithNewDoc) { TEST_F(DistLockCatalogFixture, GrabLockWithBadLockDoc) { auto future = launchAsync([this] { Date_t now(dateFromISOString("2015-05-22T19:17:18.098Z").getValue()); - auto resultStatus = catalog()->grabLock("test", OID(), "", "", now, "").getStatus(); + auto resultStatus = catalog()->grabLock(txn(), "test", OID(), "", "", now, "").getStatus(); ASSERT_EQUALS(ErrorCodes::FailedToParse, resultStatus.code()); }); @@ -427,21 +437,22 @@ TEST_F(DistLockCatalogFixture, GrabLockWithBadLockDoc) { TEST_F(DistLockCatalogFixture, GrabLockTargetError) { targeter()->setFindHostReturnValue({ErrorCodes::InternalError, "can't target"}); - auto status = catalog()->grabLock("", OID::gen(), "", "", Date_t::now(), "").getStatus(); + auto status = catalog()->grabLock(txn(), "", OID::gen(), "", "", Date_t::now(), "").getStatus(); ASSERT_NOT_OK(status); } TEST_F(DistLockCatalogFixture, GrabLockRunCmdError) { shutdownShardRegistry(); - auto status = catalog()->grabLock("", OID::gen(), "", "", Date_t::now(), "").getStatus(); + auto status = catalog()->grabLock(txn(), "", OID::gen(), "", "", Date_t::now(), "").getStatus(); ASSERT_EQUALS(ErrorCodes::ShutdownInProgress, status.code()); ASSERT_FALSE(status.reason().empty()); } TEST_F(DistLockCatalogFixture, GrabLockCommandError) { auto future = launchAsync([this] { - auto status = catalog()->grabLock("", OID::gen(), "", "", Date_t::now(), "").getStatus(); + auto status = + catalog()->grabLock(txn(), "", OID::gen(), "", "", Date_t::now(), "").getStatus(); ASSERT_EQUALS(ErrorCodes::FailedToParse, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -459,7 +470,8 @@ TEST_F(DistLockCatalogFixture, GrabLockCommandError) { TEST_F(DistLockCatalogFixture, GrabLockDupKeyError) { auto future = launchAsync([this] { - auto status = catalog()->grabLock("", OID::gen(), "", "", Date_t::now(), "").getStatus(); + auto status = + catalog()->grabLock(txn(), "", OID::gen(), "", "", Date_t::now(), "").getStatus(); ASSERT_EQUALS(ErrorCodes::LockStateChangeFailed, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -477,7 +489,8 @@ TEST_F(DistLockCatalogFixture, GrabLockDupKeyError) { TEST_F(DistLockCatalogFixture, GrabLockWriteError) { auto future = launchAsync([this] { - auto status = catalog()->grabLock("", OID::gen(), "", "", Date_t::now(), "").getStatus(); + auto status = + catalog()->grabLock(txn(), "", OID::gen(), "", "", Date_t::now(), "").getStatus(); ASSERT_EQUALS(ErrorCodes::Unauthorized, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -495,7 +508,8 @@ TEST_F(DistLockCatalogFixture, GrabLockWriteError) { TEST_F(DistLockCatalogFixture, GrabLockWriteConcernError) { auto future = launchAsync([this] { - auto status = catalog()->grabLock("", OID::gen(), "", "", Date_t::now(), "").getStatus(); + auto status = + catalog()->grabLock(txn(), "", OID::gen(), "", "", Date_t::now(), "").getStatus(); ASSERT_EQUALS(ErrorCodes::WriteConcernFailed, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -516,7 +530,8 @@ TEST_F(DistLockCatalogFixture, GrabLockWriteConcernError) { TEST_F(DistLockCatalogFixture, GrabLockWriteConcernErrorBadType) { auto future = launchAsync([this] { - auto status = catalog()->grabLock("", OID::gen(), "", "", Date_t::now(), "").getStatus(); + auto status = + catalog()->grabLock(txn(), "", OID::gen(), "", "", Date_t::now(), "").getStatus(); ASSERT_EQUALS(ErrorCodes::TypeMismatch, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -535,7 +550,8 @@ TEST_F(DistLockCatalogFixture, GrabLockWriteConcernErrorBadType) { TEST_F(DistLockCatalogFixture, GrabLockResponseMissingValueField) { auto future = launchAsync([this] { - auto status = catalog()->grabLock("", OID::gen(), "", "", Date_t::now(), "").getStatus(); + auto status = + catalog()->grabLock(txn(), "", OID::gen(), "", "", Date_t::now(), "").getStatus(); ASSERT_EQUALS(ErrorCodes::UnsupportedFormat, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -551,7 +567,8 @@ TEST_F(DistLockCatalogFixture, GrabLockResponseMissingValueField) { TEST_F(DistLockCatalogFixture, GrabLockUnsupportedWriteConcernResponse) { auto future = launchAsync([this] { - auto status = catalog()->grabLock("", OID::gen(), "", "", Date_t::now(), "").getStatus(); + auto status = + catalog()->grabLock(txn(), "", OID::gen(), "", "", Date_t::now(), "").getStatus(); ASSERT_EQUALS(ErrorCodes::UnsupportedFormat, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -573,7 +590,8 @@ TEST_F(DistLockCatalogFixture, GrabLockUnsupportedWriteConcernResponse) { TEST_F(DistLockCatalogFixture, GrabLockUnsupportedResponseFormat) { auto future = launchAsync([this] { - auto status = catalog()->grabLock("", OID::gen(), "", "", Date_t::now(), "").getStatus(); + auto status = + catalog()->grabLock(txn(), "", OID::gen(), "", "", Date_t::now(), "").getStatus(); ASSERT_EQUALS(ErrorCodes::UnsupportedFormat, status.code()); }); @@ -592,7 +610,7 @@ TEST_F(DistLockCatalogFixture, OvertakeLockNoOp) { Date_t now(dateFromISOString("2015-05-22T19:17:18.098Z").getValue()); auto resultStatus = catalog() - ->overtakeLock("test", myID, currentOwner, "me", "mongos", now, "because") + ->overtakeLock(txn(), "test", myID, currentOwner, "me", "mongos", now, "because") .getStatus(); ASSERT_EQUALS(ErrorCodes::LockStateChangeFailed, resultStatus.code()); @@ -621,7 +639,8 @@ TEST_F(DistLockCatalogFixture, OvertakeLockNoOp) { } }, new: true, - writeConcern: { w: "majority", wtimeout: 100 } + writeConcern: { w: "majority", wtimeout: 100 }, + maxTimeMS: 30000 })")); ASSERT_EQUALS(expectedCmd, request.cmdObj); @@ -637,8 +656,8 @@ TEST_F(DistLockCatalogFixture, OvertakeLockWithNewDoc) { OID myID("555f80be366c194b13fb0372"); OID currentOwner("555f99712c99a78c5b083358"); Date_t now(dateFromISOString("2015-05-22T19:17:18.098Z").getValue()); - auto resultStatus = - catalog()->overtakeLock("test", myID, currentOwner, "me", "mongos", now, "because"); + auto resultStatus = catalog()->overtakeLock( + txn(), "test", myID, currentOwner, "me", "mongos", now, "because"); ASSERT_OK(resultStatus.getStatus()); const auto& lockDoc = resultStatus.getValue(); @@ -673,7 +692,8 @@ TEST_F(DistLockCatalogFixture, OvertakeLockWithNewDoc) { } }, new: true, - writeConcern: { w: "majority", wtimeout: 100 } + writeConcern: { w: "majority", wtimeout: 100 }, + maxTimeMS: 30000 })")); ASSERT_EQUALS(expectedCmd, request.cmdObj); @@ -704,7 +724,7 @@ TEST_F(DistLockCatalogFixture, OvertakeLockWithBadLockDoc) { auto future = launchAsync([this] { Date_t now(dateFromISOString("2015-05-22T19:17:18.098Z").getValue()); auto resultStatus = - catalog()->overtakeLock("test", OID(), OID(), "", "", now, "").getStatus(); + catalog()->overtakeLock(txn(), "test", OID(), OID(), "", "", now, "").getStatus(); ASSERT_EQUALS(ErrorCodes::FailedToParse, resultStatus.code()); }); @@ -735,14 +755,16 @@ TEST_F(DistLockCatalogFixture, OvertakeLockWithBadLockDoc) { TEST_F(DistLockCatalogFixture, OvertakeLockTargetError) { targeter()->setFindHostReturnValue({ErrorCodes::InternalError, "can't target"}); - auto status = catalog()->overtakeLock("", OID(), OID(), "", "", Date_t::now(), "").getStatus(); + auto status = + catalog()->overtakeLock(txn(), "", OID(), OID(), "", "", Date_t::now(), "").getStatus(); ASSERT_NOT_OK(status); } TEST_F(DistLockCatalogFixture, OvertakeLockRunCmdError) { shutdownShardRegistry(); - auto status = catalog()->overtakeLock("", OID(), OID(), "", "", Date_t::now(), "").getStatus(); + auto status = + catalog()->overtakeLock(txn(), "", OID(), OID(), "", "", Date_t::now(), "").getStatus(); ASSERT_EQUALS(ErrorCodes::ShutdownInProgress, status.code()); ASSERT_FALSE(status.reason().empty()); } @@ -750,7 +772,7 @@ TEST_F(DistLockCatalogFixture, OvertakeLockRunCmdError) { TEST_F(DistLockCatalogFixture, OvertakeLockCommandError) { auto future = launchAsync([this] { auto status = - catalog()->overtakeLock("", OID(), OID(), "", "", Date_t::now(), "").getStatus(); + catalog()->overtakeLock(txn(), "", OID(), OID(), "", "", Date_t::now(), "").getStatus(); ASSERT_EQUALS(ErrorCodes::FailedToParse, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -769,7 +791,7 @@ TEST_F(DistLockCatalogFixture, OvertakeLockCommandError) { TEST_F(DistLockCatalogFixture, OvertakeLockWriteError) { auto future = launchAsync([this] { auto status = - catalog()->overtakeLock("", OID(), OID(), "", "", Date_t::now(), "").getStatus(); + catalog()->overtakeLock(txn(), "", OID(), OID(), "", "", Date_t::now(), "").getStatus(); ASSERT_EQUALS(ErrorCodes::Unauthorized, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -788,7 +810,7 @@ TEST_F(DistLockCatalogFixture, OvertakeLockWriteError) { TEST_F(DistLockCatalogFixture, OvertakeLockWriteConcernError) { auto future = launchAsync([this] { auto status = - catalog()->overtakeLock("", OID(), OID(), "", "", Date_t::now(), "").getStatus(); + catalog()->overtakeLock(txn(), "", OID(), OID(), "", "", Date_t::now(), "").getStatus(); ASSERT_EQUALS(ErrorCodes::WriteConcernFailed, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -810,7 +832,7 @@ TEST_F(DistLockCatalogFixture, OvertakeLockWriteConcernError) { TEST_F(DistLockCatalogFixture, OvertakeLockUnsupportedWriteConcernResponse) { auto future = launchAsync([this] { auto status = - catalog()->overtakeLock("", OID(), OID(), "", "", Date_t::now(), "").getStatus(); + catalog()->overtakeLock(txn(), "", OID(), OID(), "", "", Date_t::now(), "").getStatus(); ASSERT_EQUALS(ErrorCodes::UnsupportedFormat, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -833,7 +855,7 @@ TEST_F(DistLockCatalogFixture, OvertakeLockUnsupportedWriteConcernResponse) { TEST_F(DistLockCatalogFixture, OvertakeLockUnsupportedResponseFormat) { auto future = launchAsync([this] { auto status = - catalog()->overtakeLock("", OID(), OID(), "", "", Date_t::now(), "").getStatus(); + catalog()->overtakeLock(txn(), "", OID(), OID(), "", "", Date_t::now(), "").getStatus(); ASSERT_EQUALS(ErrorCodes::UnsupportedFormat, status.code()); }); @@ -847,7 +869,7 @@ TEST_F(DistLockCatalogFixture, OvertakeLockUnsupportedResponseFormat) { TEST_F(DistLockCatalogFixture, BasicUnlock) { auto future = launchAsync([this] { - auto status = catalog()->unlock(OID("555f99712c99a78c5b083358")); + auto status = catalog()->unlock(txn(), OID("555f99712c99a78c5b083358")); ASSERT_OK(status); }); @@ -859,7 +881,8 @@ TEST_F(DistLockCatalogFixture, BasicUnlock) { findAndModify: "locks", query: { ts: ObjectId("555f99712c99a78c5b083358") }, update: { $set: { state: 0 }}, - writeConcern: { w: "majority", wtimeout: 100 } + writeConcern: { w: "majority", wtimeout: 100 }, + maxTimeMS: 30000 })")); ASSERT_EQUALS(expectedCmd, request.cmdObj); @@ -879,7 +902,7 @@ TEST_F(DistLockCatalogFixture, BasicUnlock) { TEST_F(DistLockCatalogFixture, UnlockWithNoNewDoc) { auto future = launchAsync([this] { - auto status = catalog()->unlock(OID("555f99712c99a78c5b083358")); + auto status = catalog()->unlock(txn(), OID("555f99712c99a78c5b083358")); ASSERT_OK(status); }); @@ -891,7 +914,8 @@ TEST_F(DistLockCatalogFixture, UnlockWithNoNewDoc) { findAndModify: "locks", query: { ts: ObjectId("555f99712c99a78c5b083358") }, update: { $set: { state: 0 }}, - writeConcern: { w: "majority", wtimeout: 100 } + writeConcern: { w: "majority", wtimeout: 100 }, + maxTimeMS: 30000 })")); ASSERT_EQUALS(expectedCmd, request.cmdObj); @@ -907,21 +931,21 @@ TEST_F(DistLockCatalogFixture, UnlockWithNoNewDoc) { TEST_F(DistLockCatalogFixture, UnlockTargetError) { targeter()->setFindHostReturnValue({ErrorCodes::InternalError, "can't target"}); - auto status = catalog()->unlock(OID()); + auto status = catalog()->unlock(txn(), OID()); ASSERT_NOT_OK(status); } TEST_F(DistLockCatalogFixture, UnlockRunCmdError) { shutdownShardRegistry(); - auto status = catalog()->unlock(OID()); + auto status = catalog()->unlock(txn(), OID()); ASSERT_EQUALS(ErrorCodes::ShutdownInProgress, status.code()); ASSERT_FALSE(status.reason().empty()); } TEST_F(DistLockCatalogFixture, UnlockCommandError) { auto future = launchAsync([this] { - auto status = catalog()->unlock(OID()); + auto status = catalog()->unlock(txn(), OID()); ASSERT_EQUALS(ErrorCodes::FailedToParse, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -939,7 +963,7 @@ TEST_F(DistLockCatalogFixture, UnlockCommandError) { TEST_F(DistLockCatalogFixture, UnlockWriteError) { auto future = launchAsync([this] { - auto status = catalog()->unlock(OID()); + auto status = catalog()->unlock(txn(), OID()); ASSERT_EQUALS(ErrorCodes::Unauthorized, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -957,7 +981,7 @@ TEST_F(DistLockCatalogFixture, UnlockWriteError) { TEST_F(DistLockCatalogFixture, UnlockWriteConcernError) { auto future = launchAsync([this] { - auto status = catalog()->unlock(OID()); + auto status = catalog()->unlock(txn(), OID()); ASSERT_EQUALS(ErrorCodes::WriteConcernFailed, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -978,7 +1002,7 @@ TEST_F(DistLockCatalogFixture, UnlockWriteConcernError) { TEST_F(DistLockCatalogFixture, UnlockUnsupportedWriteConcernResponse) { auto future = launchAsync([this] { - auto status = catalog()->unlock(OID()); + auto status = catalog()->unlock(txn(), OID()); ASSERT_EQUALS(ErrorCodes::UnsupportedFormat, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -1000,7 +1024,7 @@ TEST_F(DistLockCatalogFixture, UnlockUnsupportedWriteConcernResponse) { TEST_F(DistLockCatalogFixture, UnlockUnsupportedResponseFormat) { auto future = launchAsync([this] { - auto status = catalog()->unlock(OID()); + auto status = catalog()->unlock(txn(), OID()); ASSERT_EQUALS(ErrorCodes::UnsupportedFormat, status.code()); }); @@ -1016,7 +1040,7 @@ TEST_F(DistLockCatalogFixture, BasicGetServerInfo) { auto future = launchAsync([this] { Date_t localTime(dateFromISOString("2015-05-26T13:06:27.293Z").getValue()); OID electionID("555fa85d4d8640862a0fc79b"); - auto resultStatus = catalog()->getServerInfo(); + auto resultStatus = catalog()->getServerInfo(txn()); ASSERT_OK(resultStatus.getStatus()); const auto& serverInfo = resultStatus.getValue(); @@ -1027,7 +1051,7 @@ TEST_F(DistLockCatalogFixture, BasicGetServerInfo) { onCommand([](const RemoteCommandRequest& request) -> StatusWith<BSONObj> { ASSERT_EQUALS(dummyHost, request.target); ASSERT_EQUALS("admin", request.dbname); - ASSERT_EQUALS(BSON("serverStatus" << 1), request.cmdObj); + ASSERT_EQUALS(BSON("serverStatus" << 1 << "maxTimeMS" << 30000), request.cmdObj); return fromjson(R"({ localTime: { $date: "2015-05-26T13:06:27.293Z" }, @@ -1043,21 +1067,21 @@ TEST_F(DistLockCatalogFixture, BasicGetServerInfo) { TEST_F(DistLockCatalogFixture, GetServerTargetError) { targeter()->setFindHostReturnValue({ErrorCodes::InternalError, "can't target"}); - auto status = catalog()->getServerInfo().getStatus(); + auto status = catalog()->getServerInfo(txn()).getStatus(); ASSERT_NOT_OK(status); } TEST_F(DistLockCatalogFixture, GetServerRunCmdError) { shutdownShardRegistry(); - auto status = catalog()->getServerInfo().getStatus(); + auto status = catalog()->getServerInfo(txn()).getStatus(); ASSERT_EQUALS(ErrorCodes::ShutdownInProgress, status.code()); ASSERT_FALSE(status.reason().empty()); } TEST_F(DistLockCatalogFixture, GetServerCommandError) { auto future = launchAsync([this] { - auto status = catalog()->getServerInfo().getStatus(); + auto status = catalog()->getServerInfo(txn()).getStatus(); ASSERT_EQUALS(ErrorCodes::FailedToParse, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -1075,7 +1099,7 @@ TEST_F(DistLockCatalogFixture, GetServerCommandError) { TEST_F(DistLockCatalogFixture, GetServerBadElectionId) { auto future = launchAsync([this] { - auto status = catalog()->getServerInfo().getStatus(); + auto status = catalog()->getServerInfo(txn()).getStatus(); ASSERT_EQUALS(ErrorCodes::UnsupportedFormat, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -1097,7 +1121,7 @@ TEST_F(DistLockCatalogFixture, GetServerBadElectionId) { TEST_F(DistLockCatalogFixture, GetServerBadLocalTime) { auto future = launchAsync([this] { - auto status = catalog()->getServerInfo().getStatus(); + auto status = catalog()->getServerInfo(txn()).getStatus(); ASSERT_EQUALS(ErrorCodes::UnsupportedFormat, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -1119,7 +1143,7 @@ TEST_F(DistLockCatalogFixture, GetServerBadLocalTime) { TEST_F(DistLockCatalogFixture, GetServerNoGLEStats) { auto future = launchAsync([this] { - auto status = catalog()->getServerInfo().getStatus(); + auto status = catalog()->getServerInfo(txn()).getStatus(); ASSERT_EQUALS(ErrorCodes::UnsupportedFormat, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -1136,7 +1160,7 @@ TEST_F(DistLockCatalogFixture, GetServerNoGLEStats) { TEST_F(DistLockCatalogFixture, GetServerNoElectionId) { auto future = launchAsync([this] { - auto status = catalog()->getServerInfo().getStatus(); + auto status = catalog()->getServerInfo(txn()).getStatus(); ASSERT_EQUALS(ErrorCodes::UnsupportedFormat, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -1157,7 +1181,7 @@ TEST_F(DistLockCatalogFixture, GetServerNoElectionId) { TEST_F(DistLockCatalogFixture, BasicStopPing) { auto future = launchAsync([this] { - auto status = catalog()->stopPing("test"); + auto status = catalog()->stopPing(txn(), "test"); ASSERT_OK(status); }); @@ -1169,7 +1193,8 @@ TEST_F(DistLockCatalogFixture, BasicStopPing) { findAndModify: "lockpings", query: { _id: "test" }, remove: true, - writeConcern: { w: "majority", wtimeout: 100 } + writeConcern: { w: "majority", wtimeout: 100 }, + maxTimeMS: 30000 })")); ASSERT_EQUALS(expectedCmd, request.cmdObj); @@ -1188,21 +1213,21 @@ TEST_F(DistLockCatalogFixture, BasicStopPing) { TEST_F(DistLockCatalogFixture, StopPingTargetError) { targeter()->setFindHostReturnValue({ErrorCodes::InternalError, "can't target"}); - auto status = catalog()->stopPing(""); + auto status = catalog()->stopPing(txn(), ""); ASSERT_NOT_OK(status); } TEST_F(DistLockCatalogFixture, StopPingRunCmdError) { shutdownShardRegistry(); - auto status = catalog()->stopPing(""); + auto status = catalog()->stopPing(txn(), ""); ASSERT_EQUALS(ErrorCodes::ShutdownInProgress, status.code()); ASSERT_FALSE(status.reason().empty()); } TEST_F(DistLockCatalogFixture, StopPingCommandError) { auto future = launchAsync([this] { - auto status = catalog()->stopPing(""); + auto status = catalog()->stopPing(txn(), ""); ASSERT_EQUALS(ErrorCodes::FailedToParse, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -1220,7 +1245,7 @@ TEST_F(DistLockCatalogFixture, StopPingCommandError) { TEST_F(DistLockCatalogFixture, StopPingWriteError) { auto future = launchAsync([this] { - auto status = catalog()->stopPing(""); + auto status = catalog()->stopPing(txn(), ""); ASSERT_EQUALS(ErrorCodes::Unauthorized, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -1238,7 +1263,7 @@ TEST_F(DistLockCatalogFixture, StopPingWriteError) { TEST_F(DistLockCatalogFixture, StopPingWriteConcernError) { auto future = launchAsync([this] { - auto status = catalog()->stopPing(""); + auto status = catalog()->stopPing(txn(), ""); ASSERT_EQUALS(ErrorCodes::WriteConcernFailed, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -1259,7 +1284,7 @@ TEST_F(DistLockCatalogFixture, StopPingWriteConcernError) { TEST_F(DistLockCatalogFixture, StopPingUnsupportedWriteConcernResponse) { auto future = launchAsync([this] { - auto status = catalog()->stopPing(""); + auto status = catalog()->stopPing(txn(), ""); ASSERT_EQUALS(ErrorCodes::UnsupportedFormat, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -1281,7 +1306,7 @@ TEST_F(DistLockCatalogFixture, StopPingUnsupportedWriteConcernResponse) { TEST_F(DistLockCatalogFixture, StopPingUnsupportedResponseFormat) { auto future = launchAsync([this] { - auto status = catalog()->stopPing(""); + auto status = catalog()->stopPing(txn(), ""); ASSERT_EQUALS(ErrorCodes::UnsupportedFormat, status.code()); }); @@ -1296,7 +1321,7 @@ TEST_F(DistLockCatalogFixture, StopPingUnsupportedResponseFormat) { TEST_F(DistLockCatalogFixture, BasicGetPing) { auto future = launchAsync([this] { Date_t ping(dateFromISOString("2015-05-26T13:06:27.293Z").getValue()); - auto resultStatus = catalog()->getPing("test"); + auto resultStatus = catalog()->getPing(txn(), "test"); ASSERT_OK(resultStatus.getStatus()); const auto& pingDoc = resultStatus.getValue(); @@ -1333,21 +1358,21 @@ TEST_F(DistLockCatalogFixture, BasicGetPing) { TEST_F(DistLockCatalogFixture, GetPingTargetError) { targeter()->setFindHostReturnValue({ErrorCodes::InternalError, "can't target"}); - auto status = catalog()->getPing("").getStatus(); + auto status = catalog()->getPing(txn(), "").getStatus(); ASSERT_EQUALS(ErrorCodes::InternalError, status.code()); } TEST_F(DistLockCatalogFixture, GetPingRunCmdError) { shutdownShardRegistry(); - auto status = catalog()->getPing("").getStatus(); + auto status = catalog()->getPing(txn(), "").getStatus(); ASSERT_EQUALS(ErrorCodes::ShutdownInProgress, status.code()); ASSERT_FALSE(status.reason().empty()); } TEST_F(DistLockCatalogFixture, GetPingNotFound) { auto future = launchAsync([this] { - auto status = catalog()->getPing("").getStatus(); + auto status = catalog()->getPing(txn(), "").getStatus(); ASSERT_EQUALS(ErrorCodes::NoMatchingDocument, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -1360,7 +1385,7 @@ TEST_F(DistLockCatalogFixture, GetPingNotFound) { TEST_F(DistLockCatalogFixture, GetPingUnsupportedFormat) { auto future = launchAsync([this] { - auto status = catalog()->getPing("test").getStatus(); + auto status = catalog()->getPing(txn(), "test").getStatus(); ASSERT_EQUALS(ErrorCodes::FailedToParse, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -1384,7 +1409,7 @@ TEST_F(DistLockCatalogFixture, GetPingUnsupportedFormat) { TEST_F(DistLockCatalogFixture, BasicGetLockByTS) { auto future = launchAsync([this] { OID ts("555f99712c99a78c5b083358"); - auto resultStatus = catalog()->getLockByTS(ts); + auto resultStatus = catalog()->getLockByTS(txn(), ts); ASSERT_OK(resultStatus.getStatus()); const auto& lockDoc = resultStatus.getValue(); @@ -1418,20 +1443,20 @@ TEST_F(DistLockCatalogFixture, BasicGetLockByTS) { TEST_F(DistLockCatalogFixture, GetLockByTSTargetError) { targeter()->setFindHostReturnValue({ErrorCodes::InternalError, "can't target"}); - auto status = catalog()->getLockByTS(OID()).getStatus(); + auto status = catalog()->getLockByTS(txn(), OID()).getStatus(); ASSERT_EQUALS(ErrorCodes::InternalError, status.code()); } TEST_F(DistLockCatalogFixture, GetLockByTSRunCmdError) { shutdownShardRegistry(); - auto status = catalog()->getLockByTS(OID()).getStatus(); + auto status = catalog()->getLockByTS(txn(), OID()).getStatus(); ASSERT_EQUALS(ErrorCodes::ShutdownInProgress, status.code()); ASSERT_FALSE(status.reason().empty()); } TEST_F(DistLockCatalogFixture, GetLockByTSNotFound) { auto future = launchAsync([this] { - auto status = catalog()->getLockByTS(OID()).getStatus(); + auto status = catalog()->getLockByTS(txn(), OID()).getStatus(); ASSERT_EQUALS(ErrorCodes::LockNotFound, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -1444,7 +1469,7 @@ TEST_F(DistLockCatalogFixture, GetLockByTSNotFound) { TEST_F(DistLockCatalogFixture, GetLockByTSUnsupportedFormat) { auto future = launchAsync([this] { - auto status = catalog()->getLockByTS(OID()).getStatus(); + auto status = catalog()->getLockByTS(txn(), OID()).getStatus(); ASSERT_EQUALS(ErrorCodes::FailedToParse, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -1468,7 +1493,7 @@ TEST_F(DistLockCatalogFixture, GetLockByTSUnsupportedFormat) { TEST_F(DistLockCatalogFixture, BasicGetLockByName) { auto future = launchAsync([this] { OID ts("555f99712c99a78c5b083358"); - auto resultStatus = catalog()->getLockByName("abc"); + auto resultStatus = catalog()->getLockByName(txn(), "abc"); ASSERT_OK(resultStatus.getStatus()); const auto& lockDoc = resultStatus.getValue(); @@ -1505,21 +1530,21 @@ TEST_F(DistLockCatalogFixture, BasicGetLockByName) { TEST_F(DistLockCatalogFixture, GetLockByNameTargetError) { targeter()->setFindHostReturnValue({ErrorCodes::InternalError, "can't target"}); - auto status = catalog()->getLockByName("x").getStatus(); + auto status = catalog()->getLockByName(txn(), "x").getStatus(); ASSERT_EQUALS(ErrorCodes::InternalError, status.code()); } TEST_F(DistLockCatalogFixture, GetLockByNameRunCmdError) { shutdownShardRegistry(); - auto status = catalog()->getLockByName("x").getStatus(); + auto status = catalog()->getLockByName(txn(), "x").getStatus(); ASSERT_EQUALS(ErrorCodes::ShutdownInProgress, status.code()); ASSERT_FALSE(status.reason().empty()); } TEST_F(DistLockCatalogFixture, GetLockByNameNotFound) { auto future = launchAsync([this] { - auto status = catalog()->getLockByName("x").getStatus(); + auto status = catalog()->getLockByName(txn(), "x").getStatus(); ASSERT_EQUALS(ErrorCodes::LockNotFound, status.code()); ASSERT_FALSE(status.reason().empty()); }); @@ -1532,7 +1557,7 @@ TEST_F(DistLockCatalogFixture, GetLockByNameNotFound) { TEST_F(DistLockCatalogFixture, GetLockByNameUnsupportedFormat) { auto future = launchAsync([this] { - auto status = catalog()->getLockByName("x").getStatus(); + auto status = catalog()->getLockByName(txn(), "x").getStatus(); ASSERT_EQUALS(ErrorCodes::FailedToParse, status.code()); ASSERT_FALSE(status.reason().empty()); }); diff --git a/src/mongo/s/catalog/dist_lock_catalog_mock.cpp b/src/mongo/s/catalog/dist_lock_catalog_mock.cpp index f689a71fc36..03b5b0e85f6 100644 --- a/src/mongo/s/catalog/dist_lock_catalog_mock.cpp +++ b/src/mongo/s/catalog/dist_lock_catalog_mock.cpp @@ -125,7 +125,8 @@ DistLockCatalogMock::DistLockCatalogMock() DistLockCatalogMock::~DistLockCatalogMock() {} -StatusWith<LockpingsType> DistLockCatalogMock::getPing(StringData processID) { +StatusWith<LockpingsType> DistLockCatalogMock::getPing(OperationContext* txn, + StringData processID) { auto ret = kLockpingsTypeBadRetValue; GetPingFunc checkerFunc = noGetPingSet; @@ -139,7 +140,7 @@ StatusWith<LockpingsType> DistLockCatalogMock::getPing(StringData processID) { return ret; } -Status DistLockCatalogMock::ping(StringData processID, Date_t ping) { +Status DistLockCatalogMock::ping(OperationContext* txn, StringData processID, Date_t ping) { auto ret = kBadRetValue; PingFunc checkerFunc = noPingFuncSet; @@ -153,7 +154,8 @@ Status DistLockCatalogMock::ping(StringData processID, Date_t ping) { return ret; } -StatusWith<LocksType> DistLockCatalogMock::grabLock(StringData lockID, +StatusWith<LocksType> DistLockCatalogMock::grabLock(OperationContext* txn, + StringData lockID, const OID& lockSessionID, StringData who, StringData processId, @@ -172,7 +174,8 @@ StatusWith<LocksType> DistLockCatalogMock::grabLock(StringData lockID, return ret; } -StatusWith<LocksType> DistLockCatalogMock::overtakeLock(StringData lockID, +StatusWith<LocksType> DistLockCatalogMock::overtakeLock(OperationContext* txn, + StringData lockID, const OID& lockSessionID, const OID& currentHolderTS, StringData who, @@ -192,7 +195,7 @@ StatusWith<LocksType> DistLockCatalogMock::overtakeLock(StringData lockID, return ret; } -Status DistLockCatalogMock::unlock(const OID& lockSessionID) { +Status DistLockCatalogMock::unlock(OperationContext* txn, const OID& lockSessionID) { auto ret = kBadRetValue; UnlockFunc checkerFunc = noUnLockFuncSet; @@ -206,7 +209,7 @@ Status DistLockCatalogMock::unlock(const OID& lockSessionID) { return ret; } -StatusWith<DistLockCatalog::ServerInfo> DistLockCatalogMock::getServerInfo() { +StatusWith<DistLockCatalog::ServerInfo> DistLockCatalogMock::getServerInfo(OperationContext* txn) { auto ret = kServerInfoBadRetValue; GetServerInfoFunc checkerFunc = noGetServerInfoSet; @@ -220,7 +223,8 @@ StatusWith<DistLockCatalog::ServerInfo> DistLockCatalogMock::getServerInfo() { return ret; } -StatusWith<LocksType> DistLockCatalogMock::getLockByTS(const OID& lockSessionID) { +StatusWith<LocksType> DistLockCatalogMock::getLockByTS(OperationContext* txn, + const OID& lockSessionID) { auto ret = kLocksTypeBadRetValue; GetLockByTSFunc checkerFunc = noGetLockByTSSet; @@ -234,7 +238,7 @@ StatusWith<LocksType> DistLockCatalogMock::getLockByTS(const OID& lockSessionID) return ret; } -StatusWith<LocksType> DistLockCatalogMock::getLockByName(StringData name) { +StatusWith<LocksType> DistLockCatalogMock::getLockByName(OperationContext* txn, StringData name) { auto ret = kLocksTypeBadRetValue; GetLockByNameFunc checkerFunc = noGetLockByNameSet; @@ -248,7 +252,7 @@ StatusWith<LocksType> DistLockCatalogMock::getLockByName(StringData name) { return ret; } -Status DistLockCatalogMock::stopPing(StringData processId) { +Status DistLockCatalogMock::stopPing(OperationContext* txn, StringData processId) { auto ret = kBadRetValue; StopPingFunc checkerFunc = noStopPingFuncSet; diff --git a/src/mongo/s/catalog/dist_lock_catalog_mock.h b/src/mongo/s/catalog/dist_lock_catalog_mock.h index 2a1aa449a31..4a3e4af38d3 100644 --- a/src/mongo/s/catalog/dist_lock_catalog_mock.h +++ b/src/mongo/s/catalog/dist_lock_catalog_mock.h @@ -89,18 +89,20 @@ public: using GetLockByNameFunc = stdx::function<void(StringData name)>; using GetServerInfoFunc = stdx::function<void()>; - virtual StatusWith<LockpingsType> getPing(StringData processID) override; + virtual StatusWith<LockpingsType> getPing(OperationContext* txn, StringData processID) override; - virtual Status ping(StringData processID, Date_t ping) override; + virtual Status ping(OperationContext* txn, StringData processID, Date_t ping) override; - virtual StatusWith<LocksType> grabLock(StringData lockID, + virtual StatusWith<LocksType> grabLock(OperationContext* txn, + StringData lockID, const OID& lockSessionID, StringData who, StringData processId, Date_t time, StringData why) override; - virtual StatusWith<LocksType> overtakeLock(StringData lockID, + virtual StatusWith<LocksType> overtakeLock(OperationContext* txn, + StringData lockID, const OID& lockSessionID, const OID& currentHolderTS, StringData who, @@ -108,15 +110,16 @@ public: Date_t time, StringData why) override; - virtual Status unlock(const OID& lockSessionID) override; + virtual Status unlock(OperationContext* txn, const OID& lockSessionID) override; - virtual StatusWith<ServerInfo> getServerInfo() override; + virtual StatusWith<ServerInfo> getServerInfo(OperationContext* txn) override; - virtual StatusWith<LocksType> getLockByTS(const OID& lockSessionID) override; + virtual StatusWith<LocksType> getLockByTS(OperationContext* txn, + const OID& lockSessionID) override; - virtual StatusWith<LocksType> getLockByName(StringData name) override; + virtual StatusWith<LocksType> getLockByName(OperationContext* txn, StringData name) override; - virtual Status stopPing(StringData processId) override; + virtual Status stopPing(OperationContext* txn, StringData processId) override; /** * Sets the checker method to use and the return value for grabLock to return every diff --git a/src/mongo/s/catalog/dist_lock_manager.cpp b/src/mongo/s/catalog/dist_lock_manager.cpp index 9662bbff3af..d45765bd9aa 100644 --- a/src/mongo/s/catalog/dist_lock_manager.cpp +++ b/src/mongo/s/catalog/dist_lock_manager.cpp @@ -39,26 +39,29 @@ namespace mongo { const stdx::chrono::milliseconds DistLockManager::kDefaultSingleLockAttemptTimeout(0); const stdx::chrono::milliseconds DistLockManager::kDefaultLockRetryInterval(1000); -DistLockManager::ScopedDistLock::ScopedDistLock(DistLockHandle lockHandle, +DistLockManager::ScopedDistLock::ScopedDistLock(OperationContext* txn, + DistLockHandle lockHandle, DistLockManager* lockManager) - : _lockID(std::move(lockHandle)), _lockManager(lockManager) {} + : _txn(txn), _lockID(std::move(lockHandle)), _lockManager(lockManager) {} DistLockManager::ScopedDistLock::~ScopedDistLock() { if (_lockManager) { - _lockManager->unlock(_lockID); + _lockManager->unlock(_txn, _lockID); } } -DistLockManager::ScopedDistLock::ScopedDistLock(ScopedDistLock&& other) : _lockManager(nullptr) { +DistLockManager::ScopedDistLock::ScopedDistLock(ScopedDistLock&& other) + : _txn(nullptr), _lockManager(nullptr) { *this = std::move(other); } DistLockManager::ScopedDistLock& DistLockManager::ScopedDistLock::operator=( ScopedDistLock&& other) { if (this != &other) { - if (_lockManager) { - _lockManager->unlock(_lockID); - } + invariant(_lockManager == nullptr); + invariant(_txn == nullptr); + + _txn = other._txn; _lockID = std::move(other._lockID); _lockManager = other._lockManager; other._lockManager = nullptr; @@ -72,6 +75,6 @@ Status DistLockManager::ScopedDistLock::checkStatus() { return Status(ErrorCodes::IllegalOperation, "no lock manager, lock was not acquired"); } - return _lockManager->checkStatus(_lockID); + return _lockManager->checkStatus(_txn, _lockID); } } diff --git a/src/mongo/s/catalog/dist_lock_manager.h b/src/mongo/s/catalog/dist_lock_manager.h index 973c33aa782..15bdbdc2787 100644 --- a/src/mongo/s/catalog/dist_lock_manager.h +++ b/src/mongo/s/catalog/dist_lock_manager.h @@ -35,6 +35,7 @@ namespace mongo { using DistLockHandle = OID; +class OperationContext; class Status; template <typename T> class StatusWith; @@ -70,7 +71,9 @@ public: MONGO_DISALLOW_COPYING(ScopedDistLock); public: - ScopedDistLock(DistLockHandle lockHandle, DistLockManager* lockManager); + ScopedDistLock(OperationContext* txn, + DistLockHandle lockHandle, + DistLockManager* lockManager); ~ScopedDistLock(); ScopedDistLock(ScopedDistLock&& other); @@ -82,6 +85,7 @@ public: Status checkStatus(); private: + OperationContext* _txn; DistLockHandle _lockID; DistLockManager* _lockManager; // Not owned here. }; @@ -99,7 +103,7 @@ public: * involves sending network messages. Implementation do not need to guarantee thread safety * so callers should employ proper synchronization when calling this method. */ - virtual void shutDown(bool allowNetworking) = 0; + virtual void shutDown(OperationContext* txn, bool allowNetworking) = 0; /** * Tries multiple times to lock, using the specified lock try interval, until @@ -115,6 +119,7 @@ public: * Returns ErrorCodes::LockBusy if the lock is being held. */ virtual StatusWith<ScopedDistLock> lock( + OperationContext* txn, StringData name, StringData whyMessage, stdx::chrono::milliseconds waitFor = kDefaultSingleLockAttemptTimeout, @@ -125,11 +130,11 @@ protected: * Unlocks the given lockHandle. Will attempt to retry again later if the config * server is not reachable. */ - virtual void unlock(const DistLockHandle& lockHandle) = 0; + virtual void unlock(OperationContext* txn, const DistLockHandle& lockHandle) = 0; /** * Checks if the lockHandle still exists in the config server. */ - virtual Status checkStatus(const DistLockHandle& lockHandle) = 0; + virtual Status checkStatus(OperationContext* txn, const DistLockHandle& lockHandle) = 0; }; } diff --git a/src/mongo/s/catalog/dist_lock_manager_mock.cpp b/src/mongo/s/catalog/dist_lock_manager_mock.cpp index 28dcbd5fa67..5afcfface61 100644 --- a/src/mongo/s/catalog/dist_lock_manager_mock.cpp +++ b/src/mongo/s/catalog/dist_lock_manager_mock.cpp @@ -59,12 +59,16 @@ DistLockManagerMock::DistLockManagerMock() void DistLockManagerMock::startUp() {} -void DistLockManagerMock::shutDown(bool allowNetworking) { +void DistLockManagerMock::shutDown(OperationContext* txn, bool allowNetworking) { uassert(28659, "DistLockManagerMock shut down with outstanding locks present", _locks.empty()); } StatusWith<DistLockManager::ScopedDistLock> DistLockManagerMock::lock( - StringData name, StringData whyMessage, milliseconds waitFor, milliseconds lockTryInterval) { + OperationContext* txn, + StringData name, + StringData whyMessage, + milliseconds waitFor, + milliseconds lockTryInterval) { _lockChecker(name, whyMessage, waitFor, lockTryInterval); _lockChecker = NoLockFuncSet; @@ -84,10 +88,10 @@ StatusWith<DistLockManager::ScopedDistLock> DistLockManagerMock::lock( info.lockID = DistLockHandle::gen(); _locks.push_back(info); - return DistLockManager::ScopedDistLock(info.lockID, this); + return DistLockManager::ScopedDistLock(nullptr, info.lockID, this); } -void DistLockManagerMock::unlock(const DistLockHandle& lockHandle) { +void DistLockManagerMock::unlock(OperationContext* txn, const DistLockHandle& lockHandle) { std::vector<LockInfo>::iterator it = std::find_if(_locks.begin(), _locks.end(), @@ -98,7 +102,7 @@ void DistLockManagerMock::unlock(const DistLockHandle& lockHandle) { _locks.erase(it); } -Status DistLockManagerMock::checkStatus(const DistLockHandle& lockHandle) { +Status DistLockManagerMock::checkStatus(OperationContext* txn, const DistLockHandle& lockHandle) { return Status::OK(); } diff --git a/src/mongo/s/catalog/dist_lock_manager_mock.h b/src/mongo/s/catalog/dist_lock_manager_mock.h index fa3f05357c2..c7572738586 100644 --- a/src/mongo/s/catalog/dist_lock_manager_mock.h +++ b/src/mongo/s/catalog/dist_lock_manager_mock.h @@ -43,9 +43,10 @@ public: virtual ~DistLockManagerMock() = default; virtual void startUp() override; - virtual void shutDown(bool allowNetworking) override; + virtual void shutDown(OperationContext* txn, bool allowNetworking) override; virtual StatusWith<DistLockManager::ScopedDistLock> lock( + OperationContext* txn, StringData name, StringData whyMessage, stdx::chrono::milliseconds waitFor, @@ -59,9 +60,9 @@ public: void expectLock(LockFunc checkerFunc, Status lockStatus); protected: - virtual void unlock(const DistLockHandle& lockHandle) override; + virtual void unlock(OperationContext* txn, const DistLockHandle& lockHandle) override; - virtual Status checkStatus(const DistLockHandle& lockHandle) override; + virtual Status checkStatus(OperationContext* txn, const DistLockHandle& lockHandle) override; private: struct LockInfo { diff --git a/src/mongo/s/catalog/forwarding_catalog_manager.cpp b/src/mongo/s/catalog/forwarding_catalog_manager.cpp index f14dd5cd75a..f5b861cf467 100644 --- a/src/mongo/s/catalog/forwarding_catalog_manager.cpp +++ b/src/mongo/s/catalog/forwarding_catalog_manager.cpp @@ -132,8 +132,8 @@ StatusWith<ForwardingCatalogManager::ScopedDistLock> ForwardingCatalogManager::d try { _operationLock.lock_shared(); auto guard = MakeGuard([this] { _operationLock.unlock_shared(); }); - auto dlmLock = - _actual->getDistLockManager()->lock(name, whyMessage, waitFor, lockTryInterval); + auto dlmLock = _actual->getDistLockManager()->lock( + txn, name, whyMessage, waitFor, lockTryInterval); if (dlmLock.isOK()) { guard.Dismiss(); // Don't unlock _operationLock; hold it until the returned // ScopedDistLock goes out of scope! diff --git a/src/mongo/s/catalog/legacy/catalog_manager_legacy.cpp b/src/mongo/s/catalog/legacy/catalog_manager_legacy.cpp index 9908f683c88..31f06ee13d9 100644 --- a/src/mongo/s/catalog/legacy/catalog_manager_legacy.cpp +++ b/src/mongo/s/catalog/legacy/catalog_manager_legacy.cpp @@ -262,7 +262,7 @@ void CatalogManagerLegacy::shutDown(OperationContext* txn, bool allowNetworking) _consistencyCheckerThread.join(); invariant(_distLockManager); - _distLockManager->shutDown(allowNetworking); + _distLockManager->shutDown(txn, allowNetworking); } Status CatalogManagerLegacy::shardCollection(OperationContext* txn, @@ -273,7 +273,7 @@ Status CatalogManagerLegacy::shardCollection(OperationContext* txn, const set<ShardId>& initShardIds) { // Lock the collection globally so that no other mongos can try to shard or drop the collection // at the same time. - auto scopedDistLock = getDistLockManager()->lock(ns, "shardCollection"); + auto scopedDistLock = getDistLockManager()->lock(txn, ns, "shardCollection"); if (!scopedDistLock.isOK()) { return scopedDistLock.getStatus(); } @@ -564,7 +564,8 @@ Status CatalogManagerLegacy::dropCollection(OperationContext* txn, const Namespa waitFor = stdx::chrono::seconds(data["waitForSecs"].numberInt()); } const stdx::chrono::milliseconds lockTryInterval(500); - auto scopedDistLock = getDistLockManager()->lock(ns.ns(), "drop", waitFor, lockTryInterval); + auto scopedDistLock = + getDistLockManager()->lock(txn, ns.ns(), "drop", waitFor, lockTryInterval); if (!scopedDistLock.isOK()) { return scopedDistLock.getStatus(); } @@ -972,7 +973,8 @@ bool CatalogManagerLegacy::runUserManagementWriteCommand(OperationContext* txn, dispatcher.addCommand(configServer, dbname, cmdObj); } - auto scopedDistLock = getDistLockManager()->lock("authorizationData", commandName, Seconds{5}); + auto scopedDistLock = + getDistLockManager()->lock(txn, "authorizationData", commandName, Seconds{5}); if (!scopedDistLock.isOK()) { return Command::appendCommandStatus(*result, scopedDistLock.getStatus()); } diff --git a/src/mongo/s/catalog/legacy/config_upgrade.cpp b/src/mongo/s/catalog/legacy/config_upgrade.cpp index f49043b6262..bddbdecb84b 100644 --- a/src/mongo/s/catalog/legacy/config_upgrade.cpp +++ b/src/mongo/s/catalog/legacy/config_upgrade.cpp @@ -297,7 +297,7 @@ Status checkAndInitConfigVersion(OperationContext* txn, string whyMessage(stream() << "initializing config database to new format v" << CURRENT_CONFIG_VERSION); auto lockTimeout = stdx::chrono::minutes(20); - auto scopedDistLock = distLockManager->lock("configUpgrade", whyMessage, lockTimeout); + auto scopedDistLock = distLockManager->lock(txn, "configUpgrade", whyMessage, lockTimeout); if (!scopedDistLock.isOK()) { return scopedDistLock.getStatus(); } diff --git a/src/mongo/s/catalog/legacy/legacy_dist_lock_manager.cpp b/src/mongo/s/catalog/legacy/legacy_dist_lock_manager.cpp index b7824d66d47..0651cdd4ca5 100644 --- a/src/mongo/s/catalog/legacy/legacy_dist_lock_manager.cpp +++ b/src/mongo/s/catalog/legacy/legacy_dist_lock_manager.cpp @@ -58,7 +58,7 @@ void LegacyDistLockManager::startUp() { _pinger = stdx::make_unique<LegacyDistLockPinger>(); } -void LegacyDistLockManager::shutDown(bool allowNetworking) { +void LegacyDistLockManager::shutDown(OperationContext* txn, bool allowNetworking) { stdx::unique_lock<stdx::mutex> sl(_mutex); _isStopped = true; @@ -72,7 +72,11 @@ void LegacyDistLockManager::shutDown(bool allowNetworking) { } StatusWith<DistLockManager::ScopedDistLock> LegacyDistLockManager::lock( - StringData name, StringData whyMessage, milliseconds waitFor, milliseconds lockTryInterval) { + OperationContext* txn, + StringData name, + StringData whyMessage, + milliseconds waitFor, + milliseconds lockTryInterval) { auto distLock = stdx::make_unique<DistributedLock>(_configServer, name.toString()); { @@ -135,7 +139,7 @@ StatusWith<DistLockManager::ScopedDistLock> LegacyDistLockManager::lock( _lockMap.insert(std::make_pair(lock.getLockID(), std::move(distLock))); } - return ScopedDistLock(lock.getLockID(), this); + return ScopedDistLock(txn, lock.getLockID(), this); } if (waitFor == milliseconds::zero()) @@ -161,7 +165,8 @@ StatusWith<DistLockManager::ScopedDistLock> LegacyDistLockManager::lock( return lastStatus; } -void LegacyDistLockManager::unlock(const DistLockHandle& lockHandle) BOOST_NOEXCEPT { +void LegacyDistLockManager::unlock(OperationContext* txn, + const DistLockHandle& lockHandle) BOOST_NOEXCEPT { unique_ptr<DistributedLock> distLock; { @@ -185,7 +190,7 @@ void LegacyDistLockManager::unlock(const DistLockHandle& lockHandle) BOOST_NOEXC } } -Status LegacyDistLockManager::checkStatus(const DistLockHandle& lockHandle) { +Status LegacyDistLockManager::checkStatus(OperationContext* txn, const DistLockHandle& lockHandle) { // Note: this should not happen when locks are managed through ScopedDistLock. if (_pinger->willUnlockOID(lockHandle)) { return Status(ErrorCodes::LockFailed, diff --git a/src/mongo/s/catalog/legacy/legacy_dist_lock_manager.h b/src/mongo/s/catalog/legacy/legacy_dist_lock_manager.h index 8267dd44602..85bc42bc042 100644 --- a/src/mongo/s/catalog/legacy/legacy_dist_lock_manager.h +++ b/src/mongo/s/catalog/legacy/legacy_dist_lock_manager.h @@ -50,9 +50,10 @@ public: virtual ~LegacyDistLockManager() = default; virtual void startUp() override; - virtual void shutDown(bool allowNetworking) override; + virtual void shutDown(OperationContext* txn, bool allowNetworking) override; virtual StatusWith<DistLockManager::ScopedDistLock> lock( + OperationContext* txn, StringData name, StringData whyMessage, stdx::chrono::milliseconds waitFor, @@ -62,9 +63,10 @@ public: void enablePinger(bool enable); protected: - virtual void unlock(const DistLockHandle& lockHandle) BOOST_NOEXCEPT override; + virtual void unlock(OperationContext* txn, + const DistLockHandle& lockHandle) BOOST_NOEXCEPT override; - virtual Status checkStatus(const DistLockHandle& lockHandle) override; + virtual Status checkStatus(OperationContext* txn, const DistLockHandle& lockHandle) override; private: const ConnectionString _configServer; diff --git a/src/mongo/s/catalog/replset/catalog_manager_replica_set.cpp b/src/mongo/s/catalog/replset/catalog_manager_replica_set.cpp index b70a12c79c3..acb2162f823 100644 --- a/src/mongo/s/catalog/replset/catalog_manager_replica_set.cpp +++ b/src/mongo/s/catalog/replset/catalog_manager_replica_set.cpp @@ -128,7 +128,7 @@ void CatalogManagerReplicaSet::shutDown(OperationContext* txn, bool allowNetwork } invariant(_distLockManager); - _distLockManager->shutDown(allowNetworking); + _distLockManager->shutDown(txn, allowNetworking); } Status CatalogManagerReplicaSet::shardCollection(OperationContext* txn, @@ -139,7 +139,7 @@ Status CatalogManagerReplicaSet::shardCollection(OperationContext* txn, const set<ShardId>& initShardIds) { // Lock the collection globally so that no other mongos can try to shard or drop the collection // at the same time. - auto scopedDistLock = getDistLockManager()->lock(ns, "shardCollection"); + auto scopedDistLock = getDistLockManager()->lock(txn, ns, "shardCollection"); if (!scopedDistLock.isOK()) { return scopedDistLock.getStatus(); } @@ -483,7 +483,8 @@ Status CatalogManagerReplicaSet::dropCollection(OperationContext* txn, const Nam waitFor = stdx::chrono::seconds(data["waitForSecs"].numberInt()); } const stdx::chrono::milliseconds lockTryInterval(500); - auto scopedDistLock = getDistLockManager()->lock(ns.ns(), "drop", waitFor, lockTryInterval); + auto scopedDistLock = + getDistLockManager()->lock(txn, ns.ns(), "drop", waitFor, lockTryInterval); if (!scopedDistLock.isOK()) { return scopedDistLock.getStatus(); } @@ -596,7 +597,7 @@ void CatalogManagerReplicaSet::logAction(OperationContext* txn, const ActionLogT BSONObj createCmd = BSON("create" << ActionLogType::ConfigNS << "capped" << true << "size" << kActionLogCollectionSize); auto result = - grid.shardRegistry()->runCommandOnConfigWithNotMasterRetries("config", createCmd); + grid.shardRegistry()->runCommandOnConfigWithNotMasterRetries(txn, "config", createCmd); if (!result.isOK()) { LOG(1) << "couldn't create actionlog collection: " << causedBy(result.getStatus()); return; @@ -626,7 +627,7 @@ Status CatalogManagerReplicaSet::logChange(OperationContext* txn, BSONObj createCmd = BSON("create" << ChangeLogType::ConfigNS << "capped" << true << "size" << kChangeLogCollectionSize); auto result = - grid.shardRegistry()->runCommandOnConfigWithNotMasterRetries("config", createCmd); + grid.shardRegistry()->runCommandOnConfigWithNotMasterRetries(txn, "config", createCmd); if (!result.isOK()) { LOG(1) << "couldn't create changelog collection: " << causedBy(result.getStatus()); return result.getStatus(); @@ -866,12 +867,14 @@ bool CatalogManagerReplicaSet::runUserManagementWriteCommand(OperationContext* t const std::string& dbname, const BSONObj& cmdObj, BSONObjBuilder* result) { - auto scopedDistLock = getDistLockManager()->lock("authorizationData", commandName, Seconds{5}); + auto scopedDistLock = + getDistLockManager()->lock(txn, "authorizationData", commandName, Seconds{5}); if (!scopedDistLock.isOK()) { return Command::appendCommandStatus(*result, scopedDistLock.getStatus()); } - auto response = grid.shardRegistry()->runCommandOnConfigWithNotMasterRetries(dbname, cmdObj); + auto response = + grid.shardRegistry()->runCommandOnConfigWithNotMasterRetries(txn, dbname, cmdObj); if (!response.isOK()) { return Command::appendCommandStatus(*result, response.getStatus()); } @@ -901,7 +904,8 @@ Status CatalogManagerReplicaSet::applyChunkOpsDeprecated(OperationContext* txn, const BSONArray& updateOps, const BSONArray& preCondition) { BSONObj cmd = BSON("applyOps" << updateOps << "preCondition" << preCondition); - auto response = grid.shardRegistry()->runCommandOnConfigWithNotMasterRetries("config", cmd); + auto response = + grid.shardRegistry()->runCommandOnConfigWithNotMasterRetries(txn, "config", cmd); if (!response.isOK()) { return response.getStatus(); @@ -929,7 +933,8 @@ void CatalogManagerReplicaSet::writeConfigServerDirect(OperationContext* txn, invariant(dbname == "config" || dbname == "admin"); const BSONObj cmdObj = batchRequest.toBSON(); - auto response = grid.shardRegistry()->runCommandOnConfigWithNotMasterRetries(dbname, cmdObj); + auto response = + grid.shardRegistry()->runCommandOnConfigWithNotMasterRetries(txn, dbname, cmdObj); if (!response.isOK()) { _toBatchError(response.getStatus(), batchResponse); return; @@ -1181,7 +1186,7 @@ StatusWith<OpTimePair<vector<BSONObj>>> CatalogManagerReplicaSet::_exhaustiveFin repl::ReadConcernLevel::kMajorityReadConcern}; auto result = grid.shardRegistry()->exhaustiveFindOnConfig( - readPref, nss, query, sort, limit, readConcern); + txn, readPref, nss, query, sort, limit, readConcern); if (ErrorCodes::isNetworkError(result.getStatus().code())) { lastStatus = result.getStatus(); @@ -1212,7 +1217,7 @@ bool CatalogManagerReplicaSet::_runReadCommand(OperationContext* txn, BSONObjBuilder* result) { Status lastStatus = Status::OK(); for (int retry = 0; retry < kMaxReadRetry; retry++) { - auto resultStatus = grid.shardRegistry()->runCommandOnConfig(settings, dbname, cmdObj); + auto resultStatus = grid.shardRegistry()->runCommandOnConfig(txn, settings, dbname, cmdObj); if (ErrorCodes::isNetworkError(resultStatus.getStatus().code())) { lastStatus = resultStatus.getStatus(); diff --git a/src/mongo/s/catalog/replset/catalog_manager_replica_set_drop_coll_test.cpp b/src/mongo/s/catalog/replset/catalog_manager_replica_set_drop_coll_test.cpp index 9bf0a35041c..18b971ef1f0 100644 --- a/src/mongo/s/catalog/replset/catalog_manager_replica_set_drop_coll_test.cpp +++ b/src/mongo/s/catalog/replset/catalog_manager_replica_set_drop_coll_test.cpp @@ -109,7 +109,8 @@ public: BSONObj expectedCmd(fromjson(R"({ delete: "chunks", deletes: [{ q: { ns: "test.user" }, limit: 0 }], - writeConcern: { w: "majority" } + writeConcern: { w: "majority" }, + maxTimeMS: 30000 })")); ASSERT_EQ(expectedCmd, request.cmdObj); diff --git a/src/mongo/s/catalog/replset/catalog_manager_replica_set_log_action_test.cpp b/src/mongo/s/catalog/replset/catalog_manager_replica_set_log_action_test.cpp index a169cac4b76..1559260744a 100644 --- a/src/mongo/s/catalog/replset/catalog_manager_replica_set_log_action_test.cpp +++ b/src/mongo/s/catalog/replset/catalog_manager_replica_set_log_action_test.cpp @@ -65,8 +65,9 @@ public: ASSERT_EQUALS(BSON(rpc::kReplSetMetadataFieldName << 1), request.metadata); - BSONObj expectedCreateCmd = BSON("create" << ActionLogType::ConfigNS << "capped" << true - << "size" << 1024 * 1024 * 2); + BSONObj expectedCreateCmd = + BSON("create" << ActionLogType::ConfigNS << "capped" << true << "size" + << 1024 * 1024 * 2 << "maxTimeMS" << 30000); ASSERT_EQUALS(expectedCreateCmd, request.cmdObj); return response; diff --git a/src/mongo/s/catalog/replset/catalog_manager_replica_set_test.cpp b/src/mongo/s/catalog/replset/catalog_manager_replica_set_test.cpp index 0d560d0bdd5..47dd2befb6b 100644 --- a/src/mongo/s/catalog/replset/catalog_manager_replica_set_test.cpp +++ b/src/mongo/s/catalog/replset/catalog_manager_replica_set_test.cpp @@ -624,7 +624,7 @@ TEST_F(CatalogManagerReplSetTest, RunUserManagementReadCommand) { request.metadata); ASSERT_EQUALS("test", request.dbname); - ASSERT_EQUALS(BSON("usersInfo" << 1), request.cmdObj); + ASSERT_EQUALS(BSON("usersInfo" << 1 << "maxTimeMS" << 30000), request.cmdObj); return BSON("ok" << 1 << "users" << BSONArrayBuilder().arr()); }); @@ -701,7 +701,8 @@ TEST_F(CatalogManagerReplSetTest, RunUserManagementWriteCommandSuccess) { onCommand([](const RemoteCommandRequest& request) { ASSERT_EQUALS("test", request.dbname); ASSERT_EQUALS(BSON("dropUser" - << "test"), + << "test" + << "maxTimeMS" << 30000), request.cmdObj); ASSERT_EQUALS(BSON(rpc::kReplSetMetadataFieldName << 1), request.metadata); @@ -803,7 +804,8 @@ TEST_F(CatalogManagerReplSetTest, RunUserManagementWriteCommandNotMasterRetrySuc ASSERT_EQUALS(host2, request.target); ASSERT_EQUALS("test", request.dbname); ASSERT_EQUALS(BSON("dropUser" - << "test"), + << "test" + << "maxTimeMS" << 30000), request.cmdObj); ASSERT_EQUALS(BSON(rpc::kReplSetMetadataFieldName << 1), request.metadata); @@ -2083,7 +2085,8 @@ TEST_F(CatalogManagerReplSetTest, EnableShardingNoDBExists) { multi: false, upsert: true }], - writeConcern: { w: "majority" } + writeConcern: { w: "majority" }, + maxTimeMS: 30000 })")); ASSERT_EQ(expectedCmd, request.cmdObj); @@ -2180,7 +2183,8 @@ TEST_F(CatalogManagerReplSetTest, EnableShardingDBExists) { multi: false, upsert: true }], - writeConcern: { w: "majority" } + writeConcern: { w: "majority" }, + maxTimeMS: 30000 })")); ASSERT_EQ(expectedCmd, request.cmdObj); diff --git a/src/mongo/s/catalog/replset/catalog_manager_replica_set_test_fixture.cpp b/src/mongo/s/catalog/replset/catalog_manager_replica_set_test_fixture.cpp index 6d3231d06b1..0d6b5cd315d 100644 --- a/src/mongo/s/catalog/replset/catalog_manager_replica_set_test_fixture.cpp +++ b/src/mongo/s/catalog/replset/catalog_manager_replica_set_test_fixture.cpp @@ -281,8 +281,9 @@ void CatalogManagerReplSetTestFixture::expectChangeLogCreate(const HostAndPort& onCommand([&](const RemoteCommandRequest& request) { ASSERT_EQUALS(configHost, request.target); ASSERT_EQUALS("config", request.dbname); - BSONObj expectedCreateCmd = BSON("create" << ChangeLogType::ConfigNS << "capped" << true - << "size" << 1024 * 1024 * 10); + BSONObj expectedCreateCmd = + BSON("create" << ChangeLogType::ConfigNS << "capped" << true << "size" + << 1024 * 1024 * 10 << "maxTimeMS" << 30000); ASSERT_EQUALS(expectedCreateCmd, request.cmdObj); return response; diff --git a/src/mongo/s/catalog/replset/replset_dist_lock_manager.cpp b/src/mongo/s/catalog/replset/replset_dist_lock_manager.cpp index 920c7bcb0b1..0be248e3b56 100644 --- a/src/mongo/s/catalog/replset/replset_dist_lock_manager.cpp +++ b/src/mongo/s/catalog/replset/replset_dist_lock_manager.cpp @@ -35,6 +35,7 @@ #include "mongo/base/status.h" #include "mongo/base/status_with.h" #include "mongo/db/service_context.h" +#include "mongo/db/operation_context_noop.h" #include "mongo/s/catalog/dist_lock_catalog.h" #include "mongo/s/catalog/type_lockpings.h" #include "mongo/s/catalog/type_locks.h" @@ -78,7 +79,7 @@ void ReplSetDistLockManager::startUp() { } } -void ReplSetDistLockManager::shutDown(bool allowNetworking) { +void ReplSetDistLockManager::shutDown(OperationContext* txn, bool allowNetworking) { invariant(allowNetworking); { stdx::lock_guard<stdx::mutex> lk(_mutex); @@ -93,7 +94,7 @@ void ReplSetDistLockManager::shutDown(bool allowNetworking) { _execThread.reset(); } - auto status = _catalog->stopPing(_processID); + auto status = _catalog->stopPing(txn, _processID); if (!status.isOK()) { warning() << "error encountered while cleaning up distributed ping entry for " << _processID << causedBy(status); @@ -110,40 +111,45 @@ void ReplSetDistLockManager::doTask() { << " (sleeping for " << _pingInterval << ")"; Timer elapsedSincelastPing(_serviceContext->getTickSource()); + Client::initThread("replSetDistLockPinger"); + while (!isShutDown()) { - auto pingStatus = _catalog->ping(_processID, Date_t::now()); + { + auto txn = cc().makeOperationContext(); + auto pingStatus = _catalog->ping(txn.get(), _processID, Date_t::now()); - if (!pingStatus.isOK()) { - warning() << "pinging failed for distributed lock pinger" << causedBy(pingStatus); - } + if (!pingStatus.isOK()) { + warning() << "pinging failed for distributed lock pinger" << causedBy(pingStatus); + } - const milliseconds elapsed(elapsedSincelastPing.millis()); - if (elapsed > 10 * _pingInterval) { - warning() << "Lock pinger for proc: " << _processID << " was inactive for " << elapsed - << " ms"; - } - elapsedSincelastPing.reset(); + const milliseconds elapsed(elapsedSincelastPing.millis()); + if (elapsed > 10 * _pingInterval) { + warning() << "Lock pinger for proc: " << _processID << " was inactive for " + << elapsed << " ms"; + } + elapsedSincelastPing.reset(); - std::deque<DistLockHandle> toUnlockBatch; - { - stdx::unique_lock<stdx::mutex> lk(_mutex); - toUnlockBatch.swap(_unlockList); - } + std::deque<DistLockHandle> toUnlockBatch; + { + stdx::unique_lock<stdx::mutex> lk(_mutex); + toUnlockBatch.swap(_unlockList); + } - for (const auto& toUnlock : toUnlockBatch) { - auto unlockStatus = _catalog->unlock(toUnlock); + for (const auto& toUnlock : toUnlockBatch) { + auto unlockStatus = _catalog->unlock(txn.get(), toUnlock); - if (!unlockStatus.isOK()) { - warning() << "Failed to unlock lock with " << LocksType::lockID() << ": " - << toUnlock << causedBy(unlockStatus); - queueUnlock(toUnlock); - } else { - LOG(0) << "distributed lock with " << LocksType::lockID() << ": " << toUnlock - << "' unlocked."; - } + if (!unlockStatus.isOK()) { + warning() << "Failed to unlock lock with " << LocksType::lockID() << ": " + << toUnlock << causedBy(unlockStatus); + queueUnlock(toUnlock); + } else { + LOG(0) << "distributed lock with " << LocksType::lockID() << ": " << toUnlock + << "' unlocked."; + } - if (isShutDown()) { - return; + if (isShutDown()) { + return; + } } } @@ -152,10 +158,11 @@ void ReplSetDistLockManager::doTask() { } } -StatusWith<bool> ReplSetDistLockManager::canOvertakeLock(LocksType lockDoc, +StatusWith<bool> ReplSetDistLockManager::canOvertakeLock(OperationContext* txn, + LocksType lockDoc, const milliseconds& lockExpiration) { const auto& processID = lockDoc.getProcess(); - auto pingStatus = _catalog->getPing(processID); + auto pingStatus = _catalog->getPing(txn, processID); Date_t pingValue; if (pingStatus.isOK()) { @@ -173,7 +180,7 @@ StatusWith<bool> ReplSetDistLockManager::canOvertakeLock(LocksType lockDoc, } // else use default pingValue if ping document does not exist. Timer timer(_serviceContext->getTickSource()); - auto serverInfoStatus = _catalog->getServerInfo(); + auto serverInfoStatus = _catalog->getServerInfo(txn); if (!serverInfoStatus.isOK()) { return serverInfoStatus.getStatus(); } @@ -245,7 +252,11 @@ StatusWith<bool> ReplSetDistLockManager::canOvertakeLock(LocksType lockDoc, } StatusWith<DistLockManager::ScopedDistLock> ReplSetDistLockManager::lock( - StringData name, StringData whyMessage, milliseconds waitFor, milliseconds lockTryInterval) { + OperationContext* txn, + StringData name, + StringData whyMessage, + milliseconds waitFor, + milliseconds lockTryInterval) { Timer timer(_serviceContext->getTickSource()); Timer msgTimer(_serviceContext->getTickSource()); @@ -264,8 +275,8 @@ StatusWith<DistLockManager::ScopedDistLock> ReplSetDistLockManager::lock( << " ms, process : " << _processID << " )" << " with lockSessionID: " << lockSessionID << ", why: " << whyMessage; - auto lockResult = - _catalog->grabLock(name, lockSessionID, who, _processID, Date_t::now(), whyMessage); + auto lockResult = _catalog->grabLock( + txn, name, lockSessionID, who, _processID, Date_t::now(), whyMessage); auto status = lockResult.getStatus(); @@ -274,7 +285,7 @@ StatusWith<DistLockManager::ScopedDistLock> ReplSetDistLockManager::lock( // the lock document. LOG(0) << "distributed lock '" << name << "' acquired for '" << whyMessage << "', ts : " << lockSessionID; - return ScopedDistLock(lockSessionID, this); + return ScopedDistLock(txn, lockSessionID, this); } if (status != ErrorCodes::LockStateChangeFailed) { @@ -285,7 +296,7 @@ StatusWith<DistLockManager::ScopedDistLock> ReplSetDistLockManager::lock( } // Get info from current lock and check if we can overtake it. - auto getLockStatusResult = _catalog->getLockByName(name); + auto getLockStatusResult = _catalog->getLockByName(txn, name); const auto& getLockStatus = getLockStatusResult.getStatus(); if (!getLockStatusResult.isOK() && getLockStatus != ErrorCodes::LockNotFound) { @@ -296,14 +307,15 @@ StatusWith<DistLockManager::ScopedDistLock> ReplSetDistLockManager::lock( // found, use the normal grab lock path to acquire it. if (getLockStatusResult.isOK()) { auto currentLock = getLockStatusResult.getValue(); - auto canOvertakeResult = canOvertakeLock(currentLock, lockExpiration); + auto canOvertakeResult = canOvertakeLock(txn, currentLock, lockExpiration); if (!canOvertakeResult.isOK()) { return canOvertakeResult.getStatus(); } if (canOvertakeResult.getValue()) { - auto overtakeResult = _catalog->overtakeLock(name, + auto overtakeResult = _catalog->overtakeLock(txn, + name, lockSessionID, currentLock.getLockID(), who, @@ -319,7 +331,7 @@ StatusWith<DistLockManager::ScopedDistLock> ReplSetDistLockManager::lock( LOG(0) << "lock '" << name << "' successfully forced"; LOG(0) << "distributed lock '" << name << "' acquired, ts : " << lockSessionID; - return ScopedDistLock(lockSessionID, this); + return ScopedDistLock(txn, lockSessionID, this); } if (overtakeStatus != ErrorCodes::LockStateChangeFailed) { @@ -353,8 +365,8 @@ StatusWith<DistLockManager::ScopedDistLock> ReplSetDistLockManager::lock( return {ErrorCodes::LockBusy, str::stream() << "timed out waiting for " << name}; } -void ReplSetDistLockManager::unlock(const DistLockHandle& lockSessionID) { - auto unlockStatus = _catalog->unlock(lockSessionID); +void ReplSetDistLockManager::unlock(OperationContext* txn, const DistLockHandle& lockSessionID) { + auto unlockStatus = _catalog->unlock(txn, lockSessionID); if (!unlockStatus.isOK()) { queueUnlock(lockSessionID); @@ -364,8 +376,9 @@ void ReplSetDistLockManager::unlock(const DistLockHandle& lockSessionID) { } } -Status ReplSetDistLockManager::checkStatus(const DistLockHandle& lockHandle) { - return _catalog->getLockByTS(lockHandle).getStatus(); +Status ReplSetDistLockManager::checkStatus(OperationContext* txn, + const DistLockHandle& lockHandle) { + return _catalog->getLockByTS(txn, lockHandle).getStatus(); } void ReplSetDistLockManager::queueUnlock(const DistLockHandle& lockSessionID) { diff --git a/src/mongo/s/catalog/replset/replset_dist_lock_manager.h b/src/mongo/s/catalog/replset/replset_dist_lock_manager.h index 273eee5f278..5d3024d58dc 100644 --- a/src/mongo/s/catalog/replset/replset_dist_lock_manager.h +++ b/src/mongo/s/catalog/replset/replset_dist_lock_manager.h @@ -61,18 +61,19 @@ public: virtual ~ReplSetDistLockManager(); virtual void startUp() override; - virtual void shutDown(bool allowNetworking) override; + virtual void shutDown(OperationContext* txn, bool allowNetworking) override; virtual StatusWith<DistLockManager::ScopedDistLock> lock( + OperationContext* txn, StringData name, StringData whyMessage, stdx::chrono::milliseconds waitFor, stdx::chrono::milliseconds lockTryInterval) override; protected: - virtual void unlock(const DistLockHandle& lockSessionID) override; + virtual void unlock(OperationContext* txn, const DistLockHandle& lockSessionID) override; - virtual Status checkStatus(const DistLockHandle& lockSessionID) override; + virtual Status checkStatus(OperationContext* txn, const DistLockHandle& lockSessionID) override; private: /** @@ -94,7 +95,8 @@ private: * Returns true if the current process that owns the lock has no fresh pings since * the lock expiration threshold. */ - StatusWith<bool> canOvertakeLock(const LocksType lockDoc, + StatusWith<bool> canOvertakeLock(OperationContext* txn, + const LocksType lockDoc, const stdx::chrono::milliseconds& lockExpiration); // diff --git a/src/mongo/s/catalog/replset/replset_dist_lock_manager_test.cpp b/src/mongo/s/catalog/replset/replset_dist_lock_manager_test.cpp index 0b3a01c3ac3..9c940a06d07 100644 --- a/src/mongo/s/catalog/replset/replset_dist_lock_manager_test.cpp +++ b/src/mongo/s/catalog/replset/replset_dist_lock_manager_test.cpp @@ -40,6 +40,7 @@ #include "mongo/bson/json.h" #include "mongo/bson/util/builder.h" #include "mongo/db/jsobj.h" +#include "mongo/db/operation_context_noop.h" #include "mongo/db/service_context_noop.h" #include "mongo/s/catalog/dist_lock_catalog_mock.h" #include "mongo/s/catalog/type_lockpings.h" @@ -79,14 +80,20 @@ public: ReplSetDistLockManagerFixture() : _dummyDoNotUse(stdx::make_unique<DistLockCatalogMock>()), _mockCatalog(_dummyDoNotUse.get()), - _processID("test"), - _mgr(&_context, _processID, std::move(_dummyDoNotUse), kPingInterval, kLockExpiration) {} + _processID("test") { + setGlobalServiceContext(stdx::make_unique<ServiceContextNoop>()); + _mgr = stdx::make_unique<ReplSetDistLockManager>(getGlobalServiceContext(), + _processID, + std::move(_dummyDoNotUse), + kPingInterval, + kLockExpiration); + } /** * Returns the lock manager instance that is being tested. */ ReplSetDistLockManager* getMgr() { - return &_mgr; + return _mgr.get(); } /** @@ -103,23 +110,27 @@ public: return _processID; } + OperationContext* txn() { + return &_txn; + } + protected: void setUp() override { - _context.setTickSource(stdx::make_unique<SystemTickSource>()); - _mgr.startUp(); + getGlobalServiceContext()->setTickSource(stdx::make_unique<SystemTickSource>()); + _mgr->startUp(); } void tearDown() override { // Don't care about what shutDown passes to stopPing here. _mockCatalog->expectStopPing([](StringData) {}, Status::OK()); - _mgr.shutDown(true); + _mgr->shutDown(txn(), true); } std::unique_ptr<DistLockCatalogMock> _dummyDoNotUse; // dummy placeholder DistLockCatalogMock* _mockCatalog; string _processID; - ServiceContextNoop _context; - ReplSetDistLockManager _mgr; + std::unique_ptr<ReplSetDistLockManager> _mgr; + OperationContextNoop _txn; }; class RSDistLockMgrWithMockTickSource : public ReplSetDistLockManagerFixture { @@ -128,13 +139,13 @@ public: * Returns the mock tick source. */ TickSourceMock* getMockTickSource() { - return dynamic_cast<TickSourceMock*>(_context.getTickSource()); + return dynamic_cast<TickSourceMock*>(getGlobalServiceContext()->getTickSource()); } protected: void setUp() override { - _context.setTickSource(stdx::make_unique<TickSourceMock>()); - _mgr.startUp(); + getGlobalServiceContext()->setTickSource(stdx::make_unique<TickSourceMock>()); + _mgr->startUp(); } }; @@ -202,7 +213,8 @@ TEST_F(ReplSetDistLockManagerFixture, BasicLockLifeCycle) { OID unlockSessionIDPassed; { - auto lockStatus = getMgr()->lock(lockName, + auto lockStatus = getMgr()->lock(txn(), + lockName, whyMsg, DistLockManager::kDefaultSingleLockAttemptTimeout, DistLockManager::kDefaultLockRetryInterval); @@ -334,7 +346,8 @@ TEST_F(RSDistLockMgrWithMockTickSource, LockSuccessAfterRetry) { OID unlockSessionIDPassed; { - auto lockStatus = getMgr()->lock(lockName, whyMsg, Milliseconds(10), Milliseconds(1)); + auto lockStatus = + getMgr()->lock(txn(), lockName, whyMsg, Milliseconds(10), Milliseconds(1)); ASSERT_OK(lockStatus.getStatus()); getMockCatalog()->expectNoGrabLock(); @@ -431,7 +444,8 @@ TEST_F(RSDistLockMgrWithMockTickSource, LockFailsAfterRetry) { Status::OK()); { - auto lockStatus = getMgr()->lock(lockName, whyMsg, Milliseconds(10), Milliseconds(1)); + auto lockStatus = + getMgr()->lock(txn(), lockName, whyMsg, Milliseconds(10), Milliseconds(1)); ASSERT_NOT_OK(lockStatus.getStatus()); } @@ -446,7 +460,7 @@ TEST_F(RSDistLockMgrWithMockTickSource, LockFailsAfterRetry) { // Join the background thread before trying to call asserts. Shutdown calls // stopPing and we don't care in this test. getMockCatalog()->expectStopPing([](StringData) {}, Status::OK()); - getMgr()->shutDown(true); + getMgr()->shutDown(txn(), true); // No assert until shutDown has been called to make sure that the background thread // won't be trying to access the local variables that were captured by lamdas that @@ -469,7 +483,7 @@ TEST_F(ReplSetDistLockManagerFixture, LockBusyNoRetry) { getMockCatalog()->expectGetLockByName([](StringData) {}, {ErrorCodes::LockNotFound, "not found!"}); - auto status = getMgr()->lock("", "", Milliseconds(0), Milliseconds(0)).getStatus(); + auto status = getMgr()->lock(txn(), "", "", Milliseconds(0), Milliseconds(0)).getStatus(); ASSERT_NOT_OK(status); ASSERT_EQUALS(ErrorCodes::LockBusy, status.code()); } @@ -518,7 +532,7 @@ TEST_F(RSDistLockMgrWithMockTickSource, LockRetryTimeout) { {ErrorCodes::LockNotFound, "not found!"}); auto lockStatus = - getMgr()->lock(lockName, whyMsg, Milliseconds(5), Milliseconds(1)).getStatus(); + getMgr()->lock(txn(), lockName, whyMsg, Milliseconds(5), Milliseconds(1)).getStatus(); ASSERT_NOT_OK(lockStatus); ASSERT_EQUALS(ErrorCodes::LockBusy, lockStatus.code()); @@ -572,7 +586,7 @@ TEST_F(ReplSetDistLockManagerFixture, MustUnlockOnLockError) { Status::OK()); auto lockStatus = - getMgr()->lock(lockName, whyMsg, Milliseconds(10), Milliseconds(1)).getStatus(); + getMgr()->lock(txn(), lockName, whyMsg, Milliseconds(10), Milliseconds(1)).getStatus(); ASSERT_NOT_OK(lockStatus); ASSERT_EQUALS(ErrorCodes::NetworkTimeout, lockStatus.code()); @@ -587,7 +601,7 @@ TEST_F(ReplSetDistLockManagerFixture, MustUnlockOnLockError) { // Join the background thread before trying to call asserts. Shutdown calls // stopPing and we don't care in this test. getMockCatalog()->expectStopPing([](StringData) {}, Status::OK()); - getMgr()->shutDown(true); + getMgr()->shutDown(txn(), true); // No assert until shutDown has been called to make sure that the background thread // won't be trying to access the local variables that were captured by lamdas that @@ -637,7 +651,7 @@ TEST_F(ReplSetDistLockManagerFixture, LockPinging) { // Join the background thread before trying to call asserts. Shutdown calls // stopPing and we don't care in this test. getMockCatalog()->expectStopPing([](StringData) {}, Status::OK()); - getMgr()->shutDown(true); + getMgr()->shutDown(txn(), true); // No assert until shutDown has been called to make sure that the background thread // won't be trying to access the local variables that were captured by lamdas that @@ -707,7 +721,7 @@ TEST_F(ReplSetDistLockManagerFixture, UnlockUntilNoError) { StringData why) { lockSessionID = lockSessionIDArg; }, retLockDoc); - { auto lockStatus = getMgr()->lock("test", "why", Milliseconds(0), Milliseconds(0)); } + { auto lockStatus = getMgr()->lock(txn(), "test", "why", Milliseconds(0), Milliseconds(0)); } bool didTimeout = false; { @@ -720,7 +734,7 @@ TEST_F(ReplSetDistLockManagerFixture, UnlockUntilNoError) { // Join the background thread before trying to call asserts. Shutdown calls // stopPing and we don't care in this test. getMockCatalog()->expectStopPing([](StringData) {}, Status::OK()); - getMgr()->shutDown(true); + getMgr()->shutDown(txn(), true); // No assert until shutDown has been called to make sure that the background thread // won't be trying to access the local variables that were captured by lamdas that @@ -800,8 +814,8 @@ TEST_F(ReplSetDistLockManagerFixture, MultipleQueuedUnlock) { retLockDoc); { - auto lockStatus = getMgr()->lock("test", "why", Milliseconds(0), Milliseconds(0)); - auto otherStatus = getMgr()->lock("lock", "why", Milliseconds(0), Milliseconds(0)); + auto lockStatus = getMgr()->lock(txn(), "test", "why", Milliseconds(0), Milliseconds(0)); + auto otherStatus = getMgr()->lock(txn(), "lock", "why", Milliseconds(0), Milliseconds(0)); } bool didTimeout = false; @@ -816,7 +830,7 @@ TEST_F(ReplSetDistLockManagerFixture, MultipleQueuedUnlock) { // Join the background thread before trying to call asserts. Shutdown calls // stopPing and we don't care in this test. getMockCatalog()->expectStopPing([](StringData) {}, Status::OK()); - getMgr()->shutDown(true); + getMgr()->shutDown(txn(), true); // No assert until shutDown has been called to make sure that the background thread // won't be trying to access the local variables that were captured by lamdas that @@ -840,7 +854,7 @@ TEST_F(ReplSetDistLockManagerFixture, CleanupPingOnShutdown) { stopPingCalled = true; }, Status::OK()); - getMgr()->shutDown(true); + getMgr()->shutDown(txn(), true); ASSERT_TRUE(stopPingCalled); } @@ -863,7 +877,7 @@ TEST_F(ReplSetDistLockManagerFixture, CheckLockStatusOK) { retLockDoc); - auto lockStatus = getMgr()->lock("a", "", Milliseconds(0), Milliseconds(0)); + auto lockStatus = getMgr()->lock(txn(), "a", "", Milliseconds(0), Milliseconds(0)); ASSERT_OK(lockStatus.getStatus()); getMockCatalog()->expectNoGrabLock(); @@ -901,7 +915,7 @@ TEST_F(ReplSetDistLockManagerFixture, CheckLockStatusNoLongerOwn) { retLockDoc); - auto lockStatus = getMgr()->lock("a", "", Milliseconds(0), Milliseconds(0)); + auto lockStatus = getMgr()->lock(txn(), "a", "", Milliseconds(0), Milliseconds(0)); ASSERT_OK(lockStatus.getStatus()); getMockCatalog()->expectNoGrabLock(); @@ -940,7 +954,7 @@ TEST_F(ReplSetDistLockManagerFixture, CheckLockStatusError) { retLockDoc); - auto lockStatus = getMgr()->lock("a", "", Milliseconds(0), Milliseconds(0)); + auto lockStatus = getMgr()->lock(txn(), "a", "", Milliseconds(0), Milliseconds(0)); ASSERT_OK(lockStatus.getStatus()); getMockCatalog()->expectNoGrabLock(); @@ -1002,7 +1016,8 @@ TEST_F(ReplSetDistLockManagerFixture, BasicLockOvertaking) { // First attempt will record the ping data. { - auto status = getMgr()->lock("bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); + auto status = + getMgr()->lock(txn(), "bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); ASSERT_NOT_OK(status); ASSERT_EQUALS(ErrorCodes::LockBusy, status.code()); } @@ -1032,7 +1047,7 @@ TEST_F(ReplSetDistLockManagerFixture, BasicLockOvertaking) { // Second attempt should overtake lock. { - auto lockStatus = getMgr()->lock("bar", "foo", Milliseconds(0), Milliseconds(0)); + auto lockStatus = getMgr()->lock(txn(), "bar", "foo", Milliseconds(0), Milliseconds(0)); ASSERT_OK(lockStatus.getStatus()); @@ -1078,7 +1093,8 @@ TEST_F(ReplSetDistLockManagerFixture, CannotOvertakeIfExpirationHasNotElapsed) { // First attempt will record the ping data. { - auto status = getMgr()->lock("bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); + auto status = + getMgr()->lock(txn(), "bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); ASSERT_NOT_OK(status); ASSERT_EQUALS(ErrorCodes::LockBusy, status.code()); } @@ -1089,7 +1105,8 @@ TEST_F(ReplSetDistLockManagerFixture, CannotOvertakeIfExpirationHasNotElapsed) { // Second attempt should still not overtake lock. { - auto status = getMgr()->lock("bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); + auto status = + getMgr()->lock(txn(), "bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); ASSERT_NOT_OK(status); ASSERT_EQUALS(ErrorCodes::LockBusy, status.code()); } @@ -1117,7 +1134,7 @@ TEST_F(ReplSetDistLockManagerFixture, GetPingErrorWhileOvertaking) { ASSERT_EQUALS("otherProcess", process); }, {ErrorCodes::NetworkTimeout, "bad test network"}); - auto status = getMgr()->lock("bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); + auto status = getMgr()->lock(txn(), "bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); ASSERT_NOT_OK(status); ASSERT_EQUALS(ErrorCodes::NetworkTimeout, status.code()); } @@ -1144,7 +1161,7 @@ TEST_F(ReplSetDistLockManagerFixture, GetInvalidPingDocumentWhileOvertaking) { getMockCatalog()->expectGetPing( [](StringData process) { ASSERT_EQUALS("otherProcess", process); }, invalidPing); - auto status = getMgr()->lock("bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); + auto status = getMgr()->lock(txn(), "bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); ASSERT_NOT_OK(status); ASSERT_EQUALS(ErrorCodes::UnsupportedFormat, status.code()); } @@ -1177,7 +1194,7 @@ TEST_F(ReplSetDistLockManagerFixture, GetServerInfoErrorWhileOvertaking) { getMockCatalog()->expectGetServerInfo([]() {}, {ErrorCodes::NetworkTimeout, "bad test network"}); - auto status = getMgr()->lock("bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); + auto status = getMgr()->lock(txn(), "bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); ASSERT_NOT_OK(status); ASSERT_EQUALS(ErrorCodes::NetworkTimeout, status.code()); } @@ -1192,7 +1209,7 @@ TEST_F(ReplSetDistLockManagerFixture, GetLockErrorWhileOvertaking) { getMockCatalog()->expectGetLockByName([](StringData name) { ASSERT_EQUALS("bar", name); }, {ErrorCodes::NetworkTimeout, "bad test network"}); - auto status = getMgr()->lock("bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); + auto status = getMgr()->lock(txn(), "bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); ASSERT_NOT_OK(status); ASSERT_EQUALS(ErrorCodes::NetworkTimeout, status.code()); } @@ -1207,7 +1224,7 @@ TEST_F(ReplSetDistLockManagerFixture, GetLockDisappearedWhileOvertaking) { getMockCatalog()->expectGetLockByName([](StringData name) { ASSERT_EQUALS("bar", name); }, {ErrorCodes::LockNotFound, "disappeared!"}); - auto status = getMgr()->lock("bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); + auto status = getMgr()->lock(txn(), "bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); ASSERT_NOT_OK(status); ASSERT_EQUALS(ErrorCodes::LockBusy, status.code()); } @@ -1259,7 +1276,8 @@ TEST_F(ReplSetDistLockManagerFixture, CannotOvertakeIfPingIsActive) { getServerInfoCallCount++; }, DistLockCatalog::ServerInfo(configServerLocalTime, OID())); - auto status = getMgr()->lock("bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); + auto status = + getMgr()->lock(txn(), "bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); ASSERT_NOT_OK(status); ASSERT_EQUALS(ErrorCodes::LockBusy, status.code()); } @@ -1293,7 +1311,7 @@ TEST_F(ReplSetDistLockManagerFixture, CannotOvertakeIfPingIsActive) { OID unlockSessionIDPassed; { - auto lockStatus = getMgr()->lock("bar", "foo", Milliseconds(0), Milliseconds(0)); + auto lockStatus = getMgr()->lock(txn(), "bar", "foo", Milliseconds(0), Milliseconds(0)); ASSERT_OK(lockStatus.getStatus()); @@ -1357,7 +1375,8 @@ TEST_F(ReplSetDistLockManagerFixture, CannotOvertakeIfOwnerJustChanged) { getServerInfoCallCount++; }, DistLockCatalog::ServerInfo(configServerLocalTime, OID())); - auto status = getMgr()->lock("bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); + auto status = + getMgr()->lock(txn(), "bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); ASSERT_NOT_OK(status); ASSERT_EQUALS(ErrorCodes::LockBusy, status.code()); } @@ -1391,7 +1410,7 @@ TEST_F(ReplSetDistLockManagerFixture, CannotOvertakeIfOwnerJustChanged) { OID unlockSessionIDPassed; { - auto lockStatus = getMgr()->lock("bar", "foo", Milliseconds(0), Milliseconds(0)); + auto lockStatus = getMgr()->lock(txn(), "bar", "foo", Milliseconds(0), Milliseconds(0)); ASSERT_OK(lockStatus.getStatus()); @@ -1458,7 +1477,8 @@ TEST_F(ReplSetDistLockManagerFixture, CannotOvertakeIfElectionIdChanged) { getServerInfoCallCount++; }, DistLockCatalog::ServerInfo(configServerLocalTime, lastElectionId)); - auto status = getMgr()->lock("bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); + auto status = + getMgr()->lock(txn(), "bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); ASSERT_NOT_OK(status); ASSERT_EQUALS(ErrorCodes::LockBusy, status.code()); } @@ -1492,7 +1512,7 @@ TEST_F(ReplSetDistLockManagerFixture, CannotOvertakeIfElectionIdChanged) { OID unlockSessionIDPassed; { - auto lockStatus = getMgr()->lock("bar", "foo", Milliseconds(0), Milliseconds(0)); + auto lockStatus = getMgr()->lock(txn(), "bar", "foo", Milliseconds(0), Milliseconds(0)); ASSERT_OK(lockStatus.getStatus()); @@ -1550,7 +1570,8 @@ TEST_F(ReplSetDistLockManagerFixture, LockOvertakingResultsInError) { // First attempt will record the ping data. { - auto status = getMgr()->lock("bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); + auto status = + getMgr()->lock(txn(), "bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); ASSERT_NOT_OK(status); ASSERT_EQUALS(ErrorCodes::LockBusy, status.code()); } @@ -1589,7 +1610,7 @@ TEST_F(ReplSetDistLockManagerFixture, LockOvertakingResultsInError) { Status::OK()); // Second attempt should overtake lock. - auto lockStatus = getMgr()->lock("bar", "foo", Milliseconds(0), Milliseconds(0)); + auto lockStatus = getMgr()->lock(txn(), "bar", "foo", Milliseconds(0), Milliseconds(0)); ASSERT_NOT_OK(lockStatus.getStatus()); @@ -1604,7 +1625,7 @@ TEST_F(ReplSetDistLockManagerFixture, LockOvertakingResultsInError) { // Join the background thread before trying to call asserts. Shutdown calls // stopPing and we don't care in this test. getMockCatalog()->expectStopPing([](StringData) {}, Status::OK()); - getMgr()->shutDown(true); + getMgr()->shutDown(txn(), true); // No assert until shutDown has been called to make sure that the background thread // won't be trying to access the local variables that were captured by lamdas that @@ -1655,7 +1676,8 @@ TEST_F(ReplSetDistLockManagerFixture, LockOvertakingFailed) { // First attempt will record the ping data. { - auto status = getMgr()->lock("bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); + auto status = + getMgr()->lock(txn(), "bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); ASSERT_NOT_OK(status); ASSERT_EQUALS(ErrorCodes::LockBusy, status.code()); } @@ -1681,7 +1703,8 @@ TEST_F(ReplSetDistLockManagerFixture, LockOvertakingFailed) { {ErrorCodes::LockStateChangeFailed, "nmod 0"}); { - auto status = getMgr()->lock("bar", "foo", Milliseconds(0), Milliseconds(0)).getStatus(); + auto status = + getMgr()->lock(txn(), "bar", "foo", Milliseconds(0), Milliseconds(0)).getStatus(); ASSERT_NOT_OK(status); ASSERT_EQUALS(ErrorCodes::LockBusy, status.code()); } @@ -1728,7 +1751,8 @@ TEST_F(ReplSetDistLockManagerFixture, CannotOvertakeIfConfigServerClockGoesBackw // First attempt will record the ping data. { - auto status = getMgr()->lock("bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); + auto status = + getMgr()->lock(txn(), "bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); ASSERT_NOT_OK(status); ASSERT_EQUALS(ErrorCodes::LockBusy, status.code()); } @@ -1739,7 +1763,8 @@ TEST_F(ReplSetDistLockManagerFixture, CannotOvertakeIfConfigServerClockGoesBackw // Second attempt should not overtake lock. { - auto status = getMgr()->lock("bar", "foo", Milliseconds(0), Milliseconds(0)).getStatus(); + auto status = + getMgr()->lock(txn(), "bar", "foo", Milliseconds(0), Milliseconds(0)).getStatus(); ASSERT_NOT_OK(status); ASSERT_EQUALS(ErrorCodes::LockBusy, status.code()); } @@ -1781,7 +1806,8 @@ TEST_F(RSDistLockMgrWithMockTickSource, CanOvertakeIfNoPingDocument) { // First attempt will record the ping data. { - auto status = getMgr()->lock("bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); + auto status = + getMgr()->lock(txn(), "bar", "", Milliseconds(0), Milliseconds(0)).getStatus(); ASSERT_NOT_OK(status); ASSERT_EQUALS(ErrorCodes::LockBusy, status.code()); } @@ -1826,7 +1852,10 @@ TEST_F(RSDistLockMgrWithMockTickSource, CanOvertakeIfNoPingDocument) { Status::OK()); // Second attempt should overtake lock. - { ASSERT_OK(getMgr()->lock("bar", "foo", Milliseconds(0), Milliseconds(0)).getStatus()); } + { + ASSERT_OK( + getMgr()->lock(txn(), "bar", "foo", Milliseconds(0), Milliseconds(0)).getStatus()); + } } } // unnamed namespace diff --git a/src/mongo/s/client/shard_registry.cpp b/src/mongo/s/client/shard_registry.cpp index 3d0c7725184..99df3d845b2 100644 --- a/src/mongo/s/client/shard_registry.cpp +++ b/src/mongo/s/client/shard_registry.cpp @@ -34,12 +34,14 @@ #include <set> +#include "mongo/bson/bsonobj.h" #include "mongo/client/connection_string.h" #include "mongo/client/query_fetcher.h" #include "mongo/client/remote_command_targeter.h" #include "mongo/client/remote_command_targeter_factory.h" #include "mongo/client/replica_set_monitor.h" #include "mongo/db/client.h" +#include "mongo/db/query/lite_parsed_query.h" #include "mongo/executor/task_executor.h" #include "mongo/rpc/get_status_from_command_result.h" #include "mongo/rpc/metadata/config_server_metadata.h" @@ -54,6 +56,7 @@ #include "mongo/stdx/mutex.h" #include "mongo/util/log.h" #include "mongo/util/mongoutils/str.h" +#include "mongo/util/time_support.h" namespace mongo { @@ -86,6 +89,39 @@ void updateReplSetMonitor(const std::shared_ptr<RemoteCommandTargeter>& targeter } } +BSONObj appendMaxTimeToCmdObj(long long maxTimeMicros, const BSONObj& cmdObj) { + Seconds maxTime = kConfigCommandTimeout; + + Microseconds remainingTxnMaxTime(maxTimeMicros); + bool hasTxnMaxTime(remainingTxnMaxTime != Microseconds::zero()); + bool hasUserMaxTime = !cmdObj[LiteParsedQuery::cmdOptionMaxTimeMS].eoo(); + + if (hasTxnMaxTime) { + maxTime = duration_cast<Seconds>(remainingTxnMaxTime); + } else if (hasUserMaxTime) { + return cmdObj; + } + + BSONObjBuilder updatedCmdBuilder; + if (hasTxnMaxTime && hasUserMaxTime) { // Need to remove user provided maxTimeMS. + BSONObjIterator cmdObjIter(cmdObj); + const char* maxTimeFieldName = LiteParsedQuery::cmdOptionMaxTimeMS.c_str(); + while (cmdObjIter.more()) { + BSONElement e = cmdObjIter.next(); + if (str::equals(e.fieldName(), maxTimeFieldName)) { + continue; + } + updatedCmdBuilder.append(e); + } + } else { + updatedCmdBuilder.appendElements(cmdObj); + } + + updatedCmdBuilder.append(LiteParsedQuery::cmdOptionMaxTimeMS, + durationCount<Milliseconds>(maxTime)); + return updatedCmdBuilder.obj(); +} + } // unnamed namespace ShardRegistry::ShardRegistry(std::unique_ptr<RemoteCommandTargeterFactory> targeterFactory, @@ -352,6 +388,7 @@ OpTime ShardRegistry::getConfigOpTime() { } StatusWith<ShardRegistry::QueryResponse> ShardRegistry::exhaustiveFindOnConfig( + OperationContext* txn, const ReadPreferenceSetting& readPref, const NamespaceString& nss, const BSONObj& query, @@ -419,6 +456,14 @@ StatusWith<ShardRegistry::QueryResponse> ShardRegistry::exhaustiveFindOnConfig( BSONObjBuilder findCmdBuilder; lpq->asFindCommand(&findCmdBuilder); + Seconds maxTime = kConfigCommandTimeout; + Microseconds remainingTxnMaxTime(txn->getRemainingMaxTimeMicros()); + if (remainingTxnMaxTime != Microseconds::zero()) { + maxTime = duration_cast<Seconds>(remainingTxnMaxTime); + } + findCmdBuilder.append(LiteParsedQuery::cmdOptionMaxTimeMS, + durationCount<Milliseconds>(maxTime)); + QueryFetcher fetcher(_executor.get(), host.getValue(), nss, @@ -498,7 +543,8 @@ StatusWith<BSONObj> ShardRegistry::runCommandForAddShard(OperationContext* txn, return status.getValue().response; } -StatusWith<BSONObj> ShardRegistry::runCommandOnConfig(const ReadPreferenceSetting& readPref, +StatusWith<BSONObj> ShardRegistry::runCommandOnConfig(OperationContext* txn, + const ReadPreferenceSetting& readPref, const std::string& dbName, const BSONObj& cmdObj) { auto response = _runCommandWithMetadata( @@ -506,7 +552,7 @@ StatusWith<BSONObj> ShardRegistry::runCommandOnConfig(const ReadPreferenceSettin getConfigShard(), readPref, dbName, - cmdObj, + appendMaxTimeToCmdObj(txn->getRemainingMaxTimeMicros(), cmdObj), readPref.pref == ReadPreference::PrimaryOnly ? kReplMetadata : kReplSecondaryOkMetadata); if (!response.isOK()) { @@ -517,10 +563,15 @@ StatusWith<BSONObj> ShardRegistry::runCommandOnConfig(const ReadPreferenceSettin return response.getValue().response; } -StatusWith<BSONObj> ShardRegistry::runCommandOnConfigWithNotMasterRetries(const std::string& dbname, +StatusWith<BSONObj> ShardRegistry::runCommandOnConfigWithNotMasterRetries(OperationContext* txn, + const std::string& dbname, const BSONObj& cmdObj) { auto response = _runCommandWithNotMasterRetries( - _executor.get(), getConfigShard(), dbname, cmdObj, kReplMetadata); + _executor.get(), + getConfigShard(), + dbname, + appendMaxTimeToCmdObj(txn->getRemainingMaxTimeMicros(), cmdObj), + kReplMetadata); if (!response.isOK()) { return response.getStatus(); diff --git a/src/mongo/s/client/shard_registry.h b/src/mongo/s/client/shard_registry.h index f09ed9bd54a..27efbb16488 100644 --- a/src/mongo/s/client/shard_registry.h +++ b/src/mongo/s/client/shard_registry.h @@ -201,6 +201,7 @@ public: * Note: should never be used outside of CatalogManagerReplicaSet or DistLockCatalogImpl. */ StatusWith<QueryResponse> exhaustiveFindOnConfig( + OperationContext* txn, const ReadPreferenceSetting& readPref, const NamespaceString& nss, const BSONObj& query, @@ -240,7 +241,8 @@ public: * the result. It is the responsibility of the caller to check the returned BSON for * command-specific failures. */ - StatusWith<BSONObj> runCommandOnConfig(const ReadPreferenceSetting& readPref, + StatusWith<BSONObj> runCommandOnConfig(OperationContext* txn, + const ReadPreferenceSetting& readPref, const std::string& dbname, const BSONObj& cmdObj); @@ -260,7 +262,8 @@ public: const std::string& dbname, const BSONObj& cmdObj); - StatusWith<BSONObj> runCommandOnConfigWithNotMasterRetries(const std::string& dbname, + StatusWith<BSONObj> runCommandOnConfigWithNotMasterRetries(OperationContext* txn, + const std::string& dbname, const BSONObj& cmdObj); private: |