diff options
author | Sara Golemon <sara.golemon@mongodb.com> | 2021-12-30 03:26:41 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-01-10 23:14:43 +0000 |
commit | 255959a734f98dc700afb43b05e0e9590bc7aa91 (patch) | |
tree | 17471d9b5fec1ab1346c71a0ffa1acb07b97cb8a | |
parent | 0791c57fb7a3e86be3880aa926dfb9bb54f76802 (diff) | |
download | mongo-255959a734f98dc700afb43b05e0e9590bc7aa91.tar.gz |
SERVER-62251 Add ServerParameterType::kClusterWide
23 files changed, 249 insertions, 159 deletions
diff --git a/src/mongo/client/replica_set_monitor_protocol_test_util.cpp b/src/mongo/client/replica_set_monitor_protocol_test_util.cpp index 8009462ea75..9456e4a8ba9 100644 --- a/src/mongo/client/replica_set_monitor_protocol_test_util.cpp +++ b/src/mongo/client/replica_set_monitor_protocol_test_util.cpp @@ -50,7 +50,7 @@ void ReplicaSetMonitorProtocolTestUtil::resetRSMProtocol() { ServerParameter::Map::const_iterator ReplicaSetMonitorProtocolTestUtil::findRSMProtocolServerParameter() { - const ServerParameter::Map& parameterMap = ServerParameterSet::getGlobal()->getMap(); + const auto& parameterMap = ServerParameterSet::getNodeParameterSet()->getMap(); invariant(parameterMap.size()); return parameterMap.find(kRSMProtocolFieldName); } diff --git a/src/mongo/db/commands/parameters.cpp b/src/mongo/db/commands/parameters.cpp index 430641fabe6..ce7d69ea7b2 100644 --- a/src/mongo/db/commands/parameters.cpp +++ b/src/mongo/db/commands/parameters.cpp @@ -57,7 +57,7 @@ using logv2::LogSeverity; void appendParameterNames(std::string* help) { *help += "supported:\n"; - for (const auto& kv : ServerParameterSet::getGlobal()->getMap()) { + for (const auto& kv : ServerParameterSet::getNodeParameterSet()->getMap()) { *help += " "; *help += kv.first; *help += '\n'; @@ -226,10 +226,9 @@ public: int before = result.len(); - const ServerParameter::Map& m = ServerParameterSet::getGlobal()->getMap(); - for (ServerParameter::Map::const_iterator i = m.begin(); i != m.end(); ++i) { - if (all || cmdObj.hasElement(i->first.c_str())) { - i->second->append(opCtx, result, i->second->name()); + for (const auto& param : ServerParameterSet::getNodeParameterSet()->getMap()) { + if (all || cmdObj.hasElement(param.first.c_str())) { + param.second->append(opCtx, result, param.second->name()); } } @@ -275,7 +274,8 @@ public: int numSet = 0; bool found = false; - const ServerParameter::Map& parameterMap = ServerParameterSet::getGlobal()->getMap(); + const ServerParameter::Map& parameterMap = + ServerParameterSet::getNodeParameterSet()->getMap(); // First check that we aren't setting the same parameter twice and that we actually are // setting parameters that we have registered and can change at runtime diff --git a/src/mongo/db/index_builds_coordinator_mongod.cpp b/src/mongo/db/index_builds_coordinator_mongod.cpp index 1d41a6ac8b3..be01c71eb53 100644 --- a/src/mongo/db/index_builds_coordinator_mongod.cpp +++ b/src/mongo/db/index_builds_coordinator_mongod.cpp @@ -98,11 +98,10 @@ IndexBuildsCoordinatorMongod::IndexBuildsCoordinatorMongod() // Change the 'setOnUpdate' function for the server parameter to signal the condition variable // when the value changes. - ServerParameter* serverParam = - ServerParameterSet::getGlobal()->get(kMaxNumActiveUserIndexBuildsServerParameterName); - static_cast< - IDLServerParameterWithStorage<ServerParameterType::kStartupAndRuntime, AtomicWord<int>>*>( - serverParam) + using ParamT = + IDLServerParameterWithStorage<ServerParameterType::kStartupAndRuntime, AtomicWord<int>>; + ServerParameterSet::getNodeParameterSet() + ->get<ParamT>(kMaxNumActiveUserIndexBuildsServerParameterName) ->setOnUpdate([this](const int) -> Status { _indexBuildFinished.notify_all(); return Status::OK(); diff --git a/src/mongo/db/mirror_maestro.cpp b/src/mongo/db/mirror_maestro.cpp index b5d40d0c0f6..b586b332b02 100644 --- a/src/mongo/db/mirror_maestro.cpp +++ b/src/mongo/db/mirror_maestro.cpp @@ -478,8 +478,8 @@ void MirrorMaestroImpl::init(ServiceContext* serviceContext) noexcept { _executor->startup(); _topologyVersionObserver.init(serviceContext); - _params = - ServerParameterSet::getGlobal()->get<MirroredReadsServerParameter>(kMirroredReadsParamName); + _params = ServerParameterSet::getNodeParameterSet()->get<MirroredReadsServerParameter>( + kMirroredReadsParamName); invariant(_params); // Set _initGuard.liveness to kRunning diff --git a/src/mongo/db/process_health/fault_manager_config.h b/src/mongo/db/process_health/fault_manager_config.h index 2ee6addfed9..961461111f1 100644 --- a/src/mongo/db/process_health/fault_manager_config.h +++ b/src/mongo/db/process_health/fault_manager_config.h @@ -199,18 +199,18 @@ public: private: static HealthMonitoringIntensitiesServerParameter* _getHealthObserverIntensities() { - return ServerParameterSet::getGlobal()->get<HealthMonitoringIntensitiesServerParameter>( - "healthMonitoringIntensities"); + return ServerParameterSet::getNodeParameterSet() + ->get<HealthMonitoringIntensitiesServerParameter>("healthMonitoringIntensities"); } static PeriodicHealthCheckIntervalsServerParameter* _getHealthObserverIntervals() { - return ServerParameterSet::getGlobal()->get<PeriodicHealthCheckIntervalsServerParameter>( - "healthMonitoringIntervals"); + return ServerParameterSet::getNodeParameterSet() + ->get<PeriodicHealthCheckIntervalsServerParameter>("healthMonitoringIntervals"); } static HealthMonitoringProgressMonitorServerParameter* _getLivenessConfig() { - return ServerParameterSet::getGlobal()->get<HealthMonitoringProgressMonitorServerParameter>( - "progressMonitor"); + return ServerParameterSet::getNodeParameterSet() + ->get<HealthMonitoringProgressMonitorServerParameter>("progressMonitor"); } static Milliseconds _getDefaultObserverInterval(FaultFacetType type); diff --git a/src/mongo/db/repl/initial_syncer_test.cpp b/src/mongo/db/repl/initial_syncer_test.cpp index 3875c64ef9b..6f6d5d1e489 100644 --- a/src/mongo/db/repl/initial_syncer_test.cpp +++ b/src/mongo/db/repl/initial_syncer_test.cpp @@ -4376,10 +4376,9 @@ TEST_F(InitialSyncerTest, OplogOutOfOrderOnOplogFetchFinish) { TEST_F(InitialSyncerTest, TestRemainingInitialSyncEstimatedMillisMetric) { auto initialSyncer = &getInitialSyncer(); auto opCtx = makeOpCtx(); - ASSERT_OK(ServerParameterSet::getGlobal() - ->getMap() - .find("collectionClonerBatchSize") - ->second->setFromString("1")); + ASSERT_OK(ServerParameterSet::getNodeParameterSet() + ->get("collectionClonerBatchSize") + ->setFromString("1")); _syncSourceSelector->setChooseNewSyncSourceResult_forTest(HostAndPort("localhost", 27017)); @@ -4531,10 +4530,9 @@ TEST_F(InitialSyncerTest, GetInitialSyncProgressReturnsCorrectProgress) { auto initialSyncer = &getInitialSyncer(); auto opCtx = makeOpCtx(); - ASSERT_OK(ServerParameterSet::getGlobal() - ->getMap() - .find("collectionClonerBatchSize") - ->second->setFromString("1")); + ASSERT_OK(ServerParameterSet::getNodeParameterSet() + ->get("collectionClonerBatchSize") + ->setFromString("1")); _syncSourceSelector->setChooseNewSyncSourceResult_forTest(HostAndPort("localhost", 27017)); ASSERT_OK(initialSyncer->startup(opCtx.get(), 2U)); diff --git a/src/mongo/db/repl/replication_info.cpp b/src/mongo/db/repl/replication_info.cpp index 4b831bb935e..c69661c9671 100644 --- a/src/mongo/db/repl/replication_info.cpp +++ b/src/mongo/db/repl/replication_info.cpp @@ -454,10 +454,9 @@ public: result.append(HelloCommandReply::kReadOnlyFieldName, storageGlobalParams.readOnly); - const auto& params = ServerParameterSet::getGlobal()->getMap(); - if (auto iter = params.find(kAutomationServiceDescriptorFieldName); - iter != params.end() && iter->second) { - iter->second->append(opCtx, result, kAutomationServiceDescriptorFieldName); + if (auto param = ServerParameterSet::getNodeParameterSet()->getIfExists( + kAutomationServiceDescriptorFieldName)) { + param->append(opCtx, result, kAutomationServiceDescriptorFieldName); } if (opCtx->getClient()->session()) { diff --git a/src/mongo/db/s/transaction_coordinator_test_fixture.cpp b/src/mongo/db/s/transaction_coordinator_test_fixture.cpp index 0beec9178f4..023e7deb4b4 100644 --- a/src/mongo/db/s/transaction_coordinator_test_fixture.cpp +++ b/src/mongo/db/s/transaction_coordinator_test_fixture.cpp @@ -55,10 +55,9 @@ HostAndPort makeHostAndPort(const ShardId& shardId) { void TransactionCoordinatorTestFixture::setUp() { ShardServerTestFixture::setUp(); - ASSERT_OK(ServerParameterSet::getGlobal() - ->getMap() - .find("logComponentVerbosity") - ->second->setFromString("{transaction: {verbosity: 3}}")); + ASSERT_OK(ServerParameterSet::getNodeParameterSet() + ->get("logComponentVerbosity") + ->setFromString("{transaction: {verbosity: 3}}")); for (const auto& shardId : kThreeShardIdList) { auto shardTargeter = RemoteCommandTargeterMock::get( diff --git a/src/mongo/db/server_options_helpers.cpp b/src/mongo/db/server_options_helpers.cpp index 7f7e1fe6ee2..a27b861aa09 100644 --- a/src/mongo/db/server_options_helpers.cpp +++ b/src/mongo/db/server_options_helpers.cpp @@ -149,19 +149,20 @@ Status validateBaseOptions(const moe::Environment& params) { globalFailPointRegistry().registerAllFailPointsAsServerParameters(); } else { // Deregister test-only parameters. - ServerParameterSet::getGlobal()->disableTestParameters(); + ServerParameterSet::getNodeParameterSet()->disableTestParameters(); } // Must come after registerAllFailPointsAsServerParameters() above. - const auto& spMap = ServerParameterSet::getGlobal()->getMap(); + auto* paramSet = ServerParameterSet::getNodeParameterSet(); for (const auto& setParam : parameters) { - const auto it = spMap.find(setParam.first); + auto* param = paramSet->getIfExists(setParam.first); - if (it == spMap.end()) { + if (!param) { return {ErrorCodes::BadValue, str::stream() << "Unknown --setParameter '" << setParam.first << "'"}; } - if (!enableTestCommandsValue && it->second->isTestOnly()) { + + if (!enableTestCommandsValue && param->isTestOnly()) { return {ErrorCodes::BadValue, str::stream() << "--setParameter '" << setParam.first << "' only available when used with 'enableTestCommands'"}; @@ -416,9 +417,8 @@ Status storeBaseOptions(const moe::Environment& params) { for (std::map<std::string, std::string>::iterator parametersIt = parameters.begin(); parametersIt != parameters.end(); parametersIt++) { - const auto& serverParams = ServerParameterSet::getGlobal()->getMap(); - auto iter = serverParams.find(parametersIt->first); - ServerParameter* parameter = (iter == serverParams.end()) ? nullptr : iter->second; + auto* parameter = + ServerParameterSet::getNodeParameterSet()->getIfExists(parametersIt->first); if (nullptr == parameter) { StringBuilder sb; sb << "Illegal --setParameter parameter: \"" << parametersIt->first << "\""; diff --git a/src/mongo/db/stats/resource_consumption_metrics_test.cpp b/src/mongo/db/stats/resource_consumption_metrics_test.cpp index 74245509594..a4398f8fada 100644 --- a/src/mongo/db/stats/resource_consumption_metrics_test.cpp +++ b/src/mongo/db/stats/resource_consumption_metrics_test.cpp @@ -39,13 +39,7 @@ namespace mongo { namespace { ServerParameter* getServerParameter(const std::string& name) { - const auto& spMap = ServerParameterSet::getGlobal()->getMap(); - const auto& spIt = spMap.find(name); - ASSERT(spIt != spMap.end()); - - auto* sp = spIt->second; - ASSERT(sp); - return sp; + return ServerParameterSet::getNodeParameterSet()->get(name); } } // namespace diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp index 1420dbf73c8..317e8cf5409 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp @@ -616,7 +616,7 @@ WiredTigerKVEngine::WiredTigerKVEngine(const std::string& canonicalName, WiredTigerKVEngine::~WiredTigerKVEngine() { // Remove server parameters that we added in the constructor, to enable unit tests to reload the // storage engine again in this same process. - ServerParameterSet::getGlobal()->remove("wiredTigerEngineRuntimeConfig"); + ServerParameterSet::getNodeParameterSet()->remove("wiredTigerEngineRuntimeConfig"); cleanShutdown(); diff --git a/src/mongo/dbtests/framework_options.cpp b/src/mongo/dbtests/framework_options.cpp index 303104623d2..558a09101b1 100644 --- a/src/mongo/dbtests/framework_options.cpp +++ b/src/mongo/dbtests/framework_options.cpp @@ -140,35 +140,30 @@ Status storeTestFrameworkOptions(const moe::Environment& params, if (params.count("setParameter")) { std::map<std::string, std::string> parameters = params["setParameter"].as<std::map<std::string, std::string>>(); - for (std::map<std::string, std::string>::iterator parametersIt = parameters.begin(); - parametersIt != parameters.end(); - parametersIt++) { - const auto& serverParams = ServerParameterSet::getGlobal()->getMap(); - auto iter = serverParams.find(parametersIt->first); - ServerParameter* parameter = (iter == serverParams.end()) ? nullptr : iter->second; + auto* paramSet = ServerParameterSet::getNodeParameterSet(); + for (const auto& it : parameters) { + auto parameter = paramSet->getIfExists(it.first); if (nullptr == parameter) { - StringBuilder sb; - sb << "Illegal --setParameter parameter: \"" << parametersIt->first << "\""; - return Status(ErrorCodes::BadValue, sb.str()); + return {ErrorCodes::BadValue, + str::stream() + << "Illegal --setParameter parameter: \"" << it.first << "\""}; } if (!parameter->allowedToChangeAtStartup()) { - StringBuilder sb; - sb << "Cannot use --setParameter to set \"" << parametersIt->first - << "\" at startup"; - return Status(ErrorCodes::BadValue, sb.str()); + return {ErrorCodes::BadValue, + str::stream() << "Cannot use --setParameter to set \"" << it.first + << "\" at startup"}; } - Status status = parameter->setFromString(parametersIt->second); + Status status = parameter->setFromString(it.second); if (!status.isOK()) { - StringBuilder sb; - sb << "Bad value for parameter \"" << parametersIt->first - << "\": " << status.reason(); - return Status(ErrorCodes::BadValue, sb.str()); + return {ErrorCodes::BadValue, + str::stream() << "Bad value for parameter \"" << it.first + << "\": " << status.reason()}; } LOGV2(4539300, "Setting server parameter", - "parameter"_attr = parametersIt->first, - "value"_attr = parametersIt->second); + "parameter"_attr = it.first, + "value"_attr = it.second); } } diff --git a/src/mongo/idl/feature_flag_test.cpp b/src/mongo/idl/feature_flag_test.cpp index 10ecfa9824f..e6e998975c2 100644 --- a/src/mongo/idl/feature_flag_test.cpp +++ b/src/mongo/idl/feature_flag_test.cpp @@ -40,13 +40,7 @@ namespace mongo { namespace { ServerParameter* getServerParameter(const std::string& name) { - const auto& spMap = ServerParameterSet::getGlobal()->getMap(); - const auto& spIt = spMap.find(name); - ASSERT(spIt != spMap.end()); - - auto* sp = spIt->second; - ASSERT(sp); - return sp; + return ServerParameterSet::getNodeParameterSet()->get(name); } class FeatureFlagTest : public unittest::Test { diff --git a/src/mongo/idl/server_parameter.cpp b/src/mongo/idl/server_parameter.cpp index e15bd17f483..03e7ac8143e 100644 --- a/src/mongo/idl/server_parameter.cpp +++ b/src/mongo/idl/server_parameter.cpp @@ -42,33 +42,70 @@ MONGO_INITIALIZER_GROUP(EndServerParameterRegistration, ("BeginStartupOptionHandling")) ServerParameter::ServerParameter(StringData name, ServerParameterType spt, NoRegistrationTag) - : _name(name.toString()), _type(spt) {} + : _name(name.toString()), _type(spt) { + _generation.clear(); +} ServerParameter::ServerParameter(StringData name, ServerParameterType spt) : ServerParameter(name, spt, NoRegistrationTag{}) { - ServerParameterSet::getGlobal()->add(this); + ServerParameterSet::getParameterSet(spt)->add(this); +} + +void ServerParameter::setGeneration(const OID& generation) { + uassert(6225101, + "Invalid call to setGeneration on locally scoped server parameter", + isClusterWide()); + _generation = generation; } namespace { -ServerParameterSet* gGlobalServerParameterSet = nullptr; +class NodeParameterSet : public ServerParameterSet { +public: + void add(ServerParameter* sp) final { + uassert(6225102, + str::stream() << "Registering cluster-wide parameter '" << sp->name() + << "' as node-local server parameter", + sp->isNodeLocal()); + ServerParameter*& x = _map[sp->name()]; + uassert(23784, + str::stream() << "Duplicate server parameter registration for '" << x->name() + << "'", + !x); + x = sp; + } +}; +NodeParameterSet* gNodeServerParameters = nullptr; + +class ClusterParameterSet : public ServerParameterSet { +public: + void add(ServerParameter* sp) final { + uassert(6225103, + str::stream() << "Registering node-local parameter '" << sp->name() + << "' as cluster-wide server parameter", + sp->isClusterWide()); + ServerParameter*& x = _map[sp->name()]; + uassert(6225104, + str::stream() << "Duplicate cluster-wide server parameter registration for '" + << x->name() << "'", + !x); + x = sp; + } +}; +ClusterParameterSet* gClusterServerParameters; } // namespace -ServerParameterSet* ServerParameterSet::getGlobal() { - if (!gGlobalServerParameterSet) { - gGlobalServerParameterSet = new ServerParameterSet(); +ServerParameterSet* ServerParameterSet::getNodeParameterSet() { + if (!gNodeServerParameters) { + gNodeServerParameters = new NodeParameterSet(); } - return gGlobalServerParameterSet; + return gNodeServerParameters; } -void ServerParameterSet::add(ServerParameter* sp) { - ServerParameter*& x = _map[sp->name()]; - if (x) { - LOGV2_FATAL(23784, - "'{name}' already exists in the server parameter set", - "Duplicate server parameter registration", - "name"_attr = x->name()); +ServerParameterSet* ServerParameterSet::getClusterParameterSet() { + if (!gClusterServerParameters) { + gClusterServerParameters = new ClusterParameterSet(); } - x = sp; + return gClusterServerParameters; } StatusWith<std::string> ServerParameter::coerceToString(const BSONElement& element, bool redact) { diff --git a/src/mongo/idl/server_parameter.h b/src/mongo/idl/server_parameter.h index 8d8705071f6..41001b8e43a 100644 --- a/src/mongo/idl/server_parameter.h +++ b/src/mongo/idl/server_parameter.h @@ -42,6 +42,7 @@ #include "mongo/base/status.h" #include "mongo/bson/bsonelement.h" #include "mongo/bson/bsonobjbuilder.h" +#include "mongo/bson/oid.h" #define MONGO_SERVER_PARAMETER_REGISTER(name) \ MONGO_INITIALIZER_GENERAL( \ @@ -50,32 +51,40 @@ namespace mongo { /** - * Server Parameters can be set startup up and/or runtime. - * - * At startup, --setParameter ... or config file is used. - * At runtime, { setParameter : 1, ...} is used. + * How and when a given Server Parameter may be set/modified. */ enum class ServerParameterType { /** * May not be set at any time. + * Used as a means to read out current state, similar to ServerStatus. */ kReadOnly, /** - * Parameter can only be set via runCommand. + * Parameter can only be set via `{setParameter: 1, name: value}` */ kRuntimeOnly, /** - * Parameter can only be set via --setParameter, and is only read at startup after command-line + * Parameter can only be set via `--setParameter 'name=value'`, + * and is only read at startup after command-line * parameters, and the config file are processed. */ kStartupOnly, /** * Parameter can be set at both startup and runtime. + * This is essentially a union of kRuntimeOnly and kStartupOnly. */ kStartupAndRuntime, + + /** + * Cluster-wide configuration setting. + * These are by-definition runtime settable only, however unlike other modes (including + * kRuntimeOnly), these are set via the {setClusterParameter:...} command and stored in a + * separate map. ClusterWide settings are propagated to other nodes in the cluster. + */ + kClusterWide, }; class ServerParameterSet; @@ -105,13 +114,28 @@ public: */ bool allowedToChangeAtRuntime() const { return (_type == ServerParameterType::kRuntimeOnly) || - (_type == ServerParameterType::kStartupAndRuntime); + (_type == ServerParameterType::kStartupAndRuntime) || + (_type == ServerParameterType::kClusterWide); } ServerParameterType getServerParameterType() const { return _type; } + bool isClusterWide() const { + return (_type == ServerParameterType::kClusterWide); + } + + bool isNodeLocal() const { + return (_type != ServerParameterType::kClusterWide); + } + + OID getGeneration() const { + return _generation; + } + + void setGeneration(const OID& generation); + virtual void append(OperationContext* opCtx, BSONObjBuilder& b, const std::string& name) = 0; virtual void appendSupportingRoundtrip(OperationContext* opCtx, @@ -120,6 +144,10 @@ public: append(opCtx, b, name); } + virtual Status validate(const BSONElement& newValueElement) const { + return Status::OK(); + } + virtual Status set(const BSONElement& newValueElement) = 0; virtual Status setFromString(const std::string& str) = 0; @@ -142,6 +170,7 @@ protected: private: std::string _name; + OID _generation; ServerParameterType _type; bool _testOnly = false; }; @@ -150,27 +179,45 @@ class ServerParameterSet { public: using Map = ServerParameter::Map; - void add(ServerParameter* sp); + virtual ~ServerParameterSet() = default; + + virtual void add(ServerParameter* sp) = 0; void remove(const std::string& name); const Map& getMap() const { return _map; } - static ServerParameterSet* getGlobal(); - + // Singleton instances of ServerParameterSet + // used for retreiving the local or cluster-wide maps. + static ServerParameterSet* getNodeParameterSet(); + static ServerParameterSet* getClusterParameterSet(); + static ServerParameterSet* getParameterSet(ServerParameterType spt) { + if (spt == ServerParameterType::kClusterWide) { + return getClusterParameterSet(); + } else { + return getNodeParameterSet(); + } + } void disableTestParameters(); template <typename T = ServerParameter> - T* get(StringData name) { + T* getIfExists(StringData name) { const auto& it = _map.find(name.toString()); - uassert(ErrorCodes::NoSuchKey, - str::stream() << "Unknown server parameter: " << name, - it != _map.end()); + if (it == _map.end()) { + return nullptr; + } return checked_cast<T*>(it->second); } -private: + template <typename T = ServerParameter> + T* get(StringData name) { + T* ret = getIfExists<T>(name); + uassert(ErrorCodes::NoSuchKey, str::stream() << "Unknown server parameter: " << name, ret); + return ret; + } + +protected: Map _map; }; diff --git a/src/mongo/idl/server_parameter_specialized_test.cpp b/src/mongo/idl/server_parameter_specialized_test.cpp index 869effeeb2a..8d1f8c7fcca 100644 --- a/src/mongo/idl/server_parameter_specialized_test.cpp +++ b/src/mongo/idl/server_parameter_specialized_test.cpp @@ -38,9 +38,7 @@ namespace test { template <typename T = ServerParameter> T* getServerParameter(StringData name) { - auto* sp = ServerParameterSet::getGlobal()->get<T>(name); - ASSERT(sp); - return sp; + return ServerParameterSet::getNodeParameterSet()->get<T>(name); } template <typename Validator> @@ -310,5 +308,38 @@ TEST(SpecializedServerParameter, withOptions) { ASSERT_APPENDED_STRING(dswo, "###"); } +void SpecializedRuntimeOnly::append(OperationContext*, BSONObjBuilder&, const std::string&) {} + +Status SpecializedRuntimeOnly::setFromString(const std::string& value) { + return Status::OK(); +} + +TEST(SpecializedServerParameter, withScope) { + using SPT = ServerParameterType; + + auto* nodeSet = ServerParameterSet::getNodeParameterSet(); + auto* clusterSet = ServerParameterSet::getClusterParameterSet(); + + constexpr auto kSpecializedWithOptions = "specializedWithOptions"_sd; + auto* nodeSWO = nodeSet->getIfExists(kSpecializedWithOptions); + ASSERT(nullptr != nodeSWO); + ASSERT(nullptr == clusterSet->getIfExists(kSpecializedWithOptions)); + + auto* clusterSWO = new SpecializedWithOptions(kSpecializedWithOptions, SPT::kClusterWide); + ASSERT(clusterSWO != nodeSWO); + ASSERT(clusterSWO == clusterSet->getIfExists(kSpecializedWithOptions)); + + // Duplicate key + ASSERT_THROWS_CODE(new SpecializedWithOptions(kSpecializedWithOptions, SPT::kClusterWide), + DBException, + 6225104); + + // Require runtime only. + constexpr auto kSpecializedRuntimeOnly = "specializedRuntimeOnly"_sd; + auto* clusterSRO = new SpecializedRuntimeOnly(kSpecializedRuntimeOnly, SPT::kClusterWide); + ASSERT(nullptr != clusterSRO); + // Pointer now belongs to ServerParameterSet, no need to delete. +} + } // namespace test } // namespace mongo diff --git a/src/mongo/idl/server_parameter_specialized_test.idl b/src/mongo/idl/server_parameter_specialized_test.idl index 7596a4a7fef..f6e969f473f 100644 --- a/src/mongo/idl/server_parameter_specialized_test.idl +++ b/src/mongo/idl/server_parameter_specialized_test.idl @@ -87,3 +87,7 @@ server_parameters: test_only: false condition: { expr: true } deprecated_name: deprecatedWithOptions + specializedRuntimeOnly: + description: "Only settable at runtime." + set_at: runtime + cpp_class: SpecializedRuntimeOnly diff --git a/src/mongo/idl/server_parameter_test_util.h b/src/mongo/idl/server_parameter_test_util.h index b064cf3ad83..566489dd1a9 100644 --- a/src/mongo/idl/server_parameter_test_util.h +++ b/src/mongo/idl/server_parameter_test_util.h @@ -27,8 +27,10 @@ * it in the license file. */ -#include "mongo/bson/bsontypes.h" -#include "mongo/idl/feature_flag.h" +#include <string> + +#include "mongo/bson/bsonobj.h" +#include "mongo/bson/bsonobjbuilder.h" #include "mongo/idl/server_parameter.h" namespace mongo { @@ -43,15 +45,15 @@ public: * Constructor setting the server parameter to the specified value. */ template <typename T> - RAIIServerParameterControllerForTest(const std::string& paramName, T value) - : _serverParam(_getServerParameter(paramName)) { + RAIIServerParameterControllerForTest(const std::string& name, T value) + : _serverParam(ServerParameterSet::getNodeParameterSet()->get(name)) { // Save the old value BSONObjBuilder bob; - _serverParam->appendSupportingRoundtrip(nullptr, bob, paramName); + _serverParam->appendSupportingRoundtrip(nullptr, bob, name); _oldValue = bob.obj(); // Set to the new value - uassertStatusOK(_serverParam->set(BSON(paramName << value).firstElement())); + uassertStatusOK(_serverParam->set(BSON(name << value).firstElement())); } /** @@ -64,21 +66,7 @@ public: } private: - /** - * Returns a server parameter if exists, otherwise triggers an invariant. - */ - ServerParameter* _getServerParameter(const std::string& paramName) { - const auto& spMap = ServerParameterSet::getGlobal()->getMap(); - const auto& spIt = spMap.find(paramName); - invariant(spIt != spMap.end()); - - auto* sp = spIt->second; - invariant(sp); - return sp; - } - ServerParameter* _serverParam; - BSONObj _oldValue; }; diff --git a/src/mongo/idl/server_parameter_with_storage.h b/src/mongo/idl/server_parameter_with_storage.h index 603c04c50a5..40de90721c0 100644 --- a/src/mongo/idl/server_parameter_with_storage.h +++ b/src/mongo/idl/server_parameter_with_storage.h @@ -196,16 +196,24 @@ public: static_assert(thread_safe || notRuntime, "Runtime server parameters must be thread safe"); } - /** - * Convenience wrapper for storing a value. - */ - Status setValue(const element_type& newValue) { + Status validateValue(const element_type& newValue) const { for (const auto& validator : _validators) { const auto status = validator(newValue); if (!status.isOK()) { return status; } } + return Status::OK(); + } + + /** + * Convenience wrapper for storing a value. + */ + Status setValue(const element_type& newValue) { + if (auto status = validateValue(newValue); !status.isOK()) { + return status; + } + SW::store(_storage, newValue); if (_onUpdate) { @@ -236,6 +244,17 @@ public: } } + Status validate(const BSONElement& newValueElement) const final { + element_type newValue; + + if (auto status = newValueElement.tryCoerce(&newValue); !status.isOK()) { + return {status.code(), + str::stream() << "Failed validating " << name() << ": " << status.reason()}; + } + + return validateValue(newValue); + } + /** * Update the underlying value using a BSONElement * diff --git a/src/mongo/idl/server_parameter_with_storage_test.cpp b/src/mongo/idl/server_parameter_with_storage_test.cpp index 957c2abc18d..d0d11097a90 100644 --- a/src/mongo/idl/server_parameter_with_storage_test.cpp +++ b/src/mongo/idl/server_parameter_with_storage_test.cpp @@ -179,13 +179,7 @@ TEST(ServerParameterWithStorage, BoundsTest) { } ServerParameter* getServerParameter(const std::string& name) { - const auto& spMap = ServerParameterSet::getGlobal()->getMap(); - const auto& spIt = spMap.find(name); - ASSERT(spIt != spMap.end()); - - auto* sp = spIt->second; - ASSERT(sp); - return sp; + return ServerParameterSet::getNodeParameterSet()->get(name); } TEST(IDLServerParameterWithStorage, stdIntDeclared) { diff --git a/src/mongo/s/commands/cluster_hello_cmd.cpp b/src/mongo/s/commands/cluster_hello_cmd.cpp index 4e2014f1058..f9269db5616 100644 --- a/src/mongo/s/commands/cluster_hello_cmd.cpp +++ b/src/mongo/s/commands/cluster_hello_cmd.cpp @@ -206,12 +206,9 @@ public: result.append(HelloCommandReply::kMinWireVersionFieldName, wireSpec->incomingExternalClient.minWireVersion); - { - const auto& serverParams = ServerParameterSet::getGlobal()->getMap(); - auto iter = serverParams.find(kAutomationServiceDescriptorFieldName); - if (iter != serverParams.end() && iter->second) { - iter->second->append(opCtx, result, kAutomationServiceDescriptorFieldName); - } + if (auto sp = ServerParameterSet::getNodeParameterSet()->getIfExists( + kAutomationServiceDescriptorFieldName)) { + sp->append(opCtx, result, kAutomationServiceDescriptorFieldName); } MessageCompressorManager::forSession(opCtx->getClient()->session()) diff --git a/src/mongo/s/hedge_options_util_test.cpp b/src/mongo/s/hedge_options_util_test.cpp index 7ea69523cad..33808dfb9aa 100644 --- a/src/mongo/s/hedge_options_util_test.cpp +++ b/src/mongo/s/hedge_options_util_test.cpp @@ -50,15 +50,11 @@ protected: * Set the given server parameters. */ void setParameters(const BSONObj& parameters) { - const ServerParameter::Map& parameterMap = ServerParameterSet::getGlobal()->getMap(); + auto* paramSet = ServerParameterSet::getNodeParameterSet(); BSONObjIterator parameterIterator(parameters); - while (parameterIterator.more()) { BSONElement parameter = parameterIterator.next(); - std::string parameterName = parameter.fieldName(); - - ServerParameter::Map::const_iterator foundParameter = parameterMap.find(parameterName); - uassertStatusOK(foundParameter->second->set(parameter)); + uassertStatusOK(paramSet->get(parameter.fieldName())->set(parameter)); } } diff --git a/src/mongo/shell/shell_options.cpp b/src/mongo/shell/shell_options.cpp index d67a554d584..9ad99f17852 100644 --- a/src/mongo/shell/shell_options.cpp +++ b/src/mongo/shell/shell_options.cpp @@ -307,15 +307,14 @@ Status storeMongoShellOptions(const moe::Environment& params, if (params.count("setShellParameter")) { auto ssp = params["setShellParameter"].as<std::map<std::string, std::string>>(); - auto map = ServerParameterSet::getGlobal()->getMap(); + auto* paramSet = ServerParameterSet::getNodeParameterSet(); for (auto it : ssp) { const auto& name = it.first; - auto paramIt = map.find(name); - if (paramIt == map.end() || !kSetShellParameterAllowlist.count(name)) { + auto param = paramSet->getIfExists(name); + if (!param || !kSetShellParameterAllowlist.count(name)) { return {ErrorCodes::BadValue, str::stream() << "Unknown --setShellParameter '" << name << "'"}; } - auto* param = paramIt->second; if (!param->allowedToChangeAtStartup()) { return {ErrorCodes::BadValue, str::stream() |