summaryrefslogtreecommitdiff
path: root/db/db.cpp
diff options
context:
space:
mode:
authorAntonin Kral <a.kral@bobek.cz>2011-09-14 17:08:06 +0200
committerAntonin Kral <a.kral@bobek.cz>2011-09-14 17:08:06 +0200
commit5d342a758c6095b4d30aba0750b54f13b8916f51 (patch)
tree762e9aa84781f5e3b96db2c02d356c29cf0217c0 /db/db.cpp
parentcbe2d992e9cd1ea66af9fa91df006106775d3073 (diff)
downloadmongodb-5d342a758c6095b4d30aba0750b54f13b8916f51.tar.gz
Imported Upstream version 2.0.0
Diffstat (limited to 'db/db.cpp')
-rw-r--r--db/db.cpp489
1 files changed, 246 insertions, 243 deletions
diff --git a/db/db.cpp b/db/db.cpp
index 4f4575c..e6281d7 100644
--- a/db/db.cpp
+++ b/db/db.cpp
@@ -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