summaryrefslogtreecommitdiff
path: root/src/mongo/idl
diff options
context:
space:
mode:
authorLucas de Castro Borges <lucas@gnuabordo.com.br>2025-02-14 14:26:38 -0300
committerLucas de Castro Borges <lucas@gnuabordo.com.br>2025-02-14 14:26:38 -0300
commit294bc6ecabf14c09c9bc8644704921dcf97cb44e (patch)
tree279b1e0bab53901a1647ac63c1c724f0f789a663 /src/mongo/idl
parent70be7c27a251621187a1de533462ae2bb1e3bd39 (diff)
parent1e917fd798aa25b7066d4b414b51184f13d5a092 (diff)
Update upstream source from tag 'upstream/6.0.10'debian/6.0.10-1
Update to upstream version '6.0.10' with Debian dir 2d176fa254eee97b139f712fec5709641335a8c3
Diffstat (limited to 'src/mongo/idl')
-rw-r--r--src/mongo/idl/SConscript20
-rw-r--r--src/mongo/idl/cluster_parameter_synchronization_helpers.cpp147
-rw-r--r--src/mongo/idl/cluster_parameter_synchronization_helpers.h105
-rw-r--r--src/mongo/idl/cluster_server_parameter_initializer.cpp95
-rw-r--r--src/mongo/idl/cluster_server_parameter_initializer.h46
-rw-r--r--src/mongo/idl/cluster_server_parameter_initializer_test.cpp3
-rw-r--r--src/mongo/idl/cluster_server_parameter_op_observer.cpp63
-rw-r--r--src/mongo/idl/cluster_server_parameter_op_observer.h19
-rw-r--r--src/mongo/idl/cluster_server_parameter_op_observer_test.cpp173
9 files changed, 390 insertions, 281 deletions
diff --git a/src/mongo/idl/SConscript b/src/mongo/idl/SConscript
index 2fcbf03c37a..a95eb570aa5 100644
--- a/src/mongo/idl/SConscript
+++ b/src/mongo/idl/SConscript
@@ -74,7 +74,23 @@ env.Library(
LIBDEPS_PRIVATE=[
'$BUILD_DIR/mongo/db/dbdirectclient',
'$BUILD_DIR/mongo/db/repl/replica_set_aware_service',
- ]
+ 'cluster_parameter_synchronization_helpers',
+ ],
+)
+
+env.Library(
+ target='cluster_parameter_synchronization_helpers',
+ source=[
+ 'cluster_parameter_synchronization_helpers.cpp',
+ ],
+ LIBDEPS=[
+ '$BUILD_DIR/mongo/base',
+ ],
+ LIBDEPS_PRIVATE=[
+ '$BUILD_DIR/mongo/db/audit',
+ '$BUILD_DIR/mongo/db/db_raii',
+ '$BUILD_DIR/mongo/db/logical_time',
+ ],
)
env.Library(
@@ -88,6 +104,7 @@ env.Library(
LIBDEPS_PRIVATE=[
'$BUILD_DIR/mongo/db/dbdirectclient',
'$BUILD_DIR/mongo/db/op_observer',
+ 'cluster_parameter_synchronization_helpers',
'cluster_server_parameter_initializer',
],
)
@@ -136,6 +153,7 @@ env.CppUnitTest(
'$BUILD_DIR/mongo/db/repl/storage_interface_impl',
'$BUILD_DIR/mongo/db/service_context_d_test_fixture',
'$BUILD_DIR/mongo/util/signal_handlers',
+ 'cluster_parameter_synchronization_helpers',
'cluster_server_parameter_initializer',
'cluster_server_parameter_test_parameter',
],
diff --git a/src/mongo/idl/cluster_parameter_synchronization_helpers.cpp b/src/mongo/idl/cluster_parameter_synchronization_helpers.cpp
new file mode 100644
index 00000000000..1566c42fa8e
--- /dev/null
+++ b/src/mongo/idl/cluster_parameter_synchronization_helpers.cpp
@@ -0,0 +1,147 @@
+/**
+ * Copyright (C) 2023-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::kControl
+
+#include "mongo/idl/cluster_parameter_synchronization_helpers.h"
+
+#include "mongo/base/string_data.h"
+#include "mongo/db/audit.h"
+#include "mongo/db/catalog_raii.h"
+#include "mongo/db/multitenancy_gen.h"
+#include "mongo/logv2/log.h"
+
+namespace mongo::cluster_parameters {
+
+constexpr auto kIdField = "_id"_sd;
+constexpr auto kCPTField = "clusterParameterTime"_sd;
+constexpr auto kOplog = "oplog"_sd;
+
+void updateParameter(BSONObj doc, StringData mode) {
+ auto nameElem = doc[kIdField];
+ if (nameElem.type() != String) {
+ LOGV2_DEBUG(6226301,
+ 1,
+ "Update with invalid cluster server parameter name",
+ "mode"_attr = mode,
+ "_id"_attr = nameElem);
+ return;
+ }
+
+ auto name = nameElem.valueStringData();
+ auto* sp = ServerParameterSet::getClusterParameterSet()->getIfExists(name);
+ if (!sp) {
+ LOGV2_DEBUG(6226300,
+ 3,
+ "Update to unknown cluster server parameter",
+ "mode"_attr = mode,
+ "name"_attr = name);
+ return;
+ }
+
+ auto cptElem = doc[kCPTField];
+ if ((cptElem.type() != mongo::Date) && (cptElem.type() != bsonTimestamp)) {
+ LOGV2_DEBUG(6226302,
+ 1,
+ "Update to cluster server parameter has invalid clusterParameterTime",
+ "mode"_attr = mode,
+ "name"_attr = name,
+ "clusterParameterTime"_attr = cptElem);
+ return;
+ }
+
+ uassertStatusOK(sp->set(doc));
+}
+
+void clearParameter(ServerParameter* sp) {
+ if (sp->getClusterParameterTime() == LogicalTime::kUninitialized) {
+ // Nothing to clear.
+ return;
+ }
+
+ uassertStatusOK(sp->reset());
+}
+
+void clearParameter(StringData id) {
+ auto* sp = ServerParameterSet::getClusterParameterSet()->getIfExists(id);
+ if (!sp) {
+ LOGV2_DEBUG(6226303,
+ 5,
+ "oplog event deletion of unknown cluster server parameter",
+ "name"_attr = id);
+ return;
+ }
+
+ clearParameter(sp);
+}
+
+void clearAllParameters() {
+ const auto& params = ServerParameterSet::getClusterParameterSet()->getMap();
+ for (const auto& it : params) {
+ clearParameter(it.second);
+ }
+}
+
+void initializeAllParametersFromDisk(OperationContext* opCtx) {
+ doLoadAllParametersFromDisk(
+ opCtx, "initializing"_sd, [](OperationContext* opCtx, BSONObj doc, StringData mode) {
+ updateParameter(doc, mode);
+ });
+}
+
+void resynchronizeAllParametersFromDisk(OperationContext* opCtx) {
+ const auto& allParams = ServerParameterSet::getClusterParameterSet()->getMap();
+ std::set<std::string> unsetSettings;
+ for (const auto& it : allParams) {
+ unsetSettings.insert(it.second->name());
+ }
+
+ doLoadAllParametersFromDisk(
+ opCtx,
+ "resynchronizing"_sd,
+ [&unsetSettings](OperationContext* opCtx, BSONObj doc, StringData mode) {
+ unsetSettings.erase(doc[kIdField].str());
+ updateParameter(doc, mode);
+ });
+
+ // For all known settings which were not present in this resync,
+ // explicitly clear any value which may be present in-memory.
+ for (const auto& setting : unsetSettings) {
+ clearParameter(setting);
+ }
+}
+
+void maybeUpdateClusterParametersPostImportCollectionCommit(OperationContext* opCtx,
+ const NamespaceString& nss) {
+ if (nss == NamespaceString::kClusterParametersNamespace) {
+ // Something was imported, do a full collection scan to sync up.
+ cluster_parameters::initializeAllParametersFromDisk(opCtx);
+ }
+}
+
+} // namespace mongo::cluster_parameters
diff --git a/src/mongo/idl/cluster_parameter_synchronization_helpers.h b/src/mongo/idl/cluster_parameter_synchronization_helpers.h
new file mode 100644
index 00000000000..d69271a7c03
--- /dev/null
+++ b/src/mongo/idl/cluster_parameter_synchronization_helpers.h
@@ -0,0 +1,105 @@
+/**
+ * Copyright (C) 2023-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.
+ */
+
+#pragma once
+
+#include "mongo/db/db_raii.h"
+
+namespace mongo {
+
+namespace cluster_parameters {
+
+void updateParameter(BSONObj doc, StringData mode);
+
+void clearParameter(ServerParameter* sp);
+
+void clearParameter(StringData id);
+
+void clearAllParameters();
+
+/**
+ * Used to initialize in-memory cluster parameter state based on the on-disk contents after startup
+ * recovery or initial sync is complete.
+ */
+void initializeAllParametersFromDisk(OperationContext* opCtx);
+
+/**
+ * Used on rollback. Updates settings which are present and clears settings which are not.
+ */
+void resynchronizeAllParametersFromDisk(OperationContext* opCtx);
+
+template <typename OnEntry>
+void doLoadAllParametersFromDisk(OperationContext* opCtx, StringData mode, OnEntry onEntry) try {
+
+ // If the RecoveryUnit already had an open snapshot, keep the snapshot open. Otherwise
+ // abandon the snapshot when exiting the function.
+ ScopeGuard scopeGuard([&] { opCtx->recoveryUnit()->abandonSnapshot(); });
+ if (opCtx->recoveryUnit()->isActive()) {
+ scopeGuard.dismiss();
+ }
+
+ AutoGetCollectionForRead coll(opCtx, NamespaceString::kClusterParametersNamespace);
+ if (!coll) {
+ return;
+ }
+
+ std::vector<Status> failures;
+
+ auto cursor = coll->getCursor(opCtx);
+ for (auto doc = cursor->next(); doc; doc = cursor->next()) {
+ try {
+ onEntry(opCtx, doc.get().data.toBson(), mode);
+ } catch (const DBException& ex) {
+ failures.push_back(ex.toStatus());
+ }
+ }
+
+ if (!failures.empty()) {
+ StringBuilder msg;
+ for (const auto& failure : failures) {
+ msg << failure.toString() << ", ";
+ }
+ msg.reset(msg.len() - 2);
+ uasserted(ErrorCodes::OperationFailed, msg.str());
+ }
+} catch (const DBException& ex) {
+ uassertStatusOK(ex.toStatus().withContext(
+ str::stream() << "Failed " << mode << " cluster server parameters from disk"));
+}
+
+/**
+ * Used after an importCollection commits. Will update the in-memory cluster parameter state if the
+ * given namespace is a cluster parameters namespace.
+ */
+void maybeUpdateClusterParametersPostImportCollectionCommit(OperationContext* opCtx,
+ const NamespaceString& nss);
+
+} // namespace cluster_parameters
+
+} // namespace mongo
diff --git a/src/mongo/idl/cluster_server_parameter_initializer.cpp b/src/mongo/idl/cluster_server_parameter_initializer.cpp
index 3205f7a4fa7..e28e0542ecb 100644
--- a/src/mongo/idl/cluster_server_parameter_initializer.cpp
+++ b/src/mongo/idl/cluster_server_parameter_initializer.cpp
@@ -34,6 +34,7 @@
#include "mongo/base/string_data.h"
#include "mongo/db/repl/replica_set_aware_service.h"
#include "mongo/db/service_context.h"
+#include "mongo/idl/cluster_parameter_synchronization_helpers.h"
#include "mongo/logv2/log.h"
namespace mongo {
@@ -58,102 +59,10 @@ ClusterServerParameterInitializer* ClusterServerParameterInitializer::get(
return &getInstance(serviceContext);
}
-void ClusterServerParameterInitializer::updateParameter(BSONObj doc, StringData mode) {
- auto nameElem = doc[kIdField];
- if (nameElem.type() != String) {
- LOGV2_DEBUG(6226301,
- 1,
- "Update with invalid cluster server parameter name",
- "mode"_attr = mode,
- "_id"_attr = nameElem);
- return;
- }
-
- auto name = nameElem.valueStringData();
- auto* sp = ServerParameterSet::getClusterParameterSet()->getIfExists(name);
- if (!sp) {
- LOGV2_DEBUG(6226300,
- 3,
- "Update to unknown cluster server parameter",
- "mode"_attr = mode,
- "name"_attr = name);
- return;
- }
-
- auto cptElem = doc[kCPTField];
- if ((cptElem.type() != mongo::Date) && (cptElem.type() != bsonTimestamp)) {
- LOGV2_DEBUG(6226302,
- 1,
- "Update to cluster server parameter has invalid clusterParameterTime",
- "mode"_attr = mode,
- "name"_attr = name,
- "clusterParameterTime"_attr = cptElem);
- return;
- }
-
- uassertStatusOK(sp->set(doc));
-}
-
-void ClusterServerParameterInitializer::clearParameter(ServerParameter* sp) {
- if (sp->getClusterParameterTime() == LogicalTime::kUninitialized) {
- // Nothing to clear.
- return;
- }
-
- uassertStatusOK(sp->reset());
-}
-
-void ClusterServerParameterInitializer::clearParameter(StringData id) {
- auto* sp = ServerParameterSet::getClusterParameterSet()->getIfExists(id);
- if (!sp) {
- LOGV2_DEBUG(6226303,
- 5,
- "oplog event deletion of unknown cluster server parameter",
- "name"_attr = id);
- return;
- }
-
- clearParameter(sp);
-}
-
-void ClusterServerParameterInitializer::clearAllParameters() {
- const auto& params = ServerParameterSet::getClusterParameterSet()->getMap();
- for (const auto& it : params) {
- clearParameter(it.second);
- }
-}
-
-void ClusterServerParameterInitializer::initializeAllParametersFromDisk(OperationContext* opCtx) {
- doLoadAllParametersFromDisk(opCtx, "initializing"_sd, [this](BSONObj doc, StringData mode) {
- updateParameter(doc, mode);
- });
-}
-
-void ClusterServerParameterInitializer::resynchronizeAllParametersFromDisk(
- OperationContext* opCtx) {
- const auto& allParams = ServerParameterSet::getClusterParameterSet()->getMap();
- std::set<std::string> unsetSettings;
- for (const auto& it : allParams) {
- unsetSettings.insert(it.second->name());
- }
-
- doLoadAllParametersFromDisk(
- opCtx, "resynchronizing"_sd, [this, &unsetSettings](BSONObj doc, StringData mode) {
- unsetSettings.erase(doc[kIdField].str());
- updateParameter(doc, mode);
- });
-
- // For all known settings which were not present in this resync,
- // explicitly clear any value which may be present in-memory.
- for (const auto& setting : unsetSettings) {
- clearParameter(setting);
- }
-}
-
void ClusterServerParameterInitializer::onInitialDataAvailable(OperationContext* opCtx,
bool isMajorityDataAvailable) {
LOGV2_INFO(6608200, "Initializing cluster server parameters from disk");
- initializeAllParametersFromDisk(opCtx);
+ cluster_parameters::initializeAllParametersFromDisk(opCtx);
}
} // namespace mongo
diff --git a/src/mongo/idl/cluster_server_parameter_initializer.h b/src/mongo/idl/cluster_server_parameter_initializer.h
index 0eb02bb058c..49d501a7e6d 100644
--- a/src/mongo/idl/cluster_server_parameter_initializer.h
+++ b/src/mongo/idl/cluster_server_parameter_initializer.h
@@ -52,23 +52,6 @@ public:
static ClusterServerParameterInitializer* get(OperationContext* opCtx);
static ClusterServerParameterInitializer* get(ServiceContext* serviceContext);
- void updateParameter(BSONObj doc, StringData mode);
- void clearParameter(ServerParameter* sp);
- void clearParameter(StringData id);
- void clearAllParameters();
-
- /**
- * Used to initialize in-memory cluster parameter state based on the on-disk contents after
- * startup recovery or initial sync is complete.
- */
- void initializeAllParametersFromDisk(OperationContext* opCtx);
-
- /**
- * Used on rollback and rename with drop.
- * Updates settings which are present and clears settings which are not.
- */
- void resynchronizeAllParametersFromDisk(OperationContext* opCtx);
-
// Virtual methods coming from the ReplicaSetAwareService
void onStartup(OperationContext* opCtx) override final {}
@@ -82,35 +65,6 @@ public:
void onStepUpComplete(OperationContext* opCtx, long long term) override final {}
void onStepDown() override final {}
void onBecomeArbiter() override final {}
-
-private:
- template <typename OnEntry>
- void doLoadAllParametersFromDisk(OperationContext* opCtx,
- StringData mode,
- OnEntry onEntry) try {
- std::vector<Status> failures;
-
- DBDirectClient client(opCtx);
- FindCommandRequest findRequest{NamespaceString::kClusterParametersNamespace};
- client.find(std::move(findRequest), ReadPreferenceSetting{}, [&](BSONObj doc) {
- try {
- onEntry(doc, mode);
- } catch (const DBException& ex) {
- failures.push_back(ex.toStatus());
- }
- });
- if (!failures.empty()) {
- StringBuilder msg;
- for (const auto& failure : failures) {
- msg << failure.toString() << ", ";
- }
- msg.reset(msg.len() - 2);
- uasserted(ErrorCodes::OperationFailed, msg.str());
- }
- } catch (const DBException& ex) {
- uassertStatusOK(ex.toStatus().withContext(
- str::stream() << "Failed " << mode << " cluster server parameters from disk"));
- }
};
} // namespace mongo
diff --git a/src/mongo/idl/cluster_server_parameter_initializer_test.cpp b/src/mongo/idl/cluster_server_parameter_initializer_test.cpp
index e8a62b6a1c1..a2211ed0295 100644
--- a/src/mongo/idl/cluster_server_parameter_initializer_test.cpp
+++ b/src/mongo/idl/cluster_server_parameter_initializer_test.cpp
@@ -38,6 +38,7 @@
#include "mongo/db/repl/replication_coordinator_mock.h"
#include "mongo/db/repl/storage_interface_mock.h"
#include "mongo/db/service_context_d_test_fixture.h"
+#include "mongo/idl/cluster_parameter_synchronization_helpers.h"
#include "mongo/idl/cluster_server_parameter_gen.h"
#include "mongo/idl/cluster_server_parameter_initializer.h"
#include "mongo/idl/cluster_server_parameter_test_gen.h"
@@ -68,7 +69,7 @@ public:
// Delete all cluster server parameter documents written and refresh in-memory state.
remove();
auto opCtx = cc().makeOperationContext();
- _initializer.resynchronizeAllParametersFromDisk(opCtx.get());
+ cluster_parameters::resynchronizeAllParametersFromDisk(opCtx.get());
}
/**
* Simulates the call to the ClusterServerParameterInitializer at the end of initial sync, when
diff --git a/src/mongo/idl/cluster_server_parameter_op_observer.cpp b/src/mongo/idl/cluster_server_parameter_op_observer.cpp
index b8787dcfa12..ea9553d46fb 100644
--- a/src/mongo/idl/cluster_server_parameter_op_observer.cpp
+++ b/src/mongo/idl/cluster_server_parameter_op_observer.cpp
@@ -34,7 +34,7 @@
#include <memory>
#include "mongo/db/dbdirectclient.h"
-#include "mongo/idl/cluster_server_parameter_initializer.h"
+#include "mongo/idl/cluster_parameter_synchronization_helpers.h"
#include "mongo/logv2/log.h"
namespace mongo {
@@ -67,7 +67,9 @@ void ClusterServerParameterOpObserver::onInserts(OperationContext* opCtx,
}
for (auto it = first; it != last; ++it) {
- ClusterServerParameterInitializer::get(opCtx)->updateParameter(it->doc, kOplog);
+ opCtx->recoveryUnit()->onCommit([doc = it->doc](boost::optional<Timestamp>) {
+ cluster_parameters::updateParameter(doc, kOplog);
+ });
}
}
@@ -78,7 +80,9 @@ void ClusterServerParameterOpObserver::onUpdate(OperationContext* opCtx,
return;
}
- ClusterServerParameterInitializer::get(opCtx)->updateParameter(updatedDoc, kOplog);
+ opCtx->recoveryUnit()->onCommit([updatedDoc](boost::optional<Timestamp>) {
+ cluster_parameters::updateParameter(updatedDoc, kOplog);
+ });
}
void ClusterServerParameterOpObserver::aboutToDelete(OperationContext* opCtx,
@@ -115,7 +119,8 @@ void ClusterServerParameterOpObserver::onDelete(OperationContext* opCtx,
const OplogDeleteEntryArgs& args) {
const auto& docName = aboutToDeleteDoc(opCtx);
if (!docName.empty()) {
- ClusterServerParameterInitializer::get(opCtx)->clearParameter(docName);
+ opCtx->recoveryUnit()->onCommit(
+ [docName](boost::optional<Timestamp>) { cluster_parameters::clearParameter(docName); });
}
}
@@ -123,7 +128,8 @@ void ClusterServerParameterOpObserver::onDropDatabase(OperationContext* opCtx,
const std::string& dbName) {
if (dbName == NamespaceString::kConfigDb) {
// Entire config DB deleted, reset to default state.
- ClusterServerParameterInitializer::get(opCtx)->clearAllParameters();
+ opCtx->recoveryUnit()->onCommit(
+ [](boost::optional<Timestamp>) { cluster_parameters::clearAllParameters(); });
}
}
@@ -135,58 +141,21 @@ repl::OpTime ClusterServerParameterOpObserver::onDropCollection(
CollectionDropType dropType) {
if (isConfigNamespace(collectionName)) {
// Entire collection deleted, reset to default state.
- ClusterServerParameterInitializer::get(opCtx)->clearAllParameters();
+ opCtx->recoveryUnit()->onCommit(
+ [](boost::optional<Timestamp>) { cluster_parameters::clearAllParameters(); });
}
return {};
}
-void ClusterServerParameterOpObserver::postRenameCollection(
- OperationContext* opCtx,
- const NamespaceString& fromCollection,
- const NamespaceString& toCollection,
- const UUID& uuid,
- const boost::optional<UUID>& dropTargetUUID,
- bool stayTemp) {
- if (isConfigNamespace(fromCollection)) {
- // Same as collection dropped from a config point of view.
- ClusterServerParameterInitializer::get(opCtx)->clearAllParameters();
- }
-
- if (isConfigNamespace(toCollection)) {
- // Potentially many documents now set, perform full scan.
- if (dropTargetUUID) {
- // Possibly lost configurations in overwrite.
- ClusterServerParameterInitializer::get(opCtx)->resynchronizeAllParametersFromDisk(
- opCtx);
- } else {
- // Collection did not exist prior to rename.
- ClusterServerParameterInitializer::get(opCtx)->initializeAllParametersFromDisk(opCtx);
- }
- }
-}
-
-void ClusterServerParameterOpObserver::onImportCollection(OperationContext* opCtx,
- const UUID& importUUID,
- const NamespaceString& nss,
- long long numRecords,
- long long dataSize,
- const BSONObj& catalogEntry,
- const BSONObj& storageMetadata,
- bool isDryRun) {
- if (!isDryRun && (numRecords > 0) && isConfigNamespace(nss)) {
- // Something was imported, do a full collection scan to sync up.
- // No need to apply rollback rules since nothing will have been deleted.
- ClusterServerParameterInitializer::get(opCtx)->initializeAllParametersFromDisk(opCtx);
- }
-}
-
void ClusterServerParameterOpObserver::_onReplicationRollback(OperationContext* opCtx,
const RollbackObserverInfo& rbInfo) {
if (rbInfo.rollbackNamespaces.count(NamespaceString::kClusterParametersNamespace)) {
// Some kind of rollback happend in the settings collection.
// Just reload from disk to be safe.
- ClusterServerParameterInitializer::get(opCtx)->resynchronizeAllParametersFromDisk(opCtx);
+ // We can call resynchronize directly because onReplicationRollback is guaranteed to be
+ // called from a state with no active WUOW and no database locks.
+ cluster_parameters::resynchronizeAllParametersFromDisk(opCtx);
}
}
diff --git a/src/mongo/idl/cluster_server_parameter_op_observer.h b/src/mongo/idl/cluster_server_parameter_op_observer.h
index 2ef05729e39..86bec6b61da 100644
--- a/src/mongo/idl/cluster_server_parameter_op_observer.h
+++ b/src/mongo/idl/cluster_server_parameter_op_observer.h
@@ -72,12 +72,18 @@ public:
const UUID& uuid,
std::uint64_t numRecords,
CollectionDropType dropType) final;
+
+private:
+ void _onReplicationRollback(OperationContext* opCtx, const RollbackObserverInfo& rbInfo) final;
+
+public:
+ // Remainder of operations are ignorable.
void postRenameCollection(OperationContext* opCtx,
const NamespaceString& fromCollection,
const NamespaceString& toCollection,
const UUID& uuid,
const boost::optional<UUID>& dropTargetUUID,
- bool stayTemp) final;
+ bool stayTemp) final {}
void onImportCollection(OperationContext* opCtx,
const UUID& importUUID,
const NamespaceString& nss,
@@ -85,12 +91,7 @@ public:
long long dataSize,
const BSONObj& catalogEntry,
const BSONObj& storageMetadata,
- bool isDryRun) final;
-
- void _onReplicationRollback(OperationContext* opCtx, const RollbackObserverInfo& rbInfo) final;
-
-public:
- // Remainder of operations are ignorable.
+ bool isDryRun) final {}
void onCreateIndex(OperationContext* opCtx,
const NamespaceString& nss,
@@ -212,6 +213,10 @@ public:
size_t numberOfPrePostImagesToWrite,
Date_t wallClockTime) final {}
+ void onTransactionPrepareNonPrimary(OperationContext* opCtx,
+ const std::vector<repl::OplogEntry>& statements,
+ const repl::OpTime& prepareOpTime) final {}
+
void onTransactionAbort(OperationContext* opCtx,
boost::optional<OplogSlot> abortOplogEntryOpTime) final {}
diff --git a/src/mongo/idl/cluster_server_parameter_op_observer_test.cpp b/src/mongo/idl/cluster_server_parameter_op_observer_test.cpp
index 2ba82076bf2..7553bfc191a 100644
--- a/src/mongo/idl/cluster_server_parameter_op_observer_test.cpp
+++ b/src/mongo/idl/cluster_server_parameter_op_observer_test.cpp
@@ -31,9 +31,9 @@
#include "mongo/platform/basic.h"
-#include "mongo/idl/cluster_server_parameter_test_util.h"
-
+#include "mongo/db/catalog_raii.h"
#include "mongo/idl/cluster_server_parameter_op_observer.h"
+#include "mongo/idl/cluster_server_parameter_test_util.h"
#include "mongo/logv2/log.h"
namespace mongo {
@@ -47,60 +47,58 @@ const std::vector<NamespaceString> kIgnoredNamespaces = {
class ClusterServerParameterOpObserverTest : public ClusterServerParameterTestBase {
public:
- void doInserts(const NamespaceString& nss, std::initializer_list<BSONObj> docs) {
+ void doInserts(const NamespaceString& nss,
+ std::initializer_list<BSONObj> docs,
+ bool commit = true) {
std::vector<InsertStatement> stmts;
std::transform(docs.begin(), docs.end(), std::back_inserter(stmts), [](auto doc) {
return InsertStatement(doc);
});
auto opCtx = cc().makeOperationContext();
+ WriteUnitOfWork wuow(opCtx.get());
+
+ AutoGetCollection autoColl(opCtx.get(), nss, MODE_IX);
observer.onInserts(
opCtx.get(), nss, UUID::gen(), stmts.cbegin(), stmts.cend(), false /* fromMigrate */);
+ if (commit)
+ wuow.commit();
}
- void doUpdate(const NamespaceString& nss, BSONObj updatedDoc) {
+ void doUpdate(const NamespaceString& nss, BSONObj updatedDoc, bool commit = true) {
// Actual UUID doesn't matter, just use any...
CollectionUpdateArgs updateArgs;
updateArgs.update = BSON("$set" << updatedDoc);
updateArgs.updatedDoc = updatedDoc;
OplogUpdateEntryArgs entryArgs(&updateArgs, nss, UUID::gen());
auto opCtx = cc().makeOperationContext();
+ WriteUnitOfWork wuow(opCtx.get());
+ AutoGetCollection autoColl(opCtx.get(), nss, MODE_IX);
observer.onUpdate(opCtx.get(), entryArgs);
+ if (commit)
+ wuow.commit();
}
- void doDelete(const NamespaceString& nss, BSONObj deletedDoc, bool includeDeletedDoc = true) {
+ void doDelete(const NamespaceString& nss,
+ BSONObj deletedDoc,
+ bool includeDeletedDoc = true,
+ bool commit = true) {
auto opCtx = cc().makeOperationContext();
- auto uuid = UUID::gen();
- observer.aboutToDelete(opCtx.get(), nss, uuid, deletedDoc);
+ WriteUnitOfWork wuow(opCtx.get());
+ AutoGetCollection autoColl(opCtx.get(), nss, MODE_IX);
+ observer.aboutToDelete(opCtx.get(), nss, UUID::gen(), deletedDoc);
OplogDeleteEntryArgs args;
args.deletedDoc = includeDeletedDoc ? &deletedDoc : nullptr;
- observer.onDelete(opCtx.get(), nss, uuid, 1 /* StmtId */, args);
+ observer.onDelete(opCtx.get(), nss, UUID::gen(), 1 /* StmtId */, args);
+ if (commit)
+ wuow.commit();
}
- void doDropDatabase(StringData dbname) {
+ void doDropDatabase(const std::string& dbname, bool commit = true) {
auto opCtx = cc().makeOperationContext();
- observer.onDropDatabase(opCtx.get(), dbname.toString());
- }
-
- void doRenameCollection(const NamespaceString& fromColl, const NamespaceString& toColl) {
- auto opCtx = cc().makeOperationContext();
- observer.postRenameCollection(opCtx.get(),
- fromColl,
- toColl,
- UUID::gen(),
- boost::none /* targetUUID */,
- false /* stayTemp */);
- }
-
- void doImportCollection(const NamespaceString& nss) {
- auto opCtx = cc().makeOperationContext();
- observer.onImportCollection(opCtx.get(),
- UUID::gen(),
- nss,
- 10 /* num records */,
- 1 << 20 /* data size */,
- BSONObj() /* catalogEntry */,
- BSONObj() /* storageMetadata */,
- false /* isDryRun */);
+ WriteUnitOfWork wuow(opCtx.get());
+ observer.onDropDatabase(opCtx.get(), dbname);
+ if (commit)
+ wuow.commit();
}
void doReplicationRollback(const std::vector<NamespaceString>& namespaces) {
@@ -165,6 +163,28 @@ public:
assertIgnored(NamespaceString::kClusterParametersNamespace, fn);
}
+ void assertParameterState(int line,
+ int intVal,
+ StringData strVal,
+ boost::optional<LogicalTime> cpt = boost::none) {
+ auto* sp = ServerParameterSet::getClusterParameterSet()
+ ->get<IDLServerParameterWithStorage<ServerParameterType::kClusterWide,
+ ClusterServerParameterTest>>(kCSPTest);
+ ;
+ try {
+ if (cpt) {
+ ASSERT_EQ(sp->getClusterParameterTime(), *cpt);
+ }
+
+ ClusterServerParameterTest cspTest = sp->getValue();
+ ASSERT_EQ(cspTest.getIntValue(), intVal);
+ ASSERT_EQ(cspTest.getStrValue(), strVal);
+ } catch (...) {
+ LOGV2_ERROR(6887700, "ASSERT_PARAMETER_STATE failed", "line"_attr = line);
+ throw;
+ }
+ }
+
protected:
ClusterServerParameterOpObserver observer;
};
@@ -308,12 +328,12 @@ TEST_F(ClusterServerParameterOpObserverTest, onDropDatabase) {
assertIgnoredOtherNamespaces([this](const auto& nss) {
const auto dbname = nss.db();
if (dbname != kConfigDB) {
- doDropDatabase(dbname);
+ doDropDatabase(dbname.toString());
}
});
// Actually drop the config DB.
- doDropDatabase(kConfigDB);
+ doDropDatabase(kConfigDB.toString());
auto* sp = ServerParameterSet::getClusterParameterSet()
->get<IDLServerParameterWithStorage<ServerParameterType::kClusterWide,
@@ -325,63 +345,12 @@ TEST_F(ClusterServerParameterOpObserverTest, onDropDatabase) {
ASSERT_EQ(cspTest.getStrValue(), kDefaultStrValue);
}
-TEST_F(ClusterServerParameterOpObserverTest, onRenameCollection) {
- initializeState();
-
- const NamespaceString kTestFoo("test", "foo");
- // Rename ignorable collections.
- assertIgnoredOtherNamespaces([&](const auto& nss) { doRenameCollection(nss, kTestFoo); });
- assertIgnoredOtherNamespaces([&](const auto& nss) { doRenameCollection(kTestFoo, nss); });
-
- auto* sp = ServerParameterSet::getClusterParameterSet()
- ->get<IDLServerParameterWithStorage<ServerParameterType::kClusterWide,
- ClusterServerParameterTest>>(kCSPTest);
- ASSERT(sp != nullptr);
-
- // These renames "work" despite not mutating durable state
- // since the rename away doesn't require a rescan.
-
- // Rename away (and reset to default)
- doRenameCollection(NamespaceString::kClusterParametersNamespace, kTestFoo);
- ClusterServerParameterTest cspTest = sp->getValue();
- ASSERT_EQ(cspTest.getIntValue(), kDefaultIntValue);
- ASSERT_EQ(cspTest.getStrValue(), kDefaultStrValue);
-
- // Rename in (and restore to initialized state)
- doRenameCollection(kTestFoo, NamespaceString::kClusterParametersNamespace);
- cspTest = sp->getValue();
- ASSERT_EQ(cspTest.getIntValue(), kInitialIntValue);
- ASSERT_EQ(cspTest.getStrValue(), kInitialStrValue);
-}
-
-TEST_F(ClusterServerParameterOpObserverTest, onImportCollection) {
- initializeState();
-
- const NamespaceString kTestFoo("test", "foo");
- // Import ignorable collections.
- assertIgnoredOtherNamespaces([&](const auto& nss) { doImportCollection(nss); });
-
- auto* sp = ServerParameterSet::getClusterParameterSet()
- ->get<IDLServerParameterWithStorage<ServerParameterType::kClusterWide,
- ClusterServerParameterTest>>(kCSPTest);
- ASSERT(sp != nullptr);
-
- // Import the collection (rescan).
- auto doc =
- makeClusterParametersDoc(LogicalTime(Timestamp(time(nullptr))), 333, "onImportCollection");
- upsert(doc);
- doImportCollection(NamespaceString::kClusterParametersNamespace);
- ClusterServerParameterTest cspTest = sp->getValue();
- ASSERT_EQ(cspTest.getIntValue(), 333);
- ASSERT_EQ(cspTest.getStrValue(), "onImportCollection");
-}
-
TEST_F(ClusterServerParameterOpObserverTest, onReplicationRollback) {
initializeState();
const NamespaceString kTestFoo("test", "foo");
// Import ignorable collections.
- assertIgnoredOtherNamespaces([&](const auto& nss) { doImportCollection(nss); });
+ assertIgnoredOtherNamespaces([&](const auto& nss) { doReplicationRollback({nss}); });
auto* sp = ServerParameterSet::getClusterParameterSet()
->get<IDLServerParameterWithStorage<ServerParameterType::kClusterWide,
@@ -412,5 +381,37 @@ TEST_F(ClusterServerParameterOpObserverTest, onReplicationRollback) {
ASSERT_EQ(cspTest.getStrValue(), kDefaultStrValue);
}
+#define ASSERT_PARAMETER_STATE(...) assertParameterState(__LINE__, __VA_ARGS__)
+
+TEST_F(ClusterServerParameterOpObserverTest, abortsAfterObservation) {
+
+ const auto initialDoc = initializeState();
+
+ doInserts(NamespaceString::kClusterParametersNamespace,
+ {makeClusterParametersDoc(LogicalTime(Timestamp(12345678)), 123, "abc")},
+ false /* commit */);
+
+ ASSERT_PARAMETER_STATE(kInitialIntValue, kInitialStrValue);
+
+ doUpdate(NamespaceString::kClusterParametersNamespace,
+ {makeClusterParametersDoc(LogicalTime(Timestamp(87654321)), 321, "cba")},
+ false /* commit */);
+
+ ASSERT_PARAMETER_STATE(kInitialIntValue, kInitialStrValue);
+
+ doDelete(NamespaceString::kClusterParametersNamespace,
+ initialDoc,
+ true /* includeDeletedDoc */,
+ false /* commit */);
+
+ ASSERT_PARAMETER_STATE(kInitialIntValue, kInitialStrValue);
+
+ doDropDatabase(kConfigDB.toString(), false /* commit */);
+
+ ASSERT_PARAMETER_STATE(kInitialIntValue, kInitialStrValue);
+}
+
+#undef ASSERT_PARAMETER_STATE
+
} // namespace
} // namespace mongo