Beispiel #1
0
    string Database::duplicateUncasedName( const string &name, const string &path, set< string > *duplicates ) {
        if ( duplicates ) {
            duplicates->clear();   
        }
        
        vector<string> others;
        getDatabaseNames( others , path );
        
        set<string> allShortNames;
        dbHolder.getAllShortNames( allShortNames );
        
        others.insert( others.end(), allShortNames.begin(), allShortNames.end() );
        
        for ( unsigned i=0; i<others.size(); i++ ) {

            if ( strcasecmp( others[i].c_str() , name.c_str() ) )
                continue;
            
            if ( strcmp( others[i].c_str() , name.c_str() ) == 0 )
                continue;

            if ( duplicates ) {
                duplicates->insert( others[i] );
            } else {
                return others[i];
            }
        }
        if ( duplicates ) {
            return duplicates->empty() ? "" : *duplicates->begin();
        }
        return "";
    }
Beispiel #2
0
    void IndexRebuilder::run() {
        Client::initThread(name().c_str()); 
        ON_BLOCK_EXIT_OBJ(cc(), &Client::shutdown);
        cc().getAuthorizationSession()->grantInternalAuthorization();

        std::vector<std::string> dbNames;
        getDatabaseNames(dbNames);

        try {
            std::list<std::string> collNames;
            for (std::vector<std::string>::const_iterator dbName = dbNames.begin();
                 dbName < dbNames.end();
                 dbName++) {
                Client::ReadContext ctx(*dbName);
                Database* db = ctx.ctx().db();
                db->namespaceIndex().getNamespaces(collNames, /* onlyCollections */ true);
            }
            checkNS(collNames);
        }
        catch (const DBException& e) {
            warning() << "Index rebuilding did not complete: " << e.what() << endl;
        }
        boost::unique_lock<boost::mutex> lk(ReplSet::rss.mtx);
        ReplSet::rss.indexRebuildDone = true;
        ReplSet::rss.cond.notify_all();
        LOG(1) << "checking complete" << endl;
    }
Beispiel #3
0
 /* returns true if there is data on this server.  useful when starting replication.
    local database does NOT count except for rsoplog collection.
    used to set the hasData field on replset heartbeat command response
 */
 bool replHasDatabases() {
     vector<string> names;
     {
         LOCK_REASON(lockReason, "repl: checking for existing data");
         Lock::GlobalRead lk(lockReason);
         Client::Transaction txn(DB_TXN_READ_ONLY | DB_TXN_SNAPSHOT);
         getDatabaseNames(names);
         txn.commit();
     }
     if( names.size() >= 2 ) return true;
     if( names.size() == 1 ) {
         if( names[0] != "local" )
             return true;
         // we have a local database.  return true if oplog isn't empty
         {
             LOCK_REASON(lockReason, "repl: checking for non-empty oplog");
             Client::ReadContext ctx(rsoplog, lockReason);
             Client::Transaction txn(DB_TXN_READ_ONLY | DB_TXN_SNAPSHOT);
             Collection *cl = getCollection(rsoplog);
             BSONObj o;
             if (cl != NULL && cl->findOne(BSONObj(), o)) {
                 txn.commit();
                 return true;
             }
         }
     }
     return false;
 }
