Beispiel #1
0
 virtual bool run(const string& ns, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
     fassert(16175, rotateLogs());
     return 1;
 }
Beispiel #2
0
 static void rotateLogsOrDie(int sig) {
     fassert(16176, rotateLogs());
 }
Beispiel #3
0
void *sys_allocPage()
{
   void *ret = HeapAlloc( s_heapHandle, 0, s_pageSize );
   fassert( ret != 0 );
   return ret;
}
Beispiel #4
0
 Lock::ScopedLock::~ScopedLock() { 
     LockState& ls = lockState();
     int prevCount = ls.recursiveCount();
     Lock::ScopedLock* what = ls.leaveScopedLock();
     fassert( 16171 , prevCount != 1 || what == this );
 }
Status DurableViewCatalogImpl::iterate(OperationContext* opCtx, Callback callback) {
    dassert(opCtx->lockState()->isDbLockedForMode(_db->name(), MODE_IS) ||
            opCtx->lockState()->isDbLockedForMode(_db->name(), MODE_IX));
    Collection* systemViews = _db->getCollection(opCtx, _db->getSystemViewsName());
    if (!systemViews)
        return Status::OK();

    Lock::CollectionLock lk(opCtx->lockState(), _db->getSystemViewsName(), MODE_IS);
    auto cursor = systemViews->getCursor(opCtx);
    while (auto record = cursor->next()) {
        RecordData& data = record->data;

        // Check the document is valid BSON, with only the expected fields.
        // Use the latest BSON validation version. Existing view definitions are allowed to contain
        // decimal data even if decimal is disabled.
        fassert(40224, validateBSON(data.data(), data.size(), BSONVersion::kLatest));
        BSONObj viewDef = data.toBson();

        // Check read definitions for correct structure, and refuse reading past invalid
        // definitions. Ignore any further view definitions.
        bool valid = true;
        for (const BSONElement& e : viewDef) {
            std::string name(e.fieldName());
            valid &= name == "_id" || name == "viewOn" || name == "pipeline" || name == "collation";
        }

        const auto viewName = viewDef["_id"].str();
        const auto viewNameIsValid = NamespaceString::validCollectionComponent(viewName) &&
            NamespaceString::validDBName(nsToDatabaseSubstring(viewName));
        valid &= viewNameIsValid;

        // Only perform validation via NamespaceString if the collection name has been determined to
        // be valid. If not valid then the NamespaceString constructor will uassert.
        if (viewNameIsValid) {
            NamespaceString viewNss(viewName);
            valid &= viewNss.isValid() && viewNss.db() == _db->name();
        }

        valid &= NamespaceString::validCollectionName(viewDef["viewOn"].str());

        const bool hasPipeline = viewDef.hasField("pipeline");
        valid &= hasPipeline;
        if (hasPipeline) {
            valid &= viewDef["pipeline"].type() == mongo::Array;
        }

        valid &=
            (!viewDef.hasField("collation") || viewDef["collation"].type() == BSONType::Object);

        if (!valid) {
            return {ErrorCodes::InvalidViewDefinition,
                    str::stream() << "found invalid view definition " << viewDef["_id"]
                                  << " while reading '"
                                  << _db->getSystemViewsName()
                                  << "'"};
        }

        Status callbackStatus = callback(viewDef);
        if (!callbackStatus.isOK()) {
            return callbackStatus;
        }
    }
    return Status::OK();
}
Beispiel #6
0
bool copyRuntime( const Path& binpath, const Path& tgtpath )
{
   message( "Searching VSx CRT in " + binpath.getFullLocation() );

   // open the binary path in search of "Microsoft.*.CRT"
   VFSProvider* provider = Engine::getVFS( "file" );
   fassert( provider != 0 );
   
   DirEntry* dir = provider->openDir( binpath.getFullLocation() );
   if( dir == 0 )
   {
      warning( "Can't search CRT in " + binpath.getFullLocation() );
      return false;
   }
   
   String fname;
   while( dir->read(fname) )
   {
      if( fname.wildcardMatch("Microsoft.*.CRT") )
      {
         // we're done with dir.
         delete dir;

         Path source( binpath.getFullLocation() + "/" + fname + "/");
         Path target( tgtpath.getFullLocation() + "/" + fname + "/");
         
         // first, create the target path
         int32 fsStatus;
         if( ! Sys::fal_mkdir( target.getFullLocation(), fsStatus, true ) )
         {
            warning( "Can't create CRT directory in " + target.getFullLocation() );
            return false;
         }

         // then copy everything inside it.
         DirEntry* crtdir = provider->openDir( source.getFullLocation() );
         if( crtdir == 0 )
         {
            warning( "Can't read source CRT directory " + source.getFullLocation() );
            return false;
         }

         //loop copying everything that's not a dir.
         String sFile;
         while( crtdir->read( sFile ) )
         {
            if( sFile.startsWith(".") )
               continue;

            source.setFilename( sFile );
            target.setFilename( sFile );
            if ( ! copyFile( source.get(), target.get() ) )
            {
               delete crtdir;
               warning( "Can't copy CRT file " + source.get() +  " into " 
                  + target.get() );
               return false;
            }
         }

         return true;
      }
   }

   delete dir;
   return false;
}
Beispiel #7
0
    void UpdateStage::doInsert() {
        _specificStats.inserted = true;

        const UpdateRequest* request = _params.request;
        UpdateDriver* driver = _params.driver;
        CanonicalQuery* cq = _params.canonicalQuery;
        UpdateLifecycle* lifecycle = request->getLifecycle();

        // Since this is an insert (no docs found and upsert:true), we will be logging it
        // as an insert in the oplog. We don't need the driver's help to build the
        // oplog record, then. We also set the context of the update driver to the INSERT_CONTEXT.
        // Some mods may only work in that context (e.g. $setOnInsert).
        driver->setLogOp(false);
        driver->setContext(ModifierInterface::ExecInfo::INSERT_CONTEXT);

        // Reset the document we will be writing to
        _doc.reset();

        // The original document we compare changes to - immutable paths must not change
        BSONObj original;

        bool isInternalRequest = request->isFromReplication() || request->isFromMigration();

        const vector<FieldRef*>* immutablePaths = NULL;
        if (!isInternalRequest && lifecycle)
            immutablePaths = lifecycle->getImmutableFields();

        // Calling populateDocumentWithQueryFields will populate the '_doc' with fields from the
        // query which creates the base of the update for the inserted doc (because upsert
        // was true).
        if (cq) {
            uassertStatusOK(driver->populateDocumentWithQueryFields(cq, immutablePaths, _doc));
            if (driver->isDocReplacement())
                _specificStats.fastmodinsert = true;
            original = _doc.getObject();
        }
        else {
            fassert(17354, CanonicalQuery::isSimpleIdQuery(request->getQuery()));
            BSONElement idElt = request->getQuery()[idFieldName];
            original = idElt.wrap();
            fassert(17352, _doc.root().appendElement(idElt));
        }

        // Apply the update modifications and then log the update as an insert manually.
        Status status = driver->update(StringData(), &_doc);
        if (!status.isOK()) {
            uasserted(16836, status.reason());
        }

        // Ensure _id exists and is first
        uassertStatusOK(ensureIdAndFirst(_doc));

        // Validate that the object replacement or modifiers resulted in a document
        // that contains all the immutable keys and can be stored if it isn't coming
        // from a migration or via replication.
        if (!isInternalRequest){
            FieldRefSet noFields;
            // This will only validate the modified fields if not a replacement.
            uassertStatusOK(validate(original,
                                     noFields,
                                     _doc,
                                     immutablePaths,
                                     driver->modOptions()) );
        }

        // Insert the doc
        BSONObj newObj = _doc.getObject();
        uassert(17420,
                str::stream() << "Document to upsert is larger than " << BSONObjMaxUserSize,
                newObj.objsize() <= BSONObjMaxUserSize);

        _specificStats.objInserted = newObj;

        // If this is an explain, bail out now without doing the insert.
        if (request->isExplain()) {
            return;
        }

        WriteUnitOfWork wunit(request->getOpCtx());
        invariant(_collection);
        StatusWith<DiskLoc> newLoc = _collection->insertDocument(request->getOpCtx(),
                                                                 newObj,
                                                                 !request->isGod()/*enforceQuota*/);
        uassertStatusOK(newLoc.getStatus());
        if (request->shouldCallLogOp()) {
            repl::logOp(request->getOpCtx(),
                        "i",
                        request->getNamespaceString().ns().c_str(),
                        newObj,
                        NULL,
                        NULL,
                        request->isFromMigration());
        }

        wunit.commit();
    }
