diff options
Diffstat (limited to 'src')
151 files changed, 2665 insertions, 2102 deletions
diff --git a/src/mongo/SConscript b/src/mongo/SConscript index 679a0a091ba..67ddee7fd4c 100644 --- a/src/mongo/SConscript +++ b/src/mongo/SConscript @@ -28,7 +28,8 @@ env.SConscript(['base/SConscript', 's/SConscript', 'unittest/SConscript', 'util/concurrency/SConscript', - 'util/options_parser/SConscript']) + 'util/options_parser/SConscript', + 'util/cmdline_utils/SConscript']) def add_exe( v ): return "${PROGPREFIX}%s${PROGSUFFIX}" % v @@ -371,6 +372,8 @@ env.StaticLibrary("coredb", [ 'db/exec/working_set', '$BUILD_DIR/mongo/foundation', '$BUILD_DIR/third_party/shim_snappy', + 'server_options', + '$BUILD_DIR/mongo/util/cmdline_utils/cmdline_utils', ]) coreServerFiles = [ "db/client_basic.cpp", @@ -542,6 +545,8 @@ serverOnlyFiles = [ "db/curop.cpp", "db/compact.cpp", "db/dbcommands_admin.cpp", "db/write_concern.cpp", + "db/startup_warnings.cpp", + "db/storage_options.cpp", # most commands are only for mongod "db/commands/apply_ops.cpp", @@ -563,16 +568,12 @@ serverOnlyFiles = [ "db/curop.cpp", "db/pipeline/document_source_cursor.cpp", "db/driverHelpers.cpp" ] -env.Library("dbcmdline", ["db/cmdline.cpp", "db/server_options.cpp"], +env.Library("server_options", ["db/server_options.cpp"], LIBDEPS=['bson', 'server_parameters', '$BUILD_DIR/mongo/util/options_parser/options_parser', + '$BUILD_DIR/mongo/util/cmdline_utils/cmdline_utils', ]) -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=[]) @@ -609,6 +610,8 @@ mongosLibraryFiles = [ "s/balancer_policy.cpp", "s/writeback_listener.cpp", "s/version_manager.cpp", + "s/version_mongos.cpp", + "s/mongos_persistence_stubs.cpp", ] env.Library( "mongoscore", @@ -618,15 +621,19 @@ env.Library( "mongoscore", ] ) env.CppUnitTest( "balancer_policy_test" , [ "s/balancer_policy_tests.cpp" ] , - LIBDEPS=["mongoscore", "coreshard", "mongocommon","coreserver","coredb","dbcmdline","mongodandmongos"] , - NO_CRUTCH=True) + LIBDEPS=["mongoscore", + "coreshard", + "mongocommon", + "coreserver", + "coredb", + "mongodandmongos"], + NO_CRUTCH=True) env.CppUnitTest("dbclient_rs_test", [ "client/dbclient_rs_test.cpp" ], LIBDEPS=[ "coredb", "coreserver", "coreshard", - "dbcmdline", "mocklib", "mongocommon", "mongodandmongos", @@ -638,7 +645,6 @@ env.CppUnitTest("scoped_db_conn_test", [ "client/scoped_db_conn_test.cpp" ], "coredb", "coreserver", "coreshard", - "dbcmdline", "mongocommon", "mongodandmongos", "mongoscore"], @@ -651,7 +657,6 @@ env.CppUnitTest("shard_conn_test", [ "s/shard_conn_test.cpp" ], "mongocommon", "coreserver", "coredb", - "dbcmdline", "mongodandmongos", "mocklib", "$BUILD_DIR/mongo/db/auth/authmocks"], @@ -663,7 +668,6 @@ env.CppUnitTest("shard_test", [ "s/shard_test.cpp" ], "mongocommon", "coreserver", "coredb", - "dbcmdline", "mongodandmongos", "mocklib"], NO_CRUTCH=True) @@ -674,7 +678,6 @@ env.CppUnitTest('config_server_tests', [ 's/config_server_tests.cpp' ], "mongocommon", "coreserver", "coredb", - "dbcmdline", "mongodandmongos", "mocklib"], NO_CRUTCH=True) @@ -735,7 +738,6 @@ env.StaticLibrary("serveronly", serverOnlyFiles, "db/fts/ftsmongod", "db/common", "db/ops/update_driver", - "dbcmdline", "defaultversion", "geoparser", "geoquery", @@ -820,7 +822,7 @@ env.Install( '#/', [ # mongos mongos = env.Program( "mongos", [ "s/server.cpp", "s/mongos_options.cpp" ] , - LIBDEPS=["mongoscore", "coreserver", "coredb", "mongocommon", "coreshard", "dbcmdline", "ntservice", + LIBDEPS=["mongoscore", "coreserver", "coredb", "mongocommon", "coreshard", "ntservice", "mongodandmongos", "s/upgrade", "s/write_ops", "s/write_op_impl"]) env.Install( '#/', mongos ) diff --git a/src/mongo/client/clientAndShell.cpp b/src/mongo/client/clientAndShell.cpp index a7dd940aa8e..34eec1bbeb0 100644 --- a/src/mongo/client/clientAndShell.cpp +++ b/src/mongo/client/clientAndShell.cpp @@ -19,14 +19,14 @@ #include "mongo/client/clientOnly-private.h" #include "mongo/db/client_basic.h" -#include "mongo/db/cmdline.h" +#include "mongo/db/server_options.h" #include "mongo/s/shard.h" #include "mongo/util/assert_util.h" #include "mongo/util/timer.h" namespace mongo { - CmdLine cmdLine; + ServerGlobalParams serverGlobalParams; const char * curNs = "in client mode"; diff --git a/src/mongo/client/dbclient_rs.cpp b/src/mongo/client/dbclient_rs.cpp index 4c94696c829..69419586fae 100644 --- a/src/mongo/client/dbclient_rs.cpp +++ b/src/mongo/client/dbclient_rs.cpp @@ -451,7 +451,8 @@ namespace mongo { : _lock( "ReplicaSetMonitor instance" ), _checkConnectionLock( "ReplicaSetMonitor check connection lock" ), _name( name ), _master(-1), - _nextSlave(0), _failedChecks(0), _localThresholdMillis(cmdLine.defaultLocalThresholdMillis) { + _nextSlave(0), _failedChecks(0), + _localThresholdMillis(serverGlobalParams.defaultLocalThresholdMillis) { uassert( 13642 , "need at least 1 node for a replica set" , servers.size() > 0 ); diff --git a/src/mongo/client/dbclient_rs_test.cpp b/src/mongo/client/dbclient_rs_test.cpp index 9cef022a91d..a423211ba65 100644 --- a/src/mongo/client/dbclient_rs_test.cpp +++ b/src/mongo/client/dbclient_rs_test.cpp @@ -35,7 +35,6 @@ namespace mongo { // Symbols defined to build the binary correctly. - CmdLine cmdLine; bool inShutdown() { return false; diff --git a/src/mongo/client/dbclientcursor.cpp b/src/mongo/client/dbclientcursor.cpp index 1c9ba855ff1..f6dc5758579 100644 --- a/src/mongo/client/dbclientcursor.cpp +++ b/src/mongo/client/dbclientcursor.cpp @@ -20,7 +20,6 @@ #include "mongo/client/dbclientcursor.h" #include "mongo/client/connpool.h" -#include "mongo/db/cmdline.h" #include "mongo/db/dbmessage.h" #include "mongo/db/namespace_string.h" #include "mongo/s/shard.h" diff --git a/src/mongo/client/distlock.cpp b/src/mongo/client/distlock.cpp index 6097733d5aa..56e8e296d06 100644 --- a/src/mongo/client/distlock.cpp +++ b/src/mongo/client/distlock.cpp @@ -50,7 +50,7 @@ namespace mongo { // cache process string stringstream ss; - ss << getHostName() << ":" << cmdLine.port << ":" << time(0) << ":" << rand(); + ss << getHostName() << ":" << serverGlobalParams.port << ":" << time(0) << ":" << rand(); _cachedProcessString = new string( ss.str() ); } diff --git a/src/mongo/client/examples/mongoperf.cpp b/src/mongo/client/examples/mongoperf.cpp index 8acfc40c21e..e535f187d59 100644 --- a/src/mongo/client/examples/mongoperf.cpp +++ b/src/mongo/client/examples/mongoperf.cpp @@ -33,7 +33,6 @@ #include <boost/thread/thread.hpp> #include "mongo/bson/util/atomic_int.h" -#include "mongo/db/cmdline.h" #include "mongo/db/jsobj.h" #include "mongo/db/json.h" #include "mongo/util/logfile.h" @@ -56,9 +55,6 @@ bo options; unsigned long long len; // file len const unsigned PG = 4096; unsigned nThreadsRunning = 0; -namespace mongo { - CmdLine cmdLine; -} // as this is incremented A LOT, at some point this becomes a bottleneck if very high ops/second (in cache) things are happening. AtomicUInt iops; diff --git a/src/mongo/client/scoped_db_conn_test.cpp b/src/mongo/client/scoped_db_conn_test.cpp index 749e3e52701..9c651bf374c 100644 --- a/src/mongo/client/scoped_db_conn_test.cpp +++ b/src/mongo/client/scoped_db_conn_test.cpp @@ -51,7 +51,6 @@ namespace { namespace mongo { // Symbols defined to build the binary correctly. - CmdLine cmdLine; bool inShutdown() { scoped_lock sl(shutDownMutex); diff --git a/src/mongo/db/auth/privilege_parser_test.cpp b/src/mongo/db/auth/privilege_parser_test.cpp index 6f91f03cf66..1b0c67116ed 100644 --- a/src/mongo/db/auth/privilege_parser_test.cpp +++ b/src/mongo/db/auth/privilege_parser_test.cpp @@ -32,13 +32,13 @@ #include "mongo/db/auth/privilege.h" #include "mongo/db/auth/privilege_parser.h" -#include "mongo/db/cmdline.h" +#include "mongo/db/server_options.h" #include "mongo/unittest/unittest.h" namespace mongo { // Crutches to make the test compile - CmdLine cmdLine; + ServerGlobalParams serverGlobalParams; bool inShutdown() { return false; } diff --git a/src/mongo/db/auth/security_key.cpp b/src/mongo/db/auth/security_key.cpp index 1ee9be06a99..e69696d6a6b 100644 --- a/src/mongo/db/auth/security_key.cpp +++ b/src/mongo/db/auth/security_key.cpp @@ -141,7 +141,8 @@ namespace mongo { internalSecurity.user->getName().getUser().toString(), str); internalSecurity.user->setCredentials(credentials); - if (cmdLine.clusterAuthMode == "keyfile" || cmdLine.clusterAuthMode == "sendKeyfile") { + if (serverGlobalParams.clusterAuthMode == "keyfile" || + serverGlobalParams.clusterAuthMode == "sendKeyfile") { setInternalUserAuthParams( BSON(saslCommandMechanismFieldName << "MONGODB-CR" << saslCommandUserSourceFieldName << diff --git a/src/mongo/db/auth/user_management_commands_parser_test.cpp b/src/mongo/db/auth/user_management_commands_parser_test.cpp index d578bdbc9dc..84f516aef2c 100644 --- a/src/mongo/db/auth/user_management_commands_parser_test.cpp +++ b/src/mongo/db/auth/user_management_commands_parser_test.cpp @@ -23,15 +23,15 @@ #include "mongo/client/auth_helpers.h" #include "mongo/db/auth/authz_manager_external_state_mock.h" #include "mongo/db/auth/authorization_manager.h" -#include "mongo/db/cmdline.h" #include "mongo/db/auth/user_management_commands_parser.h" #include "mongo/db/jsobj.h" +#include "mongo/db/server_options.h" #include "mongo/unittest/unittest.h" namespace mongo { // Crutches to make the test compile - CmdLine cmdLine; + ServerGlobalParams serverGlobalParams; bool inShutdown() { return false; } diff --git a/src/mongo/db/btree.cpp b/src/mongo/db/btree.cpp index c0222bb2b86..e7a44a4e370 100644 --- a/src/mongo/db/btree.cpp +++ b/src/mongo/db/btree.cpp @@ -106,7 +106,7 @@ namespace mongo { template< class V > void BucketBasics<V>::assertWritable() { - if( cmdLine.dur ) + if (storageGlobalParams.dur) dur::assertAlreadyDeclared(this, V::BucketSize); } diff --git a/src/mongo/db/client.cpp b/src/mongo/db/client.cpp index 174f598b20a..b670267098c 100644 --- a/src/mongo/db/client.cpp +++ b/src/mongo/db/client.cpp @@ -56,6 +56,7 @@ #include "mongo/db/jsobj.h" #include "mongo/db/pagefault.h" #include "mongo/db/repl/rs.h" +#include "mongo/db/storage_options.h" #include "mongo/s/chunk_version.h" #include "mongo/s/d_logic.h" #include "mongo/s/stale_exception.h" // for SendStaleConfigException @@ -252,7 +253,8 @@ namespace mongo { Client::Context::Context(const std::string& ns , Database * db) : _client( currentClient.get() ), _oldContext( _client->_context ), - _path( mongo::dbpath ), // is this right? could be a different db? may need a dassert for this + _path(storageGlobalParams.dbpath), // is this right? could be a different db? + // may need a dassert for this _justCreated(false), _doVersion( true ), _ns( ns ), diff --git a/src/mongo/db/client.h b/src/mongo/db/client.h index a1541b22ccb..4bfa9a56fbd 100644 --- a/src/mongo/db/client.h +++ b/src/mongo/db/client.h @@ -43,6 +43,7 @@ #include "mongo/db/lasterror.h" #include "mongo/db/lockstate.h" #include "mongo/db/stats/top.h" +#include "mongo/db/storage_options.h" #include "mongo/util/concurrency/rwlock.h" #include "mongo/util/concurrency/threadlocal.h" #include "mongo/util/paths.h" @@ -160,14 +161,12 @@ namespace mongo { ~GodScope(); }; - //static void assureDatabaseIsOpen(const string& ns, string path=dbpath); - /** "read lock, and set my context, all in one operation" * This handles (if not recursively locked) opening an unopened database. */ class ReadContext : boost::noncopyable { public: - ReadContext(const std::string& ns, const std::string& path=dbpath); + ReadContext(const std::string& ns, const std::string& path=storageGlobalParams.dbpath); Context& ctx() { return *c.get(); } private: scoped_ptr<Lock::DBRead> lk; @@ -180,7 +179,8 @@ namespace mongo { class Context : boost::noncopyable { public: /** this is probably what you want */ - Context(const string& ns, const std::string& path=dbpath, bool doVersion=true); + Context(const string& ns, const std::string& path=storageGlobalParams.dbpath, + bool doVersion=true); /** note: this does not call finishInit -- i.e., does not call shardVersionOk() for example. @@ -195,13 +195,15 @@ namespace mongo { Client* getClient() const { return _client; } Database* db() const { return _db; } const char * ns() const { return _ns.c_str(); } - bool equals( const string& ns , const string& path=dbpath ) const { return _ns == ns && _path == path; } + bool equals(const string& ns, const string& path=storageGlobalParams.dbpath) const { + return _ns == ns && _path == path; + } /** @return if the db was created by this Context */ bool justCreated() const { return _justCreated; } /** @return true iff the current Context is using db/path */ - bool inDB( const string& db , const string& path=dbpath ) const; + bool inDB(const string& db, const string& path=storageGlobalParams.dbpath) const; void _clear() { // this is sort of an "early destruct" indication, _ns can never be uncleared const_cast<string&>(_ns).clear(); @@ -235,7 +237,7 @@ namespace mongo { class WriteContext : boost::noncopyable { public: - WriteContext(const string& ns, const std::string& path=dbpath); + WriteContext(const string& ns, const std::string& path=storageGlobalParams.dbpath); Context& ctx() { return _c; } private: Lock::DBWrite _lk; diff --git a/src/mongo/db/clientcursor.cpp b/src/mongo/db/clientcursor.cpp index c8d1c10d890..c2768559ce9 100644 --- a/src/mongo/db/clientcursor.cpp +++ b/src/mongo/db/clientcursor.cpp @@ -942,7 +942,7 @@ namespace mongo { static Mem mlast; try { ProcessInfo p; - if ( !cmdLine.quiet && p.supported() ) { + if (!serverGlobalParams.quiet && p.supported()) { Mem m; m.res = p.getResidentSize(); m.virt = p.getVirtualMemorySize(); @@ -951,7 +951,7 @@ namespace mongo { if( now - last >= 300 || m.grew(mlast) ) { log() << "mem (MB) res:" << m.res << " virt:" << m.virt; long long totalMapped = m.mapped; - if (cmdLine.dur) { + if (storageGlobalParams.dur) { totalMapped *= 2; log() << " mapped (incl journal view):" << totalMapped; } diff --git a/src/mongo/db/cloner.cpp b/src/mongo/db/cloner.cpp index 4b70b21e082..8fa8fbc2f6a 100644 --- a/src/mongo/db/cloner.cpp +++ b/src/mongo/db/cloner.cpp @@ -46,6 +46,7 @@ #include "mongo/db/repl/oplog.h" #include "mongo/db/repl/oplogreader.h" #include "mongo/db/pdfile.h" +#include "mongo/db/storage_options.h" namespace mongo { @@ -336,11 +337,11 @@ namespace mongo { string todb = cc().database()->name(); stringstream a,b; - a << "localhost:" << cmdLine.port; - b << "127.0.0.1:" << cmdLine.port; + a << "localhost:" << serverGlobalParams.port; + b << "127.0.0.1:" << serverGlobalParams.port; bool masterSameProcess = ( a.str() == masterHost || b.str() == masterHost ); if ( masterSameProcess ) { - if ( opts.fromDB == todb && cc().database()->path() == dbpath ) { + if (opts.fromDB == todb && cc().database()->path() == storageGlobalParams.dbpath) { // guard against an "infinite" loop /* if you are replicating, the local.sources config may be wrong if you get this */ errmsg = "can't clone from self (localhost)."; @@ -688,7 +689,7 @@ namespace mongo { if ( fromhost.empty() ) { /* copy from self */ stringstream ss; - ss << "localhost:" << cmdLine.port; + ss << "localhost:" << serverGlobalParams.port; fromhost = ss.str(); } authConn_.reset( new DBClientConnection() ); @@ -744,7 +745,7 @@ namespace mongo { if ( fromSelf ) { /* copy from self */ stringstream ss; - ss << "localhost:" << cmdLine.port; + ss << "localhost:" << serverGlobalParams.port; fromhost = ss.str(); } string fromdb = cmdObj.getStringField("fromdb"); diff --git a/src/mongo/db/cmdline.cpp b/src/mongo/db/cmdline.cpp deleted file mode 100644 index 66e2212cdf5..00000000000 --- a/src/mongo/db/cmdline.cpp +++ /dev/null @@ -1,566 +0,0 @@ -// cmdline.cpp - -/** -* Copyright (C) 2008 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/>. -* -* As a special exception, the copyright holders give permission to link the -* code of portions of this program with the OpenSSL library under certain -* conditions as described in each individual source file and distribute -* linked combinations including the program with the OpenSSL library. You -* must comply with the GNU Affero General Public License in all respects for -* all of the code used other than as permitted herein. If you modify file(s) -* with this exception, you may extend this exception to your version of the -* file(s), but you are not obligated to do so. If you do not wish to do so, -* delete this exception statement from your version. If you delete this -* exception statement from all source files in the program, then also delete -* it in the license file. -*/ - -#include <boost/algorithm/string.hpp> -#include <boost/filesystem.hpp> - -#include "mongo/pch.h" - -#include "mongo/db/cmdline.h" - -#include "mongo/base/status.h" -#include "mongo/bson/util/builder.h" -#include "mongo/db/server_parameters.h" -#include "mongo/logger/message_event_utf8_encoder.h" -#include "mongo/util/map_util.h" -#include "mongo/util/mongoutils/str.h" -#include "mongo/util/net/listen.h" -#include "mongo/util/net/ssl_options.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 -#include <direct.h> -#endif - -#define MAX_LINE_LENGTH 256 - -#include <fstream> - -namespace mongo { - - namespace moe = mongo::optionenvironment; - -#ifdef _WIN32 - string dbpath = "\\data\\db\\"; -#else - string dbpath = "/data/db/"; -#endif - - static bool _isPasswordArgument(char const* argumentName); - static bool _isPasswordSwitch(char const* switchName); - -namespace { - BSONArray argvArray; - BSONObj parsedOpts; -} // namespace - - BSONArray CmdLine::getArgvArray() { - return argvArray; - } - - BSONObj CmdLine::getParsedOpts() { - return parsedOpts; - } - - Status CmdLine::setupBinaryName(const std::vector<std::string>& argv) { - - 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 - cmdLine.cwd = buffer; - return Status::OK(); - } - - 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(); - } - -namespace { - - // 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, §ionObjBuilder, 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; - } - - // 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; - } - parsedOpts = builder.obj(); - return Status::OK(); - } - - 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; - } - - ret = CmdLine::setupCwd(); - if (!ret.isOK()) { - return ret; - } - - moe::OptionsParser parser; - - // 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, ¶ms); - if (!ret.isOK()) { - std::cerr << "Error parsing command line: " << ret.toString() << std::endl; - std::cerr << "use --help for help" << std::endl; - return ret; - } - - ret = CmdLine::setArgvArray(argv); - if (!ret.isOK()) { - return ret; - } - - ret = CmdLine::setParsedOpts(params); - if (!ret.isOK()) { - return ret; - } - - if (params.count("verbose")) { - logger::globalLogDomain()->setMinimumLoggedSeverity(logger::LogSeverity::Debug(1)); - } - - for (string s = "vv"; s.length() <= 12; s.append("v")) { - if (params.count(s)) { - logger::globalLogDomain()->setMinimumLoggedSeverity( - logger::LogSeverity::Debug(s.length())); - } - } - - if (params.count("enableExperimentalIndexStatsCmd")) { - cmdLine.experimental.indexStatsCmdEnabled = true; - } - if (params.count("enableExperimentalStorageDetailsCmd")) { - cmdLine.experimental.storageDetailsCmdEnabled = true; - } - - if (params.count("port")) { - cmdLine.port = params["port"].as<int>(); - } - - if (params.count("bind_ip")) { - cmdLine.bind_ip = params["bind_ip"].as<std::string>(); - } - - if (params.count("clusterAuthMode")) { - cmdLine.clusterAuthMode = params["clusterAuthMode"].as<std::string>(); - } - - if (params.count("quiet")) { - cmdLine.quiet = true; - } - - if (params.count("traceExceptions")) { - DBException::traceExceptions = true; - } - - if (params.count("maxConns")) { - cmdLine.maxConns = params["maxConns"].as<int>(); - - if ( cmdLine.maxConns < 5 ) { - return Status(ErrorCodes::BadValue, "maxConns has to be at least 5"); - } - } - - if (params.count("objcheck")) { - cmdLine.objcheck = true; - } - if (params.count("noobjcheck")) { - if (params.count("objcheck")) { - return Status(ErrorCodes::BadValue, "can't have both --objcheck and --noobjcheck"); - } - cmdLine.objcheck = false; - } - - if (params.count("bind_ip")) { - // passing in wildcard is the same as default behavior; remove and warn - if ( cmdLine.bind_ip == "0.0.0.0" ) { - cout << "warning: bind_ip of 0.0.0.0 is unnecessary; listens on all ips by default" << endl; - cmdLine.bind_ip = ""; - } - } - -#ifndef _WIN32 - if (params.count("unixSocketPrefix")) { - cmdLine.socket = params["unixSocketPrefix"].as<string>(); - } - - if (params.count("nounixsocket")) { - cmdLine.noUnixSocket = true; - } - - if (params.count("fork") && !params.count("shutdown")) { - cmdLine.doFork = true; - } -#endif // _WIN32 - - if (params.count("logTimestampFormat")) { - using logger::MessageEventDetailsEncoder; - std::string formatterName = params["logTimestampFormat"].as<string>(); - if (formatterName == "ctime") { - MessageEventDetailsEncoder::setDateFormatter(dateToCtimeString); - } - else if (formatterName == "iso8601-utc") { - MessageEventDetailsEncoder::setDateFormatter(dateToISOStringUTC); - } - else if (formatterName == "iso8601-local") { - MessageEventDetailsEncoder::setDateFormatter(dateToISOStringLocal); - } - else { - 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()) { - 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) { - return Status(ErrorCodes::BadValue, "Cant use both a logpath and syslog "); - } - - if (cmdLine.doFork && cmdLine.logpath.empty() && !cmdLine.logWithSyslog) { - return Status(ErrorCodes::BadValue, "--fork has to be used with --logpath or --syslog"); - } - - if (params.count("keyFile")) { - cmdLine.keyFile = params["keyFile"].as<string>(); - } - - if ( params.count("pidfilepath")) { - cmdLine.pidFile = params["pidfilepath"].as<string>(); - } - - if (params.count("setParameter")) { - std::vector<std::string> parameters = - params["setParameter"].as<std::vector<std::string> >(); - for (size_t i = 0, length = parameters.size(); i < length; ++i) { - std::string name; - std::string value; - if (!mongoutils::str::splitOn(parameters[i], '=', name, value)) { - 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) { - StringBuilder sb; - sb << "Illegal --setParameter parameter: \"" << name << "\""; - return Status(ErrorCodes::BadValue, sb.str()); - } - if (!parameter->allowedToChangeAtStartup()) { - 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()) { - StringBuilder sb; - sb << "Bad value for parameter \"" << name << "\": " << status.reason(); - return Status(ErrorCodes::BadValue, sb.str()); - } - } - } - if (!params.count("clusterAuthMode") && params.count("keyFile")){ - cmdLine.clusterAuthMode = "keyfile"; - } - -#ifdef MONGO_SSL - ret = storeSSLServerOptions(params); - if (!ret.isOK()) { - return ret; - } -#else // ifdef MONGO_SSL - // Keyfile is currently the only supported value if not using SSL - if (params.count("clusterAuthMode") && cmdLine.clusterAuthMode != "keyfile") { - StringBuilder sb; - sb << "unsupported value for clusterAuthMode " << cmdLine.clusterAuthMode; - return Status(ErrorCodes::BadValue, sb.str()); - } -#endif - - return Status::OK(); - } - - static bool _isPasswordArgument(const char* argumentName) { - static const char* const passwordArguments[] = { - "sslPEMKeyPassword", - "ssl.PEMKeyPassword", - "servicePassword", - NULL // Last entry sentinel. - }; - for (const char* const* current = passwordArguments; *current; ++current) { - if (mongoutils::str::equals(argumentName, *current)) - return true; - } - return false; - } - - static bool _isPasswordSwitch(const char* switchName) { - if (switchName[0] != '-') - return false; - size_t i = 1; - if (switchName[1] == '-') - i = 2; - switchName += i; - - return _isPasswordArgument(switchName); - } - - static void _redact(char* arg) { - for (; *arg; ++arg) - *arg = 'x'; - } - - void CmdLine::censor(std::vector<std::string>* args) { - for (size_t i = 0; i < args->size(); ++i) { - std::string& arg = args->at(i); - const std::string::iterator endSwitch = std::find(arg.begin(), arg.end(), '='); - std::string switchName(arg.begin(), endSwitch); - if (_isPasswordSwitch(switchName.c_str())) { - if (endSwitch == arg.end()) { - if (i + 1 < args->size()) { - args->at(i + 1) = "<password>"; - } - } - else { - arg = switchName + "=<password>"; - } - } - } - } - - void CmdLine::censor(int argc, char** argv) { - // Algorithm: For each arg in argv: - // Look for an equal sign in arg; if there is one, temporarily nul it out. - // check to see if arg is a password switch. If so, overwrite the value - // component with xs. - // restore the nul'd out equal sign, if any. - for (int i = 0; i < argc; ++i) { - - char* const arg = argv[i]; - char* const firstEqSign = strchr(arg, '='); - if (NULL != firstEqSign) { - *firstEqSign = '\0'; - } - - if (_isPasswordSwitch(arg)) { - if (NULL == firstEqSign) { - if (i + 1 < argc) { - _redact(argv[i + 1]); - } - } - else { - _redact(firstEqSign + 1); - } - } - - if (NULL != firstEqSign) { - *firstEqSign = '='; - } - } - } - - void printCommandLineOpts() { - log() << "options: " << parsedOpts << endl; - } -} diff --git a/src/mongo/db/cmdline.h b/src/mongo/db/cmdline.h deleted file mode 100644 index e6a2d1f78ba..00000000000 --- a/src/mongo/db/cmdline.h +++ /dev/null @@ -1,214 +0,0 @@ -/** -* Copyright (C) 2008 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/>. -* -* As a special exception, the copyright holders give permission to link the -* code of portions of this program with the OpenSSL library under certain -* conditions as described in each individual source file and distribute -* linked combinations including the program with the OpenSSL library. You -* must comply with the GNU Affero General Public License in all respects for -* all of the code used other than as permitted herein. If you modify file(s) -* with this exception, you may extend this exception to your version of the -* file(s), but you are not obligated to do so. If you do not wish to do so, -* delete this exception statement from your version. If you delete this -* exception statement from all source files in the program, then also delete -* it in the license file. -*/ - -#pragma once - -#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 mongo { - - namespace optionenvironment { - class OptionSection; - class Environment; - } // namespace optionenvironment - - /* command line options - */ - /* concurrency: OK/READ */ - struct CmdLine { - - CmdLine(); - - std::string binaryName; // mongod or mongos - std::string cwd; // cwd of when process started - - // this is suboptimal as someone could rename a binary. todo... - bool isMongos() const { return binaryName == "mongos"; } - - int port; // --port - enum { - DefaultDBPort = 27017, - ConfigServerPort = 27019, - ShardServerPort = 27018 - }; - bool isDefaultPort() const { return port == DefaultDBPort; } - - std::string bind_ip; // --bind_ip - bool rest; // --rest - bool jsonp; // --jsonp - - std::string _replSet; // --replSet[/<seedlist>] - std::string ourSetName() const { - std::string setname; - size_t sl = _replSet.find('/'); - if( sl == std::string::npos ) - return _replSet; - return _replSet.substr(0, sl); - } - bool usingReplSets() const { return !_replSet.empty(); } - - std::string rsIndexPrefetch;// --indexPrefetch - bool indexBuildRetry; // --noIndexBuildRetry - - // for master/slave replication - std::string source; // --source - std::string only; // --only - - bool quiet; // --quiet - bool noTableScan; // --notablescan no table scans allowed - bool prealloc; // --noprealloc no preallocation of data files - bool preallocj; // --nopreallocj no preallocation of journal files - bool smallfiles; // --smallfiles allocate smaller data files - - bool configsvr; // --configsvr - - bool quota; // --quota - int quotaFiles; // --quotaFiles - bool cpu; // --cpu show cpu time periodically - - bool dur; // --dur durability (now --journal) - unsigned journalCommitInterval; // group/batch commit interval ms - - /** --durOptions 7 dump journal and terminate without doing anything further - --durOptions 4 recover and terminate without listening - */ - enum { // bits to be ORed - DurDumpJournal = 1, // dump diagnostics on the journal during recovery - DurScanOnly = 2, // don't do any real work, just scan and dump if dump specified - DurRecoverOnly = 4, // terminate after recovery step - DurParanoid = 8, // paranoid mode enables extra checks - DurAlwaysCommit = 16, // do a group commit every time the writelock is released - DurAlwaysRemap = 32, // remap the private view after every group commit (may lag to the next write lock acquisition, but will do all files then) - DurNoCheckSpace = 64 // don't check that there is enough room for journal files before startup (for diskfull tests) - }; - int durOptions; // --durOptions <n> for debugging - - bool objcheck; // --objcheck - - long long oplogSize; // --oplogSize - int defaultProfile; // --profile - int slowMS; // --time in ms that is "slow" - int defaultLocalThresholdMillis; // --localThreshold in ms to consider a node local - int pretouch; // --pretouch for replication application (experimental) - bool moveParanoia; // for move chunk paranoia - double syncdelay; // seconds between fsyncs - - bool noUnixSocket; // --nounixsocket - bool doFork; // --fork - std::string socket; // UNIX domain socket directory - - int maxConns; // Maximum number of simultaneous open connections. - - std::string keyFile; // Path to keyfile, or empty if none. - std::string pidFile; // Path to pid file, or empty if none. - - std::string logpath; // Path to log file, if logging to a file; otherwise, empty. - bool logAppend; // True if logging to a file in append mode. - bool logWithSyslog; // True if logging to syslog; must not be set if logpath is set. - std::string clusterAuthMode; // Cluster authentication mode - - bool isHttpInterfaceEnabled; // True if the dbwebserver should be enabled. - -#ifndef _WIN32 - ProcessId parentProc; // --fork pid of initial process - ProcessId leaderProc; // --fork pid of leader process -#endif - - /** - * Switches to enable experimental (unsupported) features. - */ - struct ExperimentalFeatures { - ExperimentalFeatures() - : indexStatsCmdEnabled(false) - , storageDetailsCmdEnabled(false) - {} - bool indexStatsCmdEnabled; // -- enableExperimentalIndexStatsCmd - bool storageDetailsCmdEnabled; // -- enableExperimentalStorageDetailsCmd - } experimental; - - static void launchOk(); - - /** - * @return true if should run program, false if should exit - */ - static Status store( const std::vector<std::string>& argv, - optionenvironment::OptionSection& options, - optionenvironment::Environment& output ); - - /** - * Blot out sensitive fields in the argv array. - */ - static void censor(int argc, char** argv); - static void censor(std::vector<std::string>* args); - - 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; - }; - - // todo move to cmdline.cpp? - inline CmdLine::CmdLine() : - port(DefaultDBPort), rest(false), jsonp(false), indexBuildRetry(true), quiet(false), - noTableScan(false), prealloc(true), preallocj(true), smallfiles(sizeof(int*) == 4), - configsvr(false), quota(false), quotaFiles(8), cpu(false), - durOptions(0), objcheck(true), oplogSize(0), defaultProfile(0), - slowMS(100), defaultLocalThresholdMillis(15), pretouch(0), moveParanoia( true ), - syncdelay(60), noUnixSocket(false), doFork(0), socket("/tmp"), maxConns(DEFAULT_MAX_CONN), - logAppend(false), logWithSyslog(false), isHttpInterfaceEnabled(false) - { - started = time(0); - - journalCommitInterval = 0; // 0 means use default - dur = false; -#if defined(_DURABLEDEFAULTON) - dur = true; -#endif - if( sizeof(void*) == 8 ) - dur = true; -#if defined(_DURABLEDEFAULTOFF) - dur = false; -#endif - } - - extern CmdLine cmdLine; - - void printCommandLineOpts(); -} - diff --git a/src/mongo/db/commands.cpp b/src/mongo/db/commands.cpp index 23288bab1ae..0e31f0b8851 100644 --- a/src/mongo/db/commands.cpp +++ b/src/mongo/db/commands.cpp @@ -242,7 +242,7 @@ namespace mongo { void Command::logIfSlow( const Timer& timer, const string& msg ) { int ms = timer.millis(); - if ( ms > cmdLine.slowMS ) { + if (ms > serverGlobalParams.slowMS) { out() << msg << " took " << ms << " ms." << endl; } } diff --git a/src/mongo/db/commands/authentication_commands.cpp b/src/mongo/db/commands/authentication_commands.cpp index 0d1e481ba03..0fba00753c3 100644 --- a/src/mongo/db/commands/authentication_commands.cpp +++ b/src/mongo/db/commands/authentication_commands.cpp @@ -165,7 +165,8 @@ namespace mongo { Status CmdAuthenticate::_authenticateCR(const UserName& user, const BSONObj& cmdObj) { - if (user == internalSecurity.user->getName() && cmdLine.clusterAuthMode == "x509") { + if (user == internalSecurity.user->getName() && + serverGlobalParams.clusterAuthMode == "x509") { return Status(ErrorCodes::AuthenticationFailed, "Mechanism x509 is required for internal cluster authentication"); } @@ -273,7 +274,8 @@ namespace mongo { // Handle internal cluster member auth, only applies to server-server connections if (srvClusterId == peerClusterId) { - if (cmdLine.clusterAuthMode.empty() || cmdLine.clusterAuthMode == "keyfile") { + if (serverGlobalParams.clusterAuthMode.empty() || + serverGlobalParams.clusterAuthMode == "keyfile") { return Status(ErrorCodes::AuthenticationFailed, "The provided certificate " "can only be used for cluster authentication, not client " "authentication. The current configuration does not allow " diff --git a/src/mongo/db/commands/index_stats.cpp b/src/mongo/db/commands/index_stats.cpp index 61224d2579c..719fac8444d 100644 --- a/src/mongo/db/commands/index_stats.cpp +++ b/src/mongo/db/commands/index_stats.cpp @@ -500,7 +500,7 @@ namespace mongo { string ns = dbname + "." + cmdObj.firstElement().valuestrsafe(); const NamespaceDetails* nsd = nsdetails(ns); - if (!cmdLine.quiet) { + if (!serverGlobalParams.quiet) { MONGO_TLOG(0) << "CMD: indexStats " << ns << endl; } if (!nsd) { @@ -544,7 +544,7 @@ namespace mongo { }; MONGO_INITIALIZER(IndexStatsCmd)(InitializerContext* context) { - if (cmdLine.experimental.indexStatsCmdEnabled) { + if (serverGlobalParams.experimental.indexStatsCmdEnabled) { // Leaked intentionally: a Command registers itself when constructed. new IndexStatsCmd(); } diff --git a/src/mongo/db/commands/isself.cpp b/src/mongo/db/commands/isself.cpp index ee14c7df526..88352fb3742 100644 --- a/src/mongo/db/commands/isself.cpp +++ b/src/mongo/db/commands/isself.cpp @@ -41,6 +41,7 @@ #include "mongo/db/auth/security_key.h" #include "mongo/db/commands.h" #include "mongo/db/jsobj.h" +#include "mongo/db/server_options.h" #include "mongo/util/net/listen.h" #include "mongo/util/net/hostandport.h" #include "mongo/client/dbclientinterface.h" @@ -76,8 +77,8 @@ namespace mongo { vector<string> out; ifaddrs * addrs; - if ( ! cmdLine.bind_ip.empty() ) { - boost::split( out, cmdLine.bind_ip, boost::is_any_of( ", " ) ); + if (!serverGlobalParams.bind_ip.empty()) { + boost::split(out, serverGlobalParams.bind_ip, boost::is_any_of(", ")); return out; } @@ -129,7 +130,7 @@ namespace mongo { hints.ai_socktype = SOCK_STREAM; hints.ai_family = (IPv6Enabled() ? AF_UNSPEC : AF_INET); - static string portNum = BSONObjBuilder::numStr(cmdLine.port); + static string portNum = BSONObjBuilder::numStr(serverGlobalParams.port); vector<string> out; @@ -203,9 +204,9 @@ namespace mongo { bool HostAndPort::isSelf() const { int _p = port(); - int p = _p == -1 ? CmdLine::DefaultDBPort : _p; + int p = _p == -1 ? ServerGlobalParams::DefaultDBPort : _p; - if( p != cmdLine.port ) { + if (p != serverGlobalParams.port) { // shortcut - ports have to match at the very least return false; } diff --git a/src/mongo/db/commands/mr.cpp b/src/mongo/db/commands/mr.cpp index 3a5539348ed..6f92e67fd50 100644 --- a/src/mongo/db/commands/mr.cpp +++ b/src/mongo/db/commands/mr.cpp @@ -43,6 +43,7 @@ #include "mongo/db/matcher.h" #include "mongo/db/query_optimizer.h" #include "mongo/db/repl/is_master.h" +#include "mongo/db/storage_options.h" #include "mongo/scripting/engine.h" #include "mongo/s/collection_metadata.h" #include "mongo/s/d_logic.h" @@ -1215,7 +1216,7 @@ namespace mongo { Lock::DBRead lock( config.ns ); // This context does no version check, safe b/c we checked earlier and have an // open cursor - Client::Context ctx(config.ns, dbpath, false); + Client::Context ctx(config.ns, storageGlobalParams.dbpath, false); // obtain full cursor on data to apply mr to shared_ptr<Cursor> temp = getOptimizedCursor( config.ns.c_str(), diff --git a/src/mongo/db/commands/parameters.cpp b/src/mongo/db/commands/parameters.cpp index 8341d758167..1e860659ff3 100644 --- a/src/mongo/db/commands/parameters.cpp +++ b/src/mongo/db/commands/parameters.cpp @@ -33,8 +33,8 @@ #include "mongo/client/dbclient_rs.h" #include "mongo/db/auth/authorization_manager.h" #include "mongo/db/commands.h" -#include "mongo/db/cmdline.h" #include "mongo/db/server_parameters.h" +#include "mongo/db/storage_options.h" #include "mongo/util/mongoutils/str.h" namespace mongo { @@ -75,9 +75,10 @@ namespace mongo { // TODO: convert to ServerParameters -- SERVER-10515 - if( cmdLine.dur && (all || cmdObj.hasElement("journalCommitInterval")) ) { + if (isJournalingEnabled() && (all || cmdObj.hasElement("journalCommitInterval")) && + !isMongos()) { result.append("journalCommitInterval", - cmdLine.journalCommitInterval); + getJournalCommitInterval()); } if( all || cmdObj.hasElement( "traceExceptions" ) ) { result.append("traceExceptions", @@ -128,13 +129,17 @@ namespace mongo { // TODO: convert to ServerParameters -- SERVER-10515 if( cmdObj.hasElement("journalCommitInterval") ) { - if( !cmdLine.dur ) { + if (isMongos()) { + errmsg = "cannot set journalCommitInterval on a mongos"; + return false; + } + if(!isJournalingEnabled()) { errmsg = "journaling is off"; return false; } int x = (int) cmdObj["journalCommitInterval"].Number(); verify( x > 1 && x < 500 ); - cmdLine.journalCommitInterval = x; + setJournalCommitInterval(x); log() << "setParameter journalCommitInterval=" << x << endl; s++; } @@ -226,23 +231,11 @@ namespace mongo { } } logLevelSetting; - ExportedServerParameter<bool> NoTableScanSetting( ServerParameterSet::getGlobal(), - "notablescan", - &cmdLine.noTableScan, - true, - true ); - ExportedServerParameter<bool> QuietSetting( ServerParameterSet::getGlobal(), "quiet", - &cmdLine.quiet, + &serverGlobalParams.quiet, true, true ); - - ExportedServerParameter<double> SyncdelaySetting( ServerParameterSet::getGlobal(), - "syncdelay", - &cmdLine.syncdelay, - true, - true ); } } diff --git a/src/mongo/db/commands/pipeline_command.cpp b/src/mongo/db/commands/pipeline_command.cpp index b103dba8588..e090c65fabb 100644 --- a/src/mongo/db/commands/pipeline_command.cpp +++ b/src/mongo/db/commands/pipeline_command.cpp @@ -43,6 +43,7 @@ #include "mongo/db/pipeline/pipeline_d.h" #include "mongo/db/pipeline/pipeline.h" #include "mongo/db/ops/query.h" +#include "mongo/db/storage_options.h" namespace mongo { @@ -227,7 +228,7 @@ namespace mongo { intrusive_ptr<ExpressionContext> pCtx = new ExpressionContext(InterruptStatusMongod::status, NamespaceString(ns)); - pCtx->tempDir = dbpath + "/_tmp"; + pCtx->tempDir = storageGlobalParams.dbpath + "/_tmp"; /* try to parse the command; if this fails, then we didn't run */ intrusive_ptr<Pipeline> pPipeline = Pipeline::parseCommand(errmsg, cmdObj, pCtx); diff --git a/src/mongo/db/commands/server_status.cpp b/src/mongo/db/commands/server_status.cpp index 8ca074d9f5f..a6d951d5bf6 100644 --- a/src/mongo/db/commands/server_status.cpp +++ b/src/mongo/db/commands/server_status.cpp @@ -36,7 +36,6 @@ #include "mongo/db/auth/authorization_session.h" #include "mongo/db/auth/privilege.h" #include "mongo/db/client_basic.h" -#include "mongo/db/cmdline.h" #include "mongo/db/commands.h" #include "mongo/db/commands/server_status.h" #include "mongo/db/stats/counters.h" @@ -103,9 +102,9 @@ namespace mongo { result.append("host", prettyHostName() ); result.append("version", versionString); - result.append("process",cmdLine.binaryName); + result.append("process", serverGlobalParams.binaryName); result.append("pid", ProcessId::getCurrent().asLongLong()); - result.append("uptime",(double) (time(0)-cmdLine.started)); + result.append("uptime", (double) (time(0) - serverGlobalParams.started)); result.append("uptimeMillis", (long long)(curTimeMillis64()-_started)); result.append("uptimeEstimate",(double) (start/1000)); result.appendDate( "localTime" , jsTime() ); diff --git a/src/mongo/db/commands/storage_details.cpp b/src/mongo/db/commands/storage_details.cpp index 6229dc34625..18bdf1fedb2 100644 --- a/src/mongo/db/commands/storage_details.cpp +++ b/src/mongo/db/commands/storage_details.cpp @@ -328,7 +328,7 @@ namespace { }; MONGO_INITIALIZER(StorageDetailsCmd)(InitializerContext* context) { - if (cmdLine.experimental.storageDetailsCmdEnabled) { + if (serverGlobalParams.experimental.storageDetailsCmdEnabled) { // Leaked intentionally: a Command registers itself when constructed. new StorageDetailsCmd(); } @@ -779,7 +779,7 @@ namespace { const string ns = dbname + "." + cmdObj.firstElement().valuestrsafe(); const NamespaceDetails* nsd = nsdetails(ns); - if (!cmdLine.quiet) { + if (!serverGlobalParams.quiet) { MONGO_TLOG(0) << "CMD: storageDetails " << ns << ", analyze " << subCommandStr << endl; } if (!nsd) { diff --git a/src/mongo/db/commands/write_commands/batch_executor.cpp b/src/mongo/db/commands/write_commands/batch_executor.cpp index 5acc6d55708..3b1094479d1 100644 --- a/src/mongo/db/commands/write_commands/batch_executor.cpp +++ b/src/mongo/db/commands/write_commands/batch_executor.cpp @@ -195,8 +195,9 @@ namespace mongo { opDebug.recordStats(); // Log operation if running with at least "-v", or if exceeds slow threshold. - if ( logger::globalLogDomain()->shouldLog( logger::LogSeverity::Debug( 1 ) ) - || opDebug.executionTime > cmdLine.slowMS + childOp.getExpectedLatencyMs() ) { + if (logger::globalLogDomain()->shouldLog(logger::LogSeverity::Debug(1)) + || opDebug.executionTime > + serverGlobalParams.slowMS + childOp.getExpectedLatencyMs()) { MONGO_TLOG(1) << opDebug.report( childOp ) << endl; } diff --git a/src/mongo/db/curop.h b/src/mongo/db/curop.h index bc21c6f7954..8df653f8ff1 100644 --- a/src/mongo/db/curop.h +++ b/src/mongo/db/curop.h @@ -201,7 +201,7 @@ namespace mongo { if ( _dbprofile <= 0 ) return false; - return _dbprofile >= 2 || ms >= cmdLine.slowMS; + return _dbprofile >= 2 || ms >= serverGlobalParams.slowMS; } AtomicUInt opNum() const { return _opNum; } diff --git a/src/mongo/db/curop_test.cpp b/src/mongo/db/curop_test.cpp index 1ec562181e6..392c53a6509 100644 --- a/src/mongo/db/curop_test.cpp +++ b/src/mongo/db/curop_test.cpp @@ -34,8 +34,6 @@ namespace mongo { - CmdLine cmdLine; // needed to satisfy reference in curop.h (and elsewhere) - namespace { const long long intervalLong = 2000 * 1000; // 2s in micros diff --git a/src/mongo/db/database.cpp b/src/mongo/db/database.cpp index 9bd972e04e1..75b8c14a930 100644 --- a/src/mongo/db/database.cpp +++ b/src/mongo/db/database.cpp @@ -46,6 +46,7 @@ #include "mongo/db/pdfile.h" #include "mongo/db/query/internal_plans.h" #include "mongo/db/ops/delete.h" +#include "mongo/db/storage_options.h" #include "mongo/db/structure/collection.h" namespace mongo { @@ -104,7 +105,7 @@ namespace mongo { Database::Database(const char *nm, bool& newDb, const string& path ) : _name(nm), _path(path), _namespaceIndex( _path, _name ), - _extentManager( _name, _path, 0, directoryperdb /* this is a global right now */ ), + _extentManager(_name, _path, 0, storageGlobalParams.directoryperdb), _profileName(_name + ".system.profile"), _namespacesName(_name + ".system.namespaces"), _extentFreelistName( _name + ".$freelist" ), @@ -118,7 +119,7 @@ namespace mongo { try { newDb = _namespaceIndex.exists(); - _profile = cmdLine.defaultProfile; + _profile = serverGlobalParams.defaultProfile; checkDuplicateUncasedNames(true); // If already exists, open. Otherwise behave as if empty until diff --git a/src/mongo/db/database.h b/src/mongo/db/database.h index ef8109736eb..e642b1ed158 100644 --- a/src/mongo/db/database.h +++ b/src/mongo/db/database.h @@ -31,10 +31,10 @@ #pragma once #include "mongo/db/cc_by_loc.h" -#include "mongo/db/cmdline.h" #include "mongo/db/namespace_details.h" -#include "mongo/db/storage/record.h" #include "mongo/db/storage/extent_manager.h" +#include "mongo/db/storage/record.h" +#include "mongo/db/storage_options.h" namespace mongo { @@ -50,7 +50,8 @@ namespace mongo { class Database { public: // you probably need to be in dbHolderMutex when constructing this - Database(const char *nm, /*out*/ bool& newDb, const string& path = dbpath); + Database(const char *nm, /*out*/ bool& newDb, + const string& path = storageGlobalParams.dbpath); /* you must use this to close - there is essential code in this method that is not in the ~Database destructor. thus the destructor is private. this could be cleaned up one day... diff --git a/src/mongo/db/database_holder.cpp b/src/mongo/db/database_holder.cpp index 94587943c5c..4fae75965c1 100644 --- a/src/mongo/db/database_holder.cpp +++ b/src/mongo/db/database_holder.cpp @@ -56,7 +56,9 @@ namespace mongo { bool cant = !Lock::isWriteLocked(ns); if( logger::globalLogDomain()->shouldLog(logger::LogSeverity::Debug(1)) || m.size() > 40 || cant || DEBUG_BUILD ) { - log() << "opening db: " << (path==dbpath?"":path) << ' ' << dbname << endl; + log() << "opening db: " + << (path == storageGlobalParams.dbpath ? "" : path) << ' ' << dbname + << endl; } massert(15927, "can't open database in a read lock. if db was just closed, consider retrying the query. might otherwise indicate an internal error", !cant); } diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp index 37be15e2f5b..5195b6ef0d8 100644 --- a/src/mongo/db/db.cpp +++ b/src/mongo/db/db.cpp @@ -42,7 +42,6 @@ #include "mongo/db/auth/authorization_manager_global.h" #include "mongo/db/client.h" #include "mongo/db/clientcursor.h" -#include "mongo/db/cmdline.h" #include "mongo/db/commands/server_status.h" #include "mongo/db/d_concurrency.h" #include "mongo/db/d_globals.h" @@ -67,13 +66,16 @@ #include "mongo/db/repl/replication_server_status.h" #include "mongo/db/repl/rs.h" #include "mongo/db/restapi.h" +#include "mongo/db/startup_warnings.h" #include "mongo/db/stats/counters.h" #include "mongo/db/stats/snapshots.h" +#include "mongo/db/storage_options.h" #include "mongo/db/ttl.h" #include "mongo/platform/process_id.h" #include "mongo/s/d_writeback.h" #include "mongo/scripting/engine.h" #include "mongo/util/background.h" +#include "mongo/util/cmdline_utils/censor_cmdline.h" #include "mongo/util/concurrency/task.h" #include "mongo/util/concurrency/thread_name.h" #include "mongo/util/exception_filter_win32.h" @@ -83,6 +85,7 @@ #include "mongo/util/ntservice.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/ramlog.h" #include "mongo/util/stacktrace.h" #include "mongo/util/startup_test.h" @@ -95,17 +98,11 @@ namespace mongo { - namespace dur { - extern unsigned long long DataLimitPerJournalFile; - } - /* only off if --nohints */ extern bool useHints; extern int diagLogging; - extern unsigned lenForNewNsFiles; extern int lockFile; - extern string repairpath; static void setupSignalHandlers(); static void startSignalProcessingThread(); @@ -119,12 +116,6 @@ namespace mongo { }; #endif - CmdLine cmdLine; - moe::Environment params; - moe::OptionSection options("Allowed options"); - static bool scriptingEnabled = true; - bool shouldRepairDatabases = 0; - static bool forceRepair = 0; Timer startupSrandTimer; const char *ourgetns() { @@ -184,19 +175,6 @@ namespace mongo { }; #endif - void sysRuntimeInfo() { - out() << "sysinfo:" << endl; -#if defined(_SC_PAGE_SIZE) - out() << " page size: " << (int) sysconf(_SC_PAGE_SIZE) << endl; -#endif -#if defined(_SC_PHYS_PAGES) - out() << " _SC_PHYS_PAGES: " << sysconf(_SC_PHYS_PAGES) << endl; -#endif -#if defined(_SC_AVPHYS_PAGES) - out() << " _SC_AVPHYS_PAGES: " << sysconf(_SC_AVPHYS_PAGES) << endl; -#endif - } - /* if server is really busy, wait a bit */ void beNice() { sleepmicros( Client::recommendedYieldMicros() ); @@ -274,7 +252,7 @@ namespace mongo { toLog.appendTimeT( "startTime", time(0) ); toLog.append( "startTimeLocal", dateToCtimeString(curTimeMillis64()) ); - toLog.append( "cmdLine", CmdLine::getParsedOpts() ); + toLog.append("cmdLine", serverGlobalParams.parsedOpts); toLog.append( "pid", ProcessId::getCurrent().asLongLong() ); @@ -296,7 +274,7 @@ namespace mongo { //testTheDb(); MessageServer::Options options; options.port = port; - options.ipList = cmdLine.bind_ip; + options.ipList = serverGlobalParams.bind_ip; MessageServer * server = createServer( options , new MyMessageHandler() ); server->setAsTimeTracker(); @@ -306,7 +284,7 @@ namespace mongo { logStartup(); startReplication(); - if ( cmdLine.isHttpInterfaceEnabled ) + if (serverGlobalParams.isHttpInterfaceEnabled) boost::thread web( boost::bind(&webServerThread, new RestAdminAccess() /* takes ownership */)); #if(TESTEXHAUST) @@ -345,7 +323,7 @@ namespace mongo { } void checkForIdIndexes(const std::string& dbName) { - if (!cmdLine.usingReplSets()) { + if (!replSettings.usingReplSets()) { // we only care about the _id index if we are in a replset return; } @@ -406,7 +384,7 @@ namespace mongo { DataFile *p = cc().database()->getFile( 0 ); DataFileHeader *h = p->getHeader(); checkForIdIndexes(dbName); - if ( !h->isCurrentVersion() || forceRepair ) { + if (!h->isCurrentVersion() || mongodGlobalParams.repair) { if( h->version <= 0 ) { uasserted(14026, @@ -424,7 +402,7 @@ namespace mongo { << endl; } - if ( shouldRepairDatabases ) { + if (mongodGlobalParams.upgrade) { // QUESTION: Repair even if file format is higher version than code? string errmsg; verify( doDBUpgrade( dbName , errmsg , h ) ); @@ -434,7 +412,7 @@ namespace mongo { log() << "\t run --upgrade to upgrade dbs, then start again" << endl; log() << "****" << endl; dbexit( EXIT_NEED_UPGRADE ); - shouldRepairDatabases = 1; + mongodGlobalParams.upgrade = 1; return; } } @@ -461,13 +439,13 @@ namespace mongo { warning() << "Internal error while reading collection " << systemIndexes; } } - Database::closeDatabase( dbName.c_str(), dbpath ); + Database::closeDatabase(dbName.c_str(), storageGlobalParams.dbpath); } } LOG(1) << "done repairDatabases" << endl; - if ( shouldRepairDatabases ) { + if (mongodGlobalParams.upgrade) { log() << "finished checking dbs" << endl; cc().shutdown(); dbexit( EXIT_CLEAN ); @@ -475,7 +453,7 @@ namespace mongo { } void clearTmpFiles() { - boost::filesystem::path path( dbpath ); + boost::filesystem::path path(storageGlobalParams.dbpath); for ( boost::filesystem::directory_iterator i( path ); i != boost::filesystem::directory_iterator(); ++i ) { string fileName = boost::filesystem::path(*i).leaf().string(); @@ -494,7 +472,7 @@ namespace mongo { */ unsigned long long checkIfReplMissingFromCommandLine() { Lock::GlobalWrite lk; // this is helpful for the query below to work as you can't open files when readlocked - if( !cmdLine.usingReplSets() ) { + if (!replSettings.usingReplSets()) { Client::GodScope gs; DBDirectClient c; return c.count("local.system.replset"); @@ -520,25 +498,25 @@ namespace mongo { void run() { Client::initThread( name().c_str() ); - if( cmdLine.syncdelay == 0 ) { + if (storageGlobalParams.syncdelay == 0) { log() << "warning: --syncdelay 0 is not recommended and can have strange performance" << endl; } - else if( cmdLine.syncdelay == 1 ) { + else if (storageGlobalParams.syncdelay == 1) { log() << "--syncdelay 1" << endl; } - else if( cmdLine.syncdelay != 60 ) { - LOG(1) << "--syncdelay " << cmdLine.syncdelay << endl; + else if (storageGlobalParams.syncdelay != 60) { + LOG(1) << "--syncdelay " << storageGlobalParams.syncdelay << endl; } int time_flushing = 0; while ( ! inShutdown() ) { _diaglog.flush(); - if ( cmdLine.syncdelay == 0 ) { + if (storageGlobalParams.syncdelay == 0) { // in case at some point we add an option to change at runtime sleepsecs(5); continue; } - sleepmillis( (long long) std::max(0.0, (cmdLine.syncdelay * 1000) - time_flushing) ); + sleepmillis((long long) std::max(0.0, (storageGlobalParams.syncdelay * 1000) - time_flushing)); if ( inShutdown() ) { // occasional issue trying to flush during shutdown when sleep interrupted @@ -592,7 +570,7 @@ namespace mongo { int m = static_cast<int>(MemoryMappedFile::totalMappedLength() / ( 1024 * 1024 )); b.appendNumber( "mapped" , m ); - if ( cmdLine.dur ) { + if (storageGlobalParams.dur) { m *= 2; b.appendNumber( "mappedWithJournal" , m ); } @@ -659,13 +637,15 @@ namespace mongo { { ProcessId pid = ProcessId::getCurrent(); LogstreamBuilder l = log(); - l << "MongoDB starting : pid=" << pid << " port=" << cmdLine.port << " dbpath=" << dbpath; + l << "MongoDB starting : pid=" << pid + << " port=" << serverGlobalParams.port + << " dbpath=" << storageGlobalParams.dbpath; if( replSettings.master ) l << " master=" << replSettings.master; if( replSettings.slave ) l << " slave=" << (int) replSettings.slave; l << ( is32bit ? " 32" : " 64" ) << "-bit host=" << getHostNameCached() << endl; } DEV log() << "_DEBUG build (which is slower)" << endl; - show_warnings(); + logStartupWarnings(); #if defined(_WIN32) printTargetMinOS(); #endif @@ -674,23 +654,24 @@ namespace mongo { stringstream ss; ss << endl; ss << "*********************************************************************" << endl; - ss << " ERROR: dbpath (" << dbpath << ") does not exist." << endl; + ss << " ERROR: dbpath (" << storageGlobalParams.dbpath << ") does not exist." << endl; ss << " Create this directory or give existing directory in --dbpath." << endl; ss << " See http://dochub.mongodb.org/core/startingandstoppingmongo" << endl; ss << "*********************************************************************" << endl; - uassert( 10296 , ss.str().c_str(), boost::filesystem::exists( dbpath ) ); + uassert(10296, ss.str().c_str(), boost::filesystem::exists(storageGlobalParams.dbpath)); } { stringstream ss; - ss << "repairpath (" << repairpath << ") does not exist"; - uassert( 12590 , ss.str().c_str(), boost::filesystem::exists( repairpath ) ); + ss << "repairpath (" << storageGlobalParams.repairpath << ") does not exist"; + uassert(12590, ss.str().c_str(), + boost::filesystem::exists(storageGlobalParams.repairpath)); } // TODO check non-journal subdirs if using directory-per-db - checkReadAhead(dbpath); + checkReadAhead(storageGlobalParams.dbpath); - acquirePathLock(forceRepair); - boost::filesystem::remove_all( dbpath + "/_tmp/" ); + acquirePathLock(mongodGlobalParams.repair); + boost::filesystem::remove_all(storageGlobalParams.dbpath + "/_tmp/"); FileAllocator::get()->start(); @@ -698,7 +679,7 @@ namespace mongo { dur::startup(); - if( cmdLine.durOptions & CmdLine::DurRecoverOnly ) + if (storageGlobalParams.durOptions & StorageGlobalParams::DurRecoverOnly) return; unsigned long long missingRepl = checkIfReplMissingFromCommandLine(); @@ -715,7 +696,7 @@ namespace mongo { Module::initAll(); - if ( scriptingEnabled ) { + if (mongodGlobalParams.scriptingEnabled) { ScriptEngine::setup(); globalScriptEngine->setCheckInterruptCallback( jsInterruptCallback ); globalScriptEngine->setGetCurrentOpIdCallback( jsGetCurrentOpIdCallback ); @@ -723,7 +704,7 @@ namespace mongo { repairDatabasesAndCheckVersion(); - if ( shouldRepairDatabases ) + if (mongodGlobalParams.upgrade) return; AuthorizationManager* authzManager = getGlobalAuthorizationManager(); @@ -747,13 +728,13 @@ namespace mongo { } #ifndef _WIN32 - CmdLine::launchOk(); + mongo::signalForkSuccess(); #endif if(AuthorizationManager::isAuthEnabled()) { // open admin db in case we need to use it later. TODO this is not the right way to // resolve this. - Client::WriteContext c("admin", dbpath); + Client::WriteContext c("admin", storageGlobalParams.dbpath); } getDeleter()->startWorkers(); @@ -793,7 +774,7 @@ namespace mongo { void initService() { ntservice::reportStatus( SERVICE_RUNNING ); log() << "Service running" << endl; - initAndListen( cmdLine.port ); + initAndListen(serverGlobalParams.port); } #endif @@ -801,10 +782,6 @@ namespace mongo { using namespace mongo; -void show_help_text(const moe::OptionSection& options) { - std::cout << options.helpString() << std::endl; -}; - static int mongoDbMain(int argc, char* argv[], char** envp); #if defined(_WIN32) @@ -825,374 +802,6 @@ int main(int argc, char* argv[], char** envp) { } #endif -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()); - } - - { - 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")) { - std::cout << options.helpString() << std::endl; - ::_exit(EXIT_SUCCESS); - } - if (params.count("version")) { - cout << mongodVersion() << endl; - printGitVersion(); - printOpenSSLVersion(); - ::_exit(EXIT_SUCCESS); - } - if (params.count("sysinfo")) { - sysRuntimeInfo(); - ::_exit(EXIT_SUCCESS); - } - - if ( params.count( "dbpath" ) ) { - dbpath = params["dbpath"].as<string>(); - if ( params.count( "fork" ) && dbpath[0] != '/' ) { - // we need to change dbpath if we fork since we change - // cwd to "/" - // fork only exists on *nix - // so '/' is safe - dbpath = cmdLine.cwd + "/" + dbpath; - } - } -#ifdef _WIN32 - if (dbpath.size() > 1 && dbpath[dbpath.size()-1] == '/') { - // size() check is for the unlikely possibility of --dbpath "/" - dbpath = dbpath.erase(dbpath.size()-1); - } -#endif - if ( params.count("slowms")) { - cmdLine.slowMS = params["slowms"].as<int>(); - } - - if ( params.count("syncdelay")) { - cmdLine.syncdelay = params["syncdelay"].as<double>(); - } - - if ( params.count("directoryperdb")) { - directoryperdb = true; - } - if (params.count("cpu")) { - cmdLine.cpu = true; - } - if (params.count("noauth")) { - AuthorizationManager::setAuthEnabled(false); - } - if (params.count("auth")) { - AuthorizationManager::setAuthEnabled(true); - } - if (params.count("quota")) { - cmdLine.quota = true; - } - if (params.count("quotaFiles")) { - cmdLine.quota = true; - cmdLine.quotaFiles = params["quotaFiles"].as<int>() - 1; - } - bool journalExplicit = false; - if( params.count("nodur") || params.count( "nojournal" ) ) { - journalExplicit = true; - cmdLine.dur = false; - } - if( params.count("dur") || params.count( "journal" ) ) { - if (journalExplicit) { - std::cerr << "Can't specify both --journal and --nojournal options." << std::endl; - ::_exit(EXIT_BADOPTIONS); - } - journalExplicit = true; - cmdLine.dur = true; - } - if (params.count("durOptions")) { - cmdLine.durOptions = params["durOptions"].as<int>(); - } - if( params.count("journalCommitInterval") ) { - // don't check if dur is false here as many will just use the default, and will default to off on win32. - // ie no point making life a little more complex by giving an error on a dev environment. - cmdLine.journalCommitInterval = params["journalCommitInterval"].as<unsigned>(); - if( cmdLine.journalCommitInterval <= 1 || cmdLine.journalCommitInterval > 300 ) { - std::cerr << "--journalCommitInterval out of allowed range (0-300ms)" << std::endl; - ::_exit(EXIT_BADOPTIONS); - } - } - if (params.count("journalOptions")) { - cmdLine.durOptions = params["journalOptions"].as<int>(); - } - if (params.count("repairpath")) { - repairpath = params["repairpath"].as<string>(); - if (!repairpath.size()) { - std::cerr << "repairpath is empty" << std::endl; - ::_exit(EXIT_BADOPTIONS); - } - - if (cmdLine.dur && !str::startsWith(repairpath, dbpath)) { - 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")) { - useHints = false; - } - if (params.count("nopreallocj")) { - cmdLine.preallocj = false; - } - if (params.count("httpinterface")) { - if (params.count("nohttpinterface")) { - std::cerr << "can't have both --httpinterface and --nohttpinterface" << std::endl; - ::_exit(EXIT_BADOPTIONS); - } - cmdLine.isHttpInterfaceEnabled = true; - } - // SERVER-10019 Enabling rest/jsonp without --httpinterface should break in the future - if (params.count("rest")) { - if (params.count("nohttpinterface")) { - log() << "** WARNING: Should not specify both --rest and --nohttpinterface" << - startupWarningsLog; - } - else if (!params.count("httpinterface")) { - log() << "** WARNING: --rest is specified without --httpinterface," << - startupWarningsLog; - log() << "** enabling http interface" << startupWarningsLog; - cmdLine.isHttpInterfaceEnabled = true; - } - cmdLine.rest = true; - } - if (params.count("jsonp")) { - if (params.count("nohttpinterface")) { - log() << "** WARNING: Should not specify both --jsonp and --nohttpinterface" << - startupWarningsLog; - } - else if (!params.count("httpinterface")) { - log() << "** WARNING --jsonp is specified without --httpinterface," << - startupWarningsLog; - log() << "** enabling http interface" << startupWarningsLog; - cmdLine.isHttpInterfaceEnabled = true; - } - cmdLine.jsonp = true; - } - if (params.count("noscripting")) { - scriptingEnabled = false; - } - if (params.count("noprealloc")) { - cmdLine.prealloc = false; - cout << "note: noprealloc may hurt performance in many applications" << endl; - } - if (params.count("smallfiles")) { - cmdLine.smallfiles = true; - verify( dur::DataLimitPerJournalFile >= 128 * 1024 * 1024 ); - dur::DataLimitPerJournalFile = 128 * 1024 * 1024; - } - if (params.count("diaglog")) { - int x = params["diaglog"].as<int>(); - if ( x < 0 || x > 7 ) { - std::cerr << "can't interpret --diaglog setting" << std::endl; - ::_exit(EXIT_BADOPTIONS); - } - _diaglog.setLevel(x); - } - if (params.count("repair")) { - if (journalExplicit && cmdLine.dur) { - std::cerr << "Can't specify both --journal and --repair options." << std::endl; - ::_exit(EXIT_BADOPTIONS); - } - - Record::MemoryTrackingEnabled = false; - shouldRepairDatabases = 1; - forceRepair = 1; - cmdLine.dur = false; - } - if (params.count("upgrade")) { - Record::MemoryTrackingEnabled = false; - shouldRepairDatabases = 1; - } - if (params.count("notablescan")) { - cmdLine.noTableScan = true; - } - if (params.count("master")) { - replSettings.master = true; - } - if (params.count("slave")) { - replSettings.slave = SimpleSlave; - } - if (params.count("slavedelay")) { - replSettings.slavedelay = params["slavedelay"].as<int>(); - } - if (params.count("fastsync")) { - replSettings.fastsync = true; - } - if (params.count("autoresync")) { - replSettings.autoresync = true; - if( params.count("replSet") ) { - std::cerr << "--autoresync is not used with --replSet\nsee " - << "http://dochub.mongodb.org/core/resyncingaverystalereplicasetmember" - << std::endl; - ::_exit(EXIT_BADOPTIONS); - } - } - if (params.count("source")) { - /* specifies what the source in local.sources should be */ - cmdLine.source = params["source"].as<string>().c_str(); - } - if( params.count("pretouch") ) { - cmdLine.pretouch = params["pretouch"].as<int>(); - } - if (params.count("replSet")) { - if (params.count("slavedelay")) { - std::cerr << "--slavedelay cannot be used with --replSet" << std::endl; - ::_exit(EXIT_BADOPTIONS); - } - else if (params.count("only")) { - 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(); - } - if (params.count("replIndexPrefetch")) { - cmdLine.rsIndexPrefetch = params["replIndexPrefetch"].as<std::string>(); - } - if (params.count("noIndexBuildRetry")) { - cmdLine.indexBuildRetry = false; - } - if (params.count("only")) { - cmdLine.only = params["only"].as<string>().c_str(); - } - if( params.count("nssize") ) { - int x = params["nssize"].as<int>(); - if (x <= 0 || x > (0x7fffffff/1024/1024)) { - std::cerr << "bad --nssize arg" << std::endl; - ::_exit(EXIT_BADOPTIONS); - } - lenForNewNsFiles = x * 1024 * 1024; - verify(lenForNewNsFiles > 0); - } - if (params.count("oplogSize")) { - long long x = params["oplogSize"].as<int>(); - if (x <= 0) { - 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 ) { - 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); - } - if (params.count("cacheSize")) { - long x = params["cacheSize"].as<long>(); - if (x <= 0) { - std::cerr << "bad --cacheSize arg" << std::endl; - ::_exit(EXIT_BADOPTIONS); - } - std::cerr << "--cacheSize option not currently supported" << std::endl; - ::_exit(EXIT_BADOPTIONS); - } - if (!params.count("port")) { - if( params.count("configsvr") ) { - cmdLine.port = CmdLine::ConfigServerPort; - } - if( params.count("shardsvr") ) { - if( params.count("configsvr") ) { - 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 ) { - std::cerr << "bad --port number" << std::endl; - ::_exit(EXIT_BADOPTIONS); - } - } - if ( params.count("configsvr" ) ) { - cmdLine.configsvr = true; - cmdLine.smallfiles = true; // config server implies small files - dur::DataLimitPerJournalFile = 128 * 1024 * 1024; - if (cmdLine.usingReplSets() || replSettings.master || replSettings.slave) { - std::cerr << "replication should not be enabled on a config server" << std::endl; - ::_exit(EXIT_BADOPTIONS); - } - if (!params.count("nodur") && !params.count("nojournal")) - cmdLine.dur = true; - if (!params.count("dbpath")) - dbpath = "/data/configdb"; - replSettings.master = true; - if (!params.count("oplogSize")) - cmdLine.oplogSize = 5 * 1024 * 1024; - } - if ( params.count( "profile" ) ) { - cmdLine.defaultProfile = params["profile"].as<int>(); - } - if (params.count("ipv6")) { - enableIPv6(); - } - - if (params.count("noMoveParanoia") && params.count("moveParanoia")) { - 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")) - cmdLine.moveParanoia = false; - - if (params.count("moveParanoia")) - cmdLine.moveParanoia = true; - - if (params.count("pairwith") || params.count("arbiter") || params.count("opIdMem")) { - 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; - - if( cmdLine.pretouch ) - log() << "--pretouch " << cmdLine.pretouch << endl; - - 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) { @@ -1204,46 +813,46 @@ MONGO_INITIALIZER_GENERAL(ForkServerOrDie, * 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) { +static void startupConfigActions(const std::vector<std::string>& args) { // 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 (serverParsedOptions.count("command")) { + vector<string> command = serverParsedOptions["command"].as< vector<string> >(); if (command[0].compare("dbpath") == 0) { - cout << dbpath << endl; + cout << storageGlobalParams.dbpath << endl; ::_exit(EXIT_SUCCESS); } if (command[0].compare("run") != 0) { cout << "Invalid command: " << command[0] << endl; - show_help_text(options); + printMongodHelp(serverOptions); ::_exit(EXIT_FAILURE); } if (command.size() > 1) { cout << "Too many parameters to 'run' command" << endl; - show_help_text(options); + printMongodHelp(serverOptions); ::_exit(EXIT_FAILURE); } } - Module::configAll(params); + Module::configAll(serverParsedOptions); #ifdef _WIN32 ntservice::configureService(initService, - params, + serverParsedOptions, defaultServiceStrings, std::vector<std::string>(), - argv); + args); #endif // _WIN32 #ifdef __linux__ - if (params.count("shutdown")){ + if (serverParsedOptions.count("shutdown")){ bool failed = false; - string name = ( boost::filesystem::path( dbpath ) / "mongod.lock" ).string(); + string name = (boost::filesystem::path(storageGlobalParams.dbpath) / "mongod.lock").string(); if ( !boost::filesystem::exists( name ) || boost::filesystem::file_size( name ) == 0 ) failed = true; @@ -1264,7 +873,8 @@ static void startupConfigActions(const std::vector<std::string>& argv) { } if (failed) { - cerr << "There doesn't seem to be a server running with dbpath: " << dbpath << endl; + std::cerr << "There doesn't seem to be a server running with dbpath: " + << storageGlobalParams.dbpath << std::endl; ::_exit(EXIT_FAILURE); } @@ -1330,7 +940,7 @@ static int mongoDbMain(int argc, char* argv[], char **envp) { mongo::runGlobalInitializersOrDie(argc, argv, envp); startupConfigActions(std::vector<std::string>(argv, argv + argc)); - CmdLine::censor(argc, argv); + cmdline_utils::censorArgvArray(argc, argv); if (!initializeServerGlobalState()) ::_exit(EXIT_FAILURE); @@ -1349,7 +959,7 @@ static int mongoDbMain(int argc, char* argv[], char **envp) { #endif StartupTest::runTests(); - initAndListen(cmdLine.port); + initAndListen(serverGlobalParams.port); dbexit(EXIT_CLEAN); return 0; } diff --git a/src/mongo/db/dbcommands.cpp b/src/mongo/db/dbcommands.cpp index 9087c598ba0..26fd3dd7951 100644 --- a/src/mongo/db/dbcommands.cpp +++ b/src/mongo/db/dbcommands.cpp @@ -298,7 +298,7 @@ namespace mongo { CmdDropDatabase() : Command("dropDatabase") {} bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) { // disallow dropping the config database - if ( cmdLine.configsvr && ( dbname == "config" ) ) { + if (serverGlobalParams.configsvr && (dbname == "config")) { errmsg = "Cannot drop 'config' database if mongod started with --configsvr"; return false; } @@ -399,7 +399,7 @@ namespace mongo { bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) { BSONElement e = cmdObj.firstElement(); result.append("was", cc().database()->getProfilingLevel()); - result.append("slowms", cmdLine.slowMS ); + result.append("slowms", serverGlobalParams.slowMS); int p = (int) e.number(); bool ok = false; @@ -412,7 +412,7 @@ namespace mongo { BSONElement slow = cmdObj["slowms"]; if ( slow.isNumber() ) - cmdLine.slowMS = slow.numberInt(); + serverGlobalParams.slowMS = slow.numberInt(); return ok; } @@ -468,7 +468,7 @@ namespace mongo { bool run(const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) { int was = _diaglog.setLevel( cmdObj.firstElement().numberInt() ); _diaglog.flush(); - if ( !cmdLine.quiet ) { + if (!serverGlobalParams.quiet) { MONGO_TLOG(0) << "CMD: diagLogging set to " << _diaglog.getLevel() << " from: " << was << endl; } result.append( "was" , was ); @@ -512,7 +512,7 @@ namespace mongo { virtual bool run(const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) { string nsToDrop = dbname + '.' + cmdObj.firstElement().valuestr(); - if ( !cmdLine.quiet ) { + if (!serverGlobalParams.quiet) { MONGO_TLOG(0) << "CMD: drop " << nsToDrop << endl; } @@ -700,7 +700,7 @@ namespace mongo { BSONElement e = jsobj.firstElement(); string toDeleteNs = dbname + '.' + e.valuestr(); NamespaceDetails *d = nsdetails(toDeleteNs); - if ( !cmdLine.quiet ) { + if (!serverGlobalParams.quiet) { MONGO_TLOG(0) << "CMD: dropIndexes " << toDeleteNs << endl; } if ( d ) { @@ -855,7 +855,8 @@ namespace mongo { seen.insert( i->c_str() ); } - // TODO: erh 1/1/2010 I think this is broken where path != dbpath ?? + // TODO: erh 1/1/2010 I think this is broken where + // path != storageGlobalParams.dbpath ?? set<string> allShortNames; { Lock::GlobalRead lk; @@ -907,7 +908,7 @@ namespace mongo { bool run(const string& dbname , BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& result, bool /*fromRepl*/) { bool ok; try { - ok = dbHolderW().closeAll( dbpath , result, false ); + ok = dbHolderW().closeAll(storageGlobalParams.dbpath, result, false); } catch(DBException&) { throw; @@ -1986,7 +1987,7 @@ namespace mongo { scoped_ptr<Lock::GlobalRead> lk; if( c->lockGlobally() ) lk.reset( new Lock::GlobalRead() ); - Client::ReadContext ctx(ns , dbpath); // read locks + Client::ReadContext ctx(ns, storageGlobalParams.dbpath); // read locks client.curop()->ensureStarted(); retval = _execCommand(c, dbname, cmdObj, queryOptions, errmsg, result, fromRepl); } @@ -2006,7 +2007,7 @@ namespace mongo { static_cast<Lock::ScopedLock*>( new Lock::GlobalWrite() ) : static_cast<Lock::ScopedLock*>( new Lock::DBWrite( dbname ) ) ); client.curop()->ensureStarted(); - Client::Context ctx(dbname, dbpath); + Client::Context ctx(dbname, storageGlobalParams.dbpath); retval = _execCommand(c, dbname, cmdObj, queryOptions, errmsg, result, fromRepl); if ( retval && c->logTheOp() && ! fromRepl ) { logOp("c", cmdns, cmdObj); diff --git a/src/mongo/db/dbcommands_admin.cpp b/src/mongo/db/dbcommands_admin.cpp index 9c1c78bafa8..1a3e5a4f093 100644 --- a/src/mongo/db/dbcommands_admin.cpp +++ b/src/mongo/db/dbcommands_admin.cpp @@ -47,7 +47,6 @@ #include "mongo/db/auth/action_set.h" #include "mongo/db/auth/action_type.h" #include "mongo/db/auth/privilege.h" -#include "mongo/db/cmdline.h" #include "mongo/db/commands.h" #include "mongo/db/curop-inl.h" #include "mongo/db/index/catalog_hack.h" @@ -57,6 +56,7 @@ #include "mongo/db/kill_current_op.h" #include "mongo/db/pdfile.h" #include "mongo/db/query/internal_plans.h" +#include "mongo/db/storage_options.h" #include "mongo/scripting/engine.h" #include "mongo/util/alignedbuilder.h" #include "mongo/util/background.h" @@ -136,7 +136,8 @@ namespace mongo { catch(...) { } try { - result.append("onSamePartition", onSamePartition(dur::getJournalDir().string(), dbpath)); + result.append("onSamePartition", onSamePartition(dur::getJournalDir().string(), + storageGlobalParams.dbpath)); } catch(...) { } @@ -175,7 +176,7 @@ namespace mongo { bool run(const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) { string ns = dbname + "." + cmdObj.firstElement().valuestrsafe(); NamespaceDetails * d = nsdetails( ns ); - if ( !cmdLine.quiet ) { + if (!serverGlobalParams.quiet) { MONGO_TLOG(0) << "CMD: validate " << ns << endl; } diff --git a/src/mongo/db/dbcommands_generic.cpp b/src/mongo/db/dbcommands_generic.cpp index 07bdbf2e3cc..393511049a5 100644 --- a/src/mongo/db/dbcommands_generic.cpp +++ b/src/mongo/db/dbcommands_generic.cpp @@ -51,9 +51,10 @@ #include "mongo/db/pdfile.h" #include "mongo/db/repl/multicmd.h" #include "mongo/db/repl/write_concern.h" -#include "mongo/server.h" +#include "mongo/db/server_options.h" #include "mongo/db/stats/counters.h" #include "mongo/scripting/engine.h" +#include "mongo/server.h" #include "mongo/util/lruishmap.h" #include "mongo/util/md5.hpp" #include "mongo/util/processinfo.h" @@ -404,8 +405,8 @@ namespace mongo { out->push_back(Privilege(ResourcePattern::forClusterResource(), actions)); } virtual bool run(const string&, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) { - result.append("argv", CmdLine::getArgvArray()); - result.append("parsed", CmdLine::getParsedOpts()); + result.append("argv", serverGlobalParams.argvArray); + result.append("parsed", serverGlobalParams.parsedOpts); return true; } diff --git a/src/mongo/db/dbeval.cpp b/src/mongo/db/dbeval.cpp index af190d082c3..c25588c8bf1 100644 --- a/src/mongo/db/dbeval.cpp +++ b/src/mongo/db/dbeval.cpp @@ -36,7 +36,6 @@ #include "mongo/db/auth/authorization_manager.h" #include "mongo/db/auth/authorization_manager_global.h" #include "mongo/db/auth/authorization_session.h" -#include "mongo/db/cmdline.h" #include "mongo/db/commands.h" #include "mongo/db/introspect.h" #include "mongo/db/jsobj.h" @@ -100,9 +99,9 @@ namespace mongo { int res; { Timer t; - res = s->invoke(f, &args, 0, cmdLine.quota ? 10 * 60 * 1000 : 0 ); + res = s->invoke(f, &args, 0, storageGlobalParams.quota ? 10 * 60 * 1000 : 0); int m = t.millis(); - if ( m > cmdLine.slowMS ) { + if (m > serverGlobalParams.slowMS) { out() << "dbeval slow, time: " << dec << m << "ms " << dbName << endl; if ( m >= 1000 ) log() << code << endl; else OCCASIONALLY log() << code << endl; diff --git a/src/mongo/db/dbhelpers.cpp b/src/mongo/db/dbhelpers.cpp index ad3df07bc8e..ba198f503ce 100644 --- a/src/mongo/db/dbhelpers.cpp +++ b/src/mongo/db/dbhelpers.cpp @@ -49,6 +49,7 @@ #include "mongo/db/query/internal_plans.h" #include "mongo/db/repl/oplog.h" #include "mongo/db/repl/write_concern.h" +#include "mongo/db/storage_options.h" #include "mongo/db/structure/collection.h" #include "mongo/s/d_logic.h" @@ -174,7 +175,7 @@ namespace mongo { } bool Helpers::isEmpty(const char *ns) { - Client::Context context(ns, dbpath); + Client::Context context(ns, storageGlobalParams.dbpath); auto_ptr<Runner> runner(InternalPlanner::collectionScan(ns)); return Runner::RUNNER_EOF == runner->getNext(NULL, NULL); } @@ -521,7 +522,7 @@ namespace mongo { : _out(0) { static int NUM = 0; - _root = dbpath; + _root = storageGlobalParams.dbpath; if ( a.size() ) _root /= a; if ( b.size() ) diff --git a/src/mongo/db/dbmessage.h b/src/mongo/db/dbmessage.h index a265a7eb0d7..88a34a3ecfb 100644 --- a/src/mongo/db/dbmessage.h +++ b/src/mongo/db/dbmessage.h @@ -209,7 +209,7 @@ namespace mongo { "Client Error: Remaining data too small for BSON object", theEnd - nextjsobj >= 5 ); - if ( cmdLine.objcheck ) { + if (serverGlobalParams.objcheck) { Status status = validateBSON( nextjsobj, theEnd - nextjsobj ); massert( 10307, str::stream() << "Client Error: bad object in message: " << status.reason(), diff --git a/src/mongo/db/dbwebserver.cpp b/src/mongo/db/dbwebserver.cpp index 6ae04510585..14163ce8de5 100644 --- a/src/mongo/db/dbwebserver.cpp +++ b/src/mongo/db/dbwebserver.cpp @@ -46,7 +46,6 @@ #include "mongo/db/auth/user_name.h" #include "mongo/db/auth/user.h" #include "mongo/db/background.h" -#include "mongo/db/cmdline.h" #include "mongo/db/commands.h" #include "mongo/db/db.h" #include "mongo/db/instance.h" @@ -89,7 +88,7 @@ namespace mongo { ss << "git hash: " << gitVersion() << '\n'; ss << openSSLVersion("OpenSSL version: ", "\n"); ss << "sys info: " << sysInfo() << '\n'; - ss << "uptime: " << time(0)-cmdLine.started << " seconds\n"; + ss << "uptime: " << time(0)-serverGlobalParams.started << " seconds\n"; ss << "</pre>"; } @@ -199,12 +198,13 @@ namespace mongo { DbWebHandler * handler = DbWebHandler::findHandler( url ); if ( handler ) { - if ( handler->requiresREST( url ) && ! cmdLine.rest ) { + if (handler->requiresREST(url) && !serverGlobalParams.rest) { _rejectREST( responseMsg , responseCode , headers ); } else { string callback = params.getStringField("jsonp"); - uassert(13453, "server not started with --jsonp", callback.empty() || cmdLine.jsonp); + uassert(13453, "server not started with --jsonp", + callback.empty() || serverGlobalParams.jsonp); handler->handle( rq , url , params , responseMsg , responseCode , headers , from ); @@ -217,7 +217,7 @@ namespace mongo { } - if ( ! cmdLine.rest ) { + if (!serverGlobalParams.rest) { _rejectREST( responseMsg , responseCode , headers ); return; } @@ -242,7 +242,7 @@ namespace mongo { string dbname; { stringstream z; - z << cmdLine.binaryName << ' ' << prettyHostName(); + z << serverGlobalParams.binaryName << ' ' << prettyHostName(); dbname = z.str(); } ss << start(dbname) << h2(dbname); @@ -359,7 +359,7 @@ namespace mongo { }; MONGO_INITIALIZER(WebStatusLogPlugin)(InitializerContext*) { - if (cmdLine.isHttpInterfaceEnabled) { + if (serverGlobalParams.isHttpInterfaceEnabled) { new LogPlugin; } return Status::OK(); @@ -565,8 +565,8 @@ namespace mongo { void webServerThread(const AdminAccess* adminAccess) { boost::scoped_ptr<const AdminAccess> adminAccessPtr(adminAccess); // adminAccess is owned here Client::initThread("websvr"); - const int p = cmdLine.port + 1000; - DbWebServer mini(cmdLine.bind_ip, p, adminAccessPtr.get()); + const int p = serverGlobalParams.port + 1000; + DbWebServer mini(serverGlobalParams.bind_ip, p, adminAccessPtr.get()); mini.setupSockets(); mini.initAndListen(); cc().shutdown(); diff --git a/src/mongo/db/driverHelpers.cpp b/src/mongo/db/driverHelpers.cpp index dcc688eeb10..b827aef5451 100644 --- a/src/mongo/db/driverHelpers.cpp +++ b/src/mongo/db/driverHelpers.cpp @@ -42,7 +42,6 @@ #include "mongo/db/auth/action_set.h" #include "mongo/db/auth/action_type.h" #include "mongo/db/auth/privilege.h" -#include "mongo/db/cmdline.h" #include "mongo/db/commands.h" #include "mongo/db/curop-inl.h" #include "mongo/db/jsobj.h" diff --git a/src/mongo/db/dur.cpp b/src/mongo/db/dur.cpp index c9c5bc46391..cda03eeacb1 100644 --- a/src/mongo/db/dur.cpp +++ b/src/mongo/db/dur.cpp @@ -72,7 +72,6 @@ #include <boost/thread/thread.hpp> #include "mongo/db/client.h" -#include "mongo/db/cmdline.h" #include "mongo/db/commands/fsync.h" #include "mongo/db/commands/server_status.h" #include "mongo/db/dur.h" @@ -80,6 +79,7 @@ #include "mongo/db/dur_journal.h" #include "mongo/db/dur_recover.h" #include "mongo/db/dur_stats.h" +#include "mongo/db/storage_options.h" #include "mongo/server.h" #include "mongo/util/concurrency/race.h" #include "mongo/util/mongoutils/hash.h" @@ -162,8 +162,8 @@ namespace mongo { "writeToDataFiles" << (unsigned) (_writeToDataFilesMicros/1000) << "remapPrivateView" << (unsigned) (_remapPrivateViewMicros/1000) ); - if( cmdLine.journalCommitInterval != 0 ) - b << "journalCommitIntervalMs" << cmdLine.journalCommitInterval; + if (storageGlobalParams.journalCommitInterval != 0) + b << "journalCommitIntervalMs" << storageGlobalParams.journalCommitInterval; return b.obj(); } @@ -350,7 +350,7 @@ namespace mongo { static int n; ++n; - verify(debug && cmdLine.dur); + verify(debug && storageGlobalParams.dur); if (commitJob.writes().empty()) return; const WriteIntent &i = commitJob.lastWrite(); @@ -449,7 +449,7 @@ namespace mongo { /** (SLOW) diagnostic to check that the private view and the non-private view are in sync. */ void debugValidateAllMapsMatch() { - if( ! (cmdLine.durOptions & CmdLine::DurParanoid) ) + if (!(storageGlobalParams.durOptions & StorageGlobalParams::DurParanoid)) return; unsigned long long bytes = 0; @@ -478,7 +478,7 @@ namespace mongo { // remapping. unsigned long long now = curTimeMicros64(); double fraction = (now-lastRemap)/2000000.0; - if( cmdLine.durOptions & CmdLine::DurAlwaysRemap ) + if (storageGlobalParams.durOptions & StorageGlobalParams::DurAlwaysRemap) fraction = 1; lastRemap = now; @@ -746,7 +746,9 @@ namespace mongo { const int N = 10; static int n; - if( privateMapBytes < UncommittedBytesLimit && ++n % N && (cmdLine.durOptions&CmdLine::DurAlwaysRemap)==0 ) { + if (privateMapBytes < UncommittedBytesLimit && ++n % N && + (storageGlobalParams.durOptions & + StorageGlobalParams::DurAlwaysRemap) == 0) { // limited locks version doesn't do any remapprivateview at all, so only try this if privateMapBytes // is in an acceptable range. also every Nth commit, we do everything so we can do some remapping; // remapping a lot all at once could cause jitter from a large amount of copy-on-writes all at once. @@ -767,7 +769,7 @@ namespace mongo { views disappear */ void closingFileNotification() { - if (!cmdLine.dur) + if (!storageGlobalParams.dur) return; if( Lock::isLocked() ) { @@ -789,7 +791,8 @@ namespace mongo { bool samePartition = true; try { - const string dbpathDir = boost::filesystem::path(dbpath).string(); + const std::string dbpathDir = + boost::filesystem::path(storageGlobalParams.dbpath).string(); samePartition = onSamePartition(getJournalDir().string(), dbpathDir); } catch(...) { @@ -798,7 +801,7 @@ namespace mongo { while( !inShutdown() ) { RACECHECK - unsigned ms = cmdLine.journalCommitInterval; + unsigned ms = storageGlobalParams.journalCommitInterval; if( ms == 0 ) { // use default ms = samePartition ? 100 : 30; @@ -841,17 +844,17 @@ namespace mongo { /** at startup, recover, and then start the journal threads */ void startup() { - if( !cmdLine.dur ) + if (!storageGlobalParams.dur) return; #if defined(_DURABLEDEFAULTON) DEV { if( time(0) & 1 ) { - cmdLine.durOptions |= CmdLine::DurAlwaysCommit; + storageGlobalParams.durOptions |= StorageGlobalParams::DurAlwaysCommit; log() << "_DEBUG _DURABLEDEFAULTON : forcing DurAlwaysCommit mode for this run" << endl; } if( time(0) & 2 ) { - cmdLine.durOptions |= CmdLine::DurAlwaysRemap; + storageGlobalParams.durOptions |= StorageGlobalParams::DurAlwaysRemap; log() << "_DEBUG _DURABLEDEFAULTON : forcing DurAlwaysRemap mode for this run" << endl; } } @@ -904,7 +907,7 @@ namespace mongo { virtual bool includeByDefault() const { return true; } BSONObj generateSection(const BSONElement& configElement) const { - if ( ! cmdLine.dur ) + if (!storageGlobalParams.dur) return BSONObj(); return dur::stats.asObj(); } diff --git a/src/mongo/db/dur.h b/src/mongo/db/dur.h index f32551b7b30..2ae50ef62d7 100644 --- a/src/mongo/db/dur.h +++ b/src/mongo/db/dur.h @@ -49,7 +49,7 @@ namespace mongo { /** Call during startup so durability module can initialize Throws if fatal error - Does nothing if cmdLine.dur is false + Does nothing if storageGlobalParams.dur is false */ void startup(); diff --git a/src/mongo/db/dur_commitjob.cpp b/src/mongo/db/dur_commitjob.cpp index 91e90924692..f755f908180 100644 --- a/src/mongo/db/dur_commitjob.cpp +++ b/src/mongo/db/dur_commitjob.cpp @@ -179,7 +179,7 @@ namespace mongo { /** note an operation other than a "basic write" */ void CommitJob::noteOp(shared_ptr<DurOp> p) { - dassert( cmdLine.dur ); + dassert(storageGlobalParams.dur); // DurOp's are rare so it is ok to have the lock cost here SimpleMutex::scoped_lock lk(groupCommitMutex); cc().writeHappened(); diff --git a/src/mongo/db/dur_commitjob.h b/src/mongo/db/dur_commitjob.h index 1bc8865dc65..6d5863e0c7d 100644 --- a/src/mongo/db/dur_commitjob.h +++ b/src/mongo/db/dur_commitjob.h @@ -30,7 +30,6 @@ #pragma once -#include "mongo/db/cmdline.h" #include "mongo/db/d_concurrency.h" #include "mongo/db/dur.h" #include "mongo/db/durop.h" diff --git a/src/mongo/db/dur_journal.cpp b/src/mongo/db/dur_journal.cpp index 0b2281b3e31..bb466139f2e 100644 --- a/src/mongo/db/dur_journal.cpp +++ b/src/mongo/db/dur_journal.cpp @@ -36,10 +36,12 @@ #include <boost/filesystem.hpp> #include <boost/filesystem/operations.hpp> +#include "mongo/base/init.h" #include "mongo/db/client.h" #include "mongo/db/dur_journalformat.h" #include "mongo/db/dur_journalimpl.h" #include "mongo/db/dur_stats.h" +#include "mongo/db/storage_options.h" #include "mongo/platform/random.h" #include "mongo/server.h" #include "mongo/util/alignedbuilder.h" @@ -77,6 +79,14 @@ namespace mongo { unsigned long long DataLimitPerJournalFile = (sizeof(void*)==4) ? 256 * 1024 * 1024 : 1 * 1024 * 1024 * 1024; #endif + MONGO_INITIALIZER(InitializeJournalingParams)(InitializerContext* context) { + if (storageGlobalParams.smallfiles == true) { + verify(dur::DataLimitPerJournalFile >= 128 * 1024 * 1024); + dur::DataLimitPerJournalFile = 128 * 1024 * 1024; + } + return Status::OK(); + } + BOOST_STATIC_ASSERT( sizeof(Checksum) == 16 ); BOOST_STATIC_ASSERT( sizeof(JHeader) == 8192 ); BOOST_STATIC_ASSERT( sizeof(JSectHeader) == 20 ); @@ -89,7 +99,7 @@ namespace mongo { void removeOldJournalFile(boost::filesystem::path p); boost::filesystem::path getJournalDir() { - boost::filesystem::path p(dbpath); + boost::filesystem::path p(storageGlobalParams.dbpath); p /= "journal"; return p; } @@ -405,12 +415,12 @@ namespace mongo { } void preallocateFiles() { - if (! (cmdLine.durOptions & CmdLine::DurNoCheckSpace)) + if (!(storageGlobalParams.durOptions & StorageGlobalParams::DurNoCheckSpace)) checkFreeSpace(); if( exists(preallocPath(0)) || // if enabled previously, keep using exists(preallocPath(1)) || - ( cmdLine.preallocj && preallocateIsFaster() ) ) { + (storageGlobalParams.preallocj && preallocateIsFaster()) ) { usingPreallocate = true; try { _preallocateFiles(); diff --git a/src/mongo/db/dur_preplogbuffer.cpp b/src/mongo/db/dur_preplogbuffer.cpp index 1999602a938..1c28a358f04 100644 --- a/src/mongo/db/dur_preplogbuffer.cpp +++ b/src/mongo/db/dur_preplogbuffer.cpp @@ -38,7 +38,6 @@ #include "mongo/pch.h" -#include "mongo/db/cmdline.h" #include "mongo/db/dur.h" #include "mongo/db/dur_commitjob.h" #include "mongo/db/dur_journal.h" @@ -174,7 +173,7 @@ namespace mongo { @return partially populated sectheader and _ab set */ static void _PREPLOGBUFFER(JSectHeader& h, AlignedBuilder& bb) { - verify( cmdLine.dur ); + verify(storageGlobalParams.dur); assertLockedForCommitting(); resetLogBuffer(h, bb); // adds JSectHeader diff --git a/src/mongo/db/dur_recover.cpp b/src/mongo/db/dur_recover.cpp index da886dd25ad..e6a7af033cb 100644 --- a/src/mongo/db/dur_recover.cpp +++ b/src/mongo/db/dur_recover.cpp @@ -36,7 +36,6 @@ #include <fcntl.h> #include <sys/stat.h> -#include "mongo/db/cmdline.h" #include "mongo/db/curop.h" #include "mongo/db/database.h" #include "mongo/db/db.h" @@ -49,6 +48,7 @@ #include "mongo/db/kill_current_op.h" #include "mongo/db/storage/durable_mapped_file.h" #include "mongo/db/pdfile.h" +#include "mongo/db/storage_options.h" #include "mongo/util/bufreader.h" #include "mongo/util/checksum.h" #include "mongo/util/compress.h" @@ -206,7 +206,7 @@ namespace mongo { ss << fileNo; // relative name -> full path name - boost::filesystem::path full(dbpath); + boost::filesystem::path full(storageGlobalParams.dbpath); full /= ss.str(); return full.string(); } @@ -349,8 +349,10 @@ namespace mongo { } void RecoveryJob::applyEntries(const vector<ParsedJournalEntry> &entries) { - bool apply = (cmdLine.durOptions & CmdLine::DurScanOnly) == 0; - bool dump = cmdLine.durOptions & CmdLine::DurDumpJournal; + bool apply = (storageGlobalParams.durOptions & + StorageGlobalParams::DurScanOnly) == 0; + bool dump = storageGlobalParams.durOptions & + StorageGlobalParams::DurDumpJournal; if( dump ) log() << "BEGIN section" << endl; @@ -457,7 +459,8 @@ namespace mongo { uasserted(13536, str::stream() << "journal version number mismatch " << h._version); } fileId = h.fileId; - if(cmdLine.durOptions & CmdLine::DurDumpJournal) { + if (storageGlobalParams.durOptions & + StorageGlobalParams::DurDumpJournal) { log() << "JHeader::fileId=" << fileId << endl; } } @@ -467,7 +470,8 @@ namespace mongo { JSectHeader h; br.peek(h); if( h.fileId != fileId ) { - if( debug || (cmdLine.durOptions & CmdLine::DurDumpJournal) ) { + if (debug || (storageGlobalParams.durOptions & + StorageGlobalParams::DurDumpJournal)) { log() << "Ending processFileBuffer at differing fileId want:" << fileId << " got:" << h.fileId << endl; log() << " sect len:" << h.sectionLen() << " seqnum:" << h.seqNumber << endl; } @@ -485,7 +489,7 @@ namespace mongo { } } catch( BufReader::eof& ) { - if( cmdLine.durOptions & CmdLine::DurDumpJournal ) + if (storageGlobalParams.durOptions & StorageGlobalParams::DurDumpJournal) log() << "ABRUPT END" << endl; return true; // abrupt end } @@ -534,8 +538,10 @@ namespace mongo { close(); - if( cmdLine.durOptions & CmdLine::DurScanOnly ) { - uasserted(13545, str::stream() << "--durOptions " << (int) CmdLine::DurScanOnly << " (scan only) specified"); + if (storageGlobalParams.durOptions & StorageGlobalParams::DurScanOnly) { + uasserted(13545, str::stream() << "--durOptions " + << (int) StorageGlobalParams::DurScanOnly + << " (scan only) specified"); } log() << "recover cleaning up" << endl; @@ -546,7 +552,7 @@ namespace mongo { } void _recover() { - verify( cmdLine.dur ); + verify(storageGlobalParams.dur); boost::filesystem::path p = getJournalDir(); if( !exists(p) ) { diff --git a/src/mongo/db/durop.cpp b/src/mongo/db/durop.cpp index 6e113c06b0c..6f32295aed7 100644 --- a/src/mongo/db/durop.cpp +++ b/src/mongo/db/durop.cpp @@ -45,8 +45,6 @@ using namespace mongoutils; namespace mongo { - extern string dbpath; // --dbpath parm - void _deleteDataFiles(const char *); namespace dur { diff --git a/src/mongo/db/explain.cpp b/src/mongo/db/explain.cpp index c88f1013667..b73f3081696 100644 --- a/src/mongo/db/explain.cpp +++ b/src/mongo/db/explain.cpp @@ -17,9 +17,9 @@ #include "mongo/db/explain.h" -#include "mongo/db/cmdline.h" -#include "mongo/util/net/sock.h" +#include "mongo/db/server_options.h" #include "mongo/util/mongoutils/str.h" +#include "mongo/util/net/sock.h" namespace mongo { @@ -263,7 +263,7 @@ namespace mongo { } string ExplainQueryInfo::server() { - return mongoutils::str::stream() << getHostNameCached() << ":" << cmdLine.port; + return mongoutils::str::stream() << getHostNameCached() << ":" << serverGlobalParams.port; } ExplainSinglePlanQueryInfo::ExplainSinglePlanQueryInfo() : diff --git a/src/mongo/db/extsort.cpp b/src/mongo/db/extsort.cpp index b4802122a0a..e4aeb5f53ca 100644 --- a/src/mongo/db/extsort.cpp +++ b/src/mongo/db/extsort.cpp @@ -44,6 +44,7 @@ #include <sys/types.h> #include "mongo/db/kill_current_op.h" +#include "mongo/db/storage_options.h" #include "mongo/platform/posix_fadvise.h" #include "mongo/util/file.h" @@ -79,7 +80,7 @@ namespace mongo { long maxFileSize) : _mayInterrupt(boost::make_shared<bool>(false)) , _sorter(Sorter<BSONObj, DiskLoc>::make( - SortOptions().TempDir(dbpath + "/_tmp") + SortOptions().TempDir(storageGlobalParams.dbpath + "/_tmp") .ExtSortAllowed() .MaxMemoryUsageBytes(maxFileSize), OldExtSortComparator(comp, _mayInterrupt))) @@ -126,8 +127,8 @@ namespace mongo { _sorted(0) { stringstream rootpath; - rootpath << dbpath; - if ( dbpath[dbpath.size()-1] != '/' ) + rootpath << storageGlobalParams.dbpath; + if (storageGlobalParams.dbpath[storageGlobalParams.dbpath.size()-1] != '/') rootpath << "/"; unsigned long long thisUniqueNumber; diff --git a/src/mongo/db/index_rebuilder.cpp b/src/mongo/db/index_rebuilder.cpp index ac1ae0ad350..6f3edbeae44 100644 --- a/src/mongo/db/index_rebuilder.cpp +++ b/src/mongo/db/index_rebuilder.cpp @@ -109,7 +109,7 @@ namespace mongo { } // If the indexBuildRetry flag isn't set, just clear the inProg flag - if (!cmdLine.indexBuildRetry) { + if (!serverGlobalParams.indexBuildRetry) { // If we crash between unsetting the inProg flag and cleaning up the index, the // index space will be lost. nsd->blowAwayInProgressIndexEntries(); diff --git a/src/mongo/db/initialize_server_global_state.cpp b/src/mongo/db/initialize_server_global_state.cpp index d23a6ef5835..3d66d684f4f 100644 --- a/src/mongo/db/initialize_server_global_state.cpp +++ b/src/mongo/db/initialize_server_global_state.cpp @@ -43,7 +43,6 @@ #include "mongo/client/sasl_client_authenticate.h" #include "mongo/db/auth/authorization_manager.h" #include "mongo/db/auth/security_key.h" -#include "mongo/db/cmdline.h" #include "mongo/logger/logger.h" #include "mongo/logger/message_event.h" #include "mongo/logger/message_event_utf8_encoder.h" @@ -68,7 +67,7 @@ namespace mongo { if ( sig == SIGUSR2 ) { ProcessId cur = ProcessId::getCurrent(); - if ( cur == cmdLine.parentProc || cur == cmdLine.leaderProc ) { + if (cur == serverGlobalParams.parentProc || cur == serverGlobalParams.leaderProc) { // signal indicates successful start allowing us to exit _exit(0); } @@ -79,10 +78,10 @@ namespace mongo { verify( signal(SIGUSR2 , launchSignal ) != SIG_ERR ); } - void CmdLine::launchOk() { - if ( cmdLine.doFork ) { + void signalForkSuccess() { + if (serverGlobalParams.doFork) { // killing leader will propagate to parent - verify( kill( cmdLine.leaderProc.toNative(), SIGUSR2 ) == 0 ); + verify(kill(serverGlobalParams.leaderProc.toNative(), SIGUSR2) == 0); } } #endif @@ -90,13 +89,14 @@ namespace mongo { static bool forkServer() { #ifndef _WIN32 - if (cmdLine.doFork) { - fassert(16447, !cmdLine.logpath.empty() || cmdLine.logWithSyslog); + if (serverGlobalParams.doFork) { + fassert(16447, !serverGlobalParams.logpath.empty() || + serverGlobalParams.logWithSyslog); cout.flush(); cerr.flush(); - cmdLine.parentProc = ProcessId::getCurrent(); + serverGlobalParams.parentProc = ProcessId::getCurrent(); // facilitate clean exit when child starts successfully setupLaunchSignals(); @@ -135,7 +135,7 @@ namespace mongo { } setsid(); - cmdLine.leaderProc = ProcessId::getCurrent(); + serverGlobalParams.leaderProc = ProcessId::getCurrent(); pid_t child2 = fork(); if (child2 == -1) { @@ -200,9 +200,9 @@ namespace mongo { #ifndef _WIN32 using logger::SyslogAppender; - if (cmdLine.logWithSyslog) { + if (serverGlobalParams.logWithSyslog) { StringBuilder sb; - sb << cmdLine.binaryName << "." << cmdLine.port; + sb << serverGlobalParams.binaryName << "." << serverGlobalParams.port; openlog(strdup(sb.str().c_str()), LOG_PID | LOG_CONS, LOG_USER); LogManager* manager = logger::globalLogManager(); manager->getGlobalDomain()->clearAppenders(); @@ -217,10 +217,10 @@ namespace mongo { } #endif // defined(_WIN32) - if (!cmdLine.logpath.empty()) { - fassert(16448, !cmdLine.logWithSyslog); + if (!serverGlobalParams.logpath.empty()) { + fassert(16448, !serverGlobalParams.logWithSyslog); std::string absoluteLogpath = boost::filesystem::absolute( - cmdLine.logpath, cmdLine.cwd).string(); + serverGlobalParams.logpath, serverGlobalParams.cwd).string(); bool exists; @@ -239,7 +239,8 @@ namespace mongo { "\" should name a file, not a directory."); } - if (!cmdLine.logAppend && boost::filesystem::is_regular(absoluteLogpath)) { + if (!serverGlobalParams.logAppend && + boost::filesystem::is_regular(absoluteLogpath)) { std::string renameTarget = absoluteLogpath + "." + terseCurrentTime(false); if (0 == rename(absoluteLogpath.c_str(), renameTarget.c_str())) { log() << "log file \"" << absoluteLogpath @@ -256,7 +257,8 @@ namespace mongo { } StatusWithRotatableFileWriter writer = - logger::globalRotatableFileManager()->openFile(absoluteLogpath, cmdLine.logAppend); + logger::globalRotatableFileManager()->openFile(absoluteLogpath, + serverGlobalParams.logAppend); if (!writer.isOK()) { return writer.getStatus(); } @@ -272,7 +274,7 @@ namespace mongo { new RotatableFileAppender<MessageEventEphemeral>( new MessageEventDetailsEncoder, writer.getValue()))); - if (cmdLine.logAppend && exists) { + if (serverGlobalParams.logAppend && exists) { log() << "***** SERVER RESTARTED *****" << endl; Status status = logger::RotatableFileWriter::Use(writer.getValue()).status(); @@ -290,24 +292,24 @@ namespace mongo { bool initializeServerGlobalState() { - Listener::globalTicketHolder.resize( cmdLine.maxConns ); + Listener::globalTicketHolder.resize(serverGlobalParams.maxConns); #ifndef _WIN32 - if (!fs::is_directory(cmdLine.socket)) { - cout << cmdLine.socket << " must be a directory" << endl; + if (!fs::is_directory(serverGlobalParams.socket)) { + cout << serverGlobalParams.socket << " must be a directory" << endl; return false; } #endif - if (!cmdLine.pidFile.empty()) { - if (!writePidFile(cmdLine.pidFile)) { + if (!serverGlobalParams.pidFile.empty()) { + if (!writePidFile(serverGlobalParams.pidFile)) { // error message logged in writePidFile return false; } } - if (!cmdLine.keyFile.empty() && cmdLine.clusterAuthMode != "x509") { - if (!setUpSecurityKey(cmdLine.keyFile)) { + if (!serverGlobalParams.keyFile.empty() && serverGlobalParams.clusterAuthMode != "x509") { + if (!setUpSecurityKey(serverGlobalParams.keyFile)) { // error message printed in setUpPrivateKey return false; } @@ -315,12 +317,13 @@ namespace mongo { // Auto-enable auth except if clusterAuthMode is not set. // clusterAuthMode is automatically set if a --keyfile parameter is provided. - if (!cmdLine.clusterAuthMode.empty()) { + if (!serverGlobalParams.clusterAuthMode.empty()) { AuthorizationManager::setAuthEnabled(true); } #ifdef MONGO_SSL - if (cmdLine.clusterAuthMode == "x509" || cmdLine.clusterAuthMode == "sendX509") { + if (serverGlobalParams.clusterAuthMode == "x509" || + serverGlobalParams.clusterAuthMode == "sendX509") { setInternalUserAuthParams(BSON(saslCommandMechanismFieldName << "MONGODB-X509" << saslCommandUserSourceFieldName << "$external" << saslCommandUserFieldName << diff --git a/src/mongo/db/initialize_server_global_state.h b/src/mongo/db/initialize_server_global_state.h index e2d558e71a0..68f25f77cf2 100644 --- a/src/mongo/db/initialize_server_global_state.h +++ b/src/mongo/db/initialize_server_global_state.h @@ -38,12 +38,19 @@ namespace mongo { bool initializeServerGlobalState(); /** - * Forks and detaches the server, on platforms that support it, if cmdLine.doFork is true. + * Forks and detaches the server, on platforms that support it, if serverGlobalParams.doFork is + * true. * * Call after processing the command line but before running mongo initializers. */ void forkServerOrDie(); + /** + * Notify the parent that we forked from that we have successfully completed basic + * initialization so it can stop waiting and exit. + */ + void signalForkSuccess(); + void setupCoreSignals(); } // namespace mongo diff --git a/src/mongo/db/instance.cpp b/src/mongo/db/instance.cpp index 043ebe96173..968b295c543 100644 --- a/src/mongo/db/instance.cpp +++ b/src/mongo/db/instance.cpp @@ -47,7 +47,6 @@ #include "mongo/db/auth/authorization_session.h" #include "mongo/db/background.h" #include "mongo/db/clientcursor.h" -#include "mongo/db/cmdline.h" #include "mongo/db/commands/fsync.h" #include "mongo/db/d_concurrency.h" #include "mongo/db/db.h" @@ -60,6 +59,7 @@ #include "mongo/db/json.h" #include "mongo/db/kill_current_op.h" #include "mongo/db/lasterror.h" +#include "mongo/db/mongod_options.h" #include "mongo/db/namespace_string.h" #include "mongo/db/ops/count.h" #include "mongo/db/ops/delete.h" @@ -70,6 +70,7 @@ #include "mongo/db/repl/is_master.h" #include "mongo/db/repl/oplog.h" #include "mongo/db/stats/counters.h" +#include "mongo/db/storage_options.h" #include "mongo/platform/process_id.h" #include "mongo/s/d_logic.h" #include "mongo/s/stale_exception.h" // for SendStaleConfigException @@ -97,8 +98,6 @@ namespace mongo { string dbExecCommand; - bool useHints = true; - KillCurrentOp killCurrentOp; int lockFile = 0; @@ -435,7 +434,7 @@ namespace mongo { OpDebug& debug = currentOp.debug(); debug.op = op; - long long logThreshold = cmdLine.slowMS; + long long logThreshold = serverGlobalParams.slowMS; bool shouldLog = logger::globalLogDomain()->shouldLog(logger::LogSeverity::Debug(1)); if ( op == dbQuery ) { @@ -961,7 +960,7 @@ namespace mongo { boost::filesystem::path path( usePath ); for ( boost::filesystem::directory_iterator i( path ); i != boost::filesystem::directory_iterator(); ++i ) { - if ( directoryperdb ) { + if (storageGlobalParams.directoryperdb) { boost::filesystem::path p = *i; string dbName = p.leaf().string(); p /= ( dbName + ".ns" ); @@ -1102,7 +1101,7 @@ namespace mongo { log() << "shutdown: waiting for fs preallocator..." << endl; FileAllocator::get()->waitUntilFinished(); - if( cmdLine.dur ) { + if (storageGlobalParams.dur) { log() << "shutdown: lock for final commit..." << endl; { int n = 10; @@ -1130,7 +1129,7 @@ namespace mongo { MemoryMappedFile::closeAllFiles( ss3 ); log() << ss3.str() << endl; - if( cmdLine.dur ) { + if (storageGlobalParams.dur) { dur::journalCleanup(true); } @@ -1239,7 +1238,7 @@ namespace mongo { } void acquirePathLock(bool doingRepair) { - string name = ( boost::filesystem::path( dbpath ) / "mongod.lock" ).string(); + string name = (boost::filesystem::path(storageGlobalParams.dbpath) / "mongod.lock").string(); bool oldFile = false; @@ -1288,7 +1287,7 @@ namespace mongo { "run with --repair again.\n" "**************"; } - else if (cmdLine.dur) { + else if (storageGlobalParams.dur) { if (!dur::haveJournalFiles(/*anyFiles=*/true)) { // Passing anyFiles=true as we are trying to protect against starting in an // unclean state with the journal directory unmounted. If there are any files, @@ -1342,7 +1341,7 @@ namespace mongo { } // Not related to lock file, but this is where we handle unclean shutdown - if( !cmdLine.dur && dur::haveJournalFiles() ) { + if (!storageGlobalParams.dur && dur::haveJournalFiles()) { cout << "**************" << endl; cout << "Error: journal files are present in journal directory, yet starting without journaling enabled." << endl; cout << "It is recommended that you start with journaling enabled so that recovery may occur." << endl; @@ -1366,7 +1365,7 @@ namespace mongo { // TODO - this is very bad that the code above not running here. // Not related to lock file, but this is where we handle unclean shutdown - if( !cmdLine.dur && dur::haveJournalFiles() ) { + if (!storageGlobalParams.dur && dur::haveJournalFiles()) { cout << "**************" << endl; cout << "Error: journal files are present in journal directory, yet starting without --journal enabled." << endl; cout << "It is recommended that you start with journaling enabled so that recovery may occur." << endl; @@ -1384,7 +1383,7 @@ namespace mongo { void DiagLog::openFile() { verify( f == 0 ); stringstream ss; - ss << dbpath << "/diaglog." << hex << time(0); + ss << storageGlobalParams.dbpath << "/diaglog." << hex << time(0); string name = ss.str(); f = new ofstream(name.c_str(), ios::out | ios::binary); if ( ! f->good() ) { diff --git a/src/mongo/db/instance.h b/src/mongo/db/instance.h index bb0307defcb..43f0674ce86 100644 --- a/src/mongo/db/instance.h +++ b/src/mongo/db/instance.h @@ -33,9 +33,9 @@ #include "mongo/client/dbclientinterface.h" #include "mongo/db/client.h" -#include "mongo/db/cmdline.h" #include "mongo/db/curop-inl.h" #include "mongo/db/dbmessage.h" +#include "mongo/db/storage_options.h" namespace mongo { @@ -69,7 +69,8 @@ namespace mongo { void assembleResponse( Message &m, DbResponse &dbresponse, const HostAndPort &client ); - void getDatabaseNames( vector< string > &names , const string& usePath = dbpath ); + void getDatabaseNames(vector<std::string> &names, + const std::string& usePath = storageGlobalParams.dbpath); /* returns true if there is no data on this server. useful when starting replication. local database does NOT count. diff --git a/src/mongo/db/introspect.cpp b/src/mongo/db/introspect.cpp index bee2531b37f..4642e9655d1 100644 --- a/src/mongo/db/introspect.cpp +++ b/src/mongo/db/introspect.cpp @@ -39,6 +39,7 @@ #include "mongo/db/introspect.h" #include "mongo/db/jsobj.h" #include "mongo/db/pdfile.h" +#include "mongo/db/storage_options.h" #include "mongo/util/goodies.h" namespace { @@ -134,8 +135,8 @@ namespace { try { Lock::DBWrite lk( currentOp.getNS() ); - if ( dbHolder()._isLoaded( nsToDatabase( currentOp.getNS() ) , dbpath ) ) { - Client::Context cx(currentOp.getNS(), dbpath); + if (dbHolder()._isLoaded(nsToDatabase(currentOp.getNS()), storageGlobalParams.dbpath)) { + Client::Context cx(currentOp.getNS(), storageGlobalParams.dbpath); _profile(c, currentOp, profileBufBuilder); } else { @@ -154,7 +155,7 @@ namespace { fassert(16372, db); const char* profileName = db->getProfilingNS(); NamespaceDetails* details = db->namespaceIndex().details(profileName); - if (!details && (cmdLine.defaultProfile || force)) { + if (!details && (serverGlobalParams.defaultProfile || force)) { // system.profile namespace doesn't exist; create it log() << "creating profile collection: " << profileName << endl; string myerrmsg; diff --git a/src/mongo/db/log_process_details.cpp b/src/mongo/db/log_process_details.cpp index 70eaa809ea7..f8447f245e9 100644 --- a/src/mongo/db/log_process_details.cpp +++ b/src/mongo/db/log_process_details.cpp @@ -32,7 +32,8 @@ #include "mongo/db/log_process_details.h" -#include "mongo/db/cmdline.h" +#include "mongo/db/server_options.h" +#include "mongo/util/net/sock.h" #include "mongo/util/net/ssl_manager.h" #include "mongo/util/processinfo.h" #include "mongo/util/version.h" @@ -54,7 +55,7 @@ namespace mongo { void logProcessDetailsForLogRotate() { log() << "pid=" << ProcessId::getCurrent() - << " port=" << cmdLine.port + << " port=" << serverGlobalParams.port << ( is32bit() ? " 32" : " 64" ) << "-bit " << "host=" << getHostNameCached(); diff --git a/src/mongo/db/mongod_options.cpp b/src/mongo/db/mongod_options.cpp index 7456a033c08..5f9a5b489f3 100644 --- a/src/mongo/db/mongod_options.cpp +++ b/src/mongo/db/mongod_options.cpp @@ -31,20 +31,30 @@ #include <string> #include <vector> +#include "mongo/base/init.h" #include "mongo/base/status.h" #include "mongo/bson/util/builder.h" +#include "mongo/db/auth/authorization_manager.h" +#include "mongo/db/instance.h" #include "mongo/db/module.h" +#include "mongo/db/pdfile.h" +#include "mongo/db/repl/replication_server_status.h" #include "mongo/db/server_options.h" +#include "mongo/util/mongoutils/str.h" #include "mongo/util/net/ssl_options.h" #include "mongo/util/options_parser/option_description.h" #include "mongo/util/options_parser/option_section.h" +#include "mongo/util/options_parser/options_parser.h" +#include "mongo/util/version.h" namespace mongo { typedef moe::OptionDescription OD; typedef moe::PositionalOptionDescription POD; - extern std::string dbpath; + MongodGlobalParams mongodGlobalParams; + + extern DiagLog _diaglog; Status addMongodOptions(moe::OptionSection* options) { @@ -78,9 +88,6 @@ namespace mongo { 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; @@ -90,8 +97,15 @@ namespace mongo { if (!ret.isOK()) { return ret; } +#ifdef _WIN32 + ret = general_options.addOption(OD("dbpath", "dbpath", moe::String, + "directory for datafiles - defaults to \\data\\db\\", + true, moe::Value(std::string("\\data\\db\\")))); +#else ret = general_options.addOption(OD("dbpath", "dbpath", moe::String, - dbpathBuilder.str().c_str(), true)); + "directory for datafiles - defaults to /data/db/", + true, moe::Value(std::string("/data/db")))); +#endif if (!ret.isOK()) { return ret; } @@ -383,6 +397,426 @@ namespace mongo { return Status::OK(); } + void printMongodHelp(const moe::OptionSection& options) { + std::cout << options.helpString() << std::endl; + }; + + namespace { + void sysRuntimeInfo() { + out() << "sysinfo:" << endl; +#if defined(_SC_PAGE_SIZE) + out() << " page size: " << (int) sysconf(_SC_PAGE_SIZE) << endl; +#endif +#if defined(_SC_PHYS_PAGES) + out() << " _SC_PHYS_PAGES: " << sysconf(_SC_PHYS_PAGES) << endl; +#endif +#if defined(_SC_AVPHYS_PAGES) + out() << " _SC_AVPHYS_PAGES: " << sysconf(_SC_AVPHYS_PAGES) << endl; +#endif + } + } // namespace + + Status handlePreValidationMongodOptions(const moe::Environment& params, + const std::vector<std::string>& args) { + if (params.count("help")) { + printMongodHelp(serverOptions); + ::_exit(EXIT_SUCCESS); + } + if (params.count("version")) { + cout << mongodVersion() << endl; + printGitVersion(); + printOpenSSLVersion(); + ::_exit(EXIT_SUCCESS); + } + if (params.count("sysinfo")) { + sysRuntimeInfo(); + ::_exit(EXIT_SUCCESS); + } + + return Status::OK(); + } + + Status storeMongodOptions(const moe::Environment& params, + const std::vector<std::string>& args) { + + Status ret = storeServerOptions(params, args); + if (!ret.isOK()) { + std::cerr << "Error storing command line: " << ret.toString() << std::endl; + ::_exit(EXIT_BADOPTIONS); + } + + if (params.count("dbpath")) { + storageGlobalParams.dbpath = params["dbpath"].as<string>(); + if (params.count("fork") && storageGlobalParams.dbpath[0] != '/') { + // we need to change dbpath if we fork since we change + // cwd to "/" + // fork only exists on *nix + // so '/' is safe + storageGlobalParams.dbpath = serverGlobalParams.cwd + "/" + + storageGlobalParams.dbpath; + } + } +#ifdef _WIN32 + if (storageGlobalParams.dbpath.size() > 1 && + storageGlobalParams.dbpath[storageGlobalParams.dbpath.size()-1] == '/') { + // size() check is for the unlikely possibility of --dbpath "/" + storageGlobalParams.dbpath = + storageGlobalParams.dbpath.erase(storageGlobalParams.dbpath.size()-1); + } +#endif + if ( params.count("slowms")) { + serverGlobalParams.slowMS = params["slowms"].as<int>(); + } + + if ( params.count("syncdelay")) { + storageGlobalParams.syncdelay = params["syncdelay"].as<double>(); + } + + if (params.count("directoryperdb")) { + storageGlobalParams.directoryperdb = true; + } + if (params.count("cpu")) { + serverGlobalParams.cpu = true; + } + if (params.count("noauth")) { + AuthorizationManager::setAuthEnabled(false); + } + if (params.count("auth")) { + AuthorizationManager::setAuthEnabled(true); + } + if (params.count("quota")) { + storageGlobalParams.quota = true; + } + if (params.count("quotaFiles")) { + storageGlobalParams.quota = true; + storageGlobalParams.quotaFiles = params["quotaFiles"].as<int>() - 1; + } + if ((params.count("nodur") || params.count("nojournal")) && + (params.count("dur") || params.count("journal"))) { + std::cerr << "Can't specify both --journal and --nojournal options." << std::endl; + ::_exit(EXIT_BADOPTIONS); + } + + if (params.count("nodur") || params.count("nojournal")) { + storageGlobalParams.dur = false; + } + + if (params.count("dur") || params.count("journal")) { + storageGlobalParams.dur = true; + } + + if (params.count("durOptions")) { + storageGlobalParams.durOptions = params["durOptions"].as<int>(); + } + if( params.count("journalCommitInterval") ) { + // don't check if dur is false here as many will just use the default, and will default + // to off on win32. ie no point making life a little more complex by giving an error on + // a dev environment. + storageGlobalParams.journalCommitInterval = + params["journalCommitInterval"].as<unsigned>(); + if (storageGlobalParams.journalCommitInterval <= 1 || + storageGlobalParams.journalCommitInterval > 300) { + std::cerr << "--journalCommitInterval out of allowed range (0-300ms)" << std::endl; + ::_exit(EXIT_BADOPTIONS); + } + } + if (params.count("journalOptions")) { + storageGlobalParams.durOptions = params["journalOptions"].as<int>(); + } + if (params.count("nohints")) { + storageGlobalParams.useHints = false; + } + if (params.count("nopreallocj")) { + storageGlobalParams.preallocj = false; + } + if (params.count("httpinterface")) { + if (params.count("nohttpinterface")) { + std::cerr << "can't have both --httpinterface and --nohttpinterface" << std::endl; + ::_exit(EXIT_BADOPTIONS); + } + serverGlobalParams.isHttpInterfaceEnabled = true; + } + // SERVER-10019 Enabling rest/jsonp without --httpinterface should break in the future + if (params.count("rest")) { + if (params.count("nohttpinterface")) { + log() << "** WARNING: Should not specify both --rest and --nohttpinterface" << + startupWarningsLog; + } + else if (!params.count("httpinterface")) { + log() << "** WARNING: --rest is specified without --httpinterface," << + startupWarningsLog; + log() << "** enabling http interface" << startupWarningsLog; + serverGlobalParams.isHttpInterfaceEnabled = true; + } + serverGlobalParams.rest = true; + } + if (params.count("jsonp")) { + if (params.count("nohttpinterface")) { + log() << "** WARNING: Should not specify both --jsonp and --nohttpinterface" << + startupWarningsLog; + } + else if (!params.count("httpinterface")) { + log() << "** WARNING --jsonp is specified without --httpinterface," << + startupWarningsLog; + log() << "** enabling http interface" << startupWarningsLog; + serverGlobalParams.isHttpInterfaceEnabled = true; + } + serverGlobalParams.jsonp = true; + } + if (params.count("noscripting")) { + mongodGlobalParams.scriptingEnabled = false; + } + if (params.count("noprealloc")) { + storageGlobalParams.prealloc = false; + cout << "note: noprealloc may hurt performance in many applications" << endl; + } + if (params.count("smallfiles")) { + storageGlobalParams.smallfiles = true; + } + if (params.count("diaglog")) { + int x = params["diaglog"].as<int>(); + if ( x < 0 || x > 7 ) { + std::cerr << "can't interpret --diaglog setting" << std::endl; + ::_exit(EXIT_BADOPTIONS); + } + _diaglog.setLevel(x); + } + + if ((params.count("dur") || params.count("journal")) && params.count("repair")) { + std::cerr << "Can't specify both --journal and --repair options." << std::endl; + ::_exit(EXIT_BADOPTIONS); + } + + if (params.count("repair")) { + Record::MemoryTrackingEnabled = false; + mongodGlobalParams.upgrade = 1; // --repair implies --upgrade + mongodGlobalParams.repair = 1; + storageGlobalParams.dur = false; + } + if (params.count("upgrade")) { + Record::MemoryTrackingEnabled = false; + mongodGlobalParams.upgrade = 1; + } + if (params.count("notablescan")) { + storageGlobalParams.noTableScan = true; + } + if (params.count("master")) { + replSettings.master = true; + } + if (params.count("slave")) { + replSettings.slave = SimpleSlave; + } + if (params.count("slavedelay")) { + replSettings.slavedelay = params["slavedelay"].as<int>(); + } + if (params.count("fastsync")) { + replSettings.fastsync = true; + } + if (params.count("autoresync")) { + replSettings.autoresync = true; + if( params.count("replSet") ) { + std::cerr << "--autoresync is not used with --replSet\nsee " + << "http://dochub.mongodb.org/core/resyncingaverystalereplicasetmember" + << std::endl; + ::_exit(EXIT_BADOPTIONS); + } + } + if (params.count("source")) { + /* specifies what the source in local.sources should be */ + replSettings.source = params["source"].as<string>().c_str(); + } + if( params.count("pretouch") ) { + replSettings.pretouch = params["pretouch"].as<int>(); + } + if (params.count("replSet")) { + if (params.count("slavedelay")) { + std::cerr << "--slavedelay cannot be used with --replSet" << std::endl; + ::_exit(EXIT_BADOPTIONS); + } + else if (params.count("only")) { + std::cerr << "--only cannot be used with --replSet" << std::endl; + ::_exit(EXIT_BADOPTIONS); + } + /* seed list of hosts for the repl set */ + replSettings.replSet = params["replSet"].as<string>().c_str(); + } + if (params.count("replIndexPrefetch")) { + replSettings.rsIndexPrefetch = params["replIndexPrefetch"].as<std::string>(); + } + if (params.count("noIndexBuildRetry")) { + serverGlobalParams.indexBuildRetry = false; + } + if (params.count("only")) { + replSettings.only = params["only"].as<string>().c_str(); + } + if( params.count("nssize") ) { + int x = params["nssize"].as<int>(); + if (x <= 0 || x > (0x7fffffff/1024/1024)) { + std::cerr << "bad --nssize arg" << std::endl; + ::_exit(EXIT_BADOPTIONS); + } + storageGlobalParams.lenForNewNsFiles = x * 1024 * 1024; + verify(storageGlobalParams.lenForNewNsFiles > 0); + } + if (params.count("oplogSize")) { + long long x = params["oplogSize"].as<int>(); + if (x <= 0) { + 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 ) { + 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); + } + replSettings.oplogSize = x * 1024 * 1024; + verify(replSettings.oplogSize > 0); + } + if (params.count("cacheSize")) { + long x = params["cacheSize"].as<long>(); + if (x <= 0) { + std::cerr << "bad --cacheSize arg" << std::endl; + ::_exit(EXIT_BADOPTIONS); + } + std::cerr << "--cacheSize option not currently supported" << std::endl; + ::_exit(EXIT_BADOPTIONS); + } + if (!params.count("port")) { + if( params.count("configsvr") ) { + serverGlobalParams.port = ServerGlobalParams::ConfigServerPort; + } + if( params.count("shardsvr") ) { + if( params.count("configsvr") ) { + std::cerr << "can't do --shardsvr and --configsvr at the same time" + << std::endl; + ::_exit(EXIT_BADOPTIONS); + } + serverGlobalParams.port = ServerGlobalParams::ShardServerPort; + } + } + else { + if (serverGlobalParams.port <= 0 || serverGlobalParams.port > 65535) { + std::cerr << "bad --port number" << std::endl; + ::_exit(EXIT_BADOPTIONS); + } + } + if ( params.count("configsvr" ) ) { + serverGlobalParams.configsvr = true; + storageGlobalParams.smallfiles = true; // config server implies small files + if (replSettings.usingReplSets() || replSettings.master || replSettings.slave) { + std::cerr << "replication should not be enabled on a config server" << std::endl; + ::_exit(EXIT_BADOPTIONS); + } + if (!params.count("nodur") && !params.count("nojournal")) + storageGlobalParams.dur = true; + if (!params.count("dbpath")) + storageGlobalParams.dbpath = "/data/configdb"; + replSettings.master = true; + if (!params.count("oplogSize")) + replSettings.oplogSize = 5 * 1024 * 1024; + } + if ( params.count( "profile" ) ) { + serverGlobalParams.defaultProfile = params["profile"].as<int>(); + } + if (params.count("ipv6")) { + enableIPv6(); + } + + if (params.count("noMoveParanoia") && params.count("moveParanoia")) { + 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")) + serverGlobalParams.moveParanoia = false; + + if (params.count("moveParanoia")) + serverGlobalParams.moveParanoia = true; + + if (params.count("pairwith") || params.count("arbiter") || params.count("opIdMem")) { + 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 (params.count("repairpath")) { + storageGlobalParams.repairpath = params["repairpath"].as<string>(); + if (!storageGlobalParams.repairpath.size()) { + std::cerr << "repairpath is empty" << std::endl; + ::_exit(EXIT_BADOPTIONS); + } + + if (storageGlobalParams.dur && + !str::startsWith(storageGlobalParams.repairpath, + storageGlobalParams.dbpath)) { + std::cerr << "You must use a --repairpath that is a subdirectory of " + << "--dbpath when using journaling" << std::endl; + ::_exit(EXIT_BADOPTIONS); + } + } + else { + storageGlobalParams.repairpath = storageGlobalParams.dbpath; + } + + if (replSettings.pretouch) + log() << "--pretouch " << replSettings.pretouch << endl; + + if (sizeof(void*) == 4 && !(params.count("nodur") || params.count("nojournal") || + params.count("dur") || params.count("journal"))) { + // 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) { + + serverOptions = moe::OptionSection("Allowed options"); + Status ret = addMongodOptions(&serverOptions); + if (!ret.isOK()) { + return ret; + } + + moe::OptionsParser parser; + ret = parser.run(serverOptions, context->args(), context->env(), &serverParsedOptions); + if (!ret.isOK()) { + std::cerr << "Error parsing command line: " << ret.toString() << std::endl; + std::cerr << "use --help for help" << std::endl; + ::_exit(EXIT_BADOPTIONS); + } + + ret = handlePreValidationMongodOptions(serverParsedOptions, context->args()); + if (!ret.isOK()) { + return ret; + } + + ret = serverParsedOptions.validate(); + if (!ret.isOK()) { + return ret; + } + + ret = storeMongodOptions(serverParsedOptions, context->args()); + if (!ret.isOK()) { + return ret; + } + + return Status::OK(); + } + Status addModuleOptions(moe::OptionSection* options) { Module::addAllOptions(options); return Status::OK(); diff --git a/src/mongo/db/mongod_options.h b/src/mongo/db/mongod_options.h index e507802684d..b5bab35e441 100644 --- a/src/mongo/db/mongod_options.h +++ b/src/mongo/db/mongod_options.h @@ -29,6 +29,8 @@ #pragma once #include "mongo/base/status.h" +#include "mongo/db/server_options.h" +#include "mongo/db/storage_options.h" namespace mongo { @@ -38,7 +40,28 @@ namespace mongo { namespace moe = mongo::optionenvironment; + struct MongodGlobalParams { + bool upgrade; + bool repair; + bool scriptingEnabled; // --noscripting + + MongodGlobalParams() : + upgrade(0), + repair(0), + scriptingEnabled(true) + { } + }; + + extern MongodGlobalParams mongodGlobalParams; + Status addMongodOptions(moe::OptionSection* options); + void printMongodHelp(const moe::OptionSection& options); + + Status handlePreValidationMongodOptions(const moe::Environment& params, + const std::vector<std::string>& args); + + Status storeMongodOptions(const moe::Environment& params, const std::vector<std::string>& args); + Status addModuleOptions(moe::OptionSection* options); } diff --git a/src/mongo/db/namespace_details.cpp b/src/mongo/db/namespace_details.cpp index daf308f5805..7aaf30ed940 100644 --- a/src/mongo/db/namespace_details.cpp +++ b/src/mongo/db/namespace_details.cpp @@ -90,7 +90,7 @@ namespace mongo { #if defined(_DEBUG) void NamespaceDetails::dump(const Namespace& k) { - if( !cmdLine.dur ) + if (!storageGlobalParams.dur) cout << "ns offsets which follow will not display correctly with --journal disabled" << endl; size_t ofs = 1; // 1 is sentinel that the find call below failed diff --git a/src/mongo/db/namespace_details.h b/src/mongo/db/namespace_details.h index 5129ba1724f..168ee241bce 100644 --- a/src/mongo/db/namespace_details.h +++ b/src/mongo/db/namespace_details.h @@ -645,8 +645,4 @@ namespace mongo { } return make_inlock(ns); } - - extern string dbpath; // --dbpath parm - extern bool directoryperdb; - } // namespace mongo diff --git a/src/mongo/db/ops/query.cpp b/src/mongo/db/ops/query.cpp index ceb86e427cc..05d9ad81f35 100644 --- a/src/mongo/db/ops/query.cpp +++ b/src/mongo/db/ops/query.cpp @@ -49,6 +49,7 @@ #include "mongo/db/repl/oplog.h" #include "mongo/db/repl/repl_reads_ok.h" #include "mongo/db/scanandorder.h" +#include "mongo/db/storage_options.h" #include "mongo/s/d_logic.h" #include "mongo/s/stale_exception.h" // for SendStaleConfigException #include "mongo/server.h" @@ -949,7 +950,7 @@ namespace mongo { BSONObj resObject; // put inside since we don't own the memory - Client::ReadContext ctx( ns , dbpath ); // read locks + Client::ReadContext ctx(ns, storageGlobalParams.dbpath); // read locks replVerifyReadsOk(&pq); bool found = Helpers::findById( currentClient, ns, query, resObject, &nsFound, &indexFound ); @@ -1116,7 +1117,7 @@ namespace mongo { } try { - Client::ReadContext ctx( ns , dbpath ); // read locks + Client::ReadContext ctx(ns, storageGlobalParams.dbpath); // read locks const ChunkVersion shardingVersionAtStart = shardingState.getVersion( ns ); replVerifyReadsOk(&pq); diff --git a/src/mongo/db/pdfile.cpp b/src/mongo/db/pdfile.cpp index 3f0a684e5fe..852e0d4d76e 100644 --- a/src/mongo/db/pdfile.cpp +++ b/src/mongo/db/pdfile.cpp @@ -73,6 +73,7 @@ _ disallow system* manipulations from the database. #include "mongo/db/repl/is_master.h" #include "mongo/db/sort_phase_one.h" #include "mongo/db/repl/oplog.h" +#include "mongo/db/storage_options.h" #include "mongo/util/assert_util.h" #include "mongo/util/file.h" #include "mongo/util/file_allocator.h" @@ -124,8 +125,6 @@ namespace mongo { /* ----------------------------------------- */ const char FREELIST_NS[] = ".$freelist"; - bool directoryperdb = false; - string repairpath; string pidfilepath; DataFileMgr theDataFileMgr; @@ -180,12 +179,16 @@ namespace mongo { virtual const char * op() const = 0; }; - void _applyOpToDataFiles( const char *database, FileOp &fo, bool afterAllocator = false, const string& path = dbpath ); + void _applyOpToDataFiles(const char *database, FileOp &fo, bool afterAllocator = false, + const string& path = storageGlobalParams.dbpath); void _deleteDataFiles(const char *database) { - if ( directoryperdb ) { + if (storageGlobalParams.directoryperdb) { FileAllocator::get()->waitUntilFinished(); - MONGO_ASSERT_ON_EXCEPTION_WITH_MSG( boost::filesystem::remove_all( boost::filesystem::path( dbpath ) / database ), "delete data files with a directoryperdb" ); + MONGO_ASSERT_ON_EXCEPTION_WITH_MSG( + boost::filesystem::remove_all( + boost::filesystem::path(storageGlobalParams.dbpath) / database), + "delete data files with a directoryperdb"); return; } class : public FileOp { @@ -200,7 +203,7 @@ namespace mongo { } void checkConfigNS(const char *ns) { - if ( cmdLine.configsvr && + if ( serverGlobalParams.configsvr && !( str::startsWith( ns, "config." ) || str::startsWith( ns, "local." ) || str::startsWith( ns, "admin." ) ) ) { @@ -1273,7 +1276,7 @@ namespace mongo { // back up original database files to 'temp' dir void _renameForBackup( const char *database, const Path &reservedPath ) { Path newPath( reservedPath ); - if ( directoryperdb ) + if (storageGlobalParams.directoryperdb) newPath /= database; class Renamer : public FileOp { public: @@ -1295,8 +1298,8 @@ namespace mongo { // move temp files to standard data dir void _replaceWithRecovered( const char *database, const char *reservedPathString ) { - Path newPath( dbpath ); - if ( directoryperdb ) + Path newPath(storageGlobalParams.dbpath); + if (storageGlobalParams.directoryperdb) newPath /= database; class Replacer : public FileOp { public: @@ -1318,7 +1321,7 @@ namespace mongo { // generate a directory name for storing temp data files Path uniqueReservedPath( const char *prefix ) { - Path repairPath = Path( repairpath ); + Path repairPath = Path(storageGlobalParams.repairpath); Path reservedPath; int i = 0; bool exists = false; @@ -1363,19 +1366,19 @@ namespace mongo { const char * dbName = dbNameS.c_str(); stringstream ss; - ss << "localhost:" << cmdLine.port; + ss << "localhost:" << serverGlobalParams.port; string localhost = ss.str(); problem() << "repairDatabase " << dbName << endl; verify( cc().database()->name() == dbName ); - verify( cc().database()->path() == dbpath ); + verify(cc().database()->path() == storageGlobalParams.dbpath); BackgroundOperation::assertNoBgOpInProgForDb(dbName); getDur().syncDataAndTruncateJournal(); // Must be done before and after repair boost::intmax_t totalSize = dbSize( dbName ); - boost::intmax_t freeSize = File::freeSpace(repairpath); + boost::intmax_t freeSize = File::freeSpace(storageGlobalParams.repairpath); if ( freeSize > -1 && freeSize < totalSize ) { stringstream ss; ss << "Cannot repair database " << dbName << " having size: " << totalSize @@ -1421,14 +1424,15 @@ namespace mongo { } Client::Context ctx( dbName ); - Database::closeDatabase( dbName, dbpath ); + Database::closeDatabase(dbName, storageGlobalParams.dbpath); if ( backupOriginalFiles ) { _renameForBackup( dbName, reservedPath ); } else { _deleteDataFiles( dbName ); - MONGO_ASSERT_ON_EXCEPTION( boost::filesystem::create_directory( Path( dbpath ) / dbName ) ); + MONGO_ASSERT_ON_EXCEPTION( + boost::filesystem::create_directory(Path(storageGlobalParams.dbpath) / dbName)); } _replaceWithRecovered( dbName, reservedPathString.c_str() ); @@ -1445,7 +1449,7 @@ namespace mongo { string c = database; c += '.'; boost::filesystem::path p(path); - if ( directoryperdb ) + if (storageGlobalParams.directoryperdb) p /= database; boost::filesystem::path q; q = p / (c+"ns"); diff --git a/src/mongo/db/pipeline/document_source_cursor.cpp b/src/mongo/db/pipeline/document_source_cursor.cpp index 009697a58f7..e399d90e28c 100644 --- a/src/mongo/db/pipeline/document_source_cursor.cpp +++ b/src/mongo/db/pipeline/document_source_cursor.cpp @@ -34,6 +34,7 @@ #include "mongo/db/instance.h" #include "mongo/db/ops/query.h" #include "mongo/db/pipeline/document.h" +#include "mongo/db/storage_options.h" #include "mongo/s/d_logic.h" #include "mongo/s/stale_exception.h" // for SendStaleConfigException @@ -106,7 +107,7 @@ namespace mongo { // We have already validated the sharding version when we constructed the cursor // so we shouldn't check it again. Lock::DBRead lk(ns); - Client::Context ctx(ns, dbpath, /*doVersion=*/false); + Client::Context ctx(ns, storageGlobalParams.dbpath, /*doVersion=*/false); ClientCursorPin pin(_cursorId); ClientCursor* cursor = pin.c(); @@ -212,7 +213,7 @@ namespace mongo { return Value(); Lock::DBRead lk(ns); - Client::Context ctx(ns, dbpath, /*doVersion=*/false); + Client::Context ctx(ns, storageGlobalParams.dbpath, /*doVersion=*/false); ClientCursorPin pin(_cursorId); ClientCursor* cursor = pin.c(); diff --git a/src/mongo/db/pipeline/document_source_merge_cursors.cpp b/src/mongo/db/pipeline/document_source_merge_cursors.cpp index 194e3c1b262..d3f4c5f1bcf 100644 --- a/src/mongo/db/pipeline/document_source_merge_cursors.cpp +++ b/src/mongo/db/pipeline/document_source_merge_cursors.cpp @@ -30,7 +30,6 @@ #include "mongo/db/pipeline/document_source.h" -#include "mongo/db/cmdline.h" namespace mongo { diff --git a/src/mongo/db/query/new_find.cpp b/src/mongo/db/query/new_find.cpp index 295ba4a9996..a3d6fce6afe 100644 --- a/src/mongo/db/query/new_find.cpp +++ b/src/mongo/db/query/new_find.cpp @@ -45,7 +45,9 @@ #include "mongo/db/query/stage_builder.h" #include "mongo/db/query/type_explain.h" #include "mongo/db/repl/repl_reads_ok.h" +#include "mongo/db/server_options.h" #include "mongo/db/server_parameters.h" +#include "mongo/db/storage_options.h" #include "mongo/s/chunk_version.h" #include "mongo/s/d_logic.h" #include "mongo/s/stale_exception.h" @@ -166,7 +168,7 @@ namespace mongo { vector<QuerySolution*> solutions; size_t options = QueryPlanner::DEFAULT; - if (cmdLine.noTableScan) { + if (storageGlobalParams.noTableScan) { const string& ns = canonicalQuery->ns(); // There are certain cases where we ignore this restriction: bool ignore = canonicalQuery->getQueryObj().isEmpty() @@ -386,7 +388,7 @@ namespace mongo { */ std::string newRunQuery(Message& m, QueryMessage& q, CurOp& curop, Message &result) { // This is a read lock. - Client::ReadContext ctx(q.ns, dbpath); + Client::ReadContext ctx(q.ns, storageGlobalParams.dbpath); // Parse, canonicalize, plan, transcribe, and get a runner. Runner* rawRunner; @@ -560,7 +562,7 @@ namespace mongo { // Fill in the missing run-time fields in explain, starting with propeties of // the process running the query. std::string server = mongoutils::str::stream() - << getHostNameCached() << ":" << cmdLine.port; + << getHostNameCached() << ":" << serverGlobalParams.port; explain->setServer(server); // Fill in the number of documents consummed that were involved in an ongoing diff --git a/src/mongo/db/query_plan.cpp b/src/mongo/db/query_plan.cpp index 6fd0d78889c..36d58c0b10b 100644 --- a/src/mongo/db/query_plan.cpp +++ b/src/mongo/db/query_plan.cpp @@ -29,7 +29,6 @@ #include "mongo/db/query_plan.h" #include "mongo/db/btreecursor.h" -#include "mongo/db/cmdline.h" #include "mongo/db/index_selection.h" #include "mongo/db/index/catalog_hack.h" #include "mongo/db/index/emulated_cursor.h" @@ -370,7 +369,7 @@ doneCheckOrder: } void QueryPlan::checkTableScanAllowed() const { - if ( likely( !cmdLine.noTableScan ) ) + if (likely(!storageGlobalParams.noTableScan)) return; // TODO - is this desirable? See SERVER-2222. @@ -386,7 +385,8 @@ doneCheckOrder: if ( !nsdetails( ns() ) ) return; - uassert( 10111, (string)"table scans not allowed:" + ns(), !cmdLine.noTableScan ); + uassert(10111, (string)"table scans not allowed:" + ns(), + !storageGlobalParams.noTableScan); } int QueryPlan::independentRangesSingleIntervalLimit() const { diff --git a/src/mongo/db/queryoptimizercursorimpl.cpp b/src/mongo/db/queryoptimizercursorimpl.cpp index 76e78a276bc..0545aa7ea9f 100644 --- a/src/mongo/db/queryoptimizercursorimpl.cpp +++ b/src/mongo/db/queryoptimizercursorimpl.cpp @@ -38,8 +38,6 @@ namespace mongo { - extern bool useHints; - QueryOptimizerCursorImpl* QueryOptimizerCursorImpl::make ( auto_ptr<MultiPlanScanner>& mps, const QueryPlanSelectionPolicy& planPolicy, @@ -394,7 +392,7 @@ namespace mongo { } void CursorGenerator::setArgumentsHint() { - if ( useHints && _parsedQuery ) { + if (storageGlobalParams.useHints && _parsedQuery) { _argumentsHint = _parsedQuery->getHint(); } diff --git a/src/mongo/db/range_deleter_db_env.cpp b/src/mongo/db/range_deleter_db_env.cpp index 5b76f118d22..326fdbfd825 100644 --- a/src/mongo/db/range_deleter_db_env.cpp +++ b/src/mongo/db/range_deleter_db_env.cpp @@ -31,7 +31,6 @@ #include "mongo/db/auth/authorization_manager.h" #include "mongo/db/auth/authorization_session.h" #include "mongo/db/clientcursor.h" -#include "mongo/db/cmdline.h" #include "mongo/db/dbhelpers.h" #include "mongo/db/repl/rs.h" #include "mongo/db/repl/write_concern.h" @@ -85,7 +84,7 @@ namespace mongo { keyPattern), false, /*maxInclusive*/ replSet? secondaryThrottle : false, - cmdLine.moveParanoia ? &removeSaver : NULL, + serverGlobalParams.moveParanoia ? &removeSaver : NULL, true, /*fromMigrate*/ true); /*onlyRemoveOrphans*/ diff --git a/src/mongo/db/repl/consensus.cpp b/src/mongo/db/repl/consensus.cpp index 68e6cb5b456..3f7c8d65822 100644 --- a/src/mongo/db/repl/consensus.cpp +++ b/src/mongo/db/repl/consensus.cpp @@ -28,7 +28,6 @@ #include "mongo/pch.h" -#include "mongo/db/cmdline.h" #include "mongo/db/commands.h" #include "mongo/db/repl/multicmd.h" #include "mongo/db/repl/rs.h" @@ -385,7 +384,7 @@ namespace mongo { rs.sethbmsg("",9); - if( !allUp && time(0) - cmdLine.started < 60 * 5 ) { + if (!allUp && time(0) - serverGlobalParams.started < 60 * 5) { /* the idea here is that if a bunch of nodes bounce all at once, we don't want to drop data if we don't have to -- we'd rather be offline and wait a little longer instead todo: make this configurable. diff --git a/src/mongo/db/repl/health.cpp b/src/mongo/db/repl/health.cpp index 6c94a4c1762..90aa448c733 100644 --- a/src/mongo/db/repl/health.cpp +++ b/src/mongo/db/repl/health.cpp @@ -31,7 +31,6 @@ #include "mongo/db/repl/health.h" #include "mongo/client/connpool.h" -#include "mongo/db/cmdline.h" #include "mongo/db/commands.h" #include "mongo/db/dbhelpers.h" #include "mongo/db/repl/bgsync.h" @@ -320,7 +319,7 @@ namespace mongo { s << tr() << td(_self->fullName() + " (me)") << td(_self->id()) << td("1") << //up - td(ago(cmdLine.started)) << + td(ago(serverGlobalParams.started)) << td("") << // last heartbeat td(ToString(_self->config().votes)) << td(ToString(_self->config().priority)) << @@ -433,7 +432,7 @@ namespace mongo { bb.append("health", 1.0); bb.append("state", (int)myState.s); bb.append("stateStr", myState.toString()); - bb.append("uptime", (unsigned)(time(0) - cmdLine.started)); + bb.append("uptime", (unsigned)(time(0) - serverGlobalParams.started)); if (!_self->config().arbiterOnly) { bb.appendTimestamp("optime", lastOpTimeWritten.asDate()); bb.appendDate("optimeDate", lastOpTimeWritten.getSecs() * 1000LL); diff --git a/src/mongo/db/repl/heartbeat.cpp b/src/mongo/db/repl/heartbeat.cpp index a64b520eb5c..f22c2526369 100644 --- a/src/mongo/db/repl/heartbeat.cpp +++ b/src/mongo/db/repl/heartbeat.cpp @@ -124,9 +124,10 @@ namespace mongo { } { string s = string(cmdObj.getStringField("replSetHeartbeat")); - if( cmdLine.ourSetName() != s ) { + if (replSettings.ourSetName() != s) { errmsg = "repl set names do not match"; - log() << "replSet set names do not match, our cmdline: " << cmdLine._replSet << rsLog; + log() << "replSet set names do not match, our cmdline: " << replSettings.replSet + << rsLog; log() << "replSet s: " << s << rsLog; result.append("mismatch", true); return false; diff --git a/src/mongo/db/repl/master_slave.cpp b/src/mongo/db/repl/master_slave.cpp index e1983cbd096..0b90942e14b 100644 --- a/src/mongo/db/repl/master_slave.cpp +++ b/src/mongo/db/repl/master_slave.cpp @@ -52,6 +52,7 @@ #include "mongo/db/repl/replication_server_status.h" // replSettings #include "mongo/db/repl/rs.h" // replLocalAuth() #include "mongo/db/server_parameters.h" +#include "mongo/db/storage_options.h" namespace mongo { @@ -103,7 +104,7 @@ namespace mongo { void help(stringstream&h) const { h << "resync (from scratch) an out of date replica slave.\nhttp://dochub.mongodb.org/core/masterslave"; } CmdResync() : Command("resync") { } virtual bool run(const string& , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) { - if( cmdLine.usingReplSets() ) { + if (replSettings.usingReplSets()) { errmsg = "resync command not currently supported with replica sets. See RS102 info in the mongodb documentations"; result.append("info", "http://dochub.mongodb.org/core/resyncingaverystalereplicasetmember"); return false; @@ -295,7 +296,7 @@ namespace mongo { SourceVector old = v; v.clear(); - if ( !cmdLine.source.empty() ) { + if (!replSettings.source.empty()) { // --source <host> specified. // check that no items are in sources other than that // add if missing @@ -306,16 +307,18 @@ namespace mongo { while (Runner::RUNNER_ADVANCED == (state = runner->getNext(&obj, NULL))) { n++; ReplSource tmp(obj); - if ( tmp.hostName != cmdLine.source ) { - log() << "repl: --source " << cmdLine.source << " != " << tmp.hostName << " from local.sources collection" << endl; + if (tmp.hostName != replSettings.source) { + log() << "repl: --source " << replSettings.source << " != " << tmp.hostName + << " from local.sources collection" << endl; log() << "repl: for instructions on changing this slave's source, see:" << endl; log() << "http://dochub.mongodb.org/core/masterslave" << endl; log() << "repl: terminating mongod after 30 seconds" << endl; sleepsecs(30); dbexit( EXIT_REPLICATION_ERROR ); } - if ( tmp.only != cmdLine.only ) { - log() << "--only " << cmdLine.only << " != " << tmp.only << " from local.sources collection" << endl; + if (tmp.only != replSettings.only) { + log() << "--only " << replSettings.only << " != " << tmp.only + << " from local.sources collection" << endl; log() << "terminating after 30 seconds" << endl; sleepsecs(30); dbexit( EXIT_REPLICATION_ERROR ); @@ -326,14 +329,14 @@ namespace mongo { if ( n == 0 ) { // source missing. add. ReplSource s; - s.hostName = cmdLine.source; - s.only = cmdLine.only; + s.hostName = replSettings.source; + s.only = replSettings.only; s.save(); } } else { try { - massert( 10384 , "--only requires use of --source", cmdLine.only.empty()); + massert(10384 , "--only requires use of --source", replSettings.only.empty()); } catch ( ... ) { dbexit( EXIT_BADOPTIONS ); @@ -470,7 +473,7 @@ namespace mongo { } bool ReplSource::handleDuplicateDbName( const BSONObj &op, const char *ns, const char *db ) { - if ( dbHolder()._isLoaded( ns, dbpath ) ) { + if (dbHolder()._isLoaded(ns, storageGlobalParams.dbpath)) { // Database is already present. return true; } @@ -480,7 +483,7 @@ namespace mongo { // missing from master after optime "ts". return false; } - if ( Database::duplicateUncasedName( false, db, dbpath ).empty() ) { + if (Database::duplicateUncasedName(false, db, storageGlobalParams.dbpath).empty()) { // No duplicate database names are present. return true; } @@ -533,7 +536,7 @@ namespace mongo { // Check for duplicates again, since we released the lock above. set< string > duplicates; - Database::duplicateUncasedName( false, db, dbpath, &duplicates ); + Database::duplicateUncasedName(false, db, storageGlobalParams.dbpath, &duplicates); // The database is present on the master and no conflicting databases // are present on the master. Drop any local conflicts. @@ -546,7 +549,7 @@ namespace mongo { } massert( 14034, "Duplicate database names present after attempting to delete duplicates", - Database::duplicateUncasedName( false, db, dbpath ).empty() ); + Database::duplicateUncasedName(false, db, storageGlobalParams.dbpath).empty() ); return true; } @@ -603,8 +606,9 @@ namespace mongo { if ( !only.empty() && only != clientName ) return; - if( cmdLine.pretouch && !alreadyLocked/*doesn't make sense if in write lock already*/ ) { - if( cmdLine.pretouch > 1 ) { + if (replSettings.pretouch && + !alreadyLocked/*doesn't make sense if in write lock already*/) { + if (replSettings.pretouch > 1) { /* note: this is bad - should be put in ReplSource. but this is first test... */ static int countdown; verify( countdown >= 0 ); @@ -614,12 +618,12 @@ namespace mongo { else { const int m = 4; if( tp.get() == 0 ) { - int nthr = min(8, cmdLine.pretouch); + int nthr = min(8, replSettings.pretouch); nthr = max(nthr, 1); tp.reset( new ThreadPool(nthr) ); } vector<BSONObj> v; - oplogReader.peek(v, cmdLine.pretouch); + oplogReader.peek(v, replSettings.pretouch); unsigned a = 0; while( 1 ) { if( a >= v.size() ) break; @@ -1021,7 +1025,7 @@ namespace mongo { int ReplSource::sync(int& nApplied) { _sleepAdviceTime = 0; ReplInfo r("sync"); - if ( !cmdLine.quiet ) { + if (!serverGlobalParams.quiet) { LogstreamBuilder l = log(); l << "repl: syncing from "; if( sourceName() != "main" ) { @@ -1032,7 +1036,8 @@ namespace mongo { nClonedThisPass = 0; // FIXME Handle cases where this db isn't on default port, or default port is spec'd in hostName. - if ( (string("localhost") == hostName || string("127.0.0.1") == hostName) && cmdLine.port == CmdLine::DefaultDBPort ) { + if ((string("localhost") == hostName || string("127.0.0.1") == hostName) && + serverGlobalParams.port == ServerGlobalParams::DefaultDBPort) { log() << "repl: can't sync from self (localhost). sources configuration may be wrong." << endl; sleepsecs(5); return -1; @@ -1172,7 +1177,7 @@ namespace mongo { stringstream ss; ss << "repl: sleep " << s << " sec before next pass"; string msg = ss.str(); - if ( ! cmdLine.quiet ) + if (!serverGlobalParams.quiet) log() << msg << endl; ReplInfo r(msg.c_str()); sleepsecs(s); diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp index e76e192bd34..3c677781e0a 100644 --- a/src/mongo/db/repl/oplog.cpp +++ b/src/mongo/db/repl/oplog.cpp @@ -50,6 +50,7 @@ #include "mongo/db/repl/rs.h" #include "mongo/db/repl/write_concern.h" #include "mongo/db/stats/counters.h" +#include "mongo/db/storage_options.h" #include "mongo/s/d_logic.h" #include "mongo/util/elapsed_tracker.h" #include "mongo/util/file.h" @@ -85,7 +86,7 @@ namespace mongo { { const char *logns = rsoplog; if ( rsOplogDetails == 0 ) { - Client::Context ctx(logns , dbpath); + Client::Context ctx(logns, storageGlobalParams.dbpath); localDB = ctx.db(); verify( localDB ); rsOplogDetails = nsdetails(logns); @@ -226,7 +227,7 @@ namespace mongo { { const char *logns = rsoplog; if ( rsOplogDetails == 0 ) { - Client::Context ctx(logns , dbpath); + Client::Context ctx(logns, storageGlobalParams.dbpath); localDB = ctx.db(); verify( localDB ); rsOplogDetails = nsdetails(logns); @@ -300,7 +301,7 @@ namespace mongo { if( logNS == 0 ) { logNS = "local.oplog.$main"; if ( localOplogMainDetails == 0 ) { - Client::Context ctx(logNS , dbpath); + Client::Context ctx(logNS, storageGlobalParams.dbpath); localDB = ctx.db(); verify( localDB ); localOplogMainDetails = nsdetails(logNS); @@ -310,7 +311,7 @@ namespace mongo { r = theDataFileMgr.fast_oplog_insert(localOplogMainDetails, logNS, len); } else { - Client::Context ctx(logNS, dbpath); + Client::Context ctx(logNS, storageGlobalParams.dbpath); verify( nsdetails( logNS ) ); // first we allocate the space, then we fill it below. r = theDataFileMgr.fast_oplog_insert( nsdetails( logNS ), logNS, len); @@ -371,7 +372,7 @@ namespace mongo { const char * ns = "local.oplog.$main"; - bool rs = !cmdLine._replSet.empty(); + bool rs = !replSettings.replSet.empty(); if( rs ) ns = rsoplog; @@ -381,9 +382,9 @@ namespace mongo { if ( nsd ) { - if ( cmdLine.oplogSize != 0 ) { + if (replSettings.oplogSize != 0) { int o = (int)(nsd->storageSize() / ( 1024 * 1024 ) ); - int n = (int)(cmdLine.oplogSize / ( 1024 * 1024 ) ); + int n = (int)(replSettings.oplogSize / (1024 * 1024)); if ( n != o ) { stringstream ss; ss << "cmdline oplogsize (" << n << ") different than existing (" << o << ") see: http://dochub.mongodb.org/core/increase-oplog"; @@ -405,8 +406,8 @@ namespace mongo { /* create an oplog collection, if it doesn't yet exist. */ BSONObjBuilder b; double sz; - if ( cmdLine.oplogSize != 0 ) - sz = (double)cmdLine.oplogSize; + if (replSettings.oplogSize != 0) + sz = (double)replSettings.oplogSize; else { /* not specified. pick a default size */ sz = 50.0 * 1024 * 1024; @@ -416,7 +417,8 @@ namespace mongo { sz = (256-64) * 1024 * 1024; #else sz = 990.0 * 1024 * 1024; - boost::intmax_t free = File::freeSpace(dbpath); //-1 if call not supported. + boost::intmax_t free = + File::freeSpace(storageGlobalParams.dbpath); //-1 if call not supported. double fivePct = free * 0.05; if ( fivePct > sz ) sz = fivePct; diff --git a/src/mongo/db/repl/repl_start.cpp b/src/mongo/db/repl/repl_start.cpp index e66c9aace7b..71e883db51c 100644 --- a/src/mongo/db/repl/repl_start.cpp +++ b/src/mongo/db/repl/repl_start.cpp @@ -32,7 +32,6 @@ #include <boost/thread.hpp> #include <iostream> -#include "mongo/db/cmdline.h" #include "mongo/db/repl/master_slave.h" #include "mongo/db/repl/oplog.h" #include "mongo/db/repl/replication_server_status.h" @@ -43,7 +42,7 @@ namespace mongo { void startReplication() { /* if we are going to be a replica set, we aren't doing other forms of replication. */ - if( !cmdLine._replSet.empty() ) { + if (!replSettings.replSet.empty()) { if( replSettings.slave || replSettings.master ) { log() << "***" << endl; log() << "ERROR: can't use --slave or --master replication options with --replSet" << endl; @@ -52,7 +51,7 @@ namespace mongo { newRepl(); replSet = true; - ReplSetCmdline *replSetCmdline = new ReplSetCmdline(cmdLine._replSet); + ReplSetCmdline *replSetCmdline = new ReplSetCmdline(replSettings.replSet); boost::thread t( boost::bind( &startReplSets, replSetCmdline) ); return; diff --git a/src/mongo/db/repl/replication_server_status.cpp b/src/mongo/db/repl/replication_server_status.cpp index ddbe4d2c312..f50cd5f913e 100644 --- a/src/mongo/db/repl/replication_server_status.cpp +++ b/src/mongo/db/repl/replication_server_status.cpp @@ -40,6 +40,7 @@ #include "mongo/db/repl/master_slave.h" #include "mongo/db/repl/oplogreader.h" #include "mongo/db/repl/rs.h" +#include "mongo/db/storage_options.h" #include "mongo/db/wire_version.h" namespace mongo { @@ -84,7 +85,7 @@ namespace mongo { int n = 0; list<BSONObj> src; { - Client::ReadContext ctx("local.sources", dbpath); + Client::ReadContext ctx("local.sources", storageGlobalParams.dbpath); auto_ptr<Runner> runner(InternalPlanner::collectionScan("local.sources")); BSONObj obj; Runner::RunnerState state; diff --git a/src/mongo/db/repl/replication_server_status.h b/src/mongo/db/repl/replication_server_status.h index e3e7d3b4460..3b7238b7c63 100644 --- a/src/mongo/db/repl/replication_server_status.h +++ b/src/mongo/db/repl/replication_server_status.h @@ -57,6 +57,25 @@ namespace mongo { int slavedelay; + long long oplogSize; // --oplogSize + + // for master/slave replication + std::string source; // --source + std::string only; // --only + int pretouch; // --pretouch for replication application (experimental) + + std::string replSet; // --replSet[/<seedlist>] + std::string ourSetName() const { + std::string setname; + size_t sl = replSet.find('/'); + if( sl == std::string::npos ) + return replSet; + return replSet.substr(0, sl); + } + bool usingReplSets() const { return !replSet.empty(); } + + std::string rsIndexPrefetch;// --indexPrefetch + std::set<std::string> discoveredSeeds; mutex discoveredSeeds_mx; @@ -68,6 +87,8 @@ namespace mongo { fastsync(), autoresync(false), slavedelay(), + oplogSize(0), + pretouch(0), discoveredSeeds(), discoveredSeeds_mx("ReplSettings::discoveredSeeds") { } diff --git a/src/mongo/db/repl/replset_commands.cpp b/src/mongo/db/repl/replset_commands.cpp index 1539436b9a1..77a1149e8b4 100644 --- a/src/mongo/db/repl/replset_commands.cpp +++ b/src/mongo/db/repl/replset_commands.cpp @@ -33,7 +33,6 @@ #include "mongo/db/auth/action_set.h" #include "mongo/db/auth/action_type.h" #include "mongo/db/auth/authorization_manager.h" -#include "mongo/db/cmdline.h" #include "mongo/db/commands.h" #include "mongo/db/repl/health.h" #include "mongo/db/repl/oplog.h" diff --git a/src/mongo/db/repl/replset_web_handler.cpp b/src/mongo/db/repl/replset_web_handler.cpp index 6ffdad86d3a..2bc56bd9f58 100644 --- a/src/mongo/db/repl/replset_web_handler.cpp +++ b/src/mongo/db/repl/replset_web_handler.cpp @@ -28,9 +28,9 @@ #include "mongo/platform/basic.h" -#include "mongo/db/cmdline.h" #include "mongo/db/dbwebserver.h" #include "mongo/db/jsobj.h" +#include "mongo/db/repl/replication_server_status.h" // replSettings #include "mongo/db/repl/rs.h" #include "mongo/util/mongoutils/html.h" #include "mongo/util/mongoutils/str.h" @@ -74,7 +74,7 @@ namespace { s << p(t); if( theReplSet == 0 ) { - if( cmdLine._replSet.empty() ) + if (replSettings.replSet.empty()) s << p("Not using --replSet"); else { s << p("Still starting up, or else set is not yet " + a("http://dochub.mongodb.org/core/replicasetconfiguration#ReplicaSetConfiguration-InitialSetup", "", "initiated") @@ -105,7 +105,7 @@ namespace { ); if( theReplSet == 0 ) { - if( cmdLine._replSet.empty() ) + if (replSettings.replSet.empty()) s << p("Not using --replSet"); else { s << p("Still starting up, or else set is not yet " + a("http://dochub.mongodb.org/core/replicasetconfiguration#ReplicaSetConfiguration-InitialSetup", "", "initiated") diff --git a/src/mongo/db/repl/rs.cpp b/src/mongo/db/repl/rs.cpp index e437245802c..02a41334784 100644 --- a/src/mongo/db/repl/rs.cpp +++ b/src/mongo/db/repl/rs.cpp @@ -33,7 +33,6 @@ #include "mongo/db/auth/authorization_manager.h" #include "mongo/db/auth/authorization_session.h" #include "mongo/db/client.h" -#include "mongo/db/cmdline.h" #include "mongo/db/dbhelpers.h" #include "mongo/db/instance.h" #include "mongo/db/repl/bgsync.h" @@ -440,7 +439,7 @@ namespace mongo { } // Figure out indexPrefetch setting - std::string& prefetch = cmdLine.rsIndexPrefetch; + std::string& prefetch = replSettings.rsIndexPrefetch; if (!prefetch.empty()) { IndexPrefetchConfig prefetchConfig = PREFETCH_ALL; if (prefetch == "none") diff --git a/src/mongo/db/repl/rs.h b/src/mongo/db/repl/rs.h index 6d8c616c8a4..f33ec6f3798 100644 --- a/src/mongo/db/repl/rs.h +++ b/src/mongo/db/repl/rs.h @@ -694,7 +694,7 @@ namespace mongo { bool check(string& errmsg, BSONObjBuilder& result) { if( !replSet ) { errmsg = "not running with --replSet"; - if( cmdLine.configsvr ) { + if (serverGlobalParams.configsvr) { result.append("info", "configsvr"); // for shell prompt } return false; diff --git a/src/mongo/db/repl/rs_config.cpp b/src/mongo/db/repl/rs_config.cpp index fcef0ccdcf8..b21370719a6 100644 --- a/src/mongo/db/repl/rs_config.cpp +++ b/src/mongo/db/repl/rs_config.cpp @@ -36,6 +36,7 @@ #include "mongo/db/instance.h" #include "mongo/db/repl/connections.h" #include "mongo/db/repl/oplog.h" +#include "mongo/db/repl/replication_server_status.h" // replSettings #include "mongo/db/repl/rs.h" #include "mongo/util/net/hostandport.h" #include "mongo/util/text.h" @@ -350,8 +351,9 @@ namespace mongo { void ReplSetConfig::checkRsConfig() const { uassert(13132, - str::stream() << "nonmatching repl set name in _id field: " << _id << " vs. " << cmdLine.ourSetName(), - _id == cmdLine.ourSetName()); + str::stream() << "nonmatching repl set name in _id field: " << _id << " vs. " + << replSettings.ourSetName(), + _id == replSettings.ourSetName()); uassert(13308, "replSet bad config version #", version > 0); uassert(13133, "replSet bad config no members", members.size() >= 1); uassert(13309, "replSet bad config maximum number of members is 12", members.size() <= 12); @@ -690,7 +692,7 @@ namespace mongo { } else { /* first, make sure other node is configured to be a replset. just to be safe. */ - string setname = cmdLine.ourSetName(); + string setname = replSettings.ourSetName(); BSONObj cmd = BSON( "replSetHeartbeat" << setname ); int theirVersion; BSONObj info; diff --git a/src/mongo/db/repl/rs_initiate.cpp b/src/mongo/db/repl/rs_initiate.cpp index 43b8bf858cc..dc53a4bb11d 100644 --- a/src/mongo/db/repl/rs_initiate.cpp +++ b/src/mongo/db/repl/rs_initiate.cpp @@ -37,11 +37,11 @@ #include "mongo/db/auth/action_type.h" #include "mongo/db/auth/authorization_manager.h" #include "mongo/db/auth/privilege.h" -#include "mongo/db/cmdline.h" #include "mongo/db/commands.h" #include "mongo/db/dbhelpers.h" #include "mongo/db/repl/health.h" #include "mongo/db/repl/oplog.h" +#include "mongo/db/repl/replication_server_status.h" // replSettings #include "mongo/db/repl/rs.h" #include "mongo/db/repl/rs_config.h" #include "mongo/util/mmap.h" @@ -78,7 +78,7 @@ namespace mongo { if( me != 1 ) { stringstream ss; ss << "can't find self in the replset config"; - if( !cmdLine.isDefaultPort() ) ss << " my port: " << cmdLine.port; + if (!serverGlobalParams.isDefaultPort()) ss << " my port: " << serverGlobalParams.port; if( me != 0 ) ss << " found: " << me; uasserted(13279, ss.str()); } @@ -218,7 +218,7 @@ namespace mongo { if( ReplSet::startupStatus != ReplSet::EMPTYCONFIG ) { result.append("startupStatus", ReplSet::startupStatus); errmsg = "all members and seeds must be reachable to initiate set"; - result.append("info", cmdLine._replSet); + result.append("info", replSettings.replSet); return false; } @@ -231,7 +231,7 @@ namespace mongo { string name; vector<HostAndPort> seeds; set<HostAndPort> seedSet; - parseReplsetCmdLine(cmdLine._replSet, name, seeds, seedSet); // may throw... + parseReplsetCmdLine(replSettings.replSet, name, seeds, seedSet); // may throw... bob b; b.append("_id", name); diff --git a/src/mongo/db/repl/rs_sync.cpp b/src/mongo/db/repl/rs_sync.cpp index 259bbf70d09..bfa54421217 100644 --- a/src/mongo/db/repl/rs_sync.cpp +++ b/src/mongo/db/repl/rs_sync.cpp @@ -43,6 +43,7 @@ #include "mongo/db/repl/oplog.h" #include "mongo/db/repl/rs.h" #include "mongo/db/repl/rs_sync.h" +#include "mongo/db/storage_options.h" #include "mongo/util/fail_point_service.h" #include "mongo/db/commands/server_status.h" #include "mongo/db/stats/timer_stats.h" @@ -116,7 +117,7 @@ namespace replset { lk.reset(new Lock::DBWrite(ns)); } - Client::Context ctx(ns, dbpath); + Client::Context ctx(ns, storageGlobalParams.dbpath); ctx.getClient()->curop()->reset(); // For non-initial-sync, we convert updates to upserts // to suppress errors when replaying oplog entries. diff --git a/src/mongo/db/restapi.cpp b/src/mongo/db/restapi.cpp index a1170c3bd4b..2585681796d 100644 --- a/src/mongo/db/restapi.cpp +++ b/src/mongo/db/restapi.cpp @@ -280,7 +280,7 @@ namespace mongo { if( *replInfo ) ss << "\nreplInfo: " << replInfo << "\n\n"; if( replSet ) { - ss << a("", "see replSetGetStatus link top of page") << "--replSet </a>" << cmdLine._replSet; + ss << a("", "see replSetGetStatus link top of page") << "--replSet </a>" << replSettings.replSet; } if ( replAllDead ) ss << "\n<b>replication replAllDead=" << replAllDead << "</b>\n"; diff --git a/src/mongo/db/server_options.cpp b/src/mongo/db/server_options.cpp index bbc4957ee66..6c27cae17ef 100644 --- a/src/mongo/db/server_options.cpp +++ b/src/mongo/db/server_options.cpp @@ -28,10 +28,19 @@ #include "mongo/db/server_options.h" +#ifdef _WIN32 +#include <direct.h> +#endif + #include "mongo/base/status.h" #include "mongo/bson/util/builder.h" -#include "mongo/db/cmdline.h" // For CmdLine::DefaultDBPort +#include "mongo/db/server_parameters.h" +#include "mongo/logger/message_event_utf8_encoder.h" +#include "mongo/util/cmdline_utils/censor_cmdline.h" +#include "mongo/util/map_util.h" +#include "mongo/util/mongoutils/str.h" #include "mongo/util/net/listen.h" // For DEFAULT_MAX_CONN +#include "mongo/util/net/ssl_options.h" #include "mongo/util/options_parser/option_description.h" #include "mongo/util/options_parser/option_section.h" @@ -40,11 +49,16 @@ namespace mongo { typedef moe::OptionDescription OD; typedef moe::PositionalOptionDescription POD; + moe::OptionSection serverOptions; + moe::Environment serverParsedOptions; + + ServerGlobalParams serverGlobalParams; + Status addGeneralServerOptions(moe::OptionSection* options) { StringBuilder portInfoBuilder; StringBuilder maxConnInfoBuilder; - portInfoBuilder << "specify port number - " << CmdLine::DefaultDBPort << " by default"; + portInfoBuilder << "specify port number - " << ServerGlobalParams::DefaultDBPort << " by default"; maxConnInfoBuilder << "max number of simultaneous connections - " << DEFAULT_MAX_CONN << " by default"; @@ -252,4 +266,259 @@ namespace mongo { return Status::OK(); } + namespace { + // Helpers for option storage + Status setupBinaryName(const std::vector<std::string>& argv) { + + if (argv.empty()) { + return Status(ErrorCodes::InternalError, "Cannot get binary name: argv array is empty"); + } + + // setup binary name + serverGlobalParams.binaryName = argv[0]; + size_t i = serverGlobalParams.binaryName.rfind('/'); + if (i != string::npos) { + serverGlobalParams.binaryName = serverGlobalParams.binaryName.substr(i + 1); + } + return Status::OK(); + } + + Status setupCwd() { + // setup cwd + char buffer[1024]; +#ifdef _WIN32 + verify(_getcwd(buffer, 1000)); +#else + verify(getcwd(buffer, 1000)); +#endif + serverGlobalParams.cwd = buffer; + return Status::OK(); + } + + Status setArgvArray(const std::vector<std::string>& argv) { + BSONArrayBuilder b; + std::vector<std::string> censoredArgv = argv; + cmdline_utils::censorArgsVector(&censoredArgv); + for (size_t i=0; i < censoredArgv.size(); i++) { + b << censoredArgv[i]; + } + serverGlobalParams.argvArray = b.arr(); + return Status::OK(); + } + + Status setParsedOpts(const moe::Environment& params) { + serverGlobalParams.parsedOpts = params.toBSON(); + cmdline_utils::censorBSONObj(&serverGlobalParams.parsedOpts); + return Status::OK(); + } + } //namespace + + void printCommandLineOpts() { + log() << "options: " << serverGlobalParams.parsedOpts << endl; + } + + Status storeServerOptions(const moe::Environment& params, + const std::vector<std::string>& args) { + + Status ret = setupBinaryName(args); + if (!ret.isOK()) { + return ret; + } + + ret = setupCwd(); + if (!ret.isOK()) { + return ret; + } + + ret = setArgvArray(args); + if (!ret.isOK()) { + return ret; + } + + ret = setParsedOpts(params); + if (!ret.isOK()) { + return ret; + } + + if (params.count("verbose")) { + logger::globalLogDomain()->setMinimumLoggedSeverity(logger::LogSeverity::Debug(1)); + } + + for (string s = "vv"; s.length() <= 12; s.append("v")) { + if (params.count(s)) { + logger::globalLogDomain()->setMinimumLoggedSeverity( + logger::LogSeverity::Debug(s.length())); + } + } + + if (params.count("enableExperimentalIndexStatsCmd")) { + serverGlobalParams.experimental.indexStatsCmdEnabled = true; + } + if (params.count("enableExperimentalStorageDetailsCmd")) { + serverGlobalParams.experimental.storageDetailsCmdEnabled = true; + } + + if (params.count("port")) { + serverGlobalParams.port = params["port"].as<int>(); + } + + if (params.count("bind_ip")) { + serverGlobalParams.bind_ip = params["bind_ip"].as<std::string>(); + } + + if (params.count("clusterAuthMode")) { + serverGlobalParams.clusterAuthMode = params["clusterAuthMode"].as<std::string>(); + } + + if (params.count("quiet")) { + serverGlobalParams.quiet = true; + } + + if (params.count("traceExceptions")) { + DBException::traceExceptions = true; + } + + if (params.count("maxConns")) { + serverGlobalParams.maxConns = params["maxConns"].as<int>(); + + if (serverGlobalParams.maxConns < 5) { + return Status(ErrorCodes::BadValue, "maxConns has to be at least 5"); + } + } + + if (params.count("objcheck")) { + serverGlobalParams.objcheck = true; + } + if (params.count("noobjcheck")) { + if (params.count("objcheck")) { + return Status(ErrorCodes::BadValue, "can't have both --objcheck and --noobjcheck"); + } + serverGlobalParams.objcheck = false; + } + + if (params.count("bind_ip")) { + // passing in wildcard is the same as default behavior; remove and warn + if (serverGlobalParams.bind_ip == "0.0.0.0") { + std::cout << "warning: bind_ip of 0.0.0.0 is unnecessary; " + << "listens on all ips by default" << endl; + serverGlobalParams.bind_ip = ""; + } + } + +#ifndef _WIN32 + if (params.count("unixSocketPrefix")) { + serverGlobalParams.socket = params["unixSocketPrefix"].as<string>(); + } + + if (params.count("nounixsocket")) { + serverGlobalParams.noUnixSocket = true; + } + + if (params.count("fork") && !params.count("shutdown")) { + serverGlobalParams.doFork = true; + } +#endif // _WIN32 + + if (params.count("logTimestampFormat")) { + using logger::MessageEventDetailsEncoder; + std::string formatterName = params["logTimestampFormat"].as<string>(); + if (formatterName == "ctime") { + MessageEventDetailsEncoder::setDateFormatter(dateToCtimeString); + } + else if (formatterName == "iso8601-utc") { + MessageEventDetailsEncoder::setDateFormatter(dateToISOStringUTC); + } + else if (formatterName == "iso8601-local") { + MessageEventDetailsEncoder::setDateFormatter(dateToISOStringLocal); + } + else { + 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")) { + serverGlobalParams.logpath = params["logpath"].as<string>(); + if (serverGlobalParams.logpath.empty()) { + return Status(ErrorCodes::BadValue, "logpath cannot be empty if supplied"); + } + } + + serverGlobalParams.logWithSyslog = params.count("syslog"); + serverGlobalParams.logAppend = params.count("logappend"); + if (!serverGlobalParams.logpath.empty() && serverGlobalParams.logWithSyslog) { + return Status(ErrorCodes::BadValue, "Cant use both a logpath and syslog "); + } + + if (serverGlobalParams.doFork && serverGlobalParams.logpath.empty() && + !serverGlobalParams.logWithSyslog) { + return Status(ErrorCodes::BadValue, "--fork has to be used with --logpath or --syslog"); + } + + if (params.count("keyFile")) { + serverGlobalParams.keyFile = params["keyFile"].as<string>(); + } + + if ( params.count("pidfilepath")) { + serverGlobalParams.pidFile = params["pidfilepath"].as<string>(); + } + + if (params.count("setParameter")) { + std::vector<std::string> parameters = + params["setParameter"].as<std::vector<std::string> >(); + for (size_t i = 0, length = parameters.size(); i < length; ++i) { + std::string name; + std::string value; + if (!mongoutils::str::splitOn(parameters[i], '=', name, value)) { + 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) { + StringBuilder sb; + sb << "Illegal --setParameter parameter: \"" << name << "\""; + return Status(ErrorCodes::BadValue, sb.str()); + } + if (!parameter->allowedToChangeAtStartup()) { + 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()) { + StringBuilder sb; + sb << "Bad value for parameter \"" << name << "\": " << status.reason(); + return Status(ErrorCodes::BadValue, sb.str()); + } + } + } + if (!params.count("clusterAuthMode") && params.count("keyFile")){ + serverGlobalParams.clusterAuthMode = "keyfile"; + } + +#ifdef MONGO_SSL + ret = storeSSLServerOptions(params); + if (!ret.isOK()) { + return ret; + } +#else // ifdef MONGO_SSL + // Keyfile is currently the only supported value if not using SSL + if (params.count("clusterAuthMode") && serverGlobalParams.clusterAuthMode != "keyfile") { + StringBuilder sb; + sb << "unsupported value for clusterAuthMode " << serverGlobalParams.clusterAuthMode; + return Status(ErrorCodes::BadValue, sb.str()); + } +#endif + + return Status::OK(); + } + + // FIXME: This function will not return the correct value if someone renames the mongos binary + bool isMongos() { return serverGlobalParams.binaryName == "mongos"; } + } // namespace mongo diff --git a/src/mongo/db/server_options.h b/src/mongo/db/server_options.h index 07c6ea1a616..78f49c20db6 100644 --- a/src/mongo/db/server_options.h +++ b/src/mongo/db/server_options.h @@ -29,6 +29,10 @@ #pragma once #include "mongo/base/status.h" +#include "mongo/platform/process_id.h" +#include "mongo/util/net/listen.h" // For DEFAULT_MAX_CONN +#include "mongo/util/options_parser/environment.h" +#include "mongo/util/options_parser/option_section.h" namespace mongo { @@ -38,9 +42,104 @@ namespace mongo { namespace moe = mongo::optionenvironment; + extern moe::OptionSection serverOptions; + extern moe::Environment serverParsedOptions; + + struct ServerGlobalParams { + + ServerGlobalParams() : + port(DefaultDBPort), rest(false), jsonp(false), indexBuildRetry(true), quiet(false), + configsvr(false), cpu(false), objcheck(true), defaultProfile(0), + slowMS(100), defaultLocalThresholdMillis(15), moveParanoia(true), + noUnixSocket(false), doFork(0), socket("/tmp"), maxConns(DEFAULT_MAX_CONN), + logAppend(false), logWithSyslog(false), isHttpInterfaceEnabled(false) + { + started = time(0); + } + + std::string binaryName; // mongod or mongos + std::string cwd; // cwd of when process started + + int port; // --port + enum { + DefaultDBPort = 27017, + ConfigServerPort = 27019, + ShardServerPort = 27018 + }; + bool isDefaultPort() const { return port == DefaultDBPort; } + + std::string bind_ip; // --bind_ip + bool rest; // --rest + bool jsonp; // --jsonp + + bool indexBuildRetry; // --noIndexBuildRetry + + bool quiet; // --quiet + + bool configsvr; // --configsvr + + bool cpu; // --cpu show cpu time periodically + + bool objcheck; // --objcheck + + int defaultProfile; // --profile + int slowMS; // --time in ms that is "slow" + int defaultLocalThresholdMillis; // --localThreshold in ms to consider a node local + bool moveParanoia; // for move chunk paranoia + + bool noUnixSocket; // --nounixsocket + bool doFork; // --fork + std::string socket; // UNIX domain socket directory + + int maxConns; // Maximum number of simultaneous open connections. + + std::string keyFile; // Path to keyfile, or empty if none. + std::string pidFile; // Path to pid file, or empty if none. + + std::string logpath; // Path to log file, if logging to a file; otherwise, empty. + bool logAppend; // True if logging to a file in append mode. + bool logWithSyslog; // True if logging to syslog; must not be set if logpath is set. + std::string clusterAuthMode; // Cluster authentication mode + + bool isHttpInterfaceEnabled; // True if the dbwebserver should be enabled. + +#ifndef _WIN32 + ProcessId parentProc; // --fork pid of initial process + ProcessId leaderProc; // --fork pid of leader process +#endif + + /** + * Switches to enable experimental (unsupported) features. + */ + struct ExperimentalFeatures { + ExperimentalFeatures() + : indexStatsCmdEnabled(false) + , storageDetailsCmdEnabled(false) + {} + bool indexStatsCmdEnabled; // -- enableExperimentalIndexStatsCmd + bool storageDetailsCmdEnabled; // -- enableExperimentalStorageDetailsCmd + } experimental; + + time_t started; + + BSONArray argvArray; + BSONObj parsedOpts; + }; + + extern ServerGlobalParams serverGlobalParams; + Status addGeneralServerOptions(moe::OptionSection* options); Status addWindowsServerOptions(moe::OptionSection* options); Status addSSLServerOptions(moe::OptionSection* options); + + Status storeServerOptions(const moe::Environment& params, + const std::vector<std::string>& args); + + void printCommandLineOpts(); + + // This function should eventually go away, but needs to be here now because we have a lot of + // code that is shared between mongod and mongos that must know at runtime which binary it is in + bool isMongos(); } diff --git a/src/mongo/db/sorter/sorter.cpp b/src/mongo/db/sorter/sorter.cpp index acd2eb62594..3539e07984c 100644 --- a/src/mongo/db/sorter/sorter.cpp +++ b/src/mongo/db/sorter/sorter.cpp @@ -52,9 +52,11 @@ #include "mongo/base/string_data.h" #include "mongo/bson/util/atomic_int.h" -#include "mongo/db/cmdline.h" +#include "mongo/db/jsobj.h" +#include "mongo/db/storage_options.h" #include "mongo/util/assert_util.h" #include "mongo/util/bufreader.h" +#include "mongo/util/goodies.h" #include "mongo/util/log.h" #include "mongo/util/mongoutils/str.h" @@ -156,7 +158,7 @@ namespace mongo { FileIterator(const string& fileName, const Settings& settings, - shared_ptr<FileDeleter> fileDeleter) + boost::shared_ptr<FileDeleter> fileDeleter) : _settings(settings) , _done(false) , _fileName(fileName) @@ -253,7 +255,7 @@ namespace mongo { boost::scoped_ptr<BufReader> _reader; string _fileName; boost::shared_ptr<FileDeleter> _fileDeleter; // Must outlive _file - ifstream _file; + std::ifstream _file; }; /** Merge-sorts results from 0 or more FileIterators */ @@ -264,7 +266,7 @@ namespace mongo { typedef std::pair<Key, Value> Data; - MergeIterator(const vector<shared_ptr<Input> >& iters, + MergeIterator(const std::vector<boost::shared_ptr<Input> >& iters, const SortOptions& opts, const Comparator& comp) : _opts(opts) @@ -770,7 +772,7 @@ namespace mongo { // This should be checked by consumers, but if we get here don't allow writes. massert(16946, "Attempting to use external sort from mongos. This is not allowed.", - !cmdLine.isMongos()); + !isMongos()); massert(17148, "Attempting to use external sort without setting SortOptions::tempDir", !opts.tempDir.empty()); @@ -783,7 +785,7 @@ namespace mongo { boost::filesystem::create_directories(opts.tempDir); - _file.open(_fileName.c_str(), ios::binary | ios::out); + _file.open(_fileName.c_str(), std::ios::binary | std::ios::out); massert(16818, str::stream() << "error opening file \"" << _fileName << "\": " << sorter::myErrnoWithDescription(), _file.good()); @@ -791,7 +793,7 @@ namespace mongo { _fileDeleter = boost::make_shared<sorter::FileDeleter>(_fileName); // throw on failure - _file.exceptions(ios::failbit | ios::badbit | ios::eofbit); + _file.exceptions(std::ios::failbit | std::ios::badbit | std::ios::eofbit); } template <typename Key, typename Value> @@ -860,7 +862,7 @@ namespace mongo { // This should be checked by consumers, but if it isn't try to fail early. massert(16947, "Attempting to use external sort from mongos. This is not allowed.", - !(cmdLine.isMongos() && opts.extSortAllowed)); + !(isMongos() && opts.extSortAllowed)); massert(17149, "Attempting to use external sort without setting SortOptions::tempDir", !(opts.extSortAllowed && opts.tempDir.empty())); diff --git a/src/mongo/db/sorter/sorter_test.cpp b/src/mongo/db/sorter/sorter_test.cpp index 5ad6cfc08e8..7fef29ca83a 100644 --- a/src/mongo/db/sorter/sorter_test.cpp +++ b/src/mongo/db/sorter/sorter_test.cpp @@ -23,6 +23,7 @@ #include "mongo/unittest/temp_dir.h" #include "mongo/unittest/unittest.h" +#include "mongo/util/goodies.h" #include "mongo/util/mongoutils/str.h" // Need access to internal classes @@ -32,7 +33,11 @@ namespace mongo { using namespace mongo::sorter; using boost::make_shared; - CmdLine cmdLine; + // Stub to avoid including the server_options library + // TODO: This should go away once we can do these checks at compile time + bool isMongos() { + return false; + } // // Sorter framework testing utilities @@ -139,7 +144,7 @@ namespace mongo { } catch (...) { mongo::unittest::log() << - "Failure from line " << line << " on iteration " << iteration << endl; + "Failure from line " << line << " on iteration " << iteration << std::endl; throw; } } @@ -147,7 +152,7 @@ namespace mongo { template <int N> boost::shared_ptr<IWIterator> makeInMemIterator(const int (&array)[N]) { - vector<IWPair> vec; + std::vector<IWPair> vec; for (int i=0; i<N; i++) vec.push_back(IWPair(array[i], -array[i])); return boost::make_shared<sorter::InMemIterator<IntWrapper, IntWrapper> >(vec); @@ -157,7 +162,7 @@ namespace mongo { boost::shared_ptr<IWIterator> mergeIterators(IteratorPtr (&array)[N], Direction Dir=ASC, const SortOptions& opts=SortOptions()) { - vector<boost::shared_ptr<IWIterator> > vec; + std::vector<boost::shared_ptr<IWIterator> > vec; for (int i=0; i<N; i++) vec.push_back(boost::shared_ptr<IWIterator>(array[i])); return boost::shared_ptr<IWIterator>(IWIterator::merge(vec, opts, IWComparator(Dir))); @@ -235,7 +240,7 @@ namespace mongo { public: void run() { { // test empty (no inputs) - vector<boost::shared_ptr<IWIterator> > vec; + std::vector<boost::shared_ptr<IWIterator> > vec; boost::shared_ptr<IWIterator> mergeIter (IWIterator::merge(vec, SortOptions(), IWComparator())); diff --git a/src/mongo/db/startup_warnings.cpp b/src/mongo/db/startup_warnings.cpp new file mode 100644 index 00000000000..2eadc90b4d8 --- /dev/null +++ b/src/mongo/db/startup_warnings.cpp @@ -0,0 +1,209 @@ +/** +* 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/>. +* +* As a special exception, the copyright holders give permission to link the +* code of portions of this program with the OpenSSL library under certain +* conditions as described in each individual source file and distribute +* linked combinations including the program with the OpenSSL library. You +* must comply with the GNU Affero General Public License in all respects +* for all of the code used other than as permitted herein. If you modify +* file(s) with this exception, you may extend this exception to your +* version of the file(s), but you are not obligated to do so. If you do not +* wish to do so, delete this exception statement from your version. If you +* delete this exception statement from all source files in the program, +* then also delete it in the license file. +*/ + +#include "mongo/db/startup_warnings.h" + +#include <boost/filesystem/operations.hpp> +#include <fstream> + +#include "mongo/db/storage_options.h" +#include "mongo/util/log.h" +#include "mongo/util/processinfo.h" +#include "mongo/util/version.h" + +namespace mongo { + + // + // system warnings + // + void logStartupWarnings() { + // each message adds a leading and a trailing newline + + bool warned = false; + { + const char * foo = strchr(versionString , '.') + 1; + int bar = atoi(foo); + if ((2 * (bar / 2)) != bar) { + log() << startupWarningsLog; + log() << "** NOTE: This is a development version (" << versionString + << ") of MongoDB." << startupWarningsLog; + log() << "** Not recommended for production." << startupWarningsLog; + warned = true; + } + } + + if (sizeof(int*) == 4) { + log() << startupWarningsLog; + log() << "** NOTE: This is a 32 bit MongoDB binary." << startupWarningsLog; + log() << "** 32 bit builds are limited to less than 2GB of data " + << "(or less with --journal)." << startupWarningsLog; + if (!storageGlobalParams.dur) { + log() << "** Note that journaling defaults to off for 32 bit " + << "and is currently off." << startupWarningsLog; + } + log() << "** See http://dochub.mongodb.org/core/32bit" << startupWarningsLog; + warned = true; + } + + if (!ProcessInfo::blockCheckSupported()) { + log() << startupWarningsLog; + log() << "** NOTE: your operating system version does not support the method that " + << "MongoDB" << startupWarningsLog; + log() << "** uses to detect impending page faults." << startupWarningsLog; + log() << "** This may result in slower performance for certain use " + << "cases" << startupWarningsLog; + warned = true; + } +#ifdef __linux__ + if (boost::filesystem::exists("/proc/vz") && !boost::filesystem::exists("/proc/bc")) { + log() << startupWarningsLog; + log() << "** WARNING: You are running in OpenVZ. This is known to be broken!!!" + << startupWarningsLog; + warned = true; + } + + if (boost::filesystem::exists("/sys/devices/system/node/node1")){ + // We are on a box with a NUMA enabled kernel and more than 1 numa node (they start at + // node0) + // Now we look at the first line of /proc/self/numa_maps + // + // Bad example: + // $ cat /proc/self/numa_maps + // 00400000 default file=/bin/cat mapped=6 N4=6 + // + // Good example: + // $ numactl --interleave=all cat /proc/self/numa_maps + // 00400000 interleave:0-7 file=/bin/cat mapped=6 N4=6 + + std::ifstream f("/proc/self/numa_maps", std::ifstream::in); + if (f.is_open()) { + std::string line; //we only need the first line + std::getline(f, line); + if (f.fail()) { + warning() << "failed to read from /proc/self/numa_maps: " + << errnoWithDescription() << startupWarningsLog; + warned = true; + } + else { + // skip over pointer + std::string::size_type where = line.find(' '); + if ((where == std::string::npos) || (++where == line.size())) { + log() << startupWarningsLog; + log() << "** WARNING: cannot parse numa_maps line: '" << line << "'" + << startupWarningsLog; + warned = true; + } + // if the text following the space doesn't begin with 'interleave', then + // issue the warning. + else if (line.find("interleave", where) != where) { + log() << startupWarningsLog; + log() << "** WARNING: You are running on a NUMA machine." + << startupWarningsLog; + log() << "** We suggest launching mongod like this to avoid " + << "performance problems:" << startupWarningsLog; + log() << "** numactl --interleave=all mongod [other options]" + << startupWarningsLog; + warned = true; + } + } + } + } + + if (storageGlobalParams.dur) { + std::fstream f("/proc/sys/vm/overcommit_memory", ios_base::in); + unsigned val; + f >> val; + + if (val == 2) { + log() << startupWarningsLog; + log() << "** WARNING: /proc/sys/vm/overcommit_memory is " << val + << startupWarningsLog; + log() << "** Journaling works best with it set to 0 or 1" + << startupWarningsLog; + } + } + + if (boost::filesystem::exists("/proc/sys/vm/zone_reclaim_mode")){ + std::fstream f("/proc/sys/vm/zone_reclaim_mode", ios_base::in); + unsigned val; + f >> val; + + if (val != 0) { + log() << startupWarningsLog; + log() << "** WARNING: /proc/sys/vm/zone_reclaim_mode is " << val + << startupWarningsLog; + log() << "** We suggest setting it to 0" << startupWarningsLog; + log() << "** http://www.kernel.org/doc/Documentation/sysctl/vm.txt" + << startupWarningsLog; + } + } +#endif + +#if defined(RLIMIT_NPROC) && defined(RLIMIT_NOFILE) + //Check that # of files rlmit > 1000 , and # of processes > # of files/2 + const unsigned int minNumFiles = 1000; + const double filesToProcsRatio = 2.0; + struct rlimit rlnproc; + struct rlimit rlnofile; + + if(!getrlimit(RLIMIT_NPROC,&rlnproc) && !getrlimit(RLIMIT_NOFILE,&rlnofile)){ + if(rlnofile.rlim_cur < minNumFiles){ + log() << startupWarningsLog; + log() << "** WARNING: soft rlimits too low. Number of files is " + << rlnofile.rlim_cur + << ", should be at least " << minNumFiles << startupWarningsLog; + } + + if(false){ + // juse to make things cleaner + } +#ifdef __APPLE__ + else if(rlnproc.rlim_cur >= 709){ + // os x doesn't make it easy to go higher + // ERH thinks its ok not to add the warning in this case 7/3/2012 + } +#endif + else if(rlnproc.rlim_cur < rlnofile.rlim_cur/filesToProcsRatio){ + log() << startupWarningsLog; + log() << "** WARNING: soft rlimits too low. rlimits set to " + << rlnproc.rlim_cur << " processes, " + << rlnofile.rlim_cur << " files. Number of processes should be at least " + << rlnofile.rlim_cur/filesToProcsRatio << " : " + << 1/filesToProcsRatio << " times number of files." << startupWarningsLog; + } + } else { + log() << startupWarningsLog; + log() << "** WARNING: getrlimit failed. " << errnoWithDescription() + << startupWarningsLog; + } +#endif + if (warned) { + log() << startupWarningsLog; + } + } +} // namespace mongo diff --git a/src/mongo/db/startup_warnings.h b/src/mongo/db/startup_warnings.h new file mode 100644 index 00000000000..35a33210159 --- /dev/null +++ b/src/mongo/db/startup_warnings.h @@ -0,0 +1,32 @@ +/** +* 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/>. +* +* As a special exception, the copyright holders give permission to link the +* code of portions of this program with the OpenSSL library under certain +* conditions as described in each individual source file and distribute +* linked combinations including the program with the OpenSSL library. You +* must comply with the GNU Affero General Public License in all respects +* for all of the code used other than as permitted herein. If you modify +* file(s) with this exception, you may extend this exception to your +* version of the file(s), but you are not obligated to do so. If you do not +* wish to do so, delete this exception statement from your version. If you +* delete this exception statement from all source files in the program, +* then also delete it in the license file. +*/ + +namespace mongo { + // Checks various startup conditions and logs any necessary warnings + void logStartupWarnings(); +} // namespace mongo diff --git a/src/mongo/db/stats/snapshots.cpp b/src/mongo/db/stats/snapshots.cpp index 74efaf81994..ecd392decea 100644 --- a/src/mongo/db/stats/snapshots.cpp +++ b/src/mongo/db/stats/snapshots.cpp @@ -127,7 +127,7 @@ namespace mongo { try { const SnapshotData* s = statsSnapshots.takeSnapshot(); - if ( prev && cmdLine.cpu ) { + if (prev && serverGlobalParams.cpu) { unsigned long long elapsed = s->_created - prev->_created; SnapshotDelta d( *prev , *s ); log() << "cpu: elapsed:" << (elapsed/1000) <<" writelock: " << (int)(100*d.percentWriteLocked()) << "%" << endl; diff --git a/src/mongo/db/storage/data_file.cpp b/src/mongo/db/storage/data_file.cpp index 59c95a203f2..941e3864512 100644 --- a/src/mongo/db/storage/data_file.cpp +++ b/src/mongo/db/storage/data_file.cpp @@ -34,7 +34,6 @@ #include <boost/filesystem/operations.hpp> -#include "mongo/db/cmdline.h" #include "mongo/db/d_concurrency.h" #include "mongo/db/dur.h" #include "mongo/db/lockstate.h" @@ -54,7 +53,7 @@ namespace mongo { if ( sizeof( int* ) == 4 ) { return 512 * 1024 * 1024; } - else if ( cmdLine.smallfiles ) { + else if (storageGlobalParams.smallfiles) { return 0x7ff00000 >> 2; } else { @@ -80,7 +79,7 @@ namespace mongo { size = (64*1024*1024) << fileNo; else size = 0x7ff00000; - if ( cmdLine.smallfiles ) { + if (storageGlobalParams.smallfiles) { size = size >> 2; } return size; @@ -100,9 +99,10 @@ namespace mongo { unsigned long long sz = mmf.length(); verify( sz <= 0x7fffffff ); verify( sz % 4096 == 0 ); - if( sz < 64*1024*1024 && !cmdLine.smallfiles ) { + if (sz < 64*1024*1024 && !storageGlobalParams.smallfiles) { if( sz >= 16*1024*1024 && sz % (1024*1024) == 0 ) { - log() << "info openExisting file size " << sz << " but cmdLine.smallfiles=false: " + log() << "info openExisting file size " << sz + << " but storageGlobalParams.smallfiles=false: " << filename << endl; } else { @@ -128,11 +128,11 @@ namespace mongo { if ( size > maxSize() ) size = maxSize(); - verify( size >= 64*1024*1024 || cmdLine.smallfiles ); + verify(size >= 64*1024*1024 || storageGlobalParams.smallfiles); verify( size % 4096 == 0 ); if ( preallocateOnly ) { - if ( cmdLine.prealloc ) { + if (storageGlobalParams.prealloc) { FileAllocator::get()->requestAllocation( filename, size ); } return; diff --git a/src/mongo/db/storage/durable_mapped_file.cpp b/src/mongo/db/storage/durable_mapped_file.cpp index 09639986f2d..5e491fc7d97 100644 --- a/src/mongo/db/storage/durable_mapped_file.cpp +++ b/src/mongo/db/storage/durable_mapped_file.cpp @@ -36,7 +36,6 @@ #include "mongo/db/storage/durable_mapped_file.h" -#include "mongo/db/cmdline.h" #include "mongo/db/d_concurrency.h" #include "mongo/db/dur.h" @@ -49,7 +48,7 @@ using namespace mongoutils; namespace mongo { void DurableMappedFile::remapThePrivateView() { - verify( cmdLine.dur ); + verify(storageGlobalParams.dur); // todo 1.9 : it turns out we require that we always remap to the same address. // so the remove / add isn't necessary and can be removed? @@ -125,8 +124,6 @@ namespace mongo { PointerToDurableMappedFile privateViews; - extern string dbpath; - // here so that it is precomputed... void DurableMappedFile::setPath(const std::string& f) { string suffix; @@ -158,7 +155,7 @@ namespace mongo { bool DurableMappedFile::finishOpening() { LOG(3) << "mmf finishOpening " << (void*) _view_write << ' ' << filename() << " len:" << length() << endl; if( _view_write ) { - if( cmdLine.dur ) { + if (storageGlobalParams.dur) { _view_private = createPrivateMap(); if( _view_private == 0 ) { msgasserted(13636, str::stream() << "file " << filename() << " open/create failed in createPrivateMap (look in log for more information)"); @@ -192,7 +189,7 @@ namespace mongo { LOG(3) << "mmf close " << filename() << endl; if( view_write() /*actually was opened*/ ) { - if( cmdLine.dur ) { + if (storageGlobalParams.dur) { dur::closingFileNotification(); } /* todo: is it ok to close files if we are not globally locked exclusively? diff --git a/src/mongo/db/storage/extent_manager.cpp b/src/mongo/db/storage/extent_manager.cpp index 6b067695a10..112492f50ed 100644 --- a/src/mongo/db/storage/extent_manager.cpp +++ b/src/mongo/db/storage/extent_manager.cpp @@ -315,8 +315,8 @@ namespace mongo { bool fileIndexExceedsQuota( const char *ns, int fileIndex ) { return - cmdLine.quota && - fileIndex >= cmdLine.quotaFiles && + storageGlobalParams.quota && + fileIndex >= storageGlobalParams.quotaFiles && // we don't enforce the quota on "special" namespaces as that could lead to problems -- e.g. // rejecting an index insert after inserting the main record. !NamespaceString::special( ns ) && diff --git a/src/mongo/db/storage/namespace_index.cpp b/src/mongo/db/storage/namespace_index.cpp index f56989c665c..3a99092ddc7 100644 --- a/src/mongo/db/storage/namespace_index.cpp +++ b/src/mongo/db/storage/namespace_index.cpp @@ -37,8 +37,6 @@ namespace mongo { - unsigned lenForNewNsFiles = 16 * 1024 * 1024; - NamespaceDetails* NamespaceIndex::details(const StringData& ns) { Namespace n(ns); return details(n); @@ -93,7 +91,7 @@ namespace mongo { boost::filesystem::path NamespaceIndex::path() const { boost::filesystem::path ret( _dir ); - if ( directoryperdb ) + if (storageGlobalParams.directoryperdb) ret /= _database; ret /= ( _database + ".ns" ); return ret; @@ -114,7 +112,7 @@ namespace mongo { } void NamespaceIndex::maybeMkdir() const { - if ( !directoryperdb ) + if (!storageGlobalParams.directoryperdb) return; boost::filesystem::path dir( _dir ); dir /= _database; @@ -153,14 +151,15 @@ namespace mongo { } } else { - // use lenForNewNsFiles, we are making a new database - massert( 10343, "bad lenForNewNsFiles", lenForNewNsFiles >= 1024*1024 ); + // use storageGlobalParams.lenForNewNsFiles, we are making a new database + massert(10343, "bad storageGlobalParams.lenForNewNsFiles", + storageGlobalParams.lenForNewNsFiles >= 1024*1024); maybeMkdir(); - unsigned long long l = lenForNewNsFiles; + unsigned long long l = storageGlobalParams.lenForNewNsFiles; if ( _f.create(pathString, l, true) ) { getDur().createdFile(pathString, l); // always a new file len = l; - verify( len == lenForNewNsFiles ); + verify(len == storageGlobalParams.lenForNewNsFiles); p = _f.getView(); } } diff --git a/src/mongo/db/storage_options.cpp b/src/mongo/db/storage_options.cpp new file mode 100644 index 00000000000..23516baf85d --- /dev/null +++ b/src/mongo/db/storage_options.cpp @@ -0,0 +1,62 @@ +/* + * 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/>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#include "mongo/db/storage_options.h" + +#include "mongo/bson/util/builder.h" +#include "mongo/db/server_parameters.h" + +namespace mongo { + + StorageGlobalParams storageGlobalParams; + + bool isJournalingEnabled() { + return storageGlobalParams.dur; + } + + void setJournalCommitInterval(unsigned newValue) { + storageGlobalParams.journalCommitInterval = newValue; + } + + unsigned getJournalCommitInterval() { + return storageGlobalParams.journalCommitInterval; + } + + ExportedServerParameter<bool> NoTableScanSetting(ServerParameterSet::getGlobal(), + "notablescan", + &storageGlobalParams.noTableScan, + true, + true); + + ExportedServerParameter<double> SyncdelaySetting(ServerParameterSet::getGlobal(), + "syncdelay", + &storageGlobalParams.syncdelay, + true, + true); + +} // namespace mongo diff --git a/src/mongo/db/storage_options.h b/src/mongo/db/storage_options.h new file mode 100644 index 00000000000..4b02468aa05 --- /dev/null +++ b/src/mongo/db/storage_options.h @@ -0,0 +1,117 @@ +/* + * 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/>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#pragma once + +#include <string> + +/* + * This file defines the storage for options that come from the command line related to data file + * persistence. Many executables that can access data files directly such as mongod and certain + * tools use these variables, but each executable may have a different set of command line flags + * that allow the user to change a different subset of these options. + */ + +namespace mongo { + + struct StorageGlobalParams { + + StorageGlobalParams() : +#ifdef _WIN32 + dbpath("\\data\\db\\"), +#else + dbpath("/data/db/"), +#endif + directoryperdb(false), + lenForNewNsFiles(16 * 1024 * 1024), + preallocj(true), + journalCommitInterval(0), // 0 means use default + quota(false), quotaFiles(8), + syncdelay(60), + useHints(true) + { + repairpath = dbpath; + dur = false; +#if defined(_DURABLEDEFAULTON) + dur = true; +#endif + if (sizeof(void*) == 8) + dur = true; +#if defined(_DURABLEDEFAULTOFF) + dur = false; +#endif + } + + std::string dbpath; + bool directoryperdb; + std::string repairpath; + unsigned lenForNewNsFiles; + + bool preallocj; // --nopreallocj no preallocation of journal files + bool prealloc; // --noprealloc no preallocation of data files + bool smallfiles; // --smallfiles allocate smaller data files + bool noTableScan; // --notablescan no table scans allowed + + bool dur; // --dur durability (now --journal) + unsigned journalCommitInterval; // group/batch commit interval ms + + /** --durOptions 7 dump journal and terminate without doing anything further + --durOptions 4 recover and terminate without listening + */ + enum { // bits to be ORed + DurDumpJournal = 1, // dump diagnostics on the journal during recovery + DurScanOnly = 2, // don't do any real work, just scan and dump if dump specified + DurRecoverOnly = 4, // terminate after recovery step + DurParanoid = 8, // paranoid mode enables extra checks + DurAlwaysCommit = 16, // do a group commit every time the writelock is released + DurAlwaysRemap = 32, // remap the private view after every group commit (may lag to the + // next write lock acquisition, but will do all files then) + DurNoCheckSpace = 64 // don't check that there is enough room for journal files before + // startup (for diskfull tests) + }; + int durOptions; // --durOptions <n> for debugging + + bool quota; // --quota + int quotaFiles; // --quotaFiles + + double syncdelay; // seconds between fsyncs + + bool useHints; // only off if --nohints + }; + + extern StorageGlobalParams storageGlobalParams; + + bool isJournalingEnabled(); + void setJournalCommitInterval(unsigned newValue); + unsigned getJournalCommitInterval(); + + // This is not really related to persistence, but mongos and the other executables share code + // and we use this function to determine at runtime which executable we are in. + bool isMongos(); + +} // namespace mongo diff --git a/src/mongo/db/write_concern.cpp b/src/mongo/db/write_concern.cpp index 4b9635044d8..331525e946b 100644 --- a/src/mongo/db/write_concern.cpp +++ b/src/mongo/db/write_concern.cpp @@ -86,7 +86,7 @@ namespace mongo { BSONElement e = cmdObj["w"]; if ( e.ok() ) { - if ( cmdLine.configsvr && (!e.isNumber() || e.numberInt() > 1) ) { + if (serverGlobalParams.configsvr && (!e.isNumber() || e.numberInt() > 1)) { // w:1 on config servers should still work, but anything greater than that // should not. result->append( "wnote", "can't use w on config servers" ); diff --git a/src/mongo/dbtests/documentsourcetests.cpp b/src/mongo/dbtests/documentsourcetests.cpp index a50663eea13..076b8bafe3f 100644 --- a/src/mongo/dbtests/documentsourcetests.cpp +++ b/src/mongo/dbtests/documentsourcetests.cpp @@ -23,6 +23,7 @@ #include "mongo/db/interrupt_status_mongod.h" #include "mongo/db/pipeline/document_source.h" #include "mongo/db/pipeline/expression_context.h" +#include "mongo/db/storage_options.h" #include "mongo/dbtests/dbtests.h" namespace DocumentSourceTests { @@ -105,7 +106,7 @@ namespace DocumentSourceTests { public: Base() : _ctx(new ExpressionContext(InterruptStatusMongod::status, NamespaceString(ns))) - { _ctx->tempDir = dbpath + "/_tmp"; } + { _ctx->tempDir = storageGlobalParams.dbpath + "/_tmp"; } protected: void createSource() { Client::ReadContext ctx (ns); @@ -411,7 +412,7 @@ namespace DocumentSourceTests { intrusive_ptr<ExpressionContext> expressionContext = new ExpressionContext(InterruptStatusMongod::status, NamespaceString(ns)); expressionContext->inShard = inShard; - expressionContext->tempDir = dbpath + "/_tmp"; + expressionContext->tempDir = storageGlobalParams.dbpath + "/_tmp"; _group = DocumentSourceGroup::createFromBson( &specElement, expressionContext ); assertRoundTrips( _group ); diff --git a/src/mongo/dbtests/framework.cpp b/src/mongo/dbtests/framework.cpp index 6a0992d0c9f..f154a15e4d3 100644 --- a/src/mongo/dbtests/framework.cpp +++ b/src/mongo/dbtests/framework.cpp @@ -30,10 +30,11 @@ #include "mongo/base/init.h" #include "mongo/base/status.h" #include "mongo/db/client.h" -#include "mongo/db/cmdline.h" #include "mongo/db/dur.h" #include "mongo/db/ops/update.h" #include "mongo/db/query/new_find.h" +#include "mongo/db/repl/replication_server_status.h" // replSettings +#include "mongo/db/storage_options.h" #include "mongo/dbtests/dbtests.h" #include "mongo/util/background.h" #include "mongo/util/concurrency/mutex.h" @@ -47,7 +48,6 @@ namespace moe = mongo::optionenvironment; namespace mongo { - CmdLine cmdLine; moe::OptionSection options; moe::Environment params; @@ -249,14 +249,14 @@ MONGO_INITIALIZER_GENERAL(ParseStartupConfiguration, bool nodur = false; if( params.count("nodur") ) { nodur = true; - cmdLine.dur = false; + storageGlobalParams.dur = false; } - if( params.count("dur") || cmdLine.dur ) { - cmdLine.dur = true; + if (params.count("dur") || storageGlobalParams.dur) { + storageGlobalParams.dur = true; } if( params.count("nopreallocj") ) { - cmdLine.preallocj = false; + storageGlobalParams.preallocj = false; } if (params.count("debug") || params.count("verbose") ) { @@ -294,17 +294,17 @@ MONGO_INITIALIZER_GENERAL(ParseStartupConfiguration, } string dbpathString = p.string(); - dbpath = dbpathString.c_str(); + storageGlobalParams.dbpath = dbpathString.c_str(); - cmdLine.prealloc = false; + storageGlobalParams.prealloc = false; // dbtest defaults to smallfiles - cmdLine.smallfiles = true; + storageGlobalParams.smallfiles = true; if( params.count("bigfiles") ) { - cmdLine.dur = true; + storageGlobalParams.dur = true; } - cmdLine.oplogSize = 10 * 1024 * 1024; + replSettings.oplogSize = 10 * 1024 * 1024; Client::initThread("testsuite"); acquirePathLock(); @@ -319,8 +319,8 @@ MONGO_INITIALIZER_GENERAL(ParseStartupConfiguration, log() << "random seed: " << seed << endl; if( time(0) % 3 == 0 && !nodur ) { - if( !cmdLine.dur ) { - cmdLine.dur = true; + if (!storageGlobalParams.dur) { + storageGlobalParams.dur = true; log() << "****************" << endl; log() << "running with journaling enabled to test that. dbtests will do this occasionally even if --dur is not specified." << endl; log() << "****************" << endl; @@ -341,10 +341,10 @@ MONGO_INITIALIZER_GENERAL(ParseStartupConfiguration, dur::startup(); - if( debug && cmdLine.dur ) { - log() << "_DEBUG: automatically enabling cmdLine.durOptions=8 (DurParanoid)" << endl; + if (debug && storageGlobalParams.dur) { + log() << "_DEBUG: automatically enabling storageGlobalParams.durOptions=8 (DurParanoid)" << endl; // this was commented out. why too slow or something? : - cmdLine.durOptions |= 8; + storageGlobalParams.durOptions |= 8; } TestWatchDog twd; diff --git a/src/mongo/dbtests/mmaptests.cpp b/src/mongo/dbtests/mmaptests.cpp index 20e363c9db0..7741ccfa933 100644 --- a/src/mongo/dbtests/mmaptests.cpp +++ b/src/mongo/dbtests/mmaptests.cpp @@ -31,12 +31,13 @@ namespace MMapTests { const int optOld; public: LeakTest() : - fn( (boost::filesystem::path(dbpath) / "testfile.map").string() ), optOld(cmdLine.durOptions) + fn((boost::filesystem::path(storageGlobalParams.dbpath) / "testfile.map").string()), + optOld(storageGlobalParams.durOptions) { - cmdLine.durOptions = 0; // DurParanoid doesn't make sense with this test + storageGlobalParams.durOptions = 0; // DurParanoid doesn't make sense with this test } ~LeakTest() { - cmdLine.durOptions = optOld; + storageGlobalParams.durOptions = optOld; try { boost::filesystem::remove(fn); } catch(...) { } } @@ -55,11 +56,11 @@ namespace MMapTests { char *p = (char *) f.getView(); verify(p); // write something to the private view as a test - if( cmdLine.dur ) + if (storageGlobalParams.dur) MemoryMappedFile::makeWritable(p, 6); strcpy(p, "hello"); } - if( cmdLine.dur ) { + if (storageGlobalParams.dur) { char *w = (char *) f.view_write(); strcpy(w + 6, "world"); } @@ -86,11 +87,11 @@ namespace MMapTests { { char *p = (char *) f.getView(); verify(p); - if( cmdLine.dur ) + if (storageGlobalParams.dur) MemoryMappedFile::makeWritable(p, 4); strcpy(p, "zzz"); } - if( cmdLine.dur ) { + if (storageGlobalParams.dur) { char *w = (char *) f.view_write(); if( i % 2 == 0 ) ++(*w); diff --git a/src/mongo/dbtests/pdfiletests.cpp b/src/mongo/dbtests/pdfiletests.cpp index ef0427453fd..ed7a0e4ebf0 100644 --- a/src/mongo/dbtests/pdfiletests.cpp +++ b/src/mongo/dbtests/pdfiletests.cpp @@ -319,11 +319,11 @@ namespace PdfileTests { public: struct SmallFilesControl { SmallFilesControl() { - old = cmdLine.smallfiles; - cmdLine.smallfiles = false; + old = storageGlobalParams.smallfiles; + storageGlobalParams.smallfiles = false; } ~SmallFilesControl() { - cmdLine.smallfiles = old; + storageGlobalParams.smallfiles = old; } bool old; }; diff --git a/src/mongo/dbtests/perf/perftest.cpp b/src/mongo/dbtests/perf/perftest.cpp index e3d982cf758..c74b8dbf7be 100644 --- a/src/mongo/dbtests/perf/perftest.cpp +++ b/src/mongo/dbtests/perf/perftest.cpp @@ -32,8 +32,6 @@ #include "mongo/unittest/unittest.h" namespace mongo { - extern string dbpath; - // This specifies default dbpath for our testing framework const std::string default_test_dbpath = "/data/db/perftest"; } // namespace mongo diff --git a/src/mongo/dbtests/perftests.cpp b/src/mongo/dbtests/perftests.cpp index 321c5b945b6..904c6baeefb 100644 --- a/src/mongo/dbtests/perftests.cpp +++ b/src/mongo/dbtests/perftests.cpp @@ -235,7 +235,9 @@ namespace PerfTests { Query q; { BSONObjBuilder b; - b.append("host",_perfhostname).append("test",s).append("dur",cmdLine.dur); + b.append("host", _perfhostname); + b.append("test", s); + b.append("dur", storageGlobalParams.dur); DEV { b.append("info.DEBUG",true); } else b.appendNull("info.DEBUG"); if( sizeof(int*) == 4 ) @@ -270,8 +272,8 @@ namespace PerfTests { b.append("test", s); b.append("rps", (int) rps); b.append("millis", ms); - b.appendBool("dur", cmdLine.dur); - if( showDurStats() && cmdLine.dur ) + b.appendBool("dur", storageGlobalParams.dur); + if (showDurStats() && storageGlobalParams.dur) b.append("durStats", dur::stats.curr->_asObj()); { bob inf; @@ -1225,7 +1227,7 @@ namespace PerfTests { // write something to the private view as a test strcpy(p, "hello"); } - if( cmdLine.dur ) { + if (storageGlobalParams.dur) { char *w = (char *) f.view_write(); strcpy(w + 6, "world"); } diff --git a/src/mongo/dbtests/replsettests.cpp b/src/mongo/dbtests/replsettests.cpp index c3008e29b42..4866c2fb917 100644 --- a/src/mongo/dbtests/replsettests.cpp +++ b/src/mongo/dbtests/replsettests.cpp @@ -26,6 +26,7 @@ #include "mongo/db/kill_current_op.h" #include "mongo/db/repl/bgsync.h" #include "mongo/db/repl/oplog.h" +#include "mongo/db/repl/replication_server_status.h" // replSettings #include "mongo/db/repl/rs.h" #include "mongo/dbtests/dbtests.h" #include "mongo/util/time_support.h" @@ -154,8 +155,8 @@ namespace ReplSetTests { c.ctx().db()->dropCollection( ns() ); } static void setup() { - cmdLine._replSet = "foo"; - cmdLine.oplogSize = 5 * 1024 * 1024; + replSettings.replSet = "foo"; + replSettings.oplogSize = 5 * 1024 * 1024; createOplog(); // setup background sync instance diff --git a/src/mongo/dbtests/repltests.cpp b/src/mongo/dbtests/repltests.cpp index b900461d749..dd5e67a2726 100644 --- a/src/mongo/dbtests/repltests.cpp +++ b/src/mongo/dbtests/repltests.cpp @@ -48,8 +48,8 @@ namespace ReplTests { public: Base() : _context( ns() ) { oldRepl(); - cmdLine._replSet = ""; - cmdLine.oplogSize = 5 * 1024 * 1024; + replSettings.replSet = ""; + replSettings.oplogSize = 5 * 1024 * 1024; replSettings.master = true; createOplog(); ensureHaveIdIndex( ns(), false ); diff --git a/src/mongo/s/balance.cpp b/src/mongo/s/balance.cpp index d0e20da4696..3ad371474d3 100644 --- a/src/mongo/s/balance.cpp +++ b/src/mongo/s/balance.cpp @@ -32,7 +32,6 @@ #include "mongo/client/dbclientcursor.h" #include "mongo/client/distlock.h" -#include "mongo/db/cmdline.h" #include "mongo/db/jsobj.h" #include "mongo/s/chunk.h" #include "mongo/s/config.h" @@ -388,7 +387,7 @@ namespace mongo { log() << "config servers and shards contacted successfully" << endl; StringBuilder buf; - buf << getHostNameCached() << ":" << cmdLine.port; + buf << getHostNameCached() << ":" << serverGlobalParams.port; _myid = buf.str(); _started = time(0); diff --git a/src/mongo/s/balancer_policy_tests.cpp b/src/mongo/s/balancer_policy_tests.cpp index a6a5ed34c18..b9ea82a8644 100644 --- a/src/mongo/s/balancer_policy_tests.cpp +++ b/src/mongo/s/balancer_policy_tests.cpp @@ -22,7 +22,6 @@ namespace mongo { // these are all crutch and hopefully will eventually go away - CmdLine cmdLine; bool inShutdown() { return false; } DBClientBase *createDirectClient() { return 0; } void dbexit( ExitCode rc, const char *why ){ @@ -32,7 +31,6 @@ namespace mongo { bool haveLocalShardingInfo( const string& ns ) { return false; } - namespace { TEST( BalancerPolicyTests , SizeMaxedShardTest ) { diff --git a/src/mongo/s/commands_admin.cpp b/src/mongo/s/commands_admin.cpp index be0d7f7ec51..6080ec54027 100644 --- a/src/mongo/s/commands_admin.cpp +++ b/src/mongo/s/commands_admin.cpp @@ -1145,7 +1145,7 @@ namespace mongo { // it's fine if mongods of a set all use default port if ( ! serverAddrs[i].hasPort() ) { - serverAddrs[i].setPort( CmdLine::ShardServerPort ); + serverAddrs[i].setPort(ServerGlobalParams::ShardServerPort); } } diff --git a/src/mongo/s/config.cpp b/src/mongo/s/config.cpp index e286ea357de..89ba0aec24a 100644 --- a/src/mongo/s/config.cpp +++ b/src/mongo/s/config.cpp @@ -34,7 +34,6 @@ #include "mongo/client/connpool.h" #include "mongo/client/dbclientcursor.h" -#include "mongo/db/cmdline.h" #include "mongo/db/pdfile.h" #include "mongo/s/chunk.h" #include "mongo/s/chunk_version.h" @@ -1066,7 +1065,7 @@ namespace mongo { if ( withPort ) { stringstream ss; - ss << name << ":" << CmdLine::ConfigServerPort; + ss << name << ":" << ServerGlobalParams::ConfigServerPort; return ss.str(); } diff --git a/src/mongo/s/config_server_tests.cpp b/src/mongo/s/config_server_tests.cpp index 9a4acf61059..355f0963c2f 100644 --- a/src/mongo/s/config_server_tests.cpp +++ b/src/mongo/s/config_server_tests.cpp @@ -34,7 +34,6 @@ namespace mongo { // Note: these are all crutch and hopefully will eventually go away - CmdLine cmdLine; bool inShutdown() { return false; diff --git a/src/mongo/s/d_migrate.cpp b/src/mongo/s/d_migrate.cpp index 77274df9d77..41839265f2d 100644 --- a/src/mongo/s/d_migrate.cpp +++ b/src/mongo/s/d_migrate.cpp @@ -51,7 +51,6 @@ #include "mongo/db/auth/authorization_session.h" #include "mongo/db/auth/privilege.h" #include "mongo/db/clientcursor.h" -#include "mongo/db/cmdline.h" #include "mongo/db/commands.h" #include "mongo/db/dbhelpers.h" #include "mongo/db/dur.h" @@ -1585,7 +1584,8 @@ namespace mongo { long long num = Helpers::removeRange( range, false, /*maxInclusive*/ secondaryThrottle, /* secondaryThrottle */ - cmdLine.moveParanoia ? &rs : 0, /*callback*/ + /*callback*/ + serverGlobalParams.moveParanoia ? &rs : 0, true ); /* flag fromMigrate in oplog */ if (num < 0) { @@ -1864,7 +1864,7 @@ namespace mongo { Helpers::removeRange( range , true , /*maxInclusive*/ false , /* secondaryThrottle */ - cmdLine.moveParanoia ? &rs : 0 , /*callback*/ + serverGlobalParams.moveParanoia ? &rs : 0 , /*callback*/ true ); /*fromMigrate*/ *lastOpApplied = cx.ctx().getClient()->getLastOp().asDate(); diff --git a/src/mongo/s/d_split.cpp b/src/mongo/s/d_split.cpp index da7a99eddfc..0bb1c0783e4 100644 --- a/src/mongo/s/d_split.cpp +++ b/src/mongo/s/d_split.cpp @@ -440,7 +440,7 @@ namespace mongo { // Remove the sentinel at the beginning before returning splitKeys.erase( splitKeys.begin() ); - if ( timer.millis() > cmdLine.slowMS ) { + if (timer.millis() > serverGlobalParams.slowMS) { warning() << "Finding the split vector for " << ns << " over "<< keyPattern << " keyCount: " << keyCount << " numSplits: " << splitKeys.size() << " lookedAt: " << currCount << " took " << timer.millis() << "ms" diff --git a/src/mongo/s/grid.cpp b/src/mongo/s/grid.cpp index 7f079d5b808..c0eb0b4d632 100644 --- a/src/mongo/s/grid.cpp +++ b/src/mongo/s/grid.cpp @@ -39,6 +39,7 @@ #include "mongo/db/json.h" #include "mongo/db/namespace_string.h" #include "mongo/s/grid.h" +#include "mongo/s/mongos_options.h" #include "mongo/s/shard.h" #include "mongo/s/type_collection.h" #include "mongo/s/type_database.h" @@ -304,7 +305,7 @@ namespace mongo { vector<HostAndPort> hosts = servers.getServers(); for ( size_t i = 0 ; i < hosts.size() ; i++ ) { if (!hosts[i].hasPort()) { - hosts[i].setPort(CmdLine::DefaultDBPort); + hosts[i].setPort(ServerGlobalParams::DefaultDBPort); } string host = hosts[i].toString(); // host:port if ( hostSet.find( host ) == hostSet.end() ) { @@ -614,7 +615,7 @@ namespace mongo { public: void run() { - if ( ! cmdLine.isMongos() ) + if (!isMongos()) return; // T0 < T1 < now < T2 < T3 and Error diff --git a/src/mongo/s/mongos_options.cpp b/src/mongo/s/mongos_options.cpp index b73e5898e15..fd0027c6551 100644 --- a/src/mongo/s/mongos_options.cpp +++ b/src/mongo/s/mongos_options.cpp @@ -19,19 +19,25 @@ #include <string> #include <vector> +#include "mongo/base/init.h" #include "mongo/base/status.h" #include "mongo/bson/util/builder.h" #include "mongo/db/server_options.h" +#include "mongo/s/chunk.h" +#include "mongo/s/version_mongos.h" #include "mongo/util/net/ssl_options.h" #include "mongo/util/options_parser/option_description.h" #include "mongo/util/options_parser/option_section.h" +#include "mongo/util/options_parser/options_parser.h" +#include "mongo/util/startup_test.h" +#include "mongo/util/stringutils.h" namespace mongo { typedef moe::OptionDescription OD; typedef moe::PositionalOptionDescription POD; - extern std::string dbpath; + MongosGlobalParams mongosGlobalParams; Status addMongosOptions(moe::OptionSection* options) { @@ -124,4 +130,147 @@ namespace mongo { return Status::OK(); } + void printMongosHelp(const moe::OptionSection& options) { + std::cout << options.helpString() << std::endl; + }; + + Status handlePreValidationMongosOptions(const moe::Environment& params, + const std::vector<std::string>& args) { + if (params.count("help")) { + printMongosHelp(serverOptions); + ::_exit(EXIT_SUCCESS); + } + if (params.count("version")) { + printShardingVersionInfo(true); + ::_exit(EXIT_SUCCESS); + } + + return Status::OK(); + } + + Status storeMongosOptions(const moe::Environment& params, + const std::vector<std::string>& args) { + + Status ret = storeServerOptions(params, args); + if (!ret.isOK()) { + std::cerr << "Error storing command line: " << ret.toString() << std::endl; + ::_exit(EXIT_BADOPTIONS); + } + + if ( params.count( "chunkSize" ) ) { + int csize = params["chunkSize"].as<int>(); + + // validate chunksize before proceeding + if ( csize == 0 ) { + std::cerr << "error: need a non-zero chunksize" << std::endl; + ::_exit(EXIT_BADOPTIONS); + } + + if ( !Chunk::setMaxChunkSizeSizeMB( csize ) ) { + std::cerr << "MaxChunkSize invalid" << std::endl; + ::_exit(EXIT_BADOPTIONS); + } + } + + if (params.count( "port" ) ) { + int port = params["port"].as<int>(); + if ( port <= 0 || port > 65535 ) { + out() << "error: port number must be between 1 and 65535" << endl; + ::_exit(EXIT_FAILURE); + } + } + + if ( params.count( "localThreshold" ) ) { + serverGlobalParams.defaultLocalThresholdMillis = params["localThreshold"].as<int>(); + } + + if ( params.count( "ipv6" ) ) { + enableIPv6(); + } + + if ( params.count( "jsonp" ) ) { + serverGlobalParams.jsonp = true; + } + + if ( params.count( "test" ) ) { + ::mongo::logger::globalLogDomain()->setMinimumLoggedSeverity( + ::mongo::logger::LogSeverity::Debug(5)); + StartupTest::runTests(); + ::_exit(EXIT_SUCCESS); + } + + if (params.count("noscripting")) { + // This option currently has no effect for mongos + } + + if (params.count("httpinterface")) { + if (params.count("nohttpinterface")) { + std::cerr << "can't have both --httpinterface and --nohttpinterface" << std::endl; + ::_exit(EXIT_BADOPTIONS); + } + serverGlobalParams.isHttpInterfaceEnabled = true; + } + + if (params.count("noAutoSplit")) { + warning() << "running with auto-splitting disabled" << endl; + Chunk::ShouldAutoSplit = false; + } + + if ( ! params.count( "configdb" ) ) { + std::cerr << "error: no args for --configdb" << std::endl; + ::_exit(EXIT_BADOPTIONS); + } + + splitStringDelim(params["configdb"].as<std::string>(), &mongosGlobalParams.configdbs, ','); + if (mongosGlobalParams.configdbs.size() != 1 && mongosGlobalParams.configdbs.size() != 3) { + std::cerr << "need either 1 or 3 configdbs" << std::endl; + ::_exit(EXIT_BADOPTIONS); + } + + if (mongosGlobalParams.configdbs.size() == 1) { + warning() << "running with 1 config server should be done only for testing purposes " + << "and is not recommended for production" << endl; + } + + mongosGlobalParams.upgrade = params.count("upgrade"); + + return Status::OK(); + } + + MONGO_INITIALIZER_GENERAL(ParseStartupConfiguration, + ("GlobalLogManager"), + ("default", "completedStartupConfig"))(InitializerContext* context) { + + serverOptions = moe::OptionSection("Allowed options"); + Status ret = addMongosOptions(&serverOptions); + if (!ret.isOK()) { + return ret; + } + + moe::OptionsParser parser; + ret = parser.run(serverOptions, context->args(), context->env(), &serverParsedOptions); + if (!ret.isOK()) { + std::cerr << "Error parsing command line: " << ret.toString() << std::endl; + std::cerr << "use --help for help" << std::endl; + ::_exit(EXIT_BADOPTIONS); + } + + ret = handlePreValidationMongosOptions(serverParsedOptions, context->args()); + if (!ret.isOK()) { + return ret; + } + + ret = serverParsedOptions.validate(); + if (!ret.isOK()) { + return ret; + } + + ret = storeMongosOptions(serverParsedOptions, context->args()); + 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 index e9f266b8207..9784591f8f3 100644 --- a/src/mongo/s/mongos_options.h +++ b/src/mongo/s/mongos_options.h @@ -17,6 +17,7 @@ #pragma once #include "mongo/base/status.h" +#include "mongo/db/server_options.h" namespace mongo { @@ -26,5 +27,25 @@ namespace mongo { namespace moe = mongo::optionenvironment; + struct MongosGlobalParams { + std::vector<std::string> configdbs; + bool upgrade; + + MongosGlobalParams() : + upgrade(false) + { } + }; + + extern MongosGlobalParams mongosGlobalParams; + Status addMongosOptions(moe::OptionSection* options); + + void printMongosHelp(const moe::OptionSection& options); + + Status handlePreValidationMongosOptions(const moe::Environment& params, + const std::vector<std::string>& args); + + Status storeMongosOptions(const moe::Environment& params, const std::vector<std::string>& args); + + bool isMongos(); } diff --git a/src/mongo/s/mongos_persistence_stubs.cpp b/src/mongo/s/mongos_persistence_stubs.cpp new file mode 100644 index 00000000000..98508931b25 --- /dev/null +++ b/src/mongo/s/mongos_persistence_stubs.cpp @@ -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/>. + */ + +#include <string> + +namespace mongo { + + // TODO: When the following calls are removed from parameters.cpp, we can remove these. + // See SERVER-10515. + + bool isJournalingEnabled() { return false; } + + void setJournalCommitInterval(unsigned newValue) { + // This is only for linking and should not get called at runtime + } + + unsigned getJournalCommitInterval() { + return 0; + } + +} // namespace mongo diff --git a/src/mongo/s/server.cpp b/src/mongo/s/server.cpp index fec01840b6b..c8b9c494902 100644 --- a/src/mongo/s/server.cpp +++ b/src/mongo/s/server.cpp @@ -57,8 +57,10 @@ #include "mongo/s/grid.h" #include "mongo/s/mongos_options.h" #include "mongo/s/request.h" +#include "mongo/s/version_mongos.h" #include "mongo/scripting/engine.h" #include "mongo/util/admin_access.h" +#include "mongo/util/cmdline_utils/censor_cmdline.h" #include "mongo/util/concurrency/task.h" #include "mongo/util/concurrency/thread_name.h" #include "mongo/util/exception_filter_win32.h" @@ -70,19 +72,15 @@ #include "mongo/util/ntservice.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/processinfo.h" #include "mongo/util/ramlog.h" #include "mongo/util/signal_handlers.h" #include "mongo/util/stacktrace.h" -#include "mongo/util/startup_test.h" #include "mongo/util/stringutils.h" #include "mongo/util/text.h" #include "mongo/util/version.h" -namespace { - bool _isUpgradeSwitchSet = false; -} - namespace mongo { #if defined(_WIN32) @@ -94,14 +92,9 @@ namespace mongo { static void initService(); #endif - CmdLine cmdLine; - moe::Environment params; - moe::OptionSection options("Allowed options"); Database *database = 0; string mongosCommand; bool dbexitCalled = false; - static bool scriptingEnabled = true; - static vector<string> configdbs; bool inShutdown() { return dbexitCalled; @@ -269,27 +262,6 @@ namespace mongo { return 0; } - void printShardingVersionInfo( bool out ) { - if ( out ) { - cout << "MongoS version " << versionString << " starting: pid=" << - ProcessId::getCurrent() << " port=" << cmdLine.port << - ( sizeof(int*) == 4 ? " 32" : " 64" ) << "-bit host=" << getHostNameCached() << - " (--help for usage)" << endl; - DEV cout << "_DEBUG build" << endl; - cout << "git version: " << gitVersion() << endl; - cout << openSSLVersion("OpenSSL version: ") << endl; - cout << "build sys info: " << sysInfo() << endl; - } - else { - log() << "MongoS version " << versionString << " starting: pid=" << - ProcessId::getCurrent() << " port=" << cmdLine.port << - ( sizeof( int* ) == 4 ? " 32" : " 64" ) << "-bit host=" << getHostNameCached() << - " (--help for usage)" << endl; - DEV log() << "_DEBUG build" << endl; - logProcessDetails(); - } - } - } // namespace mongo using namespace mongo; @@ -312,7 +284,7 @@ static bool runMongosServer( bool doUpgrade ) { ReplicaSetMonitor::setConfigChangeHook( boost::bind( &ConfigServer::replicaSetChange , &configServer , _1 ) ); - if ( ! configServer.init( configdbs ) ) { + if (!configServer.init(mongosGlobalParams.configdbs)) { log() << "couldn't resolve config db address" << endl; return false; } @@ -350,10 +322,10 @@ static bool runMongosServer( bool doUpgrade ) { init(); #if !defined(_WIN32) - CmdLine::launchOk(); + mongo::signalForkSuccess(); #endif - if ( cmdLine.isHttpInterfaceEnabled ) + if (serverGlobalParams.isHttpInterfaceEnabled) boost::thread web( boost::bind(&webServerThread, new NoAdminAccess() /* takes ownership */) ); AuthorizationManager* authzManager = getGlobalAuthorizationManager(); @@ -366,8 +338,8 @@ static bool runMongosServer( bool doUpgrade ) { } MessageServer::Options opts; - opts.port = cmdLine.port; - opts.ipList = cmdLine.bind_ip; + opts.port = serverGlobalParams.port; + opts.ipList = serverGlobalParams.bind_ip; start(opts); // listen() will return when exit code closes its socket. @@ -375,128 +347,6 @@ static bool runMongosServer( bool doUpgrade ) { return true; } -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 - 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 - // we want durability to be disabled. - cmdLine.dur = false; - - if ( params.count( "help" ) ) { - std::cout << options.helpString() << std::endl; - ::_exit(EXIT_SUCCESS); - } - if ( params.count( "version" ) ) { - printShardingVersionInfo(true); - ::_exit(EXIT_SUCCESS); - } - - if ( params.count( "chunkSize" ) ) { - int csize = params["chunkSize"].as<int>(); - - // validate chunksize before proceeding - if ( csize == 0 ) { - std::cerr << "error: need a non-zero chunksize" << std::endl; - ::_exit(EXIT_BADOPTIONS); - } - - if ( !Chunk::setMaxChunkSizeSizeMB( csize ) ) { - std::cerr << "MaxChunkSize invalid" << std::endl; - ::_exit(EXIT_BADOPTIONS); - } - } - - if (params.count( "port" ) ) { - int port = params["port"].as<int>(); - if ( port <= 0 || port > 65535 ) { - out() << "error: port number must be between 1 and 65535" << endl; - ::_exit(EXIT_FAILURE); - } - } - - if ( params.count( "localThreshold" ) ) { - cmdLine.defaultLocalThresholdMillis = params["localThreshold"].as<int>(); - } - - if ( params.count( "ipv6" ) ) { - enableIPv6(); - } - - if ( params.count( "jsonp" ) ) { - cmdLine.jsonp = true; - } - - if ( params.count( "test" ) ) { - ::mongo::logger::globalLogDomain()->setMinimumLoggedSeverity( - ::mongo::logger::LogSeverity::Debug(5)); - StartupTest::runTests(); - ::_exit(EXIT_SUCCESS); - } - - if (params.count("noscripting")) { - scriptingEnabled = false; - } - - if (params.count("httpinterface")) { - if (params.count("nohttpinterface")) { - std::cerr << "can't have both --httpinterface and --nohttpinterface" << std::endl; - ::_exit(EXIT_BADOPTIONS); - } - cmdLine.isHttpInterfaceEnabled = true; - } - - if (params.count("noAutoSplit")) { - warning() << "running with auto-splitting disabled" << endl; - Chunk::ShouldAutoSplit = false; - } - - if ( ! params.count( "configdb" ) ) { - 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 ) { - std::cerr << "need either 1 or 3 configdbs" << std::endl; - ::_exit(EXIT_BADOPTIONS); - } - - if( configdbs.size() == 1 ) { - warning() << "running with 1 config server should be done only for testing purposes and is not recommended for production" << endl; - } - - _isUpgradeSwitchSet = params.count("upgrade"); - - // 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) { @@ -513,7 +363,7 @@ static void startupConfigActions(const std::vector<std::string>& argv) { vector<string> disallowedOptions; disallowedOptions.push_back( "upgrade" ); ntservice::configureService(initService, - params, + serverParsedOptions, defaultServiceStrings, disallowedOptions, argv); @@ -526,12 +376,13 @@ static int _main() { return EXIT_FAILURE; // we either have a setting where all processes are in localhost or none are - for ( vector<string>::const_iterator it = configdbs.begin() ; it != configdbs.end() ; ++it ) { + for (std::vector<std::string>::const_iterator it = mongosGlobalParams.configdbs.begin(); + it != mongosGlobalParams.configdbs.end(); ++it) { try { HostAndPort configAddr( *it ); // will throw if address format is invalid - if ( it == configdbs.begin() ) { + if (it == mongosGlobalParams.configdbs.begin()) { grid.setAllowLocalHost( configAddr.isLocalHost() ); } @@ -555,7 +406,7 @@ static int _main() { } #endif - return !runMongosServer(_isUpgradeSwitchSet); + return !runMongosServer(mongosGlobalParams.upgrade); } #if defined(_WIN32) @@ -597,7 +448,7 @@ int mongoSMain(int argc, char* argv[], char** envp) { mongo::runGlobalInitializersOrDie(argc, argv, envp); startupConfigActions(std::vector<std::string>(argv, argv + argc)); - CmdLine::censor(argc, argv); + cmdline_utils::censorArgvArray(argc, argv); try { int exitCode = _main(); return exitCode; diff --git a/src/mongo/s/shard_conn_test.cpp b/src/mongo/s/shard_conn_test.cpp index 867bf2f951b..27b77730c7b 100644 --- a/src/mongo/s/shard_conn_test.cpp +++ b/src/mongo/s/shard_conn_test.cpp @@ -44,7 +44,6 @@ using std::vector; namespace mongo { // Note: these are all crutch and hopefully will eventually go away - CmdLine cmdLine; bool inShutdown() { return false; diff --git a/src/mongo/s/shard_test.cpp b/src/mongo/s/shard_test.cpp index de6fe4f3a6e..3bf6218f77c 100644 --- a/src/mongo/s/shard_test.cpp +++ b/src/mongo/s/shard_test.cpp @@ -34,7 +34,6 @@ namespace mongo { // Note: these are all crutch and hopefully will eventually go away - CmdLine cmdLine; bool inShutdown() { return false; diff --git a/src/mongo/s/version_mongos.cpp b/src/mongo/s/version_mongos.cpp new file mode 100644 index 00000000000..e23c8cfd92a --- /dev/null +++ b/src/mongo/s/version_mongos.cpp @@ -0,0 +1,63 @@ +/** +* 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/>. +* +* As a special exception, the copyright holders give permission to link the +* code of portions of this program with the OpenSSL library under certain +* conditions as described in each individual source file and distribute +* linked combinations including the program with the OpenSSL library. You +* must comply with the GNU Affero General Public License in all respects +* for all of the code used other than as permitted herein. If you modify +* file(s) with this exception, you may extend this exception to your +* version of the file(s), but you are not obligated to do so. If you do not +* wish to do so, delete this exception statement from your version. If you +* delete this exception statement from all source files in the program, +* then also delete it in the license file. +*/ + +#include "mongo/s/version_mongos.h" + +#include <iostream> + +#include "mongo/db/log_process_details.h" +#include "mongo/db/server_options.h" +#include "mongo/platform/process_id.h" +#include "mongo/util/debug_util.h" +#include "mongo/util/log.h" +#include "mongo/util/net/sock.h" +#include "mongo/util/version.h" + +namespace mongo { + + void printShardingVersionInfo( bool out ) { + if ( out ) { + std::cout << "MongoS version " << versionString << " starting: pid=" << + ProcessId::getCurrent() << " port=" << serverGlobalParams.port << + ( sizeof(int*) == 4 ? " 32" : " 64" ) << "-bit host=" << getHostNameCached() << + " (--help for usage)" << std::endl; + DEV std::cout << "_DEBUG build" << std::endl; + std::cout << "git version: " << gitVersion() << std::endl; + std::cout << openSSLVersion("OpenSSL version: ") << std::endl; + std::cout << "build sys info: " << sysInfo() << std::endl; + } + else { + log() << "MongoS version " << versionString << " starting: pid=" << + ProcessId::getCurrent() << " port=" << serverGlobalParams.port << + ( sizeof( int* ) == 4 ? " 32" : " 64" ) << "-bit host=" << getHostNameCached() << + " (--help for usage)" << std::endl; + DEV log() << "_DEBUG build" << std::endl; + logProcessDetails(); + } + } +} // namespace mongo diff --git a/src/mongo/s/version_mongos.h b/src/mongo/s/version_mongos.h new file mode 100644 index 00000000000..491c36da5da --- /dev/null +++ b/src/mongo/s/version_mongos.h @@ -0,0 +1,32 @@ +/** +* 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/>. +* +* As a special exception, the copyright holders give permission to link the +* code of portions of this program with the OpenSSL library under certain +* conditions as described in each individual source file and distribute +* linked combinations including the program with the OpenSSL library. You +* must comply with the GNU Affero General Public License in all respects +* for all of the code used other than as permitted herein. If you modify +* file(s) with this exception, you may extend this exception to your +* version of the file(s), but you are not obligated to do so. If you do not +* wish to do so, delete this exception statement from your version. If you +* delete this exception statement from all source files in the program, +* then also delete it in the license file. +*/ + +namespace mongo { + // print mongos version info + void printShardingVersionInfo(bool out); +} // namespace mongo diff --git a/src/mongo/shell/dbshell.cpp b/src/mongo/shell/dbshell.cpp index df530dfac35..436b383765d 100644 --- a/src/mongo/shell/dbshell.cpp +++ b/src/mongo/shell/dbshell.cpp @@ -27,7 +27,6 @@ #include "mongo/base/status.h" #include "mongo/client/dbclientinterface.h" #include "mongo/client/sasl_client_authenticate.h" -#include "mongo/db/cmdline.h" #include "mongo/db/repl/rs_member.h" #include "mongo/logger/console_appender.h" #include "mongo/logger/logger.h" @@ -791,7 +790,7 @@ Status addMongoShellOptions(moe::OptionSection* options) { Status storeMongoShellOptions() { if ( params.count( "quiet" ) ) { - mongo::cmdLine.quiet = true; + mongo::serverGlobalParams.quiet = true; } #ifdef MONGO_SSL Status ret = storeSSLClientOptions(params); @@ -961,7 +960,7 @@ int _main( int argc, char* argv[], char **envp ) { return mongo::EXIT_BADOPTIONS; } - if ( ! mongo::cmdLine.quiet ) + if (!mongo::serverGlobalParams.quiet) cout << "MongoDB shell version: " << mongo::versionString << endl; mongo::StartupTest::runTests(); @@ -972,10 +971,8 @@ int _main( int argc, char* argv[], char **envp ) { new logger::MessageEventUnadornedEncoder))); if ( !nodb ) { // connect to db - //if ( ! mongo::cmdLine.quiet ) cout << "url: " << url << endl; - stringstream ss; - if ( mongo::cmdLine.quiet ) + if (mongo::serverGlobalParams.quiet) ss << "__quiet = true;"; ss << "db = connect( \"" << fixHost( url , dbhost , port ) << "\")"; @@ -1104,7 +1101,7 @@ int _main( int argc, char* argv[], char **envp ) { f.open(rcLocation.c_str(), false); // Create empty .mongorc.js file } - if ( !nodb && !mongo::cmdLine.quiet && isatty(fileno(stdin)) ) { + if (!nodb && !mongo::serverGlobalParams.quiet && isatty(fileno(stdin))) { scope->exec( "shellHelper( 'show', 'startupWarnings' )", "(shellwarnings", false, true, false ); } @@ -1146,7 +1143,7 @@ int _main( int argc, char* argv[], char **envp ) { } if ( ! linePtr || ( strlen( linePtr ) == 4 && strstr( linePtr , "exit" ) ) ) { - if ( ! mongo::cmdLine.quiet ) + if (!mongo::serverGlobalParams.quiet) cout << "bye" << endl; if ( line ) free( line ); diff --git a/src/mongo/tools/bridge.cpp b/src/mongo/tools/bridge.cpp index b211dcdc5b0..2d3f86cd9de 100644 --- a/src/mongo/tools/bridge.cpp +++ b/src/mongo/tools/bridge.cpp @@ -34,10 +34,6 @@ int delay = 0; string destUri; void cleanup( int sig ); -namespace mongo { - CmdLine cmdLine; -} - class Forwarder { public: Forwarder( MessagingPort &mp ) : mp_( mp ) { diff --git a/src/mongo/tools/sniffer.cpp b/src/mongo/tools/sniffer.cpp index b32f62006dc..2d193186990 100644 --- a/src/mongo/tools/sniffer.cpp +++ b/src/mongo/tools/sniffer.cpp @@ -67,8 +67,6 @@ using mongo::DBClientConnection; using mongo::QueryResult; using mongo::MemoryMappedFile; -mongo::CmdLine mongo::cmdLine; - #define SNAP_LEN 65535 int captureHeaderSize; diff --git a/src/mongo/tools/tool.cpp b/src/mongo/tools/tool.cpp index cd7b1117700..f6fb9e33d4d 100644 --- a/src/mongo/tools/tool.cpp +++ b/src/mongo/tools/tool.cpp @@ -32,6 +32,7 @@ #include "mongo/db/auth/authz_manager_external_state_mock.h" #include "mongo/db/json.h" #include "mongo/db/namespace_details.h" +#include "mongo/db/storage_options.h" #include "mongo/platform/posix_fadvise.h" #include "mongo/util/file_allocator.h" #include "mongo/util/options_parser/option_section.h" @@ -45,7 +46,6 @@ using namespace mongo; namespace mongo { - CmdLine cmdLine; moe::OptionSection options("options"); moe::Environment _params; @@ -72,11 +72,11 @@ namespace mongo { setGlobalAuthorizationManager(new AuthorizationManager(new AuthzManagerExternalStateMock())); - cmdLine.prealloc = false; + storageGlobalParams.prealloc = false; // The default value may vary depending on compile options, but for tools // we want durability to be disabled. - cmdLine.dur = false; + storageGlobalParams.dur = false; _name = argv[0]; @@ -152,7 +152,7 @@ namespace mongo { bool useDirectClient = hasParam( "dbpath" ); if ( useDirectClient && _params.count("journal")){ - cmdLine.dur = true; + storageGlobalParams.dur = true; } preSetup(); @@ -191,7 +191,7 @@ namespace mongo { } else { if ( _params.count( "directoryperdb" ) ) { - directoryperdb = true; + storageGlobalParams.directoryperdb = true; } verify( lastError.get( true ) ); @@ -199,7 +199,7 @@ namespace mongo { _conn = new DBDirectClient(); _host = "DIRECT"; static string myDbpath = getParam( "dbpath" ); - dbpath = myDbpath.c_str(); + storageGlobalParams.dbpath = myDbpath.c_str(); try { acquirePathLock(); } diff --git a/src/mongo/util/assert_util.h b/src/mongo/util/assert_util.h index ff5bc810c28..8ea5f356846 100644 --- a/src/mongo/util/assert_util.h +++ b/src/mongo/util/assert_util.h @@ -293,8 +293,10 @@ namespace mongo { try { \ expression; \ } catch ( const std::exception &e ) { \ - problem() << "caught exception (" << e.what() << ") in destructor (" << __FUNCTION__ << ")" << endl; \ + problem() << "caught exception (" << e.what() << ") in destructor (" << __FUNCTION__ \ + << ")" << std::endl; \ } catch ( ... ) { \ - problem() << "caught unknown exception in destructor (" << __FUNCTION__ << ")" << endl; \ + problem() << "caught unknown exception in destructor (" << __FUNCTION__ << ")" \ + << std::endl; \ } diff --git a/src/mongo/util/cmdline_utils/SConscript b/src/mongo/util/cmdline_utils/SConscript new file mode 100644 index 00000000000..6cdfe310ef7 --- /dev/null +++ b/src/mongo/util/cmdline_utils/SConscript @@ -0,0 +1,10 @@ +# -*- mode: python -*- + +Import("env") + +env.StaticLibrary('cmdline_utils', ['censor_cmdline.cpp'], + LIBDEPS=['$BUILD_DIR/mongo/bson']) + +env.CppUnitTest('censor_cmdline_test', + 'censor_cmdline_test.cpp', + LIBDEPS=['cmdline_utils', '$BUILD_DIR/mongo/unittest/unittest']) diff --git a/src/mongo/util/cmdline_utils/censor_cmdline.cpp b/src/mongo/util/cmdline_utils/censor_cmdline.cpp new file mode 100644 index 00000000000..e50b7018c99 --- /dev/null +++ b/src/mongo/util/cmdline_utils/censor_cmdline.cpp @@ -0,0 +1,161 @@ +// cmdline.cpp + +/** +* Copyright (C) 2008 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/>. +* +* As a special exception, the copyright holders give permission to link the +* code of portions of this program with the OpenSSL library under certain +* conditions as described in each individual source file and distribute +* linked combinations including the program with the OpenSSL library. You +* must comply with the GNU Affero General Public License in all respects for +* all of the code used other than as permitted herein. If you modify file(s) +* with this exception, you may extend this exception to your version of the +* file(s), but you are not obligated to do so. If you do not wish to do so, +* delete this exception statement from your version. If you delete this +* exception statement from all source files in the program, then also delete +* it in the license file. +*/ + +#include "mongo/util/cmdline_utils/censor_cmdline.h" + +#include "mongo/util/mongoutils/str.h" + +namespace mongo { + + namespace cmdline_utils { + + static bool _isPasswordArgument(char const* argumentName); + static bool _isPasswordSwitch(char const* switchName); + + static bool _isPasswordArgument(const char* argumentName) { + static const char* const passwordArguments[] = { + "sslPEMKeyPassword", + "ssl.PEMKeyPassword", + "servicePassword", + NULL // Last entry sentinel. + }; + for (const char* const* current = passwordArguments; *current; ++current) { + if (mongoutils::str::equals(argumentName, *current)) + return true; + } + return false; + } + + static bool _isPasswordSwitch(const char* switchName) { + if (switchName[0] != '-') + return false; + size_t i = 1; + if (switchName[1] == '-') + i = 2; + switchName += i; + + return _isPasswordArgument(switchName); + } + + static void _redact(char* arg) { + for (; *arg; ++arg) + *arg = 'x'; + } + + void censorBSONObjRecursive(const BSONObj& params, // Object we are censoring + const std::string& parentPath, // Set if this is a sub object + bool isArray, + BSONObjBuilder* result) { + BSONObjIterator paramsIterator(params); + while (paramsIterator.more()) { + BSONElement param = paramsIterator.next(); + std::string dottedName = (parentPath.empty() ? param.fieldName() + : isArray ? parentPath + : parentPath + '.' + param.fieldName()); + if (param.type() == Array) { + BSONObjBuilder subArray(result->subarrayStart(param.fieldName())); + censorBSONObjRecursive(param.Obj(), dottedName, true, &subArray); + subArray.done(); + } + else if (param.type() == Object) { + BSONObjBuilder subObj(result->subobjStart(param.fieldName())); + censorBSONObjRecursive(param.Obj(), dottedName, false, &subObj); + subObj.done(); + } + else if (param.type() == String) { + if (_isPasswordArgument(dottedName.c_str())) { + result->append(param.fieldName(), "<password>"); + } + else { + result->append(param); + } + } + else { + result->append(param); + } + } + } + + void censorBSONObj(BSONObj* params) { + BSONObjBuilder builder; + censorBSONObjRecursive(*params, "", false, &builder); + *params = builder.obj(); + } + + void censorArgsVector(std::vector<std::string>* args) { + for (size_t i = 0; i < args->size(); ++i) { + std::string& arg = args->at(i); + const std::string::iterator endSwitch = std::find(arg.begin(), arg.end(), '='); + std::string switchName(arg.begin(), endSwitch); + if (_isPasswordSwitch(switchName.c_str())) { + if (endSwitch == arg.end()) { + if (i + 1 < args->size()) { + args->at(i + 1) = "<password>"; + } + } + else { + arg = switchName + "=<password>"; + } + } + } + } + + void censorArgvArray(int argc, char** argv) { + // Algorithm: For each arg in argv: + // Look for an equal sign in arg; if there is one, temporarily nul it out. + // check to see if arg is a password switch. If so, overwrite the value + // component with xs. + // restore the nul'd out equal sign, if any. + for (int i = 0; i < argc; ++i) { + + char* const arg = argv[i]; + char* const firstEqSign = strchr(arg, '='); + if (NULL != firstEqSign) { + *firstEqSign = '\0'; + } + + if (_isPasswordSwitch(arg)) { + if (NULL == firstEqSign) { + if (i + 1 < argc) { + _redact(argv[i + 1]); + } + } + else { + _redact(firstEqSign + 1); + } + } + + if (NULL != firstEqSign) { + *firstEqSign = '='; + } + } + } + } // namespace cmdline_utils +} diff --git a/src/mongo/util/cmdline_utils/censor_cmdline.h b/src/mongo/util/cmdline_utils/censor_cmdline.h new file mode 100644 index 00000000000..7ab29429697 --- /dev/null +++ b/src/mongo/util/cmdline_utils/censor_cmdline.h @@ -0,0 +1,49 @@ +/** +* Copyright (C) 2008 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/>. +* +* As a special exception, the copyright holders give permission to link the +* code of portions of this program with the OpenSSL library under certain +* conditions as described in each individual source file and distribute +* linked combinations including the program with the OpenSSL library. You +* must comply with the GNU Affero General Public License in all respects for +* all of the code used other than as permitted herein. If you modify file(s) +* with this exception, you may extend this exception to your version of the +* file(s), but you are not obligated to do so. If you do not wish to do so, +* delete this exception statement from your version. If you delete this +* exception statement from all source files in the program, then also delete +* it in the license file. +*/ + +#pragma once + +#include <string> +#include <vector> + +#include "mongo/db/jsobj.h" + +namespace mongo { + + namespace cmdline_utils { + + /** + * Blot out sensitive fields in the argv array. + */ + void censorArgvArray(int argc, char** argv); + void censorArgsVector(std::vector<std::string>* args); + void censorBSONObj(BSONObj* params); + + } // namespace cmdline_utils +} + diff --git a/src/mongo/db/cmdline_test.cpp b/src/mongo/util/cmdline_utils/censor_cmdline_test.cpp index 9fe03f309c9..7648f607ecd 100644 --- a/src/mongo/db/cmdline_test.cpp +++ b/src/mongo/util/cmdline_utils/censor_cmdline_test.cpp @@ -30,14 +30,13 @@ #include <string> #include <vector> -#include "mongo/db/cmdline.h" #include "mongo/db/jsobj.h" #include "mongo/unittest/unittest.h" +#include "mongo/util/cmdline_utils/censor_cmdline.h" #include "mongo/util/options_parser/environment.h" namespace mongo { - CmdLine cmdLine; #ifdef MONGO_SSL Status storeSSLServerOptions(const optionenvironment::Environment& params) { @@ -61,7 +60,7 @@ namespace { char** argv = &*arrayStandin.begin(); - CmdLine::censor(elementCount, argv); + cmdline_utils::censorArgvArray(elementCount, argv); for (int i = 0; i < elementCount; ++i) { ASSERT_EQUALS(std::string(expected[i]), std::string(argv[i])); @@ -74,7 +73,7 @@ namespace { std::vector<std::string> actual(toCensor, toCensor + elementCount); - CmdLine::censor(&actual); + cmdline_utils::censorArgsVector(&actual); for (int i = 0; i < elementCount; ++i) { ASSERT_EQUALS(std::string(expected[i]), actual[i]); @@ -243,49 +242,98 @@ 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(BSONObjCensorTests, Strings) { + BSONObj obj = BSON("firstarg" << "not a password" << + "sslPEMKeyPassword" << "this password should be censored" << + "middlearg" << "also not a password" << + "servicePassword" << "this password should also be censored" << + "lastarg" << false << + "servicePassword" << true); + + BSONObj res = BSON("firstarg" << "not a password" << + "sslPEMKeyPassword" << "<password>" << + "middlearg" << "also not a password" << + "servicePassword" << "<password>" << + "lastarg" << false << + "servicePassword" << true); + + cmdline_utils::censorBSONObj(&obj); + ASSERT_EQUALS(res, obj); } - 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(BSONObjCensorTests, Arrays) { + BSONObj obj = BSON("firstarg" << "not a password" << + "sslPEMKeyPassword" << BSON_ARRAY("first censored password" << + "next censored password") << + "middlearg" << "also not a password" << + "servicePassword" << BSON_ARRAY("first censored password" << + "next censored password") << + "lastarg" << false << + "servicePassword" << true); + + BSONObj res = BSON("firstarg" << "not a password" << + "sslPEMKeyPassword" << BSON_ARRAY("<password>" << + "<password>") << + "middlearg" << "also not a password" << + "servicePassword" << BSON_ARRAY("<password>" << + "<password>") << + "lastarg" << false << + "servicePassword" << true); + + cmdline_utils::censorBSONObj(&obj); + ASSERT_EQUALS(res, obj); } - 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()); + TEST(BSONObjCensorTests, SubObjects) { + BSONObj obj = BSON("firstarg" << "not a password" << + "ssl" << BSON("PEMKeyPassword" << BSON_ARRAY("first censored password" << + "next censored password") << + "PEMKeyPassword" << "should be censored too") << + "lastarg" << false << + "servicePassword" << true); + + BSONObj res = BSON("firstarg" << "not a password" << + "ssl" << BSON("PEMKeyPassword" << BSON_ARRAY("<password>" << + "<password>") << + "PEMKeyPassword" << "<password>") << + "lastarg" << false << + "servicePassword" << true); + + cmdline_utils::censorBSONObj(&obj); + ASSERT_EQUALS(res, obj); } + TEST(BSONObjCensorTests, Full) { + BSONObj obj = BSON("firstarg" << "not a password" << + "sslPEMKeyPassword" << "this password should be censored" << + "sslPEMKeyPassword" << BSON_ARRAY("first censored password" << + "next censored password") << + "middlearg" << "also not a password" << + "servicePassword" << "this password should also be censored" << + "servicePassword" << BSON_ARRAY("first censored password" << + "next censored password") << + "ssl" << BSON("PEMKeyPassword" << BSON_ARRAY("first censored password" << + "next censored password") << + "PEMKeyPassword" << "should be censored too") << + "lastarg" << false << + "servicePassword" << true); + + BSONObj res = BSON("firstarg" << "not a password" << + "sslPEMKeyPassword" << "<password>" << + "sslPEMKeyPassword" << BSON_ARRAY("<password>" << + "<password>") << + "middlearg" << "also not a password" << + "servicePassword" << "<password>" << + "servicePassword" << BSON_ARRAY("<password>" << + "<password>") << + "ssl" << BSON("PEMKeyPassword" << BSON_ARRAY("<password>" << + "<password>") << + "PEMKeyPassword" << "<password>") << + "lastarg" << false << + "servicePassword" << true); + + cmdline_utils::censorBSONObj(&obj); + ASSERT_EQUALS(res, obj); + } } // namespace } // namespace mongo diff --git a/src/mongo/util/debug_util.cpp b/src/mongo/util/debug_util.cpp index 816b0af4a2d..a496e882c67 100644 --- a/src/mongo/util/debug_util.cpp +++ b/src/mongo/util/debug_util.cpp @@ -22,7 +22,6 @@ #endif #if defined(USE_GDBSERVER) -#include "mongo/db/cmdline.h" #include "mongo/db/jsobj.h" #endif // defined(USE_GDBSERVER) @@ -53,13 +52,13 @@ namespace mongo { * Assumptions: * 1) gdbserver is on your path * 2) You have run "handle SIGSTOP noprint" in gdb - * 3) cmdLine.port + 2000 is free + * 3) serverGlobalParams.port + 2000 is free */ void launchGDB(int) { // Don't come back here signal(SIGTRAP, SIG_IGN); - int newPort = cmdLine.port + 2000; + int newPort = serverGlobalParams.port + 2000; string newPortStr = "localhost:" + BSONObjBuilder::numStr(newPort); string pidToDebug = BSONObjBuilder::numStr(getpid()); diff --git a/src/mongo/util/mmap.cpp b/src/mongo/util/mmap.cpp index 78588dd3a14..207675e75de 100644 --- a/src/mongo/util/mmap.cpp +++ b/src/mongo/util/mmap.cpp @@ -21,7 +21,6 @@ #include <boost/filesystem/operations.hpp> -#include "mongo/db/cmdline.h" #include "mongo/util/concurrency/rwlock.h" #include "mongo/util/map_util.h" #include "mongo/util/mongoutils/str.h" diff --git a/src/mongo/util/net/hostandport.h b/src/mongo/util/net/hostandport.h index ff47d7f9ef4..aa1a395643b 100644 --- a/src/mongo/util/net/hostandport.h +++ b/src/mongo/util/net/hostandport.h @@ -18,7 +18,7 @@ #pragma once #include "mongo/bson/util/builder.h" -#include "mongo/db/cmdline.h" +#include "mongo/db/server_options.h" #include "mongo/util/mongoutils/str.h" #include "mongo/util/net/sock.h" @@ -38,7 +38,7 @@ namespace mongo { /** @param p port number. -1 is ok to use default. */ HostAndPort(const std::string& h, int p /*= -1*/) : _host(h), _port(p) { - verify( !str::startsWith(h, '#') ); + verify(!mongoutils::str::startsWith(h, '#')); } HostAndPort(const SockAddr& sock ) : _host( sock.getAddr() ) , _port( sock.getPort() ) { } @@ -84,7 +84,7 @@ namespace mongo { int port() const { if (hasPort()) return _port; - return CmdLine::DefaultDBPort; + return ServerGlobalParams::DefaultDBPort; } bool hasPort() const { return _port >= 0; @@ -100,7 +100,7 @@ namespace mongo { }; inline HostAndPort HostAndPort::me() { - const char* ips = cmdLine.bind_ip.c_str(); + const char* ips = serverGlobalParams.bind_ip.c_str(); while(*ips) { string ip; const char * comma = strchr(ips, ','); @@ -112,7 +112,7 @@ namespace mongo { ip = string(ips); ips = ""; } - HostAndPort h = HostAndPort(ip, cmdLine.port); + HostAndPort h = HostAndPort(ip, serverGlobalParams.port); if (!h.isLocalHost()) { return h; } @@ -121,7 +121,7 @@ namespace mongo { string h = getHostName(); verify( !h.empty() ); verify( h != "localhost" ); - return HostAndPort(h, cmdLine.port); + return HostAndPort(h, serverGlobalParams.port); } inline string HostAndPort::toString( bool includePort ) const { @@ -142,7 +142,7 @@ namespace mongo { ss << ':'; #if defined(_DEBUG) if( p >= 44000 && p < 44100 ) { - log() << "warning: special debug port 44xxx used" << endl; + log() << "warning: special debug port 44xxx used" << std::endl; ss << p+1; } else @@ -158,7 +158,7 @@ namespace mongo { inline bool HostAndPort::isLocalHost() const { string _host = host(); return ( _host == "localhost" - || startsWith(_host.c_str(), "127.") + || mongoutils::str::startsWith(_host.c_str(), "127.") || _host == "::1" || _host == "anonymous unix socket" || _host.c_str()[0] == '/' // unix socket diff --git a/src/mongo/util/net/listen.cpp b/src/mongo/util/net/listen.cpp index 3492dc76b69..845681881ad 100644 --- a/src/mongo/util/net/listen.cpp +++ b/src/mongo/util/net/listen.cpp @@ -115,7 +115,8 @@ namespace mongo { checkTicketNumbers(); #if !defined(_WIN32) - _mine = ipToAddrs(_ip.c_str(), _port, (!cmdLine.noUnixSocket && useUnixSockets())); + _mine = ipToAddrs(_ip.c_str(), _port, (!serverGlobalParams.noUnixSocket && + useUnixSockets())); #else _mine = ipToAddrs(_ip.c_str(), _port, false); #endif @@ -289,7 +290,7 @@ namespace mongo { long long myConnectionNumber = globalConnectionNumber.addAndFetch(1); - if ( _logConnect && ! cmdLine.quiet ){ + if (_logConnect && !serverGlobalParams.quiet) { int conns = globalTicketHolder.used()+1; const char* word = (conns == 1 ? " connection" : " connections"); log() << "connection accepted from " << from.toString() << " #" << myConnectionNumber << " (" << conns << word << " now open)" << endl; @@ -483,7 +484,7 @@ namespace mongo { long long myConnectionNumber = globalConnectionNumber.addAndFetch(1); - if ( _logConnect && ! cmdLine.quiet ){ + if (_logConnect && !serverGlobalParams.quiet) { int conns = globalTicketHolder.used()+1; const char* word = (conns == 1 ? " connection" : " connections"); log() << "connection accepted from " << from.toString() << " #" << myConnectionNumber << " (" << conns << word << " now open)" << endl; diff --git a/src/mongo/util/net/message.h b/src/mongo/util/net/message.h index 738d3a34ba5..aa30bd85cfc 100644 --- a/src/mongo/util/net/message.h +++ b/src/mongo/util/net/message.h @@ -17,7 +17,10 @@ #pragma once +#include <vector> + #include "mongo/bson/util/atomic_int.h" +#include "mongo/util/goodies.h" #include "mongo/util/net/hostandport.h" #include "mongo/util/net/sock.h" @@ -201,12 +204,14 @@ namespace mongo { verify( _freeIt ); int totalSize = 0; - for( vector< pair< char *, int > >::const_iterator i = _data.begin(); i != _data.end(); ++i ) { + for (std::vector< std::pair< char *, int > >::const_iterator i = _data.begin(); + i != _data.end(); ++i) { totalSize += i->second; } char *buf = (char*)malloc( totalSize ); char *p = buf; - for( vector< pair< char *, int > >::const_iterator i = _data.begin(); i != _data.end(); ++i ) { + for (std::vector< std::pair< char *, int > >::const_iterator i = _data.begin(); + i != _data.end(); ++i) { memcpy( p, i->first, i->second ); p += i->second; } @@ -233,7 +238,8 @@ namespace mongo { if ( _buf ) { free( _buf ); } - for( vector< pair< char *, int > >::const_iterator i = _data.begin(); i != _data.end(); ++i ) { + for (std::vector< std::pair< char *, int > >::const_iterator i = _data.begin(); + i != _data.end(); ++i) { free(i->first); } } @@ -256,10 +262,10 @@ namespace mongo { } verify( _freeIt ); if ( _buf ) { - _data.push_back( make_pair( (char*)_buf, _buf->len ) ); + _data.push_back(std::make_pair((char*)_buf, _buf->len)); _buf = 0; } - _data.push_back( make_pair( d, size ) ); + _data.push_back(std::make_pair(d, size)); header()->len += size; } @@ -297,7 +303,7 @@ namespace mongo { // if just one buffer, keep it in _buf, otherwise keep a sequence of buffers in _data MsgData * _buf; // byte buffer(s) - the first must contain at least a full MsgData unless using _buf for storage instead - typedef vector< pair< char*, int > > MsgVec; + typedef std::vector< std::pair< char*, int > > MsgVec; MsgVec _data; bool _freeIt; }; diff --git a/src/mongo/util/net/message_port.cpp b/src/mongo/util/net/message_port.cpp index 1138865c294..772eeff77e9 100644 --- a/src/mongo/util/net/message_port.cpp +++ b/src/mongo/util/net/message_port.cpp @@ -22,7 +22,6 @@ #include <fcntl.h> #include <time.h> -#include "mongo/db/cmdline.h" #include "mongo/util/background.h" #include "mongo/util/goodies.h" #include "mongo/util/net/listen.h" diff --git a/src/mongo/util/net/message_port.h b/src/mongo/util/net/message_port.h index cf11bea8773..8949f8081fb 100644 --- a/src/mongo/util/net/message_port.h +++ b/src/mongo/util/net/message_port.h @@ -17,6 +17,8 @@ #pragma once +#include <vector> + #include "mongo/util/net/message.h" #include "mongo/util/net/sock.h" @@ -112,7 +114,7 @@ namespace mongo { void send( const char * data , int len, const char *context ) { psock->send( data, len, context ); } - void send( const vector< pair< char *, int > > &data, const char *context ) { + void send(const std::vector< std::pair< char *, int > > &data, const char *context) { psock->send( data, context ); } bool connect(SockAddr& farEnd) { diff --git a/src/mongo/util/net/message_server_port.cpp b/src/mongo/util/net/message_server_port.cpp index cdcaef2c6fa..f1fec225e49 100644 --- a/src/mongo/util/net/message_server_port.cpp +++ b/src/mongo/util/net/message_server_port.cpp @@ -22,7 +22,6 @@ #ifndef USE_ASIO -#include "mongo/db/cmdline.h" #include "mongo/db/lasterror.h" #include "mongo/db/stats/counters.h" #include "mongo/util/concurrency/ticketholder.h" @@ -198,7 +197,7 @@ namespace mongo { p->psock->clearCounters(); if ( ! p->recv(m) ) { - if( !cmdLine.quiet ){ + if (!serverGlobalParams.quiet) { int conns = Listener::globalTicketHolder.used()-1; const char* word = (conns == 1 ? " connection" : " connections"); log() << "end connection " << otherSide << " (" << conns << word << " now open)" << endl; diff --git a/src/mongo/util/net/sock.cpp b/src/mongo/util/net/sock.cpp index 5afd18c4c70..327296257d2 100644 --- a/src/mongo/util/net/sock.cpp +++ b/src/mongo/util/net/sock.cpp @@ -40,7 +40,6 @@ #include "mongo/util/mongoutils/str.h" #include "mongo/util/net/message.h" #include "mongo/util/net/ssl_manager.h" -#include "mongo/db/cmdline.h" namespace mongo { MONGO_FP_DECLARE(throwSockExcep); @@ -316,7 +315,8 @@ namespace mongo { SockAddr unknownAddress( "0.0.0.0", 0 ); string makeUnixSockPath(int port) { - return mongoutils::str::stream() << cmdLine.socket << "/mongodb-" << port << ".sock"; + return mongoutils::str::stream() << serverGlobalParams.socket << "/mongodb-" << port + << ".sock"; } @@ -357,8 +357,8 @@ namespace mongo { string prettyHostName() { StringBuilder s; s << getHostNameCached(); - if( cmdLine.port != CmdLine::DefaultDBPort ) - s << ':' << mongo::cmdLine.port; + if (serverGlobalParams.port != ServerGlobalParams::DefaultDBPort) + s << ':' << mongo::serverGlobalParams.port; return s.str(); } diff --git a/src/mongo/util/net/sock_test.cpp b/src/mongo/util/net/sock_test.cpp index 1bba7228e82..349e4b0903a 100644 --- a/src/mongo/util/net/sock_test.cpp +++ b/src/mongo/util/net/sock_test.cpp @@ -38,14 +38,14 @@ #include <sys/types.h> #endif -#include "mongo/db/cmdline.h" +#include "mongo/db/server_options.h" #include "mongo/unittest/unittest.h" #include "mongo/util/concurrency/synchronization.h" #include "mongo/util/fail_point_service.h" namespace mongo { - CmdLine cmdLine; + ServerGlobalParams serverGlobalParams; bool inShutdown() { return false; diff --git a/src/mongo/util/net/ssl_options.cpp b/src/mongo/util/net/ssl_options.cpp index ee1900dbb75..3251b7fd3d5 100644 --- a/src/mongo/util/net/ssl_options.cpp +++ b/src/mongo/util/net/ssl_options.cpp @@ -18,7 +18,7 @@ #include <boost/filesystem/operations.hpp> #include "mongo/base/status.h" -#include "mongo/db/cmdline.h" +#include "mongo/db/server_options.h" #include "mongo/util/options_parser/environment.h" #include "mongo/util/options_parser/option_description.h" #include "mongo/util/options_parser/option_section.h" @@ -176,16 +176,17 @@ namespace mongo { sslGlobalParams.sslFIPSMode) { return Status(ErrorCodes::BadValue, "need to enable sslOnNormalPorts"); } - if (cmdLine.clusterAuthMode == "sendKeyfile" || - cmdLine.clusterAuthMode == "sendX509" || - cmdLine.clusterAuthMode == "x509") { + if (serverGlobalParams.clusterAuthMode == "sendKeyfile" || + serverGlobalParams.clusterAuthMode == "sendX509" || + serverGlobalParams.clusterAuthMode == "x509") { if (!sslGlobalParams.sslOnNormalPorts){ return Status(ErrorCodes::BadValue, "need to enable sslOnNormalPorts"); } } - else if (params.count("clusterAuthMode") && cmdLine.clusterAuthMode != "keyfile") { + else if (params.count("clusterAuthMode") && + serverGlobalParams.clusterAuthMode != "keyfile") { StringBuilder sb; - sb << "unsupported value for clusterAuthMode " << cmdLine.clusterAuthMode; + sb << "unsupported value for clusterAuthMode " << serverGlobalParams.clusterAuthMode; return Status(ErrorCodes::BadValue, sb.str()); } diff --git a/src/mongo/util/options_parser/environment.cpp b/src/mongo/util/options_parser/environment.cpp index 41e94d90d40..cc4ad2a71aa 100644 --- a/src/mongo/util/options_parser/environment.cpp +++ b/src/mongo/util/options_parser/environment.cpp @@ -19,6 +19,8 @@ #include <iostream> #include "mongo/bson/util/builder.h" +#include "mongo/bson/bsonobjiterator.h" +#include "mongo/db/jsobj.h" #include "mongo/util/options_parser/constraints.h" namespace mongo { @@ -191,5 +193,147 @@ namespace optionenvironment { } } +namespace { + + // 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<Key, Value>& params, + BSONObjBuilder* builder, + const std::string& prefix = std::string()) { + for (std::map<Key, Value>::const_iterator it(params.begin()); + it != params.end(); it++) { + Key key = it->first; + 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<Key, Value> sectionMap; + + std::string beforeDot = key.substr(0, dotOffset); + std::string afterDot = key.substr(dotOffset + 1, key.size() - dotOffset - 1); + std::map<Key, 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, §ionObjBuilder, 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; + } + + // 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 { + 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 + + BSONObj Environment::toBSON() const { + BSONObjBuilder builder; + Status ret = valueMapToBSON(values, &builder); + if (!ret.isOK()) { + return BSONObj(); + } + return builder.obj(); + } + } // namespace optionenvironment } // namespace mongo diff --git a/src/mongo/util/options_parser/environment.h b/src/mongo/util/options_parser/environment.h index e2163ca5ecf..f7c8929814d 100644 --- a/src/mongo/util/options_parser/environment.h +++ b/src/mongo/util/options_parser/environment.h @@ -20,6 +20,7 @@ #include <vector> #include "mongo/base/status.h" +#include "mongo/db/jsobj.h" #include "mongo/util/options_parser/value.h" namespace mongo { @@ -161,13 +162,36 @@ namespace optionenvironment { Value operator[](const Key& key) const; /** - * Get all values that we have set explicitly as a map in case we need to iterate or - * move to another structure, as is currently the use case for the parsed command line - * options structure that we present to the user. + * Gets the BSON representation of this Environment. This will collapse dotted fields + * into sub objects. + * + * Example: + * + * The following Environment values map: + * "a.b.c" -> true + * "a.b.d" -> false + * "a.e.f" -> 0 + * "a.e.g" -> 1 + * "a.h" -> "foo" + * + * Has a BSON represation of (shown as JSON): + * { "a" : { + * "b" : { + * "c" : true, + * "d" : false + * }, + * "e" : { + * "f" : 0, + * "g" : 1 + * }, + * "h" : "foo" + * } + * } + * + * Note that the BSON representation only includes fields that were explicitly set using + * setAll or set, and not defaults that were specified using setDefault. */ - const std::map<Key, Value>& getExplicitlySet() const { - return values; - } + BSONObj toBSON() const; /* Debugging */ void dump(); diff --git a/src/mongo/util/options_parser/environment_test.cpp b/src/mongo/util/options_parser/environment_test.cpp index 8893ea9db9f..959d1d08f7b 100644 --- a/src/mongo/util/options_parser/environment_test.cpp +++ b/src/mongo/util/options_parser/environment_test.cpp @@ -78,29 +78,44 @@ namespace { ASSERT_EQUALS(number, 5); } - TEST(Environment, DefaultValueIterateExplicit) { + TEST(ToBSONTests, NormalValues) { moe::Environment environment; - ASSERT_OK(environment.setDefault(moe::Key("val1"), moe::Value(5))); - ASSERT_OK(environment.setDefault(moe::Key("val2"), moe::Value(5))); ASSERT_OK(environment.set(moe::Key("val1"), moe::Value(6))); - int val1; - ASSERT_OK(environment.get(moe::Key("val1"), &val1)); - ASSERT_EQUALS(val1, 6); - int val2; - ASSERT_OK(environment.get(moe::Key("val2"), &val2)); - ASSERT_EQUALS(val2, 5); - - const std::map<moe::Key, moe::Value> values = environment.getExplicitlySet(); - ASSERT_EQUALS((static_cast<std::map<moe::Key, moe::Value>::size_type>(1)), values.size()); + ASSERT_OK(environment.set(moe::Key("val2"), moe::Value(std::string("string")))); + mongo::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, environment.toBSON()); + } - typedef std::map<moe::Key, moe::Value>::const_iterator it_type; - for(it_type iterator = values.begin(); - iterator != values.end(); iterator++) { - ASSERT_EQUALS(moe::Key("val1"), iterator->first); - int val1; - ASSERT_OK(iterator->second.get(&val1)); - ASSERT_EQUALS(6, val1); - } + TEST(ToBSONTests, 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")))); + mongo::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, environment.toBSON()); } + TEST(ToBSONTests, 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))); + mongo::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, environment.toBSON()); + } } // unnamed namespace diff --git a/src/mongo/util/options_parser/options_parser_test.cpp b/src/mongo/util/options_parser/options_parser_test.cpp index 9a97892fce8..33de98fb731 100644 --- a/src/mongo/util/options_parser/options_parser_test.cpp +++ b/src/mongo/util/options_parser/options_parser_test.cpp @@ -461,7 +461,7 @@ namespace { ASSERT_EQUALS(port, 6); } - TEST(Parsing, DefaultValueIterateExplicit) { + TEST(Parsing, DefaultValuesNotInBSON) { moe::OptionsParser parser; moe::Environment environment; @@ -480,23 +480,8 @@ namespace { ASSERT_OK(parser.run(testOpts, argv, env_map, &environment)); - const std::map<moe::Key, moe::Value> values = environment.getExplicitlySet(); - ASSERT_EQUALS((static_cast<std::map<moe::Key, moe::Value>::size_type>(1)), values.size()); - - typedef std::map<moe::Key, moe::Value>::const_iterator it_type; - for(it_type iterator = values.begin(); - iterator != values.end(); iterator++) { - ASSERT_EQUALS(moe::Key("val1"), iterator->first); - int val1; - ASSERT_OK(iterator->second.get(&val1)); - ASSERT_EQUALS(6, val1); - } - - moe::Value value; - ASSERT_OK(environment.get(moe::Key("val2"), &value)); - int val2; - ASSERT_OK(value.get(&val2)); - ASSERT_EQUALS(val2, 5); + mongo::BSONObj expected = BSON("val1" << 6); + ASSERT_EQUALS(expected, environment.toBSON()); } TEST(Parsing, ImplicitValue) { diff --git a/src/mongo/util/paths.h b/src/mongo/util/paths.h index 9b59291e53a..c103ae22635 100644 --- a/src/mongo/util/paths.h +++ b/src/mongo/util/paths.h @@ -26,12 +26,12 @@ #include "mongo/util/log.h" #include "mongo/util/mongoutils/str.h" +#include "mongo/db/storage_options.h" + namespace mongo { using namespace mongoutils; - extern string dbpath; - /** this is very much like a boost::path. however, we define a new type to get some type checking. if you want to say 'my param MUST be a relative path", use this. */ @@ -48,7 +48,7 @@ namespace mongo { /** from a full path */ static RelativePath fromFullPath(boost::filesystem::path f) { - boost::filesystem::path dbp(dbpath); // normalizes / and backslash + boost::filesystem::path dbp(storageGlobalParams.dbpath); // normalizes / and backslash string fullpath = f.string(); string relative = str::after(fullpath, dbp.string()); if( relative.empty() ) { @@ -57,9 +57,6 @@ namespace mongo { rp._p = fullpath; return rp; } - /*uassert(13600, - str::stream() << "file path is not under the db path? " << fullpath << ' ' << dbpath, - relative != fullpath);*/ if( str::startsWith(relative, "/") || str::startsWith(relative, "\\") ) { relative.erase(0, 1); } @@ -75,7 +72,7 @@ namespace mongo { bool operator<(const RelativePath& r) const { return _p < r._p; } string asFullPath() const { - boost::filesystem::path x(dbpath); + boost::filesystem::path x(storageGlobalParams.dbpath); x /= _p; return x.string(); } diff --git a/src/mongo/util/version.cpp b/src/mongo/util/version.cpp index 5fcbe599bf6..e5c2af0a309 100644 --- a/src/mongo/util/version.cpp +++ b/src/mongo/util/version.cpp @@ -23,12 +23,10 @@ #include <string> #include <fstream> -#include <boost/filesystem/operations.hpp> - #include "mongo/base/parse_number.h" -#include "mongo/db/cmdline.h" #include "mongo/db/jsobj.h" #include "mongo/db/pdfile_version.h" +#include "mongo/db/storage_options.h" #include "mongo/util/file.h" #include "mongo/util/net/ssl_manager.h" #include "mongo/util/processinfo.h" @@ -201,158 +199,6 @@ namespace mongo { result.appendNumber("maxBsonObjectSize", BSONObjMaxUserSize); } - // - // system warnings - // - void show_warnings() { - // each message adds a leading and a trailing newline - - bool warned = false; - { - const char * foo = strchr( versionString , '.' ) + 1; - int bar = atoi( foo ); - if ( ( 2 * ( bar / 2 ) ) != bar ) { - log() << startupWarningsLog; - log() << "** NOTE: This is a development version (" << versionString << ") of MongoDB." << startupWarningsLog; - log() << "** Not recommended for production." << startupWarningsLog; - warned = true; - } - } - - if ( sizeof(int*) == 4 ) { - log() << startupWarningsLog; - log() << "** NOTE: This is a 32 bit MongoDB binary." << startupWarningsLog; - log() << "** 32 bit builds are limited to less than 2GB of data (or less with --journal)." << startupWarningsLog; - if( !cmdLine.dur ) { - log() << "** Note that journaling defaults to off for 32 bit and is currently off." << startupWarningsLog; - } - log() << "** See http://dochub.mongodb.org/core/32bit" << startupWarningsLog; - warned = true; - } - - if ( !ProcessInfo::blockCheckSupported() ) { - log() << startupWarningsLog; - log() << "** NOTE: your operating system version does not support the method that MongoDB" << startupWarningsLog; - log() << "** uses to detect impending page faults." << startupWarningsLog; - log() << "** This may result in slower performance for certain use cases" << startupWarningsLog; - warned = true; - } -#ifdef __linux__ - if (boost::filesystem::exists("/proc/vz") && !boost::filesystem::exists("/proc/bc")) { - log() << startupWarningsLog; - log() << "** WARNING: You are running in OpenVZ. This is known to be broken!!!" << startupWarningsLog; - warned = true; - } - - if (boost::filesystem::exists("/sys/devices/system/node/node1")){ - // We are on a box with a NUMA enabled kernel and more than 1 numa node (they start at node0) - // Now we look at the first line of /proc/self/numa_maps - // - // Bad example: - // $ cat /proc/self/numa_maps - // 00400000 default file=/bin/cat mapped=6 N4=6 - // - // Good example: - // $ numactl --interleave=all cat /proc/self/numa_maps - // 00400000 interleave:0-7 file=/bin/cat mapped=6 N4=6 - - std::ifstream f("/proc/self/numa_maps", std::ifstream::in); - if (f.is_open()) { - std::string line; //we only need the first line - std::getline(f, line); - if (f.fail()) { - warning() << "failed to read from /proc/self/numa_maps: " - << errnoWithDescription() << startupWarningsLog; - warned = true; - } - else { - // skip over pointer - std::string::size_type where = line.find(' '); - if ( (where == std::string::npos) || (++where == line.size()) ) { - log() << startupWarningsLog; - log() << "** WARNING: cannot parse numa_maps line: '" << line << "'" << startupWarningsLog; - warned = true; - } - // if the text following the space doesn't begin with 'interleave', then - // issue the warning. - else if ( line.find("interleave", where) != where ) { - log() << startupWarningsLog; - log() << "** WARNING: You are running on a NUMA machine." << startupWarningsLog; - log() << "** We suggest launching mongod like this to avoid performance problems:" << startupWarningsLog; - log() << "** numactl --interleave=all mongod [other options]" << startupWarningsLog; - warned = true; - } - } - } - } - - if (cmdLine.dur){ - fstream f ("/proc/sys/vm/overcommit_memory", ios_base::in); - unsigned val; - f >> val; - - if (val == 2) { - log() << startupWarningsLog; - log() << "** WARNING: /proc/sys/vm/overcommit_memory is " << val << startupWarningsLog; - log() << "** Journaling works best with it set to 0 or 1" << startupWarningsLog; - } - } - - if (boost::filesystem::exists("/proc/sys/vm/zone_reclaim_mode")){ - fstream f ("/proc/sys/vm/zone_reclaim_mode", ios_base::in); - unsigned val; - f >> val; - - if (val != 0) { - log() << startupWarningsLog; - log() << "** WARNING: /proc/sys/vm/zone_reclaim_mode is " << val << startupWarningsLog; - log() << "** We suggest setting it to 0" << startupWarningsLog; - log() << "** http://www.kernel.org/doc/Documentation/sysctl/vm.txt" << startupWarningsLog; - } - } -#endif - -#if defined(RLIMIT_NPROC) && defined(RLIMIT_NOFILE) - //Check that # of files rlmit > 1000 , and # of processes > # of files/2 - const unsigned int minNumFiles = 1000; - const double filesToProcsRatio = 2.0; - struct rlimit rlnproc; - struct rlimit rlnofile; - - if(!getrlimit(RLIMIT_NPROC,&rlnproc) && !getrlimit(RLIMIT_NOFILE,&rlnofile)){ - if(rlnofile.rlim_cur < minNumFiles){ - log() << startupWarningsLog; - log() << "** WARNING: soft rlimits too low. Number of files is " - << rlnofile.rlim_cur - << ", should be at least " << minNumFiles << startupWarningsLog; - } - - if(false){ - // juse to make things cleaner - } -#ifdef __APPLE__ - else if(rlnproc.rlim_cur >= 709){ - // os x doesn't make it easy to go higher - // ERH thinks its ok not to add the warning in this case 7/3/2012 - } -#endif - else if(rlnproc.rlim_cur < rlnofile.rlim_cur/filesToProcsRatio){ - log() << startupWarningsLog; - log() << "** WARNING: soft rlimits too low. rlimits set to " << rlnproc.rlim_cur << " processes, " - << rlnofile.rlim_cur << " files. Number of processes should be at least " - << rlnofile.rlim_cur/filesToProcsRatio << " : " - << 1/filesToProcsRatio << " times number of files." << startupWarningsLog; - } - } else { - log() << startupWarningsLog; - log() << "** WARNING: getrlimit failed. " << errnoWithDescription() << startupWarningsLog; - } -#endif - if (warned) { - log() << startupWarningsLog; - } - } - class VersionArrayTest : public StartupTest { public: void run() { |