diff options
author | Pierlauro Sciarelli <pierlauro.sciarelli@mongodb.com> | 2020-07-24 16:45:21 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-07-27 10:34:38 +0000 |
commit | 4dab9b9781f943fcd7e2f15e61bdbce9953d0e23 (patch) | |
tree | f75410bc446d3b9acca6de8271b6a07180ac3296 | |
parent | 21a3ee6079eb3cc83a5210cf53d98840cbc83a20 (diff) | |
download | mongo-4dab9b9781f943fcd7e2f15e61bdbce9953d0e23.tar.gz |
SERVER-49400 Differenciate VectorClock persist behavior based on cluster role
-rw-r--r-- | jstests/core/views/views_all_commands.js | 1 | ||||
-rw-r--r-- | jstests/replsets/db_reads_while_recovering_all_commands.js | 1 | ||||
-rw-r--r-- | jstests/sharding/read_write_concern_defaults_application.js | 1 | ||||
-rw-r--r-- | src/mongo/db/SConscript | 3 | ||||
-rw-r--r-- | src/mongo/db/vector_clock_mongod.cpp | 45 | ||||
-rw-r--r-- | src/mongo/db/vector_clock_mongod_test.cpp | 25 | ||||
-rw-r--r-- | src/mongo/db/vector_clock_persist_command.cpp | 78 |
7 files changed, 148 insertions, 6 deletions
diff --git a/jstests/core/views/views_all_commands.js b/jstests/core/views/views_all_commands.js index a9952cae3b5..672cdd38f97 100644 --- a/jstests/core/views/views_all_commands.js +++ b/jstests/core/views/views_all_commands.js @@ -118,6 +118,7 @@ let viewsCommandTests = { _shardsvrRenameCollection: {skip: isAnInternalCommand}, _shardsvrShardCollection: {skip: isAnInternalCommand}, _transferMods: {skip: isAnInternalCommand}, + _vectorClockPersist: {skip: isAnInternalCommand}, abortTransaction: {skip: isUnrelated}, addShard: {skip: isUnrelated}, addShardToZone: {skip: isUnrelated}, diff --git a/jstests/replsets/db_reads_while_recovering_all_commands.js b/jstests/replsets/db_reads_while_recovering_all_commands.js index 9e094c8ba79..1d7c13742df 100644 --- a/jstests/replsets/db_reads_while_recovering_all_commands.js +++ b/jstests/replsets/db_reads_while_recovering_all_commands.js @@ -66,6 +66,7 @@ const allCommands = { _shardsvrMovePrimary: {skip: isPrimaryOnly}, _shardsvrShardCollection: {skip: isPrimaryOnly}, _transferMods: {skip: isPrimaryOnly}, + _vectorClockPersist: {skip: isPrimaryOnly}, abortTransaction: {skip: isPrimaryOnly}, aggregate: { command: {aggregate: collName, pipeline: [{$match: {}}], cursor: {}}, diff --git a/jstests/sharding/read_write_concern_defaults_application.js b/jstests/sharding/read_write_concern_defaults_application.js index 4768ed04aa7..d95cdd6eec7 100644 --- a/jstests/sharding/read_write_concern_defaults_application.js +++ b/jstests/sharding/read_write_concern_defaults_application.js @@ -117,6 +117,7 @@ let testCases = { _shardsvrRenameCollection: {skip: "internal command"}, _shardsvrShardCollection: {skip: "internal command"}, _transferMods: {skip: "internal command"}, + _vectorClockPersist: {skip: "internal command"}, abortTransaction: { setUp: function(conn) { assert.commandWorked(conn.getDB(db).runCommand({create: coll, writeConcern: {w: 1}})); diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript index c5a203c7163..991bd28507e 100644 --- a/src/mongo/db/SConscript +++ b/src/mongo/db/SConscript @@ -1623,6 +1623,7 @@ env.Library( env.Library( target='vector_clock_mongod', source=[ + 'vector_clock_persist_command.cpp', 'vector_clock_mongod.cpp', ], LIBDEPS=[ @@ -1633,6 +1634,8 @@ env.Library( 'rw_concern_d', 'repl/replica_set_aware_service', 'server_options_core', + '$BUILD_DIR/mongo/db/s/sharding_api_d', + '$BUILD_DIR/mongo/s/grid', ], ) diff --git a/src/mongo/db/vector_clock_mongod.cpp b/src/mongo/db/vector_clock_mongod.cpp index 51a826a71ee..1b34ca5133d 100644 --- a/src/mongo/db/vector_clock_mongod.cpp +++ b/src/mongo/db/vector_clock_mongod.cpp @@ -33,10 +33,13 @@ #include "mongo/db/logical_time_validator.h" #include "mongo/db/persistent_task_store.h" #include "mongo/db/repl/replica_set_aware_service.h" +#include "mongo/db/repl/replication_coordinator.h" +#include "mongo/db/s/sharding_state.h" #include "mongo/db/vector_clock_document_gen.h" #include "mongo/db/vector_clock_mutable.h" #include "mongo/executor/task_executor_pool.h" #include "mongo/logv2/log.h" +#include "mongo/s/grid.h" #include "mongo/util/concurrency/thread_pool.h" namespace mongo { @@ -247,7 +250,34 @@ private: } std::string getOperationName() override { - return "persist"; + return "localPersist"; + } + }; + + /* + * VectorClockStateOperation invoking PersistOperation on a shard server's primary. + */ + class RemotePersistOperation : public VectorClockStateOperation { + void execute(VectorClockMongoD* vectorClock, OperationContext* opCtx) override { + auto const shardingState = ShardingState::get(opCtx); + invariant(shardingState->enabled()); + + auto selfShard = uassertStatusOK( + Grid::get(opCtx)->shardRegistry()->getShard(opCtx, shardingState->shardId())); + + auto cmdResponse = uassertStatusOK(selfShard->runCommandWithFixedRetryAttempts( + opCtx, + ReadPreferenceSetting{ReadPreference::PrimaryOnly}, + NamespaceString::kVectorClockNamespace.toString(), + BSON("_vectorClockPersist" << 1), + Seconds{30}, + Shard::RetryPolicy::kIdempotent)); + + uassertStatusOK(cmdResponse.commandStatus); + } + + std::string getOperationName() override { + return "remotePersist"; } }; @@ -285,6 +315,7 @@ private: }; PersistOperation _persistOperation; + RemotePersistOperation _remotePersistOperation; RecoverOperation _recoverOperation; }; @@ -431,7 +462,17 @@ void VectorClockMongoD::_recoverComponent(OperationContext* opCtx, } SharedSemiFuture<void> VectorClockMongoD::persist(OperationContext* opCtx) { - return _persistOperation.performOperation(this, opCtx->getServiceContext()); + if (serverGlobalParams.clusterRole == ClusterRole::ShardServer) { + const auto replCoord = repl::ReplicationCoordinator::get(opCtx); + + if (replCoord->getMemberState().primary()) { + return _persistOperation.performOperation(this, opCtx->getServiceContext()); + } + + return _remotePersistOperation.performOperation(this, opCtx->getServiceContext()); + } + + return SharedSemiFuture<void>(); } void VectorClockMongoD::waitForInMemoryVectorClockToBePersisted(OperationContext* opCtx) { diff --git a/src/mongo/db/vector_clock_mongod_test.cpp b/src/mongo/db/vector_clock_mongod_test.cpp index 6b8a9d663f0..d59d947bd90 100644 --- a/src/mongo/db/vector_clock_mongod_test.cpp +++ b/src/mongo/db/vector_clock_mongod_test.cpp @@ -33,6 +33,7 @@ #include "mongo/db/keys_collection_manager.h" #include "mongo/db/logical_time_validator.h" #include "mongo/db/persistent_task_store.h" +#include "mongo/db/repl/replication_coordinator_mock.h" #include "mongo/db/s/sharding_mongod_test_fixture.h" #include "mongo/db/vector_clock_document_gen.h" #include "mongo/db/vector_clock_mutable.h" @@ -84,6 +85,22 @@ private: std::shared_ptr<KeysCollectionManager> _keyManager; }; +class VectorClockMongoDTestPrimary : public VectorClockMongoDTest { +protected: + void setUp() override { + VectorClockMongoDTest::setUp(); + + serverGlobalParams.clusterRole = ClusterRole::ShardServer; + + auto replCoord = repl::ReplicationCoordinator::get(operationContext()); + ASSERT_OK(replCoord->setFollowerMode(repl::MemberState::RS_PRIMARY)); + } + + void tearDown() override { + VectorClockMongoDTest::tearDown(); + } +}; + TEST_F(VectorClockMongoDTest, TickClusterTime) { auto sc = getServiceContext(); auto vc = VectorClockMutable::get(sc); @@ -281,7 +298,7 @@ TEST_F(VectorClockMongoDTest, GossipInExternal) { ASSERT_EQ(afterTime3.topologyTime().asTimestamp(), Timestamp(0, 0)); } -TEST_F(VectorClockMongoDTest, PersistVectorClockDocument) { +TEST_F(VectorClockMongoDTestPrimary, PersistVectorClockDocument) { auto sc = getServiceContext(); auto opCtx = operationContext(); @@ -306,7 +323,7 @@ TEST_F(VectorClockMongoDTest, PersistVectorClockDocument) { ASSERT_EQUALS(store.count(opCtx, VectorClock::stateQuery()), 1); } -TEST_F(VectorClockMongoDTest, RecoverVectorClockDocument) { +TEST_F(VectorClockMongoDTestPrimary, RecoverVectorClockDocument) { auto sc = getServiceContext(); auto opCtx = operationContext(); const auto configTime = LogicalTime(Timestamp(3, 3)); @@ -335,7 +352,7 @@ TEST_F(VectorClockMongoDTest, RecoverVectorClockDocument) { ASSERT_EQUALS(actualTopologyTime, topologyTime); } -TEST_F(VectorClockMongoDTest, RecoverNotExistingVectorClockDocument) { +TEST_F(VectorClockMongoDTestPrimary, RecoverNotExistingVectorClockDocument) { auto sc = getServiceContext(); auto opCtx = operationContext(); auto vc = VectorClockMutable::get(sc); @@ -364,7 +381,7 @@ TEST_F(VectorClockMongoDTest, RecoverNotExistingVectorClockDocument) { ASSERT_EQUALS(actualTopologyTime, topologyTime); } -TEST_F(VectorClockMongoDTest, SubsequentPersistRecoverVectorClockDocument) { +TEST_F(VectorClockMongoDTestPrimary, SubsequentPersistRecoverVectorClockDocument) { auto sc = getServiceContext(); auto opCtx = operationContext(); auto vc = VectorClockMutable::get(sc); diff --git a/src/mongo/db/vector_clock_persist_command.cpp b/src/mongo/db/vector_clock_persist_command.cpp new file mode 100644 index 00000000000..6635898febf --- /dev/null +++ b/src/mongo/db/vector_clock_persist_command.cpp @@ -0,0 +1,78 @@ +/** + * Copyright (C) 2020-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * <http://www.mongodb.com/licensing/server-side-public-license>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kCommand + +#include "mongo/platform/basic.h" + +#include <set> + +#include "mongo/db/commands.h" +#include "mongo/db/repl/replication_coordinator.h" +#include "mongo/db/vector_clock.h" + +namespace mongo { +namespace { + +/** + * Internal sharding command run on shard primaries to persist the vector clock state. + */ +class VectorClockPersistCommand : public BasicCommand { +public: + VectorClockPersistCommand() : BasicCommand("_vectorClockPersist") {} + + AllowedOnSecondary secondaryAllowed(ServiceContext*) const override { + return AllowedOnSecondary::kNever; + } + + virtual bool supportsWriteConcern(const BSONObj& cmd) const override { + return true; + } + + std::string help() const override { + return "Internal sharding command run on shard primaries to persist the vector clock " + "state."; + } + + bool run(OperationContext* opCtx, + const std::string& dbname_unused, + const BSONObj& cmdObj, + BSONObjBuilder& result) { + auto sc = opCtx->getServiceContext(); + auto vc = VectorClock::get(sc); + + vc->persist(opCtx).get(opCtx); + + return true; + } + +} vectorClockPersistCmd; + +} // namespace +} // namespace mongo |