summaryrefslogtreecommitdiff
path: root/src/mongo/util/options_parser/options_parser.cpp
diff options
context:
space:
mode:
authorShaun Verch <shaun.verch@10gen.com>2013-08-15 11:59:46 -0400
committerShaun Verch <shaun.verch@10gen.com>2013-09-05 13:49:33 -0400
commit5ee03db5cdc40ecc0a28aaad8031df177188ffee (patch)
tree8199d2184bab251c6f3d260cc461c9c92f06ef48 /src/mongo/util/options_parser/options_parser.cpp
parent50a2462a66402499fa81c9fdb84ee6bab0e5d1a3 (diff)
downloadmongo-5ee03db5cdc40ecc0a28aaad8031df177188ffee.tar.gz
SERVER-8510 Handle default, implicit, and composing options in new configuration parser
Diffstat (limited to 'src/mongo/util/options_parser/options_parser.cpp')
-rw-r--r--src/mongo/util/options_parser/options_parser.cpp130
1 files changed, 129 insertions, 1 deletions
diff --git a/src/mongo/util/options_parser/options_parser.cpp b/src/mongo/util/options_parser/options_parser.cpp
index 37d7067d9c7..f4de3e2c2ff 100644
--- a/src/mongo/util/options_parser/options_parser.cpp
+++ b/src/mongo/util/options_parser/options_parser.cpp
@@ -310,6 +310,59 @@ namespace optionenvironment {
return Status::OK();
}
+ /**
+ * For all options that we registered as composable, combine the values from source and dest
+ * and set the result in dest. Note that this only works for options that are registered as
+ * vectors of strings.
+ */
+ Status addCompositions(const OptionSection& options,
+ const Environment& source,
+ Environment* dest) {
+ std::vector<OptionDescription> options_vector;
+ Status ret = options.getAllOptions(&options_vector);
+ if (!ret.isOK()) {
+ return ret;
+ }
+
+ for(std::vector<OptionDescription>::const_iterator iterator = options_vector.begin();
+ iterator != options_vector.end(); iterator++) {
+ if (iterator->_isComposing) {
+ std::vector<std::string> source_value;
+ ret = source.get(iterator->_dottedName, &source_value);
+ if (!ret.isOK() && ret != ErrorCodes::NoSuchKey) {
+ StringBuilder sb;
+ sb << "Error getting composable vector value from source: "
+ << ret.toString();
+ return Status(ErrorCodes::InternalError, sb.str());
+ }
+ // Only do something if our source environment has something to add
+ else if (ret.isOK()) {
+ std::vector<std::string> dest_value;
+ ret = dest->get(iterator->_dottedName, &dest_value);
+ if (!ret.isOK() && ret != ErrorCodes::NoSuchKey) {
+ StringBuilder sb;
+ sb << "Error getting composable vector value from dest: "
+ << ret.toString();
+ return Status(ErrorCodes::InternalError, sb.str());
+ }
+
+ // Append source_value on the end of dest_value
+ dest_value.insert(dest_value.end(),
+ source_value.begin(),
+ source_value.end());
+
+ // Set the resulting value in our output environment
+ ret = dest->set(Key(iterator->_dottedName), Value(dest_value));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ }
+ }
+ }
+
+ return Status::OK();
+ }
+
} // namespace
/**
@@ -451,6 +504,46 @@ namespace optionenvironment {
}
/**
+ * Extract default values from the given options and add to environment
+ */
+ Status OptionsParser::getDefaultValues(const OptionSection& options,
+ Environment* environment) {
+ Environment defaultEnvironment;
+
+ // This should have been caught at the time we registered our options, but we check that the
+ // default types match our declared types here just to be sure.
+ Status ret = addTypeConstraints(options, &defaultEnvironment);
+ if (!ret.isOK()) {
+ return ret;
+ }
+
+ std::map <Key, Value> defaultOptions;
+
+ ret = options.getDefaults(&defaultOptions);
+ if (!ret.isOK()) {
+ return ret;
+ }
+
+ typedef std::map<Key, Value>::iterator it_type;
+ for(it_type iterator = defaultOptions.begin();
+ iterator != defaultOptions.end(); iterator++) {
+ ret = defaultEnvironment.set(iterator->first, iterator->second);
+ if (!ret.isOK()) {
+ return ret;
+ }
+ }
+
+ ret = defaultEnvironment.validate();
+ if (!ret.isOK()) {
+ return ret;
+ }
+
+ *environment = defaultEnvironment;
+
+ return Status::OK();
+ }
+
+ /**
* Reads the entire config file into the output string. This is done this way because the JSON
* parser only takes complete strings
*/
@@ -550,10 +643,17 @@ namespace optionenvironment {
const std::map<std::string, std::string>& env, // XXX: Currently unused
Environment* environment) {
+ Environment defaultEnvironment;
Environment commandLineEnvironment;
Environment configEnvironment;
+ Environment composedEnvironment;
- Status ret = parseCommandLine(options, argv, &commandLineEnvironment);
+ Status ret = getDefaultValues(options, &defaultEnvironment);
+ if (!ret.isOK()) {
+ return ret;
+ }
+
+ ret = parseCommandLine(options, argv, &commandLineEnvironment);
if (!ret.isOK()) {
return ret;
}
@@ -602,8 +702,30 @@ namespace optionenvironment {
}
}
+ // Adds the values for all our options that were registered as composable to the composed
+ // environment. addCompositions doesn't override the values like "setAll" on our
+ // environment. Instead it aggregates the values in the result environment.
+ ret = addCompositions(options, commandLineEnvironment, &composedEnvironment);
+ if (!ret.isOK()) {
+ return ret;
+ }
+
+ ret = addCompositions(options, configEnvironment, &composedEnvironment);
+ if (!ret.isOK()) {
+ return ret;
+ }
+
+ ret = addCompositions(options, defaultEnvironment, &composedEnvironment);
+ if (!ret.isOK()) {
+ return ret;
+ }
+
// Add the values to our result in the order of override
// NOTE: This should not fail validation as we haven't called environment->validate() yet
+ ret = environment->setAll(defaultEnvironment);
+ if (!ret.isOK()) {
+ return ret;
+ }
ret = environment->setAll(configEnvironment);
if (!ret.isOK()) {
return ret;
@@ -613,6 +735,12 @@ namespace optionenvironment {
return ret;
}
+ // Add this last because it represents the aggregated results of composing all environments
+ ret = environment->setAll(composedEnvironment);
+ if (!ret.isOK()) {
+ return ret;
+ }
+
return Status::OK();
}