summaryrefslogtreecommitdiff
path: root/src/mongo/db/db.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/db.cpp')
-rw-r--r--src/mongo/db/db.cpp1257
1 files changed, 398 insertions, 859 deletions
diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp
index 2361ec2a945..90a8013dba2 100644
--- a/src/mongo/db/db.cpp
+++ b/src/mongo/db/db.cpp
@@ -14,18 +14,38 @@
*
* 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/pch.h"
+#include <boost/shared_ptr.hpp>
#include <boost/thread/thread.hpp>
#include <boost/filesystem/operations.hpp>
#include <fstream>
+#include "mongo/base/init.h"
#include "mongo/base/initializer.h"
+#include "mongo/base/status.h"
+#include "mongo/db/auth/auth_index_d.h"
+#include "mongo/db/auth/authz_manager_external_state_d.h"
+#include "mongo/db/auth/authorization_manager.h"
+#include "mongo/db/auth/authorization_manager_global.h"
+#include "mongo/db/catalog/index_catalog.h"
+#include "mongo/db/catalog/index_key_validate.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"
@@ -33,33 +53,48 @@
#include "mongo/db/dbmessage.h"
#include "mongo/db/dbwebserver.h"
#include "mongo/db/dur.h"
+#include "mongo/db/index_names.h"
#include "mongo/db/index_rebuilder.h"
#include "mongo/db/initialize_server_global_state.h"
#include "mongo/db/instance.h"
#include "mongo/db/introspect.h"
#include "mongo/db/json.h"
#include "mongo/db/kill_current_op.h"
-#include "mongo/db/module.h"
-#include "mongo/db/pdfile.h"
-#include "mongo/db/repl.h"
+#include "mongo/db/log_process_details.h"
+#include "mongo/db/mongod_options.h"
+#include "mongo/db/query/internal_plans.h"
+#include "mongo/db/range_deleter_service.h"
+#include "mongo/db/repair_database.h"
+#include "mongo/db/repl/repl_start.h"
+#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/storage_engine_metadata.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"
#include "mongo/util/file_allocator.h"
#include "mongo/util/net/message_server.h"
+#include "mongo/util/net/ssl_manager.h"
#include "mongo/util/ntservice.h"
+#include "mongo/util/options_parser/startup_options.h"
#include "mongo/util/ramlog.h"
+#include "mongo/util/scopeguard.h"
+#include "mongo/util/signal_handlers.h"
#include "mongo/util/stacktrace.h"
#include "mongo/util/startup_test.h"
#include "mongo/util/text.h"
-#include "mongo/util/version.h"
+#include "mongo/util/version_reporting.h"
#if !defined(_WIN32)
# include <sys/file.h>
@@ -67,36 +102,24 @@
namespace mongo {
- namespace dur {
- extern unsigned long long DataLimitPerJournalFile;
- }
+ void (*snmpInit)() = NULL;
/* only off if --nohints */
extern bool useHints;
extern int diagLogging;
- extern unsigned lenForNewNsFiles;
extern int lockFile;
- extern string repairpath;
- static void setupSignalHandlers();
- void startReplication();
- static void startSignalProcessingThread();
void exitCleanly( ExitCode code );
#ifdef _WIN32
ntservice::NtServiceDefaultStrings defaultServiceStrings = {
L"MongoDB",
- L"Mongo DB",
- L"Mongo DB Server"
+ L"MongoDB",
+ L"MongoDB Server"
};
#endif
- CmdLine cmdLine;
- static bool scriptingEnabled = true;
- static bool noHttpInterface = false;
- bool shouldRepairDatabases = 0;
- static bool forceRepair = 0;
Timer startupSrandTimer;
const char *ourgetns() {
@@ -156,19 +179,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() );
@@ -232,7 +242,6 @@ namespace mongo {
virtual void disconnected( AbstractMessagingPort* p ) {
Client * c = currentClient.get();
if( c ) c->shutdown();
- globalScriptEngine->threadDone();
}
};
@@ -245,12 +254,10 @@ namespace mongo {
toLog.append( "hostname", getHostNameCached() );
toLog.appendTimeT( "startTime", time(0) );
- char buf[64];
- curTimeString( buf );
- toLog.append( "startTimeLocal", buf );
+ toLog.append( "startTimeLocal", dateToCtimeString(curTimeMillis64()) );
- toLog.append( "cmdLine", CmdLine::getParsedOpts() );
- toLog.append( "pid", getpid() );
+ toLog.append("cmdLine", serverGlobalParams.parsedOpts);
+ toLog.append( "pid", ProcessId::getCurrent().asLongLong() );
BSONObjBuilder buildinfo( toLog.subobjStart("buildinfo"));
@@ -260,7 +267,6 @@ namespace mongo {
BSONObj o = toLog.obj();
Lock::GlobalWrite lk;
- Client::GodScope gs;
DBDirectClient c;
const char* name = "local.startup_log";
c.createCollection( name, 10 * 1024 * 1024, true );
@@ -271,15 +277,32 @@ 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();
+ // We must setupSockets for both the main server and the web server (if enabled) prior to
+ // calling logStartup() in order to avoid getting too high of a file descriptor for our
+ // calls to select (see SERVER-17653).
+ server->setupSockets();
+
+ boost::shared_ptr<DbWebServer> dbWebServer;
+ if (serverGlobalParams.isHttpInterfaceEnabled) {
+ dbWebServer.reset(new DbWebServer(serverGlobalParams.bind_ip,
+ serverGlobalParams.port + 1000,
+ new RestAdminAccess()));
+ dbWebServer->setupSockets();
+ }
+
logStartup();
startReplication();
- if ( !noHttpInterface )
- boost::thread web( boost::bind(&webServerThread, new RestAdminAccess() /* takes ownership */));
+
+ if (serverGlobalParams.isHttpInterfaceEnabled) {
+ invariant(dbWebServer);
+ boost::thread web(boost::bind(&webServerListenThread, dbWebServer));
+ web.detach();
+ }
#if(TESTEXHAUST)
boost::thread thr(testExhaust);
@@ -288,7 +311,7 @@ namespace mongo {
}
- bool doDBUpgrade( const string& dbName , string errmsg , DataFileHeader * h ) {
+ void doDBUpgrade( const string& dbName, DataFileHeader* h ) {
static DBDirectClient db;
if ( h->version == 4 && h->versionMinor == 4 ) {
@@ -302,24 +325,56 @@ namespace mongo {
BSONObj out;
bool ok = db.runCommand( dbName , BSON( "reIndex" << c.substr( dbName.size() + 1 ) ) , out );
if ( ! ok ) {
- errmsg = "reindex failed";
- log() << "\t\t reindex failed: " << out << endl;
- return false;
+ log() << "\t\t reindex failed: " << out;
+ fassertFailed( 17393 );
}
}
getDur().writingInt(h->versionMinor) = 5;
- return true;
+ return;
}
// do this in the general case
- return repairDatabase( dbName.c_str(), errmsg );
+ fassert( 17401, repairDatabase( dbName ) );
+ }
+
+ void checkForIdIndexes( Database* db ) {
+
+ if ( db->name() == "local") {
+ // we do not need an _id index on anything in the local database
+ return;
+ }
+
+ list<string> collections;
+ db->namespaceIndex().getNamespaces( collections );
+
+ // for each collection, ensure there is a $_id_ index
+ for (list<string>::iterator i = collections.begin(); i != collections.end(); ++i) {
+ const string& collectionName = *i;
+ NamespaceString ns( collectionName );
+ if ( ns.isSystem() )
+ continue;
+
+ Collection* coll = db->getCollection( collectionName );
+ if ( !coll )
+ continue;
+
+ if ( coll->getIndexCatalog()->findIdIndex() )
+ continue;
+
+ log() << "WARNING: the collection '" << *i
+ << "' lacks a unique index on _id."
+ << " This index is needed for replication to function properly"
+ << startupWarningsLog;
+ log() << "\t To fix this, you need to create a unique index on _id."
+ << " See http://dochub.mongodb.org/core/build-replica-set-indexes"
+ << startupWarningsLog;
+ }
}
// ran at startup.
- static void repairDatabasesAndCheckVersion() {
+ static void repairDatabasesAndCheckVersion(bool shouldClearNonLocalTmpCollections) {
// LastError * le = lastError.get( true );
- Client::GodScope gs;
LOG(1) << "enter repairDatabases (to check pdfile version #)" << endl;
Lock::GlobalWrite lk;
@@ -328,10 +383,20 @@ namespace mongo {
for ( vector< string >::iterator i = dbNames.begin(); i != dbNames.end(); ++i ) {
string dbName = *i;
LOG(1) << "\t" << dbName << endl;
+
Client::Context ctx( dbName );
- MongoDataFile *p = cc().database()->getFile( 0 );
+ DataFile *p = ctx.db()->getExtentManager().getFile( 0 );
DataFileHeader *h = p->getHeader();
- if ( !h->isCurrentVersion() || forceRepair ) {
+
+ if ( replSettings.usingReplSets() ) {
+ // we only care about the _id index if we are in a replset
+ checkForIdIndexes(ctx.db());
+ }
+
+ if (shouldClearNonLocalTmpCollections || dbName == "local")
+ ctx.db()->clearTmpCollections();
+
+ if (!h->isCurrentVersion() || mongodGlobalParams.repair) {
if( h->version <= 0 ) {
uasserted(14026,
@@ -339,37 +404,40 @@ namespace mongo {
<< " info: " << h->versionMinor << ' ' << h->fileLength);
}
- log() << "****" << endl;
- log() << "****" << endl;
- log() << "need to upgrade database " << dbName << " "
- << "with pdfile version " << h->version << "." << h->versionMinor << ", "
- << "new version: "
- << PDFILE_VERSION << "." << PDFILE_VERSION_MINOR_22_AND_OLDER
- << endl;
- if ( shouldRepairDatabases ) {
+ if ( !h->isCurrentVersion() ) {
+ log() << "****" << endl;
+ log() << "****" << endl;
+ log() << "need to upgrade database " << dbName << " "
+ << "with pdfile version " << h->version << "." << h->versionMinor << ", "
+ << "new version: "
+ << PDFILE_VERSION << "." << PDFILE_VERSION_MINOR_22_AND_OLDER
+ << endl;
+ }
+
+ if (mongodGlobalParams.upgrade) {
// QUESTION: Repair even if file format is higher version than code?
- log() << "\t starting upgrade" << endl;
- string errmsg;
- verify( doDBUpgrade( dbName , errmsg , h ) );
+ doDBUpgrade( dbName, h );
}
else {
log() << "\t Not upgrading, exiting" << endl;
log() << "\t run --upgrade to upgrade dbs, then start again" << endl;
log() << "****" << endl;
dbexit( EXIT_NEED_UPGRADE );
- shouldRepairDatabases = 1;
+ mongodGlobalParams.upgrade = 1;
return;
}
}
else {
- if (h->versionMinor == PDFILE_VERSION_MINOR_22_AND_OLDER) {
- const string systemIndexes = cc().database()->name + ".system.indexes";
- shared_ptr<Cursor> cursor(theDataFileMgr.findAll(systemIndexes));
- for ( ; cursor && cursor->ok(); cursor->advance()) {
- const BSONObj index = cursor->current();
- const BSONObj key = index.getObjectField("key");
- const string plugin = IndexPlugin::findPluginName(key);
- if (IndexPlugin::existedBefore24(plugin))
+ const string systemIndexes = cc().database()->name() + ".system.indexes";
+ auto_ptr<Runner> runner(InternalPlanner::collectionScan(systemIndexes));
+ BSONObj index;
+ Runner::RunnerState state;
+ while (Runner::RUNNER_ADVANCED == (state = runner->getNext(&index, NULL))) {
+ const BSONObj key = index.getObjectField("key");
+ const string plugin = IndexNames::findPluginName(key);
+
+ if (!h->is24IndexClean()) {
+ if (IndexNames::existedBefore24(plugin))
continue;
log() << "Index " << index << " claims to be of type '" << plugin << "', "
@@ -378,14 +446,32 @@ namespace mongo {
<< "http://dochub.mongodb.org/core/upgrade-2.4"
<< startupWarningsLog;
}
+
+ const Status keyStatus = validateKeyPattern(key);
+ if (!keyStatus.isOK()) {
+ log() << "Problem with index " << index << ": " << keyStatus.reason()
+ << " This index can still be used however it cannot be rebuilt."
+ << " For more info see"
+ << " http://dochub.mongodb.org/core/index-validation"
+ << startupWarningsLog;
+ }
+ }
+
+ if (Runner::RUNNER_EOF != state) {
+ warning() << "Internal error while reading collection " << systemIndexes;
}
- Database::closeDatabase( dbName.c_str(), dbpath );
+
+ // 2.4 does not properly drop indexes on collections named "system". Check for
+ // orphaned indexes and clean up any if found.
+ ctx.db()->cleanUpOrphanIndexesOnSystemCollection();
+
+ 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 );
@@ -393,7 +479,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();
@@ -412,8 +498,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() ) {
- Client::GodScope gs;
+ if (!replSettings.usingReplSets()) {
DBDirectClient c;
return c.count("local.system.replset");
}
@@ -438,22 +523,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
@@ -466,7 +554,7 @@ namespace mongo {
_flushed(time_flushing);
- if( logLevel >= 1 || time_flushing >= 10000 ) {
+ if( logger::globalLogDomain()->shouldLog(logger::LogSeverity::Debug(1)) || time_flushing >= 10000 ) {
log() << "flushing mmaps took " << time_flushing << "ms " << " for " << numFiles << " files" << endl;
}
}
@@ -507,7 +595,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 );
}
@@ -529,39 +617,47 @@ namespace mongo {
/// warn if readahead > 256KB (gridfs chunk size)
static void checkReadAhead(const string& dir) {
#ifdef __linux__
- const dev_t dev = getPartition(dir);
-
- // This path handles the case where the filesystem uses the whole device (including LVM)
- string path = str::stream() <<
- "/sys/dev/block/" << major(dev) << ':' << minor(dev) << "/queue/read_ahead_kb";
-
- if (!boost::filesystem::exists(path)){
- // This path handles the case where the filesystem is on a partition.
- path = str::stream()
- << "/sys/dev/block/" << major(dev) << ':' << minor(dev) // this is a symlink
- << "/.." // parent directory of a partition is for the whole device
- << "/queue/read_ahead_kb";
- }
+ try {
+ const dev_t dev = getPartition(dir);
+
+ // This path handles the case where the filesystem uses the whole device (including LVM)
+ string path = str::stream() <<
+ "/sys/dev/block/" << major(dev) << ':' << minor(dev) << "/queue/read_ahead_kb";
+
+ if (!boost::filesystem::exists(path)){
+ // This path handles the case where the filesystem is on a partition.
+ path = str::stream()
+ << "/sys/dev/block/" << major(dev) << ':' << minor(dev) // this is a symlink
+ << "/.." // parent directory of a partition is for the whole device
+ << "/queue/read_ahead_kb";
+ }
- if (boost::filesystem::exists(path)) {
- ifstream file (path.c_str());
- if (file.is_open()) {
- int kb;
- file >> kb;
- if (kb > 256) {
- log() << startupWarningsLog;
+ if (boost::filesystem::exists(path)) {
+ ifstream file (path.c_str());
+ if (file.is_open()) {
+ int kb;
+ file >> kb;
+ if (kb > 256) {
+ log() << startupWarningsLog;
- log() << "** WARNING: Readahead for " << dir << " is set to " << kb << "KB"
- << startupWarningsLog;
+ log() << "** WARNING: Readahead for " << dir << " is set to " << kb << "KB"
+ << startupWarningsLog;
- log() << "** We suggest setting it to 256KB (512 sectors) or less"
- << startupWarningsLog;
+ log() << "** We suggest setting it to 256KB (512 sectors) or less"
+ << startupWarningsLog;
- log() << "** http://dochub.mongodb.org/core/readahead"
- << startupWarningsLog;
+ log() << "** http://dochub.mongodb.org/core/readahead"
+ << startupWarningsLog;
+ }
}
}
}
+ catch (const std::exception& e) {
+ log() << "unable to validate readahead settings due to error: " << e.what()
+ << startupWarningsLog;
+ log() << "for more information, see http://dochub.mongodb.org/core/readahead"
+ << startupWarningsLog;
+ }
#endif // __linux__
}
@@ -569,59 +665,64 @@ namespace mongo {
Client::initThread("initandlisten");
- Logstream::get().addGlobalTee( new RamLog("global") );
-
bool is32bit = sizeof(int*) == 4;
{
-#if !defined(_WIN32)
- pid_t pid = getpid();
-#else
- DWORD pid=GetCurrentProcessId();
-#endif
- Nullstream& l = log();
- l << "MongoDB starting : pid=" << pid << " port=" << cmdLine.port << " dbpath=" << dbpath;
+ ProcessId pid = ProcessId::getCurrent();
+ LogstreamBuilder l = log();
+ 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();
- log() << mongodVersion() << endl;
- printGitVersion();
- printSysInfo();
- printAllocator();
- printCommandLineOpts();
-
+ logStartupWarnings();
+#if defined(_WIN32)
+ printTargetMinOS();
+#endif
+ logProcessDetails();
{
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));
}
+ // Read storage engine metadata file (introduced in 2.8) if present.
+ // Do not start server if storage engine in metadata is not 'mmapv1'.
+ StorageEngineMetadata::validate(storageGlobalParams.dbpath, "mmapv1");
+
// 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();
+ // TODO: This should go into a MONGO_INITIALIZER once we have figured out the correct
+ // dependencies.
+ if (snmpInit) {
+ snmpInit();
+ }
+
MONGO_ASSERT_ON_EXCEPTION_WITH_MSG( clearTmpFiles(), "clear tmp files" );
dur::startup();
- if( cmdLine.durOptions & CmdLine::DurRecoverOnly )
+ if (storageGlobalParams.durOptions & StorageGlobalParams::DurRecoverOnly)
return;
unsigned long long missingRepl = checkIfReplMissingFromCommandLine();
@@ -636,25 +737,35 @@ namespace mongo {
log() << startupWarningsLog;
}
- Module::initAll();
-
- if ( scriptingEnabled ) {
+ if (mongodGlobalParams.scriptingEnabled) {
ScriptEngine::setup();
globalScriptEngine->setCheckInterruptCallback( jsInterruptCallback );
globalScriptEngine->setGetCurrentOpIdCallback( jsGetCurrentOpIdCallback );
}
- repairDatabasesAndCheckVersion();
+ // On replica set members we only clear temp collections on DBs other than "local" during
+ // promotion to primary. On pure slaves, they are only cleared when the oplog tells them to.
+ // The local DB is special because it is not replicated. See SERVER-10927 for more details.
+ const bool shouldClearNonLocalTmpCollections = !(missingRepl
+ || replSettings.usingReplSets()
+ || replSettings.slave == SimpleSlave);
+ repairDatabasesAndCheckVersion(shouldClearNonLocalTmpCollections);
- if ( shouldRepairDatabases )
+ if (mongodGlobalParams.upgrade)
return;
+ uassertStatusOK(getGlobalAuthorizationManager()->initialize());
+
/* this is for security on certain platforms (nonce generation) */
srand((unsigned) (curTimeMicros() ^ startupSrandTimer.micros()));
- snapshotThread.go();
+ // The snapshot thread provides historical collection level and lock statistics for use
+ // by the web interface. Only needed when HTTP is enabled.
+ if (serverGlobalParams.isHttpInterfaceEnabled)
+ snapshotThread.go();
+
d.clientCursorMonitor.go();
- PeriodicTask::theRunner->go();
+ PeriodicTask::startRunningPeriodicTasks();
if (missingRepl) {
// a warning was logged earlier
}
@@ -663,23 +774,28 @@ namespace mongo {
}
#ifndef _WIN32
- CmdLine::launchOk();
+ mongo::signalForkSuccess();
#endif
- if( !noauth ) {
+ if(getGlobalAuthorizationManager()->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);
}
+ authindex::configureSystemIndexes("admin");
+
+ getDeleter()->startWorkers();
+
+ // Starts a background thread that rebuilds all incomplete indices.
+ indexRebuilder.go();
+
listen(listenPort);
// listen() will return when exit code closes its socket.
exitCleanly(EXIT_NET_ERROR);
}
- void testPretouch();
-
void initAndListen(int listenPort) {
try {
_initAndListen(listenPort);
@@ -706,7 +822,7 @@ namespace mongo {
void initService() {
ntservice::reportStatus( SERVICE_RUNNING );
log() << "Service running" << endl;
- initAndListen( cmdLine.port );
+ initAndListen(serverGlobalParams.port);
}
#endif
@@ -714,547 +830,172 @@ namespace mongo {
using namespace mongo;
-#include <boost/program_options.hpp>
-
-namespace po = boost::program_options;
-
-void show_help_text(po::options_description options) {
- cout << options << endl;
-};
-
static int mongoDbMain(int argc, char* argv[], char** envp);
+#if defined(_WIN32)
+// In Windows, wmain() is an alternate entry point for main(), and receives the same parameters
+// as main() but encoded in Windows Unicode (UTF-16); "wide" 16-bit wchar_t characters. The
+// WindowsCommandLine object converts these wide character strings to a UTF-8 coded equivalent
+// and makes them available through the argv() and envp() members. This enables mongoDbMain()
+// to process UTF-8 encoded arguments and environment variables without regard to platform.
+int wmain(int argc, wchar_t* argvW[], wchar_t* envpW[]) {
+ WindowsCommandLine wcl(argc, argvW, envpW);
+ int exitCode = mongoDbMain(argc, wcl.argv(), wcl.envp());
+ ::_exit(exitCode);
+}
+#else
int main(int argc, char* argv[], char** envp) {
int exitCode = mongoDbMain(argc, argv, envp);
::_exit(exitCode);
}
-
-static void buildOptionsDescriptions(po::options_description *pVisible,
- po::options_description *pHidden,
- po::positional_options_description *pPositional) {
-
- po::options_description& visible_options = *pVisible;
- po::options_description& hidden_options = *pHidden;
- po::positional_options_description& positional_options = *pPositional;
-
- po::options_description general_options("General options");
-#if defined(_WIN32)
- po::options_description windows_scm_options("Windows Service Control Manager options");
#endif
- po::options_description ms_options("Master/slave options (old; use replica sets instead)");
- po::options_description rs_options("Replica set options");
- po::options_description replication_options("Replication options");
- po::options_description sharding_options("Sharding options");
- po::options_description hidden_sharding_options("Sharding options");
- po::options_description ssl_options("SSL options");
-
- CmdLine::addGlobalOptions( general_options , hidden_options , ssl_options );
-
- StringBuilder dbpathBuilder;
- dbpathBuilder << "directory for datafiles - defaults to " << dbpath;
-
- general_options.add_options()
- ("auth", "run with security")
- ("cpu", "periodically show cpu and iowait utilization")
- ("dbpath", po::value<string>() , dbpathBuilder.str().c_str())
- ("diaglog", po::value<int>(), "0=off 1=W 2=R 3=both 7=W+some reads")
- ("directoryperdb", "each database will be stored in a separate directory")
- ("ipv6", "enable IPv6 support (disabled by default)")
- ("journal", "enable journaling")
- ("journalCommitInterval", po::value<unsigned>(), "how often to group/batch commit (ms)")
- ("journalOptions", po::value<int>(), "journal diagnostic options")
- ("jsonp","allow JSONP access via http (has security implications)")
- ("noauth", "run without security")
- ("nohttpinterface", "disable http interface")
- // SERVER-8536
- // ("noIndexBuildRetry", "don't retry any index builds that were interrupted by shutdown")
- ("nojournal", "disable journaling (journaling is on by default for 64 bit)")
- ("noprealloc", "disable data file preallocation - will often hurt performance")
- ("noscripting", "disable scripting engine")
- ("notablescan", "do not allow table scans")
- ("nssize", po::value<int>()->default_value(16), ".ns file size (in MB) for new databases")
- ("profile",po::value<int>(), "0=off 1=slow, 2=all")
- ("quota", "limits each database to a certain number of files (8 default)")
- ("quotaFiles", po::value<int>(), "number of files allowed per db, requires --quota")
- ("repair", "run repair on all dbs")
- ("repairpath", po::value<string>() , "root directory for repair files - defaults to dbpath" )
- ("rest","turn on simple rest api")
-#if defined(__linux__)
- ("shutdown", "kill a running server (for init scripts)")
-#endif
- ("slowms",po::value<int>(&cmdLine.slowMS)->default_value(100), "value of slow for profile and console log" )
- ("smallfiles", "use a smaller default file size")
- ("syncdelay",po::value<double>(&cmdLine.syncdelay)->default_value(60), "seconds between disk syncs (0=never, but not recommended)")
- ("sysinfo", "print some diagnostic system information")
- ("upgrade", "upgrade db if needed")
- ;
-#if defined(_WIN32)
- CmdLine::addWindowsOptions( windows_scm_options, hidden_options );
-#endif
-
- replication_options.add_options()
- ("oplogSize", po::value<int>(), "size to use (in MB) for replication op log. default is 5% of disk space (i.e. large is good)")
- ;
-
- ms_options.add_options()
- ("master", "master mode")
- ("slave", "slave mode")
- ("source", po::value<string>(), "when slave: specify master as <server:port>")
- ("only", po::value<string>(), "when slave: specify a single database to replicate")
- ("slavedelay", po::value<int>(), "specify delay (in seconds) to be used when applying master ops to slave")
- ("autoresync", "automatically resync if slave data is stale")
- ;
-
- rs_options.add_options()
- ("replSet", po::value<string>(), "arg is <setname>[/<optionalseedhostlist>]")
- ("replIndexPrefetch", po::value<string>(), "specify index prefetching behavior (if secondary) [none|_id_only|all]")
- ;
-
- sharding_options.add_options()
- ("configsvr", "declare this is a config db of a cluster; default port 27019; default dir /data/configdb")
- ("shardsvr", "declare this is a shard db of a cluster; default port 27018")
- ;
-
- hidden_sharding_options.add_options()
- ("noMoveParanoia" , "turn off paranoid saving of data for the moveChunk command; default" )
- ("moveParanoia" , "turn on paranoid saving of data during the moveChunk command (used for internal system diagnostics)" )
- ;
- hidden_options.add(hidden_sharding_options);
-
- hidden_options.add_options()
- ("fastsync", "indicate that this instance is starting from a dbpath snapshot of the repl peer")
- ("pretouch", po::value<int>(), "n pretouch threads for applying replicationed operations") // experimental
- ("command", po::value< vector<string> >(), "command")
- ("cacheSize", po::value<long>(), "cache size (in MB) for rec store")
- ("nodur", "disable journaling")
- // things we don't want people to use
- ("nohints", "ignore query hints")
- ("nopreallocj", "don't preallocate journal files")
- ("dur", "enable journaling") // old name for --journal
- ("durOptions", po::value<int>(), "durability diagnostic options") // deprecated name
- // deprecated pairing command line options
- ("pairwith", "DEPRECATED")
- ("arbiter", "DEPRECATED")
- ("opIdMem", "DEPRECATED")
- ;
-
- positional_options.add("command", 3);
- visible_options.add(general_options);
-#if defined(_WIN32)
- visible_options.add(windows_scm_options);
-#endif
- visible_options.add(replication_options);
- visible_options.add(ms_options);
- visible_options.add(rs_options);
- visible_options.add(sharding_options);
-#ifdef MONGO_SSL
- visible_options.add(ssl_options);
-#endif
- Module::addOptions( visible_options );
+MONGO_INITIALIZER_GENERAL(ForkServer,
+ ("EndStartupOptionHandling"),
+ ("default"))(InitializerContext* context) {
+ mongo::forkServerOrDie();
+ return Status::OK();
}
-static void processCommandLineOptions(const std::vector<std::string>& argv) {
- po::options_description visible_options("Allowed options");
- po::options_description hidden_options("Hidden options");
- po::positional_options_description positional_options;
- buildOptionsDescriptions(&visible_options, &hidden_options, &positional_options);
-
- {
- po::variables_map params;
-
- if (!CmdLine::store(argv,
- visible_options,
- hidden_options,
- positional_options,
- params)) {
- ::_exit(EXIT_FAILURE);
- }
-
- if (params.count("help")) {
- show_help_text(visible_options);
- ::_exit(EXIT_SUCCESS);
- }
- if (params.count("version")) {
- cout << mongodVersion() << endl;
- printGitVersion();
- ::_exit(EXIT_SUCCESS);
- }
- if (params.count("sysinfo")) {
- sysRuntimeInfo();
+/*
+ * 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>& 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 (moe::startupOptionsParsed.count("command")) {
+ vector<string> command = moe::startupOptionsParsed["command"].as< vector<string> >();
+
+ if (command[0].compare("dbpath") == 0) {
+ cout << storageGlobalParams.dbpath << endl;
::_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);
+ if (command[0].compare("run") != 0) {
+ cout << "Invalid command: " << command[0] << endl;
+ printMongodHelp(moe::startupOptions);
+ ::_exit(EXIT_FAILURE);
}
-#endif
- if ( params.count("directoryperdb")) {
- directoryperdb = true;
- }
- if (params.count("cpu")) {
- cmdLine.cpu = true;
- }
- if (params.count("noauth")) {
- noauth = true;
- }
- if (params.count("auth")) {
- noauth = false;
- }
- 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) {
- log() << "Can't specify both --journal and --nojournal options." << 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 ) {
- out() << "--journalCommitInterval out of allowed range (0-300ms)" << endl;
- dbexit( EXIT_BADOPTIONS );
- }
- }
- if (params.count("journalOptions")) {
- cmdLine.durOptions = params["journalOptions"].as<int>();
+ if (command.size() > 1) {
+ cout << "Too many parameters to 'run' command" << endl;
+ printMongodHelp(moe::startupOptions);
+ ::_exit(EXIT_FAILURE);
}
- if (params.count("repairpath")) {
- repairpath = params["repairpath"].as<string>();
- if (!repairpath.size()) {
- out() << "repairpath is empty" << endl;
- dbexit( EXIT_BADOPTIONS );
- }
+ }
- if (cmdLine.dur && !str::startsWith(repairpath, dbpath)) {
- out() << "You must use a --repairpath that is a subdirectory of --dbpath when using journaling" << endl;
- dbexit( EXIT_BADOPTIONS );
- }
- }
- if (params.count("nohints")) {
- useHints = false;
- }
- if (params.count("nopreallocj")) {
- cmdLine.preallocj = false;
- }
- if (params.count("nohttpinterface")) {
- noHttpInterface = true;
- }
- if (params.count("rest")) {
- cmdLine.rest = true;
- }
- if (params.count("jsonp")) {
- 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 ) {
- out() << "can't interpret --diaglog setting" << endl;
- dbexit( EXIT_BADOPTIONS );
- }
- _diaglog.setLevel(x);
- }
- if (params.count("repair")) {
- if (journalExplicit && cmdLine.dur) {
- log() << "Can't specify both --journal and --repair options." << endl;
- ::_exit(EXIT_BADOPTIONS);
- }
+#ifdef _WIN32
+ ntservice::configureService(initService,
+ moe::startupOptionsParsed,
+ defaultServiceStrings,
+ std::vector<std::string>(),
+ args);
+#endif // _WIN32
- 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") ) {
- out() << "--autoresync is not used with --replSet" << endl;
- out() << "see http://dochub.mongodb.org/core/resyncingaverystalereplicasetmember" << endl;
- dbexit( 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")) {
- out() << "--slavedelay cannot be used with --replSet" << endl;
- dbexit( EXIT_BADOPTIONS );
- }
- else if (params.count("only")) {
- out() << "--only cannot be used with --replSet" << endl;
- dbexit( 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)) {
- out() << "bad --nssize arg" << endl;
- dbexit( EXIT_BADOPTIONS );
- }
- lenForNewNsFiles = x * 1024 * 1024;
- verify(lenForNewNsFiles > 0);
- }
- if (params.count("oplogSize")) {
- long long x = params["oplogSize"].as<int>();
- if (x <= 0) {
- out() << "bad --oplogSize arg" << endl;
- dbexit( EXIT_BADOPTIONS );
- }
- // note a small size such as x==1 is ok for an arbiter.
- if( x > 1000 && sizeof(void*) == 4 ) {
- out() << "--oplogSize of " << x << "MB is too big for 32 bit version. Use 64 bit build instead." << endl;
- dbexit( EXIT_BADOPTIONS );
- }
- cmdLine.oplogSize = x * 1024 * 1024;
- verify(cmdLine.oplogSize > 0);
- }
- if (params.count("cacheSize")) {
- long x = params["cacheSize"].as<long>();
- if (x <= 0) {
- out() << "bad --cacheSize arg" << endl;
- dbexit( EXIT_BADOPTIONS );
- }
- log() << "--cacheSize option not currently supported" << endl;
- }
- if (params.count("port") == 0 ) {
- if( params.count("configsvr") ) {
- cmdLine.port = CmdLine::ConfigServerPort;
- }
- if( params.count("shardsvr") ) {
- if( params.count("configsvr") ) {
- log() << "can't do --shardsvr and --configsvr at the same time" << endl;
- dbexit( EXIT_BADOPTIONS );
- }
- cmdLine.port = CmdLine::ShardServerPort;
- }
- }
- else {
- if ( cmdLine.port <= 0 || cmdLine.port > 65535 ) {
- out() << "bad --port number" << endl;
- dbexit( EXIT_BADOPTIONS );
+#ifdef __linux__
+ if (moe::startupOptionsParsed.count("shutdown")){
+ bool failed = false;
+
+ string name = (boost::filesystem::path(storageGlobalParams.dbpath) / "mongod.lock").string();
+ if ( !boost::filesystem::exists( name ) || boost::filesystem::file_size( name ) == 0 )
+ failed = true;
+
+ pid_t pid;
+ string procPath;
+ if (!failed){
+ try {
+ ifstream f (name.c_str());
+ f >> pid;
+ procPath = (str::stream() << "/proc/" << pid);
+ if (!boost::filesystem::exists(procPath))
+ failed = true;
}
- }
- if ( 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) {
- log() << "replication should not be enabled on a config server" << endl;
- ::_exit(-1);
+ catch (const std::exception& e){
+ cerr << "Error reading pid from lock file [" << name << "]: " << e.what() << endl;
+ failed = true;
}
- if ( params.count( "nodur" ) == 0 && params.count( "nojournal" ) == 0 )
- cmdLine.dur = true;
- if ( params.count( "dbpath" ) == 0 )
- dbpath = "/data/configdb";
- replSettings.master = true;
- if ( params.count( "oplogSize" ) == 0 )
- cmdLine.oplogSize = 5 * 1024 * 1024;
}
- if ( params.count( "profile" ) ) {
- cmdLine.defaultProfile = params["profile"].as<int>();
- }
- if (params.count("ipv6")) {
- enableIPv6();
- }
-
- if (params.count("noMoveParanoia") > 0 && params.count("moveParanoia") > 0) {
- out() << "The moveParanoia and noMoveParanoia flags cannot both be set; please use only one of them." << endl;
- ::_exit( EXIT_BADOPTIONS );
- }
-
- if (params.count("noMoveParanoia"))
- cmdLine.moveParanoia = false;
- if (params.count("moveParanoia"))
- cmdLine.moveParanoia = true;
-
- if (params.count("pairwith") || params.count("arbiter") || params.count("opIdMem")) {
- out() << "****" << endl;
- out() << "Replica Pairs have been deprecated. Invalid options: --pairwith, --arbiter, and/or --opIdMem" << endl;
- out() << "<http://dochub.mongodb.org/core/replicapairs>" << endl;
- out() << "****" << endl;
- dbexit( EXIT_BADOPTIONS );
+ if (failed) {
+ std::cerr << "There doesn't seem to be a server running with dbpath: "
+ << storageGlobalParams.dbpath << std::endl;
+ ::_exit(EXIT_FAILURE);
}
- // needs to be after things like --configsvr parsing, thus here.
- if( repairpath.empty() )
- repairpath = dbpath;
-
- // The "command" option is deprecated. For backward compatibility, still support the "run"
- // and "dbppath" command. The "run" command is the same as just running mongod, so just
- // falls through.
- if (params.count("command")) {
- vector<string> command = params["command"].as< vector<string> >();
-
- if (command[0].compare("dbpath") == 0) {
- cout << dbpath << endl;
- ::_exit(EXIT_SUCCESS);
- }
-
- if (command[0].compare("run") != 0) {
- cout << "Invalid command: " << command[0] << endl;
- cout << visible_options << endl;
- ::_exit(EXIT_FAILURE);
- }
-
- if (command.size() > 1) {
- cout << "Too many parameters to 'run' command" << endl;
- cout << visible_options << endl;
- ::_exit(EXIT_FAILURE);
- }
+ cout << "killing process with pid: " << pid << endl;
+ int ret = kill(pid, SIGTERM);
+ if (ret) {
+ int e = errno;
+ cerr << "failed to kill process: " << errnoWithDescription(e) << endl;
+ ::_exit(EXIT_FAILURE);
}
- if( 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;
+ while (boost::filesystem::exists(procPath)) {
+ sleepsecs(1);
}
- Module::configAll(params);
-
-#ifdef _WIN32
- ntservice::configureService(initService,
- params,
- defaultServiceStrings,
- std::vector<std::string>(),
- argv);
-#endif // _WIN32
-
-#ifdef __linux__
- if (params.count("shutdown")){
- bool failed = false;
-
- string name = ( boost::filesystem::path( dbpath ) / "mongod.lock" ).string();
- if ( !boost::filesystem::exists( name ) || boost::filesystem::file_size( name ) == 0 )
- failed = true;
-
- pid_t pid;
- string procPath;
- if (!failed){
- try {
- ifstream f (name.c_str());
- f >> pid;
- procPath = (str::stream() << "/proc/" << pid);
- if (!boost::filesystem::exists(procPath))
- failed = true;
- }
- catch (const std::exception& e){
- cerr << "Error reading pid from lock file [" << name << "]: " << e.what() << endl;
- failed = true;
- }
- }
-
- if (failed) {
- cerr << "There doesn't seem to be a server running with dbpath: " << dbpath << endl;
- ::_exit(EXIT_FAILURE);
- }
+ ::_exit(EXIT_SUCCESS);
+ }
+#endif
+}
- cout << "killing process with pid: " << pid << endl;
- int ret = kill(pid, SIGTERM);
- if (ret) {
- int e = errno;
- cerr << "failed to kill process: " << errnoWithDescription(e) << endl;
- ::_exit(EXIT_FAILURE);
- }
+MONGO_INITIALIZER_GENERAL(CreateAuthorizationManager,
+ ("SetupInternalSecurityUser"),
+ MONGO_NO_DEPENDENTS)
+ (InitializerContext* context) {
+ AuthorizationManager* authzManager =
+ new AuthorizationManager(new AuthzManagerExternalStateMongod());
+ setGlobalAuthorizationManager(authzManager);
+ return Status::OK();
+}
- while (boost::filesystem::exists(procPath)) {
- sleepsecs(1);
- }
+#ifdef MONGO_SSL
+MONGO_INITIALIZER_GENERAL(setSSLManagerType,
+ MONGO_NO_PREREQUISITES,
+ ("SSLManager"))(InitializerContext* context) {
+ isSSLServer = true;
+ return Status::OK();
+}
+#endif
- ::_exit(EXIT_SUCCESS);
+#if defined(_WIN32)
+namespace mongo {
+ // the hook for mongoAbort
+ extern void (*reportEventToSystem)(const char *msg);
+ static void reportEventToSystemImpl(const char *msg) {
+ static ::HANDLE hEventLog = RegisterEventSource( NULL, TEXT("mongod") );
+ if( hEventLog ) {
+ std::wstring s = toNativeString(msg);
+ LPCTSTR txt = s.c_str();
+ BOOL ok = ReportEvent(
+ hEventLog, EVENTLOG_ERROR_TYPE,
+ 0, 0, NULL,
+ 1,
+ 0,
+ &txt,
+ 0);
+ wassert(ok);
}
-#endif
}
-}
+} // namespace mongo
+#endif // if defined(_WIN32)
static int mongoDbMain(int argc, char* argv[], char **envp) {
static StaticObserver staticObserver;
+#if defined(_WIN32)
+ mongo::reportEventToSystem = &mongo::reportEventToSystemImpl;
+#endif
+
getcurns = ourgetns;
setupSignalHandlers();
+ // Mongod shouldn't lazily kill cursors. It doesn't mix well with connection pooling.
+ DBClientConnection::setLazyKillCursor(false);
+
dbExecCommand = argv[0];
srand(curTimeMicros());
@@ -1271,10 +1012,14 @@ static int mongoDbMain(int argc, char* argv[], char **envp) {
if( argc == 1 )
cout << dbExecCommand << " --help for help and startup options" << endl;
+ Status status = mongo::runGlobalInitializers(argc, argv, envp);
+ if (!status.isOK()) {
+ severe() << "Failed global initialization: " << status;
+ ::_exit(EXIT_FAILURE);
+ }
- processCommandLineOptions(std::vector<std::string>(argv, argv + argc));
- mongo::runGlobalInitializersOrDie(argc, argv, envp);
- CmdLine::censor(argc, argv);
+ startupConfigActions(std::vector<std::string>(argv, argv + argc));
+ cmdline_utils::censorArgvArray(argc, argv);
if (!initializeServerGlobalState())
::_exit(EXIT_FAILURE);
@@ -1293,213 +1038,7 @@ static int mongoDbMain(int argc, char* argv[], char **envp) {
#endif
StartupTest::runTests();
- initAndListen(cmdLine.port);
+ initAndListen(serverGlobalParams.port);
dbexit(EXIT_CLEAN);
return 0;
}
-
-namespace mongo {
-
- string getDbContext();
-
-#undef out
-
-
-#if !defined(_WIN32)
-
-} // namespace mongo
-
-#include <signal.h>
-#include <string.h>
-
-namespace mongo {
-
- void abruptQuit(int x) {
- ostringstream ossSig;
- ossSig << "Got signal: " << x << " (" << strsignal( x ) << ")." << endl;
- rawOut( ossSig.str() );
-
- /*
- ostringstream ossOp;
- ossOp << "Last op: " << currentOp.infoNoauth() << endl;
- rawOut( ossOp.str() );
- */
-
- ostringstream oss;
- oss << "Backtrace:" << endl;
- printStackTrace( oss );
- rawOut( oss.str() );
-
- // Don't go through normal shutdown procedure. It may make things worse.
- ::_exit(EXIT_ABRUPT);
-
- }
-
- void abruptQuitWithAddrSignal( int signal, siginfo_t *siginfo, void * ) {
- ostringstream oss;
- oss << "Invalid";
- if ( signal == SIGSEGV || signal == SIGBUS ) {
- oss << " access";
- } else {
- oss << " operation";
- }
- oss << " at address: " << siginfo->si_addr << " from thread: " << getThreadName() << endl;
- rawOut( oss.str() );
- abruptQuit( signal );
- }
-
- sigset_t asyncSignals;
- // The signals in asyncSignals will be processed by this thread only, in order to
- // ensure the db and log mutexes aren't held.
- void signalProcessingThread() {
- while (true) {
- int actualSignal = 0;
- int status = sigwait( &asyncSignals, &actualSignal );
- fassert(16781, status == 0);
- switch (actualSignal) {
- case SIGUSR1:
- // log rotate signal
- fassert(16782, rotateLogs());
- break;
- default:
- // interrupt/terminate signal
- Client::initThread( "signalProcessingThread" );
- log() << "got signal " << actualSignal << " (" << strsignal( actualSignal )
- << "), will terminate after current cmd ends" << endl;
- exitCleanly( EXIT_CLEAN );
- break;
- }
- }
- }
-
- // this will be called in certain c++ error cases, for example if there are two active
- // exceptions
- void myterminate() {
- rawOut( "terminate() called, printing stack (if implemented for platform):" );
- printStackTrace();
- ::abort();
- }
-
- // this gets called when new fails to allocate memory
- void my_new_handler() {
- rawOut( "out of memory, printing stack and exiting:" );
- printStackTrace();
- ::_exit(EXIT_ABRUPT);
- }
-
- void setupSignals_ignoreHelper( int signal ) {}
-
- void setupSignalHandlers() {
- setupCoreSignals();
-
- struct sigaction addrSignals;
- memset( &addrSignals, 0, sizeof( struct sigaction ) );
- addrSignals.sa_sigaction = abruptQuitWithAddrSignal;
- sigemptyset( &addrSignals.sa_mask );
- addrSignals.sa_flags = SA_SIGINFO;
-
- verify( sigaction(SIGSEGV, &addrSignals, 0) == 0 );
- verify( sigaction(SIGBUS, &addrSignals, 0) == 0 );
- verify( sigaction(SIGILL, &addrSignals, 0) == 0 );
- verify( sigaction(SIGFPE, &addrSignals, 0) == 0 );
-
- verify( signal(SIGABRT, abruptQuit) != SIG_ERR );
- verify( signal(SIGQUIT, abruptQuit) != SIG_ERR );
- verify( signal(SIGPIPE, SIG_IGN) != SIG_ERR );
-
- setupSIGTRAPforGDB();
-
- // asyncSignals is a global variable listing the signals that should be handled by the
- // interrupt thread, once it is started via startSignalProcessingThread().
- sigemptyset( &asyncSignals );
- sigaddset( &asyncSignals, SIGHUP );
- sigaddset( &asyncSignals, SIGINT );
- sigaddset( &asyncSignals, SIGTERM );
- sigaddset( &asyncSignals, SIGUSR1 );
-
- set_terminate( myterminate );
- set_new_handler( my_new_handler );
- }
-
- void startSignalProcessingThread() {
- verify( pthread_sigmask( SIG_SETMASK, &asyncSignals, 0 ) == 0 );
- boost::thread it( signalProcessingThread );
- }
-
-#else // WIN32
- void consoleTerminate( const char* controlCodeName ) {
- Client::initThread( "consoleTerminate" );
- log() << "got " << controlCodeName << ", will terminate after current cmd ends" << endl;
- exitCleanly( EXIT_KILL );
- }
-
- BOOL WINAPI CtrlHandler( DWORD fdwCtrlType ) {
-
- switch( fdwCtrlType ) {
-
- case CTRL_C_EVENT:
- rawOut( "Ctrl-C signal" );
- consoleTerminate( "CTRL_C_EVENT" );
- return TRUE ;
-
- case CTRL_CLOSE_EVENT:
- rawOut( "CTRL_CLOSE_EVENT signal" );
- consoleTerminate( "CTRL_CLOSE_EVENT" );
- return TRUE ;
-
- case CTRL_BREAK_EVENT:
- rawOut( "CTRL_BREAK_EVENT signal" );
- consoleTerminate( "CTRL_BREAK_EVENT" );
- return TRUE;
-
- case CTRL_LOGOFF_EVENT:
- // only sent to services, and only in pre-Vista Windows; FALSE means ignore
- return FALSE;
-
- case CTRL_SHUTDOWN_EVENT:
- rawOut( "CTRL_SHUTDOWN_EVENT signal" );
- consoleTerminate( "CTRL_SHUTDOWN_EVENT" );
- return TRUE;
-
- default:
- return FALSE;
- }
- }
-
- // called by mongoAbort()
- extern void (*reportEventToSystem)(const char *msg);
- void reportEventToSystemImpl(const char *msg) {
- static ::HANDLE hEventLog = RegisterEventSource( NULL, TEXT("mongod") );
- if( hEventLog ) {
- std::wstring s = toNativeString(msg);
- LPCTSTR txt = s.c_str();
- BOOL ok = ReportEvent(
- hEventLog, EVENTLOG_ERROR_TYPE,
- 0, 0, NULL,
- 1,
- 0,
- &txt,
- 0);
- wassert(ok);
- }
- }
-
- void myPurecallHandler() {
- printStackTrace();
- mongoAbort("pure virtual");
- }
-
- void setupSignalHandlers() {
- reportEventToSystem = reportEventToSystemImpl;
- setWindowsUnhandledExceptionFilter();
- massert(10297,
- "Couldn't register Windows Ctrl-C handler",
- SetConsoleCtrlHandler(static_cast<PHANDLER_ROUTINE>(CtrlHandler), TRUE));
- _set_purecall_handler( myPurecallHandler );
- }
-
- void startSignalProcessingThread() {}
-
-#endif // if !defined(_WIN32)
-
-} // namespace mongo