Beispiel #8
0
 void Suite::registerSuite( const std::string& name , Suite* s ) {
     Suite*& m = _allSuites()[name];
     fassert( 10162, ! m );
     m = s;
 }
Beispiel #9
0
void *sys_allocPage()
{
   void *ret = mmap(((void *)0), s_pageSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
   fassert( ret != MAP_FAILED );
   return ret;
}
OpTime ReplicationCoordinatorExternalStateMock::onTransitionToPrimary(OperationContext* opCtx,
                                                                      bool isV1ElectionProtocol) {
    _lastOpTime = _firstOpTimeOfMyTerm;
    _firstOpTimeOfMyTerm = OpTime();
    return fassert(40297, _lastOpTime);
}
Beispiel #11
0
        int Suite::run( const std::vector<std::string>& suites , const std::string& filter , int runsPerTest ) {

            if (_allSuites().empty()) {
                log() << "error: no suites registered.";
                return EXIT_FAILURE;
            }

            for ( unsigned int i = 0; i < suites.size(); i++ ) {
                if ( _allSuites().count( suites[i] ) == 0 ) {
                    log() << "invalid test suite [" << suites[i] << "], use --list to see valid names" << std::endl;
                    return EXIT_FAILURE;
                }
            }

            std::vector<std::string> torun(suites);

            if ( torun.empty() ) {
                for ( SuiteMap::const_iterator i = _allSuites().begin();
                      i !=_allSuites().end(); ++i ) {

                    torun.push_back( i->first );
                }
            }

            std::vector<Result*> results;

            for ( std::vector<std::string>::iterator i=torun.begin(); i!=torun.end(); i++ ) {
                std::string name = *i;
                Suite* s = _allSuites()[name];
                fassert( 16145,  s );

                log() << "going to run suite: " << name << std::endl;
                results.push_back( s->run( filter, runsPerTest ) );
            }

            log() << "**************************************************" << std::endl;

            int rc = 0;

            int tests = 0;
            int fails = 0;
            int asserts = 0;

            for ( std::vector<Result*>::iterator i=results.begin(); i!=results.end(); i++ ) {
                Result* r = *i;
                log() << r->toString();
                if ( abs( r->rc() ) > abs( rc ) )
                    rc = r->rc();

                tests += r->_tests;
                fails += r->_fails;
                asserts += r->_asserts;
            }

            Result totals ("TOTALS");
            totals._tests = tests;
            totals._fails = fails;
            totals._asserts = asserts;

            log() << totals.toString(); // includes endl

            return rc;
        }
Beispiel #12
0
    StatusWith<DiskLoc> Collection::insertDocument( const BSONObj& docToInsert, bool enforceQuota ) {

        if ( _indexCatalog.findIdIndex() ) {
            if ( docToInsert["_id"].eoo() ) {
                return StatusWith<DiskLoc>( ErrorCodes::InternalError,
                                            "Collection::insertDocument got document without _id" );
            }
        }

        int lenWHdr = _details->getRecordAllocationSize( docToInsert.objsize() + Record::HeaderSize );
        fassert( 17208, lenWHdr >= ( docToInsert.objsize() + Record::HeaderSize ) );

        if ( _details->isCapped() ) {
            // TOOD: old god not done
            Status ret = _indexCatalog.checkNoIndexConflicts( docToInsert );
            if ( !ret.isOK() )
                return StatusWith<DiskLoc>( ret );
        }

        // TODO: for now, capped logic lives inside NamespaceDetails, which is hidden
        //       under the RecordStore, this feels broken since that should be a
        //       collection access method probably
        StatusWith<DiskLoc> loc = _recordStore.allocRecord( lenWHdr,
                                                            enforceQuota ? largestFileNumberInQuota() : 0 );
        if ( !loc.isOK() )
            return loc;

        Record *r = loc.getValue().rec();
        fassert( 17210, r->lengthWithHeaders() >= lenWHdr );

        // copy the data
        r = reinterpret_cast<Record*>( getDur().writingPtr(r, lenWHdr) );
        memcpy( r->data(), docToInsert.objdata(), docToInsert.objsize() );

        addRecordToRecListInExtent(r, loc.getValue()); // XXX move down into record store

        _details->incrementStats( r->netLength(), 1 );

        // TOOD: old god not done
        _infoCache.notifyOfWriteOp();

        try {
            _indexCatalog.indexRecord( docToInsert, loc.getValue() );
        }
        catch( AssertionException& e ) {
            if ( _details->isCapped() ) {
                return StatusWith<DiskLoc>( ErrorCodes::InternalError,
                                            str::stream() << "unexpected index insertion failure on"
                                            << " capped collection" << e.toString()
                                            << " - collection and its index will not match" );
            }

            // normal case -- we can roll back
            deleteDocument( loc.getValue(), false, true, NULL );
            return StatusWith<DiskLoc>( e.toStatus( "insertDocument" ) );
        }

        // TODO: this is what the old code did, but is it correct?
        _details->paddingFits();

        return loc;

    }
void OplogBufferCollection::_dropCollection(OperationContext* txn) {
    fassert(40155, _storageInterface->dropCollection(txn, _nss));
}
void OplogBufferCollection::_createCollection(OperationContext* txn) {
    CollectionOptions options;
    options.temp = true;
    fassert(40154, _storageInterface->createCollection(txn, _nss, options));
}
Beispiel #15
0
    long long Helpers::removeRange( const string& ns ,
                                    const BSONObj& min ,
                                    const BSONObj& max ,
                                    const BSONObj& keyPattern ,
                                    bool yield ,
                                    bool maxInclusive ,
                                    RemoveCallback * callback,
                                    bool fromMigrate ) {
        fassert( 16251, Lock::isWriteLocked( ns ) );
        BSONObj keya , keyb;
        BSONObj minClean = toKeyFormat( min , keya );
        BSONObj maxClean = toKeyFormat( max , keyb );
        verify( keya == keyb );

        Client::Context ctx(ns);

        shared_ptr<Cursor> cursor;
        auto_ptr<ClientCursor> clientCursor;
        {
            NamespaceDetails* nsd = nsdetails( ns.c_str() );
            if ( ! nsd )
                return 0;

            int ii = nsd->findIndexByKeyPattern( keya );
            verify( ii >= 0 );

            IndexDetails& i = nsd->idx( ii );

            cursor.reset( BtreeCursor::make( nsd , ii , i , minClean , maxClean , maxInclusive, 1 ) );
            clientCursor.reset( new ClientCursor( QueryOption_NoCursorTimeout , cursor , ns ) );
            clientCursor->setDoingDeletes( true );
        }

        long long num = 0;

        while ( clientCursor->ok() ) {

            if ( yield && ! clientCursor->yieldSometimes( ClientCursor::WillNeed) ) {
                // cursor got finished by someone else, so we're done
                clientCursor.release(); // if the collection/db is dropped, cc may be deleted
                break;
            }

            if ( ! clientCursor->ok() )
                break;

            DiskLoc rloc = clientCursor->currLoc();

            if ( callback )
                callback->goingToDelete( clientCursor->current() );

            clientCursor->advance();
            // SERVER-5198 Additional advancement is unnecessary for a single btree cursor, and see
            // SERVER-5725.
            cursor->prepareToTouchEarlierIterate();

            logOp( "d" , ns.c_str() , rloc.obj()["_id"].wrap() , 0 , 0 , fromMigrate );
            theDataFileMgr.deleteRecord(ns.c_str() , rloc.rec(), rloc);
            num++;

            cursor->recoverFromTouchingEarlierIterate();

            getDur().commitIfNeeded();


        }

        return num;
    }
Beispiel #16
0
ServiceContext* getGlobalServiceContext() {
    fassert(17508, globalServiceContext);
    return globalServiceContext;
}
Beispiel #17
0
 void minOSPageSizeBytesTest(size_t minOSPageSizeBytes) {
     fassert( 16325, minOSPageSizeBytes > 0 );
     fassert( 16326, minOSPageSizeBytes < 1000000 );
     // check to see if the page size is a power of 2
     fassert( 16327, (minOSPageSizeBytes & (minOSPageSizeBytes - 1)) == 0);
 }
Beispiel #18
0
        void flush() {
            if (!_view || !_fd)
                return;

            {
                LockMongoFilesShared mmfilesLock;

                std::set<MongoFile*> mmfs = MongoFile::getAllFiles();
                std::set<MongoFile*>::const_iterator it = mmfs.find(_theFile);
                if ( it == mmfs.end() || (*it)->getUniqueId() != _id ) {
                    // this was deleted while we were unlocked
                    return;
                }

                // Hold the flush mutex to ensure the file is not closed during flush
                _flushMutex.lock();
            }

            stdx::lock_guard<stdx::mutex> lk(_flushMutex, stdx::adopt_lock);

            int loopCount = 0;
            bool success = false;
            bool timeout = false;
            int dosError = ERROR_SUCCESS;
            const int maximumTimeInSeconds = 60 * 15;
            Timer t;
            while ( !success && !timeout ) {
                ++loopCount;
                success = FALSE != FlushViewOfFile( _view, 0 );
                if ( !success ) {
                    dosError = GetLastError();
                    if ( dosError != ERROR_LOCK_VIOLATION ) {
                        break;
                    }
                    timeout = t.seconds() > maximumTimeInSeconds;
                }
            }
            if ( success && loopCount > 1 ) {
                log() << "FlushViewOfFile for " << _filename
                        << " succeeded after " << loopCount
                        << " attempts taking " << t.millis()
                        << "ms" << endl;
            }
            else if ( !success ) {
                log() << "FlushViewOfFile for " << _filename
                        << " failed with error " << dosError
                        << " after " << loopCount
                        << " attempts taking " << t.millis()
                        << "ms" << endl;
                // Abort here to avoid data corruption
                fassert(16387, false);
            }

            success = FALSE != FlushFileBuffers(_fd);
            if (!success) {
                int err = GetLastError();
                log() << "FlushFileBuffers failed: " << errnoWithDescription( err )
                      << " file: " << _filename << endl;
                dataSyncFailedHandler();
            }
        }
    bool initializeServerGlobalState(bool isMongodShutdownSpecialCase) {

        Listener::globalTicketHolder.resize( cmdLine.maxConns );

#ifndef _WIN32
        if (!fs::is_directory(cmdLine.socket)) {
            cout << cmdLine.socket << " must be a directory" << endl;
            return false;
        }

        if (cmdLine.doFork) {
            fassert(16447, !cmdLine.logpath.empty() || cmdLine.logWithSyslog);

            cout.flush();
            cerr.flush();

            cmdLine.parentProc = getpid();

            // facilitate clean exit when child starts successfully
            setupLaunchSignals();

            pid_t c = fork();
            if ( c ) {
                int pstat;
                waitpid(c, &pstat, 0);

                if ( WIFEXITED(pstat) ) {
                    if ( ! WEXITSTATUS(pstat) ) {
                        cout << "child process started successfully, parent exiting" << endl;
                    }

                    _exit( WEXITSTATUS(pstat) );
                }

                _exit(50);
            }

            if ( chdir("/") < 0 ) {
                cout << "Cant chdir() while forking server process: " << strerror(errno) << endl;
                ::_exit(-1);
            }
            setsid();

            cmdLine.leaderProc = getpid();

            pid_t c2 = fork();
            if ( c2 ) {
                int pstat;
                cout << "forked process: " << c2 << endl;
                waitpid(c2, &pstat, 0);

                if ( WIFEXITED(pstat) ) {
                    _exit( WEXITSTATUS(pstat) );
                }

                _exit(51);
            }

            // stdout handled in initLogging
            //fclose(stdout);
            //freopen("/dev/null", "w", stdout);

            fclose(stderr);
            fclose(stdin);

            FILE* f = freopen("/dev/null", "w", stderr);
            if ( f == NULL ) {
                cout << "Cant reassign stderr while forking server process: " << strerror(errno) << endl;
                return false;
            }

            f = freopen("/dev/null", "r", stdin);
            if ( f == NULL ) {
                cout << "Cant reassign stdin while forking server process: " << strerror(errno) << endl;
                return false;
            }

            setupCoreSignals();
            setupSignals( true );
        }

        if (cmdLine.logWithSyslog) {
            StringBuilder sb;
            sb << cmdLine.binaryName << "." << cmdLine.port;
            Logstream::useSyslog( sb.str().c_str() );
        }
#endif
        if (!cmdLine.logpath.empty() && !isMongodShutdownSpecialCase) {
            fassert(16448, !cmdLine.logWithSyslog);
            string absoluteLogpath = boost::filesystem::absolute(
                    cmdLine.logpath, cmdLine.cwd).string();
            if (!initLogging(absoluteLogpath, cmdLine.logAppend)) {
                cout << "Bad logpath value: \"" << absoluteLogpath << "\"; terminating." << endl;
                return false;
            }
        }

        if (!cmdLine.pidFile.empty()) {
            writePidFile(cmdLine.pidFile);
        }

        if (!cmdLine.keyFile.empty()) {

            if (!setUpSecurityKey(cmdLine.keyFile)) {
                // error message printed in setUpPrivateKey
                return false;
            }

            noauth = false;
        }

#ifdef MONGO_SSL
        if (cmdLine.sslOnNormalPorts) {

            if ( cmdLine.sslPEMKeyPassword.size() == 0 ) {
                log() << "need sslPEMKeyPassword" << endl;
                return false;
            }

            if ( cmdLine.sslPEMKeyFile.size() == 0 ) {
                log() << "need sslPEMKeyFile" << endl;
                return false;
            }

            cmdLine.sslServerManager = new SSLManager( false );
            if ( ! cmdLine.sslServerManager->setupPEM( cmdLine.sslPEMKeyFile , cmdLine.sslPEMKeyPassword ) ) {
                return false;
            }
        }
        else if ( cmdLine.sslPEMKeyFile.size() || cmdLine.sslPEMKeyPassword.size() ) {
            log() << "need to enable sslOnNormalPorts" << endl;
            return false;
        }
#endif

        return true;
    }
    bool initializeServerGlobalState(bool isMongodShutdownSpecialCase) {

        Listener::globalTicketHolder.resize( cmdLine.maxConns );

#ifndef _WIN32
        if (!fs::is_directory(cmdLine.socket)) {
            cout << cmdLine.socket << " must be a directory" << endl;
            return false;
        }

        if (cmdLine.doFork) {
            fassert(16447, !cmdLine.logpath.empty() || cmdLine.logWithSyslog);

            cout.flush();
            cerr.flush();

            cmdLine.parentProc = getpid();

            // facilitate clean exit when child starts successfully
            setupLaunchSignals();

            cout << "about to fork child process, waiting until server is ready for connections."
                 << endl;

            pid_t child1 = fork();
            if (child1 == -1) {
                cout << "ERROR: stage 1 fork() failed: " << errnoWithDescription();
                _exit(EXIT_ABRUPT);
            }
            else if (child1) {
                // this is run in the original parent process
                int pstat;
                waitpid(child1, &pstat, 0);

                if (WIFEXITED(pstat)) {
                    if (WEXITSTATUS(pstat)) {
                        cout << "ERROR: child process failed, exited with error number "
                             << WEXITSTATUS(pstat) << endl;
                    }
                    else {
                        cout << "child process started successfully, parent exiting" << endl;
                    }

                    _exit(WEXITSTATUS(pstat));
                }

                _exit(50);
            }

            if ( chdir("/") < 0 ) {
                cout << "Cant chdir() while forking server process: " << strerror(errno) << endl;
                ::_exit(-1);
            }
            setsid();

            cmdLine.leaderProc = getpid();

            pid_t child2 = fork();
            if (child2 == -1) {
                cout << "ERROR: stage 2 fork() failed: " << errnoWithDescription();
                _exit(EXIT_ABRUPT);
            }
            else if (child2) {
                // this is run in the middle process
                int pstat;
                cout << "forked process: " << child2 << endl;
                waitpid(child2, &pstat, 0);

                if ( WIFEXITED(pstat) ) {
                    _exit( WEXITSTATUS(pstat) );
                }

                _exit(51);
            }

            // this is run in the final child process (the server)

            // stdout handled in initLogging
            //fclose(stdout);
            //freopen("/dev/null", "w", stdout);

            fclose(stderr);
            fclose(stdin);

            FILE* f = freopen("/dev/null", "w", stderr);
            if ( f == NULL ) {
                cout << "Cant reassign stderr while forking server process: " << strerror(errno) << endl;
                return false;
            }

            f = freopen("/dev/null", "r", stdin);
            if ( f == NULL ) {
                cout << "Cant reassign stdin while forking server process: " << strerror(errno) << endl;
                return false;
            }

            setupCoreSignals();
            setupSignals( true );
        }

        if (cmdLine.logWithSyslog) {
            StringBuilder sb;
            sb << cmdLine.binaryName << "." << cmdLine.port;
            Logstream::useSyslog( sb.str().c_str() );
        }
#endif
        if (!cmdLine.logpath.empty() && !isMongodShutdownSpecialCase) {
            fassert(16448, !cmdLine.logWithSyslog);
            string absoluteLogpath = boost::filesystem::absolute(
                    cmdLine.logpath, cmdLine.cwd).string();
            if (!initLogging(absoluteLogpath, cmdLine.logAppend)) {
                cout << "Bad logpath value: \"" << absoluteLogpath << "\"; terminating." << endl;
                return false;
            }
        }

        if (!cmdLine.pidFile.empty()) {
            writePidFile(cmdLine.pidFile);
        }

        if (!cmdLine.keyFile.empty()) {

            if (!setUpSecurityKey(cmdLine.keyFile)) {
                // error message printed in setUpPrivateKey
                return false;
            }

            noauth = false;
        }

        return true;
    }
Beispiel #21
0
void Strategy::clientCommandOp(OperationContext* txn, Request& request) {
    QueryMessage q(request.d());

    LOG(3) << "command: " << q.ns << " " << q.query << " ntoreturn: " << q.ntoreturn
           << " options: " << q.queryOptions;

    if (q.queryOptions & QueryOption_Exhaust) {
        uasserted(18527,
                  string("the 'exhaust' query option is invalid for mongos commands: ") + q.ns +
                      " " + q.query.toString());
    }

    NamespaceString nss(request.getns());
    // Regular queries are handled in strategy_shard.cpp
    verify(nss.isCommand() || nss.isSpecialCommand());

    if (handleSpecialNamespaces(txn, request, q))
        return;

    int loops = 5;
    bool cmChangeAttempted = false;

    while (true) {
        BSONObjBuilder builder;
        try {
            BSONObj cmdObj = q.query;
            {
                BSONElement e = cmdObj.firstElement();
                if (e.type() == Object &&
                    (e.fieldName()[0] == '$' ? str::equals("query", e.fieldName() + 1)
                                             : str::equals("query", e.fieldName()))) {
                    // Extract the embedded query object.

                    if (cmdObj.hasField(Query::ReadPrefField.name())) {
                        // The command has a read preference setting. We don't want
                        // to lose this information so we copy this to a new field
                        // called $queryOptions.$readPreference
                        BSONObjBuilder finalCmdObjBuilder;
                        finalCmdObjBuilder.appendElements(e.embeddedObject());

                        BSONObjBuilder queryOptionsBuilder(
                            finalCmdObjBuilder.subobjStart("$queryOptions"));
                        queryOptionsBuilder.append(cmdObj[Query::ReadPrefField.name()]);
                        queryOptionsBuilder.done();

                        cmdObj = finalCmdObjBuilder.obj();
                    } else {
                        cmdObj = e.embeddedObject();
                    }
                }
            }

            Command::runAgainstRegistered(txn, q.ns, cmdObj, builder, q.queryOptions);
            BSONObj x = builder.done();
            replyToQuery(0, request.p(), request.m(), x);
            return;
        } catch (const StaleConfigException& e) {
            if (loops <= 0)
                throw e;

            loops--;
            log() << "retrying command: " << q.query;

            // For legacy reasons, ns may not actually be set in the exception :-(
            string staleNS = e.getns();
            if (staleNS.size() == 0)
                staleNS = q.ns;

            ShardConnection::checkMyConnectionVersions(txn, staleNS);
            if (loops < 4)
                versionManager.forceRemoteCheckShardVersionCB(txn, staleNS);
        } catch (const DBException& e) {
            if (e.getCode() == ErrorCodes::IncompatibleCatalogManager) {
                fassert(28791, !cmChangeAttempted);
                cmChangeAttempted = true;

                grid.forwardingCatalogManager()->waitForCatalogManagerChange(txn);
            } else {
                Command::appendCommandStatus(builder, e.toStatus());
                BSONObj x = builder.done();
                replyToQuery(0, request.p(), request.m(), x);
                return;
            }
        }
    }
}
Beispiel #22
0
 void Lock::GlobalRead::_tempRelease() { 
     fassert(16127, !noop);
     char ts = threadState();
     fassert(16128, ts == 'R');
     qlk.unlock_R();
 }
    Status LegacyReplicationCoordinator::processHeartbeat(const ReplSetHeartbeatArgs& args,
                                                          ReplSetHeartbeatResponse* response) {
        if (args.getProtocolVersion() != 1) {
            return Status(ErrorCodes::BadValue, "incompatible replset protocol version");
        }

        {
            if (_settings.ourSetName() != args.getSetName()) {
                log() << "replSet set names do not match, our cmdline: " << _settings.replSet
                      << rsLog;
                log() << "replSet s: " << args.getSetName() << rsLog;
                response->noteMismatched();
                return Status(ErrorCodes::BadValue, "repl set names do not match");
            }
        }

        response->noteReplSet();
        if( (theReplSet == 0) || (theReplSet->startupStatus == ReplSetImpl::LOADINGCONFIG) ) {
            if (!args.getSenderHost().empty()) {
                scoped_lock lck( _settings.discoveredSeeds_mx );
                _settings.discoveredSeeds.insert(args.getSenderHost().toString());
            }
            response->setHbMsg("still initializing");
            return Status::OK();
        }

        if (theReplSet->name() != args.getSetName()) {
            response->noteMismatched();
            return Status(ErrorCodes::BadValue, "repl set names do not match (2)");
        }
        response->setSetName(theReplSet->name());

        MemberState currentState = theReplSet->state();
        response->setState(currentState.s);
        if (currentState == MemberState::RS_PRIMARY) {
            response->setElectionTime(theReplSet->getElectionTime().asDate());
        }

        response->setElectable(theReplSet->iAmElectable());
        response->setHbMsg(theReplSet->hbmsg());
        response->setTime((long long) time(0));
        response->setOpTime(theReplSet->lastOpTimeWritten.asDate());
        const Member *syncTarget = BackgroundSync::get()->getSyncTarget();
        if (syncTarget) {
            response->setSyncingTo(syncTarget->fullName());
        }

        int v = theReplSet->config().version;
        response->setVersion(v);
        if (v > args.getConfigVersion()) {
            ReplicaSetConfig config;
            fassert(18635, config.initialize(theReplSet->config().asBson()));
            response->setConfig(config);
        }

        Member* from = NULL;
        if (v == args.getConfigVersion() && args.getSenderId() != -1) {
            from = theReplSet->getMutableMember(args.getSenderId());
        }
        if (!from) {
            from = theReplSet->findByName(args.getSenderHost().toString());
            if (!from) {
                return Status::OK();
            }
        }

        // if we thought that this node is down, let it know
        if (!from->hbinfo().up()) {
            response->noteStateDisagreement();
        }

        // note that we got a heartbeat from this node
        theReplSet->mgr->send(stdx::bind(&ReplSet::msgUpdateHBRecv,
                                         theReplSet, from->hbinfo().id(), time(0)));


        return Status::OK();
    }
Beispiel #24
0
 int socketPoll( pollfd* fdarray, unsigned long nfds, int timeout ) {
     fassert(17185, isPollSupported());
     return wsaPollFunction(fdarray, nfds, timeout);
 }
 void WiredTigerRecoveryUnit::assertInActiveTxn() const {
     fassert( 28575, _active );
 }
Beispiel #26
0
    DiskLoc DataFileMgr::insert(const char* ns,
                                const void* obuf,
                                int32_t len,
                                bool mayInterrupt,
                                bool god,
                                bool mayAddIndex,
                                bool* addedID) {

        Database* database = cc().database();

        bool wouldAddIndex = false;
        massert( 10093 , "cannot insert into reserved $ collection", god || NamespaceString::normal( ns ) );
        uassert( 10094 , str::stream() << "invalid ns: " << ns , isValidNS( ns ) );
        {
            const char *sys = strstr(ns, "system.");
            if ( sys ) {

                if ( !insert_checkSys(sys, ns, wouldAddIndex, obuf, god) )
                    return DiskLoc();

                if ( mayAddIndex && wouldAddIndex ) {
                    // TODO: this should be handled above this function
                    BSONObj spec( static_cast<const char*>( obuf ) );
                    string collectionToIndex = spec.getStringField( "ns" );
                    uassert(10096, "invalid ns to index", collectionToIndex.find( '.' ) != string::npos);
                    massert(10097,
                            str::stream() << "trying to create index on wrong db "
                            << " db: " << database->name() << " collection: " << collectionToIndex,
                            database->ownsNS( collectionToIndex ) );

                    Collection* collection = database->getCollection( collectionToIndex );
                    if ( !collection ) {
                        collection = database->createCollection( collectionToIndex, false, NULL, true );
                        verify( collection );
                        if ( !god )
                            ensureIdIndexForNewNs( collection );
                    }

                    Status status = collection->getIndexCatalog()->createIndex( spec, mayInterrupt );
                    if ( status.code() == ErrorCodes::IndexAlreadyExists )
                        return DiskLoc();
                    uassertStatusOK( status );
                    return DiskLoc();
                }
            }
        }

        Collection* collection = database->getCollection( ns );
        if ( collection == NULL ) {
            collection = database->createCollection( ns, false, NULL, false );

            int ies = Extent::initialSize(len);
            if( str::contains(ns, '$') &&
                len + Record::HeaderSize >= BtreeData_V1::BucketSize - 256 &&
                len + Record::HeaderSize <= BtreeData_V1::BucketSize + 256 ) {
                // probably an index.  so we pick a value here for the first extent instead of using
                // initialExtentSize() which is more for user collections.
                // TODO: we could look at the # of records in the parent collection to be smarter here.
                ies = (32+4) * 1024;
            }
            collection->increaseStorageSize( ies, false);
            if ( !god )
                ensureIdIndexForNewNs( collection );
        }

        NamespaceDetails* d = collection->details();

        IDToInsert idToInsert; // only initialized if needed

        if( !god ) {
            /* Check if we have an _id field. If we don't, we'll add it.
               Note that btree buckets which we insert aren't BSONObj's, but in that case god==true.
            */
            BSONObj io((const char *) obuf);
            BSONElement idField = io.getField( "_id" );
            uassert( 10099 ,  "_id cannot be an array", idField.type() != Array );
            // we don't add _id for capped collections in local as they don't have an _id index
            if( idField.eoo() &&
                !wouldAddIndex &&
                nsToDatabase( ns ) != "local" &&
                d->haveIdIndex() ) {

                if( addedID )
                    *addedID = true;

                idToInsert.init();
                len += idToInsert.size();
            }

            BSONElementManipulator::lookForTimestamps( io );
        }

        int lenWHdr = d->getRecordAllocationSize( len + Record::HeaderSize );
        fassert( 16440, lenWHdr >= ( len + Record::HeaderSize ) );

        // If the collection is capped, check if the new object will violate a unique index
        // constraint before allocating space.
        if ( d->isCapped() && !god) {
            BSONObj temp = BSONObj( reinterpret_cast<const char *>( obuf ) );
            Status ret = collection->getIndexCatalog()->checkNoIndexConflicts( temp );
            uassert(12582, "duplicate key insert for unique index of capped collection", ret.isOK() );
        }

        DiskLoc loc = allocateSpaceForANewRecord(ns, d, lenWHdr, god);

        if ( loc.isNull() ) {
            string errmsg = str::stream() << "insert: couldn't alloc space for object ns:" << ns
                                          << " capped:" << d->isCapped();
            log() << errmsg;
            uasserted( 17248, errmsg );
        }

        Record *r = loc.rec();
        {
            verify( r->lengthWithHeaders() >= lenWHdr );
            r = (Record*) getDur().writingPtr(r, lenWHdr);
            if( idToInsert.needed() ) {
                /* a little effort was made here to avoid a double copy when we add an ID */
                int originalSize = *((int*) obuf);
                ((int&)*r->data()) = originalSize + idToInsert.size();
                memcpy(r->data()+4, idToInsert.rawdata(), idToInsert.size());
                memcpy(r->data()+4+idToInsert.size(), ((char*)obuf)+4, originalSize-4);
            }
            else {
                if( obuf ) // obuf can be null from internal callers
                    memcpy(r->data(), obuf, len);
            }
        }

        addRecordToRecListInExtent(r, loc);

        d->incrementStats( r->netLength(), 1 );

        // we don't bother resetting query optimizer stats for the god tables - also god is true when adding a btree bucket
        if ( !god )
            collection->infoCache()->notifyOfWriteOp();

        /* add this record to our indexes */
        if ( d->getTotalIndexCount() > 0 ) {
            try {
                BSONObj obj(r->data());
                collection->getIndexCatalog()->indexRecord(obj, loc);
            }
            catch( AssertionException& e ) {
                // should be a dup key error on _id index
                if( d->isCapped() ) {
                    massert( 12583, "unexpected index insertion failure on capped collection", !d->isCapped() );
                    string s = e.toString();
                    s += " : on addIndex/capped - collection and its index will not match";
                    setLastError(0, s.c_str());
                    error() << s << endl;
                }
                else {
                    // normal case -- we can roll back
                    _deleteRecord(d, ns, r, loc);
                    throw;
                }
            }
        }

        d->paddingFits();

        return loc;
    }
Beispiel #27
0
    Status IndexBuilder::_build(OperationContext* txn,
                                Database* db,
                                bool allowBackgroundBuilding,
                                Lock::DBLock* dbLock) const {
        const NamespaceString ns(_index["ns"].String());

        Collection* c = db->getCollection( txn, ns.ns() );
        if ( !c ) {
            WriteUnitOfWork wunit(txn);
            c = db->getOrCreateCollection( txn, ns.ns() );
            verify(c);
            wunit.commit();
        }

        // Show which index we're building in the curop display.
        txn->getCurOp()->setQuery(_index);

        MultiIndexBlock indexer(txn, c);
        indexer.allowInterruption();
        if (allowBackgroundBuilding)
            indexer.allowBackgroundBuilding();

        Status status = Status::OK();
        IndexDescriptor* descriptor(NULL);
        try {
            status = indexer.init(_index);
            if ( status.code() == ErrorCodes::IndexAlreadyExists )
                return Status::OK();

            if (status.isOK()) {
                if (allowBackgroundBuilding) {
                    descriptor = indexer.registerIndexBuild();
                    invariant(dbLock);
                    dbLock->relockWithMode(MODE_IX);
                }

                Lock::CollectionLock colLock(txn->lockState(), ns.ns(), MODE_IX);
                status = indexer.insertAllDocumentsInCollection();
            }

            if (status.isOK()) {
                if (allowBackgroundBuilding) {
                    dbLock->relockWithMode(MODE_X);
                }
                WriteUnitOfWork wunit(txn);
                indexer.commit();
                wunit.commit();
            }
        }
        catch (const DBException& e) {
            status = e.toStatus();
        }

        if (allowBackgroundBuilding) {
            dbLock->relockWithMode(MODE_X);
            Database* db = dbHolder().get(txn, ns.db());
            fassert(28553, db);
            fassert(28554, db->getCollection(txn, ns.ns()));
            indexer.unregisterIndexBuild(descriptor);
        }

        if (status.code() == ErrorCodes::InterruptedAtShutdown) {
            // leave it as-if kill -9 happened. This will be handled on restart.
            indexer.abortWithoutCleanup();
        }

        return status;
    }
void ReplicationCoordinatorImpl::_startElectSelfV1() {
    invariant(!_voteRequester);
    invariant(!_freshnessChecker);

    stdx::unique_lock<stdx::mutex> lk(_mutex);
    switch (_rsConfigState) {
        case kConfigSteady:
            break;
        case kConfigInitiating:
        case kConfigReconfiguring:
        case kConfigHBReconfiguring:
            LOG(2) << "Not standing for election; processing a configuration change";
            // Transition out of candidate role.
            _topCoord->processLoseElection();
            return;
        default:
            severe() << "Entered replica set election code while in illegal config state "
                     << int(_rsConfigState);
            fassertFailed(28641);
    }

    auto finishedEvent = _makeEvent();
    if (!finishedEvent) {
        return;
    }
    _electionFinishedEvent = finishedEvent;

    auto dryRunFinishedEvent = _makeEvent();
    if (!dryRunFinishedEvent) {
        return;
    }
    _electionDryRunFinishedEvent = dryRunFinishedEvent;

    LoseElectionDryRunGuardV1 lossGuard(this);


    invariant(_rsConfig.getMemberAt(_selfIndex).isElectable());
    // Note: If we aren't durable, send last applied.
    const auto lastOpTime = _isDurableStorageEngine() ? _getMyLastDurableOpTime_inlock()
                                                      : _getMyLastAppliedOpTime_inlock();

    if (lastOpTime == OpTime()) {
        log() << "not trying to elect self, "
                 "do not yet have a complete set of data from any point in time";
        return;
    }

    log() << "conducting a dry run election to see if we could be elected";
    _voteRequester.reset(new VoteRequester);

    // This is necessary because the voteRequester may call directly into winning an
    // election, if there are no other MaybeUp nodes.  Winning an election attempts to lock
    // _mutex again.
    lk.unlock();

    long long term = _topCoord->getTerm();
    StatusWith<ReplicationExecutor::EventHandle> nextPhaseEvh =
        _voteRequester->start(&_replExecutor,
                              _rsConfig,
                              _selfIndex,
                              _topCoord->getTerm(),
                              true,  // dry run
                              lastOpTime);
    if (nextPhaseEvh.getStatus() == ErrorCodes::ShutdownInProgress) {
        return;
    }
    fassert(28685, nextPhaseEvh.getStatus());
    _replExecutor.onEvent(nextPhaseEvh.getValue(),
                          stdx::bind(&ReplicationCoordinatorImpl::_onDryRunComplete, this, term));
    lossGuard.dismiss();
}
    void SimpleRecordStoreV1::_compactExtent(OperationContext* txn,
                                             const DiskLoc diskloc,
                                             int extentNumber,
                                             RecordStoreCompactAdaptor* adaptor,
                                             const CompactOptions* compactOptions,
                                             CompactStats* stats ) {

        log() << "compact begin extent #" << extentNumber
              << " for namespace " << _ns << " " << diskloc;

        unsigned oldObjSize = 0; // we'll report what the old padding was
        unsigned oldObjSizeWithPadding = 0;

        Extent *e = _extentManager->getExtent( diskloc );
        e->assertOk();
        fassert( 17437, e->validates(diskloc) );

        {
            // the next/prev pointers within the extent might not be in order so we first
            // page the whole thing in sequentially
            log() << "compact paging in len=" << e->length/1000000.0 << "MB" << endl;
            Timer t;
            size_t length = e->length;

            touch_pages( reinterpret_cast<const char*>(e), length );
            int ms = t.millis();
            if( ms > 1000 )
                log() << "compact end paging in " << ms << "ms "
                      << e->length/1000000.0/t.seconds() << "MB/sec" << endl;
        }

        {
            log() << "compact copying records" << endl;
            long long datasize = 0;
            long long nrecords = 0;
            DiskLoc L = e->firstRecord;
            if( !L.isNull() ) {
                while( 1 ) {
                    Record *recOld = recordFor(L);
                    L = getNextRecordInExtent(L);

                    if ( compactOptions->validateDocuments && !adaptor->isDataValid(recOld) ) {
                        // object is corrupt!
                        log() << "compact skipping corrupt document!";
                        stats->corruptDocuments++;
                    }
                    else {
                        unsigned dataSize = adaptor->dataSize( recOld );
                        unsigned docSize = dataSize;

                        nrecords++;
                        oldObjSize += docSize;
                        oldObjSizeWithPadding += recOld->netLength();

                        unsigned lenWHdr = docSize + Record::HeaderSize;
                        unsigned lenWPadding = lenWHdr;

                        switch( compactOptions->paddingMode ) {
                        case CompactOptions::NONE:
                            if ( _details->isUserFlagSet(Flag_UsePowerOf2Sizes) )
                                lenWPadding = quantizePowerOf2AllocationSpace(lenWPadding);
                            break;
                        case CompactOptions::PRESERVE:
                            // if we are preserving the padding, the record should not change size
                            lenWPadding = recOld->lengthWithHeaders();
                            break;
                        case CompactOptions::MANUAL:
                            lenWPadding = compactOptions->computeRecordSize(lenWPadding);
                            if (lenWPadding < lenWHdr || lenWPadding > BSONObjMaxUserSize / 2 ) {
                                lenWPadding = lenWHdr;
                            }
                            break;
                        }

                        CompactDocWriter writer( recOld, dataSize, lenWPadding );
                        StatusWith<DiskLoc> status = insertRecord( txn, &writer, 0 );
                        uassertStatusOK( status.getStatus() );
                        datasize += recordFor( status.getValue() )->netLength();

                        adaptor->inserted( recordFor( status.getValue() ), status.getValue() );
                    }

                    if( L.isNull() ) {
                        // we just did the very last record from the old extent.  it's still pointed to
                        // by the old extent ext, but that will be fixed below after this loop
                        break;
                    }

                    // remove the old records (orphan them) periodically so our commit block doesn't get too large
                    bool stopping = false;
                    RARELY stopping = !txn->checkForInterruptNoAssert().isOK();
                    if( stopping || txn->recoveryUnit()->isCommitNeeded() ) {
                        *txn->recoveryUnit()->writing(&e->firstRecord) = L;
                        Record *r = recordFor(L);
                        txn->recoveryUnit()->writingInt(r->prevOfs()) = DiskLoc::NullOfs;
                        txn->recoveryUnit()->commitIfNeeded();
                        txn->checkForInterrupt();
                    }
                }
            } // if !L.isNull()

            invariant( _details->firstExtent() == diskloc );
            invariant( _details->lastExtent() != diskloc );
            DiskLoc newFirst = e->xnext;
            _details->setFirstExtent( txn, newFirst );
            *txn->recoveryUnit()->writing(&_extentManager->getExtent( newFirst )->xprev) = DiskLoc();
            _extentManager->freeExtent( txn, diskloc );

            txn->recoveryUnit()->commitIfNeeded();

            {
                double op = 1.0;
                if( oldObjSize )
                    op = static_cast<double>(oldObjSizeWithPadding)/oldObjSize;
                log() << "compact finished extent #" << extentNumber << " containing " << nrecords
                      << " documents (" << datasize/1000000.0 << "MB)"
                      << " oldPadding: " << op << ' ' << static_cast<unsigned>(op*100.0)/100;
            }
        }

    }
Beispiel #30
0
static const char *
rdv_onion_name(enum onion_type onion_type) {
	fassert(onion_type < lengthof(onion_names));

	return (onion_names[onion_type]);
}