summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierlauro Sciarelli <pierlauro.sciarelli@mongodb.com>2020-07-24 16:45:21 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-07-27 10:34:38 +0000
commit4dab9b9781f943fcd7e2f15e61bdbce9953d0e23 (patch)
treef75410bc446d3b9acca6de8271b6a07180ac3296
parent21a3ee6079eb3cc83a5210cf53d98840cbc83a20 (diff)
downloadmongo-4dab9b9781f943fcd7e2f15e61bdbce9953d0e23.tar.gz
SERVER-49400 Differenciate VectorClock persist behavior based on cluster role
-rw-r--r--jstests/core/views/views_all_commands.js1
-rw-r--r--jstests/replsets/db_reads_while_recovering_all_commands.js1
-rw-r--r--jstests/sharding/read_write_concern_defaults_application.js1
-rw-r--r--src/mongo/db/SConscript3
-rw-r--r--src/mongo/db/vector_clock_mongod.cpp45
-rw-r--r--src/mongo/db/vector_clock_mongod_test.cpp25
-rw-r--r--src/mongo/db/vector_clock_persist_command.cpp78
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