diff options
-rw-r--r-- | jstests/dur/journaling_options.js | 117 | ||||
-rw-r--r-- | jstests/libs/config_files/enable_journal.json | 7 | ||||
-rw-r--r-- | src/mongo/db/mongod_options.cpp | 98 | ||||
-rw-r--r-- | src/mongo/db/mongod_options.h | 15 | ||||
-rw-r--r-- | src/mongo/db/mongod_options_init.cpp | 8 | ||||
-rw-r--r-- | src/mongo/util/options_parser/environment.cpp | 22 | ||||
-rw-r--r-- | src/mongo/util/options_parser/environment.h | 6 |
7 files changed, 246 insertions, 27 deletions
diff --git a/jstests/dur/journaling_options.js b/jstests/dur/journaling_options.js new file mode 100644 index 00000000000..1c62c2167b0 --- /dev/null +++ b/jstests/dur/journaling_options.js @@ -0,0 +1,117 @@ +var baseName = "jstests_dur_journaling_options"; + +function removeOptionsAddedByFramework(getCmdLineOptsResult) { + // Remove options that we are not interested in checking, but that get set by the test + delete getCmdLineOptsResult.parsed.setParameter + delete getCmdLineOptsResult.parsed.storage.dbPath + delete getCmdLineOptsResult.parsed.net + delete getCmdLineOptsResult.parsed.fastsync + return getCmdLineOptsResult; +} + +jsTest.log("Testing \"dur\" command line option"); +var mongodSource = MongoRunner.runMongod({ dur : "" }); +var getCmdLineOptsExpected = { + "parsed" : { + "storage" : { + "journal" : { + "enabled" : true + } + } + } +}; + +var getCmdLineOptsResult = mongodSource.adminCommand("getCmdLineOpts"); +printjson(getCmdLineOptsResult); +getCmdLineOptsResult = removeOptionsAddedByFramework(getCmdLineOptsResult); +assert.docEq(getCmdLineOptsResult.parsed, getCmdLineOptsExpected.parsed); +MongoRunner.stopMongod(mongodSource.port); + +jsTest.log("Testing \"nodur\" command line option"); +mongodSource = MongoRunner.runMongod({ nodur : "" }); +getCmdLineOptsExpected = { + "parsed" : { + "storage" : { + "journal" : { + "enabled" : false + } + } + } +}; + +getCmdLineOptsResult = mongodSource.adminCommand("getCmdLineOpts"); +printjson(getCmdLineOptsResult); +getCmdLineOptsResult = removeOptionsAddedByFramework(getCmdLineOptsResult); +assert.docEq(getCmdLineOptsResult.parsed, getCmdLineOptsExpected.parsed); +MongoRunner.stopMongod(mongodSource.port); + +jsTest.log("Testing \"journal\" command line option"); +mongodSource = MongoRunner.runMongod({ journal : "" }); +getCmdLineOptsExpected = { + "parsed" : { + "storage" : { + "journal" : { + "enabled" : true + } + } + } +}; + +getCmdLineOptsResult = mongodSource.adminCommand("getCmdLineOpts"); +printjson(getCmdLineOptsResult); +getCmdLineOptsResult = removeOptionsAddedByFramework(getCmdLineOptsResult); +assert.docEq(getCmdLineOptsResult.parsed, getCmdLineOptsExpected.parsed); +MongoRunner.stopMongod(mongodSource.port); + +jsTest.log("Testing \"nojournal\" command line option"); +mongodSource = MongoRunner.runMongod({ nojournal : "" }); +getCmdLineOptsExpected = { + "parsed" : { + "storage" : { + "journal" : { + "enabled" : false + } + } + } +}; + +getCmdLineOptsResult = mongodSource.adminCommand("getCmdLineOpts"); +printjson(getCmdLineOptsResult); +getCmdLineOptsResult = removeOptionsAddedByFramework(getCmdLineOptsResult); +assert.docEq(getCmdLineOptsResult.parsed, getCmdLineOptsExpected.parsed); +MongoRunner.stopMongod(mongodSource.port); + +jsTest.log("Testing \"storage.journal.enabled\" config file option"); +mongodSource = MongoRunner.runMongod({ config : "jstests/libs/config_files/enable_journal.json" }); +getCmdLineOptsExpected = { + "parsed" : { + "config" : "jstests/libs/config_files/enable_journal.json", + "storage" : { + "journal" : { + "enabled" : false + } + } + } +}; + +getCmdLineOptsResult = mongodSource.adminCommand("getCmdLineOpts"); +printjson(getCmdLineOptsResult); +getCmdLineOptsResult = removeOptionsAddedByFramework(getCmdLineOptsResult); +assert.docEq(getCmdLineOptsResult.parsed, getCmdLineOptsExpected.parsed); +MongoRunner.stopMongod(mongodSource.port); + +jsTest.log("Testing with no explicit journal setting"); +mongodSource = MongoRunner.runMongod(); +getCmdLineOptsExpected = { + "parsed" : { + "storage" : { } + } +}; + +getCmdLineOptsResult = mongodSource.adminCommand("getCmdLineOpts"); +printjson(getCmdLineOptsResult); +getCmdLineOptsResult = removeOptionsAddedByFramework(getCmdLineOptsResult); +assert.docEq(getCmdLineOptsResult.parsed, getCmdLineOptsExpected.parsed); +MongoRunner.stopMongod(mongodSource.port); + +print(baseName + " succeeded."); diff --git a/jstests/libs/config_files/enable_journal.json b/jstests/libs/config_files/enable_journal.json new file mode 100644 index 00000000000..d75b94ccbc7 --- /dev/null +++ b/jstests/libs/config_files/enable_journal.json @@ -0,0 +1,7 @@ +{ + "storage" : { + "journal" : { + "enabled" : false + } + } +} diff --git a/src/mongo/db/mongod_options.cpp b/src/mongo/db/mongod_options.cpp index d1a9c9cfeb4..7d06ab0b358 100644 --- a/src/mongo/db/mongod_options.cpp +++ b/src/mongo/db/mongod_options.cpp @@ -465,6 +465,71 @@ namespace mongo { return true; } + Status validateMongodOptions(const moe::Environment& params) { + if ((params.count("nodur") || params.count("nojournal")) && + (params.count("dur") || params.count("journal"))) { + return Status(ErrorCodes::BadValue, + "Can't specify both --journal and --nojournal options."); + } + + return Status::OK(); + } + + Status canonicalizeMongodOptions(moe::Environment* params) { + + // "storage.journal.enabled" comes from the config file, so override it if any of "journal", + // "nojournal", "dur", and "nodur" are set, since those come from the command line. + if (params->count("nodur") || params->count("nojournal")) { + Status ret = params->set("storage.journal.enabled", moe::Value(false)); + if (!ret.isOK()) { + return ret; + } + ret = params->remove("nodur"); + if (!ret.isOK()) { + return ret; + } + ret = params->remove("nojournal"); + if (!ret.isOK()) { + return ret; + } + } + + if (params->count("dur") || params->count("journal")) { + Status ret = params->set("storage.journal.enabled", moe::Value(true)); + if (!ret.isOK()) { + return ret; + } + ret = params->remove("dur"); + if (!ret.isOK()) { + return ret; + } + ret = params->remove("journal"); + if (!ret.isOK()) { + return ret; + } + } + + // "storage.journal.durOptions" comes from the config file, so override it if "durOptions" + // is set since that comes from the command line. + if (params->count("durOptions")) { + int durOptions; + Status ret = params->get("durOptions", &durOptions); + if (!ret.isOK()) { + return ret; + } + ret = params->set("storage.journal.debugFlags", moe::Value(durOptions)); + if (!ret.isOK()) { + return ret; + } + ret = params->remove("durOptions"); + if (!ret.isOK()) { + return ret; + } + } + + return Status::OK(); + } + Status storeMongodOptions(const moe::Environment& params, const std::vector<std::string>& args) { @@ -547,29 +612,11 @@ namespace mongo { storageGlobalParams.quota = true; storageGlobalParams.quotaFiles = params["storage.quota.maxFilesPerDB"].as<int>() - 1; } - if ((params.count("nodur") || params.count("nojournal")) && - (params.count("dur") || params.count("journal"))) { - return Status(ErrorCodes::BadValue, - "Can't specify both --journal and --nojournal options."); - } - // "storage.journal.enabled" comes from the config file, so check it before we check - // "journal", "nojournal", "dur", and "nodur", since those come from the command line. if (params.count("storage.journal.enabled")) { storageGlobalParams.dur = params["storage.journal.enabled"].as<bool>(); } - if (params.count("nodur") || params.count("nojournal")) { - storageGlobalParams.dur = false; - } - - if (params.count("dur") || params.count("journal")) { - storageGlobalParams.dur = true; - } - - if (params.count("durOptions")) { - storageGlobalParams.durOptions = params["durOptions"].as<int>(); - } if (params.count("storage.journal.commitIntervalMs")) { // don't check if dur is false here as many will just use the default, and will default // to off on win32. ie no point making life a little more complex by giving an error on @@ -677,9 +724,10 @@ namespace mongo { _diaglog.setLevel(x); } - if ((params.count("dur") || params.count("journal")) && params.count("repair")) { + if ((params.count("storage.journal.enabled") && + params["storage.journal.enabled"].as<bool>() == true) && params.count("repair")) { return Status(ErrorCodes::BadValue, - "Can't specify both --journal and --repair options."); + "Can't have journaling enabled when using --repair option."); } if (params.count("repair")) { @@ -836,10 +884,9 @@ namespace mongo { // If we haven't explicitly specified a journal option, default journaling to true for // the config server role - if (!params.count("nodur") && - !params.count("nojournal") && - !params.count("storage.journal.enabled")) + if (!params.count("storage.journal.enabled")) { storageGlobalParams.dur = true; + } if (!params.count("storage.dbPath")) storageGlobalParams.dbpath = "/data/configdb"; @@ -917,10 +964,7 @@ namespace mongo { log() << "--pretouch " << replSettings.pretouch << endl; // Check if we are 32 bit and have not explicitly specified any journaling options - if (sizeof(void*) == 4 && - !(params.count("nodur") || params.count("nojournal") || - params.count("dur") || params.count("journal") || - params.count("storage.journal.enabled"))) { + if (sizeof(void*) == 4 && !params.count("storage.journal.enabled")) { // trying to make this stand out more like startup warnings log() << endl; warning() << "32-bit servers don't have journaling enabled by default. " diff --git a/src/mongo/db/mongod_options.h b/src/mongo/db/mongod_options.h index e7c9c4626fe..61112f54f3d 100644 --- a/src/mongo/db/mongod_options.h +++ b/src/mongo/db/mongod_options.h @@ -69,5 +69,20 @@ namespace mongo { bool handlePreValidationMongodOptions(const moe::Environment& params, const std::vector<std::string>& args); + /** + * Handle custom validation of mongod options that can not currently be done by using + * Constraints in the Environment. See the "validate" function in the Environment class for + * more details. + */ + Status validateMongodOptions(const moe::Environment& params); + + /** + * Canonicalize mongod options for the given environment. + * + * For example, the options "dur", "nodur", "journal", "nojournal", and + * "storage.journaling.enabled" should all be merged into "storage.journaling.enabled". + */ + Status canonicalizeMongodOptions(moe::Environment* params); + Status storeMongodOptions(const moe::Environment& params, const std::vector<std::string>& args); } diff --git a/src/mongo/db/mongod_options_init.cpp b/src/mongo/db/mongod_options_init.cpp index 1ecd743c83b..67bdabdd82b 100644 --- a/src/mongo/db/mongod_options_init.cpp +++ b/src/mongo/db/mongod_options_init.cpp @@ -44,6 +44,14 @@ namespace mongo { if (!ret.isOK()) { return ret; } + ret = validateMongodOptions(moe::startupOptionsParsed); + if (!ret.isOK()) { + return ret; + } + ret = canonicalizeMongodOptions(&moe::startupOptionsParsed); + if (!ret.isOK()) { + return ret; + } return Status::OK(); } diff --git a/src/mongo/util/options_parser/environment.cpp b/src/mongo/util/options_parser/environment.cpp index 9f50ae2797c..f7ace993f7e 100644 --- a/src/mongo/util/options_parser/environment.cpp +++ b/src/mongo/util/options_parser/environment.cpp @@ -81,6 +81,28 @@ namespace optionenvironment { return Status::OK(); } + /** Removes a Value from our Environment */ + Status Environment::remove(const Key& remove_key) { + + // 1. Save old values + std::map <Key, Value> old_values = values; + + // 2. Remove value to be removed + values.erase(remove_key); + + // 3. Validate only if our environment is already valid + if (valid) { + Status ret = validate(); + if (!ret.isOK()) { + // 4. Revert to old values if this was invalid + values = old_values; + return ret; + } + } + + return Status::OK(); + } + /** Set the default Value for the given Key in our Environment. Always disallow empty values */ Status Environment::setDefault(const Key& add_key, const Value& add_value) { diff --git a/src/mongo/util/options_parser/environment.h b/src/mongo/util/options_parser/environment.h index 7ba68919ed4..5f4cfa96ba5 100644 --- a/src/mongo/util/options_parser/environment.h +++ b/src/mongo/util/options_parser/environment.h @@ -118,6 +118,12 @@ namespace optionenvironment { */ Status set(const Key& key, const Value& value); + /** Remove the Value from this Environment with the given Key. If "validate" has + * already been called on this Environment, runs all Constraints on the new Environment. + * If any of the Constraints fail, reverts to the old Environment and returns an error + */ + Status remove(const Key& key); + /** Add a default Value to this Environment with the given Key. Fails if validate has * already been called on our environment. The get functions will return the default * if one exists and the value has not been explicitly set. |