Beispiel #4
0
    // ran at startup.
    static void repairDatabasesAndCheckVersion() {
        //        LastError * le = lastError.get( true );
        Client::GodScope gs;
        log(1) << "enter repairDatabases (to check pdfile version #)" << endl;

        //verify(checkNsFilesOnLoad);
        checkNsFilesOnLoad = false; // we are mainly just checking the header - don't scan the whole .ns file for every db here.

        Lock::GlobalWrite lk;
        vector< string > dbNames;
        getDatabaseNames( dbNames );
        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 );
            DataFileHeader *h = p->getHeader();
            if ( !h->isCurrentVersion() || forceRepair ) {

                if( h->version <= 0 ) {
                    uasserted(14026, 
                      str::stream() << "db " << dbName << " appears corrupt pdfile version: " << h->version 
							        << " 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 << endl;
                if ( shouldRepairDatabases ) {
                    // QUESTION: Repair even if file format is higher version than code?
                    log() << "\t starting upgrade" << endl;
                    string errmsg;
                    verify( doDBUpgrade( dbName , errmsg , 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;
                    return;
                }
            }
            else {
                Database::closeDatabase( dbName.c_str(), dbpath );
            }
        }

        log(1) << "done repairDatabases" << endl;

        if ( shouldRepairDatabases ) {
            log() << "finished checking dbs" << endl;
            cc().shutdown();
            dbexit( EXIT_CLEAN );
        }

        checkNsFilesOnLoad = true;
    }
Beispiel #5
0
    void dropAllDatabasesExceptLocal(OperationContext* txn) {
        Lock::GlobalWrite lk(txn->lockState());

        vector<string> n;
        getDatabaseNames(n);
        if( n.size() == 0 ) return;
        log() << "dropAllDatabasesExceptLocal " << n.size() << endl;
        for( vector<string>::iterator i = n.begin(); i != n.end(); i++ ) {
            if( *i != "local" ) {
                Client::Context ctx(*i);
                dropDatabase(txn, ctx.db());
            }
        }
    }
Beispiel #6
0
    Database::Database(const char *nm, bool& newDb, const string& _path )
        : name(nm), path(_path), namespaceIndex( path, name ), 
          profileName(name + ".system.profile")
    {
        
        { // check db name is valid
            size_t L = strlen(nm);
            uassert( 10028 ,  "db name is empty", L > 0 );
            uassert( 10029 ,  "bad db name [1]", *nm != '.' );
            uassert( 10030 ,  "bad db name [2]", nm[L-1] != '.' );
            uassert( 10031 ,  "bad char(s) in db name", strchr(nm, ' ') == 0 );
            uassert( 10032 ,  "db name too long", L < 64 );
        }
        
        newDb = namespaceIndex.exists();
        profile = 0;

        {
            vector<string> others;
            getDatabaseNames( others , path );
            
            for ( unsigned i=0; i<others.size(); i++ ){

                if ( strcasecmp( others[i].c_str() , nm ) )
                    continue;

                if ( strcmp( others[i].c_str() , nm ) == 0 )
                    continue;
                
                stringstream ss;
                ss << "db already exists with different case other: [" << others[i] << "] me [" << nm << "]";
                uasserted( DatabaseDifferCaseCode , ss.str() );
            }
        }

        
        // If already exists, open.  Otherwise behave as if empty until
        // there's a write, then open.
        if ( ! newDb || cmdLine.defaultProfile ) {
            namespaceIndex.init();
            if( _openAllFiles )
                openAllFiles();
            
        }
       

        magic = 781231;
    }
Beispiel #7
0
 /* returns true if there is data on this server.  useful when starting replication.
    local database does NOT count except for rsoplog collection.
    used to set the hasData field on replset heartbeat command response
 */
 bool replHasDatabases() {
     vector<string> names;
     getDatabaseNames(names);
     if( names.size() >= 2 ) return true;
     if( names.size() == 1 ) {
         if( names[0] != "local" )
             return true;
         // we have a local database.  return true if oplog isn't empty
         {
             Lock::DBRead lk(rsoplog);
             BSONObj o;
             if( Helpers::getFirst(rsoplog, o) )
                 return true;
         }
     }
     return false;
 }
Beispiel #8
0
 void clearTmpCollections() {
     Lock::GlobalWrite lk; // _openAllFiles is false at this point, so this is helpful for the query below to work as you can't open files when readlocked
     Client::GodScope gs;
     vector< string > toDelete;
     DBDirectClient cli;
     vector< string > dbNames;
     getDatabaseNames( dbNames );
     for (vector<string>::const_iterator it(dbNames.begin()), end(dbNames.end()); it != end; ++it){
         const string coll = *it + ".system.namespaces";
         scoped_ptr< DBClientCursor > c (cli.query(coll, Query( fromjson( "{'options.temp': {$in: [true, 1]}}" ) ) ));
         while( c->more() ) {
             BSONObj o = c->next();
             toDelete.push_back( o.getStringField( "name" ) );
         }
     }
     for( vector< string >::iterator i = toDelete.begin(); i != toDelete.end(); ++i ) {
         log() << "Dropping old temporary collection: " << *i << endl;
         cli.dropCollection( *i );
     }
 }
Beispiel #9
0
    void IndexRebuilder::run() {
        // Disable record access timer warnings
        ON_BLOCK_EXIT(resetMemoryTracking, Record::MemoryTrackingEnabled);
        Record::MemoryTrackingEnabled = false;

        Client::GodScope gs;
        Lock::GlobalWrite lk;

        bool firstTime = true;
        std::vector<std::string> dbNames;
        getDatabaseNames(dbNames);

        for (std::vector<std::string>::const_iterator it = dbNames.begin();
             it < dbNames.end();
             it++) {
            checkDB(*it, &firstTime);
        }

        cc().shutdown();
    }
Beispiel #10
0
Datei: db.cpp Projekt: zhuk/mongo
    void repairDatabases() {

        dblock lk;
        vector< string > dbNames;
        getDatabaseNames( dbNames );
        for ( vector< string >::iterator i = dbNames.begin(); i != dbNames.end(); ++i ) {
            string dbName = *i;
            assert( !setClientTempNs( dbName.c_str() ) );
            MongoDataFile *p = database->getFile( 0 );
            MDFHeader *h = p->getHeader();
            if ( !h->currentVersion() ) {
                log() << "****" << endl;
                log() << "****" << endl;
                log() << "need to upgrade database " << dbName << " with pdfile version " << h->version << "." << h->versionMinor << ", "
                      << "new version: " << VERSION << "." << VERSION_MINOR << endl;
                if ( shouldRepairDatabases ){
                    // QUESTION: Repair even if file format is higher version than code?
                    log() << "\t starting repair" << endl;
                    string errmsg;
                    assert( repairDatabase( dbName.c_str(), errmsg ) );
                }
                else {
                    log() << "\t Not repairing, exiting!" << endl;
                    log() << "\t run --upgrade to upgrade dbs, then start again" << endl;
                    log() << "****" << endl;
                    dbexit( EXIT_NEED_UPGRADE );
                    shouldRepairDatabases = 1;
                    return;
                }
            } else {
                closeClient( dbName.c_str() );
            }
        }

        if ( shouldRepairDatabases ){
            log() << "finished checking dbs" << endl;
            dbexit( EXIT_CLEAN );
        }
    }
 Status AuthzManagerExternalStateMongod::getAllDatabaseNames(
         std::vector<std::string>* dbnames) {
     Lock::GlobalRead lk;
     getDatabaseNames(*dbnames);
     return Status::OK();
 }
Beispiel #12
0
    void acquirePathLock(bool doingRepair) {
        string name = ( boost::filesystem::path( dbpath ) / "mongod.lock" ).string();

        bool oldFile = false;

        if ( boost::filesystem::exists( name ) && boost::filesystem::file_size( name ) > 0 ) {
            oldFile = true;
        }

#ifdef _WIN32
        lockFileHandle = CreateFileA( name.c_str(), GENERIC_READ | GENERIC_WRITE,
            0 /* do not allow anyone else access */, NULL, 
            OPEN_ALWAYS /* success if fh can open */, 0, NULL );

        if (lockFileHandle == INVALID_HANDLE_VALUE) {
            DWORD code = GetLastError();
            char *msg;
            FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
                NULL, code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                (LPSTR)&msg, 0, NULL);
            string m = msg;
            str::stripTrailing(m, "\r\n");
            uasserted( 13627 , str::stream() << "Unable to create/open lock file: " << name << ' ' << m << ". Is a mongod instance already running?" );
        }
        lockFile = _open_osfhandle((intptr_t)lockFileHandle, 0);
#else
        lockFile = open( name.c_str(), O_RDWR | O_CREAT , S_IRWXU | S_IRWXG | S_IRWXO );
        if( lockFile <= 0 ) {
            uasserted( 10309 , str::stream() << "Unable to create/open lock file: " << name << ' ' << errnoWithDescription() << " Is a mongod instance already running?" );
        }
        if (flock( lockFile, LOCK_EX | LOCK_NB ) != 0) {
            close ( lockFile );
            lockFile = 0;
            uassert( 10310 ,  "Unable to lock file: " + name + ". Is a mongod instance already running?",  0 );
        }
#endif

        if ( oldFile ) {
            // we check this here because we want to see if we can get the lock
            // if we can't, then its probably just another mongod running
            
            string errmsg;
            if (doingRepair && dur::haveJournalFiles()) {
                errmsg = "************** \n"
                         "You specified --repair but there are dirty journal files. Please\n"
                         "restart without --repair to allow the journal files to be replayed.\n"
                         "If you wish to repair all databases, please shutdown cleanly and\n"
                         "run with --repair again.\n"
                         "**************";
            }
            else if (cmdLine.dur) {
                if (!dur::haveJournalFiles(/*anyFiles=*/true)) {
                    // Passing anyFiles=true as we are trying to protect against starting in an
                    // unclean state with the journal directory unmounted. If there are any files,
                    // even prealloc files, then it means that it is mounted so we can continue.
                    // Previously there was an issue (SERVER-5056) where we would fail to start up
                    // if killed during prealloc.
                    
                    vector<string> dbnames;
                    getDatabaseNames( dbnames );
                    
                    if ( dbnames.size() == 0 ) {
                        // this means that mongod crashed
                        // between initial startup and when journaling was initialized
                        // it is safe to continue
                    }
                    else {
                        errmsg = str::stream()
                            << "************** \n"
                            << "old lock file: " << name << ".  probably means unclean shutdown,\n"
                            << "but there are no journal files to recover.\n"
                            << "this is likely human error or filesystem corruption.\n"
                            << "please make sure that your journal directory is mounted.\n"
                            << "found " << dbnames.size() << " dbs.\n"
                            << "see: http://dochub.mongodb.org/core/repair for more information\n"
                            << "*************";
                    }


                }
            }
            else {
                if (!dur::haveJournalFiles() && !doingRepair) {
                    errmsg = str::stream()
                             << "************** \n"
                             << "Unclean shutdown detected.\n"
                             << "Please visit http://dochub.mongodb.org/core/repair for recovery instructions.\n"
                             << "*************";
                }
            }

            if (!errmsg.empty()) {
                cout << errmsg << endl;
#ifdef _WIN32
                CloseHandle( lockFileHandle );
#else
                close ( lockFile );
#endif
                lockFile = 0;
                uassert( 12596 , "old lock file" , 0 );
            }
        }

        // Not related to lock file, but this is where we handle unclean shutdown
        if( !cmdLine.dur && dur::haveJournalFiles() ) {
            cout << "**************" << endl;
            cout << "Error: journal files are present in journal directory, yet starting without journaling enabled." << endl;
            cout << "It is recommended that you start with journaling enabled so that recovery may occur." << endl;
            cout << "**************" << endl;
            uasserted(13597, "can't start without --journal enabled when journal/ files are present");
        }

#ifdef _WIN32
        uassert( 13625, "Unable to truncate lock file", _chsize(lockFile, 0) == 0);
        writePid( lockFile );
        _commit( lockFile );
#else
        uassert( 13342, "Unable to truncate lock file", ftruncate(lockFile, 0) == 0);
        writePid( lockFile );
        fsync( lockFile );
        flushMyDirectory(name);
#endif
    }
Beispiel #13
0
    // ran at startup.
    static void repairDatabasesAndCheckVersion(bool shouldClearNonLocalTmpCollections) {
        //        LastError * le = lastError.get( true );
        LOG(1) << "enter repairDatabases (to check pdfile version #)" << endl;

        Lock::GlobalWrite lk;
        vector< string > dbNames;
        getDatabaseNames( dbNames );
        for ( vector< string >::iterator i = dbNames.begin(); i != dbNames.end(); ++i ) {
            string dbName = *i;
            LOG(1) << "\t" << dbName << endl;

            Client::Context ctx( dbName );
            DataFile *p = ctx.db()->getExtentManager().getFile( 0 );
            DataFileHeader *h = p->getHeader();

            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,
                      str::stream() << "db " << dbName << " appears corrupt pdfile version: " << h->version
                                    << " info: " << h->versionMinor << ' ' << h->fileLength);
                }

                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?
                    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 );
                    mongodGlobalParams.upgrade = 1;
                    return;
                }
            }
            else {
                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->versionMinor == PDFILE_VERSION_MINOR_22_AND_OLDER) {
                        if (IndexNames::existedBefore24(plugin))
                            continue;

                        log() << "Index " << index << " claims to be of type '" << plugin << "', "
                              << "which is either invalid or did not exist before v2.4. "
                              << "See the upgrade section: "
                              << "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(), storageGlobalParams.dbpath);
            }
        }

        LOG(1) << "done repairDatabases" << endl;

        if (mongodGlobalParams.upgrade) {
            log() << "finished checking dbs" << endl;
            cc().shutdown();
            dbexit( EXIT_CLEAN );
        }
    }
