diff options
author | Antonin Kral <a.kral@bobek.cz> | 2011-09-14 17:08:06 +0200 |
---|---|---|
committer | Antonin Kral <a.kral@bobek.cz> | 2011-09-14 17:08:06 +0200 |
commit | 5d342a758c6095b4d30aba0750b54f13b8916f51 (patch) | |
tree | 762e9aa84781f5e3b96db2c02d356c29cf0217c0 /db/db.cpp | |
parent | cbe2d992e9cd1ea66af9fa91df006106775d3073 (diff) | |
download | mongodb-5d342a758c6095b4d30aba0750b54f13b8916f51.tar.gz |
Imported Upstream version 2.0.0
Diffstat (limited to 'db/db.cpp')
-rw-r--r-- | db/db.cpp | 489 |
1 files changed, 246 insertions, 243 deletions
@@ -18,12 +18,12 @@ #include "pch.h" #include "db.h" -#include "query.h" #include "introspect.h" #include "repl.h" #include "../util/unittest.h" #include "../util/file_allocator.h" #include "../util/background.h" +#include "../util/text.h" #include "dbmessage.h" #include "instance.h" #include "clientcursor.h" @@ -36,28 +36,33 @@ #include "stats/snapshots.h" #include "../util/concurrency/task.h" #include "../util/version.h" +#include "../util/ramlog.h" +#include "../util/net/message_server.h" #include "client.h" #include "restapi.h" #include "dbwebserver.h" #include "dur.h" #include "concurrency.h" +#include "../s/d_writeback.h" #if defined(_WIN32) # include "../util/ntservice.h" #else # include <sys/file.h> -# include <sys/resource.h> #endif namespace mongo { + namespace dur { + extern unsigned long long DataLimitPerJournalFile; + } + /* only off if --nocursors which is for debugging. */ extern bool useCursors; /* only off if --nohints */ extern bool useHints; - extern char *appsrvPath; extern int diagLogging; extern unsigned lenForNewNsFiles; extern int lockFile; @@ -65,9 +70,7 @@ namespace mongo { extern string repairpath; void setupSignals( bool inFork ); - void startReplSets(ReplSetCmdline*); void startReplication(); - void pairWith(const char *remoteEnd, const char *arb); void exitCleanly( ExitCode code ); CmdLine cmdLine; @@ -93,65 +96,6 @@ namespace mongo { QueryResult* emptyMoreResult(long long); - void connThread( MessagingPort * p ); - - class OurListener : public Listener { - public: - OurListener(const string &ip, int p) : Listener(ip, p) { } - virtual void accepted(MessagingPort *mp) { - - if ( ! connTicketHolder.tryAcquire() ) { - log() << "connection refused because too many open connections: " << connTicketHolder.used() << " of " << connTicketHolder.outof() << endl; - // TODO: would be nice if we notified them... - mp->shutdown(); - delete mp; - return; - } - - try { -#ifndef __linux__ // TODO: consider making this ifdef _WIN32 - boost::thread thr(boost::bind(&connThread,mp)); -#else - pthread_attr_t attrs; - pthread_attr_init(&attrs); - pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED); - - static const size_t STACK_SIZE = 4*1024*1024; - - struct rlimit limits; - assert(getrlimit(RLIMIT_STACK, &limits) == 0); - if (limits.rlim_cur > STACK_SIZE) { - pthread_attr_setstacksize(&attrs, (DEBUG_BUILD - ? (STACK_SIZE / 2) - : STACK_SIZE)); - } - else if (limits.rlim_cur < 1024*1024) { - warning() << "Stack size set to " << (limits.rlim_cur/1024) << "KB. We suggest at least 1MB" << endl; - } - - pthread_t thread; - int failed = pthread_create(&thread, &attrs, (void*(*)(void*)) &connThread, mp); - - pthread_attr_destroy(&attrs); - - if (failed) { - log() << "pthread_create failed: " << errnoWithDescription(failed) << endl; - throw boost::thread_resource_error(); // for consistency with boost::thread - } -#endif - } - catch ( boost::thread_resource_error& ) { - log() << "can't create new thread, closing connection" << endl; - mp->shutdown(); - delete mp; - } - catch ( ... ) { - log() << "unkonwn exception starting connThread" << endl; - mp->shutdown(); - delete mp; - } - } - }; /* todo: make this a real test. the stuff in dbtests/ seem to do all dbdirectclient which exhaust doesn't support yet. */ // QueryOption_Exhaust @@ -193,23 +137,8 @@ namespace mongo { }; #endif - void listen(int port) { - //testTheDb(); - log() << "waiting for connections on port " << port << endl; - OurListener l(cmdLine.bind_ip, port); - l.setAsTimeTracker(); - startReplication(); - if ( !noHttpInterface ) - boost::thread web( boost::bind(&webServerThread, new RestAdminAccess() /* takes ownership */)); - -#if(TESTEXHAUST) - boost::thread thr(testExhaust); -#endif - l.initAndListen(); - } - void sysRuntimeInfo() { - out() << "sysinfo:\n"; + out() << "sysinfo:" << endl; #if defined(_SC_PAGE_SIZE) out() << " page size: " << (int) sysconf(_SC_PAGE_SIZE) << endl; #endif @@ -226,36 +155,15 @@ namespace mongo { sleepmicros( Client::recommendedYieldMicros() ); } - /* we create one thread for each connection from an app server database. - app server will open a pool of threads. - todo: one day, asio... - */ - void connThread( MessagingPort * inPort ) { - TicketHolderReleaser connTicketReleaser( &connTicketHolder ); - - /* todo: move to Client object */ - LastError *le = new LastError(); - lastError.reset(le); - - inPort->_logLevel = 1; - auto_ptr<MessagingPort> dbMsgPort( inPort ); - Client& c = Client::initThread("conn", inPort); - - try { - - c.getAuthenticationInfo()->isLocalHost = dbMsgPort->farEnd.isLocalHost(); - - Message m; - while ( 1 ) { - inPort->clearCounters(); + class MyMessageHandler : public MessageHandler { + public: + virtual void connected( AbstractMessagingPort* p ) { + Client& c = Client::initThread("conn", p); + c.getAuthenticationInfo()->isLocalHost = p->remote().isLocalHost(); + } - if ( !dbMsgPort->recv(m) ) { - if( !cmdLine.quiet ) - log() << "end connection " << dbMsgPort->farEnd.toString() << endl; - dbMsgPort->shutdown(); - break; - } -sendmore: + virtual void process( Message& m , AbstractMessagingPort* port , LastError * le) { + while ( true ) { if ( inShutdown() ) { log() << "got request after shutdown()" << endl; break; @@ -264,10 +172,10 @@ sendmore: lastError.startRequest( m , le ); DbResponse dbresponse; - assembleResponse( m, dbresponse, dbMsgPort->farEnd ); + assembleResponse( m, dbresponse, port->remote() ); if ( dbresponse.response ) { - dbMsgPort->reply(m, *dbresponse.response, dbresponse.responseTo); + port->reply(m, *dbresponse.response, dbresponse.responseTo); if( dbresponse.exhaust ) { MsgData *header = dbresponse.response->header(); QueryResult *qr = (QueryResult *) header; @@ -289,46 +197,42 @@ sendmore: b.decouple(); DEV log() << "exhaust=true sending more" << endl; beNice(); - goto sendmore; + continue; // this goes back to top loop } } } - - networkCounter.hit( inPort->getBytesIn() , inPort->getBytesOut() ); - - m.reset(); + break; } - - } - catch ( AssertionException& e ) { - log() << "AssertionException in connThread, closing client connection" << endl; - log() << ' ' << e.what() << endl; - dbMsgPort->shutdown(); - } - catch ( SocketException& ) { - problem() << "SocketException in connThread, closing client connection" << endl; - dbMsgPort->shutdown(); - } - catch ( const ClockSkewException & ) { - exitCleanly( EXIT_CLOCK_SKEW ); - } - catch ( std::exception &e ) { - problem() << "Uncaught std::exception: " << e.what() << ", terminating" << endl; - dbexit( EXIT_UNCAUGHT ); - } - catch ( ... ) { - problem() << "Uncaught exception, terminating" << endl; - dbexit( EXIT_UNCAUGHT ); } - // thread ending... - { + virtual void disconnected( AbstractMessagingPort* p ) { Client * c = currentClient.get(); if( c ) c->shutdown(); + globalScriptEngine->threadDone(); } - globalScriptEngine->threadDone(); + + }; + + void listen(int port) { + //testTheDb(); + MessageServer::Options options; + options.port = port; + options.ipList = cmdLine.bind_ip; + + MessageServer * server = createServer( options , new MyMessageHandler() ); + server->setAsTimeTracker(); + + startReplication(); + if ( !noHttpInterface ) + boost::thread web( boost::bind(&webServerThread, new RestAdminAccess() /* takes ownership */)); + +#if(TESTEXHAUST) + boost::thread thr(testExhaust); +#endif + server->run(); } + bool doDBUpgrade( const string& dbName , string errmsg , DataFileHeader * h ) { static DBDirectClient db; @@ -378,7 +282,9 @@ sendmore: if ( !h->isCurrentVersion() || forceRepair ) { if( h->version <= 0 ) { - uasserted(10000, str::stream() << "db " << dbName << " appears corrupt pdfile version: " << h->version << " info: " << h->versionMinor << ' ' << h->fileLength); + uasserted(14026, + str::stream() << "db " << dbName << " appears corrupt pdfile version: " << h->version + << " info: " << h->versionMinor << ' ' << h->fileLength); } log() << "****" << endl; @@ -494,10 +400,12 @@ sendmore: return cc().curop()->opNum(); } - void _initAndListen(int listenPort, const char *appserverLoc = NULL) { + void _initAndListen(int listenPort ) { Client::initThread("initandlisten"); + Logstream::get().addGlobalTee( new RamLog("global") ); + bool is32bit = sizeof(int*) == 4; { @@ -510,13 +418,14 @@ sendmore: l << "MongoDB starting : pid=" << pid << " port=" << cmdLine.port << " dbpath=" << dbpath; if( replSettings.master ) l << " master=" << replSettings.master; if( replSettings.slave ) l << " slave=" << (int) replSettings.slave; - l << ( is32bit ? " 32" : " 64" ) << "-bit " << endl; + l << ( is32bit ? " 32" : " 64" ) << "-bit host=" << getHostNameCached() << endl; } DEV log() << "_DEBUG build (which is slower)" << endl; show_warnings(); log() << mongodVersion() << endl; printGitVersion(); printSysInfo(); + printCommandLineOpts(); { stringstream ss; @@ -529,12 +438,12 @@ sendmore: uassert( 12590 , ss.str().c_str(), boost::filesystem::exists( repairpath ) ); } - acquirePathLock(); + acquirePathLock(forceRepair); remove_all( dbpath + "/_tmp/" ); FileAllocator::get()->start(); - BOOST_CHECK_EXCEPTION( clearTmpFiles() ); + MONGO_BOOST_CHECK_EXCEPTION_WITH_MSG( clearTmpFiles(), "clear tmp files" ); _diaglog.init(); @@ -556,7 +465,7 @@ sendmore: repairDatabasesAndCheckVersion(); - /* we didn't want to pre-open all fiels for the repair check above. for regular + /* we didn't want to pre-open all files for the repair check above. for regular operation we do for read/write lock concurrency reasons. */ Database::_openAllFiles = true; @@ -569,12 +478,7 @@ sendmore: snapshotThread.go(); clientCursorMonitor.go(); - - if( !cmdLine._replSet.empty() ) { - replSet = true; - ReplSetCmdline *replSetCmdline = new ReplSetCmdline(cmdLine._replSet); - boost::thread t( boost::bind( &startReplSets, replSetCmdline) ); - } + PeriodicTask::theRunner->go(); listen(listenPort); @@ -584,8 +488,14 @@ sendmore: void testPretouch(); - void initAndListen(int listenPort, const char *appserverLoc = NULL) { - try { _initAndListen(listenPort, appserverLoc); } + void initAndListen(int listenPort) { + try { + _initAndListen(listenPort); + } + catch ( DBException &e ) { + log() << "exception in initAndListen: " << e.toString() << ", terminating" << endl; + dbexit( EXIT_UNCAUGHT ); + } catch ( std::exception &e ) { log() << "exception in initAndListen std::exception: " << e.what() << ", terminating" << endl; dbexit( EXIT_UNCAUGHT ); @@ -603,7 +513,7 @@ sendmore: #if defined(_WIN32) bool initService() { ServiceController::reportStatus( SERVICE_RUNNING ); - initAndListen( cmdLine.port, appsrvPath ); + initAndListen( cmdLine.port ); return true; } #endif @@ -625,23 +535,12 @@ void show_help_text(po::options_description options) { /* Return error string or "" if no errors. */ string arg_error_check(int argc, char* argv[]) { - for (int i = 1; i < argc; i++) { - string s = argv[i]; - /* check for inclusion of old-style arbiter setting. */ - if (s == "--pairwith") { - if (argc > i + 2) { - string old_arbiter = argv[i + 2]; - if (old_arbiter == "-" || old_arbiter.substr(0, 1) != "-") { - return "Specifying arbiter using --pairwith is no longer supported, please use --arbiter"; - } - } - } - } return ""; } int main(int argc, char* argv[]) { static StaticObserver staticObserver; + doPreServerStatupInits(); getcurns = ourgetns; po::options_description general_options("General options"); @@ -667,18 +566,16 @@ int main(int argc, char* argv[]) { ("directoryperdb", "each database will be stored in a separate directory") ("journal", "enable journaling") ("journalOptions", po::value<int>(), "journal diagnostic options") + ("journalCommitInterval", po::value<unsigned>(), "how often to group/batch commit (ms)") ("ipv6", "enable IPv6 support (disabled by default)") ("jsonp","allow JSONP access via http (has security implications)") ("noauth", "run without security") ("nohttpinterface", "disable http interface") + ("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") -#if !defined(_WIN32) - ("nounixsocket", "disable listening on unix sockets") -#endif ("nssize", po::value<int>()->default_value(16), ".ns file size (in MB) for new databases") - ("objcheck", "inspect client data for validity on receipt") ("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 allower per db, requires --quota") @@ -687,6 +584,9 @@ int main(int argc, char* argv[]) { ("repairpath", po::value<string>() , "root directory for repair files - defaults to dbpath" ) ("slowms",po::value<int>(&cmdLine.slowMS)->default_value(100), "value of slow for profile and console log" ) ("smallfiles", "use a smaller default file size") +#if defined(__linux__) + ("shutdown", "kill a running server (for init scripts)") +#endif ("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") @@ -698,7 +598,6 @@ int main(int argc, char* argv[]) { replication_options.add_options() ("fastsync", "indicate that this instance is starting from a dbpath snapshot of the repl peer") - ("autoresync", "automatically resync if slave data is stale") ("oplogSize", po::value<int>(), "size limit (in MB) for op log") ; @@ -708,6 +607,7 @@ int main(int argc, char* argv[]) { ("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() @@ -724,17 +624,17 @@ int main(int argc, char* argv[]) { ("pretouch", po::value<int>(), "n pretouch threads for applying replicationed operations") ("command", po::value< vector<string> >(), "command") ("cacheSize", po::value<long>(), "cache size (in MB) for rec store") - // these move to unhidden later: - ("opIdMem", po::value<long>(), "size limit (in bytes) for in memory storage of op ids for replica pairs DEPRECATED") - ("pairwith", po::value<string>(), "address of server to pair with DEPRECATED") - ("arbiter", po::value<string>(), "address of replica pair arbiter server DEPRECATED") ("nodur", "disable journaling (currently the default)") - ("nojournal", "disable journaling (currently the default)") - ("appsrvpath", po::value<string>(), "root directory for the babble app server") + // things we don't want people to use ("nocursors", "diagnostic/debugging option that turns off cursors DO NOT USE IN PRODUCTION") ("nohints", "ignore query hints") + ("nopreallocj", "don't preallocate journal files") ("dur", "enable journaling") // deprecated version ("durOptions", po::value<int>(), "durability diagnostic options") // deprecated version + // deprecated pairing command line options + ("pairwith", "DEPRECATED") + ("arbiter", "DEPRECATED") + ("opIdMem", "DEPRECATED") ; @@ -828,44 +728,46 @@ int main(int argc, char* argv[]) { cmdLine.quota = true; cmdLine.quotaFiles = params["quotaFiles"].as<int>() - 1; } - if( params.count("nodur") ) { - cmdLine.dur = false; - } - if( params.count("nojournal") ) { + bool journalExplicit = false; + if( params.count("nodur") || params.count( "nojournal" ) ) { + journalExplicit = true; cmdLine.dur = false; } if( params.count("dur") || params.count( "journal" ) ) { + 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 (params.count("objcheck")) { - objcheck = true; - } - if (params.count("appsrvpath")) { - /* casting away the const-ness here */ - appsrvPath = (char*)(params["appsrvpath"].as<string>().c_str()); - } if (params.count("repairpath")) { repairpath = params["repairpath"].as<string>(); if (!repairpath.size()) { - out() << "repairpath has to be non-zero" << endl; + out() << "repairpath is empty" << endl; dbexit( EXIT_BADOPTIONS ); } } - else { - repairpath = dbpath; - } if (params.count("nocursors")) { useCursors = false; } if (params.count("nohints")) { useHints = false; } + if (params.count("nopreallocj")) { + cmdLine.preallocj = false; + } if (params.count("nohttpinterface")) { noHttpInterface = true; } @@ -884,6 +786,8 @@ int main(int argc, char* argv[]) { } if (params.count("smallfiles")) { cmdLine.smallfiles = true; + assert( dur::DataLimitPerJournalFile >= 128 * 1024 * 1024 ); + dur::DataLimitPerJournalFile = 128 * 1024 * 1024; } if (params.count("diaglog")) { int x = params["diaglog"].as<int>(); @@ -898,10 +802,12 @@ int main(int argc, char* argv[]) { return 0; } if (params.count("repair")) { + Record::MemoryTrackingEnabled = false; shouldRepairDatabases = 1; forceRepair = 1; } if (params.count("upgrade")) { + Record::MemoryTrackingEnabled = false; shouldRepairDatabases = 1; } if (params.count("notablescan")) { @@ -921,6 +827,11 @@ int main(int argc, char* argv[]) { } if (params.count("autoresync")) { replSettings.autoresync = true; + if( params.count("replSet") ) { + out() << "--autoresync is not used with --replSet" << endl; + out() << "see http://www.mongodb.org/display/DOCS/Resyncing+a+Very+Stale+Replica+Set+Member" << endl; + dbexit( EXIT_BADOPTIONS ); + } } if (params.count("source")) { /* specifies what the source in local.sources should be */ @@ -944,25 +855,6 @@ int main(int argc, char* argv[]) { if (params.count("only")) { cmdLine.only = params["only"].as<string>().c_str(); } - if (params.count("pairwith")) { - cout << "***********************************\n" - << "WARNING WARNING WARNING\n" - << " replica pairs are deprecated\n" - << " see: http://www.mongodb.org/display/DOCS/Replica+Pairs \n" - << "***********************************" << endl; - string paired = params["pairwith"].as<string>(); - if (params.count("arbiter")) { - string arbiter = params["arbiter"].as<string>(); - pairWith(paired.c_str(), arbiter.c_str()); - } - else { - pairWith(paired.c_str(), "-"); - } - } - else if (params.count("arbiter")) { - out() << "specifying --arbiter without --pairwith" << endl; - dbexit( EXIT_BADOPTIONS ); - } if( params.count("nssize") ) { int x = params["nssize"].as<int>(); if (x <= 0 || x > (0x7fffffff/1024/1024)) { @@ -986,15 +878,6 @@ int main(int argc, char* argv[]) { cmdLine.oplogSize = x * 1024 * 1024; assert(cmdLine.oplogSize > 0); } - if (params.count("opIdMem")) { - long x = params["opIdMem"].as<long>(); - if (x <= 0) { - out() << "bad --opIdMem arg" << endl; - dbexit( EXIT_BADOPTIONS ); - } - replSettings.opIdMem = x; - assert(replSettings.opIdMem > 0); - } if (params.count("cacheSize")) { long x = params["cacheSize"].as<long>(); if (x <= 0) { @@ -1007,8 +890,13 @@ int main(int argc, char* argv[]) { if( params.count("configsvr") ) { cmdLine.port = CmdLine::ConfigServerPort; } - if( params.count("shardsvr") ) + 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 ) { @@ -1017,27 +905,36 @@ int main(int argc, char* argv[]) { } } if ( params.count("configsvr" ) ) { + cmdLine.configsvr = true; if (cmdLine.usingReplSets() || replSettings.master || replSettings.slave) { log() << "replication should not be enabled on a config server" << endl; ::exit(-1); } - if ( params.count( "diaglog" ) == 0 ) - _diaglog.level = 1; + if ( params.count( "nodur" ) == 0 && params.count( "nojournal" ) == 0 ) + cmdLine.dur = true; if ( params.count( "dbpath" ) == 0 ) dbpath = "/data/configdb"; } if ( params.count( "profile" ) ) { cmdLine.defaultProfile = params["profile"].as<int>(); } - if (params.count("nounixsocket")) { - noUnixSocket = true; - } if (params.count("ipv6")) { enableIPv6(); } if (params.count("noMoveParanoia")) { cmdLine.moveParanoia = false; } + if (params.count("pairwith") || params.count("arbiter") || params.count("opIdMem")) { + out() << "****" << endl; + out() << "Replica Pairs have been deprecated." << endl; + out() << "<http://www.mongodb.org/display/DOCS/Replica+Pairs>" << endl; + out() << "****" << endl; + dbexit( EXIT_BADOPTIONS ); + } + + // needs to be after things like --configsvr parsing, thus here. + if( repairpath.empty() ) + repairpath = dbpath; Module::configAll( params ); dataFileSync.go(); @@ -1069,15 +966,85 @@ int main(int argc, char* argv[]) { if( cmdLine.pretouch ) log() << "--pretouch " << cmdLine.pretouch << endl; +#ifdef __linux__ + if (params.count("shutdown")){ + bool failed = false; + + string name = ( boost::filesystem::path( dbpath ) / "mongod.lock" ).native_file_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; + + string exePath = procPath + "/exe"; + if (boost::filesystem::exists(exePath)){ + char buf[256]; + int ret = readlink(exePath.c_str(), buf, sizeof(buf)-1); + buf[ret] = '\0'; // readlink doesn't terminate string + if (ret == -1) { + int e = errno; + cerr << "Error resolving " << exePath << ": " << errnoWithDescription(e); + failed = true; + } + else if (!endsWith(buf, "mongod")){ + cerr << "Process " << pid << " is running " << buf << " not mongod" << endl; + ::exit(-1); + } + } + } + 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(-1); + } + + cout << "killing process with pid: " << pid << endl; + int ret = kill(pid, SIGTERM); + if (ret) { + int e = errno; + cerr << "failed to kill process: " << errnoWithDescription(e) << endl; + ::exit(-1); + } + + while (boost::filesystem::exists(procPath)) { + sleepsecs(1); + } + + ::exit(0); + } +#endif + #if defined(_WIN32) if (serviceParamsCheck( params, dbpath, argc, argv )) { return 0; } #endif + + + 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; + } + } UnitTest::runTests(); - initAndListen(cmdLine.port, appsrvPath); + initAndListen(cmdLine.port); dbexit(EXIT_CLEAN); return 0; } @@ -1088,14 +1055,6 @@ namespace mongo { #undef out - void exitCleanly( ExitCode code ) { - killCurrentOp.killAll(); - { - dblock lk; - log() << "now exiting" << endl; - dbexit( code ); - } - } #if !defined(_WIN32) @@ -1166,7 +1125,7 @@ namespace mongo { void myterminate() { rawOut( "terminate() called, printing stack:" ); printStackTrace(); - abort(); + ::abort(); } void setupSignals_ignoreHelper( int signal ) {} @@ -1235,19 +1194,63 @@ namespace mongo { } } + LPTOP_LEVEL_EXCEPTION_FILTER filtLast = 0; + ::HANDLE standardOut = GetStdHandle(STD_OUTPUT_HANDLE); + LONG WINAPI exceptionFilter(struct _EXCEPTION_POINTERS *ExceptionInfo) { + { + // given the severity of the event we write to console in addition to the --logFile + // (rawOut writes to the logfile, if a special one were specified) + DWORD written; + WriteFile(standardOut, "unhandled windows exception\n", 20, &written, 0); + FlushFileBuffers(standardOut); + } + + DWORD ec = ExceptionInfo->ExceptionRecord->ExceptionCode; + if( ec == EXCEPTION_ACCESS_VIOLATION ) { + rawOut("access violation"); + } + else { + rawOut("unhandled windows exception"); + char buf[64]; + strcpy(buf, "ec=0x"); + _ui64toa(ec, buf+5, 16); + rawOut(buf); + } + if( filtLast ) + return filtLast(ExceptionInfo); + return EXCEPTION_EXECUTE_HANDLER; + } + + // 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() { - rawOut( "pure virtual method called, printing stack:" ); printStackTrace(); - abort(); + mongoAbort("pure virtual"); } void setupSignals( bool inFork ) { - if( SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE ) ) - ; - else - massert( 10297 , "Couldn't register Windows Ctrl-C handler", false); + reportEventToSystem = reportEventToSystemImpl; + filtLast = SetUnhandledExceptionFilter(exceptionFilter); + massert(10297 , "Couldn't register Windows Ctrl-C handler", SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE)); _set_purecall_handler( myPurecallHandler ); } + #endif } // namespace mongo |