diff options
author | Shaun Verch <shaun.verch@10gen.com> | 2013-11-13 17:06:50 -0500 |
---|---|---|
committer | Shaun Verch <shaun.verch@10gen.com> | 2013-11-13 17:18:56 -0500 |
commit | 4290019980d65512b764c62512a61bc8c646779c (patch) | |
tree | f9134e6099aa2847d412b9f7a6057699e3047328 /src/mongo/util/options_parser | |
parent | ceecafadac2206dc402bcd5fe2a88625d3037202 (diff) | |
download | mongo-4290019980d65512b764c62512a61bc8c646779c.tar.gz |
SERVER-11575 Remove code for parsing JSON config file
Diffstat (limited to 'src/mongo/util/options_parser')
-rw-r--r-- | src/mongo/util/options_parser/option_description.h | 6 | ||||
-rw-r--r-- | src/mongo/util/options_parser/options_parser.cpp | 268 | ||||
-rw-r--r-- | src/mongo/util/options_parser/options_parser.h | 10 | ||||
-rw-r--r-- | src/mongo/util/options_parser/options_parser_test.cpp | 4 |
4 files changed, 15 insertions, 273 deletions
diff --git a/src/mongo/util/options_parser/option_description.h b/src/mongo/util/options_parser/option_description.h index 20b3fc98409..a3e332e55e0 100644 --- a/src/mongo/util/options_parser/option_description.h +++ b/src/mongo/util/options_parser/option_description.h @@ -46,10 +46,10 @@ namespace optionenvironment { enum OptionSources { SourceCommandLine = 1, SourceINIConfig = 2, - SourceJSONConfig = 4, - SourceAllConfig = SourceINIConfig | SourceJSONConfig, + SourceYAMLConfig = 4, + SourceAllConfig = SourceINIConfig | SourceYAMLConfig, SourceAllLegacy = SourceINIConfig | SourceCommandLine, - SourceAll = SourceCommandLine | SourceINIConfig | SourceJSONConfig + SourceAll = SourceCommandLine | SourceINIConfig | SourceYAMLConfig }; /** diff --git a/src/mongo/util/options_parser/options_parser.cpp b/src/mongo/util/options_parser/options_parser.cpp index 3aa81c24dea..7670b4bd524 100644 --- a/src/mongo/util/options_parser/options_parser.cpp +++ b/src/mongo/util/options_parser/options_parser.cpp @@ -46,7 +46,7 @@ namespace optionenvironment { // // These conversions are different depending on the data source because our current // implementation uses boost::program_options for the command line and INI files and the - // mongo JSON parser for JSON config files. Our destination storage in both cases is an + // yaml-cpp YAML parser for YAML config files. Our destination storage in both cases is an // Environment which stores Value objects. // // 1. YAML Config Files @@ -121,7 +121,7 @@ namespace optionenvironment { // Get expected type for (std::vector<OptionDescription>::const_iterator iterator = options_vector.begin(); iterator != options_vector.end(); iterator++) { - if (key == iterator->_dottedName && (iterator->_sources & SourceJSONConfig)) { + if (key == iterator->_dottedName && (iterator->_sources & SourceYAMLConfig)) { isRegistered = true; type = iterator->_type; } @@ -280,77 +280,6 @@ namespace optionenvironment { return Status::OK(); } - // Check if the given key is registered in our OptionDescription. This is needed for JSON - // Config File handling since the JSON parser just reads in whatever fields and values it - // sees without taking a description of what to look for. - Status isRegistered(const std::vector<OptionDescription>& options_vector, const Key& key) { - - for(std::vector<OptionDescription>::const_iterator iterator = options_vector.begin(); - iterator != options_vector.end(); iterator++) { - if (key == iterator->_dottedName && (iterator->_sources & SourceJSONConfig)) { - return Status::OK(); - } - } - StringBuilder sb; - sb << "Unrecognized option: " << key; - return Status(ErrorCodes::BadValue, sb.str()); - } - - // Convert a BSONElement to a Value. See comments at the beginning of this section. - Status BSONElementToValue(const BSONElement& element, Value* value) { - - std::vector<BSONElement> elements; - std::vector<std::string> valueStrings; - try { - switch (element.type()) { - case ::mongo::NumberInt: - *value = Value(element.Int()); - return Status::OK(); - case ::mongo::NumberDouble: - *value = Value(element.Double()); - return Status::OK(); - case ::mongo::NumberLong: - // FIXME: Figure out how to stop this, or detect overflow - *value = Value(static_cast<unsigned long long>(element.Long())); - return Status::OK(); - case ::mongo::String: - *value = Value(element.String()); - return Status::OK(); - case ::mongo::Array: - elements = element.Array(); - for(std::vector<BSONElement>::const_iterator iterator = elements.begin(); - iterator != elements.end(); iterator++) { - if (iterator->type() == ::mongo::String) { - valueStrings.push_back(iterator->String()); - } - else { - StringBuilder sb; - sb << "Arrays can only contain strings in JSON Config File"; - return Status(ErrorCodes::BadValue, sb.str()); - } - } - *value = Value(valueStrings); - return Status::OK(); - case ::mongo::Bool: - *value = Value(element.Bool()); - return Status::OK(); - case ::mongo::EOO: - return Status(ErrorCodes::InternalError, - "Error converting BSONElement to value; BSONElement empty"); - default: - StringBuilder sb; - sb << "Conversion from BSONElement type: " << - element.type() << " not supported."; - return Status(ErrorCodes::TypeMismatch, sb.str()); - } - } - catch ( std::exception &e ) { - StringBuilder sb; - sb << "Exception thrown by BSON conversion: " << e.what(); - return Status(ErrorCodes::InternalError, sb.str()); - } - } - // Add all the values in the given YAML Node to our environment. See comments at the // beginning of this section. Status addYAMLNodesToEnvironment(const YAML::Node& root, @@ -427,140 +356,6 @@ namespace optionenvironment { return Status::OK(); } - // Add all the values in the given BSONObj to our environment. See comments at the - // beginning of this section. - Status addBSONElementsToEnvironment(const BSONObj& obj, - const OptionSection& options, - const std::string parentPath, - Environment* environment) { - - std::vector<OptionDescription> options_vector; - Status ret = options.getAllOptions(&options_vector); - if (!ret.isOK()) { - return ret; - } - - BSONObjIterator iterator(obj); - while (iterator.more()) { - BSONElement elem = iterator.next(); - string fieldName= elem.fieldName(); - - // The following code should allow the following comment styles: - // { "option" : { "value" : <value>, "comment" : "comment string" } } - // { "option" : <value>, "comment" : "comment string" } - - // Ignore fields with a name of "comment" - if (fieldName == "comment") { - continue; - } - - std::string dottedName; - if (parentPath.empty()) { - // We are at the top level, so the full specifier is just the current field name - dottedName = fieldName; - } - else { - // If our field name is "value", assume this contains the value for the parent - if (fieldName == "value") { - dottedName = parentPath; - } - // If this is not a special field name, and we are in a sub object, append our - // current fieldName to the selector for the sub object we are traversing - else { - dottedName = parentPath + '.' + fieldName; - } - } - - if (elem.type() == ::mongo::Object) { - addBSONElementsToEnvironment( elem.Obj(), options, dottedName, environment ); - } - else { - Value optionValue; - Status ret = BSONElementToValue(elem, &optionValue); - if (!ret.isOK()) { - return ret; - } - - ret = isRegistered(options_vector, dottedName); - if (!ret.isOK()) { - return ret; - } - - Value dummyVal; - if (environment->get(dottedName, &dummyVal).isOK()) { - StringBuilder sb; - sb << "Error parsing JSON config: duplcate key: " << dottedName; - return Status(ErrorCodes::BadValue, sb.str()); - } - - ret = environment->set(dottedName, optionValue); - if (!ret.isOK()) { - return ret; - } - } - } - - return Status::OK(); - } - - // Iterate through our options and add type constraints to our environment based on what - // types the options were registered with. This is needed for the JSON config file - // handling, since the JSON parser just reads the types without checking them. Currently, - // the boost parsers check the types for us. - Status addTypeConstraints(const OptionSection& options, Environment* environment) { - - 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++) { - switch (iterator->_type) { - case StringVector: - environment->addKeyConstraint( - new TypeKeyConstraint<std::vector<std::string> >(iterator->_dottedName)); - break; - case Bool: - environment->addKeyConstraint( - new TypeKeyConstraint<bool>(iterator->_dottedName)); - break; - case Double: - environment->addKeyConstraint( - new TypeKeyConstraint<double>(iterator->_dottedName)); - break; - case Int: - environment->addKeyConstraint( - new TypeKeyConstraint<int>(iterator->_dottedName)); - break; - case Long: - environment->addKeyConstraint( - new TypeKeyConstraint<long>(iterator->_dottedName)); - break; - case String: - environment->addKeyConstraint( - new TypeKeyConstraint<std::string>(iterator->_dottedName)); - break; - case UnsignedLongLong: - environment->addKeyConstraint( - new TypeKeyConstraint<unsigned long long>(iterator->_dottedName)); - break; - case Unsigned: - environment->addKeyConstraint( - new TypeKeyConstraint<unsigned>(iterator->_dottedName)); - break; - case Switch: - environment->addKeyConstraint( - new TypeKeyConstraint<bool>(iterator->_dottedName)); - break; - default: /* XXX: should not get here */ - return Status(ErrorCodes::InternalError, "Unrecognized option type"); - } - } - 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 @@ -620,6 +415,7 @@ namespace optionenvironment { */ Status addConstraints(const OptionSection& options, Environment* dest) { std::vector<boost::shared_ptr<Constraint> > constraints_vector; + Status ret = options.getConstraints(&constraints_vector); if (!ret.isOK()) { return ret; @@ -801,37 +597,6 @@ namespace { } // namespace /** - * This function delegates the JSON config parsing to the MongoDB JSON parser. - * - * 1. Parse JSON - * 2. Add all elements from the resulting BSONObj to the Environment - * - * This function checks for duplicates and unregistered options, but the caller is responsible - * for checking that the options are the correct types - * - * Also note that the size of our JSON config file is limited in size. The equivalent BSON - * object can only be 16MB. We catch the exception that is thrown in this case and return an - * error Status from this function - */ - Status OptionsParser::parseJSONConfigFile(const OptionSection& options, - const std::string& config, - Environment* environment) { - BSONObj BSONConfig; - try { - BSONConfig = fromjson(config); - Status ret = addBSONElementsToEnvironment(BSONConfig, options, "", environment); - if (!ret.isOK()) { - return ret; - } - } catch ( MsgAssertionException& e ) { - StringBuilder sb; - sb << "Error parsing JSON config file: " << e.what(); - return Status(ErrorCodes::BadValue, sb.str()); - } - return Status::OK(); - } - - /** * Add default values from the given OptionSection to the given Environment */ Status OptionsParser::addDefaultValues(const OptionSection& options, @@ -856,8 +621,10 @@ namespace { } /** - * Reads the entire config file into the output string. This is done this way because the JSON - * parser only takes complete strings + * Reads the entire config file into the output string. This was done this way because the JSON + * parser only takes complete strings, and we were using that to parse the config file before. + * We could redesign the parser to use some kind of streaming interface, but for now this is + * simple and works for the current use case of config files which should be limited in size. */ Status OptionsParser::readConfigFile(const std::string& filename, std::string* contents) { @@ -919,25 +686,6 @@ namespace { return Status::OK(); } - bool OptionsParser::isJSONConfig(const std::string& config) { - for (std::string::const_iterator curChar = config.begin(); - curChar < config.end(); curChar++) { - if (isspace(*curChar)) { - // Skip whitespace - } - else if (*curChar == '{') { - // If first non whitespace character is '{', then this is a JSON config file - return true; - } - else { - // Otherwise, this is a legacy INI config file - return false; - } - } - // Treat the empty config file as INI - return false; - } - /** * Run the OptionsParser * @@ -946,7 +694,7 @@ namespace { * 1. Parse argc and argv using the given OptionSection as a description of expected options * 2. Check for a "config" argument * 3. If "config" found, read config file - * 4. Detect config file type (JSON or INI) + * 4. Detect config file type (YAML or INI) * 5. Parse config file using the given OptionSection as a description of expected options * 6. Add the results to the output Environment in the proper order to ensure correct precedence */ diff --git a/src/mongo/util/options_parser/options_parser.h b/src/mongo/util/options_parser/options_parser.h index d7e0b44235b..03ae98a903b 100644 --- a/src/mongo/util/options_parser/options_parser.h +++ b/src/mongo/util/options_parser/options_parser.h @@ -28,7 +28,7 @@ namespace optionenvironment { class OptionSection; class Value; - /** Handles parsing of the command line as well as JSON and INI config files. Takes an + /** Handles parsing of the command line as well as YAML and INI config files. Takes an * OptionSection instance that describes the allowed options, parses argv (env not yet * supported), and populates an Environment with the results. * @@ -75,7 +75,7 @@ namespace optionenvironment { OptionsParser() { } virtual ~OptionsParser() { } - /** Handles parsing of the command line as well as JSON and INI config files. The + /** Handles parsing of the command line as well as YAML and INI config files. The * OptionSection be a description of the allowed options. This function populates the * given Environment with the results of parsing the command line and or config files but * does not call validate on the Environment. @@ -98,15 +98,9 @@ namespace optionenvironment { /** Handles parsing of an INI config string and adds the results to the given Environment */ Status parseINIConfigFile(const OptionSection&, const std::string& config, Environment*); - /** Handles parsing of a JSON config string and adds the results to the given Environment */ - Status parseJSONConfigFile(const OptionSection&, const std::string& config, Environment*); - /** Gets defaults from the OptionSection and adds them to the given Environment */ Status addDefaultValues(const OptionSection&, Environment*); - /** Detects whether the given string represents a JSON config file or an INI config file */ - bool isJSONConfig(const std::string& config); - /** Reads the given config file into the output string. This function is virtual for * testing purposes only. */ virtual Status readConfigFile(const std::string& filename, std::string*); diff --git a/src/mongo/util/options_parser/options_parser_test.cpp b/src/mongo/util/options_parser/options_parser_test.cpp index 5ebe022638f..a5940ff5481 100644 --- a/src/mongo/util/options_parser/options_parser_test.cpp +++ b/src/mongo/util/options_parser/options_parser_test.cpp @@ -2128,7 +2128,7 @@ namespace { } - TEST(OptionSources, SourceJSONConfig) { + TEST(OptionSources, SourceYAMLConfig) { OptionsParserTester parser; moe::Environment environment; moe::Value value; @@ -2139,7 +2139,7 @@ namespace { moe::OptionSection testOpts; testOpts.addOptionChaining("config", "config", moe::String, "Config file to parse"); testOpts.addOptionChaining("parameter", "parameter", moe::String, "Parameter") - .setSources(moe::SourceJSONConfig); + .setSources(moe::SourceYAMLConfig); argv.clear(); argv.push_back("binaryname"); |