summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShaun Verch <shaun.verch@10gen.com>2013-08-14 11:54:01 -0400
committerShaun Verch <shaun.verch@10gen.com>2013-09-05 13:49:35 -0400
commit03ca1e173f4ad480a817d542780035532a4efb0f (patch)
treec247110abd231bee71e20abc8f3cd4129fa6550c
parentea40937c304ad77884cc3087b491de502dca66b6 (diff)
downloadmongo-03ca1e173f4ad480a817d542780035532a4efb0f.tar.gz
SERVER-8510 Use new option parser in mongod and mongos and move parsing into MONGO_INITIALIZERS
-rw-r--r--src/mongo/SConscript20
-rw-r--r--src/mongo/db/cmdline.cpp541
-rw-r--r--src/mongo/db/cmdline.h36
-rw-r--r--src/mongo/db/cmdline_test.cpp48
-rw-r--r--src/mongo/db/db.cpp414
-rw-r--r--src/mongo/db/mongod_options.cpp367
-rw-r--r--src/mongo/db/mongod_options.h30
-rw-r--r--src/mongo/db/server_options.cpp293
-rw-r--r--src/mongo/db/server_options.h34
-rw-r--r--src/mongo/dbtests/basictests.cpp20
-rw-r--r--src/mongo/s/mongos_options.cpp126
-rw-r--r--src/mongo/s/mongos_options.h30
-rw-r--r--src/mongo/s/server.cpp127
-rw-r--r--src/mongo/shell/dbshell.cpp4
-rw-r--r--src/mongo/util/ntservice.cpp3
-rw-r--r--src/mongo/util/ntservice.h10
-rw-r--r--src/mongo/util/options_parser/options_parser_test.cpp33
17 files changed, 1480 insertions, 656 deletions
diff --git a/src/mongo/SConscript b/src/mongo/SConscript
index f9808bddaab..58b3966fb78 100644
--- a/src/mongo/SConscript
+++ b/src/mongo/SConscript
@@ -374,7 +374,9 @@ coreServerFiles = [ "db/client_basic.cpp",
"db/stats/service_stats.cpp",
]
-env.StaticLibrary('ntservice', ['util/ntservice.cpp'], LIBDEPS=['foundation'])
+env.StaticLibrary('ntservice', ['util/ntservice.cpp'],
+ LIBDEPS=['foundation',
+ '$BUILD_DIR/mongo/util/options_parser/options_parser'])
if windows:
env.CppUnitTest('ntservice_test', 'util/ntservice_test.cpp',
LIBDEPS=['ntservice'],
@@ -562,8 +564,16 @@ serverOnlyFiles = [ "db/curop.cpp",
"db/pipeline/document_source_cursor.cpp",
"db/driverHelpers.cpp" ]
-env.Library( "dbcmdline", "db/cmdline.cpp", LIBDEPS=['bson', 'server_parameters'] )
-env.CppUnitTest('cmdline_test', 'db/cmdline_test.cpp', LIBDEPS=['dbcmdline'])
+env.Library("dbcmdline", ["db/cmdline.cpp", "db/server_options.cpp"],
+ LIBDEPS=['bson',
+ 'server_parameters',
+ '$BUILD_DIR/mongo/util/options_parser/options_parser',
+ ])
+env.CppUnitTest('cmdline_test', 'db/cmdline_test.cpp',
+ LIBDEPS=['bson',
+ 'dbcmdline',
+ '$BUILD_DIR/mongo/util/options_parser/options_parser',
+ ])
env.CppUnitTest('diskloc_test', 'db/diskloc_test.cpp', LIBDEPS=[])
@@ -765,7 +775,7 @@ env.StaticLibrary("mongodwebserver",
],
LIBDEPS=["coredb", "mongodandmongos"])
-mongodOnlyFiles = [ "db/db.cpp", "db/commands/touch.cpp", ]
+mongodOnlyFiles = [ "db/db.cpp", "db/commands/touch.cpp", "db/mongod_options.cpp" ]
# ----- TARGETS ------
@@ -817,7 +827,7 @@ env.Install( '#/', [
# mongos
mongos = env.Program(
- "mongos", [ "s/server.cpp"] ,
+ "mongos", [ "s/server.cpp", "s/mongos_options.cpp" ] ,
LIBDEPS=["mongoscore", "coreserver", "coredb", "mongocommon", "coreshard", "dbcmdline", "ntservice",
"mongodandmongos", "s/upgrade"])
env.Install( '#/', mongos )
diff --git a/src/mongo/db/cmdline.cpp b/src/mongo/db/cmdline.cpp
index 16e89d4c861..517e149b7b2 100644
--- a/src/mongo/db/cmdline.cpp
+++ b/src/mongo/db/cmdline.cpp
@@ -29,6 +29,9 @@
#include "mongo/util/map_util.h"
#include "mongo/util/mongoutils/str.h"
#include "mongo/util/net/listen.h"
+#include "mongo/util/options_parser/environment.h"
+#include "mongo/util/options_parser/option_section.h"
+#include "mongo/util/options_parser/options_parser.h"
#include "mongo/util/password.h"
#ifdef _WIN32
@@ -39,10 +42,10 @@
#include <fstream>
-namespace po = boost::program_options;
-
namespace mongo {
+ namespace moe = mongo::optionenvironment;
+
#ifdef _WIN32
string dbpath = "\\data\\db\\";
#else
@@ -65,253 +68,227 @@ namespace {
return parsedOpts;
}
- void CmdLine::addGlobalOptions( boost::program_options::options_description& general ,
- boost::program_options::options_description& hidden ,
- boost::program_options::options_description& ssl_options ) {
- /* support for -vv -vvvv etc. */
- for (string s = "vv"; s.length() <= 12; s.append("v")) {
- hidden.add_options()(s.c_str(), "verbose");
- }
-
- StringBuilder portInfoBuilder;
- StringBuilder maxConnInfoBuilder;
-
- portInfoBuilder << "specify port number - " << DefaultDBPort << " by default";
- maxConnInfoBuilder << "max number of simultaneous connections - " << DEFAULT_MAX_CONN << " by default";
-
- general.add_options()
- ("help,h", "show this usage information")
- ("version", "show version information")
- ("config,f", po::value<string>(), "configuration file specifying additional options")
- ("verbose,v", "be more verbose (include multiple times for more verbosity e.g. -vvvvv)")
- ("quiet", "quieter output")
- ("port", po::value<int>(), portInfoBuilder.str().c_str())
- ("bind_ip", po::value<string>(), "comma separated list of ip addresses to listen on - all local ips by default")
- ("maxConns",po::value<int>(), maxConnInfoBuilder.str().c_str())
- ("logpath", po::value<string>() , "log file to send write to instead of stdout - has to be a file, not directory" )
- ("logappend" , "append to logpath instead of over-writing" )
- ("logTimestampFormat", po::value<string>(), "Desired format for timestamps in log "
- "messages. One of ctime, iso8601-utc or iso8601-local")
- ("pidfilepath", po::value<string>(), "full path to pidfile (if not set, no pidfile is created)")
- ("keyFile", po::value<string>(), "private key for cluster authentication")
- ("setParameter", po::value< std::vector<std::string> >()->composing(),
- "Set a configurable parameter")
- ("httpinterface", "enable http interface")
- ("clusterAuthMode", po::value<std::string>(),
- "Authentication mode used for cluster authentication."
- " Alternatives are (keyfile|sendKeyfile|sendX509|x509)")
-#ifndef _WIN32
- ("nounixsocket", "disable listening on unix sockets")
- ("unixSocketPrefix", po::value<string>(), "alternative directory for UNIX domain sockets (defaults to /tmp)")
- ("fork" , "fork server process" )
- ("syslog" , "log to system's syslog facility instead of file or stdout" )
-#endif
- ;
-
+ Status CmdLine::setupBinaryName(const std::vector<std::string>& argv) {
-#ifdef MONGO_SSL
- ssl_options.add_options()
- ("sslOnNormalPorts" , "use ssl on configured ports" )
- ("sslPEMKeyFile" , po::value<string>(), "PEM file for ssl" )
- ("sslPEMKeyPassword" , po::value<string>()->implicit_value(""),
- "PEM file password" )
- ("sslClusterFile", po::value<string>(),
- "Key file for internal SSL authentication" )
- ("sslClusterPassword", po::value<string>()->implicit_value(""),
- "Internal authentication key file password" )
- ("sslCAFile", po::value<std::string>(),
- "Certificate Authority file for SSL")
- ("sslCRLFile", po::value<std::string>(),
- "Certificate Revocation List file for SSL")
- ("sslWeakCertificateValidation", "allow client to connect without presenting a certificate")
- ("sslFIPSMode", "activate FIPS 140-2 mode at startup")
+ if (argv.empty()) {
+ return Status(ErrorCodes::InternalError, "Cannot get binary name: argv array is empty");
+ }
+
+ // setup binary name
+ cmdLine.binaryName = argv[0];
+ size_t i = cmdLine.binaryName.rfind( '/' );
+ if ( i != string::npos ) {
+ cmdLine.binaryName = cmdLine.binaryName.substr( i + 1 );
+ }
+ return Status::OK();
+ }
+
+ Status CmdLine::setupCwd() {
+ // setup cwd
+ char buffer[1024];
+#ifdef _WIN32
+ verify( _getcwd( buffer , 1000 ) );
+#else
+ verify( getcwd( buffer , 1000 ) );
#endif
- ;
-
- // Extra hidden options
- hidden.add_options()
- ("nohttpinterface", "disable http interface")
- ("objcheck", "inspect client data for validity on receipt (DEFAULT)")
- ("noobjcheck", "do NOT inspect client data for validity on receipt")
- ("traceExceptions", "log stack traces for every exception")
- ("enableExperimentalIndexStatsCmd", po::bool_switch(),
- "EXPERIMENTAL (UNSUPPORTED). Enable command computing aggregate statistics on indexes.")
- ("enableExperimentalStorageDetailsCmd", po::bool_switch(),
- "EXPERIMENTAL (UNSUPPORTED). Enable command computing aggregate statistics on storage.")
- ;
+ cmdLine.cwd = buffer;
+ return Status::OK();
}
-#if defined(_WIN32)
- void CmdLine::addWindowsOptions( boost::program_options::options_description& windows ,
- boost::program_options::options_description& hidden ) {
- windows.add_options()
- ("install", "install Windows service")
- ("remove", "remove Windows service")
- ("reinstall", "reinstall Windows service (equivalent to --remove followed by --install)")
- ("serviceName", po::value<string>(), "Windows service name")
- ("serviceDisplayName", po::value<string>(), "Windows service display name")
- ("serviceDescription", po::value<string>(), "Windows service description")
- ("serviceUser", po::value<string>(), "account for service execution")
- ("servicePassword", po::value<string>(), "password used to authenticate serviceUser")
- ;
- hidden.add_options()("service", "start mongodb service");
+ Status CmdLine::setArgvArray(const std::vector<std::string>& argv) {
+ BSONArrayBuilder b;
+ std::vector<std::string> censoredArgv = argv;
+ censor(&censoredArgv);
+ for (size_t i=0; i < censoredArgv.size(); i++) {
+ b << censoredArgv[i];
+ }
+ argvArray = b.arr();
+ return Status::OK();
}
-#endif
- bool CmdLine::parseConfigFile( istream &f, stringstream &ss ) {
- string s;
- char line[MAX_LINE_LENGTH];
+namespace {
- while ( !f.eof() ) {
- f.getline(line, MAX_LINE_LENGTH);
- // Check if we failed to read from the stream for a reason other than eof
- if ( f.fail() && !f.eof() ) {
- return false;
+ // Converts a map of values with dotted key names to a BSONObj with sub objects.
+ // 1. Check for dotted field names and call valueMapToBSON recursively.
+ // 2. Append the actual value to our builder if we did not find a dot in our key name.
+ Status valueMapToBSON(const std::map<moe::Key, moe::Value>& params,
+ BSONObjBuilder* builder,
+ const std::string& prefix = std::string()) {
+ for (std::map<moe::Key, moe::Value>::const_iterator it(params.begin());
+ it != params.end(); it++) {
+ moe::Key key = it->first;
+ moe::Value value = it->second;
+
+ // 1. Check for dotted field names and call valueMapToBSON recursively.
+ // NOTE: this code depends on the fact that std::map is sorted
+ //
+ // EXAMPLE:
+ // The map:
+ // {
+ // "var1.dotted1" : false,
+ // "var2" : true,
+ // "var1.dotted2" : 6
+ // }
+ //
+ // Gets sorted by keys as:
+ // {
+ // "var1.dotted1" : false,
+ // "var1.dotted2" : 6,
+ // "var2" : true
+ // }
+ //
+ // Which means when we see the "var1" prefix, we can iterate until we see either a name
+ // without a dot or without "var1" as a prefix, aggregating its fields in a new map as
+ // we go. Because the map is sorted, once we see a name without a dot or a "var1"
+ // prefix we know that we've seen everything with "var1" as a prefix and can recursively
+ // build the entire sub object at once using our new map (which is the only way to make
+ // a single coherent BSON sub object using this append only builder).
+ //
+ // The result of this function for this example should be a BSON object of the form:
+ // {
+ // "var1" : {
+ // "dotted1" : false,
+ // "dotted2" : 6
+ // },
+ // "var2" : true
+ // }
+
+ // Check to see if this key name is dotted
+ std::string::size_type dotOffset = key.find('.');
+ if (dotOffset != string::npos) {
+
+ // Get the name of the "section" that we are currently iterating. This will be
+ // the name of our sub object.
+ std::string sectionName = key.substr(0, dotOffset);
+
+ // Build a map of the "section" that we are iterating to be passed in a
+ // recursive call.
+ std::map<moe::Key, moe::Value> sectionMap;
+
+ std::string beforeDot = key.substr(0, dotOffset);
+ std::string afterDot = key.substr(dotOffset + 1, key.size() - dotOffset - 1);
+ std::map<moe::Key, moe::Value>::const_iterator it_next = it;
+
+ do {
+ // Here we know that the key at it_next has a dot and has the prefix we are
+ // currently creating a sub object for. Since that means we will definitely
+ // process that element in this loop, advance the outer for loop iterator here.
+ it = it_next;
+
+ // Add the value to our section map with a key of whatever is after the dot
+ // since the section name itself will be part of our sub object builder.
+ sectionMap[afterDot] = value;
+
+ // Peek at the next value for our iterator and check to see if we've finished.
+ if (++it_next == params.end()) {
+ break;
+ }
+ key = it_next->first;
+ value = it_next->second;
+
+ // Look for a dot for our next iteration.
+ dotOffset = key.find('.');
+
+ beforeDot = key.substr(0, dotOffset);
+ afterDot = key.substr(dotOffset + 1, key.size() - dotOffset - 1);
+ }
+ while (dotOffset != string::npos && beforeDot == sectionName);
+
+ // Use the section name in our object builder, and recursively call
+ // valueMapToBSON with our sub map with keys that have the section name removed.
+ BSONObjBuilder sectionObjBuilder(builder->subobjStart(sectionName));
+ valueMapToBSON(sectionMap, &sectionObjBuilder, sectionName);
+ sectionObjBuilder.done();
+
+ // Our iterator is currently on the last field that matched our dot and prefix, so
+ // continue to the next loop iteration.
+ continue;
}
- s = line;
- std::remove(s.begin(), s.end(), ' ');
- std::remove(s.begin(), s.end(), '\t');
- boost::to_upper(s);
-
- if ( s.find( "FASTSYNC" ) != string::npos )
- cout << "warning \"fastsync\" should not be put in your configuration file" << endl;
-
- if ( s.c_str()[0] == '#' ) {
- // skipping commented line
- } else if ( s.find( "=FALSE" ) == string::npos ) {
- ss << line << endl;
- } else {
- cout << "warning: remove or comment out this line by starting it with \'#\', skipping now : " << line << endl;
+
+ // 2. Append the actual value to our builder if we did not find a dot in our key name.
+ const type_info& type = value.type();
+
+ if (type == typeid(string)){
+ if (value.as<string>().empty()) {
+ // boost po uses empty string for flags like --quiet
+ // TODO: Remove this when we remove boost::program_options
+ builder->appendBool(key, true);
+ }
+ else {
+ if ( _isPasswordArgument(key.c_str()) ) {
+ builder->append( key, "<password>" );
+ }
+ else {
+ builder->append( key, value.as<string>() );
+ }
+ }
}
+ else if (type == typeid(int))
+ builder->append(key, value.as<int>());
+ else if (type == typeid(double))
+ builder->append(key, value.as<double>());
+ else if (type == typeid(bool))
+ builder->appendBool(key, value.as<bool>());
+ else if (type == typeid(long))
+ builder->appendNumber(key, (long long)value.as<long>());
+ else if (type == typeid(unsigned))
+ builder->appendNumber(key, (long long)value.as<unsigned>());
+ else if (type == typeid(unsigned long long))
+ builder->appendNumber(key, (long long)value.as<unsigned long long>());
+ else if (type == typeid(vector<string>))
+ builder->append(key, value.as<vector<string> >());
+ else
+ builder->append(key, "UNKNOWN TYPE: " + demangleName(type));
+ }
+ return Status::OK();
+ }
+} // namespace
+
+ Status CmdLine::setParsedOpts(moe::Environment& params) {
+ const std::map<moe::Key, moe::Value> paramsMap = params.getExplicitlySet();
+ BSONObjBuilder builder;
+ Status ret = valueMapToBSON(paramsMap, &builder);
+ if (!ret.isOK()) {
+ return ret;
}
- return true;
+ parsedOpts = builder.obj();
+ return Status::OK();
}
- bool CmdLine::store( const std::vector<std::string>& argv,
- boost::program_options::options_description& visible,
- boost::program_options::options_description& hidden,
- boost::program_options::positional_options_description& positional,
- boost::program_options::variables_map &params ) {
+ Status CmdLine::store( const std::vector<std::string>& argv,
+ moe::OptionSection& options,
+ moe::Environment& params ) {
+ Status ret = CmdLine::setupBinaryName(argv);
+ if (!ret.isOK()) {
+ return ret;
+ }
- if (argv.empty())
- return false;
+ ret = CmdLine::setupCwd();
+ if (!ret.isOK()) {
+ return ret;
+ }
- {
- // setup binary name
- cmdLine.binaryName = argv[0];
- size_t i = cmdLine.binaryName.rfind( '/' );
- if ( i != string::npos )
- cmdLine.binaryName = cmdLine.binaryName.substr( i + 1 );
-
- // setup cwd
- char buffer[1024];
-#ifdef _WIN32
- verify( _getcwd( buffer , 1000 ) );
-#else
- verify( getcwd( buffer , 1000 ) );
-#endif
- cmdLine.cwd = buffer;
- }
-
-
- /* don't allow guessing - creates ambiguities when some options are
- * prefixes of others. allow long disguises and don't allow guessing
- * to get away with our vvvvvvv trick. */
- int style = (((po::command_line_style::unix_style ^
- po::command_line_style::allow_guessing) |
- po::command_line_style::allow_long_disguise) ^
- po::command_line_style::allow_sticky);
-
-
- try {
-
- po::options_description all;
- all.add( visible );
- all.add( hidden );
-
- po::store( po::command_line_parser(std::vector<std::string>(argv.begin() + 1,
- argv.end()))
- .options( all )
- .positional( positional )
- .style( style )
- .run(),
- params );
-
- if ( params.count("config") ) {
- ifstream f( params["config"].as<string>().c_str() );
- if ( ! f.is_open() ) {
- cout << "ERROR: could not read from config file" << endl << endl;
- cout << visible << endl;
- return false;
- }
+ moe::OptionsParser parser;
- stringstream ss;
- if ( !CmdLine::parseConfigFile( f, ss ) ) {
- cout << "ERROR: could not read from config file" << endl << endl;
- cout << visible << endl;
- return false;
- }
- po::store( po::parse_config_file( ss , all ) , params );
- f.close();
- }
+ // XXX: env is not used in the parser at this point, so just leave it empty
+ std::map<std::string, std::string> env;
+
+ ret = parser.run(options, argv, env, &params);
+ if (!ret.isOK()) {
+ std::cerr << "Error parsing command line: " << ret.toString() << std::endl;
+ std::cerr << "use --help for help" << std::endl;
+ return ret;
}
- catch (po::error &e) {
- cout << "error command line: " << e.what() << endl;
- cout << "use --help for help" << endl;
- //cout << visible << endl;
- return false;
+
+ ret = CmdLine::setArgvArray(argv);
+ if (!ret.isOK()) {
+ return ret;
}
- {
- BSONArrayBuilder b;
- std::vector<std::string> censoredArgv = argv;
- censor(&censoredArgv);
- for (size_t i=0; i < censoredArgv.size(); i++) {
- b << censoredArgv[i];
- }
- argvArray = b.arr();
- }
-
- {
- BSONObjBuilder b;
- for (po::variables_map::const_iterator it(params.begin()), end(params.end()); it != end; it++){
- if (!it->second.defaulted()){
- const string& key = it->first;
- const po::variable_value& value = it->second;
- const type_info& type = value.value().type();
-
- if (type == typeid(string)){
- if (value.as<string>().empty())
- b.appendBool(key, true); // boost po uses empty string for flags like --quiet
- else {
- if ( _isPasswordArgument(key.c_str()) ) {
- b.append( key, "<password>" );
- }
- else {
- b.append( key, value.as<string>() );
- }
- }
- }
- else if (type == typeid(int))
- b.append(key, value.as<int>());
- else if (type == typeid(double))
- b.append(key, value.as<double>());
- else if (type == typeid(bool))
- b.appendBool(key, value.as<bool>());
- else if (type == typeid(long))
- b.appendNumber(key, (long long)value.as<long>());
- else if (type == typeid(unsigned))
- b.appendNumber(key, (long long)value.as<unsigned>());
- else if (type == typeid(unsigned long long))
- b.appendNumber(key, (long long)value.as<unsigned long long>());
- else if (type == typeid(vector<string>))
- b.append(key, value.as<vector<string> >());
- else
- b.append(key, "UNKNOWN TYPE: " + demangleName(type));
- }
- }
- parsedOpts = b.obj();
+ ret = CmdLine::setParsedOpts(params);
+ if (!ret.isOK()) {
+ return ret;
}
if (params.count("verbose")) {
@@ -356,8 +333,7 @@ namespace {
cmdLine.maxConns = params["maxConns"].as<int>();
if ( cmdLine.maxConns < 5 ) {
- out() << "maxConns has to be at least 5" << endl;
- return false;
+ return Status(ErrorCodes::BadValue, "maxConns has to be at least 5");
}
}
@@ -366,8 +342,7 @@ namespace {
}
if (params.count("noobjcheck")) {
if (params.count("objcheck")) {
- out() << "can't have both --objcheck and --noobjcheck" << endl;
- return false;
+ return Status(ErrorCodes::BadValue, "can't have both --objcheck and --noobjcheck");
}
cmdLine.objcheck = false;
}
@@ -407,29 +382,27 @@ namespace {
MessageEventDetailsEncoder::setDateFormatter(dateToISOStringLocal);
}
else {
- cout << "Value of logTimestampFormat must be one of ctime, iso8601-utc or "
- "iso8601-local; not \"" << formatterName << "\"." << endl;
- return false;
+ StringBuilder sb;
+ sb << "Value of logTimestampFormat must be one of ctime, iso8601-utc " <<
+ "or iso8601-local; not \"" << formatterName << "\".";
+ return Status(ErrorCodes::BadValue, sb.str());
}
}
if (params.count("logpath")) {
cmdLine.logpath = params["logpath"].as<string>();
if (cmdLine.logpath.empty()) {
- cout << "logpath cannot be empty if supplied" << endl;
- return false;
+ return Status(ErrorCodes::BadValue, "logpath cannot be empty if supplied");
}
}
cmdLine.logWithSyslog = params.count("syslog");
cmdLine.logAppend = params.count("logappend");
if (!cmdLine.logpath.empty() && cmdLine.logWithSyslog) {
- cout << "Cant use both a logpath and syslog " << endl;
- return false;
+ return Status(ErrorCodes::BadValue, "Cant use both a logpath and syslog ");
}
if (cmdLine.doFork && cmdLine.logpath.empty() && !cmdLine.logWithSyslog) {
- cout << "--fork has to be used with --logpath or --syslog" << endl;
- return false;
+ return Status(ErrorCodes::BadValue, "--fork has to be used with --logpath or --syslog");
}
if (params.count("keyFile")) {
@@ -447,27 +420,29 @@ namespace {
std::string name;
std::string value;
if (!mongoutils::str::splitOn(parameters[i], '=', name, value)) {
- cout << "Illegal option assignment: \"" << parameters[i] << "\"" << endl;
- return false;
+ StringBuilder sb;
+ sb << "Illegal option assignment: \"" << parameters[i] << "\"";
+ return Status(ErrorCodes::BadValue, sb.str());
}
ServerParameter* parameter = mapFindWithDefault(
ServerParameterSet::getGlobal()->getMap(),
name,
static_cast<ServerParameter*>(NULL));
if (NULL == parameter) {
- cout << "Illegal --setParameter parameter: \"" << name << "\"" << endl;
- return false;
+ StringBuilder sb;
+ sb << "Illegal --setParameter parameter: \"" << name << "\"";
+ return Status(ErrorCodes::BadValue, sb.str());
}
if (!parameter->allowedToChangeAtStartup()) {
- cout << "Cannot use --setParameter to set \"" << name << "\" at startup" <<
- endl;
- return false;
+ StringBuilder sb;
+ sb << "Cannot use --setParameter to set \"" << name << "\" at startup";
+ return Status(ErrorCodes::BadValue, sb.str());
}
Status status = parameter->setFromString(value);
if (!status.isOK()) {
- cout << "Bad value for parameter \"" << name << "\": " << status.reason()
- << endl;
- return false;
+ StringBuilder sb;
+ sb << "Bad value for parameter \"" << name << "\": " << status.reason();
+ return Status(ErrorCodes::BadValue, sb.str());
}
}
}
@@ -477,50 +452,49 @@ namespace {
#ifdef MONGO_SSL
- if (params.count("sslPEMKeyFile")) {
- cmdLine.sslPEMKeyFile = params["sslPEMKeyFile"].as<string>();
+ if (params.count("ssl.PEMKeyFile")) {
+ cmdLine.sslPEMKeyFile = params["ssl.PEMKeyFile"].as<string>();
}
- if (params.count("sslPEMKeyPassword")) {
- cmdLine.sslPEMKeyPassword = params["sslPEMKeyPassword"].as<string>();
+ if (params.count("ssl.PEMKeyPassword")) {
+ cmdLine.sslPEMKeyPassword = params["ssl.PEMKeyPassword"].as<string>();
}
- if (params.count("sslClusterFile")) {
- cmdLine.sslClusterFile = params["sslClusterFile"].as<string>();
+ if (params.count("ssl.clusterFile")) {
+ cmdLine.sslClusterFile = params["ssl.clusterFile"].as<string>();
}
- if (params.count("sslClusterPassword")) {
- cmdLine.sslClusterPassword = params["sslClusterPassword"].as<string>();
+ if (params.count("ssl.clusterPassword")) {
+ cmdLine.sslClusterPassword = params["ssl.clusterPassword"].as<string>();
}
- if (params.count("sslCAFile")) {
- cmdLine.sslCAFile = params["sslCAFile"].as<std::string>();
+ if (params.count("ssl.CAFile")) {
+ cmdLine.sslCAFile = params["ssl.CAFile"].as<std::string>();
}
- if (params.count("sslCRLFile")) {
- cmdLine.sslCRLFile = params["sslCRLFile"].as<std::string>();
+ if (params.count("ssl.CRLFile")) {
+ cmdLine.sslCRLFile = params["ssl.CRLFile"].as<std::string>();
}
- if (params.count("sslWeakCertificateValidation")) {
+ if (params.count("ssl.weakCertificateValidation")) {
cmdLine.sslWeakCertificateValidation = true;
}
- if (params.count("sslOnNormalPorts")) {
+ if (params.count("ssl.sslOnNormalPorts")) {
cmdLine.sslOnNormalPorts = true;
if ( cmdLine.sslPEMKeyFile.size() == 0 ) {
- log() << "need sslPEMKeyFile with sslOnNormalPorts" << endl;
- return false;
+ return Status(ErrorCodes::BadValue,
+ "need sslPEMKeyFile with sslOnNormalPorts");
}
if (cmdLine.sslWeakCertificateValidation &&
cmdLine.sslCAFile.empty()) {
- log() << "need sslCAFile with sslWeakCertificateValidation" << endl;
- return false;
+ return Status(ErrorCodes::BadValue,
+ "need sslCAFile with sslWeakCertificateValidation");
}
if (!cmdLine.sslCRLFile.empty() &&
cmdLine.sslCAFile.empty()) {
- log() << "need sslCAFile with sslCRLFile" << endl;
- return false;
+ return Status(ErrorCodes::BadValue, "need sslCAFile with sslCRLFile");
}
- if (params.count("sslFIPSMode")) {
+ if (params.count("ssl.FIPSMode")) {
cmdLine.sslFIPSMode = true;
}
}
@@ -532,35 +506,36 @@ namespace {
cmdLine.sslCRLFile.size() ||
cmdLine.sslWeakCertificateValidation ||
cmdLine.sslFIPSMode) {
- log() << "need to enable sslOnNormalPorts" << endl;
- return false;
+ return Status(ErrorCodes::BadValue, "need to enable sslOnNormalPorts");
}
if (cmdLine.clusterAuthMode == "sendKeyfile" ||
cmdLine.clusterAuthMode == "sendX509" ||
cmdLine.clusterAuthMode == "x509") {
if (!cmdLine.sslOnNormalPorts){
- log() << "need to enable sslOnNormalPorts" << endl;
- return false;
+ return Status(ErrorCodes::BadValue, "need to enable sslOnNormalPorts");
}
}
else if (params.count("clusterAuthMode") && cmdLine.clusterAuthMode != "keyfile") {
- log() << "unsupported value for clusterAuthMode " << cmdLine.clusterAuthMode << endl;
- return false;
+ StringBuilder sb;
+ sb << "unsupported value for clusterAuthMode " << cmdLine.clusterAuthMode;
+ return Status(ErrorCodes::BadValue, sb.str());
}
#else // ifdef MONGO_SSL
// Keyfile is currently the only supported value if not using SSL
if (params.count("clusterAuthMode") && cmdLine.clusterAuthMode != "keyfile") {
- log() << "unsupported value for clusterAuthMode " << cmdLine.clusterAuthMode << endl;
- return false;
+ StringBuilder sb;
+ sb << "unsupported value for clusterAuthMode " << cmdLine.clusterAuthMode;
+ return Status(ErrorCodes::BadValue, sb.str());
}
#endif
- return true;
+ return Status::OK();
}
static bool _isPasswordArgument(const char* argumentName) {
static const char* const passwordArguments[] = {
"sslPEMKeyPassword",
+ "ssl.PEMKeyPassword",
"servicePassword",
NULL // Last entry sentinel.
};
diff --git a/src/mongo/db/cmdline.h b/src/mongo/db/cmdline.h
index ac1801d6890..4d4d0030a05 100644
--- a/src/mongo/db/cmdline.h
+++ b/src/mongo/db/cmdline.h
@@ -19,20 +19,18 @@
#include <string>
#include <vector>
+#include "mongo/base/status.h"
#include "mongo/db/jsobj.h"
#include "mongo/platform/process_id.h"
#include "mongo/util/net/listen.h"
-namespace boost {
- namespace program_options {
- class options_description;
- class positional_options_description;
- class variables_map;
- }
-}
-
namespace mongo {
+ namespace optionenvironment {
+ class OptionSection;
+ class Environment;
+ } // namespace optionenvironment
+
/* command line options
*/
/* concurrency: OK/READ */
@@ -160,23 +158,12 @@ namespace mongo {
static void launchOk();
- static void addGlobalOptions( boost::program_options::options_description& general ,
- boost::program_options::options_description& hidden ,
- boost::program_options::options_description& ssl_options );
-
- static void addWindowsOptions( boost::program_options::options_description& windows ,
- boost::program_options::options_description& hidden );
-
-
- static bool parseConfigFile( istream &f, std::stringstream &ss);
/**
* @return true if should run program, false if should exit
*/
- static bool store( const std::vector<std::string>& argv,
- boost::program_options::options_description& visible,
- boost::program_options::options_description& hidden,
- boost::program_options::positional_options_description& positional,
- boost::program_options::variables_map &output );
+ static Status store( const std::vector<std::string>& argv,
+ optionenvironment::OptionSection& options,
+ optionenvironment::Environment& output );
/**
* Blot out sensitive fields in the argv array.
@@ -187,6 +174,11 @@ namespace mongo {
static BSONArray getArgvArray();
static BSONObj getParsedOpts();
+ static Status setupBinaryName(const std::vector<std::string>& argv);
+ static Status setupCwd();
+ static Status setArgvArray(const std::vector<std::string>& argv);
+ static Status setParsedOpts(optionenvironment::Environment& params);
+
time_t started;
};
diff --git a/src/mongo/db/cmdline_test.cpp b/src/mongo/db/cmdline_test.cpp
index 108ea228bf1..8955adbec51 100644
--- a/src/mongo/db/cmdline_test.cpp
+++ b/src/mongo/db/cmdline_test.cpp
@@ -19,7 +19,9 @@
#include <vector>
#include "mongo/db/cmdline.h"
+#include "mongo/db/jsobj.h"
#include "mongo/unittest/unittest.h"
+#include "mongo/util/options_parser/environment.h"
namespace mongo {
@@ -27,6 +29,8 @@ namespace mongo {
namespace {
+ namespace moe = mongo::optionenvironment;
+
void testCensoringArgv(const char* const * expected,
const char* const * toCensor,
int elementCount) {
@@ -220,5 +224,49 @@ namespace {
testCensoringVector(expected, argv, argc);
}
+ TEST(ParsedOptsTests, NormalValues) {
+ moe::Environment environment;
+ ASSERT_OK(environment.set(moe::Key("val1"), moe::Value(6)));
+ ASSERT_OK(environment.set(moe::Key("val2"), moe::Value(std::string("string"))));
+ ASSERT_OK(CmdLine::setParsedOpts(environment));
+ BSONObj obj = BSON( "val1" << 6 << "val2" << "string" );
+ // TODO: Put a comparison here that doesn't depend on the field order. Right now it is
+ // based on the sort order of keys in a std::map.
+ ASSERT_EQUALS(obj, CmdLine::getParsedOpts());
+ }
+
+ TEST(ParsedOptsTests, DottedValues) {
+ moe::Environment environment;
+ ASSERT_OK(environment.set(moe::Key("val1.dotted1"), moe::Value(6)));
+ ASSERT_OK(environment.set(moe::Key("val2"), moe::Value(true)));
+ ASSERT_OK(environment.set(moe::Key("val1.dotted2"), moe::Value(std::string("string"))));
+ ASSERT_OK(CmdLine::setParsedOpts(environment));
+ BSONObj obj = BSON( "val1" << BSON( "dotted1" << 6 << "dotted2" << "string" )
+ << "val2" << true );
+ // TODO: Put a comparison here that doesn't depend on the field order. Right now it is
+ // based on the sort order of keys in a std::map.
+ ASSERT_EQUALS(obj, CmdLine::getParsedOpts());
+ }
+
+ TEST(ParsedOptsTests, DeepDottedValues) {
+ moe::Environment environment;
+ ASSERT_OK(environment.set(moe::Key("val1.first1.second1.third1"), moe::Value(6)));
+ ASSERT_OK(environment.set(moe::Key("val1.first1.second2.third1"), moe::Value(false)));
+ ASSERT_OK(environment.set(moe::Key("val1.first2"), moe::Value(std::string("string"))));
+ ASSERT_OK(environment.set(moe::Key("val1.first1.second1.third2"), moe::Value(true)));
+ ASSERT_OK(environment.set(moe::Key("val2"), moe::Value(6.0)));
+ ASSERT_OK(CmdLine::setParsedOpts(environment));
+ BSONObj obj = BSON( "val1" << BSON( "first1" <<
+ BSON( "second1" <<
+ BSON( "third1" << 6 << "third2" << true ) <<
+ "second2" <<
+ BSON( "third1" << false ) ) <<
+ "first2" << "string" ) <<
+ "val2" << 6.0 );
+ // TODO: Put a comparison here that doesn't depend on the field order. Right now it is
+ // based on the sort order of keys in a std::map.
+ ASSERT_EQUALS(obj, CmdLine::getParsedOpts());
+ }
+
} // namespace
} // namespace mongo
diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp
index b3f11d5b7dc..b4888277077 100644
--- a/src/mongo/db/db.cpp
+++ b/src/mongo/db/db.cpp
@@ -45,6 +45,7 @@
#include "mongo/db/introspect.h"
#include "mongo/db/json.h"
#include "mongo/db/kill_current_op.h"
+#include "mongo/db/mongod_options.h"
#include "mongo/db/pdfile.h"
#include "mongo/db/query/internal_plans.h"
#include "mongo/db/range_deleter_service.h"
@@ -66,6 +67,8 @@
#include "mongo/util/net/message_server.h"
#include "mongo/util/net/ssl_manager.h"
#include "mongo/util/ntservice.h"
+#include "mongo/util/options_parser/environment.h"
+#include "mongo/util/options_parser/option_section.h"
#include "mongo/util/ramlog.h"
#include "mongo/util/stacktrace.h"
#include "mongo/util/startup_test.h"
@@ -103,6 +106,8 @@ namespace mongo {
#endif
CmdLine cmdLine;
+ moe::Environment params;
+ moe::OptionSection options("Allowed options");
static bool scriptingEnabled = true;
bool shouldRepairDatabases = 0;
static bool forceRepair = 0;
@@ -781,12 +786,8 @@ namespace mongo {
using namespace mongo;
-#include <boost/program_options.hpp>
-
-namespace po = boost::program_options;
-
-void show_help_text(po::options_description options) {
- cout << options << endl;
+void show_help_text(const moe::OptionSection& options) {
+ std::cout << options.helpString() << std::endl;
};
static int mongoDbMain(int argc, char* argv[], char** envp);
@@ -809,147 +810,23 @@ int main(int argc, char* argv[], char** envp) {
}
#endif
-static void buildOptionsDescriptions(po::options_description *pVisible,
- po::options_description *pHidden,
- po::positional_options_description *pPositional) {
-
- po::options_description& visible_options = *pVisible;
- po::options_description& hidden_options = *pHidden;
- po::positional_options_description& positional_options = *pPositional;
-
- po::options_description general_options("General options");
-#if defined(_WIN32)
- po::options_description windows_scm_options("Windows Service Control Manager options");
-#endif
- po::options_description ms_options("Master/slave options (old; use replica sets instead)");
- po::options_description rs_options("Replica set options");
- po::options_description replication_options("Replication options");
- po::options_description sharding_options("Sharding options");
- po::options_description hidden_sharding_options("Sharding options");
- po::options_description ssl_options("SSL options");
-
- CmdLine::addGlobalOptions( general_options , hidden_options , ssl_options );
-
- StringBuilder dbpathBuilder;
- dbpathBuilder << "directory for datafiles - defaults to " << dbpath;
-
- general_options.add_options()
- ("auth", "run with security")
- ("cpu", "periodically show cpu and iowait utilization")
- ("dbpath", po::value<string>() , dbpathBuilder.str().c_str())
- ("diaglog", po::value<int>(), "0=off 1=W 2=R 3=both 7=W+some reads")
- ("directoryperdb", "each database will be stored in a separate directory")
- ("ipv6", "enable IPv6 support (disabled by default)")
- ("journal", "enable journaling")
- ("journalCommitInterval", po::value<unsigned>(), "how often to group/batch commit (ms)")
- ("journalOptions", po::value<int>(), "journal diagnostic options")
- ("jsonp","allow JSONP access via http (has security implications)")
- ("noauth", "run without security")
- ("noIndexBuildRetry", "don't retry any index builds that were interrupted by shutdown")
- ("nojournal", "disable journaling (journaling is on by default for 64 bit)")
- ("noprealloc", "disable data file preallocation - will often hurt performance")
- ("noscripting", "disable scripting engine")
- ("notablescan", "do not allow table scans")
- ("nssize", po::value<int>()->default_value(16), ".ns file size (in MB) for new databases")
- ("profile",po::value<int>(), "0=off 1=slow, 2=all")
- ("quota", "limits each database to a certain number of files (8 default)")
- ("quotaFiles", po::value<int>(), "number of files allowed per db, requires --quota")
- ("repair", "run repair on all dbs")
- ("repairpath", po::value<string>() , "root directory for repair files - defaults to dbpath" )
- ("rest","turn on simple rest api")
-#if defined(__linux__)
- ("shutdown", "kill a running server (for init scripts)")
-#endif
- ("slowms",po::value<int>()->default_value(100), "value of slow for profile and console log" )
- ("smallfiles", "use a smaller default file size")
- ("syncdelay",po::value<double>()->default_value(60), "seconds between disk syncs (0=never, but not recommended)")
- ("sysinfo", "print some diagnostic system information")
- ("upgrade", "upgrade db if needed")
- ;
-
-#if defined(_WIN32)
- CmdLine::addWindowsOptions( windows_scm_options, hidden_options );
-#endif
-
- replication_options.add_options()
- ("oplogSize", po::value<int>(), "size to use (in MB) for replication op log. default is 5% of disk space (i.e. large is good)")
- ;
-
- ms_options.add_options()
- ("master", "master mode")
- ("slave", "slave mode")
- ("source", po::value<string>(), "when slave: specify master as <server:port>")
- ("only", po::value<string>(), "when slave: specify a single database to replicate")
- ("slavedelay", po::value<int>(), "specify delay (in seconds) to be used when applying master ops to slave")
- ("autoresync", "automatically resync if slave data is stale")
- ;
-
- rs_options.add_options()
- ("replSet", po::value<string>(), "arg is <setname>[/<optionalseedhostlist>]")
- ("replIndexPrefetch", po::value<string>(), "specify index prefetching behavior (if secondary) [none|_id_only|all]")
- ;
-
- sharding_options.add_options()
- ("configsvr", "declare this is a config db of a cluster; default port 27019; default dir /data/configdb")
- ("shardsvr", "declare this is a shard db of a cluster; default port 27018")
- ;
-
- hidden_sharding_options.add_options()
- ("noMoveParanoia" , "turn off paranoid saving of data for the moveChunk command; default" )
- ("moveParanoia" , "turn on paranoid saving of data during the moveChunk command (used for internal system diagnostics)" )
- ;
- hidden_options.add(hidden_sharding_options);
-
- hidden_options.add_options()
- ("fastsync", "indicate that this instance is starting from a dbpath snapshot of the repl peer")
- ("pretouch", po::value<int>(), "n pretouch threads for applying master/slave operations")
- ("command", po::value< vector<string> >(), "command")
- ("cacheSize", po::value<long>(), "cache size (in MB) for rec store")
- ("nodur", "disable journaling")
- // things we don't want people to use
- ("nohints", "ignore query hints")
- ("nopreallocj", "don't preallocate journal files")
- ("dur", "enable journaling") // old name for --journal
- ("durOptions", po::value<int>(), "durability diagnostic options") // deprecated name
- // deprecated pairing command line options
- ("pairwith", "DEPRECATED")
- ("arbiter", "DEPRECATED")
- ("opIdMem", "DEPRECATED")
- ;
-
- positional_options.add("command", 3);
- visible_options.add(general_options);
-#if defined(_WIN32)
- visible_options.add(windows_scm_options);
-#endif
- visible_options.add(replication_options);
- visible_options.add(ms_options);
- visible_options.add(rs_options);
- visible_options.add(sharding_options);
-#ifdef MONGO_SSL
- visible_options.add(ssl_options);
-#endif
-}
-
-static void processCommandLineOptions(const std::vector<std::string>& argv) {
- po::options_description visible_options("Allowed options");
- po::options_description hidden_options("Hidden options");
- po::positional_options_description positional_options;
- buildOptionsDescriptions(&visible_options, &hidden_options, &positional_options);
+static Status processCommandLineOptions(const std::vector<std::string>& argv) {
+ Status ret = addMongodOptions(&options);
+ if (!ret.isOK()) {
+ StringBuilder sb;
+ sb << "Error getting mongod options descriptions: " << ret.toString();
+ return Status(ErrorCodes::InternalError, sb.str());
+ }
{
- po::variables_map params;
-
- if (!CmdLine::store(argv,
- visible_options,
- hidden_options,
- positional_options,
- params)) {
- ::_exit(EXIT_FAILURE);
+ ret = CmdLine::store(argv, options, params);
+ if (!ret.isOK()) {
+ std::cerr << "Error parsing command line: " << ret.toString() << std::endl;
+ ::_exit(EXIT_BADOPTIONS);
}
if (params.count("help")) {
- show_help_text(visible_options);
+ std::cout << options.helpString() << std::endl;
::_exit(EXIT_SUCCESS);
}
if (params.count("version")) {
@@ -1013,7 +890,7 @@ static void processCommandLineOptions(const std::vector<std::string>& argv) {
}
if( params.count("dur") || params.count( "journal" ) ) {
if (journalExplicit) {
- log() << "Can't specify both --journal and --nojournal options." << endl;
+ std::cerr << "Can't specify both --journal and --nojournal options." << std::endl;
::_exit(EXIT_BADOPTIONS);
}
journalExplicit = true;
@@ -1027,8 +904,8 @@ static void processCommandLineOptions(const std::vector<std::string>& argv) {
// ie no point making life a little more complex by giving an error on a dev environment.
cmdLine.journalCommitInterval = params["journalCommitInterval"].as<unsigned>();
if( cmdLine.journalCommitInterval <= 1 || cmdLine.journalCommitInterval > 300 ) {
- out() << "--journalCommitInterval out of allowed range (0-300ms)" << endl;
- dbexit( EXIT_BADOPTIONS );
+ std::cerr << "--journalCommitInterval out of allowed range (0-300ms)" << std::endl;
+ ::_exit(EXIT_BADOPTIONS);
}
}
if (params.count("journalOptions")) {
@@ -1037,13 +914,14 @@ static void processCommandLineOptions(const std::vector<std::string>& argv) {
if (params.count("repairpath")) {
repairpath = params["repairpath"].as<string>();
if (!repairpath.size()) {
- out() << "repairpath is empty" << endl;
- dbexit( EXIT_BADOPTIONS );
+ std::cerr << "repairpath is empty" << std::endl;
+ ::_exit(EXIT_BADOPTIONS);
}
if (cmdLine.dur && !str::startsWith(repairpath, dbpath)) {
- out() << "You must use a --repairpath that is a subdirectory of --dbpath when using journaling" << endl;
- dbexit( EXIT_BADOPTIONS );
+ std::cerr << "You must use a --repairpath that is a subdirectory of "
+ << "--dbpath when using journaling" << std::endl;
+ ::_exit(EXIT_BADOPTIONS);
}
}
if (params.count("nohints")) {
@@ -1054,8 +932,8 @@ static void processCommandLineOptions(const std::vector<std::string>& argv) {
}
if (params.count("httpinterface")) {
if (params.count("nohttpinterface")) {
- log() << "can't have both --httpinterface and --nohttpinterface" << endl;
- ::_exit( EXIT_BADOPTIONS );
+ std::cerr << "can't have both --httpinterface and --nohttpinterface" << std::endl;
+ ::_exit(EXIT_BADOPTIONS);
}
cmdLine.isHttpInterfaceEnabled = true;
}
@@ -1101,14 +979,14 @@ static void processCommandLineOptions(const std::vector<std::string>& argv) {
if (params.count("diaglog")) {
int x = params["diaglog"].as<int>();
if ( x < 0 || x > 7 ) {
- out() << "can't interpret --diaglog setting" << endl;
- dbexit( EXIT_BADOPTIONS );
+ std::cerr << "can't interpret --diaglog setting" << std::endl;
+ ::_exit(EXIT_BADOPTIONS);
}
_diaglog.setLevel(x);
}
if (params.count("repair")) {
if (journalExplicit && cmdLine.dur) {
- log() << "Can't specify both --journal and --repair options." << endl;
+ std::cerr << "Can't specify both --journal and --repair options." << std::endl;
::_exit(EXIT_BADOPTIONS);
}
@@ -1139,9 +1017,10 @@ static void processCommandLineOptions(const std::vector<std::string>& argv) {
if (params.count("autoresync")) {
replSettings.autoresync = true;
if( params.count("replSet") ) {
- out() << "--autoresync is not used with --replSet" << endl;
- out() << "see http://dochub.mongodb.org/core/resyncingaverystalereplicasetmember" << endl;
- dbexit( EXIT_BADOPTIONS );
+ std::cerr << "--autoresync is not used with --replSet\nsee "
+ << "http://dochub.mongodb.org/core/resyncingaverystalereplicasetmember"
+ << std::endl;
+ ::_exit(EXIT_BADOPTIONS);
}
}
if (params.count("source")) {
@@ -1153,12 +1032,12 @@ static void processCommandLineOptions(const std::vector<std::string>& argv) {
}
if (params.count("replSet")) {
if (params.count("slavedelay")) {
- out() << "--slavedelay cannot be used with --replSet" << endl;
- dbexit( EXIT_BADOPTIONS );
+ std::cerr << "--slavedelay cannot be used with --replSet" << std::endl;
+ ::_exit(EXIT_BADOPTIONS);
}
else if (params.count("only")) {
- out() << "--only cannot be used with --replSet" << endl;
- dbexit( EXIT_BADOPTIONS );
+ std::cerr << "--only cannot be used with --replSet" << std::endl;
+ ::_exit(EXIT_BADOPTIONS);
}
/* seed list of hosts for the repl set */
cmdLine._replSet = params["replSet"].as<string>().c_str();
@@ -1175,8 +1054,8 @@ static void processCommandLineOptions(const std::vector<std::string>& argv) {
if( params.count("nssize") ) {
int x = params["nssize"].as<int>();
if (x <= 0 || x > (0x7fffffff/1024/1024)) {
- out() << "bad --nssize arg" << endl;
- dbexit( EXIT_BADOPTIONS );
+ std::cerr << "bad --nssize arg" << std::endl;
+ ::_exit(EXIT_BADOPTIONS);
}
lenForNewNsFiles = x * 1024 * 1024;
verify(lenForNewNsFiles > 0);
@@ -1184,13 +1063,16 @@ static void processCommandLineOptions(const std::vector<std::string>& argv) {
if (params.count("oplogSize")) {
long long x = params["oplogSize"].as<int>();
if (x <= 0) {
- out() << "bad --oplogSize arg" << endl;
- dbexit( EXIT_BADOPTIONS );
+ std::cerr << "bad --oplogSize arg" << std::endl;
+ ::_exit(EXIT_BADOPTIONS);
}
// note a small size such as x==1 is ok for an arbiter.
if( x > 1000 && sizeof(void*) == 4 ) {
- out() << "--oplogSize of " << x << "MB is too big for 32 bit version. Use 64 bit build instead." << endl;
- dbexit( EXIT_BADOPTIONS );
+ StringBuilder sb;
+ std::cerr << "--oplogSize of " << x
+ << "MB is too big for 32 bit version. Use 64 bit build instead."
+ << std::endl;
+ ::_exit(EXIT_BADOPTIONS);
}
cmdLine.oplogSize = x * 1024 * 1024;
verify(cmdLine.oplogSize > 0);
@@ -1198,10 +1080,11 @@ static void processCommandLineOptions(const std::vector<std::string>& argv) {
if (params.count("cacheSize")) {
long x = params["cacheSize"].as<long>();
if (x <= 0) {
- out() << "bad --cacheSize arg" << endl;
- dbexit( EXIT_BADOPTIONS );
+ std::cerr << "bad --cacheSize arg" << std::endl;
+ ::_exit(EXIT_BADOPTIONS);
}
- log() << "--cacheSize option not currently supported" << endl;
+ std::cerr << "--cacheSize option not currently supported" << std::endl;
+ ::_exit(EXIT_BADOPTIONS);
}
if (params.count("port") == 0 ) {
if( params.count("configsvr") ) {
@@ -1209,16 +1092,16 @@ static void processCommandLineOptions(const std::vector<std::string>& argv) {
}
if( params.count("shardsvr") ) {
if( params.count("configsvr") ) {
- log() << "can't do --shardsvr and --configsvr at the same time" << endl;
- dbexit( EXIT_BADOPTIONS );
+ std::cerr << "can't do --shardsvr and --configsvr at the same time" << std::endl;
+ ::_exit(EXIT_BADOPTIONS);
}
cmdLine.port = CmdLine::ShardServerPort;
}
}
else {
if ( cmdLine.port <= 0 || cmdLine.port > 65535 ) {
- out() << "bad --port number" << endl;
- dbexit( EXIT_BADOPTIONS );
+ std::cerr << "bad --port number" << std::endl;
+ ::_exit(EXIT_BADOPTIONS);
}
}
if ( params.count("configsvr" ) ) {
@@ -1226,8 +1109,8 @@ static void processCommandLineOptions(const std::vector<std::string>& argv) {
cmdLine.smallfiles = true; // config server implies small files
dur::DataLimitPerJournalFile = 128 * 1024 * 1024;
if (cmdLine.usingReplSets() || replSettings.master || replSettings.slave) {
- log() << "replication should not be enabled on a config server" << endl;
- ::_exit(-1);
+ std::cerr << "replication should not be enabled on a config server" << std::endl;
+ ::_exit(EXIT_BADOPTIONS);
}
if ( params.count( "nodur" ) == 0 && params.count( "nojournal" ) == 0 )
cmdLine.dur = true;
@@ -1245,8 +1128,9 @@ static void processCommandLineOptions(const std::vector<std::string>& argv) {
}
if (params.count("noMoveParanoia") > 0 && params.count("moveParanoia") > 0) {
- out() << "The moveParanoia and noMoveParanoia flags cannot both be set; please use only one of them." << endl;
- ::_exit( EXIT_BADOPTIONS );
+ std::cerr << "The moveParanoia and noMoveParanoia flags cannot both be set; "
+ << "please use only one of them." << std::endl;
+ ::_exit(EXIT_BADOPTIONS);
}
if (params.count("noMoveParanoia"))
@@ -1256,104 +1140,132 @@ static void processCommandLineOptions(const std::vector<std::string>& argv) {
cmdLine.moveParanoia = true;
if (params.count("pairwith") || params.count("arbiter") || params.count("opIdMem")) {
- out() << "****" << endl;
- out() << "Replica Pairs have been deprecated. Invalid options: --pairwith, --arbiter, and/or --opIdMem" << endl;
- out() << "<http://dochub.mongodb.org/core/replicapairs>" << endl;
- out() << "****" << endl;
- dbexit( EXIT_BADOPTIONS );
+ std::cerr << "****\n"
+ << "Replica Pairs have been deprecated. Invalid options: --pairwith, "
+ << "--arbiter, and/or --opIdMem\n"
+ << "<http://dochub.mongodb.org/core/replicapairs>\n"
+ << "****" << std::endl;
+ ::_exit(EXIT_BADOPTIONS);
}
// needs to be after things like --configsvr parsing, thus here.
if( repairpath.empty() )
repairpath = dbpath;
- // The "command" option is deprecated. For backward compatibility, still support the "run"
- // and "dbppath" command. The "run" command is the same as just running mongod, so just
- // falls through.
- if (params.count("command")) {
- vector<string> command = params["command"].as< vector<string> >();
-
- if (command[0].compare("dbpath") == 0) {
- cout << dbpath << endl;
- ::_exit(EXIT_SUCCESS);
- }
-
- if (command[0].compare("run") != 0) {
- cout << "Invalid command: " << command[0] << endl;
- cout << visible_options << endl;
- ::_exit(EXIT_FAILURE);
- }
-
- if (command.size() > 1) {
- cout << "Too many parameters to 'run' command" << endl;
- cout << visible_options << endl;
- ::_exit(EXIT_FAILURE);
- }
- }
-
if( cmdLine.pretouch )
log() << "--pretouch " << cmdLine.pretouch << endl;
- if (sizeof(void*) == 4 && !journalExplicit){
+ if (sizeof(void*) == 4 && !journalExplicit) {
// trying to make this stand out more like startup warnings
log() << endl;
warning() << "32-bit servers don't have journaling enabled by default. Please use --journal if you want durability." << endl;
log() << endl;
}
+ }
+
+ return Status::OK();
+}
+
+MONGO_INITIALIZER_GENERAL(ParseStartupConfiguration,
+ ("GlobalLogManager"),
+ ("default", "completedStartupConfig"))(InitializerContext* context) {
+
+ Status ret = processCommandLineOptions(context->args());
+ if (!ret.isOK()) {
+ return ret;
+ }
+
+ return Status::OK();
+}
+
+MONGO_INITIALIZER_GENERAL(ForkServerOrDie,
+ ("completedStartupConfig"),
+ ("default"))(InitializerContext* context) {
+ mongo::forkServerOrDie();
+ return Status::OK();
+}
+
+/*
+ * This function should contain the startup "actions" that we take based on the startup config. It
+ * is intended to separate the actions from "storage" and "validation" of our startup configuration.
+ */
+static void startupConfigActions(const std::vector<std::string>& argv) {
+ // The "command" option is deprecated. For backward compatibility, still support the "run"
+ // and "dbppath" command. The "run" command is the same as just running mongod, so just
+ // falls through.
+ if (params.count("command")) {
+ vector<string> command = params["command"].as< vector<string> >();
+
+ if (command[0].compare("dbpath") == 0) {
+ cout << dbpath << endl;
+ ::_exit(EXIT_SUCCESS);
+ }
+
+ if (command[0].compare("run") != 0) {
+ cout << "Invalid command: " << command[0] << endl;
+ show_help_text(options);
+ ::_exit(EXIT_FAILURE);
+ }
+
+ if (command.size() > 1) {
+ cout << "Too many parameters to 'run' command" << endl;
+ show_help_text(options);
+ ::_exit(EXIT_FAILURE);
+ }
+ }
#ifdef _WIN32
- ntservice::configureService(initService,
- params,
- defaultServiceStrings,
- std::vector<std::string>(),
- argv);
+ ntservice::configureService(initService,
+ params,
+ defaultServiceStrings,
+ std::vector<std::string>(),
+ argv);
#endif // _WIN32
#ifdef __linux__
- if (params.count("shutdown")){
- bool failed = false;
-
- string name = ( boost::filesystem::path( dbpath ) / "mongod.lock" ).string();
- if ( !boost::filesystem::exists( name ) || boost::filesystem::file_size( name ) == 0 )
- failed = true;
-
- pid_t pid;
- string procPath;
- if (!failed){
- try {
- ifstream f (name.c_str());
- f >> pid;
- procPath = (str::stream() << "/proc/" << pid);
- if (!boost::filesystem::exists(procPath))
- failed = true;
- }
- catch (const std::exception& e){
- cerr << "Error reading pid from lock file [" << name << "]: " << e.what() << endl;
+ if (params.count("shutdown")){
+ bool failed = false;
+
+ string name = ( boost::filesystem::path( dbpath ) / "mongod.lock" ).string();
+ if ( !boost::filesystem::exists( name ) || boost::filesystem::file_size( name ) == 0 )
+ failed = true;
+
+ pid_t pid;
+ string procPath;
+ if (!failed){
+ try {
+ ifstream f (name.c_str());
+ f >> pid;
+ procPath = (str::stream() << "/proc/" << pid);
+ if (!boost::filesystem::exists(procPath))
failed = true;
- }
}
-
- if (failed) {
- cerr << "There doesn't seem to be a server running with dbpath: " << dbpath << endl;
- ::_exit(EXIT_FAILURE);
+ catch (const std::exception& e){
+ cerr << "Error reading pid from lock file [" << name << "]: " << e.what() << endl;
+ failed = true;
}
+ }
- cout << "killing process with pid: " << pid << endl;
- int ret = kill(pid, SIGTERM);
- if (ret) {
- int e = errno;
- cerr << "failed to kill process: " << errnoWithDescription(e) << endl;
- ::_exit(EXIT_FAILURE);
- }
+ if (failed) {
+ cerr << "There doesn't seem to be a server running with dbpath: " << dbpath << endl;
+ ::_exit(EXIT_FAILURE);
+ }
- while (boost::filesystem::exists(procPath)) {
- sleepsecs(1);
- }
+ cout << "killing process with pid: " << pid << endl;
+ int ret = kill(pid, SIGTERM);
+ if (ret) {
+ int e = errno;
+ cerr << "failed to kill process: " << errnoWithDescription(e) << endl;
+ ::_exit(EXIT_FAILURE);
+ }
- ::_exit(EXIT_SUCCESS);
+ while (boost::filesystem::exists(procPath)) {
+ sleepsecs(1);
}
-#endif
+
+ ::_exit(EXIT_SUCCESS);
}
+#endif
}
MONGO_INITIALIZER_GENERAL(CreateAuthorizationManager,
@@ -1399,10 +1311,8 @@ static int mongoDbMain(int argc, char* argv[], char **envp) {
if( argc == 1 )
cout << dbExecCommand << " --help for help and startup options" << endl;
-
- processCommandLineOptions(std::vector<std::string>(argv, argv + argc));
- mongo::forkServerOrDie();
mongo::runGlobalInitializersOrDie(argc, argv, envp);
+ startupConfigActions(std::vector<std::string>(argv, argv + argc));
CmdLine::censor(argc, argv);
if (!initializeServerGlobalState())
diff --git a/src/mongo/db/mongod_options.cpp b/src/mongo/db/mongod_options.cpp
new file mode 100644
index 00000000000..5b4d877062e
--- /dev/null
+++ b/src/mongo/db/mongod_options.cpp
@@ -0,0 +1,367 @@
+/*
+ * Copyright (C) 2013 10gen Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "mongo/db/mongod_options.h"
+
+#include <string>
+#include <vector>
+
+#include "mongo/base/status.h"
+#include "mongo/bson/util/builder.h"
+#include "mongo/db/server_options.h"
+#include "mongo/util/options_parser/option_description.h"
+#include "mongo/util/options_parser/option_section.h"
+
+namespace mongo {
+
+ typedef moe::OptionDescription OD;
+ typedef moe::PositionalOptionDescription POD;
+
+ extern std::string dbpath;
+
+ Status addMongodOptions(moe::OptionSection* options) {
+
+ moe::OptionSection general_options("General options");
+
+ Status ret = addGeneralServerOptions(&general_options);
+ if (!ret.isOK()) {
+ return ret;
+ }
+
+#if defined(_WIN32)
+ moe::OptionSection windows_scm_options("Windows Service Control Manager options");
+
+ ret = addWindowsServerOptions(&windows_scm_options);
+ if (!ret.isOK()) {
+ return ret;
+ }
+#endif
+
+#ifdef MONGO_SSL
+ moe::OptionSection ssl_options("SSL options");
+
+ ret = addSSLServerOptions(&ssl_options);
+ if (!ret.isOK()) {
+ return ret;
+ }
+#endif
+
+ moe::OptionSection ms_options("Master/slave options (old; use replica sets instead)");
+ moe::OptionSection rs_options("Replica set options");
+ moe::OptionSection replication_options("Replication options");
+ moe::OptionSection sharding_options("Sharding options");
+
+ StringBuilder dbpathBuilder;
+ dbpathBuilder << "directory for datafiles - defaults to " << dbpath;
+
+ ret = general_options.addOption(OD("auth", "auth", moe::Switch, "run with security", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = general_options.addOption(OD("cpu", "cpu", moe::Switch,
+ "periodically show cpu and iowait utilization", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = general_options.addOption(OD("dbpath", "dbpath", moe::String,
+ dbpathBuilder.str().c_str(), true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = general_options.addOption(OD("diaglog", "diaglog", moe::Int,
+ "0=off 1=W 2=R 3=both 7=W+some reads", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = general_options.addOption(OD("directoryperdb", "directoryperdb", moe::Switch,
+ "each database will be stored in a separate directory", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = general_options.addOption(OD("ipv6", "ipv6", moe::Switch,
+ "enable IPv6 support (disabled by default)", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = general_options.addOption(OD("journal", "journal", moe::Switch, "enable journaling",
+ true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = general_options.addOption(OD("journalCommitInterval", "journalCommitInterval",
+ moe::Unsigned, "how often to group/batch commit (ms)", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = general_options.addOption(OD("journalOptions", "journalOptions", moe::Int,
+ "journal diagnostic options", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = general_options.addOption(OD("jsonp", "jsonp", moe::Switch,
+ "allow JSONP access via http (has security implications)", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = general_options.addOption(OD("noauth", "noauth", moe::Switch, "run without security",
+ true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = general_options.addOption(OD("noIndexBuildRetry", "noIndexBuildRetry", moe::Switch,
+ "don't retry any index builds that were interrupted by shutdown", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = general_options.addOption(OD("nojournal", "nojournal", moe::Switch,
+ "disable journaling (journaling is on by default for 64 bit)", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = general_options.addOption(OD("noprealloc", "noprealloc", moe::Switch,
+ "disable data file preallocation - will often hurt performance", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = general_options.addOption(OD("noscripting", "noscripting", moe::Switch,
+ "disable scripting engine", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = general_options.addOption(OD("notablescan", "notablescan", moe::Switch,
+ "do not allow table scans", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = general_options.addOption(OD("nssize", "nssize", moe::Int,
+ ".ns file size (in MB) for new databases", true, moe::Value(16)));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = general_options.addOption(OD("profile", "profile", moe::Int, "0=off 1=slow, 2=all",
+ true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = general_options.addOption(OD("quota", "quota", moe::Switch,
+ "limits each database to a certain number of files (8 default)", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = general_options.addOption(OD("quotaFiles", "quotaFiles", moe::Int,
+ "number of files allowed per db, requires --quota", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = general_options.addOption(OD("repair", "repair", moe::Switch, "run repair on all dbs",
+ true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = general_options.addOption(OD("repairpath", "repairpath", moe::String,
+ "root directory for repair files - defaults to dbpath" , true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = general_options.addOption(OD("rest", "rest", moe::Switch, "turn on simple rest api",
+ true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+#if defined(__linux__)
+ ret = general_options.addOption(OD("shutdown", "shutdown", moe::Switch,
+ "kill a running server (for init scripts)", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+#endif
+ ret = general_options.addOption(OD("slowms", "slowms", moe::Int,
+ "value of slow for profile and console log" , true, moe::Value(100)));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = general_options.addOption(OD("smallfiles", "smallfiles", moe::Switch,
+ "use a smaller default file size", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = general_options.addOption(OD("syncdelay", "syncdelay", moe::Double,
+ "seconds between disk syncs (0=never, but not recommended)", true,
+ moe::Value(60.0)));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = general_options.addOption(OD("sysinfo", "sysinfo", moe::Switch,
+ "print some diagnostic system information", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = general_options.addOption(OD("upgrade", "upgrade", moe::Switch,
+ "upgrade db if needed", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+
+ ret = replication_options.addOption(OD("oplogSize", "oplogSize", moe::Int,
+ "size to use (in MB) for replication op log. default is 5% of disk space "
+ "(i.e. large is good)", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+
+ ret = ms_options.addOption(OD("master", "master", moe::Switch, "master mode", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = ms_options.addOption(OD("slave", "slave", moe::Switch, "slave mode", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = ms_options.addOption(OD("source", "source", moe::String,
+ "when slave: specify master as <server:port>", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = ms_options.addOption(OD("only", "only", moe::String,
+ "when slave: specify a single database to replicate", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = ms_options.addOption(OD("slavedelay", "slavedelay", moe::Int,
+ "specify delay (in seconds) to be used when applying master ops to slave",
+ true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = ms_options.addOption(OD("autoresync", "autoresync", moe::Switch,
+ "automatically resync if slave data is stale", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+
+ ret = rs_options.addOption(OD("replSet", "replSet", moe::String,
+ "arg is <setname>[/<optionalseedhostlist>]", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = rs_options.addOption(OD("replIndexPrefetch", "replIndexPrefetch", moe::String,
+ "specify index prefetching behavior (if secondary) [none|_id_only|all]", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+
+ ret = sharding_options.addOption(OD("configsvr", "configsvr", moe::Switch,
+ "declare this is a config db of a cluster; default port 27019; "
+ "default dir /data/configdb", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = sharding_options.addOption(OD("shardsvr", "shardsvr", moe::Switch,
+ "declare this is a shard db of a cluster; default port 27018", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+
+ ret = sharding_options.addOption(OD("noMoveParanoia", "noMoveParanoia", moe::Switch,
+ "turn off paranoid saving of data for the moveChunk command; default", false));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = sharding_options.addOption(OD("moveParanoia", "moveParanoia", moe::Switch,
+ "turn on paranoid saving of data during the moveChunk command "
+ "(used for internal system diagnostics)", false));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ options->addSection(general_options);
+#if defined(_WIN32)
+ options->addSection(windows_scm_options);
+#endif
+ options->addSection(replication_options);
+ options->addSection(ms_options);
+ options->addSection(rs_options);
+ options->addSection(sharding_options);
+#ifdef MONGO_SSL
+ options->addSection(ssl_options);
+#endif
+
+ ret = options->addOption(OD("fastsync", "fastsync", moe::Switch,
+ "indicate that this instance is starting from a "
+ "dbpath snapshot of the repl peer", false));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("pretouch", "pretouch", moe::Int,
+ "n pretouch threads for applying master/slave operations", false));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("command", "command", moe::StringVector, "command", false));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("cacheSize", "cacheSize", moe::Long,
+ "cache size (in MB) for rec store", false));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("nodur", "nodur", moe::Switch, "disable journaling", false));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ // things we don't want people to use
+ ret = options->addOption(OD("nohints", "nohints", moe::Switch, "ignore query hints",
+ false));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("nopreallocj", "nopreallocj", moe::Switch,
+ "don't preallocate journal files", false));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("dur", "dur", moe::Switch, "enable journaling", false));
+ if (!ret.isOK()) {
+ return ret;
+ } // old name for --journal
+ ret = options->addOption(OD("durOptions", "durOptions", moe::Int,
+ "durability diagnostic options", false));
+ if (!ret.isOK()) {
+ return ret;
+ } // deprecated name
+ // deprecated pairing command line options
+ ret = options->addOption(OD("pairwith", "pairwith", moe::Switch, "DEPRECATED", false));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("arbiter", "arbiter", moe::Switch, "DEPRECATED", false));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("opIdMem", "opIdMem", moe::Switch, "DEPRECATED", false));
+ if (!ret.isOK()) {
+ return ret;
+ }
+
+ ret = options->addPositionalOption(POD("command", moe::String, 3));
+ if (!ret.isOK()) {
+ return ret;
+ }
+
+ return Status::OK();
+ }
+
+} // namespace mongo
diff --git a/src/mongo/db/mongod_options.h b/src/mongo/db/mongod_options.h
new file mode 100644
index 00000000000..f87850ab2b7
--- /dev/null
+++ b/src/mongo/db/mongod_options.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2013 10gen Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "mongo/base/status.h"
+
+namespace mongo {
+
+ namespace optionenvironment {
+ class OptionSection;
+ } // namespace optionenvironment
+
+ namespace moe = mongo::optionenvironment;
+
+ Status addMongodOptions(moe::OptionSection* options);
+}
diff --git a/src/mongo/db/server_options.cpp b/src/mongo/db/server_options.cpp
new file mode 100644
index 00000000000..0e00d096220
--- /dev/null
+++ b/src/mongo/db/server_options.cpp
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2013 10gen Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "mongo/db/server_options.h"
+
+#include "mongo/base/status.h"
+#include "mongo/bson/util/builder.h"
+#include "mongo/db/cmdline.h" // For CmdLine::DefaultDBPort
+#include "mongo/util/net/listen.h" // For DEFAULT_MAX_CONN
+#include "mongo/util/options_parser/option_description.h"
+#include "mongo/util/options_parser/option_section.h"
+
+namespace mongo {
+
+ typedef moe::OptionDescription OD;
+ typedef moe::PositionalOptionDescription POD;
+
+ Status addGeneralServerOptions(moe::OptionSection* options) {
+ StringBuilder portInfoBuilder;
+ StringBuilder maxConnInfoBuilder;
+
+ portInfoBuilder << "specify port number - " << CmdLine::DefaultDBPort << " by default";
+ maxConnInfoBuilder << "max number of simultaneous connections - "
+ << DEFAULT_MAX_CONN << " by default";
+
+ Status ret = options->addOption(OD("help", "help,h", moe::Switch,
+ "show this usage information", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("version", "version", moe::Switch, "show version information",
+ true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("config", "config,f", moe::String,
+ "configuration file specifying additional options", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("verbose", "verbose,v", moe::Switch,
+ "be more verbose (include multiple times for more verbosity e.g. -vvvvv)",
+ true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("quiet", "quiet", moe::Switch, "quieter output", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("port", "port", moe::Int, portInfoBuilder.str().c_str(), true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("bind_ip", "bind_ip", moe::String,
+ "comma separated list of ip addresses to listen on - all local ips by default",
+ true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("maxConns", "maxConns", moe::Int,
+ maxConnInfoBuilder.str().c_str(), true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("logpath", "logpath", moe::String,
+ "log file to send write to instead of stdout - has to be a file, not directory",
+ true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("logappend", "logappend", moe::Switch,
+ "append to logpath instead of over-writing", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("logTimestampFormat", "logTimestampFormat", moe::String,
+ "Desired format for timestamps in log messages. One of ctime, "
+ "iso8601-utc or iso8601-local", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("pidfilepath", "pidfilepath", moe::String,
+ "full path to pidfile (if not set, no pidfile is created)", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("keyFile", "keyFile", moe::String,
+ "private key for cluster authentication", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("setParameter", "setParameter", moe::StringVector,
+ "Set a configurable parameter", true, moe::Value(), moe::Value(), true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("httpinterface", "httpinterface", moe::Switch,
+ "enable http interface", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("clusterAuthMode", "clusterAuthMode", moe::String,
+ "Authentication mode used for cluster authentication. Alternatives are "
+ "(keyfile|sendKeyfile|sendX509|x509)", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+#ifndef _WIN32
+ ret = options->addOption(OD("nounixsocket", "nounixsocket", moe::Switch,
+ "disable listening on unix sockets", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("unixSocketPrefix", "unixSocketPrefix", moe::String,
+ "alternative directory for UNIX domain sockets (defaults to /tmp)", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("fork", "fork", moe::Switch, "fork server process", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("syslog", "syslog", moe::Switch,
+ "log to system's syslog facility instead of file or stdout", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+#endif
+
+ /* support for -vv -vvvv etc. */
+ for (string s = "vv"; s.length() <= 12; s.append("v")) {
+ ret = options->addOption(OD(s.c_str(), s.c_str(), moe::Switch, "verbose", false));
+ if(!ret.isOK()) {
+ return ret;
+ }
+ }
+
+ // Extra hidden options
+ ret = options->addOption(OD("nohttpinterface", "nohttpinterface", moe::Switch,
+ "disable http interface", false));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("objcheck", "objcheck", moe::Switch,
+ "inspect client data for validity on receipt (DEFAULT)", false));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("noobjcheck", "noobjcheck", moe::Switch,
+ "do NOT inspect client data for validity on receipt", false));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("traceExceptions", "traceExceptions", moe::Switch,
+ "log stack traces for every exception", false));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("enableExperimentalIndexStatsCmd",
+ "enableExperimentalIndexStatsCmd", moe::Switch,
+ "EXPERIMENTAL (UNSUPPORTED). "
+ "Enable command computing aggregate statistics on indexes.", false));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("enableExperimentalStorageDetailsCmd",
+ "enableExperimentalStorageDetailsCmd", moe::Switch,
+ "EXPERIMENTAL (UNSUPPORTED). "
+ "Enable command computing aggregate statistics on storage.", false));
+ if (!ret.isOK()) {
+ return ret;
+ }
+
+ return Status::OK();
+ }
+
+ Status addWindowsServerOptions(moe::OptionSection* options) {
+ Status ret = options->addOption(OD("install", "install", moe::Switch,
+ "install Windows service", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("remove", "remove", moe::Switch, "remove Windows service",
+ true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("reinstall", "reinstall", moe::Switch,
+ "reinstall Windows service (equivalent to --remove followed by --install)",
+ true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("serviceName", "serviceName", moe::String,
+ "Windows service name", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("serviceDisplayName", "serviceDisplayName", moe::String,
+ "Windows service display name", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("serviceDescription", "serviceDescription", moe::String,
+ "Windows service description", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("serviceUser", "serviceUser", moe::String,
+ "account for service execution", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("servicePassword", "servicePassword", moe::String,
+ "password used to authenticate serviceUser", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+
+ ret = options->addOption(OD("service", "service", moe::Switch, "start mongodb service",
+ false));
+ if (!ret.isOK()) {
+ return ret;
+ }
+
+ return Status::OK();
+ }
+
+ Status addSSLServerOptions(moe::OptionSection* options) {
+ Status ret = options->addOption(OD("ssl.sslOnNormalPorts", "sslOnNormalPorts", moe::Switch,
+ "use ssl on configured ports", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("ssl.PEMKeyFile", "sslPEMKeyFile", moe::String,
+ "PEM file for ssl" , true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("ssl.PEMKeyPassword", "sslPEMKeyPassword", moe::String,
+ "PEM file password" , true, moe::Value(), moe::Value(std::string(""))));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("ssl.clusterFile", "sslClusterFile", moe::String,
+ "Key file for internal SSL authentication" , true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("ssl.clusterPassword", "sslClusterPassword", moe::String,
+ "Internal authentication key file password" , true, moe::Value(), moe::Value(std::string(""))));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("ssl.CAFile", "sslCAFile", moe::String,
+ "Certificate Authority file for SSL", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("ssl.CRLFile", "sslCRLFile", moe::String,
+ "Certificate Revocation List file for SSL", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("ssl.weakCertificateValidation", "sslWeakCertificateValidation",
+ moe::Switch, "allow client to connect without presenting a certificate", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = options->addOption(OD("ssl.FIPSMode", "sslFIPSMode", moe::Switch,
+ "activate FIPS 140-2 mode at startup", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+
+ return Status::OK();
+ }
+
+} // namespace mongo
diff --git a/src/mongo/db/server_options.h b/src/mongo/db/server_options.h
new file mode 100644
index 00000000000..1320c422cd3
--- /dev/null
+++ b/src/mongo/db/server_options.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2013 10gen Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "mongo/base/status.h"
+
+namespace mongo {
+
+ namespace optionenvironment {
+ class OptionSection;
+ } // namespace optionenvironment
+
+ namespace moe = mongo::optionenvironment;
+
+ Status addGeneralServerOptions(moe::OptionSection* options);
+
+ Status addWindowsServerOptions(moe::OptionSection* options);
+
+ Status addSSLServerOptions(moe::OptionSection* options);
+}
diff --git a/src/mongo/dbtests/basictests.cpp b/src/mongo/dbtests/basictests.cpp
index af8b33645e9..9f1516adced 100644
--- a/src/mongo/dbtests/basictests.cpp
+++ b/src/mongo/dbtests/basictests.cpp
@@ -568,25 +568,6 @@ namespace BasicTests {
}
};
- class CmdLineParseConfigTest {
- public:
- void run() {
- stringstream ss1;
- istringstream iss1("");
- ASSERT(CmdLine::parseConfigFile( iss1, ss1 ));
- stringstream ss2;
- istringstream iss2("password=\'foo bar baz\'");
- ASSERT(CmdLine::parseConfigFile( iss2, ss2 ));
- stringstream ss3;
- istringstream iss3("\t this = false \n#that = true\n #another = whocares\n\n other = monkeys ");
- ASSERT(CmdLine::parseConfigFile( iss3, ss3 ));
-
- ASSERT( ss1.str().compare("\n") == 0 );
- ASSERT( ss2.str().compare("password=\'foo bar baz\'\n") == 0 );
- ASSERT( ss3.str().compare("\n other = monkeys \n") == 0 );
- }
- };
-
struct CompressionTest1 {
void run() {
const char * c = "this is a test";
@@ -636,7 +617,6 @@ namespace BasicTests {
add< HostAndPortTests >();
add< RelativePathTest >();
- add< CmdLineParseConfigTest >();
add< CompressionTest1 >();
diff --git a/src/mongo/s/mongos_options.cpp b/src/mongo/s/mongos_options.cpp
new file mode 100644
index 00000000000..e3f3a699712
--- /dev/null
+++ b/src/mongo/s/mongos_options.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2013 10gen Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "mongo/s/mongos_options.h"
+
+#include <string>
+#include <vector>
+
+#include "mongo/base/status.h"
+#include "mongo/bson/util/builder.h"
+#include "mongo/db/server_options.h"
+#include "mongo/util/options_parser/option_description.h"
+#include "mongo/util/options_parser/option_section.h"
+
+namespace mongo {
+
+ typedef moe::OptionDescription OD;
+ typedef moe::PositionalOptionDescription POD;
+
+ extern std::string dbpath;
+
+ Status addMongosOptions(moe::OptionSection* options) {
+
+ moe::OptionSection general_options("General options");
+
+ Status ret = addGeneralServerOptions(&general_options);
+ if (!ret.isOK()) {
+ return ret;
+ }
+
+#if defined(_WIN32)
+ moe::OptionSection windows_scm_options("Windows Service Control Manager options");
+
+ ret = addWindowsServerOptions(&windows_scm_options);
+ if (!ret.isOK()) {
+ return ret;
+ }
+#endif
+
+#ifdef MONGO_SSL
+ moe::OptionSection ssl_options("SSL options");
+
+ ret = addSSLServerOptions(&ssl_options);
+ if (!ret.isOK()) {
+ return ret;
+ }
+#endif
+
+ moe::OptionSection sharding_options("Sharding options");
+
+ ret = sharding_options.addOption(OD("configdb", "configdb", moe::String,
+ "1 or 3 comma separated config servers" , true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = sharding_options.addOption(OD("localThreshold", "localThreshold", moe::Int,
+ "ping time (in ms) for a node to be considered local (default 15ms)" , true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = sharding_options.addOption(OD("test", "test", moe::Switch, "just run unit tests",
+ true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = sharding_options.addOption(OD("upgrade", "upgrade", moe::Switch,
+ "upgrade meta data version", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = sharding_options.addOption(OD("chunkSize", "chunkSize", moe::Int,
+ "maximum amount of data per chunk" , true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = sharding_options.addOption(OD("ipv6", "ipv6", moe::Switch,
+ "enable IPv6 support (disabled by default)", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = sharding_options.addOption(OD("jsonp", "jsonp", moe::Switch,
+ "allow JSONP access via http (has security implications)", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+ ret = sharding_options.addOption(OD("noscripting", "noscripting", moe::Switch,
+ "disable scripting engine", true));
+ if (!ret.isOK()) {
+ return ret;
+ }
+
+ options->addSection(general_options);
+
+#if defined(_WIN32)
+ options->addSection(windows_scm_options);
+#endif
+
+ options->addSection(sharding_options);
+
+#ifdef MONGO_SSL
+ options->addSection(ssl_options);
+#endif
+
+ ret = options->addOption(OD("noAutoSplit", "noAutoSplit", moe::Switch,
+ "do not send split commands with writes", false));
+ if (!ret.isOK()) {
+ return ret;
+ }
+
+ return Status::OK();
+ }
+
+} // namespace mongo
diff --git a/src/mongo/s/mongos_options.h b/src/mongo/s/mongos_options.h
new file mode 100644
index 00000000000..e9f266b8207
--- /dev/null
+++ b/src/mongo/s/mongos_options.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2013 10gen Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "mongo/base/status.h"
+
+namespace mongo {
+
+ namespace optionenvironment {
+ class OptionSection;
+ } // namespace optionenvironment
+
+ namespace moe = mongo::optionenvironment;
+
+ Status addMongosOptions(moe::OptionSection* options);
+}
diff --git a/src/mongo/s/server.cpp b/src/mongo/s/server.cpp
index 65febb145fe..162fe5919b9 100644
--- a/src/mongo/s/server.cpp
+++ b/src/mongo/s/server.cpp
@@ -54,6 +54,7 @@
#include "mongo/s/config_upgrade.h"
#include "mongo/s/cursors.h"
#include "mongo/s/grid.h"
+#include "mongo/s/mongos_options.h"
#include "mongo/s/request.h"
#include "mongo/scripting/engine.h"
#include "mongo/util/admin_access.h"
@@ -65,6 +66,8 @@
#include "mongo/util/net/message_server.h"
#include "mongo/util/net/ssl_manager.h"
#include "mongo/util/ntservice.h"
+#include "mongo/util/options_parser/environment.h"
+#include "mongo/util/options_parser/option_section.h"
#include "mongo/util/processinfo.h"
#include "mongo/util/ramlog.h"
#include "mongo/util/signal_handlers.h"
@@ -90,6 +93,8 @@ namespace mongo {
#endif
CmdLine cmdLine;
+ moe::Environment params;
+ moe::OptionSection options("Allowed options");
Database *database = 0;
string mongosCommand;
bool dbexitCalled = false;
@@ -370,62 +375,19 @@ static bool runMongosServer( bool doUpgrade ) {
return true;
}
-#include <boost/program_options.hpp>
-
-namespace po = boost::program_options;
-
-static void processCommandLineOptions(const std::vector<std::string>& argv) {
- po::options_description general_options("General options");
-#if defined(_WIN32)
- po::options_description windows_scm_options("Windows Service Control Manager options");
-#endif
- po::options_description ssl_options("SSL options");
- po::options_description sharding_options("Sharding options");
- po::options_description visible_options("Allowed options");
- po::options_description hidden_options("Hidden options");
- po::positional_options_description positional_options;
-
- CmdLine::addGlobalOptions( general_options, hidden_options, ssl_options );
-
- hidden_options.add_options()
- ("noAutoSplit", "do not send split commands with writes");
-
-#if defined(_WIN32)
- CmdLine::addWindowsOptions( windows_scm_options, hidden_options );
-#endif
-
- sharding_options.add_options()
- ( "configdb" , po::value<string>() , "1 or 3 comma separated config servers" )
- ( "localThreshold", po::value <int>(), "ping time (in ms) for a node to be "
- "considered local (default 15ms)" )
- ( "test" , "just run unit tests" )
- ( "upgrade" , "upgrade meta data version" )
- ( "chunkSize" , po::value<int>(), "maximum amount of data per chunk" )
- ( "ipv6", "enable IPv6 support (disabled by default)" )
- ( "jsonp","allow JSONP access via http (has security implications)" )
- ( "noscripting", "disable scripting engine" )
- ;
-
- visible_options.add(general_options);
-
-#if defined(_WIN32)
- visible_options.add(windows_scm_options);
-#endif
-
- visible_options.add(sharding_options);
-
-#ifdef MONGO_SSL
- visible_options.add(ssl_options);
-#endif
+static Status processCommandLineOptions(const std::vector<std::string>& argv) {
+ Status ret = addMongosOptions(&options);
+ if (!ret.isOK()) {
+ StringBuilder sb;
+ sb << "Error getting mongos options descriptions: " << ret.toString();
+ return Status(ErrorCodes::InternalError, sb.str());
+ }
// parse options
- po::variables_map params;
- if (!CmdLine::store(argv,
- visible_options,
- hidden_options,
- positional_options,
- params)) {
- ::_exit(EXIT_FAILURE);
+ ret = CmdLine::store(argv, options, params);
+ if (!ret.isOK()) {
+ std::cerr << "Error parsing command line: " << ret.toString() << std::endl;
+ ::_exit(EXIT_BADOPTIONS);
}
// The default value may vary depending on compile options, but for mongos
@@ -433,10 +395,9 @@ static void processCommandLineOptions(const std::vector<std::string>& argv) {
cmdLine.dur = false;
if ( params.count( "help" ) ) {
- cout << visible_options << endl;
+ std::cout << options.helpString() << std::endl;
::_exit(EXIT_SUCCESS);
}
-
if ( params.count( "version" ) ) {
printShardingVersionInfo(true);
::_exit(EXIT_SUCCESS);
@@ -447,13 +408,13 @@ static void processCommandLineOptions(const std::vector<std::string>& argv) {
// validate chunksize before proceeding
if ( csize == 0 ) {
- out() << "error: need a non-zero chunksize" << endl;
- ::_exit(EXIT_FAILURE);
+ std::cerr << "error: need a non-zero chunksize" << std::endl;
+ ::_exit(EXIT_BADOPTIONS);
}
if ( !Chunk::setMaxChunkSizeSizeMB( csize ) ) {
- out() << "MaxChunkSize invalid" << endl;
- ::_exit(EXIT_FAILURE);
+ std::cerr << "MaxChunkSize invalid" << std::endl;
+ ::_exit(EXIT_BADOPTIONS);
}
}
@@ -478,9 +439,9 @@ static void processCommandLineOptions(const std::vector<std::string>& argv) {
}
if ( params.count( "test" ) ) {
- ::mongo::logger::globalLogDomain()->setMinimumLoggedSeverity(::mongo::logger::LogSeverity::Debug(5));
+ ::mongo::logger::globalLogDomain()->setMinimumLoggedSeverity(
+ ::mongo::logger::LogSeverity::Debug(5));
StartupTest::runTests();
- cout << "tests passed" << endl;
::_exit(EXIT_SUCCESS);
}
@@ -490,8 +451,8 @@ static void processCommandLineOptions(const std::vector<std::string>& argv) {
if (params.count("httpinterface")) {
if (params.count("nohttpinterface")) {
- out() << "can't have both --httpinterface and --nohttpinterface" << endl;
- ::_exit(EXIT_FAILURE);
+ std::cerr << "can't have both --httpinterface and --nohttpinterface" << std::endl;
+ ::_exit(EXIT_BADOPTIONS);
}
cmdLine.isHttpInterfaceEnabled = true;
}
@@ -502,14 +463,14 @@ static void processCommandLineOptions(const std::vector<std::string>& argv) {
}
if ( ! params.count( "configdb" ) ) {
- out() << "error: no args for --configdb" << endl;
- ::_exit(EXIT_FAILURE);
+ std::cerr << "error: no args for --configdb" << std::endl;
+ ::_exit(EXIT_BADOPTIONS);
}
splitStringDelim( params["configdb"].as<string>() , &configdbs , ',' );
if ( configdbs.size() != 1 && configdbs.size() != 3 ) {
- out() << "need either 1 or 3 configdbs" << endl;
- ::_exit(EXIT_FAILURE);
+ std::cerr << "need either 1 or 3 configdbs" << std::endl;
+ ::_exit(EXIT_BADOPTIONS);
}
if( configdbs.size() == 1 ) {
@@ -521,6 +482,33 @@ static void processCommandLineOptions(const std::vector<std::string>& argv) {
// dbpath currently must be linked in to mongos, but the directory should never be written to.
dbpath = "";
+ return Status::OK();
+}
+
+MONGO_INITIALIZER_GENERAL(ParseStartupConfiguration,
+ ("GlobalLogManager"),
+ ("default", "completedStartupConfig"))(InitializerContext* context) {
+
+ Status ret = processCommandLineOptions(context->args());
+ if (!ret.isOK()) {
+ return ret;
+ }
+
+ return Status::OK();
+}
+
+MONGO_INITIALIZER_GENERAL(ForkServerOrDie,
+ ("completedStartupConfig"),
+ ("default"))(InitializerContext* context) {
+ mongo::forkServerOrDie();
+ return Status::OK();
+}
+
+/*
+ * This function should contain the startup "actions" that we take based on the startup config. It
+ * is intended to separate the actions from "storage" and "validation" of our startup configuration.
+ */
+static void startupConfigActions(const std::vector<std::string>& argv) {
#if defined(_WIN32)
vector<string> disallowedOptions;
disallowedOptions.push_back( "upgrade" );
@@ -607,9 +595,8 @@ int mongoSMain(int argc, char* argv[], char** envp) {
mongosCommand = argv[0];
- processCommandLineOptions(std::vector<std::string>(argv, argv + argc));
- mongo::forkServerOrDie();
mongo::runGlobalInitializersOrDie(argc, argv, envp);
+ startupConfigActions(std::vector<std::string>(argv, argv + argc));
CmdLine::censor(argc, argv);
try {
int exitCode = _main();
diff --git a/src/mongo/shell/dbshell.cpp b/src/mongo/shell/dbshell.cpp
index 73092620bca..5405e4651e4 100644
--- a/src/mongo/shell/dbshell.cpp
+++ b/src/mongo/shell/dbshell.cpp
@@ -475,7 +475,9 @@ string finishCode( string code ) {
return code;
}
-namespace moe = mongo::optionenvironment;
+namespace mongo {
+ namespace moe = mongo::optionenvironment;
+}
moe::OptionSection options;
moe::Environment params;
diff --git a/src/mongo/util/ntservice.cpp b/src/mongo/util/ntservice.cpp
index 2e07afa21d4..075832dd20b 100644
--- a/src/mongo/util/ntservice.cpp
+++ b/src/mongo/util/ntservice.cpp
@@ -24,6 +24,7 @@
#include "mongo/db/client.h"
#include "mongo/db/instance.h"
#include "mongo/util/assert_util.h"
+#include "mongo/util/options_parser/environment.h"
#include "mongo/util/text.h"
#include "mongo/util/winutil.h"
@@ -57,7 +58,7 @@ namespace {
void configureService(
ServiceCallback serviceCallback,
- const boost::program_options::variables_map& params,
+ const moe::Environment& params,
const NtServiceDefaultStrings& defaultStrings,
const std::vector<std::string>& disallowedOptions,
const std::vector<std::string>& argv
diff --git a/src/mongo/util/ntservice.h b/src/mongo/util/ntservice.h
index 68d32037144..405515d0ac5 100644
--- a/src/mongo/util/ntservice.h
+++ b/src/mongo/util/ntservice.h
@@ -24,7 +24,6 @@
#ifdef _WIN32
-#include <boost/program_options.hpp>
#include <string>
#include <vector>
@@ -32,6 +31,13 @@
namespace mongo {
+ namespace optionenvironment {
+ class OptionSection;
+ class Environment;
+ } // namespace optionenvironment
+
+ namespace moe = mongo::optionenvironment;
+
namespace ntservice {
struct NtServiceDefaultStrings {
const wchar_t* serviceName;
@@ -55,7 +61,7 @@ namespace ntservice {
*/
void configureService(
ServiceCallback serviceCallback,
- const boost::program_options::variables_map& params,
+ const moe::Environment& params,
const NtServiceDefaultStrings& defaultStrings,
const std::vector<std::string>& disallowedOptions,
const std::vector<std::string>& argv);
diff --git a/src/mongo/util/options_parser/options_parser_test.cpp b/src/mongo/util/options_parser/options_parser_test.cpp
index 4868b9d1bc9..9a97892fce8 100644
--- a/src/mongo/util/options_parser/options_parser_test.cpp
+++ b/src/mongo/util/options_parser/options_parser_test.cpp
@@ -776,6 +776,39 @@ namespace {
ASSERT_EQUALS(str, "NotCommented");
}
+ TEST(INIConfigFile, Monkeys) {
+ OptionsParserTester parser;
+ moe::Environment environment;
+
+ moe::OptionSection testOpts;
+ testOpts.addOption(moe::OptionDescription("config", "config",
+ moe::String, "Config file to parse"));
+ testOpts.addOption(moe::OptionDescription("this", "this", moe::Switch, "This"));
+ testOpts.addOption(moe::OptionDescription("that", "that", moe::Switch, "That"));
+ testOpts.addOption(moe::OptionDescription("another", "another", moe::String, "Another"));
+ testOpts.addOption(moe::OptionDescription("other", "other", moe::String, "Other"));
+
+ std::vector<std::string> argv;
+ argv.push_back("binaryname");
+ argv.push_back("--config");
+ argv.push_back("default.conf");
+ std::map<std::string, std::string> env_map;
+
+ parser.setConfig("default.conf",
+ "\t this = false \n#that = true\n #another = whocares"
+ "\n\n other = monkeys ");
+
+ ASSERT_OK(parser.run(testOpts, argv, env_map, &environment));
+ moe::Value value;
+ ASSERT_NOT_OK(environment.get(moe::Key("this"), &value));
+ ASSERT_NOT_OK(environment.get(moe::Key("that"), &value));
+ ASSERT_NOT_OK(environment.get(moe::Key("another"), &value));
+ ASSERT_OK(environment.get(moe::Key("other"), &value));
+ std::string str;
+ ASSERT_OK(value.get(&str));
+ ASSERT_EQUALS(str, "monkeys");
+ }
+
TEST(INIConfigFile, DefaultValueOverride) {
OptionsParserTester parser;
moe::Environment environment;