summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSara Golemon <sara.golemon@mongodb.com>2021-12-30 03:26:41 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-01-10 23:14:43 +0000
commit255959a734f98dc700afb43b05e0e9590bc7aa91 (patch)
tree17471d9b5fec1ab1346c71a0ffa1acb07b97cb8a
parent0791c57fb7a3e86be3880aa926dfb9bb54f76802 (diff)
downloadmongo-255959a734f98dc700afb43b05e0e9590bc7aa91.tar.gz
SERVER-62251 Add ServerParameterType::kClusterWide
-rw-r--r--src/mongo/client/replica_set_monitor_protocol_test_util.cpp2
-rw-r--r--src/mongo/db/commands/parameters.cpp12
-rw-r--r--src/mongo/db/index_builds_coordinator_mongod.cpp9
-rw-r--r--src/mongo/db/mirror_maestro.cpp4
-rw-r--r--src/mongo/db/process_health/fault_manager_config.h12
-rw-r--r--src/mongo/db/repl/initial_syncer_test.cpp14
-rw-r--r--src/mongo/db/repl/replication_info.cpp7
-rw-r--r--src/mongo/db/s/transaction_coordinator_test_fixture.cpp7
-rw-r--r--src/mongo/db/server_options_helpers.cpp16
-rw-r--r--src/mongo/db/stats/resource_consumption_metrics_test.cpp8
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp2
-rw-r--r--src/mongo/dbtests/framework_options.cpp35
-rw-r--r--src/mongo/idl/feature_flag_test.cpp8
-rw-r--r--src/mongo/idl/server_parameter.cpp67
-rw-r--r--src/mongo/idl/server_parameter.h77
-rw-r--r--src/mongo/idl/server_parameter_specialized_test.cpp37
-rw-r--r--src/mongo/idl/server_parameter_specialized_test.idl4
-rw-r--r--src/mongo/idl/server_parameter_test_util.h28
-rw-r--r--src/mongo/idl/server_parameter_with_storage.h27
-rw-r--r--src/mongo/idl/server_parameter_with_storage_test.cpp8
-rw-r--r--src/mongo/s/commands/cluster_hello_cmd.cpp9
-rw-r--r--src/mongo/s/hedge_options_util_test.cpp8
-rw-r--r--src/mongo/shell/shell_options.cpp7
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()