void* MemoryMappedFile::map(const char *filename, long &length) { // length may be updated by callee. theFileAllocator().allocateAsap( filename, length ); len = length; fd = open(filename, O_RDWR | O_NOATIME); if ( fd <= 0 ) { out() << "couldn't open " << filename << ' ' << OUTPUT_ERRNO << endl; return 0; } off_t filelen = lseek(fd, 0, SEEK_END); if ( filelen != length ){ cout << "wanted length: " << length << " filelen: " << filelen << endl; cout << sizeof(size_t) << endl; massert( "file size allocation failed", filelen == length ); } lseek( fd, 0, SEEK_SET ); view = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if ( view == MAP_FAILED ) { out() << " mmap() failed for " << filename << " len:" << length << " " << OUTPUT_ERRNO << endl; if ( errno == ENOMEM ){ out() << " mmap failed with out of memory, if you're using 32-bits, then you probably need to upgrade to 64" << endl; } return 0; } return view; }
void _initAndListen(int listenPort, const char *appserverLoc = null) { #if !defined(_WIN32) pid_t pid = 0; pid = getpid(); #else int pid=0; #endif bool is32bit = sizeof(int*) == 4; log() << "Mongo DB : starting : pid = " << pid << " port = " << cmdLine.port << " dbpath = " << dbpath << " master = " << master << " slave = " << (int) slave << " " << ( is32bit ? "32" : "64" ) << "-bit " << endl; show_32_warning(); stringstream ss; ss << "dbpath (" << dbpath << ") does not exist"; massert( ss.str().c_str(), boost::filesystem::exists( dbpath ) ); acquirePathLock(); theFileAllocator().start(); BOOST_CHECK_EXCEPTION( clearTmpFiles() ); clearTmpCollections(); if ( opLogging ) log() << "opLogging = " << opLogging << endl; _oplog.init(); mms.go(); #if 0 { stringstream indexpath; indexpath << dbpath << "/indexes.dat"; RecCache::tempStore.init(indexpath.str().c_str(), BucketSize); } #endif if ( useJNI ) { ScriptEngine::setup(); } repairDatabases(); if ( shouldRepairDatabases ) return; /* this is for security on certain platforms */ srand(curTimeMicros() ^ startupSrandTimer.micros()); listen(listenPort); // listen() will return when exit code closes its socket. while( 1 ) sleepsecs( 100 ); }
void* MemoryMappedFile::map(const char *filename, unsigned long long &length, int options) { // length may be updated by callee. _filename = filename; theFileAllocator().allocateAsap( filename, length ); len = length; massert( 10446 , (string)"mmap() can't map area of size 0 [" + filename + "]" , length > 0 ); fd = open(filename, O_RDWR | O_NOATIME); if ( fd <= 0 ) { out() << "couldn't open " << filename << ' ' << errnoWithDescription() << endl; return 0; } unsigned long long filelen = lseek(fd, 0, SEEK_END); if ( filelen != length ){ cout << "wanted length: " << length << " filelen: " << filelen << endl; cout << sizeof(size_t) << endl; massert( 10447 , "file size allocation failed", filelen == length ); } lseek( fd, 0, SEEK_SET ); void * view = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if ( view == MAP_FAILED ) { out() << " mmap() failed for " << filename << " len:" << length << " " << errnoWithDescription() << endl; if ( errno == ENOMEM ){ out() << "mmap failed with out of memory, if you're using 32-bits, then you probably need to upgrade to 64" << endl; } return 0; } #if defined(__sunos__) #warning madvise not supported on solaris yet #else if ( options & SEQUENTIAL ){ if ( madvise( view , length , MADV_SEQUENTIAL ) ){ out() << " madvise failed for " << filename << " " << errnoWithDescription() << endl; } } #endif DEV if (! dbMutex.info().isLocked()){ _unlock(); } views.push_back( view ); return view; }
void shutdown() { #ifndef _WIN32 { // close listener sockets // We would only hang here if a synchronous signal is received // during a registerListenerSocket() call, which we don't expect. boostlock lk( listenerSocketMutex ); for( vector< int >::iterator i = listenerSockets.begin(); i != listenerSockets.end(); ++i ) close( *i ); } #endif log() << "\t shutdown: going to flush oplog..." << endl; stringstream ss2; flushOpLog( ss2 ); rawOut( ss2.str() ); /* must do this before unmapping mem or you may get a seg fault */ log() << "\t shutdown: going to close sockets..." << endl; closeAllSockets(); // wait until file preallocation finishes // we would only hang here if the file_allocator code generates a // synchronous signal, which we don't expect log() << "\t shutdown: waiting for fs..." << endl; theFileAllocator().waitUntilFinished(); log() << "\t shutdown: closing all files..." << endl; stringstream ss3; MemoryMappedFile::closeAllFiles( ss3 ); rawOut( ss3.str() ); // should we be locked here? we aren't. might be ok as-is. recCacheCloseAll(); #if !defined(_WIN32) && !defined(__sunos__) if ( lockFile ){ log() << "\t shutdown: removing fs lock..." << endl; if( ftruncate( lockFile , 0 ) ) log() << "\t couldn't remove fs lock errno=" << errno << endl; flock( lockFile, LOCK_UN ); } #endif }
int Suite::run( int argc , char** argv , string default_dbpath ) { unsigned long long seed = time( 0 ); string dbpathSpec; po::options_description shell_options("options"); po::options_description hidden_options("Hidden options"); po::options_description cmdline_options("Command line options"); po::positional_options_description positional_options; shell_options.add_options() ("help,h", "show this usage information") ("dbpath", po::value<string>(&dbpathSpec)->default_value(default_dbpath), "db data path for this test run. NOTE: the contents of this " "directory will be overwritten if it already exists") ("debug", "run tests with verbose output") ("list,l", "list available test suites") ("verbose,v", "verbose") ("seed", po::value<unsigned long long>(&seed), "random number seed") ; hidden_options.add_options() ("suites", po::value< vector<string> >(), "test suites to run") ; positional_options.add("suites", -1); cmdline_options.add(shell_options).add(hidden_options); po::variables_map params; int command_line_style = (((po::command_line_style::unix_style ^ po::command_line_style::allow_guessing) | po::command_line_style::allow_long_disguise) ^ po::command_line_style::allow_sticky); try { po::store(po::command_line_parser(argc, argv).options(cmdline_options). positional(positional_options). style(command_line_style).run(), params); po::notify(params); } catch (po::error &e) { cout << "ERROR: " << e.what() << endl << endl; show_help_text(argv[0], shell_options); return EXIT_BADOPTIONS; } if (params.count("help")) { show_help_text(argv[0], shell_options); return EXIT_CLEAN; } if (params.count("debug") || params.count("verbose") ) { logLevel = 1; } if (params.count("list")) { for ( map<string,Suite*>::iterator i = _suites->begin() ; i != _suites->end(); i++ ) cout << i->first << endl; return 0; } boost::filesystem::path p(dbpathSpec); /* remove the contents of the test directory if it exists. */ if (boost::filesystem::exists(p)) { if (!boost::filesystem::is_directory(p)) { cout << "ERROR: path \"" << p.string() << "\" is not a directory" << endl << endl; show_help_text(argv[0], shell_options); return EXIT_BADOPTIONS; } boost::filesystem::directory_iterator end_iter; for (boost::filesystem::directory_iterator dir_iter(p); dir_iter != end_iter; ++dir_iter) { boost::filesystem::remove_all(*dir_iter); } } else { boost::filesystem::create_directory(p); } string dbpathString = p.native_directory_string(); dbpath = dbpathString.c_str(); cmdLine.prealloc = false; cmdLine.smallfiles = true; cmdLine.oplogSize = 10 * 1024 * 1024; Client::initThread("testsuite"); acquirePathLock(); srand( (unsigned) seed ); printGitVersion(); printSysInfo(); out() << "random seed: " << seed << endl; theFileAllocator().start(); vector<string> suites; if (params.count("suites")) { suites = params["suites"].as< vector<string> >(); } int ret = run(suites); #if !defined(_WIN32) && !defined(__sunos__) flock( lockFile, LOCK_UN ); #endif cc().shutdown(); dbexit( (ExitCode)ret ); // so everything shuts down cleanly return ret; }
void _initAndListen(int listenPort, const char *appserverLoc = NULL) { 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; if( replSettings.master ) l << " master=" << replSettings.master; if( replSettings.slave ) l << " slave=" << (int) replSettings.slave; l << ( is32bit ? " 32" : " 64" ) << "-bit " << endl; } DEV log() << "_DEBUG build (which is slower)" << endl; show_warnings(); log() << mongodVersion() << endl; printGitVersion(); printSysInfo(); { stringstream ss; ss << "dbpath (" << dbpath << ") does not exist"; uassert( 10296 , ss.str().c_str(), boost::filesystem::exists( dbpath ) ); } { stringstream ss; ss << "repairpath (" << repairpath << ") does not exist"; uassert( 12590 , ss.str().c_str(), boost::filesystem::exists( repairpath ) ); } acquirePathLock(); remove_all( dbpath + "/_tmp/" ); theFileAllocator().start(); BOOST_CHECK_EXCEPTION( clearTmpFiles() ); Client::initThread("initandlisten"); _diaglog.init(); clearTmpCollections(); Module::initAll(); #if 0 { stringstream indexpath; indexpath << dbpath << "/indexes.dat"; RecCache::tempStore.init(indexpath.str().c_str(), BucketSize); } #endif if ( useJNI ) { ScriptEngine::setup(); globalScriptEngine->setCheckInterruptCallback( jsInterruptCallback ); } repairDatabases(); /* we didn't want to pre-open all fiels for the repair check above. for regular operation we do for read/write lock concurrency reasons. */ Database::_openAllFiles = true; if ( shouldRepairDatabases ) return; /* this is for security on certain platforms (nonce generation) */ srand((unsigned) (curTimeMicros() ^ startupSrandTimer.micros())); snapshotThread.go(); clientCursorMonitor.go(); if( !cmdLine._replSet.empty() ) { replSet = true; ReplSetCmdline *replSetCmdline = new ReplSetCmdline(cmdLine._replSet); boost::thread t( boost::bind( &startReplSets, replSetCmdline) ); } listen(listenPort); // listen() will return when exit code closes its socket. exitCleanly(EXIT_NET_ERROR); }
int Tool::main( int argc , char ** argv ){ static StaticObserver staticObserver; cmdLine.prealloc = false; boost::filesystem::path::default_name_check( boost::filesystem::no_check ); _name = argv[0]; /* using the same style as db.cpp */ int command_line_style = (((po::command_line_style::unix_style ^ po::command_line_style::allow_guessing) | po::command_line_style::allow_long_disguise) ^ po::command_line_style::allow_sticky); try { po::options_description all_options("all options"); all_options.add(*_options).add(*_hidden_options); po::store( po::command_line_parser( argc , argv ). options(all_options). positional( _positonalOptions ). style(command_line_style).run() , _params ); po::notify( _params ); } catch (po::error &e) { cerr << "ERROR: " << e.what() << endl << endl; printHelp(cerr); return EXIT_BADOPTIONS; } // hide password from ps output for (int i=0; i < (argc-1); ++i){ if (!strcmp(argv[i], "-p") || !strcmp(argv[i], "--password")){ char* arg = argv[i+1]; while (*arg){ *arg++ = 'x'; } } } if ( _params.count( "help" ) ){ printHelp(cout); return 0; } if ( _params.count( "verbose" ) ) { logLevel = 1; } for (string s = "vv"; s.length() <= 10; s.append("v")) { if (_params.count(s)) { logLevel = s.length(); } } preSetup(); bool useDirectClient = hasParam( "dbpath" ); if ( ! useDirectClient ) { _host = "127.0.0.1"; if ( _params.count( "host" ) ) _host = _params["host"].as<string>(); if ( _params.count( "port" ) ) _host += ':' + _params["port"].as<string>(); if ( _noconnection ){ // do nothing } else if ( _host.find( "," ) == string::npos ){ DBClientConnection * c = new DBClientConnection( _autoreconnect ); _conn = c; string errmsg; if ( ! c->connect( _host , errmsg ) ){ cerr << "couldn't connect to [" << _host << "] " << errmsg << endl; return -1; } } else { log(1) << "using pairing" << endl; DBClientPaired * c = new DBClientPaired(); _paired = true; _conn = c; if ( ! c->connect( _host ) ){ cerr << "couldn't connect to paired server: " << _host << endl; return -1; } } (_usesstdout ? cout : cerr ) << "connected to: " << _host << endl; } else { if ( _params.count( "directoryperdb" ) ) { directoryperdb = true; } assert( lastError.get( true ) ); Client::initThread("tools"); _conn = new DBDirectClient(); _host = "DIRECT"; static string myDbpath = getParam( "dbpath" ); dbpath = myDbpath.c_str(); try { acquirePathLock(); } catch ( DBException& e ){ cerr << endl << "If you are running a mongod on the same " "path you should connect to that instead of direct data " "file access" << endl << endl; dbexit( EXIT_CLEAN ); return -1; } theFileAllocator().start(); } if ( _params.count( "db" ) ) _db = _params["db"].as<string>(); if ( _params.count( "collection" ) ) _coll = _params["collection"].as<string>(); if ( _params.count( "username" ) ) _username = _params["username"].as<string>(); if ( _params.count( "password" ) && ( _password.empty() ) ) { _password = askPassword(); } if (_params.count("ipv6")) enableIPv6(); int ret = -1; try { ret = run(); } catch ( DBException& e ){ cerr << "assertion: " << e.toString() << endl; ret = -1; } if ( currentClient.get() ) currentClient->shutdown(); if ( useDirectClient ) dbexit( EXIT_CLEAN ); return ret; }