Beispiel #14
0
        void run(){
        if ( _token.size() == 0  && _name.size() == 0 ){
            log(1) << "mms not configured" << endl;
            return;
        }

        if ( _token.size() == 0 ){
            log() << "no token for mms - not running" << endl;
            return;
        }
        
        if ( _name.size() == 0 ){
            log() << "no name for mms - not running" << endl;
            return;
        }

        log() << "mms monitor staring...  token:" << _token << " name:" << _name << " interval: " << _secsToSleep << endl;

        unsigned long long lastTime = 0;
        unsigned long long lastLockTime = 0;
        
        while ( ! inShutdown() ){
            sleepsecs( _secsToSleep );
            
            stringstream url;
            url << _baseurl << _token << "?";
            url << "monitor_name=" << _name << "&";
            url << "version=" << versionString << "&";
            url << "git_hash=" << gitVersion() << "&";

            { //percent_locked
                unsigned long long time = curTimeMicros64();
                unsigned long long start , lock;
                dbMutexInfo.timingInfo( start , lock );
                if ( lastTime ){
                    double timeDiff = (double) (time - lastTime);
                    double lockDiff = (double) (lock - lastLockTime);
                    url << "percent_locked=" << (int)ceil( 100 * ( lockDiff / timeDiff ) ) << "&";
                }
                lastTime = time;
                lastLockTime = lock;
            }
            
            vector< string > dbNames;
            getDatabaseNames( dbNames );
            boost::intmax_t totalSize = 0;
            for ( vector< string >::iterator i = dbNames.begin(); i != dbNames.end(); ++i ) {
                boost::intmax_t size = dbSize( i->c_str() );
                totalSize += size;
            }
            url << "data_size=" << totalSize / ( 1024 * 1024 ) << "&";

            
            
            /* TODO: 
              message_operations
              update_operations
              insert_operations
              get_more_operations
              delete_operations
              kill_cursors_operations 
            */
            

            log(1) << "mms url: " << url.str() << endl;
            
            try {
                HttpClient c;
                map<string,string> headers;
                stringstream ss;
                int rc = c.get( url.str() , headers , ss );
                log(1) << "\t response code: " << rc << endl;
                if ( rc != 200 ){
                    log() << "mms error response code:" << rc << endl;
                    log(1) << "mms error body:" << ss.str() << endl;
                }
            }
            catch ( std::exception& e ){
                log() << "mms get exception: " << e.what() << endl;
            }
        }
        }